diff options
author | Martin Odersky <odersky@gmail.com> | 2005-08-29 14:38:38 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-08-29 14:38:38 +0000 |
commit | 184a284ccc9c842adaaec728914f11a2cad33c18 (patch) | |
tree | 25ae4ff123300b6dc24f4c1a2ec0182105e75ec6 | |
parent | 7d50bd127a071b84cc3d5e6e989b5f57d5988aaf (diff) | |
download | scala-184a284ccc9c842adaaec728914f11a2cad33c18.tar.gz scala-184a284ccc9c842adaaec728914f11a2cad33c18.tar.bz2 scala-184a284ccc9c842adaaec728914f11a2cad33c18.zip |
*** empty log message ***
41 files changed, 1048 insertions, 327 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala index 2f6f1e6075..4186eab583 100755 --- a/sources/scala/tools/nsc/Global.scala +++ b/sources/scala/tools/nsc/Global.scala @@ -56,8 +56,13 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable val copy = new LazyTreeCopier(); type AttrInfo = Pair[Type, List[Any]]; + + /** A map from symbols to their attributes */ val attributes = new HashMap[Symbol, List[AttrInfo]]; + /** A map from parameter accessor symbols to their aliases */ + val aliases = new HashMap[Symbol, Symbol]; + // reporting ------------------------------------------------------- def error(msg: String) = reporter.error(null, msg); @@ -144,6 +149,8 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable def apply(unit: CompilationUnit): unit; private val isErased = prev.name == "erasure" || prev.erasedTypes; override def erasedTypes: boolean = isErased; + private val isFlat = prev.name == "flatten" || prev.flatClasses; + override def flatClasses: boolean = isFlat; def applyPhase(unit: CompilationUnit): unit = { if (settings.debug.value) inform("[running phase " + name + " on " + unit + "]"); apply(unit) @@ -186,6 +193,14 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable val global: Global.this.type = Global.this; } + object lambdaLift extends LambdaLift { + val global: Global.this.type = Global.this; + } + + object flatten extends Flatten { + val global: Global.this.type = Global.this; + } + object sampleTransform extends SampleTransform { val global: Global.this.type = Global.this; } @@ -208,6 +223,8 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable transMatcher, explicitOuter, erasure, + lambdaLift, + flatten, if (settings.Xshowicode.value) genicode else sampleTransform); @@ -239,6 +256,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable val namerPhase = phaseNamed("namer"); val typerPhase = phaseNamed("typer"); + val refchecksPhase = phaseNamed("refchecks"); val erasurePhase = phaseNamed("erasure"); val typer = new analyzer.Typer(analyzer.NoContext.make(EmptyTree, definitions.RootClass, new Scope())) { diff --git a/sources/scala/tools/nsc/Phase.scala b/sources/scala/tools/nsc/Phase.scala index 536cd81390..31410ce162 100644 --- a/sources/scala/tools/nsc/Phase.scala +++ b/sources/scala/tools/nsc/Phase.scala @@ -23,6 +23,7 @@ abstract class Phase(val prev: Phase) { def name: String; def description: String = name; def erasedTypes: boolean = false; + def flatClasses: boolean = false; def run: unit; override def toString() = name; diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala index 4602059037..453ecced91 100755 --- a/sources/scala/tools/nsc/ast/TreeGen.scala +++ b/sources/scala/tools/nsc/ast/TreeGen.scala @@ -66,6 +66,17 @@ abstract class TreeGen { tree } + /** Cast `tree' to type `pt' */ + def cast(tree: Tree, pt: Type): Tree = { + if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt); + assert(!tree.tpe.isInstanceOf[MethodType], tree); + typer.typed { + atPos(tree.pos) { + Apply(TypeApply(Select(tree, Object_asInstanceOf), List(TypeTree(pt))), List()) + } + } + } + /** Builds a reference with stable type to given symbol */ def mkStableRef(pre: Type, sym: Symbol): Tree = stabilize(mkRef(pre, sym)); def mkStableRef(sym: Symbol): Tree = stabilize(mkRef(sym)); @@ -75,13 +86,11 @@ abstract class TreeGen { def Ident(sym: Symbol) = { assert(sym.isTerm); - sym.setFlag(ACCESSED); global.Ident(sym.name) setSymbol sym setType sym.tpe; } def Select(qual: Tree, sym: Symbol) = { assert(sym.isTerm); - sym.setFlag(ACCESSED); val result = global.Select(qual, sym.name) setSymbol sym; if (qual.tpe != null) result setType qual.tpe.memberType(sym); result diff --git a/sources/scala/tools/nsc/ast/TreeInfo.scala b/sources/scala/tools/nsc/ast/TreeInfo.scala index 0b18c18b4e..d0bd3011ea 100644 --- a/sources/scala/tools/nsc/ast/TreeInfo.scala +++ b/sources/scala/tools/nsc/ast/TreeInfo.scala @@ -94,19 +94,6 @@ abstract class TreeInfo { false } - /** Is tree a pure constructor? - */ - def isPureConstr(tree: Tree): boolean = tree match { - case Ident(_) | Select(_, _) => - tree.symbol.isPrimaryConstructor - case TypeApply(fn, _) => - isPureConstr(fn) - case Apply(fn, List()) => - isPureConstr(fn) - case _ => - false - } - /** Is tree a self constructor call? */ def isSelfConstrCall(tree: Tree): boolean = tree match { @@ -151,6 +138,13 @@ abstract class TreeInfo { case _ => false } + /** Is this pattern node a catch-all (wildcard or variable) pattern? */ + def isDefaultCase(cdef: CaseDef) = cdef match { + case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true + case CaseDef(Bind(_, Ident(nme.WILDCARD)), EmptyTree, _) => true + case _ => false + } + /** Is this pattern node a sequence-valued pattern? */ def isSequenceValued(tree: Tree): boolean = tree match { case Bind(_, body) => isSequenceValued(body) diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala index fbf017fdbc..49dd0a3b05 100644 --- a/sources/scala/tools/nsc/ast/TreePrinters.scala +++ b/sources/scala/tools/nsc/ast/TreePrinters.scala @@ -272,7 +272,7 @@ abstract class TreePrinters { case ClassDef(_, _, _, _, impl) => ClassDef(tree.symbol, impl) case ModuleDef(_, _, impl) => ModuleDef(tree.symbol, impl) case ValDef(_, _, _, rhs) => ValDef(tree.symbol, rhs) - case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss => rhs) + case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss, rhs) case AbsTypeDef(_, _, _, _) => AbsTypeDef(tree.symbol) case AliasTypeDef(_, _, _, rhs) => AliasTypeDef(tree.symbol, rhs) case _ => tree diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala index ed680a8814..cdfe4ce8b4 100644 --- a/sources/scala/tools/nsc/ast/Trees.scala +++ b/sources/scala/tools/nsc/ast/Trees.scala @@ -376,10 +376,8 @@ abstract class Trees: Global { override def isType = selector.isTypeName; } - def Select(qualifier: Tree, sym: Symbol): Select = { - sym.setFlag(ACCESSED); - Select(qualifier, sym.name) setSymbol sym - } + def Select(qualifier: Tree, sym: Symbol): Select = + Select(qualifier, sym.name) setSymbol sym; /** Identifier */ case class Ident(name: Name) @@ -388,10 +386,8 @@ abstract class Trees: Global { override def isType = name.isTypeName; } - def Ident(sym: Symbol): Ident = { - sym.setFlag(ACCESSED); - Ident(sym.name) setSymbol sym - } + def Ident(sym: Symbol): Ident = + Ident(sym.name) setSymbol sym; /** Literal */ case class Literal(value: Constant) @@ -921,7 +917,8 @@ abstract class Trees: Global { def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = List.mapConserve(stats)(stat => if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat)) - else transform(stat)); + else transform(stat)) filter (EmptyTree !=); + def transformUnit(unit: CompilationUnit): unit = { unit.body = transform(unit.body) } def atOwner[A](owner: Symbol)(trans: => A): A = { val prevOwner = currentOwner; @@ -938,11 +935,11 @@ abstract class Trees: Global { case EmptyTree => ; case PackageDef(name, stats) => - atOwner(tree.symbol) { + atOwner(tree.symbol.moduleClass) { traverseTrees(stats) } case ClassDef(mods, name, tparams, tpt, impl) => - atOwner(tree.symbol.moduleClass) { + atOwner(tree.symbol) { traverseTrees(tparams); traverse(tpt); traverse(impl) } case ModuleDef(mods, name, impl) => @@ -1074,6 +1071,14 @@ abstract class Trees: Global { def apply(tree: Tree): Tree = { val tree1 = tree.duplicate; traverse(tree1); tree1 } } + class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser { + override def traverse(tree: Tree): unit = { + if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.owner == oldowner) + tree.symbol.owner = newowner; + super.traverse(tree) + } + } + final class TreeList { private var trees = List[Tree](); def append(t: Tree): TreeList = { trees = t :: trees; this } diff --git a/sources/scala/tools/nsc/ast/parser/Parsers.scala b/sources/scala/tools/nsc/ast/parser/Parsers.scala index 79bc2b024c..b002dfd967 100755 --- a/sources/scala/tools/nsc/ast/parser/Parsers.scala +++ b/sources/scala/tools/nsc/ast/parser/Parsers.scala @@ -753,7 +753,7 @@ abstract class Parsers: SyntaxAnalyzer { * | SimpleExpr1 ArgumentExprs */ def simpleExpr(): Tree = { - var t: Tree = _; + var t: Tree = null; var isNew = false; in.token match { case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | @@ -1111,6 +1111,7 @@ abstract class Parsers: SyntaxAnalyzer { */ def paramClauses(owner: Name, implicitViews: List[Tree], ofCaseClass: boolean): List[List[ValDef]] = { var implicitmod = 0; + var caseParam = ofCaseClass; def param(): ValDef = { atPos(in.pos) { var mods = Flags.PARAM; @@ -1119,8 +1120,9 @@ abstract class Parsers: SyntaxAnalyzer { if (in.token == VAL) in.nextToken() else { if (mods != Flags.PARAMACCESSOR) accept(VAL); - if (!ofCaseClass) mods = mods | Flags.PRIVATE | Flags.LOCAL; + if (!(caseParam)) mods = mods | Flags.PRIVATE | Flags.LOCAL; } + if (caseParam) mods = mods | Flags.CASEACCESSOR; } val name = ident(); accept(COLON); @@ -1149,13 +1151,14 @@ abstract class Parsers: SyntaxAnalyzer { in.nextToken(); vds += paramClause(); accept(RPAREN); + caseParam = false } val result = vds.toList; if (owner == nme.CONSTRUCTOR && (result.isEmpty || (!result.head.isEmpty && (result.head.head.mods & Flags.IMPLICIT) != 0))) syntaxError(pos, "auxiliary constructor needs non-implicit parameter list", false); - addImplicitViews(result, implicitViews) + addImplicitViews(owner, result, implicitViews) } /** ParamType ::= Type | `=>' Type | Type `*' diff --git a/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala index 47648f339c..9ceb0dedff 100644 --- a/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -94,7 +94,7 @@ abstract class TreeBuilder { if (parents.tail.isEmpty && stats.isEmpty) New(parents.head, argss) else { - val x = freshName(nme.ANON_CLASS_NAME.toString()).toTypeName; + val x = nme.ANON_CLASS_NAME.toTypeName; Block( List(ClassDef( FINAL | SYNTHETIC, x, List(), TypeTree(), @@ -272,8 +272,9 @@ abstract class TreeBuilder { argtpes ::: List(restpe)); /** Append implicit view section if for `implicitViews' if nonempty */ - def addImplicitViews(vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = { - def makeViewParam(tpt: Tree) = ValDef(PARAM | IMPLICIT | LOCAL | PRIVATE, freshName("view$"), tpt, EmptyTree); + def addImplicitViews(owner: Name, vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = { + val mods = if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM; + def makeViewParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshName("view$"), tpt, EmptyTree); if (implicitViews.isEmpty) vparamss else vparamss ::: List(implicitViews map makeViewParam) } diff --git a/sources/scala/tools/nsc/backend/icode/GenICode.scala b/sources/scala/tools/nsc/backend/icode/GenICode.scala index 727202ca72..e730351784 100644 --- a/sources/scala/tools/nsc/backend/icode/GenICode.scala +++ b/sources/scala/tools/nsc/backend/icode/GenICode.scala @@ -248,7 +248,7 @@ abstract class GenICode extends SubComponent { // normal method call var invokeStyle = - if (sym.isConstructor) + if (sym.isClassConstructor) NewInstance; else if (sym.isStatic) Static(false) diff --git a/sources/scala/tools/nsc/matching/BerrySethis.scala b/sources/scala/tools/nsc/matching/BerrySethis.scala index 4e774ad94e..85638903b0 100644 --- a/sources/scala/tools/nsc/matching/BerrySethis.scala +++ b/sources/scala/tools/nsc/matching/BerrySethis.scala @@ -453,7 +453,7 @@ class BerrySethi { def makeTransition(srcI:Integer, destI:Integer, label: Label): Unit = { var src = srcI.intValue() ; var dest = destI.intValue() ; - var arrows: Vector = _; //, revArrows; + var arrows: Vector = null; //, revArrows; //Label revLabel = new Pair( srcI, label ); label match { case DefaultLabel() => @@ -660,8 +660,8 @@ class BindingBerrySethi extends BerrySethi { override def makeTransition(srcI: Integer, destI: Integer, label: Label): Unit = { val src = srcI.intValue() ; val dest = destI.intValue() ; - var arrows: Vector = _; - var revArrows: Vector = _; + var arrows: Vector = null; + var revArrows: Vector = null; val revLabel = new LPair(srcI, label); label match { case DefaultLabel() => diff --git a/sources/scala/tools/nsc/matching/DetWordAutoms.scala b/sources/scala/tools/nsc/matching/DetWordAutoms.scala index 553b5b1e13..59bca48cb6 100644 --- a/sources/scala/tools/nsc/matching/DetWordAutoms.scala +++ b/sources/scala/tools/nsc/matching/DetWordAutoms.scala @@ -175,10 +175,10 @@ class DetWordAutom { def determinize( nfa: NondetWordAutom ): Unit = { //Console.println("DetWordAutom:determinize"); //System.out.println("nfa:");nfa.print(); - var states:TreeSet = _; // temp: Set[Set[Integer]] - var deftrans:HashMap = _; // Set[Integer] -> Int + var states:TreeSet = null; // temp: Set[Set[Integer]] + var deftrans:HashMap = null; // Set[Integer] -> Int - var trans: HashMap = _; // always points to a mapping ( Label -> Q ) + var trans: HashMap = null; // always points to a mapping ( Label -> Q ) var ix = 0; // state index this._labels = nfa.labels; @@ -300,7 +300,7 @@ class DetWordAutom { val state_x = indexMap.get( state ).asInstanceOf[Integer]; val defTarget = deftrans.get( state ).asInstanceOf[TreeSet]; - var defTarget_x: Integer = _; + var defTarget_x: Integer = null; if( null != defTarget) { defTarget_x = indexMap.get( defTarget ).asInstanceOf[Integer]; ////System.out.println("deftarget" + defTarget); @@ -316,7 +316,7 @@ class DetWordAutom { while(labs.hasNext()) { val label = labs.next(); val target = trans.get( label ).asInstanceOf[TreeSet]; - var target_x: Integer = _; + var target_x: Integer = null; if( null != target ) { // //System.out.println("target :"+target); target_x = indexMap.get( target ).asInstanceOf[Integer]; @@ -375,7 +375,7 @@ class DetWordAutom { * null if no such transition exists. */ def delta(i: Int, label: Label): Integer = { - var target:Integer =_; + var target:Integer = null; label match { case DefaultLabel() => if (! hasDefault(i)) @@ -860,7 +860,7 @@ class DetWordAutom { * gets flattened. */ def printBefore(states: TreeSet, deftrans: HashMap): Unit = { - var trans: HashMap = _; + var trans: HashMap = null; Console.println(states); val it = states.iterator(); while (it.hasNext()) { diff --git a/sources/scala/tools/nsc/matching/LeftTracers.scala b/sources/scala/tools/nsc/matching/LeftTracers.scala index fe38779951..4ab525f70f 100644 --- a/sources/scala/tools/nsc/matching/LeftTracers.scala +++ b/sources/scala/tools/nsc/matching/LeftTracers.scala @@ -132,12 +132,12 @@ abstract class LeftTracerInScala extends Autom2Scala { */ def code_state(i: Int, elseBody: Tree): Tree = { - var runFinished: Tree = _; // holds result of the run + var runFinished: Tree = null; // holds result of the run var finalSwRes: Int = 0; runFinished = run_finished(i); - var stateBody: Tree = _ ; // action(delta) for one particular label/test + var stateBody: Tree = null ; // action(delta) for one particular label/test // default action (fail if there is none) diff --git a/sources/scala/tools/nsc/matching/PatternMatchers.scala b/sources/scala/tools/nsc/matching/PatternMatchers.scala index c3ae5d9c4a..a87ef728f2 100644 --- a/sources/scala/tools/nsc/matching/PatternMatchers.scala +++ b/sources/scala/tools/nsc/matching/PatternMatchers.scala @@ -386,8 +386,9 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt // Console.println("newHeader :: casted="+casted); // Console.println("newHeader :: casted.tpe="+casted.tpe); //Console.println("newHeader :: "); - val ts = casted.tpe.symbol.asInstanceOf[ClassSymbol] - .caseFieldAccessors(index); + val caseAccs = casted.tpe.symbol.caseFieldAccessors; + if (caseAccs.length <= index) System.out.println("selecting " + index + " in case fields of " + casted.tpe.symbol + "=" + casted.tpe.symbol.caseFieldAccessors);//debug + val ts = caseAccs(index); //Console.println("newHeader :: ts="+ts); //val accType = casted.tpe.memberType(ts); // old scalac //val accTree = global.typer.typed(Select(ident, ts)); // ! diff --git a/sources/scala/tools/nsc/matching/PatternNodes.scala b/sources/scala/tools/nsc/matching/PatternNodes.scala index f16178dbab..382760eb38 100644 --- a/sources/scala/tools/nsc/matching/PatternNodes.scala +++ b/sources/scala/tools/nsc/matching/PatternNodes.scala @@ -35,7 +35,7 @@ trait PatternNodes: TransMatcher { } def dup(): PatternNode = { - var res: PatternNode = _; + var res: PatternNode = null; this match { case h:Header => res = new Header(h.selector, h.next); diff --git a/sources/scala/tools/nsc/matching/RightTracers.scala b/sources/scala/tools/nsc/matching/RightTracers.scala index 8dc3d638a9..a916d07929 100644 --- a/sources/scala/tools/nsc/matching/RightTracers.scala +++ b/sources/scala/tools/nsc/matching/RightTracers.scala @@ -71,7 +71,7 @@ abstract class RightTracerInScala extends Autom2Scala { case Star(t) => traverse(t); case Bind(name, subtree) => - var sym: Symbol = _; + var sym: Symbol = null; if( isVariableName( name ) && isVariableSymbol( {sym = tree.symbol; tree.symbol} )) handleVariableSymbol( sym ); @@ -136,7 +136,7 @@ abstract class RightTracerInScala extends Autom2Scala { val helpVar = owner.newVariable( pos, fresh.newName( realVar.name .toString()+"RTIS" )); - var rhs: Tree = _; + var rhs: Tree = null; //System.out.println("RTiS making helpvar : "+realVar+" -> "+helpVar); diff --git a/sources/scala/tools/nsc/matching/TransMatcher.scala b/sources/scala/tools/nsc/matching/TransMatcher.scala index c35d3a0baa..5d7bb9de86 100644 --- a/sources/scala/tools/nsc/matching/TransMatcher.scala +++ b/sources/scala/tools/nsc/matching/TransMatcher.scala @@ -25,6 +25,7 @@ with RightTracers { import global._; import definitions._; import posAssigner.atPos; + import typer.typed; val phaseName = "transmatcher"; @@ -98,7 +99,7 @@ with RightTracers { error("shouldn't happen?!"); case Bind(name, subtree) => - var sym: Symbol = _; + var sym: Symbol = null; if (isVariableName(name) && isVariableSymbol( {sym = tree.symbol; tree.symbol} )) @@ -139,7 +140,7 @@ with RightTracers { def isRegular(pats:List[CaseDef]): Pair[List[CaseDef],Boolean] = { var existsReg = false; var isReg = false; - var nilVars:List[Symbol] = _; + var nilVars:List[Symbol] = null; def isRegular1(pat: Tree): Tree = pat match { case Alternative(trees) => @@ -247,7 +248,7 @@ with RightTracers { // global.log("internal pattern matching structure"); // pm.print(); //} - pm.toTree(); + pm.toTree() } } override def transform(tree: Tree): Tree = tree match { @@ -261,14 +262,19 @@ with RightTracers { Console.println("BODY "+t.body.toString()); } */ - // @todo: remove from partial matcher + // @todo: remove from partial matcher TransMatcher.this.currentOwner = currentOwner; TransMatcher.this.resultType = tree.tpe; - //Console.println("TransMatcher selector.tpe ="+selector.tpe+")"); - //Console.println("TransMatcher resultType ="+resultType+")"); - val t = handle(nselector, ncases.asInstanceOf[List[CaseDef]]); - //Console.println(t.toString()); - t + //Console.println("TransMatcher selector.tpe ="+selector.tpe+")"); + //Console.println("TransMatcher resultType ="+resultType+")"); + val t = + typed { + atPos(tree.pos) { + handle(nselector, ncases.asInstanceOf[List[CaseDef]]) + } + } + //Console.println(t.toString()); + t case _ => super.transform(tree); } diff --git a/sources/scala/tools/nsc/matching/WordAutoms.scala b/sources/scala/tools/nsc/matching/WordAutoms.scala index 5912ad3900..1d02f0126e 100644 --- a/sources/scala/tools/nsc/matching/WordAutoms.scala +++ b/sources/scala/tools/nsc/matching/WordAutoms.scala @@ -34,7 +34,7 @@ abstract class WordAutomInScala extends Autom2Scala { def getMatcherSwitch(selector: Tree, failTree: Tree, body: scala.List[Tree] /*, resultType: Type*/ ): Tree = { - var result: Tree = _; + var result: Tree = null; var ncases: scala.List[CaseDef] = Nil; val it = body.reverse.elements; //val tags = new Array[int](body.length); diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala index a620ec8190..275948bdc0 100755 --- a/sources/scala/tools/nsc/symtab/Definitions.scala +++ b/sources/scala/tools/nsc/symtab/Definitions.scala @@ -158,6 +158,7 @@ abstract class Definitions: SymbolTable { var BoxedUnitClass: Symbol = _; var BoxedUnitModule: Symbol = _; def BoxedUnit_UNIT = getMember(BoxedUnitModule, "UNIT"); + var ObjectRefClass: Symbol = _; def getModule(fullname: Name): Symbol = getModuleOrClass(fullname, true); @@ -231,20 +232,24 @@ abstract class Definitions: SymbolTable { owner.newTypeParameter(Position.NOPOS, "T" + index) .setInfo(TypeBounds(AllClass.typeConstructor, AnyClass.typeConstructor)); - val boxedSym = new HashMap[Symbol, Symbol]; - val boxedArraySym = new HashMap[Symbol, Symbol]; + val boxedClass = new HashMap[Symbol, Symbol]; + val boxedArrayClass = new HashMap[Symbol, Symbol]; + val refClass = new HashMap[Symbol, Symbol]; private val abbrvTag = new HashMap[Symbol, char]; private def getValueClass(name: String, tag: char): Symbol = { val result = getClass("scala." + name); - boxedSym(result) = getClass("scala.runtime.Boxed" + name); - if (name != "Unit") boxedArraySym(result) = getClass("scala.runtime.Boxed" + name + "Array"); + boxedClass(result) = getClass("scala.runtime.Boxed" + name); + if (name != "Unit") { + boxedArrayClass(result) = getClass("scala.runtime.Boxed" + name + "Array"); + refClass(result) = getClass("scala.runtime." + name + "Ref"); + } abbrvTag(result) = tag; result } /** Is symbol a value class? */ - def isValueClass(sym: Symbol): boolean = boxedSym contains sym; + def isValueClass(sym: Symbol): boolean = boxedClass contains sym; /** Is symbol a value or array class? */ def isUnboxedClass(sym: Symbol): boolean = isValueClass(sym) || sym == ArrayClass; @@ -368,6 +373,7 @@ abstract class Definitions: SymbolTable { BoxedNumberClass = getClass("scala.runtime.BoxedNumber"); BoxedUnitClass = getClass("scala.runtime.BoxedUnit"); BoxedUnitModule = getModule("scala.runtime.BoxedUnit"); + ObjectRefClass = getClass("scala.runtime.ObjectRef"); } } } diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala index a7a4d0bf1e..c7d187af97 100644 --- a/sources/scala/tools/nsc/symtab/Flags.scala +++ b/sources/scala/tools/nsc/symtab/Flags.scala @@ -42,7 +42,7 @@ object Flags { // (typically, access methods for valdefs) final val STATIC = 0x00800000; // static field, method or class - final val ACCESSED = 0x01000000; // symbol was accessed at least once + final val CASEACCESSOR = 0x01000000; // symbol is a case parameter (or its accessor) final val MODULE = 0x02000000; // symbol is module or class implementing a module final val BRIDGE = 0x04000000; // function is a bridge method. Set by Erasure final val ACCESSOR = 0x08000000; // a value or variable accessor @@ -50,7 +50,7 @@ object Flags { final val ACCESS_METHOD = 0x10000000; // function is an access function for a method in some // outer class; set by ExplicitOuter final val PARAMACCESSOR = 0x20000000; // for value definitions: is an access method for a final val parameter - // for parameters: is a val parameter + // for parameters: is a val parameter final val LABEL = 0x40000000; // symbol is a label. Set by TailCall final val CAPTURED = 0x80000000l; // variable is accessed from nested function. Set by LambdaLift @@ -59,8 +59,8 @@ object Flags { final val OVERLOADED = 0x200000000l; // symbol is overloaded final val TRANS_FLAG = 0x400000000l; // transient flag guaranteed to be reset after each phase. - final val LIFTED = TRANS_FLAG; // transient flag for lambdalift final val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer + final val FLATTENED = 0x800000000l; // class has been lifted out to package level final val INITIALIZED = 0x1000000000l; // symbol's definition is complete final val LOCKED = 0x2000000000l; // temporary flag to catch cyclic dependencies @@ -82,16 +82,16 @@ object Flags { final val ExplicitFlags = // these modifiers can be set explicitly in source programs. PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE; final val PrintableFlags = // these modifiers appear in TreePrinter output. - ExplicitFlags | LOCAL | SYNTHETIC | STABLE | ACCESSOR | + ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | ACCESSOR | ACCESS_METHOD | PARAMACCESSOR | LABEL | BRIDGE | STATIC; final val GenFlags = // these modifiers can be in generated trees SourceFlags | PrintableFlags; - final val FieldFlags = MUTABLE | ACCESSED | PARAMACCESSOR | STATIC | FINAL; + final val FieldFlags = MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL; final val AccessFlags = PRIVATE | PROTECTED; final val VARIANCES = COVARIANT | CONTRAVARIANT; final val ConstrFlags = JAVA; - final val PickledFlags = 0xFFFFFFFF & ~LOCKED & ~INITIALIZED; + final val PickledFlags = 0xFFFFFFFF; /** Module flags inherited by their module-class */ final val ModuleToClassFlags = AccessFlags | PACKAGE; @@ -142,7 +142,7 @@ object Flags { case STABLE => "<stable>" case STATIC => "<static>" - case ACCESSED => "<accessed>" + case CASEACCESSOR => "<caseaccessor>" case ACCESSOR => "<accessor>" case ACCESS_METHOD => "<access>" diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala index 0cdc909380..681efa46c3 100755 --- a/sources/scala/tools/nsc/symtab/StdNames.scala +++ b/sources/scala/tools/nsc/symtab/StdNames.scala @@ -31,7 +31,7 @@ abstract class StdNames: SymbolTable { val NEWkw = newTermName("new"); val NULLkw = newTermName("null"); val OBJECTkw = newTermName("object"); - val OUTER = "$outer"; + val OUTER = newTermName("$outer"); val OVERRIDEkw = newTermName("override"); val PACKAGEkw = newTermName("package"); val PRIVATEkw = newTermName("private"); @@ -76,8 +76,10 @@ abstract class StdNames: SymbolTable { def TUPLE_FIELD(index: int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index); + def LOCAL_NAME(name: Name) = newTermName(name.toString() + " "); + def isLocalName(name: Name) = name(name.length - 1) == ' '; + def GETTER_NAME(name: Name) = newTermName(name.toString().substring(0, name.length - 1)); def SETTER_NAME(name: Name) = encode(name.toString() + "_="); - def LOCAL_NAME(name: Name) = encode(name.toString() + " "); val ERROR = newTermName("<error>"); val ERRORtype = newTypeName("<error>"); diff --git a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala index 46e9ff6b42..1900dd82c8 100755 --- a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -80,7 +80,7 @@ abstract class SymbolLoaders { /** Is the given name a valid input file base name? */ def isValid(name: String): boolean = - name.length() > 0 && !name.endsWith("$class") && name.indexOf("$$anon") == -1; + name.length() > 0 && !name.endsWith("$class") && name.indexOf("$anon") == -1; def enterPackage(str: String, completer: SymbolLoader): unit = { val pkg = root.newPackage(Position.NOPOS, newTermName(str)); diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala index 44340e8b1b..ea62d09721 100755 --- a/sources/scala/tools/nsc/symtab/Symbols.scala +++ b/sources/scala/tools/nsc/symtab/Symbols.scala @@ -18,11 +18,11 @@ abstract class Symbols: SymbolTable { /** The class for all symbols */ abstract class Symbol(initOwner: Symbol, initPos: int, initName: Name) { - var owner = initOwner; - var name = initName; + var rawowner = initOwner; + var rawname = initName; + private var rawflags: long = 0; var pos = initPos; val id = { ids = ids + 1; ids } - private var rawflags: long = 0; def setPos(pos: int): this.type = { this.pos = pos; this } @@ -35,7 +35,7 @@ abstract class Symbols: SymbolTable { final def newValueParameter(pos: int, name: Name) = newValue(pos, name).setFlag(PARAM); final def newLocalDummy(pos: int) = - newValue(pos, nme.LOCAL(owner)).setInfo(NoType); + newValue(pos, nme.LOCAL(this)).setInfo(NoType); final def newMethod(pos: int, name: Name) = newValue(pos, name).setFlag(METHOD); final def newLabel(pos: int, name: Name) = @@ -102,8 +102,9 @@ abstract class Symbols: SymbolTable { final def isMethod = isTerm && hasFlag(METHOD); final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD; final def isLabel = isTerm && hasFlag(LABEL); - final def isConstructor = isTerm && (name == nme.CONSTRUCTOR); + final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR); final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR); + final def isConstructor = isTerm && (name == nme.CONSTRUCTOR) || (name == nme.MIXIN_CONSTRUCTOR); final def isModule = isTerm && hasFlag(MODULE); final def isPackage = isModule && hasFlag(PACKAGE); final def isThisSym = isTerm && name == nme.this_; @@ -125,10 +126,14 @@ abstract class Symbols: SymbolTable { isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD) || hasFlag(STABLE)); /** Does this symbol denote the primary constructor - * of its enclosing class? */ + * of its enclosing class or trait? */ final def isPrimaryConstructor = isConstructor && owner.primaryConstructor == this; + /** Is this symbol an implementation class for a trait ? */ + final def isImplClass: boolean = + name.endsWith(nme.IMPL_CLASS_SUFFIX); + /** Is this symbol static (i.e. with no outer instance)? */ final def isStatic: boolean = hasFlag(STATIC) || isRoot || owner.isStaticOwner; @@ -157,6 +162,10 @@ abstract class Symbols: SymbolTable { case _ => false }); + /** Is this class nested in another class or module (not a package)? */ + final def isNestedClass: boolean = + isClass && !isRoot && !owner.isPackageClass; + /** Is this class locally defined? * A class is local, if * - it is anonymous, or @@ -184,7 +193,13 @@ abstract class Symbols: SymbolTable { else if (hasFlag(CONTRAVARIANT)) -1 else 0; -// Flags ---------------------------------------------------------------------------- +// Flags, owner, and name attributes -------------------------------------------------------------- + + def owner: Symbol = rawowner; + final def owner_=(owner: Symbol): unit = { rawowner = owner } + + def name: Name = rawname; + final def name_=(name: Name): unit = { rawname = name } final def flags = { val fs = rawflags & phase.flagMask; @@ -254,14 +269,11 @@ abstract class Symbols: SymbolTable { this } - /** Set new info valid from start of next phase. */ + /** Set new info valid from start of this phase. */ final def updateInfo(info: Type): Symbol = { - val current = phase; - phase = phase.next; assert(infos.start.id <= phase.id); if (infos.start == phase) infos = infos.prev; infos = new TypeHistory(phase, info, infos); - phase = current; this } @@ -409,10 +421,10 @@ abstract class Symbols: SymbolTable { def enclMethod: Symbol = if (isSourceMethod) this else owner.enclMethod; /** The primary constructor of a class */ - def primaryConstructor: Symbol = info.decl(nme.CONSTRUCTOR).alternatives.head; - - /** The (primary) trait constructor of (the implementation class of) a mixin */ - def mixinConstructor: Symbol = info.decl(nme.MIXIN_CONSTRUCTOR); + def primaryConstructor: Symbol = { + val c = info.decl(if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR); + if (c hasFlag OVERLOADED) c.alternatives.head else c + } /** The self symbol of a class with explicit self type, or else the symbol itself. */ @@ -427,11 +439,14 @@ abstract class Symbols: SymbolTable { /** If symbol is a class, the type this.type in this class, otherwise NoPrefix */ def thisType: Type = NoPrefix; - /** Return every accessor of a primary constructor parameter in this case class */ - final def caseFieldAccessors: List[Symbol] = { - assert(isClass && hasFlag(CASE)); - info.decls.toList filter (sym => !(sym hasFlag PRIVATE) && sym.hasFlag(PARAMACCESSOR)) - } + /** Return every accessor of a primary constructor parameter in this case class + * todo: limit to accessors for first constructor parameter section. + */ + final def caseFieldAccessors: List[Symbol] = + info.decls.toList filter (sym => !(sym hasFlag PRIVATE) && sym.hasFlag(CASEACCESSOR)); + + final def constrParamAccessors: List[Symbol] = + info.decls.toList filter (sym => !sym.isMethod && sym.hasFlag(PARAMACCESSOR)); /** The symbol accessed by this accessor function. */ @@ -439,9 +454,13 @@ abstract class Symbols: SymbolTable { assert(hasFlag(ACCESSOR)); val name1 = if (name.endsWith(nme._EQ)) name.subName(0, name.length - nme._EQ.length) else name; - owner.info.decl(name1.toString() + "$") + owner.info.decl(nme.LOCAL_NAME(name1)) } + /** The getter for this symbol */ + final def getter: Symbol = + if (nme.isLocalName(name)) owner.info.decl(nme.GETTER_NAME(name)) else NoSymbol; + /** The class with the same name in the same package as this module or * case class factory */ @@ -511,10 +530,7 @@ abstract class Symbols: SymbolTable { /** The simple name of this Symbol (this is always a term name) */ final def simpleName: Name = name; -/* - if (isConstructor && !settings.debug.value) - newTermName("<init owner.name.toTermName else name; -*/ + /** String representation of symbol's definition key word */ final def keyString: String = if (isTrait) @@ -541,7 +557,7 @@ abstract class Symbols: SymbolTable { else if (isVariable) "variable" else if (isPackage) "package" else if (isModule) "object" - else if (isConstructor) "constructor" + else if (isClassConstructor) "constructor" else if (isSourceMethod) "method" else if (isTerm) "value" else ""; @@ -704,6 +720,21 @@ abstract class Symbols: SymbolTable { thissym = this; } + override def owner: Symbol = + if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) rawowner.owner + else rawowner; + + private var flatname = nme.EMPTY; + + override def name: Name = + if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) { + if (flatname == nme.EMPTY) { + assert(rawowner.isClass); + flatname = newTypeName(rawowner.name.toString() + "$" + rawname); + } + flatname + } else rawname; + private var thisTypeCache: Type = _; private var thisTypePhase: Phase = null; @@ -714,10 +745,9 @@ abstract class Symbols: SymbolTable { thisTypePhase = phase; if (!isValid(p)) { thisTypeCache = - if (isModuleClass && !isRoot && !phase.erasedTypes) { - assert(sourceModule != NoSymbol, "" + this + " " + phase); - singleType(owner.thisType, sourceModule); - } else ThisType(this); + if (isModuleClass && !isRoot && !phase.erasedTypes) + singleType(owner.thisType, sourceModule); + else ThisType(this); } } thisTypeCache diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index b488685727..0c66540d66 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -800,7 +800,7 @@ abstract class Types: SymbolTable { /** The canonical creator for this-types */ def ThisType(sym: Symbol): Type = - if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType {}); + if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType); /** The canonical creator for single-types */ def singleType(pre: Type, sym: Symbol): Type = { @@ -809,7 +809,7 @@ abstract class Types: SymbolTable { else if (checkMalformedSwitch && !pre.isStable && !pre.isError) throw new MalformedType(pre, sym.name.toString()) else - unique(new SingleType(pre, rebind(pre, sym)) with UniqueType {}) + unique(new SingleType(pre, rebind(pre, sym)) with UniqueType) } /** The canonical creator for super-types */ @@ -1050,11 +1050,13 @@ abstract class Types: SymbolTable { val decls1 = mapOver(decls); if ((parents1 eq parents) && (decls1 eq decls)) tp else cloneDecls(refinedType(parents1, tp.symbol.owner), tp, decls1) +/* case ClassInfoType(parents, decls, clazz) => val parents1 = List.mapConserve(parents)(this); val decls1 = mapOver(decls); if ((parents1 eq parents) && (decls1 eq decls)) tp else cloneDecls(ClassInfoType(parents1, new Scope(), clazz), tp, decls1) +*/ case MethodType(paramtypes, result) => val paramtypes1 = List.mapConserve(paramtypes)(this); val result1 = this(result); @@ -1253,7 +1255,10 @@ abstract class Types: SymbolTable { // Helper Methods ------------------------------------------------------------- final def isValid(p: Phase): boolean = - p != null && infoTransformers.nextFrom(p).phase.id >= phase.id; + p != null && + (if (phase.id > p.id) infoTransformers.nextFrom(p).phase.id >= phase.id + else infoTransformers.nextFrom(phase).phase.id >= p.id); + /** Do tp1 and tp2 denote equivalent types? */ def isSameType(tp1: Type, tp2: Type): boolean = (tp1 eq tp2) || { diff --git a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala index 9aec7dc802..42aa2e933c 100755 --- a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala +++ b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala @@ -17,7 +17,7 @@ object PickleFormat { * | 5 ALIASsym len_Nat SymbolInfo * | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref] * | 7 MODULEsym len_Nat SymbolInfo - * | 8 VALsym len_Nat SymbolInfo + * | 8 VALsym len_Nat SymbolInfo [alias_Ref] * | 9 EXTref len_Nat name_Ref [owner_Ref] * | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref] * | 11 NOtpe len_Nat diff --git a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala index 8123fe6973..1c221462c2 100755 --- a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -83,7 +83,12 @@ abstract class Pickler extends SubComponent { putEntry(sym.name); putSymbol(sym.owner); putType(sym.info); - if (sym.thisSym != sym) putType(sym.typeOfThis) + if (sym.thisSym != sym) + putType(sym.typeOfThis); + aliases.get(sym) match { + case Some(alias) => putSymbol(alias); + case None => + } } else if (sym != NoSymbol) { putEntry(if (sym.isModuleClass) sym.name.toTermName else sym.name); if (!sym.owner.isRoot) putSymbol(sym.owner); @@ -170,7 +175,15 @@ abstract class Pickler extends SubComponent { writeSymInfo(sym); if (sym.isAbstractType) TYPEsym else ALIASsym case sym: TermSymbol => - writeSymInfo(sym); if (sym.isModule) MODULEsym else VALsym + writeSymInfo(sym); + if (sym.isModule) MODULEsym + else { + aliases.get(sym) match { + case Some(alias) => writeRef(alias); + case None => + } + VALsym + } case NoType => NOtpe case NoPrefix => diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala index 8fd7f63cb9..3429ba88d7 100755 --- a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -19,7 +19,8 @@ abstract class UnPickler { new UnPickle(bytes, offset, classRoot, moduleRoot); } catch { case ex: Throwable => - if (settings.debug.value) ex.printStackTrace(); + ex.printStackTrace();//debug + System.out.println("EX");//debug throw new RuntimeException("error reading Scala signature of " + classRoot.nameString + ": " + ex.getMessage()); } @@ -119,10 +120,11 @@ abstract class UnPickler { errorBadSignature("bad symbol tag: " + tag); } sym.setFlag(flags); - sym.setInfo(new LazyTypeRef(inforef)); + val aliasIndex = if ((sym hasFlag PARAMACCESSOR) && readIndex != end) readNat() else 0; + sym.setInfo(new LazyTypeRef(inforef, aliasIndex)); if (sym.owner.isClass && sym != classRoot && sym != moduleRoot && - !sym.isModuleClass && !sym.isRefinementClass && !sym.hasFlag(PARAM | LOCAL)) - symScope(sym.owner) enter sym + !sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter) + symScope(sym.owner) enter sym; } sym } @@ -195,8 +197,12 @@ abstract class UnPickler { private def errorBadSignature(msg: String) = throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg); - private class LazyTypeRef(i: int) extends LazyType { - override def complete(sym: Symbol): unit = sym setInfo at(i, readType); + private class LazyTypeRef(i: int, aliasIndex: int) extends LazyType { + def this(i: int) = this(i, 0); + override def complete(sym: Symbol): unit = { + sym setInfo at(i, readType); + if (aliasIndex != 0) aliases(sym) = at(aliasIndex, readSymbol); + } override def load(sym: Symbol): unit = complete(sym) } } diff --git a/sources/scala/tools/nsc/transform/AddInterfaces.scala b/sources/scala/tools/nsc/transform/AddInterfaces.scala index 8161e69782..79bdada436 100755 --- a/sources/scala/tools/nsc/transform/AddInterfaces.scala +++ b/sources/scala/tools/nsc/transform/AddInterfaces.scala @@ -27,11 +27,8 @@ abstract class AddInterfaces extends InfoTransform { private def implClassName(sym: Symbol): Name = newTermName(sym.name.toString() + nme.IMPL_CLASS_SUFFIX); - def isImplClass(sym: Symbol): boolean = - sym.name.endsWith(nme.IMPL_CLASS_SUFFIX); - private def needsImplClass(sym: Symbol): boolean = - sym.isTrait && (!(sym hasFlag INTERFACE) || (sym hasFlag lateINTERFACE)) && !isImplClass(sym); + sym.isTrait && (!(sym hasFlag INTERFACE) || (sym hasFlag lateINTERFACE)) && !sym.isImplClass; private def needsImplMethod(sym: Symbol): boolean = sym.isMethod && isInterfaceMember(sym) && @@ -39,7 +36,7 @@ abstract class AddInterfaces extends InfoTransform { private def isInterfaceMember(sym: Symbol): boolean = sym.isType || - sym.isMethod && !(sym hasFlag (PRIVATE | BRIDGE | LABEL)) && !sym.isMixinConstructor; + sym.isMethod && !(sym hasFlag (PRIVATE | BRIDGE | LABEL)) && !sym.isConstructor; private def implClass(iface: Symbol): Symbol = implClassMap.get(iface) match { case Some(c) => c @@ -49,7 +46,8 @@ abstract class AddInterfaces extends InfoTransform { setFlag (iface.flags & ~(INTERFACE | lateINTERFACE)) setInfo new LazyImplClassType(iface); impl.name = implClassName(iface); - //impl.typeOfThis = iface.tpe; + //includeInTypeOfThis(iface, impl); + //includeInTypeOfThis(impl, impl); implClassMap(iface) = impl; if (settings.debug.value) log("generating impl class " + impl); impl @@ -63,7 +61,6 @@ abstract class AddInterfaces extends InfoTransform { for (val sym <- ifaceDecls.elements) { if (isInterfaceMember(sym)) { if (needsImplMethod(sym)) { - assert(!sym.isMixinConstructor);//debug val impl = sym.cloneSymbol(implClass).setInfo(sym.info); if (!impl.isExternal) implMethodMap(sym) = impl; decls enter impl; @@ -114,7 +111,7 @@ abstract class AddInterfaces extends InfoTransform { else { assert(!parents.head.symbol.isTrait); if (clazz hasFlag INTERFACE) erasedTypeRef(ObjectClass) :: parents.tail - else if (isImplClass(clazz) || clazz == ArrayClass) parents + else if (clazz.isImplClass || clazz == ArrayClass) parents else traitToImplClass(parents) } val decls1 = addImplClasses( @@ -127,11 +124,16 @@ abstract class AddInterfaces extends InfoTransform { // Tree transformation -------------------------------------------------------------- - private def changeOwner(oldowner: Symbol, newowner: Symbol) = new Traverser { - override def traverse(tree: Tree): unit = - if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.owner == oldowner) - tree.symbol.owner = newowner - else super.traverse(tree) + private class ChangeOwnerAndReturnTraverser(oldowner: Symbol, newowner: Symbol) + extends ChangeOwnerTraverser(oldowner, newowner) { + override def traverse(tree: Tree): unit = { + tree match { + case Return(expr) => + if (tree.symbol == oldowner) tree.symbol = newowner; + case _ => + } + super.traverse(tree) + } } private def ifaceMemberDef(tree: Tree): Tree = @@ -146,7 +148,7 @@ abstract class AddInterfaces extends InfoTransform { implMethodMap.get(ifaceMethod) match { case Some(implMethod) => tree.symbol = implMethod; - changeOwner(ifaceMethod, implMethod).traverse(tree); + new ChangeOwnerAndReturnTraverser(ifaceMethod, implMethod).traverse(tree); tree case None => throw new Error("implMethod missing for " + ifaceMethod + " " + ifaceMethod.isExternal) @@ -159,9 +161,10 @@ abstract class AddInterfaces extends InfoTransform { private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos){ val templ1 = Template(templ.parents, templ.body map implMemberDef) + setPos templ.pos setSymbol clazz.newLocalDummy(templ.pos); - changeOwner(templ.symbol.owner, clazz).traverse(templ1); - changeOwner(templ.symbol, templ1.symbol).traverse(templ1); + new ChangeOwnerTraverser(templ.symbol.owner, clazz).traverse(templ1); + new ChangeOwnerTraverser(templ.symbol, templ1.symbol).traverse(templ1); templ1 } @@ -182,7 +185,8 @@ abstract class AddInterfaces extends InfoTransform { protected val traitTransformer = new Transformer { override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = - super.transformStats(stats ::: implClassDefs(stats), exprOwner) filter (EmptyTree !=); + super.transformStats(stats, exprOwner) ::: + super.transformStats(implClassDefs(stats), exprOwner); override def transform(tree: Tree): Tree = { val tree1 = tree match { case ClassDef(mods, name, tparams, tpt, impl) => @@ -192,9 +196,16 @@ abstract class AddInterfaces extends InfoTransform { } else tree case Template(parents, body) => - copy.Template(tree, tree.symbol.owner.info.parents map TypeTree, body) + val parents1 = tree.symbol.owner.info.parents map (t => TypeTree(t) setPos tree.pos); + copy.Template(tree, parents1, body) case This(_) => - if (needsImplClass(tree.symbol)) This(implClass(tree.symbol)) else tree + if (needsImplClass(tree.symbol)) { + val impl = implClass(tree.symbol); + var owner = currentOwner; + while (owner != tree.symbol && owner != impl) owner = owner.owner; + if (owner == impl) This(impl) setPos tree.pos + else tree + } else tree case Super(qual, mix) => val mix1 = if (mix == nme.EMPTY.toTypeName) mix @@ -206,7 +217,7 @@ abstract class AddInterfaces extends InfoTransform { if (needsImplClass(ps.head.symbol)) implClass(ps.head.symbol).name else mix } - if (needsImplClass(tree.symbol)) Super(implClass(tree.symbol), mix1) + if (needsImplClass(tree.symbol)) Super(implClass(tree.symbol), mix1) setPos tree.pos else copy.Super(tree, qual, mix1) case _ => tree diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala index d9462c2118..ee8f6359bb 100755 --- a/sources/scala/tools/nsc/transform/Erasure.scala +++ b/sources/scala/tools/nsc/transform/Erasure.scala @@ -106,7 +106,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { else if (sym.isAbstractType) TypeBounds(WildcardType, WildcardType) else if (sym.isTerm && sym.owner == ArrayClass) { - if (sym.isConstructor) + if (sym.isClassConstructor) tp match { case MethodType(formals, TypeRef(pre, sym, args)) => MethodType(formals map erasure, typeRef(erasure(pre), sym, args)) @@ -139,11 +139,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { else Block(List(tree), gen.mkRef(BoxedUnit_UNIT)) } else if (sym == ArrayClass) { val elemClass = tree.tpe.typeArgs.head.symbol; - val boxedClass = if (isValueClass(elemClass)) boxedArraySym(elemClass) + val boxedClass = if (isValueClass(elemClass)) boxedArrayClass(elemClass) else BoxedObjectArrayClass; Apply(Select(New(TypeTree(boxedClass.tpe)), nme.CONSTRUCTOR), List(tree)) } else { - val boxedModule = boxedSym(tree.tpe.symbol).linkedModule; + val boxedModule = boxedClass(tree.tpe.symbol).linkedModule; Apply(Select(gen.mkRef(boxedModule), nme.box), List(tree)) } } @@ -156,7 +156,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { if (pt.symbol == UnitClass) { Literal(()) } else if (pt.symbol == BooleanClass) { - val tree1 = adaptToType(tree, boxedSym(BooleanClass).tpe); + val tree1 = adaptToType(tree, boxedClass(BooleanClass).tpe); Apply(Select(tree1, "booleanValue"), List()) } else if (pt.symbol == ArrayClass) { val tree1 = adaptToType(tree, BoxedArrayClass.tpe); @@ -179,17 +179,6 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { } } - /** Cast `tree' to type `pt' */ - private def cast(tree: Tree, pt: Type): Tree = { - if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt); - assert(!tree.tpe.isInstanceOf[MethodType], tree); - typed { - atPos(tree.pos) { - Apply(TypeApply(Select(tree, Object_asInstanceOf), List(TypeTree(pt))), List()) - } - } - } - /** Is symbol a member of unboxed arrays (which will be expanded directly later)? */ private def isUnboxedArrayMember(sym: Symbol) = sym.name == nme.apply || sym.name == nme.length || sym.name == nme.update || @@ -210,13 +199,13 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { adaptToType(box(tree), pt) else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.paramTypes.isEmpty) { assert(tree.symbol.isStable); - adaptToType(Apply(tree, List()) setType tree.tpe.resultType, pt) + adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt) } else if (pt <:< tree.tpe) - cast(tree, pt) + gen.cast(tree, pt) else if (isUnboxedClass(pt.symbol) && !isUnboxedClass(tree.tpe.symbol)) adaptToType(unbox(tree, pt), pt) else - cast(tree, pt) + gen.cast(tree, pt) } // todo: remove after removing ==, != from value classes @@ -242,52 +231,58 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { * - All forms of `x.m' where `x' is a boxed type and `m' is a member of an unboxed class * become `x.m' where `m' is the corresponding member of the boxed class. */ - private def adaptMember(tree: Tree): Tree = tree match { - case Apply(sel @ Select(qual, name), args) => - if (corresponds(sel.symbol, Any_==)) - Apply(Select(qual, Object_equals), args) - else if (corresponds(sel.symbol, Any_!=)) - Apply(Select(Apply(Select(qual, Object_equals), args), Boolean_not), List()) - else qual match { - case New(tpt) => - assert(tpt.isInstanceOf[TypeTree]); - if (tpt.tpe.symbol == BoxedArrayClass) { - assert(name == nme.CONSTRUCTOR); - Typed(Apply(Select(New(TypeTree(BoxedAnyArrayClass.tpe)), name), args), tpt) - } else tree - case _ => - tree - } - case Select(qual, name) if (name != nme.CONSTRUCTOR) => - if (tree.symbol == Any_asInstanceOf || tree.symbol == Any_asInstanceOfErased) - adaptMember(Select(qual, Object_asInstanceOf)) - else if (tree.symbol == Any_isInstanceOf || tree.symbol == Any_isInstanceOfErased) - adaptMember(Select(qual, Object_isInstanceOf)) - else if (tree.symbol != NoSymbol && tree.symbol.owner == AnyClass) - adaptMember(Select(qual, getMember(ObjectClass, name))) - else { - var qual1 = typedQualifier(qual); - if ((isValueClass(qual1.tpe.symbol) && isBoxedValueMember(tree.symbol)) || - (qual1.tpe.symbol == ArrayClass && !isUnboxedArrayMember(tree.symbol))) { - qual1 = box(qual1); - } else if (!isValueClass(qual1.tpe.symbol) && - tree.symbol != NoSymbol && isValueClass(tree.symbol.owner)) { - qual1 = unbox(qual1, tree.symbol.owner.tpe) + private def adaptMember(tree: Tree): Tree = { + tree match { + case Apply(sel @ Select(qual, name), args) => + if (corresponds(sel.symbol, Any_==)) + atPos(tree.pos) { + Apply(Select(qual, Object_equals), args) + } + else if (corresponds(sel.symbol, Any_!=)) + atPos(tree.pos) { + Apply(Select(Apply(Select(qual, Object_equals), args), Boolean_not), List()) + } + else qual match { + case New(tpt) => + assert(tpt.isInstanceOf[TypeTree]); + if (tpt.tpe.symbol == BoxedArrayClass) { + assert(name == nme.CONSTRUCTOR); + atPos(tree.pos) { + Typed(Apply(Select(New(TypeTree(BoxedAnyArrayClass.tpe)), name), args), tpt) + } + } else tree + case _ => + tree + } + case Select(qual, name) if (name != nme.CONSTRUCTOR) => + if (tree.symbol == Any_asInstanceOf || tree.symbol == Any_asInstanceOfErased) + adaptMember(atPos(tree.pos)(Select(qual, Object_asInstanceOf))) + else if (tree.symbol == Any_isInstanceOf || tree.symbol == Any_isInstanceOfErased) + adaptMember(atPos(tree.pos)(Select(qual, Object_isInstanceOf))) + else if (tree.symbol != NoSymbol && tree.symbol.owner == AnyClass) + adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name)))) + else { + var qual1 = typedQualifier(qual); + if ((isValueClass(qual1.tpe.symbol) && isBoxedValueMember(tree.symbol)) || + (qual1.tpe.symbol == ArrayClass && !isUnboxedArrayMember(tree.symbol))) { + qual1 = box(qual1); + } else if (!isValueClass(qual1.tpe.symbol) && + tree.symbol != NoSymbol && isValueClass(tree.symbol.owner)) { + qual1 = unbox(qual1, tree.symbol.owner.tpe) + } + if (tree.symbol != NoSymbol) + if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.symbol)) + tree.symbol = NoSymbol + else if (qual.tpe.isInstanceOf[MethodType] && qual.tpe.paramTypes.isEmpty) { + assert(qual.symbol.isStable); + qual1 = Apply(qual, List()) setPos qual.pos setType qual.tpe.resultType; + } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.symbol isSubClass tree.symbol.owner))) + qual1 = gen.cast(qual1, tree.symbol.owner.tpe); + copy.Select(tree, qual1, name) } - if (tree.symbol != NoSymbol) - if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.symbol)) - tree.symbol = NoSymbol - else if (qual.tpe.isInstanceOf[MethodType] && qual.tpe.paramTypes.isEmpty) { - assert(qual.symbol.isStable); - qual1 = Apply(qual, List()) setType qual.tpe.resultType; - } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.symbol isSubClass tree.symbol.owner))) - qual1 = cast(qual1, tree.symbol.owner.tpe); - copy.Select(tree, qual1, name) - } - case Template(parents, body) => - copy.Template(tree, tree.symbol.owner.info.parents map TypeTree, body) - case _ => - tree + case _ => + tree + } } /** A replacement for the standard typer's `adapt' method */ @@ -312,8 +307,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { */ private def checkNoDoubleDefs(root: Symbol): unit = { def doubleDefError(sym1: Symbol, sym2: Symbol) = { - val tpe1 = atPhase(typerPhase.next)(root.tpe.memberType(sym1)); - val tpe2 = atPhase(typerPhase.next)(root.tpe.memberType(sym2)); + val tpe1 = atPhase(refchecksPhase.next)(root.tpe.memberType(sym1)); + val tpe2 = atPhase(refchecksPhase.next)(root.tpe.memberType(sym2)); unit.error( if (sym1.owner == root) sym1.pos else root.pos, (if (sym1.owner == sym2.owner) "double definition:\n" @@ -330,7 +325,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { val decls = root.info.decls; var e = decls.elems; while (e != null) { - if (e.sym.isTerm && !e.sym.isConstructor && !e.sym.isMixinConstructor) { + if (e.sym.isTerm && !e.sym.isConstructor) { var e1 = decls.lookupNextEntry(e); while (e1 != null) { if (atPhase(phase.next)(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym); @@ -341,15 +336,12 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { } for (val bc <- root.info.baseClasses.tail; val other <- bc.info.decls.toList) { - if (other.isTerm && - !other.isConstructor && - !other.isMixinConstructor && - !(other hasFlag (PRIVATE | BRIDGE))) { + if (other.isTerm && !other.isConstructor && !(other hasFlag (PRIVATE | BRIDGE))) { for (val member <- root.info.nonPrivateMember(other.name).alternatives) { if (member != other && !(member hasFlag BRIDGE) && atPhase(phase.next)(member.tpe =:= other.tpe) && - !atPhase(typerPhase.next)( + !atPhase(refchecksPhase.next)( root.thisType.memberType(member) matches root.thisType.memberType(other))) { if (settings.debug.value) log("" + member.locationString + " " + member.infosString + other.locationString + " " + other.infosString); doubleDefError(member, other) @@ -374,7 +366,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { val bridgeTarget = new HashMap[Symbol, Symbol]; var bridges: List[Tree] = List(); for (val bc <- site.baseClasses.tail; val other <- bc.info.members) { - if (other.isMethod && !other.isConstructor && !other.isMixinConstructor) { + if (other.isMethod && !other.isConstructor) { for (val member <- site.nonPrivateMember(other.name).alternatives) { if (member != other && !(member hasFlag DEFERRED) && diff --git a/sources/scala/tools/nsc/transform/ExplicitOuter.scala b/sources/scala/tools/nsc/transform/ExplicitOuter.scala index bea9fd63ce..673ba1fdb8 100755 --- a/sources/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/sources/scala/tools/nsc/transform/ExplicitOuter.scala @@ -31,9 +31,9 @@ abstract class ExplicitOuter extends InfoTransform { * 2. Add a mixin constructor $init$ to all traits except interfaces * Leave all other types unchanged. */ - override def transformInfo(sym: Symbol, tp: Type): Type = tp match { + def transformInfo(sym: Symbol, tp: Type): Type = tp match { case MethodType(formals, restpe) => - if ((sym.isConstructor || sym.isMixinConstructor) && !sym.owner.isStatic) + if (sym.isConstructor && !sym.owner.isStatic) MethodType(formals ::: List(sym.owner.owner.enclClass.thisType), restpe) else tp; case ClassInfoType(parents, decls, clazz) => @@ -46,7 +46,7 @@ abstract class ExplicitOuter extends InfoTransform { setFlag (LOCAL | PRIVATE | PARAMACCESSOR) setInfo outerType); decls1 enter (clazz.newMethod(clazz.pos, nme.OUTER) - setFlag (PRIVATE | PARAMACCESSOR | ACCESSOR | STABLE | FINAL) + setFlag (PARAMACCESSOR | ACCESSOR | STABLE | FINAL) setInfo MethodType(List(), outerType)); } if (clazz.isTrait) { @@ -65,6 +65,64 @@ abstract class ExplicitOuter extends InfoTransform { private def makeMixinConstructor(clazz: Symbol): Symbol = clazz.newMethod(clazz.pos, nme.MIXIN_CONSTRUCTOR) setInfo MethodType(List(), UnitClass.tpe); + /** A base class for transformers that maintain `outerParam' values for + * outer parameters of constructors. + * The class provides methods for referencing via outer. + */ + class OuterPathTransformer extends Transformer { + + /** The directly enclosing outer parameter, if we are in a constructor */ + protected var outerParam: Symbol = NoSymbol; + + /** The first outer selection from currently transformed tree + */ + protected def outerValue: Tree = + if (outerParam != NoSymbol) gen.Ident(outerParam) + else outerSelect(gen.This(currentOwner.enclClass)); + + /** The path + * `base'.$outer ... .$outer + * which refers to the outer instance `to' of value `base + */ + protected def outerPath(base: Tree, to: Symbol): Tree = + if (base.tpe.symbol == to) base else outerPath(outerSelect(base), to); + + /** Select and apply outer accessor from `base' + */ + private def outerSelect(base: Tree): Tree = { + assert(base.tpe != null, base); + assert(base.tpe.symbol != null, base); + val clazz = base.tpe.symbol.owner.enclClass; + Apply( + Select(base, base.tpe.member(nme.OUTER)) setType MethodType(List(), clazz.thisType), + List()) setType clazz.thisType + } + + override def transform(tree: Tree): Tree = { + try {//debug + val savedOuterParam = outerParam; + tree match { + case Template(_, _) => + outerParam = NoSymbol; + case DefDef(_, _, _, vparamss, _, _) => + if (tree.symbol.isConstructor && !(tree.symbol.owner.isStatic)) { + val lastParam = vparamss.head.last; + assert(lastParam.name == nme.OUTER, tree); + outerParam = lastParam.symbol + } + case _ => + } + val result = super.transform(tree); + outerParam = savedOuterParam; + result + } catch {//debug + case ex: Throwable => + System.out.println("exception when transforming " + tree); + throw ex + } + } + } + class ExplicitOuterTransformer(unit: CompilationUnit) extends Transformer { /** A map that takes triples consisting of @@ -107,24 +165,6 @@ abstract class ExplicitOuter extends InfoTransform { accessor } - /** The path - * `from'.this.$outer ... .$outer - * which is equivalent to an outer self reference `to'.this from within class `from' - */ - def outerPath(base: Tree, to: Symbol): Tree = - if (base.tpe.symbol == to) base else outerPath(outerSelect(base), to); - - /** Select and apply outer accessor from `base' - */ - def outerSelect(base: Tree): Tree = { - assert(base.tpe != null, base); - assert(base.tpe.symbol != null, base); - val clazz = base.tpe.symbol.owner.enclClass; - Apply( - Select(base, base.tpe.member(nme.OUTER)) setType MethodType(List(), clazz.thisType), - List()) setType clazz.thisType; - } - /** The first step performs the following transformations: * 1. A class which is not an interface and is not static gets an outer link * (@see outerDefs) @@ -147,20 +187,10 @@ abstract class ExplicitOuter extends InfoTransform { * is augmented to this.<init>(args, OUTER) where OUTER is the last parameter * of the secondary constructor. */ - private val firstTransformer = new Transformer { + private val firstTransformer = new OuterPathTransformer { var localTyper: analyzer.Typer = typer; - /** The directly enclosing outer parameter, if we are in a constructor - */ - var outerParam: Symbol = NoSymbol; - - /** The first outer selection from currently transformed tree - */ - def outerValue: Tree = - if (outerParam != NoSymbol) gen.Ident(outerParam) - else outerSelect(gen.This(currentOwner.enclClass)); - /** The two definitions * val outer : C.this.type _; * def outer(): C.this.type = outer ; @@ -172,7 +202,7 @@ abstract class ExplicitOuter extends InfoTransform { List( localTyper.typed { atPos(clazz.pos) { - ValDef(outerVal, EmptyTree) + ValDef(outerVal) } }, localTyper.typed { @@ -186,7 +216,7 @@ abstract class ExplicitOuter extends InfoTransform { * def $init$(): Unit = () */ def mixinConstructorDef(clazz: Symbol): Tree = localTyper.typed { - DefDef(clazz.mixinConstructor, vparamss => Literal(())) + DefDef(clazz.primaryConstructor, vparamss => Literal(())) } /** Add calls to supermixin constructors @@ -198,7 +228,7 @@ abstract class ExplicitOuter extends InfoTransform { atPos(tree.pos) { Apply( localTyper.typedOperator { - Select(Super(clazz, mixin.name), mixin.mixinConstructor) + Select(Super(clazz, mixin.name), mixin.primaryConstructor) }, List()) setType UnitClass.tpe; // don't type this with typed(...), // as constructor arguments might be missing @@ -216,19 +246,16 @@ abstract class ExplicitOuter extends InfoTransform { case Block(_, _) => assert(false, tree); tree case expr => - Block(mixinConstructorCalls, expr) setType expr.tpe + Block(mixinConstructorCalls, expr) setType expr.tpe setPos expr.pos; } } /** The first-step transformation method */ override def transform(tree: Tree): Tree = { - try { - val savedOuterParam = outerParam; val sym = tree.symbol; val tree1 = tree match { case Template(parents, decls) => val savedLocalTyper = localTyper; - outerParam = NoSymbol; localTyper = localTyper.atOwner(tree, currentOwner); var decls1 = decls; if (!(currentOwner hasFlag INTERFACE)) { @@ -240,13 +267,13 @@ abstract class ExplicitOuter extends InfoTransform { localTyper = savedLocalTyper; copy.Template(tree, parents, decls1); case constrDef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) - if (sym.isConstructor || sym.isMixinConstructor) => + if (sym.isConstructor) => val vparamss1 = if (sym.owner.isStatic) vparamss else { // (4) val outerField = sym.owner.info.decl(nme.LOCAL_NAME(nme.OUTER)); - outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField.info; - List(vparamss.head ::: List(ValDef(outerParam, EmptyTree))) + val outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField.info; + List(vparamss.head ::: List(ValDef(outerParam) setType NoType)) } val rhs1 = if ((sym.isPrimaryConstructor || sym.isMixinConstructor) && sym.owner != ArrayClass) @@ -255,34 +282,31 @@ abstract class ExplicitOuter extends InfoTransform { copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1); case This(qual) => if (sym == currentOwner.enclClass || sym.isStatic) tree - else atPos(tree.pos)(outerPath(outerValue, sym)) // (5) + else atPos(tree.pos)(outerPath(outerValue, sym)); // (5) case Select(qual @ Super(_, mix), name) => val qsym = qual.symbol; if (!needSuperAccessors || tree.symbol.isType || qsym == currentOwner.enclClass) tree else atPos(tree.pos) { // (6) val accessor = superAccessor(qsym, tree.symbol, mix); - Select(if (qsym.isStatic) This(qsym) else outerPath(outerValue, qsym), accessor) + Select(if (qsym.isStatic) This(qsym) + else outerPath(outerValue, qsym), accessor) setType accessor.tpe } case Apply(sel @ Select(qual, name), args) if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) && !sel.symbol.owner.isStatic) => val outerVal = - if (qual.isInstanceOf[This]) { assert(outerParam != NoSymbol); outerValue } // (8) - else gen.mkQualifier(qual.tpe.prefix); // (7) + atPos(tree.pos) { + if (qual.isInstanceOf[This]) { assert(outerParam != NoSymbol); outerValue } // (8) + else if (qual.tpe.prefix == NoPrefix) gen.This(currentOwner.enclClass) + else gen.mkQualifier(qual.tpe.prefix); // (7) + } copy.Apply(tree, sel, args ::: List(outerVal)) case _ => tree } - val result = super.transform(tree1); - outerParam = savedOuterParam; - result - } catch {//debug - case ex: Throwable => - System.out.println("exception when transforming " + tree); - throw ex - } + super.transform(tree1) } } diff --git a/sources/scala/tools/nsc/transform/Flatten.scala b/sources/scala/tools/nsc/transform/Flatten.scala new file mode 100755 index 0000000000..7f4122c279 --- /dev/null +++ b/sources/scala/tools/nsc/transform/Flatten.scala @@ -0,0 +1,91 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author + */ +// $Id$ +package scala.tools.nsc.transform; + +import symtab._; +import Flags._; +import util.ListBuffer; +import collection.mutable.HashMap; + +abstract class Flatten extends InfoTransform { + import global._; + import definitions._; + + /** the following two members override abstract members in Transform */ + val phaseName: String = "flatten"; + + private val flattened = new TypeMap { + def apply(tp: Type): Type = tp match { + case TypeRef(pre, sym, args) if (pre.symbol.isClass && !pre.symbol.isPackageClass) => + assert(args.isEmpty); + typeRef(sym.toplevelClass.owner.thisType, sym, args) + case ClassInfoType(parents, decls, clazz) => + val parents1 = List.mapConserve(parents)(this); + if (parents1 eq parents) tp + else ClassInfoType(parents1, decls, clazz) + case _ => + mapOver(tp) + } + } + + def transformInfo(sym: Symbol, tp: Type): Type = flattened(tp); + + protected def newTransformer(unit: CompilationUnit): Transformer = + new Flattener(unit); + + class Flattener(unit: CompilationUnit) extends Transformer { + + /** Buffers for lifted out classes */ + private val liftedDefs = new HashMap[Symbol, ListBuffer[Tree]]; + + override def transform(tree: Tree): Tree = { + tree match { + case PackageDef(_, _) => + liftedDefs(tree.symbol.moduleClass) = new ListBuffer; + case _ => + } + postTransform(super.transform(tree)) + } + + private def postTransform(tree: Tree): Tree = { + val sym = tree.symbol; + val tree1 = tree match { + case ClassDef(_, _, _, _, _) if sym.isNestedClass => + liftedDefs(sym.toplevelClass.owner) += tree; + EmptyTree + case Super(qual, mix) if (mix != nme.EMPTY.toTypeName) => + val ps = tree.symbol.info.parents dropWhile (p => p.symbol.name != mix); + assert(!ps.isEmpty, tree); + val mix1 = if (ps.head.symbol.isNestedClass) atPhase(phase.next)(ps.head.symbol.name) + else mix; + copy.Super(tree, qual, mix1) + case _ => + tree + } + tree1 setType flattened(tree1.tpe); + if (sym != null && sym.isNestedClass && !(sym hasFlag FLATTENED)) { + sym setFlag FLATTENED; + atPhase(phase.next) { + System.out.println("re-enter " + sym + " in " + sym.owner);//debug + val scope = sym.owner.info.decls; + val old = scope lookup sym.name; + if (old != NoSymbol) scope unlink old; + scope enter sym; + } + } + tree1 + } + + /** Transform statements and add lifted definitions to them. */ + override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { + val stats1 = super.transformStats(stats, exprOwner); + if (currentOwner.isPackageClass && liftedDefs(currentOwner).hasNext) + stats1 ::: liftedDefs(currentOwner).toList + else + stats1 + } + } +} diff --git a/sources/scala/tools/nsc/transform/LambdaLift.scala b/sources/scala/tools/nsc/transform/LambdaLift.scala new file mode 100755 index 0000000000..353baf620b --- /dev/null +++ b/sources/scala/tools/nsc/transform/LambdaLift.scala @@ -0,0 +1,317 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author + */ +// $Id$ +package scala.tools.nsc.transform; + +import symtab._; +import Flags._; +import util.{ListBuffer, TreeSet}; +import collection.mutable.HashMap; + +abstract class LambdaLift extends InfoTransform { + import global._; + import definitions._; + import typer.{typed}; // methods to type trees + import posAssigner.atPos; // for filling in tree positions + + /** the following two members override abstract members in Transform */ + val phaseName: String = "lambdalift"; + + private val lifted = new TypeMap { + def apply(tp: Type): Type = tp match { + case TypeRef(pre, sym, args) => + if (pre == NoPrefix && sym.isClass && !sym.isPackageClass) { + assert(args.isEmpty); + typeRef(apply(sym.owner.enclClass.thisType), sym, args) + } else mapOver(tp) + case ClassInfoType(parents, decls, clazz) => + val parents1 = List.mapConserve(parents)(this); + if (parents1 eq parents) tp + else ClassInfoType(parents1, decls, clazz) + case _ => + mapOver(tp) + } + } + + def transformInfo(sym: Symbol, tp: Type): Type = lifted(tp); + + protected def newTransformer(unit: CompilationUnit): Transformer = + new LambdaLifter(unit); + + class LambdaLifter(unit: CompilationUnit) extends explicitOuter.OuterPathTransformer { + + /** A map storing free variables of functions and classes */ + private val free = new HashMap[Symbol,SymSet]; + + /** A map storing the free variable proxies of functions and classes */ + private val proxies = new HashMap[Symbol, List[Symbol]]; + + /** A hashtable storing calls between functions */ + private val called = new HashMap[Symbol, SymSet]; + + /** The set of symbols that need to be renamed. */ + private val renamable = newSymSet; + + /** A flag to indicate whether new free variables have been found */ + private var changedFreeVars: boolean = _; + + /** Buffers for lifted out classes and methods */ + private val liftedDefs = new HashMap[Symbol, ListBuffer[Tree]]; + + private type SymSet = TreeSet[Symbol]; + + private def newSymSet = new TreeSet[Symbol]((x, y) => x.isLess(y)); + + private def symSet(f: HashMap[Symbol, SymSet], sym: Symbol): SymSet = f.get(sym) match { + case Some(ss) => ss + case None => val ss = newSymSet; f(sym) = ss; ss + } + + private def outer(sym: Symbol): Symbol = + if (sym.isConstructor) sym.owner.owner else sym.owner; + + private def enclMethOrClass(sym: Symbol): Symbol = { + def localToConstr(sym: Symbol) = + if (sym.isLocalDummy) sym.owner.primaryConstructor else sym; + var encl = localToConstr(sym); + while (!encl.isMethod && !encl.isClass) + encl = localToConstr(outer(encl)); + encl + } + + /** Mark symbol `sym' as being free in `owner', unless `sym' + * is defined in `owner' or there is a class between `owner's owner + * and the owner of `sym'. + * Return `true' if there is no class between `owner' and + * the owner of sym. + * pre: sym.isLocal, (owner.isMethod || owner.isClass) + */ + private def markFree(sym: Symbol, owner: Symbol): boolean = { + if (settings.debug.value) log("mark " + sym + " of " + sym.owner + " free in " + owner); + if (owner == enclMethOrClass(sym.owner)) true + else if (owner.isPackageClass || !markFree(sym, enclMethOrClass(outer(owner)))) false + else { + val ss = symSet(free, owner); + if (!(ss contains sym)) { + ss addEntry sym; + renamable addEntry sym; + changedFreeVars = true; + if (settings.debug.value) log("" + sym + " is free in " + owner); + if (sym.isVariable && !(sym hasFlag CAPTURED)) { + sym setFlag CAPTURED; + val symClass = sym.tpe.symbol; + atPhase(phase.next) { + sym updateInfo ( + if (isValueClass(symClass)) refClass(symClass).tpe else ObjectRefClass.tpe) + } + } + } + !owner.isClass + } + } + + def freeVars(sym: Symbol): Iterator[Symbol] = free.get(sym) match { + case Some(ss) => ss.elements + case None => Iterator.empty + } + + /** The traverse function */ + private val freeVarTraverser = new Traverser { + override def traverse(tree: Tree): unit = { + try { //debug + val sym = tree.symbol; + tree match { + case ClassDef(_, _, _, _, _) => + liftedDefs(tree.symbol) = new ListBuffer; + if (sym.isLocal) renamable addEntry sym; + case DefDef(_, _, _, _, _, _) => + if (sym.isLocal) renamable addEntry sym; + if (sym.isPrimaryConstructor) symSet(called, sym) addEntry sym.owner; + case Ident(name) => + if (sym == NoSymbol) { + assert(name == nme.WILDCARD) + } else if (sym.isLocal) { + val owner = enclMethOrClass(currentOwner); + if (owner.isMethod && sym.isMethod) symSet(called, owner) addEntry sym; + else if (sym.isTerm) markFree(sym, owner) + } + case _ => + } + super.traverse(tree) + } catch {//debug + case ex: Throwable => + System.out.println("exception when traversing " + tree); + throw ex + } + } + } + + /** Compute free variables map `fvs'. + * Also assign unique names to all + * value/variable/let that are free in some function or class, and to + * all class/function symbols that are owned by some function. + */ + private def computeFreeVars: unit = { + freeVarTraverser.traverse(unit.body); + + do { + changedFreeVars = false; + for (val caller <- called.keys; + val callee <- called(caller).elements; + val fv <- freeVars(callee)) + markFree(fv, caller); + } while (changedFreeVars); + + for (val sym <- renamable.elements) { + sym.name = unit.fresh.newName(sym.name.toString()); + if (settings.debug.value) log("renamed: " + sym.name); + } + + atPhase(phase.next) { + for (val owner <- free.keys) { + if (settings.debug.value) + log("free(" + owner + owner.locationString + ") = " + free(owner).elements.toList); + proxies(owner) = + for (val fv <- free(owner).elements.toList) yield { + val proxy = owner.newValue(owner.pos, fv.name) + setFlag (if (owner.isClass) PARAMACCESSOR | PRIVATE | LOCAL else PARAM) + setFlag SYNTHETIC + setInfo fv.info; + if (owner.isClass) owner.info.decls enter proxy; + proxy + } + } + } + } + + private def proxy(sym: Symbol) = { + def searchIn(owner: Symbol): Symbol = { + if (settings.debug.value) log("searching for " + sym + " in " + owner + " " + enclMethOrClass(owner));//debug + proxies.get(enclMethOrClass(owner)) match { + case Some(ps) => + ps filter (p => p.name == sym.name) match { + case List(p) => p + case List() => searchIn(outer(owner)) + } + case None => searchIn(outer(owner)) + } + } + if (settings.debug.value) log("proxy " + sym + " in " + sym.owner + " from " + currentOwner + " " + enclMethOrClass(sym.owner));//debug + if (enclMethOrClass(sym.owner) == enclMethOrClass(currentOwner)) sym + else searchIn(currentOwner) + } + + private def proxyRef(sym: Symbol) = { + val psym = proxy(sym); + if (psym.isLocal) gen.Ident(psym) + else if (psym.owner == currentOwner.enclClass) gen.mkRef(psym) + else { + psym resetFlag (PRIVATE | LOCAL); + Select(outerPath(outerValue, psym.owner), psym) setType psym.tpe + } + } + + private def addFreeArgs(pos: int, sym: Symbol, args: List[Tree]) = { + def freeArg(fv: Symbol) = atPos(pos)(proxyRef(fv)); + val fvs = freeVars(sym).toList; + if (fvs.isEmpty) args else args ::: (fvs map freeArg) + } + + private def addFreeParams(tree: Tree, sym: Symbol): Tree = proxies.get(sym) match { + case Some(ps) => + val freeParams = ps map (p => ValDef(p) setPos tree.pos setType NoType); + tree match { + case DefDef(mods, name, tparams, List(vparams), tpt, rhs) => + sym.updateInfo( + lifted(MethodType(sym.info.paramTypes ::: (ps map (.tpe)), sym.info.resultType))); + copy.DefDef(tree, mods, name, tparams, List(vparams ::: freeParams), tpt, rhs) + case ClassDef(mods, name, tparams, tpt, impl @ Template(parents, body)) => + copy.ClassDef(tree, mods, name, tparams, tpt, + copy.Template(impl, parents, body ::: freeParams)) + } + case None => + tree + } + + private def liftDef(tree: Tree): Tree = { + val sym = tree.symbol; + if (sym.isMethod) sym setFlag (PRIVATE | LOCAL); + sym.owner = sym.owner.enclClass; + liftedDefs(sym.owner) += tree; + sym.owner.info.decls enter sym; + EmptyTree + } + + private def postTransform(tree: Tree): Tree = { + val sym = tree.symbol; + tree match { + case ClassDef(_, _, _, _, _) => + if (sym.isLocal) liftDef(tree) else tree + case DefDef(_, _, _, _, _, _) => + val tree1 = addFreeParams(tree, sym); + if (sym.isLocal) liftDef(tree1) else tree1 + case ValDef(mods, name, tpt, rhs) => + if (sym hasFlag CAPTURED) { + val tpt1 = TypeTree(sym.tpe) setPos tpt.pos; + val rhs1 = + atPos(rhs.pos) { + typed { + Apply(Select(New(TypeTree(sym.tpe)), nme.CONSTRUCTOR), List(rhs)) + } + } + copy.ValDef(tree, mods, name, tpt1, rhs1) + } else tree + case Return(Block(stats, value)) => + Block(stats, copy.Return(tree, value)) setType tree.tpe setPos tree.pos; + case Return(expr) => + if (sym != currentOwner.enclMethod) { + System.out.println(sym);//debug + System.out.println(currentOwner.enclMethod);//debug + unit.error(tree.pos, "non-local return not yet implemented"); + } + tree + case Apply(fn, args) => + copy.Apply(tree, fn, addFreeArgs(tree.pos, sym, args)); + case Assign(Apply(TypeApply(sel @ Select(qual, _), _), List()), rhs) => + // eliminate casts introduced by selecting a captured variable field + // on the lhs of an assignment. + assert(sel.symbol == Object_asInstanceOf); + copy.Assign(tree, qual, rhs) + case Ident(name) => + val tree1 = + if (sym != NoSymbol && sym.isLocal && sym.isTerm && !sym.isMethod && + enclMethOrClass(sym.owner) != enclMethOrClass(currentOwner)) + atPos(tree.pos)(proxyRef(sym)) + else tree; + if (sym hasFlag CAPTURED) + atPos(tree.pos) { + val tp = tree.tpe; + val elemTree = typed { Select(tree1 setType sym.tpe, nme.elem) } + if (elemTree.tpe.symbol != tp.symbol) gen.cast(elemTree, tp) else elemTree + } + else tree1 + case _ => + tree + } + } + + override def transform(tree: Tree): Tree = + postTransform(super.transform(tree) setType lifted(tree.tpe)); + + /** Transform statements and add lifted definitions to them. */ + override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { + val stats1 = super.transformStats(stats, exprOwner); + if (currentOwner.isClass && !currentOwner.isPackageClass && liftedDefs(currentOwner).hasNext) + stats1 ::: liftedDefs(currentOwner).toList + else + stats1 + } + + override def transformUnit(unit: CompilationUnit): unit = { + computeFreeVars; + atPhase(phase.next)(super.transformUnit(unit)) + } + } +} diff --git a/sources/scala/tools/nsc/transform/TailCalls.scala b/sources/scala/tools/nsc/transform/TailCalls.scala index 40e815203f..1a96619ef3 100644 --- a/sources/scala/tools/nsc/transform/TailCalls.scala +++ b/sources/scala/tools/nsc/transform/TailCalls.scala @@ -150,7 +150,8 @@ abstract class TailCalls extends Transform copy.DefDef(tree, mods, name, tparams, vparams, tpt, newRHS); } else { log("Non-final method: " + name); - DefDef(newCtx.currentMethod, (x) => transform(rhs, newCtx)); + // Martin: OK like that? + copy.DefDef(tree, mods, name, tparams, vparams, tpt, transform(rhs, newCtx)) } log("Leaving DefDef: " + name); t1; diff --git a/sources/scala/tools/nsc/transform/Transform.scala b/sources/scala/tools/nsc/transform/Transform.scala index 0710e67641..cfdf796f27 100644 --- a/sources/scala/tools/nsc/transform/Transform.scala +++ b/sources/scala/tools/nsc/transform/Transform.scala @@ -19,7 +19,7 @@ abstract class Transform extends SubComponent { /** The phase defined by this transform */ class Phase(prev: scala.tools.nsc.Phase) extends StdPhase(prev) { def apply(unit: global.CompilationUnit): unit = { - unit.body = newTransformer(unit).transform(unit.body); + newTransformer(unit).transformUnit(unit); } } } diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala index a97d27e38b..741e530a44 100755 --- a/sources/scala/tools/nsc/transform/UnCurry.scala +++ b/sources/scala/tools/nsc/transform/UnCurry.scala @@ -22,7 +22,7 @@ package scala.tools.nsc.transform; * - for every argument list that is an escaped sequence * (a_1:_*) => (a_1)g * - convert implicit method types to method types - * - todo: check-no-double-def in erasure + * - convert non-trivial catches in try statements to matches */ /*</export>*/ abstract class UnCurry extends InfoTransform { @@ -120,6 +120,12 @@ abstract class UnCurry extends InfoTransform { val pat1 = transform(pat); inPattern = false; copy.CaseDef(tree, pat1, transform(guard), transform(body)) +/* + case Try(body, catches, finally) => + catches1 = catches map { + case cdef @ CaseDef(pat, guard, body) if TreeInfo.isDefaultCase(cdef) => + CaseDef(TypedTree(Ident(TreeInfo.defaultCaseVar(pat)), TypeTree(ThrowableClass.tpe))) +*/ case _ => val tree1 = super.transform(tree); if (isByNameRef(tree1)) @@ -133,8 +139,8 @@ abstract class UnCurry extends InfoTransform { if (tree.symbol.isMethod && (!tree.tpe.isInstanceOf[PolyType] || tree.tpe.typeParams.isEmpty)) { if (!tree.tpe.isInstanceOf[MethodType]) tree.tpe = MethodType(List(), tree.tpe); atPos(tree.pos)(Apply(tree, List()) setType tree.tpe.resultType) - } else if (tree.isType) { - TypeTree(tree.tpe) + } else if (tree.isType && !tree.isInstanceOf[TypeTree]) { + TypeTree(tree.tpe) setPos tree.pos } else { tree } diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala index bb63df325d..601bb74ef5 100755 --- a/sources/scala/tools/nsc/typechecker/Namers.scala +++ b/sources/scala/tools/nsc/typechecker/Namers.scala @@ -14,6 +14,20 @@ trait Namers: Analyzer { import global._; import definitions._; + def updatePosFlags(sym: Symbol, pos: int, mods: int): Symbol = { + if (settings.debug.value) log("overwriting " + sym); + sym.pos = pos; + val oldflags = sym.flags & (INITIALIZED | LOCKED); + val newflags = mods & ~(INITIALIZED | LOCKED); + sym.flags = oldflags | newflags; + if (sym.isModule) + updatePosFlags(sym.moduleClass, pos, (mods & ModuleToClassFlags) | MODULE | FINAL); + if (sym.owner.isPackageClass && sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader]) + // pre-set linked symbol to NoType, in case it is not loaded together with this symbol. + sym.linkedSym.setInfo(NoType); + sym + } + class Namer(val context: Context) { private def isTemplateContext(context: Context): boolean = context.tree match { @@ -35,20 +49,6 @@ trait Namers: Analyzer { sym.name.toString() + " is already defined as " + (if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString())); - private def updatePosFlags(sym: Symbol, pos: int, mods: int): Symbol = { - if (settings.debug.value) log("overwriting " + sym); - sym.pos = pos; - val oldflags = sym.flags & (INITIALIZED | LOCKED); - val newflags = mods & ~(INITIALIZED | LOCKED); - sym.flags = oldflags | newflags; - if (sym.isModule) - updatePosFlags(sym.moduleClass, pos, (mods & ModuleToClassFlags) | MODULE | FINAL); - if (sym.owner.isPackageClass && sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader]) - // pre-set linked symbol to NoType, in case it is not loaded together with this symbol. - sym.linkedSym.setInfo(NoType); - sym - } - def enterInScope(sym: Symbol): Symbol = { if (!(sym.isSourceMethod && sym.owner.isClass)) { val prev = context.scope.lookupEntry(sym.name); @@ -284,7 +284,7 @@ trait Namers: Analyzer { val restype = if (tpt.isEmpty) { tpt.tpe = if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe - else deconstIfNotFinal(meth, typer.typed(rhs).tpe); + else deconstIfNotFinal(meth, typer.computeType(rhs)); tpt.tpe } else typer.typedType(tpt).tpe; def mkMethodType(vparams: List[Symbol], restpe: Type) = { @@ -359,7 +359,7 @@ trait Namers: Analyzer { context.error(tpt.pos, "missing parameter type"); ErrorType } else { - tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).typed(rhs).tpe); + tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).computeType(rhs)); tpt.tpe } else typer.typedType(tpt).tpe diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala index 885da9c542..0cceb34512 100755 --- a/sources/scala/tools/nsc/typechecker/RefChecks.scala +++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala @@ -8,7 +8,7 @@ package scala.tools.nsc.typechecker; import symtab.Flags._; import collection.mutable.HashMap; import util.ListBuffer; -import transform.Transform; +import transform.InfoTransform; /** Post-attribution checking and transformation. * //todo: check whether we always check type parameter bounds. @@ -32,7 +32,7 @@ import transform.Transform; * different from java.lang.Object * - Calls to case factory methods are replaced by new's. */ -abstract class RefChecks extends Transform { +abstract class RefChecks extends InfoTransform { import global._; import definitions._; @@ -43,6 +43,13 @@ abstract class RefChecks extends Transform { val phaseName: String = "refchecks"; def newTransformer(unit: CompilationUnit): Transformer = new RefCheckTransformer(unit); + def transformInfo(sym: Symbol, tp: Type): Type = { + if (sym.isModule && !sym.isStatic) { + sym setFlag (METHOD | STABLE); + PolyType(List(), tp) + } else tp + } + class RefCheckTransformer(unit: CompilationUnit) extends Transformer { // Override checking ------------------------------------------------------------ @@ -162,7 +169,6 @@ abstract class RefChecks extends Transform { "\n and " + infoString(alt2) + "\n override " + infoString(other)); } else if (member != NoSymbol && !(member hasFlag LOCAL)) { - member.flags = member.flags | ACCESSED; checkOverride(clazz, member, other); } } @@ -352,7 +358,7 @@ abstract class RefChecks extends Transform { } private def enterReference(pos: int, sym: Symbol): unit = - if (sym.isLocal && sym.isTerm) { + if (sym.isLocal) { val e = currentLevel.scope.lookupEntry(sym.name); if (e != null && sym == e.sym) { var l = currentLevel; @@ -477,7 +483,9 @@ abstract class RefChecks extends Transform { val sym = tree.symbol; val localTyper = typer.atOwner(currentOwner); val cdef = ClassDef(mods | MODULE, name, List(), EmptyTree, impl) - setSymbol sym.moduleClass setType NoType; + setPos tree.pos + setSymbol sym.moduleClass + setType NoType; if (sym.isStatic) List(transform(cdef)) else { val moduleType = sym.tpe; @@ -492,17 +500,19 @@ abstract class RefChecks extends Transform { ValDef(mvar, if (sym.isLocal) Literal(Constant(null)) else EmptyTree)); // def m: T = { if (m$ == null) m$ = new m$class; m$ } - sym.setFlag(METHOD | STABLE); - sym.setInfo(PolyType(List(), moduleType)); - val ddef = localTyper.typed( - DefDef(sym, vparamss => - Block( - List( - If( - Apply(Select(Ident(mvar), nme.EQ), List(Literal(Constant(null)))), - Assign(Ident(mvar), New(TypeTree(moduleType), List(List()))), - EmptyTree)), - Ident(mvar)))); + val ddef = + atPhase(phase.next) { + localTyper.typed { + DefDef(sym, vparamss => + Block( + List( + If( + Apply(Select(Ident(mvar), nme.EQ), List(Literal(Constant(null)))), + Assign(Ident(mvar), New(TypeTree(moduleType), List(List()))), + EmptyTree)), + Ident(mvar))) + } + } transformTrees(List(cdef, vdef, ddef)) } @@ -583,7 +593,6 @@ abstract class RefChecks extends Transform { if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor else if (name != nme.WILDCARD && name != nme.WILDCARD_STAR.toTypeName) { - sym setFlag ACCESSED; assert(sym != NoSymbol, tree);//debug enterReference(tree.pos, sym); } @@ -592,7 +601,6 @@ abstract class RefChecks extends Transform { if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor else { - sym setFlag ACCESSED; if (sym hasFlag DEFERRED) { qual match { case Super(qualifier, mixin) => diff --git a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala index 791f865f24..c2191eff3d 100644 --- a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -57,12 +57,35 @@ abstract class TreeCheckers extends Analyzer { override def typed(tree: Tree) = super.typed(tree); // doto remove for new compiler object precheck extends Traverser { - override def traverse(tree: Tree): unit = { - if (tree.pos == Position.NOPOS) - error(tree.pos, "tree without position: " + tree) - else if (tree.tpe == null && phase.id >= typerPhase.id) - error(tree.pos, "tree without type: " + tree) - } + override def traverse(tree: Tree): unit = + try { + tree match { + case Apply(_, args) => + assert(args forall (EmptyTree !=)) + case _ => + } + if (tree.pos == Position.NOPOS && tree != EmptyTree) { + error(tree.pos, "tree without position: " + tree) + } else if (tree.tpe == null && phase.id >= typerPhase.id) { + error(tree.pos, "tree without type: " + tree); + } else if (tree.isDef && tree.symbol.owner != currentOwner) { + var owner = currentOwner; + while (owner.isTerm && !owner.isMethod && tree.symbol.owner != owner) + owner = owner.owner; + if (tree.symbol.owner != owner) { + error(tree.pos, "" + tree.symbol + " has wrong owner: " + tree.symbol.owner + + tree.symbol.owner.locationString + ", should be: " + + currentOwner + currentOwner.locationString) + } + } else { + super.traverse(tree) + } + } catch { + case ex: Throwable => + if (settings.debug.value) + System.out.println("exception when traversing " + tree); + throw(ex) + } } object postcheck extends Traverser { diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala index 55ee7c475c..68c092b8c0 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -9,6 +9,7 @@ package scala.tools.nsc.typechecker; import nsc.util.ListBuffer; import symtab.Flags._; import scala.tools.util.Position; +import collection.mutable.HashMap; /** Methods to create symbols and to enter them into scopes. */ abstract class Typers: Analyzer { @@ -21,6 +22,8 @@ abstract class Typers: Analyzer { var selcnt = 0; var implcnt = 0; + private var transformed = new HashMap[Tree, Tree]; + def newTyper(context: Context): Typer = new Typer(context); class Typer(context0: Context) { @@ -34,8 +37,8 @@ abstract class Typers: Analyzer { private def inferView(pos: int, from: Type, to: Type, reportAmbiguous: boolean): Tree = { if (settings.debug.value) log("infer view from " + from + " to " + to);//debug - val res = inferImplicit(pos, functionType(List(from), to), true, reportAmbiguous); - res + if (phase.erasedTypes) EmptyTree + else inferImplicit(pos, functionType(List(from), to), true, reportAmbiguous); } private def inferView(pos: int, from: Type, name: Name, reportAmbiguous: boolean): Tree = { @@ -502,11 +505,69 @@ abstract class Typers: Analyzer { val sym = vdef.symbol; var tpt1 = checkNoEscaping.privates(sym, typedType(vdef.tpt)); val rhs1 = - if (vdef.rhs.isEmpty) vdef.rhs - else newTyper(context.make(vdef, sym)).typed(vdef.rhs, tpt1.tpe); + if (vdef.rhs.isEmpty) { + if ((sym hasFlag MUTABLE) && sym.owner.isTerm && phase.id <= typerPhase.id) + error(vdef.pos, "local variables must be initialized"); + vdef.rhs + } else { + newTyper(context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt1.tpe) + } copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, rhs1) setType NoType } + /** Enter in global.aliases all aliases of local parameter accessors. */ + def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree): unit = { + if (settings.debug.value) log("computing param aliases for " + clazz + ":" + clazz.primaryConstructor.tpe + ":" + rhs);//debug + def decompose(call: Tree): Pair[Tree, List[Tree]] = call match { + case Apply(fn, args) => + val Pair(superConstr, args1) = decompose(fn); + val formals = fn.tpe.paramTypes; + val args2 = if (formals.isEmpty || formals.last.symbol != RepeatedParamClass) args + else args.take(formals.length - 1) ::: List(EmptyTree); + if (args2.length != formals.length) assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug + Pair(superConstr, args1 ::: args2) + case Block(stats, expr) => + decompose(stats.head) + case _ => + Pair(call, List()) + } + val Pair(superConstr, superArgs) = decompose(rhs); + assert(superConstr.symbol != null, superConstr);//debug + if (superConstr.symbol.isPrimaryConstructor) { + val superClazz = superConstr.symbol.owner; + val superParamAccessors = superClazz.constrParamAccessors; + if (superParamAccessors.length != superArgs.length) { + System.out.println("" + superClazz + ":" + superClazz.info.decls.toList.filter(.hasFlag(PARAMACCESSOR))); + assert(false, "mismatch: " + superParamAccessors + ";" + rhs + ";" + superClazz.info.decls); //debug + } + List.map2(superParamAccessors, superArgs) { (superAcc, superArg) => + superArg match { + case Ident(name) => + if (vparamss.exists(.exists(vp => vp.symbol == superArg.symbol))) { + val alias = aliases.get(superAcc.initialize) match { + case Some(getter) => + getter + case None => + val getter = superAcc.getter; + if (getter != NoSymbol && + superClazz.info.nonPrivateMember(getter.name) == getter) getter + else NoSymbol + } + if (alias != NoSymbol) { + var ownAcc = clazz.info.decl(name); + if (ownAcc hasFlag ACCESSOR) ownAcc = ownAcc.accessed; + assert(ownAcc hasFlag PARAMACCESSOR, clazz.toString() + " " + name); + System.out.println("" + ownAcc + " has alias " + alias + alias.locationString);//debug + aliases(ownAcc) = alias + } + } + case _ => + } + } + () + } + } + def typedDefDef(ddef: DefDef): DefDef = { val meth = ddef.symbol; reenterTypeParams(ddef.tparams); @@ -526,10 +587,10 @@ abstract class Typers: Analyzer { context.enclClass.owner.setFlag(INCONSTRUCTOR); val result = typed(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe); context.enclClass.owner.resetFlag(INCONSTRUCTOR); + if (meth.isPrimaryConstructor && !phase.erasedTypes) + computeParamAliases(meth.owner, vparamss1, result); result - } else { - typed(ddef.rhs, tpt1.tpe); - } + } else transformedOrTyped(ddef.rhs, tpt1.tpe); copy.DefDef(ddef, ddef.mods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType } @@ -643,6 +704,7 @@ abstract class Typers: Analyzer { setFlag FINAL setInfo MethodType(formals, body.tpe); anonClass.info.decls enter applyMethod; for (val vparam <- vparamSyms) vparam.owner = applyMethod; + new ChangeOwnerTraverser(context.owner, applyMethod).traverse(body); var members = List( DefDef(FINAL, nme.apply, List(), List(vparams), TypeTree(body.tpe), body) setSymbol applyMethod); @@ -657,16 +719,15 @@ abstract class Typers: Analyzer { CaseDef(substParam(cdef.pat.duplicate), substParam(cdef.guard.duplicate), Literal(true)); - def isDefaultCase(cdef: CaseDef) = cdef match { - case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true - case CaseDef(Bind(_, Ident(nme.WILDCARD)), EmptyTree, _) => true - case _ => false - } - if (cases exists isDefaultCase) Literal(true) - else Match( - Ident(idparam), - (cases map transformCase) ::: - List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false)))) + val result = + if (cases exists treeInfo.isDefaultCase) Literal(true) + else + Match( + Ident(idparam), + (cases map transformCase) ::: + List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false)))); + new ChangeOwnerTraverser(applyMethod, isDefinedAtMethod).traverse(result); + result } members = DefDef(isDefinedAtMethod, vparamss => idbody(vparamss.head.head)) :: members; } @@ -1278,6 +1339,18 @@ abstract class Typers: Analyzer { /** Types a type or type constructor tree */ def typedTypeConstructor(tree: Tree): Tree = typed(tree, TYPEmode | FUNmode, WildcardType); + + def computeType(tree: Tree): Type = { + val tree1 = typed(tree); + transformed(tree) = tree1; + tree1.tpe + } + + def transformedOrTyped(tree: Tree, pt: Type): Tree = transformed.get(tree) match { + case Some(tree1) => transformed -= tree; tree1 + case None => typed(tree, pt) + } + /* def convertToTypeTree(tree: Tree): Tree = tree match { case TypeTree() => tree diff --git a/sources/scala/tools/nsc/util/HashSet.scala b/sources/scala/tools/nsc/util/HashSet.scala index 0e26231d65..5751c49001 100755 --- a/sources/scala/tools/nsc/util/HashSet.scala +++ b/sources/scala/tools/nsc/util/HashSet.scala @@ -5,7 +5,7 @@ // $Id$ package scala.tools.nsc.util; -class HashSet[T <: AnyRef](capacity: int) { +class HashSet[T <: AnyRef](capacity: int) extends Set[T] { private var size = capacity; private var used = 0; diff --git a/sources/scala/tools/nsc/util/Set.scala b/sources/scala/tools/nsc/util/Set.scala new file mode 100755 index 0000000000..dab7898e39 --- /dev/null +++ b/sources/scala/tools/nsc/util/Set.scala @@ -0,0 +1,23 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author Martin Odersky + */ +// $Id$ +package scala.tools.nsc.util; + +/** A common trait for lightweight sets. + */ +abstract class Set[T <: AnyRef] { + + def findEntry(x: T): T; + + def addEntry(x: T): unit; + + def elements: Iterator[T]; + + def contains(x: T): boolean = + findEntry(x) != null; + + def toList = elements.toList; + +} diff --git a/sources/scala/tools/nsc/util/TreeSet.scala b/sources/scala/tools/nsc/util/TreeSet.scala new file mode 100755 index 0000000000..552f06b3f4 --- /dev/null +++ b/sources/scala/tools/nsc/util/TreeSet.scala @@ -0,0 +1,52 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author Martin Odersky + */ +// $Id$ +package scala.tools.nsc.util; + +/** Sets implemented as binary trees. + */ +class TreeSet[T <: AnyRef](less: (T, T) => boolean) extends Set[T] { + + private class Tree(val elem: T) { + var l: Tree = null; + var r: Tree = null; + } + + private var tree: Tree = null; + + def findEntry(x: T): T = { + def find(t: Tree): T = { + if (t == null) null + else if (less(x, t.elem)) find(t.l) + else if (less(t.elem, x)) find(t.r) + else t.elem + } + find(tree) + } + + def addEntry(x: T): unit = { + def add(t: Tree): Tree = { + if (t == null) new Tree(x) + else if (less(x, t.elem)) { t.l = add(t.l); t } + else if (less(t.elem, x)) { t.r = add(t.r); t } + else t + } + tree = add(tree) + } + + def elements = { + def elems(t: Tree): Iterator[T] = { + var it = Iterator.single(t.elem); + if (t.l != null) it = elems(t.l) append it; + if (t.r != null) it = it append elems(t.r); + it + } + if (tree == null) Iterator.empty else elems(tree) + } + + override def toString(): String = { + if (tree == null) "<empty>" else "(..." + tree.elem + "...)"; + } +} |