diff options
author | Martin Odersky <odersky@gmail.com> | 2006-09-11 22:35:32 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2006-09-11 22:35:32 +0000 |
commit | 540f1b3922fb41a598247036e82ffb407761ce17 (patch) | |
tree | 847e4a9f230a04bbeaa9e5997f7b9f862d1f8776 | |
parent | 1237c5202669272825990e0c41803bd39a0846c8 (diff) | |
download | scala-540f1b3922fb41a598247036e82ffb407761ce17.tar.gz scala-540f1b3922fb41a598247036e82ffb407761ce17.tar.bz2 scala-540f1b3922fb41a598247036e82ffb407761ce17.zip |
moved mixin constructor generation from explici...
moved mixin constructor generation from explicitOuter to AddInterfaces
4 files changed, 77 insertions, 110 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index bd191710bf..2bc085b07a 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -315,11 +315,7 @@ trait Symbols requires SymbolTable { // Flags, owner, and name attributes -------------------------------------------------------------- - def owner: Symbol = { - val r = rawowner - if ((r.rawflags & IMPLCLASS) != 0 && !phase.next.erasedTypes) r.toInterface - else r - } + def owner: Symbol = rawowner final def owner_=(owner: Symbol): unit = { rawowner = owner } def ownerChain: List[Symbol] = this :: owner.ownerChain diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 9e9f06fc5d..0d0e9b69e1 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -101,8 +101,10 @@ abstract class AddInterfaces extends InfoTransform { /** Compute the decls of implementation class `implClass', * given the decls `ifaceDecls' of its interface */ - def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = { + private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = { val decls = newScope + decls enter (implClass.newMethod(implClass.pos, nme.MIXIN_CONSTRUCTOR) + setInfo MethodType(List(), UnitClass.tpe)) for (val sym <- ifaceDecls.elements) { if (isInterfaceMember(sym)) { if (needsImplMethod(sym)) { @@ -127,7 +129,7 @@ abstract class AddInterfaces extends InfoTransform { case ClassInfoType(parents, decls, _) => //ClassInfoType(mixinToImplClass(parents) ::: List(iface.tpe), implDecls(sym, decls), sym) ClassInfoType( - ObjectClass.tpe :: (parents.tail map mixinToImplClass) ::: List(iface.tpe), //!!! + ObjectClass.tpe :: (parents.tail map mixinToImplClass) ::: List(iface.tpe), implDecls(sym, decls), sym) case PolyType(tparams, restpe) => @@ -211,10 +213,17 @@ abstract class AddInterfaces extends InfoTransform { else if (needsImplMethod(tree.symbol)) implMethodDef(tree, tree.symbol) else EmptyTree + /** The mixin constructor definition + * def $init$(): Unit = () + */ + private def mixinConstructorDef(clazz: Symbol): Tree = + DefDef(clazz.primaryConstructor, vparamss => Block(List(), Literal(()))) + 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)); + val templ1 = atPos(templ.pos) { + Template(templ.parents, mixinConstructorDef(clazz) :: (templ.body map implMemberDef)) + .setSymbol(clazz.newLocalDummy(templ.pos)) + } new ChangeOwnerTraverser(templ.symbol.owner, clazz)( new ChangeOwnerTraverser(templ.symbol, templ1.symbol)(templ1)) } @@ -234,26 +243,52 @@ abstract class AddInterfaces extends InfoTransform { buf.toList } + /** Add calls to supermixin constructors + * super[mix].$init$() + * to `tree'. `tree' which is assumed to be the body of a constructor of class `clazz'. + */ + private def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = { + def mixinConstructorCall(mixinClass: Symbol): Tree = atPos(tree.pos) { + Apply(Select(This(clazz), mixinClass.primaryConstructor), List()) + } + val mixinConstructorCalls: List[Tree] = { + for (val mc <- clazz.mixinClasses.reverse; mc.isImplClass && mc.toInterface != ScalaObjectClass) + yield mixinConstructorCall(mc) + } + tree match { //todo: remove checking code + case Block(supercall :: stats, expr) => + assert(supercall match { + case Apply(Select(Super(_, _), _), _) => true + case _ => false + }) + copy.Block(tree, supercall :: mixinConstructorCalls ::: stats, expr) + case Block(_, _) => + assert(false, tree); tree + } + } + protected val mixinTransformer = new Transformer { override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = (super.transformStats(stats, exprOwner) ::: super.transformStats(implClassDefs(stats), exprOwner)) override def transform(tree: Tree): Tree = { + val sym = tree.symbol val tree1 = tree match { - case ClassDef(mods, name, tparams, tpt, impl) => - if (tree.symbol.needsImplClass) { - implClass(tree.symbol).initialize // to force lateDEFERRED flags - copy.ClassDef(tree, mods | INTERFACE, name, tparams, tpt, ifaceTemplate(impl)) - } - else tree + case ClassDef(mods, name, tparams, tpt, impl) if (sym.needsImplClass) => + implClass(sym).initialize // to force lateDEFERRED flags + copy.ClassDef(tree, mods | INTERFACE, name, tparams, tpt, ifaceTemplate(impl)) + case DefDef(mods, name, tparams, vparamss, tpt, rhs) + if (sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass) => + copy.DefDef(tree, mods, name, tparams, vparamss, tpt, + addMixinConstructorCalls(rhs, sym.owner)) // (3) case Template(parents, body) => - val parents1 = tree.symbol.owner.info.parents map (t => TypeTree(t) setPos tree.pos) + val parents1 = sym.owner.info.parents map (t => TypeTree(t) setPos tree.pos) copy.Template(tree, parents1, body) case This(_) => - if (tree.symbol.needsImplClass) { - val impl = implClass(tree.symbol) + if (sym.needsImplClass) { + val impl = implClass(sym) var owner = currentOwner - while (owner != tree.symbol && owner != impl) owner = owner.owner; + while (owner != sym && owner != impl) owner = owner.owner; if (owner == impl) This(impl) setPos tree.pos else tree } else tree @@ -262,13 +297,13 @@ abstract class AddInterfaces extends InfoTransform { if (mix == nme.EMPTY.toTypeName) mix else { val ps = atPhase(currentRun.erasurePhase) { - tree.symbol.info.parents dropWhile (p => p.symbol.name != mix) + sym.info.parents dropWhile (p => p.symbol.name != mix) } assert(!ps.isEmpty, tree); if (ps.head.symbol.needsImplClass) implClass(ps.head.symbol).name else mix } - if (tree.symbol.needsImplClass) Super(implClass(tree.symbol), mix1) setPos tree.pos + if (sym.needsImplClass) Super(implClass(sym), mix1) setPos tree.pos else copy.Super(tree, qual, mix1) case _ => tree diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index f99daa5cc8..d33da6a548 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -367,7 +367,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { super.typed1(adaptMember(tree), mode, pt); } catch { case ex: Throwable => - if (settings.debug.value) + //if (settings.debug.value) System.out.println("exception when typing " + tree); throw ex } diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index d85e491739..5d5f08922b 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -70,36 +70,27 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter if (sym.isClassConstructor && isInner(sym.owner)) // 1 MethodType(sym.owner.outerClass.thisType :: formals, restpe) else tp - case ClassInfoType(parents, decls, clazz) => - var decls1 = decls - if (!(clazz hasFlag INTERFACE)) { - if (isInner(clazz)) { - if (decls1 eq decls) decls1 = newScope(decls1.toList) - val outerAcc = clazz.newMethod(clazz.pos, nme.OUTER) // 3 - outerAcc.expandName(clazz) - decls1 enter ( - clazz.newOuterAccessor(clazz.pos) - setInfo MethodType(List(), clazz.outerClass.thisType)) - if (!parents.isEmpty) { - for (val mc <- clazz.mixinClasses) { - val mixinOuterAcc: Symbol = atPhase(phase.next)(outerAccessor(mc)) - if (mixinOuterAcc != NoSymbol) - decls1 enter (mixinOuterAcc.cloneSymbol(clazz) resetFlag DEFERRED) - } - } - if (!clazz.isTrait) // 2 - //todo: avoid outer field if superclass has same outer value? - decls1 enter ( - clazz.newValue(clazz.pos, nme.getterToLocal(nme.OUTER)) - setFlag (PROTECTED | PARAMACCESSOR) - setInfo clazz.outerClass.thisType) - } - if (clazz.isTrait) { // 4 (todo: can go into next phase?) - if (decls1 eq decls) decls1 = newScope(decls1.toList) - decls1 enter makeMixinConstructor(clazz) + case ClassInfoType(parents, decls, clazz) if (isInner(clazz) && !(clazz hasFlag INTERFACE)) => + val decls1 = newScope(decls.toList) + val outerAcc = clazz.newMethod(clazz.pos, nme.OUTER) // 3 + outerAcc.expandName(clazz) + decls1 enter ( + clazz.newOuterAccessor(clazz.pos) + setInfo MethodType(List(), clazz.outerClass.thisType)) + if (!parents.isEmpty) { + for (val mc <- clazz.mixinClasses) { + val mixinOuterAcc: Symbol = atPhase(phase.next)(outerAccessor(mc)) + if (mixinOuterAcc != NoSymbol) + decls1 enter (mixinOuterAcc.cloneSymbol(clazz) resetFlag DEFERRED) } } - if (decls1 eq decls) tp else ClassInfoType(parents, decls1, clazz) + if (!clazz.isTrait) // 2 + //todo: avoid outer field if superclass has same outer value? + decls1 enter ( + clazz.newValue(clazz.pos, nme.getterToLocal(nme.OUTER)) + setFlag (PROTECTED | PARAMACCESSOR) + setInfo clazz.outerClass.thisType) + ClassInfoType(parents, decls1, clazz) case PolyType(tparams, restp) => val restp1 = transformInfo(sym, restp) if (restp eq restp1) tp else PolyType(tparams, restp1) @@ -107,9 +98,6 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter tp } - 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. @@ -234,52 +222,6 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter } } - /** The mixin constructor definition - * def $init$(): Unit = () - */ - def mixinConstructorDef(clazz: Symbol): Tree = - localTyper.typed { - val constr = clazz.primaryConstructor - atPhase(currentRun.explicitOuterPhase) { - // necessary so that we do not include an outer parameter already here - // this will be added later in transform. - DefDef(constr, vparamss => Block(List(), Literal(()))) - } - } - - /** Add calls to supermixin constructors - * super[mix].$init$() - * to `tree'. `tree' which is assumed to be the body of a constructor of class `clazz'. - */ - def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = { - def mixinConstructorCall(mixinClass: Symbol): Tree = - atPos(tree.pos) { - Apply( - localTyper.typedOperator { - Select(This(clazz), mixinClass.primaryConstructor) - }, - List()) setType UnitClass.tpe; // don't type this with typed(...), - // as constructor arguments might be missing - } - - val mixinConstructorCalls: List[Tree] = { - for (val mc <- clazz.mixinClasses.reverse; mc.needsImplClass && mc != ScalaObjectClass) - yield mixinConstructorCall(mc) - } - - //begin mixin constructor calls - tree match { - case Block(supercall :: stats, expr) => - assert(supercall match { - case Apply(Select(Super(_, _), _), _) => true - case _ => false - }) - copy.Block(tree, supercall :: mixinConstructorCalls ::: stats, expr) - case Block(_, _) => - assert(false, tree); tree - } - } - /** The main transformation method */ override def transform(tree: Tree): Tree = { val sym = tree.symbol @@ -296,9 +238,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter if (!currentClass.isTrait) newDefs += outerFieldDef // (1a) newDefs += outerAccessorDef // (1) } - if (currentClass.isTrait) - newDefs += mixinConstructorDef(currentClass) - else + if (!currentClass.isTrait) for (val mc <- currentClass.mixinClasses) if (outerAccessor(mc) != NoSymbol) newDefs += mixinOuterAccessorDef(mc) @@ -318,15 +258,11 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter val clazz = sym.owner val vparamss1 = if (isInner(clazz)) { // (4) - val outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField(clazz).info + val outerParam = + sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField(clazz).info ((ValDef(outerParam) setType NoType) :: vparamss.head) :: vparamss.tail } else vparamss - // todo: move - val rhs1 = - if (sym.isPrimaryConstructor && sym.isClassConstructor && clazz != ArrayClass) - addMixinConstructorCalls(rhs, clazz); // (3) - else rhs - super.transform(copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1)) + super.transform(copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs)) } } else { //todo: see whether we can move this to transformInfo if (sym.owner.isTrait && (sym hasFlag (ACCESSOR | SUPERACCESSOR))) |