Changeset 4292

Show
Ignore:
Timestamp:
10/26/09 21:56:40 (4 weeks ago)
Author:
sukyoungryu
Message:

[self type idiom] Added another self-type idiom test.
[overloading checker] Implemented overloading checking of inherited dotted methods and functional methods.

Location:
trunk/ProjectFortress
Files:
2 added
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/ProjectFortress/src/com/sun/fortress/scala_src/typechecker/ExclusionOracle.scala

    r4275 r4292  
    3030import com.sun.fortress.compiler.index.TypeConsIndex 
    3131import com.sun.fortress.compiler.index.{Function => JavaFunction} 
    32 import com.sun.fortress.compiler.typechecker.TypeAnalyzer 
    3332import com.sun.fortress.exceptions.StaticError 
    3433import com.sun.fortress.exceptions.TypeError 
     
    3938import com.sun.fortress.parser_util.IdentifierUtil 
    4039import com.sun.fortress.repository.FortressRepository 
     40import com.sun.fortress.scala_src.types.TypeAnalyzer 
    4141import com.sun.fortress.scala_src.useful._ 
    4242import com.sun.fortress.scala_src.useful.ErrorLog 
     
    7474      case (_, SAnyType(_)) => false 
    7575      case (f@SVarType(_,_,_), s@SVarType(_,_,_)) => 
    76         ( toOption(typeAnalyzer.kindEnv.staticParam(f.getName)), 
    77           toOption(typeAnalyzer.kindEnv.staticParam(s.getName)) ) match { 
     76        ( toOption(typeAnalyzer.env.staticParam(f.getName)), 
     77          toOption(typeAnalyzer.env.staticParam(s.getName)) ) match { 
    7878          case (Some(fp), Some(sp)) => 
    7979            var result = false 
     
    105105        } 
    106106      case (f@SVarType(_,_,_), _) => 
    107         toOption(typeAnalyzer.kindEnv.staticParam(f.getName)) match { 
     107        toOption(typeAnalyzer.env.staticParam(f.getName)) match { 
    108108          case Some(fp) => 
    109109            var result = false 
     
    120120        } 
    121121      case (_, s@SVarType(_,_,_)) => 
    122         toOption(typeAnalyzer.kindEnv.staticParam(s.getName)) match { 
     122        toOption(typeAnalyzer.env.staticParam(s.getName)) match { 
    123123          case Some(sp) => 
    124124            var result = false 
     
    148148      case (_, _:TupleType) => true 
    149149      case (f:TraitType, s:TraitType) => 
    150         ( toOption(typeAnalyzer.traitTable.typeCons(f.getName)), 
    151           toOption(typeAnalyzer.traitTable.typeCons(s.getName)) ) match { 
     150        ( toOption(typeAnalyzer.traits.typeCons(f.getName)), 
     151          toOption(typeAnalyzer.traits.typeCons(s.getName)) ) match { 
    152152          case (Some(fi), Some(si)) => 
    153153            ( NodeUtil.isTraitOrObject(fi), NodeUtil.isTraitOrObject(si) ) match { 
     
    182182    for ( t <- toList(tIndex.extendsTypes) ) { 
    183183      if ( t.getBaseType.isInstanceOf[NamedType] ) { 
    184         result ++= transitivelyExcludes(typeAnalyzer.traitTable.typeCons(t.getBaseType.asInstanceOf[NamedType].getName).unwrap.asInstanceOf[ProperTraitIndex]) 
     184        result ++= transitivelyExcludes(typeAnalyzer.traits.typeCons(t.getBaseType.asInstanceOf[NamedType].getName).unwrap.asInstanceOf[ProperTraitIndex]) 
    185185      } 
    186186    } 
     
    254254          if (t.isInstanceOf[VarType]) result = false 
    255255          else { 
    256             toOption(typeAnalyzer.traitTable.typeCons(t.getName)) match { 
     256            toOption(typeAnalyzer.traits.typeCons(t.getName)) match { 
    257257              case None => 
    258258                errors.signal("Unrecognized name: " + t.getName, NodeUtil.getSpan(t)) 
  • trunk/ProjectFortress/src/com/sun/fortress/scala_src/typechecker/OverloadingChecker.scala

    r4289 r4292  
    2323import edu.rice.cs.plt.collect.Relation 
    2424import edu.rice.cs.plt.tuple.{Option => JavaOption} 
     25import edu.rice.cs.plt.tuple.{Pair => JavaPair} 
    2526import com.sun.fortress.compiler.GlobalEnvironment 
    2627import com.sun.fortress.compiler.index.CompilationUnitIndex 
     
    3334import com.sun.fortress.compiler.index.{Method => JavaMethod} 
    3435import com.sun.fortress.compiler.index.{Variable => JavaVariable} 
    35 import com.sun.fortress.compiler.typechecker.TypeAnalyzer 
     36import com.sun.fortress.compiler.typechecker.StaticTypeReplacer 
    3637import com.sun.fortress.exceptions.InterpreterBug 
    3738import com.sun.fortress.exceptions.StaticError 
     
    4344import com.sun.fortress.nodes_util.Span 
    4445import com.sun.fortress.parser_util.IdentifierUtil 
     46import com.sun.fortress.scala_src.types.TypeAnalyzer 
    4547import com.sun.fortress.scala_src.useful._ 
    4648import com.sun.fortress.scala_src.useful.Lists._ 
     
    7173                             f: IdOrOpOrAnonymousName) 
    7274                            : Set[((JavaList[StaticParam],Type,Type), Span)] = { 
    73       val fns = toSig(toSet(index.functions.matchFirst(f)).asInstanceOf[Set[JavaFunctional]]) 
     75      val fns = toFunctionSig(toSet(index.functions.matchFirst(f)).asInstanceOf[Set[JavaFunctional]]) 
    7476      if ( index.variables.keySet.contains(f) ) 
    7577        index.variables.get(f) match { 
     
    8486    } 
    8587 
    86     private def toSig(set: Set[JavaFunctional]) 
    87                      : Set[((JavaList[StaticParam],Type,Type), Span)] = 
    88       set.filter(isDeclaredFunctional(_)) 
    89          .map((f: JavaFunctional) => 
     88    // for functions 
     89    private def toFunctionSig(set: Set[JavaFunctional]) 
     90                             : Set[((JavaList[StaticParam],Type,Type), Span)] = 
     91      set.filter(isDeclaredFunction(_)) 
     92         .map(f => ((f.staticParameters, 
     93                     paramsToType(f.parameters, f.getSpan), 
     94                     f.getReturnType.unwrap), 
     95                    f.getSpan)) 
     96 
     97    // for functional methods 
     98    private def toFunctionalMethodSig(set: Set[(JavaFunction, StaticTypeReplacer)]) 
     99                                     : Set[((JavaList[StaticParam],Type,Type), Span)] = 
     100      set.filter(p => isFunctionalMethod(p._1)) 
     101         .map(p => { 
     102              val (f, replacer) = p 
    90103              ((f.staticParameters, 
    91                 paramsToType(f.parameters, f.getSpan), 
    92                 f.getReturnType.unwrap), 
    93                f.getSpan)) 
     104                replacer.replaceIn(paramsToType(f.parameters, f.getSpan)), 
     105                replacer.replaceIn(f.getReturnType.unwrap)), 
     106               f.getSpan)}) 
     107 
     108    // for dotted methods 
     109    private def toMethodSig(set: Set[(JavaMethod, StaticTypeReplacer)]) 
     110                           : Set[((JavaList[StaticParam],Type,Type), Span)] = 
     111      set.filter(p => isDeclaredMethod(p._1)) 
     112         .map(p => { 
     113              val (f, replacer) = p 
     114              ((f.staticParameters, 
     115                replacer.replaceIn(paramsToType(f.selfType.unwrap, f.parameters, f.getSpan)), 
     116                replacer.replaceIn(f.getReturnType.unwrap)), 
     117               f.getSpan)}) 
    94118 
    95119    /* Called by com.sun.fortress.compiler.StaticChecker.checkComponent 
     
    129153            } 
    130154          } 
    131           checkOverloading(f, set) 
     155          checkFunctionOverloading(f, set) 
    132156        } 
    133157        /* All inherited abstract methods in object expressions should be defined, 
     
    144168            // Extend the type analyzer with the collected static parameters 
    145169            val oldTypeAnalyzer = typeAnalyzer 
    146             val staticParameters = new ArrayList[StaticParam]() 
    147170            // Add static parameters of the enclosing trait or object 
    148             staticParameters.addAll( traitOrObject.staticParameters ) 
    149             typeAnalyzer = typeAnalyzer.extend(staticParameters, none[WhereClause]) 
     171            typeAnalyzer = typeAnalyzer.extend(toList(traitOrObject.staticParameters), 
     172                                               None) 
    150173            /* The parameter type of a setter must be the same as the return type 
    151174             * of a getter with the same name, if any. 
     
    166189                } 
    167190            } 
    168             val methods = traitOrObject.dottedMethods 
    169             for ( f <- toSet(methods.firstSet) ; if isDeclaredName(f) ) { 
    170               checkOverloading(f, toSig(toSet(methods.matchFirst(f)).asInstanceOf[Set[JavaFunctional]])) 
     191            val identity = new StaticTypeReplacer(new ArrayList[StaticParam](), 
     192                                                  new ArrayList[StaticArg]()) 
     193            var methods = toSet(traitOrObject.dottedMethods) 
     194                          .asInstanceOf[Set[JavaPair[IdOrOpOrAnonymousName, JavaFunctional]]] 
     195                          .map(p => new JavaPair(p.first, (p.second, identity))) 
     196            methods ++= 
     197              STypesUtil.inheritedMethods(typeAnalyzer.traits, 
     198                                          toList(traitOrObject.extendsTypes), 
     199                                          methods, typeAnalyzer) 
     200              .asInstanceOf[Set[JavaPair[IdOrOpOrAnonymousName, (JavaFunctional, StaticTypeReplacer)]]] 
     201 
     202            for ( f <- methods.map(x => x.first) ; if isDeclaredName(f) ) { 
     203              var ss = Set[(JavaMethod, StaticTypeReplacer)]() 
     204              methods.filter(p => (p.first == f && p.second._1.isInstanceOf[JavaMethod]) && 
     205                             p.second._1.asInstanceOf[JavaMethod].selfType.isSome) 
     206                     .foreach(ss += _.second.asInstanceOf[(JavaMethod, StaticTypeReplacer)]) 
     207              checkMethodOverloading(f, toMethodSig(ss)) 
     208            } 
     209            for ( f <- methods.map(x => x.first) ; if isDeclaredName(f) ) { 
     210              var ss = Set[(JavaFunction, StaticTypeReplacer)]() 
     211              methods.filter(p => p.first == f && p.second._1.isInstanceOf[JavaFunction]) 
     212                     .foreach(ss += _.second.asInstanceOf[(JavaFunction, StaticTypeReplacer)]) 
     213              checkFunctionOverloading(f, toFunctionalMethodSig(ss)) 
    171214            } 
    172215            typeAnalyzer = oldTypeAnalyzer 
     
    174217        toJavaList(errors) 
    175218    } 
     219 
     220    /* Checks the validity of the overloaded method declarations. */ 
     221    private def checkMethodOverloading(name: IdOrOpOrAnonymousName, 
     222                                       set: Set[((JavaList[StaticParam],Type,Type), Span)]) 
     223                                      : Unit = 
     224      checkOverloading(name, set, true) 
     225 
     226    /* Checks the validity of the overloaded function declarations. */ 
     227    private def checkFunctionOverloading(name: IdOrOpOrAnonymousName, 
     228                                         set: Set[((JavaList[StaticParam],Type,Type), Span)]) 
     229                                        : Unit = 
     230      checkOverloading(name, set, false) 
    176231 
    177232    /* Checks the validity of the overloaded function declarations. */ 
    178233    private def checkOverloading(name: IdOrOpOrAnonymousName, 
    179                                  set: Set[((JavaList[StaticParam],Type,Type), Span)]) 
     234                                 set: Set[((JavaList[StaticParam],Type,Type), Span)], 
     235                                 isMethod: Boolean) 
    180236                                : Unit = set.size match { 
    181237      case 0 => 
     
    189245                    "There are multiple declarations of " + 
    190246                    name + " with the same type: " + 
    191                     param + " -> " + result) 
     247                    (if (isMethod) dropReceiver(param) else param) + 
     248                    " -> " + result) 
    192249            case _ => 
    193250              // A functional which takes a single parameter of a parametric type 
     
    249306        staticParameters.addAll(sub_type._1._1) 
    250307        staticParameters.addAll(super_type._1._1) 
    251         typeAnalyzer = typeAnalyzer.extend(staticParameters, none[WhereClause]) 
     308        typeAnalyzer = typeAnalyzer.extend(toList(staticParameters), None) 
    252309        val result = subtype(super_type._1._2, sub_type._1._2) && 
    253310                     subtype(sub_type._1._3, super_type._1._3) 
     
    273330        staticParameters.addAll(first._1._1) 
    274331        staticParameters.addAll(second._1._1) 
    275         typeAnalyzer = typeAnalyzer.extend(staticParameters, none[WhereClause]) 
     332        typeAnalyzer = typeAnalyzer.extend(toList(staticParameters), None) 
    276333        val result = new ExclusionOracle(typeAnalyzer, 
    277334                                         new ErrorLog()).excludes(first._1._2, 
     
    291348        staticParameters.addAll(first._1._1) 
    292349        staticParameters.addAll(second._1._1) 
    293         typeAnalyzer = typeAnalyzer.extend(staticParameters, none[WhereClause]) 
     350        typeAnalyzer = typeAnalyzer.extend(toList(staticParameters), None) 
    294351        var result = false 
    295352        val exclusionOracle = new ExclusionOracle(typeAnalyzer, new ErrorLog()) 
     
    333390                    var i = 0 
    334391                    while ( i < size ) { 
    335                         elems = elems ::: List(typeAnalyzer.meet(toJavaList(tuples.map(ty => NodeUtil.getTupleTypeElem(ty, i))))) 
     392                        elems = elems ::: List(typeAnalyzer.meet(tuples.map(ty => NodeUtil.getTupleTypeElem(ty, i)))) 
    336393                        i += 1 
    337394                    } 
     
    419476        // add static parameters of "f"'s enclosing trait or object 
    420477        if ( NodeUtil.isFunctionalMethod(f) ) { 
    421             val ind = typeAnalyzer.traitTable.typeCons(NodeUtil.getDeclaringTrait(f)) 
     478            val ind = typeAnalyzer.traits.typeCons(NodeUtil.getDeclaringTrait(f)) 
    422479            if ( ind.isSome && NodeUtil.isTraitOrObject(ind.unwrap) ) { 
    423480                staticParameters.addAll( NodeUtil.getStaticParameters(ind.unwrap) ) 
     
    427484        // add static parameters of "g"'s enclosing trait or object 
    428485        if ( NodeUtil.isFunctionalMethod(g) ) { 
    429             val ind = typeAnalyzer.traitTable.typeCons(NodeUtil.getDeclaringTrait(g)) 
     486            val ind = typeAnalyzer.traits.typeCons(NodeUtil.getDeclaringTrait(g)) 
    430487            if ( ind.isSome && NodeUtil.isTraitOrObject(ind.unwrap) ) { 
    431488                staticParameters.addAll( NodeUtil.getStaticParameters(ind.unwrap) ) 
     
    438495        // Whether "g"'s parameter type is a subtype of "f"'s parameter type 
    439496        // and "f"'s return type is a subtype of "g"'s return type 
    440         typeAnalyzer = typeAnalyzer.extend(staticParameters, none[WhereClause]) 
     497        typeAnalyzer = typeAnalyzer.extend(toList(staticParameters), None) 
    441498        val result = subtype(paramsToType(g.parameters, g.getSpan), 
    442499                             paramsToType(f.parameters, f.getSpan)) && 
     
    446503    } 
    447504 
     505    /* Drop the first element denoting the receiver type of the given type. */ 
     506    private def dropReceiver(param: Type) = param match { 
     507      case STupleType(info, _::ty::Nil, None, Nil) => ty 
     508      case STupleType(info, elements, varargs, keywords) => 
     509        STupleType(info, elements.takeRight(elements.size-1), varargs, keywords) 
     510      case _ => NodeFactory.makeVoidType(NodeUtil.getSpan(param)) 
     511    } 
     512 
    448513    def isDeclaredName(f: IdOrOpOrAnonymousName) = f match { 
    449514        case SId(_,_,str) => IdentifierUtil.validId(str) 
     
    452517    } 
    453518 
    454     def isDeclaredFunctional(f: JavaFunctional) = f match { 
     519    def isDeclaredMethod(f: JavaFunctional) = f match { 
     520        case DeclaredMethod(_,_) => true 
     521        case _ => false 
     522    } 
     523 
     524    def isDeclaredFunction(f: JavaFunctional) = f match { 
    455525        case DeclaredFunction(_) => true 
    456         case DeclaredMethod(_,_) => true 
     526        case _ => false 
     527    } 
     528 
     529    def isFunctionalMethod(f: JavaFunctional) = f match { 
     530        case FunctionalMethod(_,_) => true 
    457531        case _ => false 
    458532    } 
     
    483557      } 
    484558 
     559    /* Returns the type of the given self type and a list of parameters. */ 
     560    private def paramsToType(self: Type, params: JavaList[Param], span: Span): Type = { 
     561      val span = params.size match { 
     562        case 0 => NodeUtil.getSpan(self) 
     563        case _ => NodeUtil.spanAll(params) 
     564      } 
     565      val elems = toList(params).map(paramToType) 
     566      if (elems.forall(_.isDefined)) 
     567        NodeFactory.makeTupleType(span, toJavaList(List(self) ++ elems.map(_.get))) 
     568      else { 
     569        error(span, 
     570              "Type checking couldn't infer the type of " + params) 
     571        NodeFactory.makeVoidType(span) 
     572      } 
     573    } 
     574 
    485575    private def error(loc: Span, msg: String) = 
    486576        errors = errors ::: List(TypeError.make(msg, loc)) 
  • trunk/ProjectFortress/src/com/sun/fortress/scala_src/useful/STypesUtil.scala

    r4291 r4292  
    860860  } 
    861861 
    862   // Invariant: Parameter types of all the methods should exist. 
     862  // Invariant: Parameter types of all the methods should exist, 
     863  //            either given or inferred. 
    863864  def inheritedMethods(traits: TraitTable, 
    864865                       extendedTraits: List[TraitTypeWhere], 
    865                        initial: Set[Pair[IdOrOpOrAnonymousName, Functional]], 
     866                       initial: Set[Pair[IdOrOpOrAnonymousName, 
     867                                         (Functional, StaticTypeReplacer)]], 
    866868                       analyzer: TypeAnalyzer) = { 
    867869    // Return all of the methods from super-traits 
    868870    def inheritedMethodsHelper(history: HierarchyHistory, 
    869871                               extended_traits: List[TraitTypeWhere], 
    870                                given: Set[Pair[IdOrOpOrAnonymousName, Functional]]) 
    871                               : Set[Pair[IdOrOpOrAnonymousName, Functional]] = { 
     872                               given: Set[(String, Type)]) 
     873                              : Set[Pair[IdOrOpOrAnonymousName, 
     874                                         (Functional, StaticTypeReplacer)]] = { 
    872875      var allMethods = given 
    873       var methods = Set[Pair[IdOrOpOrAnonymousName, Functional]]() 
     876      // a set of inherited methods: 
     877      // a set of pairs of method names and 
     878      //                   pairs of Functionals and static parameters substitutions 
     879      var methods = Set[Pair[IdOrOpOrAnonymousName, (Functional, StaticTypeReplacer)]]() 
    874880      var h = history 
    875881      for (trait_ <- extended_traits) { 
     
    882888                case Some(ti) => 
    883889                  if ( ti.isInstanceOf[TraitIndex] ) { 
     890                    val tindex = ti.asInstanceOf[TraitIndex] 
    884891                    // Instantiate methods with static args 
    885892                    val paramsToArgs = new StaticTypeReplacer(ti.staticParameters, 
    886893                                                              toJavaList(trait_args)) 
    887                     var collected: Collection[Pair[IdOrOpOrAnonymousName, Functional]] = 
    888                       toSet(ti.asInstanceOf[TraitIndex].dottedMethods) 
    889                       .asInstanceOf[CSet[Pair[IdOrOpOrAnonymousName, Functional]]] 
    890                     collected ++= 
    891                       toSet(ti.asInstanceOf[TraitIndex].functionalMethods) 
    892                       .asInstanceOf[CSet[Pair[IdOrOpOrAnonymousName, Functional]]] 
     894                    var collected = toSet(tindex.dottedMethods) 
     895                      .asInstanceOf[Collection[Pair[IdOrOpOrAnonymousName, Functional]]] 
     896                    collected ++= toSet(tindex.functionalMethods) 
     897                      .asInstanceOf[Collection[Pair[IdOrOpOrAnonymousName, Functional]]] 
    893898                    for ( pair <- collected ; if pair.first.isInstanceOf[IdOrOp] ) { 
    894                       val fname = pair.first.asInstanceOf[IdOrOp].getText 
    895                       val span = NU.getSpan(pair.first) 
    896                       val paramTy = paramsToType(toList(pair.second.parameters), 
    897                                                  span) match { 
    898                         case Some(t) => paramsToArgs.replaceIn(t) 
    899                         case _ => NF.makeVoidType(span) 
    900                       } 
     899                      val (method_name, method_func) = (pair.first, pair.second) 
     900                      val new_pair = toNameParamTy(method_name, method_func) 
     901                      val fname = new_pair._1 
     902                      val paramTy = paramsToArgs.replaceIn(new_pair._2) 
    901903                      if (!isOverride(fname, paramTy, allMethods, analyzer)) { 
    902                         methods += pair 
    903                         allMethods += pair 
     904                        methods += new Pair(method_name, (method_func, paramsToArgs)) 
     905                        allMethods += ((fname, paramTy)) 
    904906                      } 
    905907                    } 
    906908                    val instantiated_extends_types = 
    907                       toList(ti.asInstanceOf[TraitIndex].extendsTypes).map( (t:TraitTypeWhere) => 
    908                             t.accept(paramsToArgs).asInstanceOf[TraitTypeWhere] ) 
     909                      toList(tindex.extendsTypes).map(_.accept(paramsToArgs).asInstanceOf[TraitTypeWhere]) 
    909910                    val old_hist = h 
    910911                    val inherited = inheritedMethodsHelper(h, instantiated_extends_types, 
    911912                                                           allMethods) 
    912913                    methods ++= inherited 
    913                     allMethods ++= inherited 
     914                    allMethods ++= inherited.map(p => toNameParamTy(p.first, p.second._1)) 
    914915                    h = old_hist 
    915916                  } else return methods 
     
    922923      methods 
    923924    } 
    924     inheritedMethodsHelper(new HierarchyHistory(), extendedTraits, initial) 
     925    inheritedMethodsHelper(new HierarchyHistory(), extendedTraits, 
     926                           initial.map(p => toNameParamTy(p.first, p.second._1))) 
     927  } 
     928 
     929  private def toNameParamTy(name: IdOrOpOrAnonymousName, func: Functional) = { 
     930    val span = NU.getSpan(name) 
     931    val ty = paramsToType(toList(func.parameters), span) match { 
     932      case Some(t) => t 
     933      case _ => NF.makeVoidType(span) 
     934    } 
     935   (name.asInstanceOf[IdOrOp].getText, ty) 
    925936  } 
    926937 
    927938  private def isOverride(fname: String, paramTy: Type, 
    928                          allMethods: Set[Pair[IdOrOpOrAnonymousName, Functional]], 
     939                         allMethods: Set[(String, Type)], 
    929940                         analyzer: TypeAnalyzer): Boolean = { 
    930     for (f <- allMethods; 
    931          if fname.equals(f.first.asInstanceOf[IdOrOp].getText)) { 
    932       val span = NU.getSpan(f.first) 
    933       val otherParamTy = paramsToType(toList(f.second.parameters), span) match { 
    934         case Some(t) => t 
    935         case _ => NF.makeVoidType(span) 
    936       } 
    937       if (analyzer.equivalent(paramTy, otherParamTy).isTrue) return true 
     941    for (f <- allMethods; if fname.equals(f._1)) { 
     942      if (analyzer.equivalent(paramTy, f._2).isTrue) return true 
    938943    } 
    939944    false 
     
    949954        if (elems.forall(_.isDefined)) 
    950955          Some(NF.makeTupleType(NU.spanAll(toJavaList(params)), 
    951                                 Lists.toJavaList(elems.map(_.get)))) 
     956                                toJavaList(elems.map(_.get)))) 
    952957        else None 
    953958    }