From bc13888586e6ed7062d59c8e883888cbaa5a7770 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 26 Jan 2006 13:00:58 +0000 Subject: --- src/compiler/scala/tools/nsc/Global.scala | 2 +- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 2 + .../scala/tools/nsc/ast/TreePrinters.scala | 5 +- src/compiler/scala/tools/nsc/symtab/Symbols.scala | 2 +- .../scala/tools/nsc/transform/ExplicitOuter.scala | 78 +++++++++++++++------- src/compiler/scala/tools/util/PlainFile.java | 19 +++++- 6 files changed, 78 insertions(+), 30 deletions(-) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 53b86da085..e8555633ce 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -191,7 +191,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable val global: Global.this.type = Global.this } - object analyzer extends Analyzer { + object analyzer extends AnyRef with Analyzer { val global: Global.this.type = Global.this; } diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 425cf9eac8..5f4a6ba3cb 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -46,6 +46,8 @@ abstract class TreeGen { qual } } else This(sym) + case _ => + throw new Error("bad qualifier: " + tpe) } /** Builds a reference to given symbol with given stable prefix. */ diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index ba3eaf6fd7..d0ccc76479 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -74,7 +74,10 @@ abstract class TreePrinters { } def symName(tree: Tree, name: Name): String = - if (tree.symbol != NoSymbol) tree.symbol.nameString else name.toString(); + if (tree.symbol != NoSymbol) { + ((if (tree.symbol.isMixinConstructor) "/*"+tree.symbol.owner.name+"*/" else "") + + tree.symbol.nameString) + } else name.toString(); def printOpt(prefix: String, tree: Tree): unit = if (!tree.isEmpty) { print(prefix); print(tree) } diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index ceaea4424e..7650d881d4 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -29,7 +29,7 @@ mixin class Symbols requires SymbolTable { var rawowner = initOwner; var rawname = initName; - private var rawflags: long = 0; + var rawflags: long = 0; private var rawpos = initPos; val id = { ids = ids + 1; ids } diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index ec598d784f..bb9b34d177 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -207,16 +207,32 @@ abstract class ExplicitOuter extends InfoTransform { atPos(tree.pos) { Apply( localTyper.typedOperator { - Select(Super(clazz, mixinClass.name), mixinClass.primaryConstructor) + Select(This(clazz), mixinClass.primaryConstructor) }, List()) setType UnitClass.tpe; // don't type this with typed(...), // as constructor arguments might be missing } + /* val mixinConstructorCalls = for (val mixinClass <- clazz.info.parents.tail; !(mixinClass.symbol hasFlag INTERFACE) && mixinClass.symbol != ScalaObjectClass) yield mixinConstructorCall(mixinClass.symbol); tree match { + */ + val mixinConstructorCalls: List[Tree] = { + val ps = clazz.info.parents; + if (ps.isEmpty) List() + else { + val superClass = ps.head.symbol; + for { + val mclazz <- clazz.info.baseClasses.tail.takeWhile(superClass ne).reverse; + mclazz.needsImplClass && mclazz != ScalaObjectClass + } yield mixinConstructorCall(mclazz) + } + } + + //val result = + tree match { case Block(supercall :: stats, expr) => assert(supercall match { case Apply(Select(Super(_, _), _), _) => true @@ -225,9 +241,10 @@ abstract class ExplicitOuter extends InfoTransform { copy.Block(tree, supercall :: mixinConstructorCalls ::: stats, expr); case Block(_, _) => assert(false, tree); tree - case expr => - Block(mixinConstructorCalls, expr) setType expr.tpe setPos expr.pos; } + + //System.out.println("new constructor of "+clazz+": "+result); + //result } /** The first-step transformation method */ @@ -238,7 +255,7 @@ abstract class ExplicitOuter extends InfoTransform { val savedLocalTyper = localTyper; localTyper = localTyper.atOwner(tree, currentOwner); var decls1 = decls; - if (!(currentOwner hasFlag INTERFACE)) { + if (!(currentOwner hasFlag INTERFACE) || (currentOwner hasFlag lateINTERFACE)) { if (!isStatic(currentOwner)) decls1 = decls1 ::: outerDefs(currentOwner); // (1) if (currentOwner.isMixin) @@ -248,32 +265,45 @@ abstract class ExplicitOuter extends InfoTransform { copy.Template(tree, parents, decls1); case constrDef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) if (sym.isConstructor) => - val vparamss1 = - if (isStatic(sym.owner)) vparamss - else { // (4) - val outerField = outerMember(sym.owner.info).accessed; - 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) - addMixinConstructorCalls(rhs, sym.owner); // (3) - else rhs; - copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1); + rhs match { + case Literal(_) => + val rhs1 = Block(List(), rhs) setPos rhs.pos setType rhs.tpe; + transform(copy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs1)) + case _ => + val clazz = sym.owner.toInterface; + val vparamss1 = + if (isStatic(clazz)) vparamss + else { // (4) + val outerField = outerMember(clazz.info).accessed; + 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.isClassConstructor && clazz != ArrayClass) + addMixinConstructorCalls(rhs, clazz); // (3) + else rhs; + copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1) + } case This(qual) => if (sym == currentOwner.enclClass || (sym hasFlag MODULE) && sym.isStatic) tree else atPos(tree.pos)(outerPath(outerValue, sym)); // (5) case Apply(sel @ Select(qual, name), args) if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) && !isStatic(sel.symbol.owner)) => - val outerVal = - atPos(tree.pos) { - if (qual.isInstanceOf[This]) { assert(outerParam != NoSymbol); outerValue } // (8) - else { - var pre = qual.tpe.prefix; - if (pre == NoPrefix) pre = outerClass(sym.owner).thisType; - gen.mkQualifier(pre) - } + val outerVal = atPos(tree.pos) { + if (name == nme.MIXIN_CONSTRUCTOR) { + val mclazz = sym.owner.toInterface; + //System.out.println("adding mixin constructor for " + currentOwner.enclClass + " " + mclazz + " " + currentOwner.enclClass.thisType.baseType(mclazz));//DEBUG + var pre = currentOwner.enclClass.thisType.baseType(mclazz).prefix; + if (pre == NoPrefix) pre = outerClass(mclazz).thisType; + gen.mkQualifier(pre) + } else if (qual.isInstanceOf[This]) { + assert(outerParam != NoSymbol); outerValue + } else { + var pre = qual.tpe.prefix; + if (pre == NoPrefix) pre = outerClass(sym.owner).thisType; + gen.mkQualifier(pre) } + } copy.Apply(tree, sel, args ::: List(outerVal)) case _ => tree diff --git a/src/compiler/scala/tools/util/PlainFile.java b/src/compiler/scala/tools/util/PlainFile.java index 1bd2664cea..13b1bf2e4c 100644 --- a/src/compiler/scala/tools/util/PlainFile.java +++ b/src/compiler/scala/tools/util/PlainFile.java @@ -119,12 +119,25 @@ public class PlainFile extends AbstractFile { if (names == null || names.length == 0) return EmptyIterator.object; class ListIterator implements Iterator { private int i; + File lookAhead = null; public boolean hasNext() { - return i < names.length; + if (lookAhead != null) return true; + else if (i == names.length) return false; + else { + lookAhead = new File(file, names[i++]); + if (lookAhead.exists()) return true; + else { + lookAhead = null; + return hasNext(); + } + } } public Object next() { - if (i == names.length) throw new NoSuchElementException(); - return new PlainFile(new File(file, names[i++])); + if (hasNext()) { + File f = lookAhead; + lookAhead = null; + return new PlainFile(f); + } else throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); -- cgit v1.2.3