root/trunk/ProjectFortress/src/com/sun/fortress/scala_src/typechecker/impls/Common.scala @ 3915

Revision 3915, 8.6 KB (checked in by jrhil47, 5 months ago)

[index] Changed all Functional indices to store a thunk to get the return types, since during type checking the return types might need to be lazily evaluated. Also changed Functional indices to yield an Option for return types.
[type checker] Started implementing extraction of bindings from nodes for type environments.

Line 
1/*******************************************************************************
2    Copyright 2009 Sun Microsystems, Inc.,
3    4150 Network Circle, Santa Clara, California 95054, U.S.A.
4    All rights reserved.
5
6    U.S. Government Rights - Commercial software.
7    Government users are subject to the Sun Microsystems, Inc. standard
8    license agreement and applicable provisions of the FAR and its supplements.
9
10    Use is subject to license terms.
11
12    This distribution may include materials developed by third parties.
13
14    Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15    trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16 ******************************************************************************/
17
18package com.sun.fortress.scala_src.typechecker.impls
19
20import edu.rice.cs.plt.collect.IndexedRelation
21import edu.rice.cs.plt.collect.Relation
22import com.sun.fortress.compiler.disambiguator.ExprDisambiguator.HierarchyHistory
23import com.sun.fortress.compiler.index.Method
24import com.sun.fortress.compiler.index.ProperTraitIndex
25import com.sun.fortress.compiler.index.TraitIndex
26import com.sun.fortress.compiler.typechecker.StaticTypeReplacer
27import com.sun.fortress.exceptions.InterpreterBug.bug
28import com.sun.fortress.exceptions.StaticError.errorMsg
29import com.sun.fortress.nodes._
30import com.sun.fortress.scala_src.nodes._
31import com.sun.fortress.scala_src.typechecker._
32import com.sun.fortress.scala_src.useful.Lists._
33import com.sun.fortress.scala_src.useful.Options._
34import com.sun.fortress.scala_src.useful.Sets._
35import com.sun.fortress.scala_src.useful.STypesUtil._
36
37/**
38 * Provides some helper methods that are common to cases among multiple groups.
39 * Note that helpers that are generally used in _every_ case/group should go in
40 * the STypeChecker class; the helpers herein each generally apply to cases
41 * among only a few groups.
42 *
43 * This trait must be mixed in with an STypeChecker instance to provide the
44 * full type checker implementation.
45 *
46 * (The self-type annotation at the beginning declares that this trait must be
47 * mixed into STypeChecker. This is what allows this trait to access its
48 * protected members.)
49 */
50trait Common { self: STypeChecker =>
51 
52  // TODO: Rewrite this method!
53  protected def inheritedMethods(extendedTraits: List[TraitTypeWhere]) = {
54   
55    // Return all of the methods from super-traits
56    def inheritedMethodsHelper(history: HierarchyHistory,
57                               extended_traits: List[TraitTypeWhere])
58                               : Relation[IdOrOpOrAnonymousName, Method] = {
59      var methods = new IndexedRelation[IdOrOpOrAnonymousName, Method](false)
60      var done = false
61      var h = history
62      for ( trait_ <- extended_traits ; if (! done) ) {
63        val type_ = trait_.getBaseType
64        if ( ! h.hasExplored(type_) ) {
65          h = h.explore(type_)
66          type_ match {
67            case ty@STraitType(_, name, _, params) =>
68              toOption(traits.typeCons(name)) match {
69                case Some(ti) =>
70                  if ( ti.isInstanceOf[TraitIndex] ) {
71                    val trait_params = ti.staticParameters
72                    val trait_args = ty.getArgs
73                    // Instantiate methods with static args
74                    val dotted = toSet(ti.asInstanceOf[TraitIndex].dottedMethods).map(t => (t.first, t.second))
75                    for ( pair <- dotted ) {
76                        methods.add(pair._1,
77                                    pair._2.instantiate(trait_params,trait_args).asInstanceOf[Method])
78                    }
79                    val getters = ti.asInstanceOf[TraitIndex].getters
80                    for ( getter <- toSet(getters.keySet) ) {
81                        methods.add(getter,
82                                    getters.get(getter).instantiate(trait_params,trait_args).asInstanceOf[Method])
83                    }
84                    val setters = ti.asInstanceOf[TraitIndex].setters
85                    for ( setter <- toSet(setters.keySet) ) {
86                        methods.add(setter,
87                                    setters.get(setter).instantiate(trait_params,trait_args).asInstanceOf[Method])
88                    }
89                    val paramsToArgs = new StaticTypeReplacer(trait_params, trait_args)
90                    val instantiated_extends_types =
91                      toList(ti.asInstanceOf[TraitIndex].extendsTypes).map( (t:TraitTypeWhere) =>
92                            t.accept(paramsToArgs).asInstanceOf[TraitTypeWhere] )
93                    methods.addAll(inheritedMethodsHelper(h, instantiated_extends_types))
94                  } else done = true
95                case _ => done = true
96              }
97            case _ => done = true
98          }
99        }
100      }
101      methods
102    }
103    inheritedMethodsHelper(new HierarchyHistory(), extendedTraits)
104  }
105
106  /**
107   * Identical to the overloading but with an explicitly given list of static
108   * parameters.
109   */
110  protected def staticInstantiation(sargs: List[StaticArg],
111                                    sparams: List[StaticParam],
112                                    body: Type): Option[Type] = {
113
114    // Check that the args match.
115    if (!staticArgsMatchStaticParams(sargs, sparams)) return None
116
117    // Create mapping from parameter names to static args.
118    val paramMap = Map(sparams.map(_.getName).zip(sargs): _*)
119
120    // Gets the actual value out of a static arg.
121    def sargToVal(sarg: StaticArg): Node = sarg match {
122      case sarg:TypeArg => sarg.getTypeArg
123      case sarg:IntArg => sarg.getIntVal
124      case sarg:BoolArg => sarg.getBoolArg
125      case sarg:OpArg => sarg.getName
126      case sarg:DimArg => sarg.getDimArg
127      case sarg:UnitArg => sarg.getUnitArg
128      case _ => bug("unexpected kind of static arg")
129    }
130
131    // Replaces all the params with args in a node.
132    object staticReplacer extends Walker {
133      override def walk(node: Any): Any = node match {
134        case n:VarType => paramMap.get(n.getName).map(sargToVal).getOrElse(n)
135        // TODO: Check proper name for OpArgs.
136        case n:OpArg => paramMap.get(n.getName.getOriginalName).getOrElse(n)
137        case n:IntRef => paramMap.get(n.getName).map(sargToVal).getOrElse(n)
138        case n:BoolRef => paramMap.get(n.getName).map(sargToVal).getOrElse(n)
139        case n:DimRef => paramMap.get(n.getName).map(sargToVal).getOrElse(n)
140        case n:UnitRef => paramMap.get(n.getName).map(sargToVal).getOrElse(n)
141        case _ => super.walk(node)
142      }
143    }
144
145    // Get the replaced type and clear out its static params, if any.
146    Some(clearStaticParams(staticReplacer(body).asInstanceOf[Type]))
147  }
148
149  /**
150   * Instantiates a generic type with some static arguments. The static
151   * parameters are retrieved from the body type and replaced inside body with
152   * their corresponding static arguments. In the end, any static parameters
153   * in the replaced type will be cleared.
154   *
155   * @param args A list of static arguments to apply to the generic type body.
156   * @param body The generic type whose static parameters are to be replaced.
157   * @return An option of a type identical to body but with every occurrence of
158   *         one of its declared static parameters replaced by corresponding
159   *         static args. If None, then the instantiation failed.
160   */
161  protected def staticInstantiation(sargs: List[StaticArg],
162                                    body: Type): Option[Type] =
163    staticInstantiation(sargs, getStaticParams(body), body)
164
165  /**
166   * Determines if the kinds of the given static args match those of the static
167   * parameters. In the case of type arguments, the type is checked to be a
168   * subtype of the corresponding type parameter's bounds.
169   */
170  protected def staticArgsMatchStaticParams(args: List[StaticArg],
171                                            params: List[StaticParam]): Boolean = {
172   
173    if (args.length != params.length) return false
174
175    // Match a single pair.
176    def argMatchesParam(argAndParam: (StaticArg, StaticParam)): Boolean = {
177      val (arg, param) = argAndParam
178      (arg, param.getKind) match {
179        case (STypeArg(_, argType), _:KindType) =>
180            toList(param.getExtendsClause).forall((bound:Type) =>
181              isSubtype(argType, bound, arg,
182                        errorMsg(normalize(argType), " not a subtype of ", normalize(bound))))
183        case (_:IntArg, _:KindInt) => true
184        case (_:BoolArg, _:KindBool) => true
185        case (_:DimArg, _:KindDim) => true
186        case (_:OpArg, _:KindOp) => true
187        case (_:UnitArg, _:KindUnit) => true
188        case (_:IntArg, _:KindNat) => true
189        case (_, _) => false
190      }
191    }
192
193    // Match every pair.
194    args.zip(params).forall(argMatchesParam)
195  }
196
197}
Note: See TracBrowser for help on using the browser.