diff options
author | paltherr <paltherr@epfl.ch> | 2003-12-19 22:05:06 +0000 |
---|---|---|
committer | paltherr <paltherr@epfl.ch> | 2003-12-19 22:05:06 +0000 |
commit | 782063cf853062ee6467b0dc664b52a7d505ffe8 (patch) | |
tree | 0ec65867365a99d09f26c11abfe26abf0fb1d1cc | |
parent | 3d2b827dcc7ff027b1fad4bc39ea7ef1f9539769 (diff) | |
download | scala-782063cf853062ee6467b0dc664b52a7d505ffe8.tar.gz scala-782063cf853062ee6467b0dc664b52a7d505ffe8.tar.bz2 scala-782063cf853062ee6467b0dc664b52a7d505ffe8.zip |
- Moved phase AddConstructors before phase AddI...
- Moved phase AddConstructors before phase AddInterfaces
-rw-r--r-- | sources/scalac/CompilerPhases.java | 14 | ||||
-rw-r--r-- | sources/scalac/transformer/AddInterfaces.java | 515 | ||||
-rw-r--r-- | sources/scalac/transformer/AddInterfacesPhase.java | 5 |
3 files changed, 214 insertions, 320 deletions
diff --git a/sources/scalac/CompilerPhases.java b/sources/scalac/CompilerPhases.java index 9ba1198626..2993d98469 100644 --- a/sources/scalac/CompilerPhases.java +++ b/sources/scalac/CompilerPhases.java @@ -32,9 +32,9 @@ public class CompilerPhases { public final PhaseDescriptor EXPLICITOUTER; public final PhaseDescriptor ADDACCESSORS; public final PhaseDescriptor TAILCALL; + public final PhaseDescriptor ADDCONSTRUCTORS; public final PhaseDescriptor ADDINTERFACES; public final PhaseDescriptor EXPANDMIXIN; - public final PhaseDescriptor ADDCONSTRUCTORS; public final PhaseDescriptor MAKEBOXINGEXPLICIT; public final PhaseDescriptor ERASURE; public final PhaseDescriptor GENMSIL; @@ -58,9 +58,9 @@ public class CompilerPhases { protected Class EXPLICITOUTER_PHASE() { return scalac.transformer.ExplicitOuterClassesPhase.class; } protected Class ADDACCESSORS_PHASE() { return scalac.transformer.AddAccessorsPhase.class; } protected Class TAILCALL_PHASE() { return scalac.transformer.TailCallPhase.class; } + protected Class ADDCONSTRUCTORS_PHASE() { return scalac.transformer.AddConstructorsPhase.class; } protected Class ADDINTERFACES_PHASE() { return scalac.transformer.AddInterfacesPhase.class; } protected Class EXPANDMIXIN_PHASE() { return scalac.transformer.ExpandMixinsPhase.class; } - protected Class ADDCONSTRUCTORS_PHASE() { return scalac.transformer.AddConstructorsPhase.class; } protected Class ERASURE_PHASE() { return scalac.transformer.ErasurePhase.class; } protected Class GENMSIL_PHASE() { return scalac.backend.msil.GenMSILPhase.class; } protected Class GENJVM_PHASE() { return scalac.backend.jvm.GenJVMPhase.class; } @@ -127,6 +127,11 @@ public class CompilerPhases { "add tail-calls", "added tail-calls", TAILCALL_PHASE()), + this.ADDCONSTRUCTORS = new PhaseDescriptor( + "addconstructors", + "add explicit constructor for each class", + "added constructors", + ADDCONSTRUCTORS_PHASE()), this.ADDINTERFACES = new PhaseDescriptor( "addinterfaces", "add one interface per class", @@ -137,11 +142,6 @@ public class CompilerPhases { "expand mixins by code copying", "expanded mixins", EXPANDMIXIN_PHASE()), - this.ADDCONSTRUCTORS = new PhaseDescriptor( - "addconstructors", - "add explicit constructor for each class", - "added constructors", - ADDCONSTRUCTORS_PHASE()), this.MAKEBOXINGEXPLICIT = new PhaseDescriptor( "boxing", "makes boxing explicit", diff --git a/sources/scalac/transformer/AddInterfaces.java b/sources/scalac/transformer/AddInterfaces.java index 76326afd5c..b242500663 100644 --- a/sources/scalac/transformer/AddInterfaces.java +++ b/sources/scalac/transformer/AddInterfaces.java @@ -13,14 +13,20 @@ package scalac.transformer; -import scalac.*; -import ch.epfl.lamp.util.*; -import scalac.ast.*; -import scalac.symtab.*; -import scalac.util.*; -import Tree.*; - -import java.util.*; +import java.util.Map; +import java.util.HashMap; + +import scalac.Global; +import scalac.ast.GenTransformer; +import scalac.ast.Tree; +import scalac.ast.Tree.Template; +import scalac.ast.TreeGen; +import scalac.ast.TreeList; +import scalac.symtab.Type; +import scalac.symtab.Scope; +import scalac.symtab.Symbol; +import scalac.symtab.SymbolSubstTypeMap; +import scalac.util.Debug; /** * Add, for each class, an interface with the same name, to be used @@ -38,344 +44,233 @@ import java.util.*; * @author Michel Schinz * @version 1.0 */ +public class AddInterfaces extends GenTransformer { -class AddInterfaces extends Transformer { - protected AddInterfacesPhase phase; - protected Definitions defs; - - public AddInterfaces(Global global, AddInterfacesPhase phase) { - super(global); - this.phase = phase; - this.defs = global.definitions; - } + //######################################################################### + // Private Fields - protected LinkedList/*<Pair<Symbol,Symbol>>*/ ownerSubstStack = - new LinkedList(); - protected Pair/*<Symbol,Symbol>*/ ownerSubst = null; - protected SymbolSubstTypeMap typeSubst = null; - protected Type.SubstThisMap thisTypeSubst = null; + /** The AddInterface phase */ + private final AddInterfacesPhase phase; - protected LinkedList/*<List<Tree>>*/ bodyStack = new LinkedList(); + /** The current class (null is none) */ + private Symbol clasz; - public Tree[] transform(Tree[] trees) { - List newTrees = new ArrayList(); + /** The current member (null is none) */ + private Symbol member; - bodyStack.addFirst(newTrees); + /** The current class substitution (null is none) */ + private Type.Map classSubst; - for (int i = 0; i < trees.length; ++i) - newTrees.add(transform(trees[i])); + /** The current parameter substitution (null is none) */ + private SymbolSubstTypeMap paramSubst; - bodyStack.removeFirst(); + //######################################################################### + // Public Constructors - return (Tree[]) newTrees.toArray(new Tree[newTrees.size()]); + /** Initializes this instance. */ + public AddInterfaces(Global global, AddInterfacesPhase phase) { + super(global); + this.phase = phase; } - public Tree transform(Tree tree) { - // Update tree type, to take into account the new (type) - // symbols of enclosing classes / methods. - Type newTp = tree.getType(); - if (typeSubst != null) newTp = typeSubst.apply(newTp); - if (thisTypeSubst != null) newTp = thisTypeSubst.apply(newTp); - tree.setType(newTp); - - if (tree.definesSymbol() && !(tree instanceof ClassDef)) { - // Update symbol's owner, if needed. - Symbol sym = tree.symbol(); - if (ownerSubst != null && ownerSubst.fst == sym.owner()) - sym.setOwner((Symbol)ownerSubst.snd); - - // Update symbol's type. Do that only for symbols which do - // not belong to a class, since the type of these (i.e. - // class members) has been changed during cloning - // operation. - if (! (sym.owner().isClass() || thisTypeSubst == null)) - sym.updateInfo(typeSubst.apply(sym.info())); - } + //######################################################################### + // Public Methods + /** Transforms the given symbol. */ + public Symbol getSymbolFor(Tree tree) { switch (tree) { - case ClassDef(_,_,_,_,_,_): { - Symbol sym = tree.symbol(); - if (phase.needInterface(sym)) { - ClassDef classDef = (ClassDef)tree; - Symbol ifaceSym = sym; - Symbol classSym = phase.getClassSymbol(ifaceSym); - - List/*<Tree>*/ enclosingBody = (List)bodyStack.getFirst(); - enclosingBody.add(makeInterface(classDef)); - - typeSubst = phase.getClassSubst(classSym); - Tree newTree = makeClass(classDef); - typeSubst = null; - - return newTree; - } else - return super.transform(tree); - } - - case DefDef(int mods, - Name name, - AbsTypeDef[] tparams, - ValDef[][] vparams, - Tree tpe, - Tree rhs): { - Symbol sym = tree.symbol(); - Tree newTree; - - Symbol owner; - if (sym.isConstructor()) - owner = sym.constructorClass(); - else - owner = sym.owner(); - - if (owner.isClass() && phase.needInterface(owner)) { - Symbol classOwner = phase.getClassSymbol(owner); - Map ownerMemberMap = phase.getClassMemberMap(classOwner); - Symbol newSym = (Symbol)ownerMemberMap.get(sym); - assert newSym != null - : Debug.show(sym) + " not in " + ownerMemberMap; - - global.nextPhase(); - typeSubst.insertSymbol(sym.typeParams(), newSym.typeParams()); - if (!sym.isConstructor()) - typeSubst.insertSymbol(sym.valueParams(), newSym.valueParams()); - global.prevPhase(); - - pushOwnerSubst(sym, newSym); - - newTree = gen.DefDef(newSym, transform(rhs)); - - popOwnerSubst(); - - typeSubst.removeSymbol(sym.valueParams()); - typeSubst.removeSymbol(sym.typeParams()); - } else - newTree = super.transform(tree); - return newTree; - } - - case Return(Tree expr): { - Symbol sym = tree.symbol(); - Symbol owner = sym.owner(); - if (owner.isClass() && phase.needInterface(owner)) { - Symbol classOwner = phase.getClassSymbol(owner); - Map ownerMemberMap = phase.getClassMemberMap(classOwner); - Symbol newSym = (Symbol)ownerMemberMap.get(sym); - assert newSym != null - : Debug.show(sym) + " not in " + ownerMemberMap; - return gen.Return(tree.pos, newSym, transform(expr)); - } else - return super.transform(tree); - } - - case This(_): { - // Use class symbol for references to "this". - Symbol classThisSym = phase.getClassSymbol(tree.symbol()); - return gen.This(tree.pos, classThisSym); - } - - case Super(_, _): { - // Use class symbol for references to "super". - Symbol classSuperSym = phase.getClassSymbol(tree.symbol()); - return gen.Super(tree.pos, classSuperSym); + case Return(_): + return member; + case This(_): + case Super(_, _): + return clasz; + case Select(Super(_, _), _): + Symbol symbol = tree.symbol(); + if (symbol.isInitializer()) return getClassMember(symbol); + return getClassMember(symbol, true); + case Select(_, _): + Symbol symbol = tree.symbol(); + if (symbol.isInitializer()) return getClassMember(symbol); + return symbol; + case Ident(_): + Symbol symbol = tree.symbol(); + if (symbol.isInitializer()) return getClassMember(symbol); + if (symbol.isParameter()) return getClassVParam(symbol); + return symbol; + default: + return tree.symbol(); } + } - case Select(Super(_, _), _): { - // Use class member symbols for references to "super". + /** Transforms the given type. */ + public Type transform(Type type) { + if (classSubst != null) type = classSubst.apply(type); + if (paramSubst != null) type = paramSubst.apply(type); + return type; + } - Symbol sym = tree.symbol(); - Symbol classOwner = phase.getClassSymbol(sym.owner()); - Map ownerMemberMap = phase.getClassMemberMap(classOwner); - if (ownerMemberMap != null && ownerMemberMap.containsKey(sym)) { - Tree qualifier = transform(((Select)tree).qualifier); - Symbol newSym = (Symbol)ownerMemberMap.get(sym); - return gen.Select(tree.pos, qualifier, newSym); - } else - return super.transform(tree); - } + /** Transforms the given trees. */ + public Tree[] transform(Tree[] trees) { + if (member != null) return super.transform(trees); + TreeList list = new TreeList(); + for (int i = 0; i < trees.length; i++) template(list, trees[i]); + return list.toArray(); + } - case Select(Tree qualifier, _): { - Symbol sym = tree.symbol(); - if (sym.isConstructor()) { - // If the constructor now refers to the interface - // constructor, use the class constructor instead. - Symbol clsSym = sym.constructorClass(); - if (phase.needInterface(clsSym)) { - Symbol realClsSym = phase.getClassSymbol(clsSym); - Map memMap = phase.getClassMemberMap(realClsSym); - assert memMap != null - : Debug.show(clsSym) + " " + Debug.show(realClsSym); - return gen.Select(tree.pos, qualifier, (Symbol)memMap.get(sym)); - } else - return super.transform(tree); - } else { - qualifier = transform(qualifier); - Symbol owner = sym.owner(); - if (owner.isClass() - && owner.isJava() && !owner.isInterface() - && owner != defs.ANY_CLASS - && owner != defs.ANYREF_CLASS - && owner != defs.JAVA_OBJECT_CLASS) { - Type qualifierType = qualifier.getType().bound(); - if (phase.needInterface(qualifierType.symbol())) { - Type castType = qualifierType.baseType(owner); - qualifier = gen.mkAsInstanceOf(qualifier, castType); - } - } - return copy.Select(tree, sym, qualifier); + /** Transforms the given tree. */ + public Tree transform(Tree tree) { + switch (tree) { + case ValDef(_, _, _, _): + case LabelDef(_, _, _): + Symbol symbol = tree.symbol(); + if (symbol.owner() != member) { + symbol.setOwner(member); + symbol.updateInfo(transform(symbol.info())); } - } - - case Ident(_): { - Symbol sym = tree.symbol(); - if (sym.isConstructor()) { - // If the constructor now refers to the interface - // constructor, use the class constructor instead. - Symbol clsSym = sym.constructorClass(); - if (phase.needInterface(clsSym)) { - Symbol realClsSym = phase.getClassSymbol(clsSym); - Map memMap = phase.getClassMemberMap(realClsSym); - assert memMap != null - : Debug.show(clsSym) + " " + Debug.show(realClsSym); - assert memMap.containsKey(sym) - : Debug.show(sym) + " not in " + memMap; - return gen.Ident(tree.pos, (Symbol)memMap.get(sym)); - } else - return super.transform(tree); - } else if (typeSubst != null) { - Symbol newSym = (Symbol)typeSubst.lookupSymbol(tree.symbol()); - if (newSym != null) - return gen.Ident(tree.pos, newSym); - else - return super.transform(tree); - } else { - return super.transform(tree); + return super.transform(tree); + case Select(Tree qualifier, _): + Type prefix = qualifier.type(); + qualifier = transform(qualifier); + Symbol symbol = getSymbolFor(tree); + if (symbol.isJava() && !symbol.owner().isInterface()) { + if (qualifier.type().widen().symbol().isInterface()) { + Type baseType = prefix.baseType(symbol.owner()); + assert baseType != Type.NoType: tree; + qualifier = gen.mkAsInstanceOf(qualifier, baseType); + } } + return gen.Select(tree.pos, qualifier, symbol); + default: + return super.transform(tree); } + } - case New(Template templ): { - Tree.New newTree = (Tree.New)super.transform(tree); - Tree.Apply parent = (Tree.Apply)newTree.templ.parents[0]; - Symbol ifaceSym = TreeInfo.methSymbol(parent).type().resultType().symbol(); - if (phase.needInterface(ifaceSym)) { - Map clsMap = new HashMap(); - Symbol classSym = phase.getClassSymbol(ifaceSym); - clsMap.put(ifaceSym, classSym); - clsMap.put(ifaceSym.primaryConstructor(), classSym.primaryConstructor()); - - SymbolSubstTypeMap clsSubst = - new SymbolSubstTypeMap(clsMap, Collections.EMPTY_MAP); + //######################################################################### + // Private Methods - newTree.setType(clsSubst.apply(newTree.type)); - newTree.templ.setType(clsSubst.apply(newTree.templ.type)); - parent.setType(clsSubst.apply(parent.type)); - parent.fun.setType(clsSubst.apply(parent.fun.type)); + /** Transforms the given template and adds it to given list. */ + private void template(TreeList trees, Tree tree) { + switch (tree) { + case Empty: + return; + case PackageDef(_, _): + trees.append(super.transform(tree)); + return; + case ClassDef(_, _, _, _, _, Template(_, Tree[] body)): + TreeList list = new TreeList(transform(body)); + this.clasz = tree.symbol(); + Map methods = new HashMap(); + if (phase.needInterface(clasz)) { + Symbol clone = phase.getClassSymbol(clasz); + trees.append(getClassTree(clasz, list, methods)); + list = new TreeList(); + this.classSubst = new Type.SubstThisMap(clasz, clone); + this.paramSubst = phase.getClassSubst(clone); + this.clasz = clone; } - return newTree; - } - - case Template(_,_): { - Symbol sym = tree.symbol(); - if (sym != Symbol.NONE) { - Symbol newDummySymbol = sym.cloneSymbol(); - pushOwnerSubst(sym, newDummySymbol); - Tree newTemplate = super.transform(tree); - popOwnerSubst(); - return newTemplate; - } else - return super.transform(tree); - } - + for (int i = 0; i < body.length; i++) member(methods, body[i]); + trees.append(getClassTree(clasz, list, methods)); + assert methods.isEmpty(): Debug.show(methods.keySet().toArray()); + this.paramSubst = null; + this.classSubst = null; + this.clasz = null; + return; + case DefDef(_, _, _, _, _, _): + return; + case ValDef(_, _, _, _): + if (tree.symbol().owner().isPackage()) trees.append(tree); + return; default: - return super.transform(tree); + throw Debug.abort("illegal tree", tree); } } - protected Tree makeInterface(ClassDef classDef) { - Template classImpl = classDef.impl; - Tree[] classBody = classImpl.body; - TreeList ifaceBody = new TreeList(); - - for (int i = 0; i < classBody.length; ++i) { - Tree t = classBody[i]; - Symbol tSym = t.symbol(); - - if (!t.definesSymbol() || !phase.memberGoesInInterface(tSym)) - continue; - - if (tSym.isClass()) - ifaceBody.append(transform(new Tree[] { t })); - else if (tSym.isType()) - ifaceBody.append(t); - else if (tSym.isMethod()) - ifaceBody.append(gen.DefDef(tSym, Tree.Empty)); - else - throw Debug.abort("don't know what to do with this ", t); + /** + * Transforms the given class member. Methods with a non-empty + * body are added to the given method map. All other members are + * dropped. + */ + private void member(Map methods, Tree tree) { + switch (tree) { + case ClassDef(_, _, _, _, _, _): + return; + case DefDef(_, _, _, _, _, Tree rhs): + if (rhs == Tree.Empty) return; + Symbol symbol = tree.symbol(); + this.member = getClassMember(symbol); + if (member != symbol) { + paramSubst.insertSymbol( + symbol.typeParams(), member.nextTypeParams()); + paramSubst.insertSymbol( + symbol.valueParams(), member.nextValueParams()); + } + methods.put(member, gen.DefDef(member, transform(rhs))); + if (member != symbol) { + paramSubst.removeSymbol(symbol.valueParams()); + paramSubst.removeSymbol(symbol.typeParams()); + } + this.member = null; + return; + case ValDef(_, _, _, Tree rhs): + assert rhs == Tree.Empty: tree; + return; + default: + throw Debug.abort("illegal tree", tree); } - - return gen.ClassDef(classDef.symbol(), ifaceBody.toArray()); } - protected Tree makeClass(ClassDef classDef) { - Symbol ifaceSym = classDef.symbol(); - Symbol classSym = phase.getClassSymbol(ifaceSym); - - TreeList newClassBody = new TreeList(); - Template classImpl = classDef.impl; - Tree[] classBody = classImpl.body; - - Map classMemberMap = phase.getClassMemberMap(classSym); - - assert thisTypeSubst == null; - thisTypeSubst = new Type.SubstThisMap(ifaceSym, classSym); - - for (int i = 0; i < classBody.length; ++i) { - Tree t = classBody[i]; - Symbol tSym = t.symbol(); - - if (t.definesSymbol() && !(classMemberMap.containsKey(tSym) - || tSym.isConstructor())) - continue; - - Tree newT = transform(t); - - if (t.definesSymbol() && classMemberMap.containsKey(tSym)) - newT.setSymbol((Symbol)classMemberMap.get(tSym)); - - newClassBody.append(newT); + /** + * Returns the tree of the given class whose body is built by + * adding to the given body the class members. Non-abstract + * methods are removed from the given method map. All other + * members are generated from their symbol. + */ + private Tree getClassTree(Symbol clasz, TreeList body, Map methods) { + Scope members = clasz.nextInfo().members(); + for (Scope.SymbolIterator i = members.iterator(true); i.hasNext(); ) { + Symbol member = i.next(); + if (!member.isTerm()) continue; + body.append(getMemberTree(member, methods)); } - - thisTypeSubst = null; - - Tree[] newParents = Tree.cloneArray(transform(classImpl.parents), 1); - global.nextPhase(); - Type ifaceType = classSym.parents()[newParents.length - 1]; - global.prevPhase(); - newParents[newParents.length - 1] = - gen.mkPrimaryConstr(classDef.pos, ifaceType); - - Symbol local = classDef.impl.symbol(); - local.setOwner(classSym); - return gen.ClassDef(classSym, newParents, local, newClassBody.toArray()); + return gen.ClassDef(clasz, body.toArray()); } - protected Tree[][] extractParentArgs(Tree[] parents) { - Tree[][] pArgs = new Tree[parents.length][]; - for (int i = 0; i < parents.length; ++i) { - switch(parents[i]) { - case Apply(_, Tree[] args): pArgs[i] = transform(args); break; - default: throw Debug.abort("unexpected parent constr. ", parents[i]); - } - } - return pArgs; + /** + * Returns the tree of the given member. Non-abstract methods are + * removed from the given method map. All other members are + * generated from their symbol. + */ + private Tree getMemberTree(Symbol member, Map methods) { + if (!member.isMethod()) return gen.ValDef(member, Tree.Empty); + if (member.isDeferred()) return gen.DefDef(member, Tree.Empty); + Tree method = (Tree)methods.remove(member); + assert method != null: Debug.show(member); + return method; } - protected void pushOwnerSubst(Symbol from, Symbol to) { - ownerSubstStack.addFirst(ownerSubst); - ownerSubst = new Pair(from, to); + /** Returns the symbol of given parameter in current class. */ + private Symbol getClassVParam(Symbol vparam) { + if (paramSubst == null) return vparam; + Symbol clone = (Symbol)paramSubst.lookupSymbol(vparam); + assert clone != null: Debug.show(vparam, " - ", clasz, " - ", member); + return clone; } - protected void popOwnerSubst() { - ownerSubst = (Pair)ownerSubstStack.removeFirst(); + /** Returns the symbol of given member in current class. */ + private Symbol getClassMember(Symbol member) { + return getClassMember(member, false); + } + // !!! Try to remove version with lazy argument. It is currently + // needed for super calls to abstract method (possible in mixins). + private Symbol getClassMember(Symbol member, boolean lazy) { + Symbol owner = member.owner(); + assert owner.isClass(): Debug.show(member); + if (!phase.needInterface(owner)) return member; + Symbol clasz = phase.getClassSymbol(owner); + Symbol clone = (Symbol)phase.getClassMemberMap(clasz).get(member); + assert clone != null || lazy: Debug.show(member, " not in ", clasz); + return clone != null ? clone : member; } + //######################################################################### } diff --git a/sources/scalac/transformer/AddInterfacesPhase.java b/sources/scalac/transformer/AddInterfacesPhase.java index c878742737..c91274df78 100644 --- a/sources/scalac/transformer/AddInterfacesPhase.java +++ b/sources/scalac/transformer/AddInterfacesPhase.java @@ -70,7 +70,7 @@ public class AddInterfacesPhase extends Phase { while (oldMembersIt.hasNext()) { Symbol member = oldMembersIt.next(); - if (!memberGoesInInterface(member)) + if (!memberGoesInInterface(member) || member.isInitializer()) continue; if (member.isPrivate()) { @@ -128,8 +128,7 @@ public class AddInterfacesPhase extends Phase { } protected boolean memberGoesInInterface(Symbol member) { - return member.isType() - || (member.isMethod() && !member.isConstructor()); + return member.isType() || member.isMethod(); } protected Type removeValueParams(Type tp) { |