From 858b174325c75316f5f838ce5876ac71514d9266 Mon Sep 17 00:00:00 2001 From: paltherr Date: Tue, 25 Nov 2003 12:38:05 +0000 Subject: - Modified to use new GetTreeCloner - Added a transformInfo - Fixed some problems with calls via super --- sources/scalac/transformer/ExpandMixins.java | 164 ++++++++++------------ sources/scalac/transformer/ExpandMixinsPhase.java | 51 ++++--- 2 files changed, 111 insertions(+), 104 deletions(-) diff --git a/sources/scalac/transformer/ExpandMixins.java b/sources/scalac/transformer/ExpandMixins.java index 3134858db9..2378fbaa44 100644 --- a/sources/scalac/transformer/ExpandMixins.java +++ b/sources/scalac/transformer/ExpandMixins.java @@ -22,7 +22,7 @@ import scalac.ast.Tree; import scalac.ast.Tree.Template; import scalac.ast.TreeList; import scalac.ast.TreeGen; -import scalac.ast.TreeCloner; +import scalac.ast.GenTreeCloner; import scalac.ast.TreeSymbolCloner; import scalac.ast.Transformer; import scalac.symtab.Modifiers; @@ -78,7 +78,7 @@ public class ClassExpander { this.gen = global.treeGen; this.clasz = clasz; this.parents = Type.cloneArray(clasz.parents()); - this.members = clasz.members().cloneScope(); + this.members = clasz.members(); // !!! .cloneScope(); this.template = gen.Template(template.pos, template.symbol(), Tree.cloneArray(template.parents), template.body); this.body = new LinkedList(); @@ -86,23 +86,31 @@ public class ClassExpander { this.cloner = new SymbolCloner( global.freshNameCreator, new HashMap(), map.getSymbols()); this.state = parents.length; + + this.mixinMemberCloner = new MixinMemberCloner(this); + this.superFixer = new SuperFixer(global); } //######################################################################## // Public Methods + // !!! remove this.parents + /** Inlines the ith mixin with given type, interface and body. */ public void inlineMixin(int i, Type type, Symbol iface, Template impl) { assert 0 < i && i < state : "state = " + state + ", i = " + i; switch (parents[i]) { case TypeRef(Type prefix, Symbol mixin, Type[] args): + // relpace "This/Super(mixin)" by "This/Super(clasz)" map.insertSymbol(mixin, clasz); + // owner of inlined value parameters and constructor is "clasz" cloner.owners.put(mixin.primaryConstructor(), clasz); - inlineMixinTParams(type); + // map mixin type parameters to mixin type arguments + map.insertType(type.symbol().typeParams(), type.typeArgs()); Tree.Apply constr = (Tree.Apply)template.parents[i]; Symbol[] vparams = mixin.valueParams(); inlineMixinVParams(vparams, constr.args, 0); - handleMixinInterfaceMembers(mixin); - inlineMixinMembers(mixin.nextInfo().members(), impl, vparams.length); + createMixedInMemberSymbols(mixin.nextInfo().members()); + inlineMixedInCode(impl, vparams.length); parents[i] = Type.TypeRef(prefix, iface, args); template.parents[i] = gen.mkPrimaryConstr(constr.pos, parents[i]); state = i; @@ -119,16 +127,19 @@ public class ClassExpander { switch (tree) { case Select(Super(_, _), _): Symbol symbol = map.lookupSymbol(tree.symbol()); - if (symbol != null) - return gen.Select(gen.This(tree.pos, clasz), symbol); + if (symbol != null) { + Tree qualifier = gen.This(tree.pos, clasz); + assert qualifier.type().baseType(symbol.owner()) != Type.NoType: tree; // !!! + return gen.Select(qualifier, symbol); + } } return super.transform(tree); } }; - body.addAll(Arrays.asList(superFixer.transform(template.body))); + body.addAll(Arrays.asList(this.superFixer.transform( +superFixer.transform(template.body)))); template.body = (Tree[])body.toArray(new Tree[body.size()]); // !!! *1 fix ExpandMixinsPhase.transformInfo and remove next line - clasz.updateInfo(Type.compoundType(parents, members, clasz)); state = 0; return template; } @@ -136,16 +147,6 @@ public class ClassExpander { //######################################################################## // Private Methods - private void inlineMixinTParams(Type type) { - switch (type) { - case TypeRef(Type prefix, Symbol symbol, Type[] args): - map.insertType(symbol.typeParams(), args); - return; - default: - throw Debug.abort("illegal case", type); - } - } - private void inlineMixinVParams(Symbol[] params, Tree[] args, int fstPos) { for (int i = 0; i < params.length; i++) { Symbol member = cloner.cloneSymbol(params[i], true); @@ -153,6 +154,7 @@ public class ClassExpander { member.flags |= Modifiers.PRIVATE; members.enter(member); } + // !!! remove double loop // We need two loops because parameters may appear in their types. for (int i = 0; i < params.length; i++) { Symbol member = map.lookupSymbol(params[i]); @@ -161,45 +163,7 @@ public class ClassExpander { } } - // !!! This is just rapid fix. Needs to be reviewed. - private void handleMixinInterfaceMembers(Symbol mixin) { - Type[] parents = mixin.info().parents(); - //assert parents.length == 2: Debug.show(mixin) +" -- "+ mixin.info(); - for (int i = 1; i < parents.length; i++) - handleMixinInterfaceMembersRec(parents[i].symbol()); - } - private void handleMixinInterfaceMembersRec(Symbol interfase) { - handleMixinInterfaceMembersAux(interfase.nextInfo().members()); - Type[] parents = interfase.parents(); - for (int i = 0; i < parents.length; i++) { - Symbol clasz = parents[i].symbol(); - if (clasz.isInterface()) handleMixinInterfaceMembersRec(clasz); - } - } - private void handleMixinInterfaceMembersAux(Scope symbols) { - for (SymbolIterator i = symbols.iterator(true); i.hasNext();) { - Symbol member = i.next(); - if (!member.isAbstractType()) continue; - // !!! use same trick as in erasure? - //Symbol clone = member.cloneSymbol(clasz); - //clone.setInfo(clasz.thisType().memberInfo(member)); - //Symbol subst = clasz.thisType().memberType(clone).symbol(); - Symbol subst = clasz.thisType().memberType(member).symbol(); - if (subst == member) continue; - Type subst1 = map.lookupType(member); - assert subst1 == null || subst1.symbol() == subst: - Debug.show(member," -> ",subst," + ",subst1); - if (subst1 == null) { - Type prefix = Type.localThisType; - // compute outer type links of subst - Type[] args = Symbol.type(subst.owner().typeParams()); - args = Type.asSeenFrom(args, clasz.thisType(), subst.owner()); - map.insertType(member, Type.TypeRef(prefix, subst, args)); - } - } - } - - private void inlineMixinMembers(Scope symbols, Template mixin, int fstPos) { + private void createMixedInMemberSymbols(Scope symbols) { // The map names is used to implement an all or nothing // strategy for overloaded symbols. Map/**/ names = new HashMap(); @@ -223,46 +187,72 @@ public class ClassExpander { if (member == null) continue; member.setType(map.applyParams(member.type())); } + } + + private void inlineMixedInCode(Template mixin, int fstPos) { cloner.owners.put(mixin.symbol(), template.symbol()); - final Set clones = new HashSet(); - TreeSymbolCloner mixinSymbolCloner = new TreeSymbolCloner(cloner) { - public Symbol cloneSymbol(Symbol symbol) { - Symbol clone = super.cloneSymbol(symbol); - clones.add(clone); - return clone; - } - }; - TreeCloner mixinTreeCloner = new TreeCloner(global, map) { - public Tree transform(Tree tree) { - switch (tree) { - case Select(Super(_, _), _): - Tree qualifier = ((Tree.Select)tree).qualifier; - qualifier = gen.Super(qualifier.pos, clasz); - Symbol symbol = tree.symbol().overridingSymbol(parents[0]); - assert symbol != Symbol.NONE: Debug.show(tree.symbol()); - return gen.Select(tree.pos, qualifier, symbol); - default: - return super.transform(tree); - } - } - }; int pos = 0; for (int i = 0; i < mixin.body.length; i++) { Tree tree = mixin.body[i]; // Inline local code and members whose symbol has been cloned. if (!tree.definesSymbol() || map.lookupSymbol(tree.symbol()) != null) { - mixinSymbolCloner.traverse(tree); - for (Iterator j = clones.iterator(); j.hasNext();) { - Symbol clone = (Symbol)j.next(); - clone.setType(map.apply(clone.type())); - } - clones.clear(); - body.add(fstPos + pos, mixinTreeCloner.transform(tree)); + body.add(fstPos + pos, mixinMemberCloner.transform(tree)); ++pos; } } } + private final GenTreeCloner mixinMemberCloner; + + private class MixinMemberCloner extends GenTreeCloner { + public MixinMemberCloner(ClassExpander expander) { + super(expander.global, expander.map, expander.cloner); + } + + public Symbol getSymbolFor(Tree tree) { + switch (tree) { + case Select(Super(_, _), _): + // !!! check + global.nextPhase(); + Symbol symbol = tree.symbol().overridingSymbol(parents[0]); + global.prevPhase(); + assert !symbol.isNone(): tree; + return symbol; + case Super(_, _): + case This(_): + return clasz; + default: + return super.getSymbolFor(tree); + } + } + + } + + private final Transformer superFixer; + + private class SuperFixer extends Transformer { + private final Type parent; + + public SuperFixer(Global global) { + super(global); + this.parent = clasz.parents()[0]; + } + public Tree transform(Tree tree) { + if (tree.definesSymbol() && tree.symbol().owner().isClass()) + return tree; + switch (tree) { + case Select(Super(_, _), _): + Tree qualifier = ((Tree.Select)tree).qualifier; + qualifier = gen.Super(qualifier.pos, clasz); + Symbol symbol = tree.symbol().overridingSymbol(parent); + assert !symbol.isNone(): tree + " -- " + parent + " -- " + Debug.show(clasz.parents()) + " -- " + Debug.show(clasz); + return gen.Select(tree.pos, qualifier, symbol); + default: + return super.transform(tree); + } + } + } + //######################################################################## } diff --git a/sources/scalac/transformer/ExpandMixinsPhase.java b/sources/scalac/transformer/ExpandMixinsPhase.java index ce4be8d368..01a99aa897 100644 --- a/sources/scalac/transformer/ExpandMixinsPhase.java +++ b/sources/scalac/transformer/ExpandMixinsPhase.java @@ -20,9 +20,9 @@ import scalac.ast.Tree; import scalac.ast.Tree.Template; import scalac.ast.Traverser; import scalac.ast.Transformer; +import scalac.symtab.Scope; import scalac.symtab.Symbol; import scalac.symtab.Type; -import scalac.checkers.*; import scalac.util.Debug; // TODO do not copy hidden members which are not accessible via @@ -71,30 +71,45 @@ public class ExpandMixinsPhase extends Phase { public void apply(Unit[] units) { collector.traverse(units); expander.apply(units); - assert templates.isEmpty() : templates.keySet(); + assert templates.isEmpty(): templates.keySet(); } public Type transformInfo(Symbol symbol, Type type) { // !!! make this work and remove *1 in ClassExpander // if (!symbol.isJava() && symbol.isClass() && !symbol.isInterface()) // type = getExpandedTemplate(symbol).type(); + if (symbol.isClass() && !symbol.isInterface()) { + switch (type) { + case CompoundType(Type[] parents, Scope members): + Type[] types = parents; + for (int i = 1; i < parents.length; i++) { + switch (parents[i]) { + case TypeRef(Type prefix, Symbol parent, Type[] args): + if (parent.isInterface()) continue; + if (types == parents) types = Type.cloneArray(parents); + parent = (Symbol)interfaces.get(parent); + assert parent != null: parents[i]; + types[i] = Type.TypeRef(prefix, parent, args); + continue; + default: + throw Debug.abort("illegal case", parents[i]); + } + } + if (types != parents) + type = Type.compoundType(types, members, symbol); + break; + default: + throw Debug.abort("illegal case", type); + } + } return type; } - public Checker[] postCheckers(Global global) { - return new Checker[] { - new CheckSymbols(global), - new CheckTypes(global), - new CheckOwners(global), - new CheckNames(global) - }; - } - //######################################################################## // Private Methods private Template getExpandedTemplate(Symbol clasz) { - if (global.debug) global.log("get expanded " + clasz + " in " + clasz.owner()); + assert Debug.log("get expanded " + clasz + " in " + clasz.owner()); Template template = (Template)expansions.get(clasz); if (template == null) { template = (Template)templates.remove(clasz); @@ -107,18 +122,20 @@ public class ExpandMixinsPhase extends Phase { private Template expandTemplate(Symbol clasz, Template template) { assert Debug.log("expanding ", clasz); - ClassExpander expander = null; + ClassExpander expander = new ClassExpander(global, clasz, template); Type[] parents = clasz.parents(); + // force expansion of superclass + if (!parents[0].symbol().isExternal()) + getExpandedTemplate(parents[0].symbol()); + // inline mixins for (int i = parents.length - 1; i > 0; --i) { Symbol parent = parents[i].symbol(); if (parent.isInterface()) continue; - if (expander == null) - expander = new ClassExpander(global, clasz, template); assert Debug.log("expanding ", clasz, ": inlining ", parent); expander.inlineMixin(i, parents[i], (Symbol)interfaces.get(parent), getExpandedTemplate(parent)); } - return expander == null ? template : expander.getTemplate(); + return expander.getTemplate(); } //######################################################################## @@ -148,7 +165,7 @@ public class ExpandMixinsPhase extends Phase { } public void apply(Unit unit) { if (unit.mixinOnly) { - global.log("removing " + unit + " after mixin expansion"); + assert Debug.log("removing " +unit+ " after mixin expansion"); unit.body = Tree.EMPTY_ARRAY; } else super.apply(unit); -- cgit v1.2.3