root/trunk/ProjectFortress/src/com/sun/fortress/scala_src/useful/STypesUtil.scala @ 3915

Revision 3915, 9.8 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.useful
19
20import _root_.java.util.ArrayList
21import com.sun.fortress.compiler.GlobalEnvironment
22import com.sun.fortress.compiler.Types
23import com.sun.fortress.compiler.index._
24import com.sun.fortress.compiler.typechecker.StaticTypeReplacer
25import com.sun.fortress.compiler.typechecker.TypeAnalyzer
26import com.sun.fortress.compiler.typechecker.TypesUtil
27import com.sun.fortress.exceptions.InterpreterBug.bug
28import com.sun.fortress.exceptions.TypeError
29import com.sun.fortress.nodes._
30import com.sun.fortress.nodes_util.ExprFactory
31import com.sun.fortress.nodes_util.{NodeFactory => NF}
32import com.sun.fortress.nodes_util.{NodeUtil => NU}
33import com.sun.fortress.scala_src.nodes._
34import com.sun.fortress.scala_src.useful.Lists._
35import com.sun.fortress.scala_src.useful.Options._
36import com.sun.fortress.useful.HasAt
37import com.sun.fortress.useful.NI
38
39object STypesUtil {
40
41  /**
42   * A function type that takes two types and returns a boolean.
43   */
44  type Subtype = (Type, Type) => Boolean
45
46  /**
47   * Return the arrow type of the given FnDecl node.
48   */
49  def makeArrowFromFnDecl(f: FnDecl): ArrowType = {
50    val returnType = f.getHeader.getReturnType.unwrap
51    val params = toList(f.getHeader.getParams).map(NU.getParamType)
52    val argType = makeArgumentType(params)
53    val sparams = f.getHeader.getStaticParams
54    val where = f.getHeader.getWhereClause
55    val throws = f.getHeader.getThrowsClause
56    NF.makeArrowType(NU.getSpan(f),
57                     false,
58                     argType,
59                     returnType,
60                     NF.makeEffect(throws),
61                     sparams,
62                     where)
63  }
64 
65  /**
66   * Return the arrow type of the given Method.
67   * @TODO Make sure that the getReturnType method in these indices works
68   * as it should.
69   */
70  def makeArrowFromFunctional(f: Functional): ArrowType = f match {
71    case m:Method =>
72      val returnType = m.getReturnType.unwrap
73      val params = toList(m.parameters).map(NU.getParamType)
74      val argType = makeArgumentType(params)
75      m match {
76        case m:DeclaredMethod => makeArrowFromFnDecl(m.ast)
77        case g:FieldGetterMethod =>
78          NF.makeArrowType(NU.getSpan(g.ast),
79                           argType,
80                           returnType)
81        case s:FieldSetterMethod =>
82          NF.makeArrowType(NU.getSpan(s.ast),
83                           argType,
84                           returnType)
85      }
86    case f:Function => f match {
87      case f:DeclaredFunction => makeArrowFromFnDecl(f.ast)
88      case f:FunctionalMethod => makeArrowFromFnDecl(f.ast)
89      case f:Constructor =>
90        val argType =
91          makeArgumentType(toList(f.parameters).map(NU.getParamType))
92        val returnType = f.getReturnType.unwrap
93        val sparams = f.staticParameters
94        val where = f.where
95        val throws = f.thrownTypes
96        NF.makeArrowType(NF.typeSpan,
97                         false,
98                         argType,
99                         returnType,
100                         NF.makeEffect(throws),
101                         sparams,
102                         where)
103    }
104  }
105 
106  /**
107   * Make a single argument type from a list of types.
108   */
109  def makeArgumentType(ts: List[Type]): Type = ts match {
110    case Nil => Types.VOID
111    case t :: Nil => t
112    case _ =>
113      val span1 = NU.getSpan(ts.head)
114      val span2 = NU.getSpan(ts.last)
115      NF.makeTupleType(NU.spanTwo(span1, span2), toJavaList(ts))
116  }
117 
118  /**
119   * Make a domain type from a list of parameters, including varargs and
120   * keyword types. Ported from `TypeEnv.domainFromParams`.
121   */
122  def makeDomainType(ps: List[Param]): Type = {
123    val paramTypes = new ArrayList[Type](ps.length)
124    val keywordTypes = new ArrayList[KeywordType](ps.length)
125    var varargsType: Option[Type] = None
126    val span = ps match {
127      case Nil => NF.typeSpan
128      case _ => NU.spanTwo(NU.getSpan(ps.first), NU.getSpan(ps.last))
129    }
130   
131    // Extract out the appropriate parameter types.
132    ps.foreach(p => p match {
133      case SParam(_, _, _, _, _, Some(vaType)) => // Vararg
134        varargsType = Some(vaType)
135      case SParam(_, name, _, Some(idType), Some(expr), _) => // Keyword
136        keywordTypes.add(NF.makeKeywordType(name, idType))
137      case SParam(_, _, _, Some(idType), _, _) => // Normal
138        paramTypes.add(idType)
139      case _ => bug("Parameter missing type")
140    })
141    NF.makeDomain(span, paramTypes, toJavaOption(varargsType), keywordTypes)
142  }
143 
144  /**
145   * Convert a static parameter to the corresponding static arg. Ported from
146   * `TypeEnv.staticParamsToArgs`.
147   */
148  def staticParamToArg(p: StaticParam): StaticArg = {
149    val span = NU.getSpan(p)
150    (p.getName, p.getKind) match {
151      case (id:Id, _:KindBool) => NF.makeBoolArg(span, NF.makeBoolRef(span, id))
152      case (id:Id, _:KindDim) => NF.makeDimArg(span, NF.makeDimRef(span, id))
153      case (id:Id, _:KindInt) => NF.makeIntArg(span, NF.makeIntRef(span, id))
154      case (id:Id, _:KindNat) => NF.makeIntArg(span, NF.makeIntRef(span, id))
155      case (id:Id, _:KindType) => NF.makeTypeArg(span, NF.makeVarType(span, id))
156      case (id:Id, _:KindUnit) =>
157        NF.makeUnitArg(span, NF.makeUnitRef(span, false, id))
158      case (op:Op, _:KindOp) => NF.makeOpArg(span, ExprFactory.makeOpRef(op))
159      case _ => bug("Unexpected static parameter kind")
160    }
161  }
162
163  /**
164   * Get all the static parameters out of the given type.
165   */
166  def getStaticParams(typ: Type): List[StaticParam] =
167    toList(typ.getInfo.getStaticParams)
168
169  /**
170   * Return an identical type that has no static params.
171   * TODO: How to handle where clauses in TypeInfos?
172   */
173  def clearStaticParams(typ: Type): Type = {
174
175    // A walker that clears static params out of TypeInfos.
176    object paramWalker extends Walker {
177      override def walk(node: Any): Any = node match {
178        case STypeInfo(_, _, Nil, _) => node
179        case STypeInfo(a, b, _, _) => STypeInfo(a, b, Nil, None)
180        case _ => super.walk(node)
181      }
182    }
183    paramWalker(typ).asInstanceOf[Type]
184  }
185
186  /**
187   * Insert static parameters into a type. If the type already has static
188   * parameters, a bug is thrown.
189   */
190  def insertStaticParams(typ: Type, sparams: List[StaticParam]): Type = {
191
192    // A walker that clears static params out of TypeInfos.
193    object paramWalker extends Walker {
194      override def walk(node: Any): Any = node match {
195        case STypeInfo(a, b, Nil, c) => STypeInfo(a, b, sparams, c)
196        case STypeInfo(_, _, _, _) =>
197          bug("cannot overwrite static parameters")
198        case _ => super.walk(node)
199      }
200    }
201    paramWalker(typ).asInstanceOf
202  }
203
204  /**
205   * Determine if the type previously inferred by the type checker from the
206   * given expression is an arrow or intersection of arrow types.
207   */
208  def isArrows(expr: Expr): Boolean = isArrows(SExprUtil.getType(expr).get)
209
210  /**
211   * Determine if the given type is an arrow or intersection of arrow types.
212   */
213  def isArrows(ty: Type): Boolean =
214    TypesUtil.isArrows(ty).asInstanceOf[Boolean]
215
216  /**
217   * Performs the given substitution on the body type.
218   */
219  def substituteTypesForInferenceVars(substitution: Map[_InferenceVarType, Type],
220                                      body: Type): Type = {
221
222    object substitutionWalker extends Walker {
223      override def walk(node: Any): Any = node match {
224        case ty:_InferenceVarType => substitution.get(ty).getOrElse(super.walk(ty))
225        case _ => super.walk(node)
226      }
227    }
228
229    // Perform the substitution on the body type.
230    substitutionWalker(body).asInstanceOf[Type]
231  }
232
233  /**
234   * Returns the type of the static parameter's bound if it is a type parameter.
235   */
236  def staticParamBoundType(sparam: StaticParam): Option[Type] =
237    sparam.getKind match {
238      case SKindType(_) => Some(NF.makeIntersectionType(sparam.getExtendsClause))
239      case _ => None
240    }
241
242  /**
243   * Given a static parameters, returns a static arg containing a fresh
244   * inference variable.
245   */
246  def makeInferenceArg(sparam: StaticParam): StaticArg = sparam.getKind match {
247    case SKindType(_) => {
248      // Create a new inference var type.
249      val t = NF.make_InferenceVarType(NU.getSpan(sparam))
250      NF.makeTypeArg(NF.makeSpan(t), t)
251    }
252    case SKindInt(_) => NI.nyi()
253    case SKindBool(_) => NI.nyi()
254    case SKindDim(_) => NI.nyi()
255    case SKindOp(_) => NI.nyi()
256    case SKindUnit(_) => NI.nyi()
257    case SKindNat(_) => NI.nyi()
258    case _ => bug("unexpected kind of static parameter")
259  }
260
261  /**
262   * Returns a list of conjuncts of the given type. If given an intersection
263   * type, this is the set of the constituents. If ANY, this is empty. If some
264   * other type, this is the singleton set of that type.
265   */
266  def conjuncts(ty: Type): Set[Type] = ty match {
267    case _:AnyType => Set.empty[Type]
268    case SIntersectionType(_, elts) => Set(elts:_*).flatMap(conjuncts)
269    case _ => Set(ty)
270  }
271
272  /**
273   * Returns TypeConsIndex of "typ".
274   */
275  def getTypes(typ:Id, globalEnv: GlobalEnvironment,
276               compilation_unit: CompilationUnitIndex): TypeConsIndex = typ match {
277    case SId(info,Some(name),text) =>
278      globalEnv.api(name).typeConses.get(SId(info,None,text))
279    case _ => compilation_unit.typeConses.get(typ)
280  }
281}
Note: See TracBrowser for help on using the browser.