summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-09-11 22:35:32 +0000
committerMartin Odersky <odersky@gmail.com>2006-09-11 22:35:32 +0000
commit540f1b3922fb41a598247036e82ffb407761ce17 (patch)
tree847e4a9f230a04bbeaa9e5997f7b9f862d1f8776
parent1237c5202669272825990e0c41803bd39a0846c8 (diff)
downloadscala-540f1b3922fb41a598247036e82ffb407761ce17.tar.gz
scala-540f1b3922fb41a598247036e82ffb407761ce17.tar.bz2
scala-540f1b3922fb41a598247036e82ffb407761ce17.zip
moved mixin constructor generation from explici...
moved mixin constructor generation from explicitOuter to AddInterfaces
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala69
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala110
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)))