| 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 | |
|---|
| 18 | package com.sun.fortress.scala_src.typechecker.impls |
|---|
| 19 | |
|---|
| 20 | import edu.rice.cs.plt.collect.IndexedRelation |
|---|
| 21 | import edu.rice.cs.plt.collect.Relation |
|---|
| 22 | import com.sun.fortress.compiler.disambiguator.ExprDisambiguator.HierarchyHistory |
|---|
| 23 | import com.sun.fortress.compiler.index.Method |
|---|
| 24 | import com.sun.fortress.compiler.index.ProperTraitIndex |
|---|
| 25 | import com.sun.fortress.compiler.index.TraitIndex |
|---|
| 26 | import com.sun.fortress.compiler.typechecker.StaticTypeReplacer |
|---|
| 27 | import com.sun.fortress.exceptions.InterpreterBug.bug |
|---|
| 28 | import com.sun.fortress.exceptions.StaticError.errorMsg |
|---|
| 29 | import com.sun.fortress.nodes._ |
|---|
| 30 | import com.sun.fortress.scala_src.nodes._ |
|---|
| 31 | import com.sun.fortress.scala_src.typechecker._ |
|---|
| 32 | import com.sun.fortress.scala_src.useful.Lists._ |
|---|
| 33 | import com.sun.fortress.scala_src.useful.Options._ |
|---|
| 34 | import com.sun.fortress.scala_src.useful.Sets._ |
|---|
| 35 | import 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 | */ |
|---|
| 50 | trait 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 | } |
|---|