summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/transform/Mixin.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-09-13 14:35:48 +0000
committerMartin Odersky <odersky@gmail.com>2005-09-13 14:35:48 +0000
commitb058c90501ec726024b2af18fd163f01567911aa (patch)
tree724d395d16ebd2ed1bd1732bcda013e38b37a855 /sources/scala/tools/nsc/transform/Mixin.scala
parentb6f8d5a603fab46e6e8e30fc85a35d36fda6f05e (diff)
downloadscala-b058c90501ec726024b2af18fd163f01567911aa.tar.gz
scala-b058c90501ec726024b2af18fd163f01567911aa.tar.bz2
scala-b058c90501ec726024b2af18fd163f01567911aa.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc/transform/Mixin.scala')
-rwxr-xr-xsources/scala/tools/nsc/transform/Mixin.scala373
1 files changed, 231 insertions, 142 deletions
diff --git a/sources/scala/tools/nsc/transform/Mixin.scala b/sources/scala/tools/nsc/transform/Mixin.scala
index 4cf1ea4ff4..296f614f73 100755
--- a/sources/scala/tools/nsc/transform/Mixin.scala
+++ b/sources/scala/tools/nsc/transform/Mixin.scala
@@ -18,53 +18,20 @@ abstract class Mixin extends InfoTransform {
/** the following two members override abstract members in Transform */
val phaseName: String = "mixin";
- override def phaseNewFlags: long = lateMODULE;
+ override def phaseNewFlags: long = lateMODULE | notABSTRACT;
- def isForwarded(sym: Symbol) =
+ private def isForwarded(sym: Symbol) =
sym.owner.isImplClass && sym.isMethod && !(sym hasFlag (ACCESSOR | SUPERACCESSOR));
- def isStatic(sym: Symbol) = isForwarded(sym) && (sym.hasFlag(PRIVATE) || sym.isConstructor);
+ private def isStatic(sym: Symbol) = isForwarded(sym) && (sym.hasFlag(PRIVATE) || sym.isConstructor);
- def isSelfRef(tree: Tree) = tree match {
- case This(_) => true
- case Super(_, mix) => mix != nme.EMPTY.toTypeName
- case _ => false
- }
-/*
- def toImplClass(sym: Symbol): Symbol = {
- val impl = clazz.owner.info.decl(nme.IMPL_CLASS_NAME(clazz.name));
-
- }
-
- def toInterface(sym: Symbol): Symbol;
-*/
- def toInterface(tp: Type): Type =
- if (tp.symbol.isImplClass) {
- val iface = tp.parents.last;
- if (!tp.symbol.name.startsWith(iface.symbol.name)) assert(false, "bad interface: " + tp + " " + iface);
- iface
- } else tp;
-
- def makeUnique(decls: Scope, sym: Symbol): unit = {
- if ((sym hasFlag PRIVATE) && decls.lookup(sym.name) != NoSymbol) {
- val prefix = sym.name.toString() + "$";
- var index = 0;
- while (decls.lookup(newTermName(prefix + index)) != NoSymbol) index = index + 1;
- sym.name = newTermName(prefix + index)
- }
- }
-
- private def staticRef(sym: Symbol) = {
- System.out.println("static ref " + sym.owner + " . " + sym);//debug
- sym.owner.info;
- Select(gen.mkRef(sym.owner.sourceModule), sym);
- }
+ private def toInterface(tp: Type): Type = tp.symbol.toInterface.tpe;
private def rebindSuper(base: Symbol, member: Symbol, prevowner: Symbol): Symbol = {
var bcs = base.info.baseClasses.dropWhile(prevowner !=).tail;
var sym: Symbol = NoSymbol;
while (!bcs.isEmpty && sym == NoSymbol) {
- System.out.println("rebindsuper " + bcs.head + " " + bcs.head.info.nonPrivateDecl(member.name));//debug
+ if (settings.debug.value) log("rebindsuper " + bcs.head + " " + bcs.head.info.nonPrivateDecl(member.name));
sym = member.overridingSymbol(bcs.head).suchThat(sym => !sym.hasFlag(DEFERRED));
bcs = bcs.tail
}
@@ -72,78 +39,115 @@ abstract class Mixin extends InfoTransform {
sym
}
- private def implClass(iface: Symbol): Symbol =
- atPhase(flattenPhase)(iface.owner.info.decl(nme.implClassName(iface.name)));
+ private def implClass(iface: Symbol): Symbol = erasure.implClass(iface);
override def transformInfo(sym: Symbol, tp: Type): Type = tp match {
case ClassInfoType(parents, decls, clazz) =>
+ assert(sym == clazz, "not equal: " + sym + " " + clazz);
var parents1 = parents;
var decls1 = decls;
def addMember(member: Symbol): Symbol = {
if (decls1 eq decls) decls1 = new Scope(decls.toList);
- System.out.println("new member of " + clazz + ":" + member);//debug
+ if (settings.debug.value) log("new member of " + clazz + ":" + member.defString);//debug
decls1 enter member;
member
}
- def newGetter(field: Symbol): Symbol =
- clazz.newMethod(field.pos, nme.getterName(field.name))
- setFlag (field.flags & ~(PRIVATE | LOCAL | MUTABLE) | (ACCESSOR | DEFERRED | SYNTHETIC))
- setInfo MethodType(List(), field.info);
- def newSetter(field: Symbol): Symbol =
- clazz.newMethod(field.pos, nme.getterToSetter(nme.getterName(field.name)))
- setFlag (field.flags & ~(PRIVATE | LOCAL | MUTABLE) | (ACCESSOR | DEFERRED | SYNTHETIC))
- setInfo MethodType(List(field.info), UnitClass.tpe);
-
- if (clazz.isPackageClass) {
- for (val sym <- decls.elements) {
+ def addPackageClassMembers = {
+ for (val sym <- decls.toList) {
if (sym.isImplClass) {
- sym setFlag lateMODULE;
+ sym setFlag lateMODULE | notABSTRACT;
addMember(
clazz.newModule(sym.pos, sym.name.toTermName, sym.asInstanceOf[ClassSymbol])
setInfo sym.tpe)
}
}
- } else if (clazz hasFlag lateINTERFACE) {
+ }
+ def addLateInterfaceMembers = {
+ def newGetter(field: Symbol): Symbol =
+ clazz.newMethod(field.pos, nme.getterName(field.name))
+ setFlag (field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | DEFERRED | SYNTHETIC)
+ setInfo MethodType(List(), field.info);
+ def newSetter(field: Symbol): Symbol =
+ clazz.newMethod(field.pos, nme.getterToSetter(nme.getterName(field.name)))
+ setFlag (field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | DEFERRED | SYNTHETIC)
+ setInfo MethodType(List(field.info), UnitClass.tpe);
+ clazz.info;
val impl = implClass(clazz);
- assert(impl != NoSymbol, clazz);
- for (val member <- decls.toList) {
- if (!member.isMethod) {
- assert(member.isTerm && !member.hasFlag(DEFERRED));
- member.makeNotPrivate(clazz);
+ assert(impl != NoSymbol, "" + clazz + " " + flattenPhase.flatClasses + atPhase(flattenPhase)(clazz.owner.info.decls));
+ for (val member <- impl.info.decls.toList) {
+ if (!member.isMethod && !member.isModule && !member.isModuleVar)) {
+ assert(member.isTerm && !member.hasFlag(DEFERRED), member);
+ if (member.getter(impl) hasFlag PRIVATE) member.makeNotPrivate(clazz);
var getter = member.getter(clazz);
if (getter == NoSymbol) getter = addMember(newGetter(member));
- getter setFlag FINAL;
+ else getter setFlag (member getFlag MUTABLE);
if (!member.tpe.isInstanceOf[ConstantType]) {
var setter = member.setter(clazz);
- if (getter == NoSymbol) setter = addMember(newSetter(member));
- setter setFlag FINAL
+ if (setter == NoSymbol) setter = addMember(newSetter(member));
}
- }
- }
- } else if (clazz.isImplClass) {
- transformInfo(clazz.owner, clazz.owner.info);
- parents1 = List();
- decls1 = new Scope(decls.toList filter isForwarded)
- } else if (!parents.isEmpty) {
- parents1 = parents.head :: (parents.tail map toInterface);
+ } else if ((member hasFlag LIFTED) && !(member hasFlag PRIVATE)) {
+ member.expandName(clazz);
+ addMember(member.cloneSymbol(clazz));
+ }
+ }
+ }
+ def addMixedinMembers = {
for (val bc <- clazz.info.baseClasses.tail.takeWhile(parents.head.symbol !=)) {
if (bc.isImplClass) {
for (val member <- bc.info.decls.toList) {
- if (isForwarded(member) && (clazz.info.member(member.name).alternatives contains member)) {
- val member1 = member.cloneSymbol(clazz) setFlag MIXEDIN;
+ if (isForwarded(member) && !isStatic(member) &&
+ (clazz.info.member(member.name).alternatives contains member)) {
+ val member1 = addMember(member.cloneSymbol(clazz) setFlag MIXEDIN);
member1.asInstanceOf[TermSymbol] setAlias member;
+ }
+ }
+ } else if (bc.hasFlag(lateINTERFACE)) {
+ for (val member <- atPhase(phase.next)(bc.info.decls.toList)) {
+ if (member hasFlag ACCESSOR) {
+ val member1 = addMember(
+ member.cloneSymbol(clazz) setFlag (MIXEDIN | FINAL) resetFlag DEFERRED);
+ if (!member.isSetter)
+ member.tpe match {
+ case MethodType(List(), ConstantType(_)) =>
+ ;
+ case _ =>
+ addMember(
+ clazz.newValue(member.pos, nme.getterToLocal(member.name))
+ setFlag (LOCAL | PRIVATE | MIXEDIN | member.getFlag(MUTABLE))
+ setInfo member.tpe.resultType)
+ }
} else if (member hasFlag SUPERACCESSOR) {
- member.asInstanceOf[TermSymbol] setAlias rebindSuper(clazz, member.alias, bc);
- addMember(member)
+ val member1 = addMember(member.cloneSymbol(clazz)) setFlag MIXEDIN;
+ assert(member1.alias != NoSymbol, member1);
+ member1.asInstanceOf[TermSymbol] setAlias rebindSuper(clazz, member.alias, bc);
+ } else if (member.isMethod && member.sModule && !(member hasFlag LIFTED)) {
+ addMember(member.cloneSymbol(clazz) setFlag MIXEDIN)
}
}
}
}
}
- if ((parents1 eq parents) && (decls1 eq decls)) tp else ClassInfoType(parents, decls1, clazz)
+
+ if (clazz.isPackageClass) {
+ addPackageClassMembers
+ } else {
+ atPhase(phase.next)(clazz.owner.info);
+ if (clazz.isImplClass) {
+ parents1 = List();
+ decls1 = new Scope(decls.toList filter isForwarded)
+ } else if (!parents.isEmpty) {
+ parents1 = parents.head :: (parents.tail map toInterface);
+ if (!(clazz hasFlag INTERFACE)) addMixedinMembers
+ else if (clazz hasFlag lateINTERFACE) addLateInterfaceMembers
+ }
+ }
+ if (settings.debug.value && !clazz.isPackageClass) log("new defs of " + clazz + " = " + decls1);
+ decls1 = atPhase(phase.next)(new Scope(decls1.toList));//debug
+ if ((parents1 eq parents) && (decls1 eq decls)) tp
+ else ClassInfoType(parents1, decls1, clazz);
+
case MethodType(formals, restp) =>
- if (isForwarded(sym))
- MethodType(toInterface(sym.owner.thisType) :: formals, restp)
+ if (isForwarded(sym)) MethodType(toInterface(sym.owner.typeOfThis) :: formals, restp)
else tp
case _ =>
tp
@@ -152,95 +156,180 @@ abstract class Mixin extends InfoTransform {
protected def newTransformer(unit: CompilationUnit): Transformer = new MixinTransformer;
class MixinTransformer extends Transformer {
+ private var self: Symbol = _;
+ private var localTyper: analyzer.Typer = _;
+ private var enclInterface: Symbol = _;
+
+ private def preTransform(tree: Tree): Tree = {
+ val sym = tree.symbol;
+ tree match {
+ case Template(parents, body) =>
+ localTyper = typer.atOwner(tree, currentOwner);
+ tree
+ case DefDef(mods, name, tparams, List(vparams), tpt, rhs) if currentOwner.isImplClass =>
+ if (isForwarded(sym)) {
+ sym setFlag notOVERRIDE;
+ self = sym.newValue(sym.pos, nme.SELF)
+ setFlag (PARAM | SYNTHETIC)
+ setInfo toInterface(currentOwner.typeOfThis);
+ enclInterface = currentOwner.toInterface;
+ val selfdef = ValDef(self) setType NoType;
+ copy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs)
+ } else {
+ EmptyTree
+ }
+ case ValDef(_, _, _, _) if (currentOwner.isImplClass) =>
+ EmptyTree
+ case _ =>
+ tree
+ }
+ }
- var self: Symbol = _;
- var localTyper: analyzer.Typer = _;
+ private def selfRef(pos: int) = gen.Ident(self) setPos pos;
+
+ private def staticRef(sym: Symbol) = {
+ sym.owner.info;
+ if (sym.owner.sourceModule == NoSymbol)
+ assert(false, "" + sym.owner + " " + sym.owner.owner.info.decls);//debug
+ Select(gen.mkRef(sym.owner.sourceModule), sym);
+ }
private def addNewDefs(clazz: Symbol, stats: List[Tree]): List[Tree] = {
val newDefs = new ListBuffer[Tree];
def addDef(pos: int, tree: Tree): unit = {
- System.out.println("add new def to " + clazz + ": " + tree);
- newDefs += localTyper.typed(atPos(pos)(tree))
+ if (settings.debug.value) log("add new def to " + clazz + ": " + tree);
+ newDefs += localTyper.typed {
+ atPos(pos) {
+ tree
+ }
+ }
}
def position(sym: Symbol) =
if (sym.pos == Position.NOPOS) clazz.pos else sym.pos;
def addDefDef(sym: Symbol, rhs: List[Symbol] => Tree): unit =
addDef(position(sym), DefDef(sym, vparamss => rhs(vparamss.head)));
- if (!clazz.isImplClass) {
- atPhase(phase.next) {
- for (val sym <- clazz.info.decls.toList) {
- if (sym hasFlag MIXEDIN) {
- if (sym hasFlag SUPERACCESSOR) {
- addDefDef(sym, vparams =>
- Apply(Select(Super(clazz, nme.EMPTY.toTypeName), sym.alias), vparams map Ident))
- } else if (sym hasFlag ACCESSOR) {
- addDefDef(sym, vparams =>
- Select(This(clazz), sym.accessed))
- } else if (isForwarded(sym)) {
- addDefDef(sym, vparams =>
- Apply(staticRef(sym.alias), gen.This(clazz) :: (vparams map Ident)))
- } else {
- addDef(position(sym), ValDef(sym))
- }
+ def completeSuperAccessor(stat: Tree) = stat match {
+ case DefDef(mods, name, tparams, List(vparams), tpt, EmptyTree)
+ if (stat.symbol hasFlag SUPERACCESSOR) =>
+ assert(stat.symbol hasFlag MIXEDIN, stat);
+ val rhs1 =
+ localTyper.typed {
+ atPos(stat.pos) {
+ Apply(Select(Super(clazz, nme.EMPTY.toTypeName), stat.symbol.alias),
+ vparams map (vparam => Ident(vparam.symbol)))
+ }
+ }
+ copy.DefDef(stat, mods, name, tparams, List(vparams), tpt, rhs1)
+ case _ =>
+ assert(!(stat.symbol hasFlag SUPERACCESSOR), stat);
+ stat
+ }
+ var stats1 = stats;
+ if (clazz hasFlag lateINTERFACE) {
+ for (val sym <- clazz.info.decls.toList) {
+ if ((sym hasFlag SYNTHETIC) && (sym hasFlag ACCESSOR))
+ addDefDef(sym, vparamss => EmptyTree)
+ }
+ } else if (!clazz.isImplClass && !(clazz hasFlag INTERFACE)) {
+ for (val sym <- clazz.info.decls.toList) {
+ if (sym hasFlag MIXEDIN) {
+ if (sym hasFlag ACCESSOR) {
+ addDefDef(sym, vparams => {
+ val accessedRef = sym.tpe match {
+ case MethodType(List(), ConstantType(c)) => Literal(c)
+ case _ => Select(This(clazz), sym.accessed)
+ }
+ if (sym.isSetter) Assign(accessedRef, Ident(vparams.head)) else accessedRef})
+ } else if (sym.isModule && !(sym hasFlag LIFTED)) {
+ val vdef = refchecks.newModuleVarDef(sym);
+ addDef(position(sym), vdef);
+ addDef(position(sym), refchecks.newModuleAccessDef(sym, vdef.symbol));
+ } else if (!sym.isMethod) {
+ addDef(position(sym), ValDef(sym))
+ } else if (!(sym hasFlag SUPERACCESSOR)) {
+ assert(sym.alias != NoSymbol, sym);
+ addDefDef(sym, vparams =>
+ Apply(staticRef(sym.alias), gen.This(clazz) :: (vparams map Ident)))
}
}
}
+ stats1 = stats map completeSuperAccessor;
}
- if (newDefs.hasNext) stats ::: newDefs.toList else stats
+ if (newDefs.hasNext) stats1 ::: newDefs.toList else stats1
}
- override def transform(tree: Tree): Tree = {
- try { //debug
+ private def postTransform(tree: Tree): Tree = atPhase(phase.next) {
val sym = tree.symbol;
- val tree1 = tree match {
+ tree match {
case Template(parents, body) =>
- localTyper = typer.atOwner(tree, currentOwner);
- tree
- case DefDef(mods, name, tparams, List(vparams), tpt, rhs) =>
- if (isForwarded(sym)) {
- self = sym.newValue(sym.pos, nme.SELF)
- setFlag PARAM
- setInfo toInterface(currentOwner.thisType);
- val selfdef = ValDef(self) setType NoType;
- copy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs)
- } else if (currentOwner.isImplClass) {
- EmptyTree
- } else tree
- case ValDef(_, _, _, _) if (currentOwner.isImplClass) =>
- EmptyTree
- case Super(_, mix) if (mix == nme.EMPTY.toTypeName && currentOwner.isImplClass) =>
- atPos(tree.pos){
+ val parents1 = currentOwner.info.parents map (t => TypeTree(t) setPos tree.pos);
+ val body1 = addNewDefs(currentOwner, body);
+ copy.Template(tree, parents1, body1)
+ case Apply(Select(qual, _), args) =>
+ assert(sym != NoSymbol, tree);//debug
+ if (isStatic(sym)) {
+ assert(sym.isConstructor || currentOwner.enclClass.isImplClass, tree);
localTyper.typed {
- Select(Ident(self), sym.superAccessor(self.tpe.symbol))
- }
- }
- case Apply(Select(qual, _), args)
- if (isSelfRef(qual) && currentOwner.enclClass.isImplClass &&
- sym.owner.isImplClass && isStatic(sym)) =>
- atPos(tree.pos) {
- atPhase(phase.next) {
- localTyper.typed {
- Apply(staticRef(sym), Ident(self) :: args)
+ atPos(tree.pos) {
+ Apply(staticRef(sym), qual :: args)
}
}
+ } else tree
+ case This(_) if tree.symbol.isImplClass =>
+ assert(tree.symbol == currentOwner.enclClass, "" + tree.symbol + " " + currentOwner.enclClass);
+ selfRef(tree.pos)
+ case Select(qual @ Super(_, mix), name) =>
+ if (currentOwner.enclClass.isImplClass) {
+ if (mix == nme.EMPTY.toTypeName) {
+ val superAccName = enclInterface.expandedName(nme.superName(sym.name));
+ val superAcc = enclInterface.info.decl(superAccName) suchThat (.alias.==(sym));
+ assert(superAcc != NoSymbol, tree);//debug
+ localTyper.typedOperator {
+ atPos(tree.pos){
+ Select(selfRef(qual.pos), superAcc)
+ }
+ }
+ } else {
+ copy.Select(tree, selfRef(qual.pos), name)
+ }
+ } else {
+ if (mix == nme.EMPTY.toTypeName) tree
+ else copy.Select(tree, gen.This(currentOwner.enclClass) setPos qual.pos, name)
+ }
+ case Select(qual, name) if sym.owner.isImplClass && !isStatic(sym) =>
+ if (sym.isMethod) {
+ assert(sym hasFlag LIFTED, sym);
+ val sym1 = enclInterface.info.decl(sym.name);
+ assert(sym1 != NoSymbol && !(sym1 hasFlag OVERLOADED), sym);//debug
+ tree setSymbol sym1
+ } else {
+ val getter = sym.getter(enclInterface);
+ assert(getter != NoSymbol, "" + enclInterface + " " + sym);
+ localTyper.typed {
+ atPos(tree.pos) {
+ Apply(Select(qual, getter), List())
+ }
+ }
}
- case This(_) if (sym.isImplClass) =>
- atPos(tree.pos)(gen.Ident(self))
- case _ =>
- tree
- }
- val tree2 = super.transform(tree1);
- tree2 match {
- case Template(parents, body) =>
- copy.Template(tree2, parents, addNewDefs(currentOwner, body))
+ case Assign(Apply(lhs @ Select(qual, _), List()), rhs) =>
+ localTyper.typed {
+ atPos(tree.pos) {
+ Apply(Select(qual, lhs.symbol.setter(enclInterface)) setPos lhs.pos, List(rhs))
+ }
+ }
case _ =>
- tree2
+ tree
+ }
+ }
+
+ override def transform(tree: Tree): Tree = {
+ try { //debug
+ postTransform(super.transform(preTransform(tree)))
+ } catch {
+ case ex: Throwable =>
+ System.out.println("exception when traversing " + tree);
+ throw ex
}
- } catch {//debug
- case ex: Throwable =>
- System.out.println("exception when traversing " + tree);
- throw ex
- }
}
}
}