summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2004-01-22 09:31:38 +0000
committerpaltherr <paltherr@epfl.ch>2004-01-22 09:31:38 +0000
commitbba5b99fcfdbbff8ead57fc33cff84703de31443 (patch)
tree54f4c6cd44edc5b133e434e1c04a94f2f4bc8eac /sources
parent9694e01a39a1ca1ef2018864ba1ed6854bb9f872 (diff)
downloadscala-bba5b99fcfdbbff8ead57fc33cff84703de31443.tar.gz
scala-bba5b99fcfdbbff8ead57fc33cff84703de31443.tar.bz2
scala-bba5b99fcfdbbff8ead57fc33cff84703de31443.zip
- Enabled type cloning in Symbol cloner
- Rewrote ExpandMixins to implement a correct transformInfo
Diffstat (limited to 'sources')
-rw-r--r--sources/scalac/symtab/SymbolCloner.java3
-rw-r--r--sources/scalac/transformer/ExpandMixins.java287
-rw-r--r--sources/scalac/transformer/ExpandMixinsPhase.java479
3 files changed, 401 insertions, 368 deletions
diff --git a/sources/scalac/symtab/SymbolCloner.java b/sources/scalac/symtab/SymbolCloner.java
index c6713c7504..6df8eb8bca 100644
--- a/sources/scalac/symtab/SymbolCloner.java
+++ b/sources/scalac/symtab/SymbolCloner.java
@@ -19,7 +19,6 @@ import scalac.util.Debug;
* the new owner of cloned symbols, clones their type and keeps track
* of all cloned symbols. Clone a type means clone all symbol declared
* in that type (for example parameters of a MethodType).
- * !!! The type cloning is not yet enabled.
*/
public class SymbolCloner {
@@ -92,7 +91,7 @@ public class SymbolCloner {
clone.name = renamer.newName(symbol.name);
}
clones.put(symbol, clone);
- // !!! clone.setType(cloneType(clone.info()));
+ clone.setType(cloneType(symbol.info()));
return clone;
}
diff --git a/sources/scalac/transformer/ExpandMixins.java b/sources/scalac/transformer/ExpandMixins.java
deleted file mode 100644
index ded85488db..0000000000
--- a/sources/scalac/transformer/ExpandMixins.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-\* */
-
-// $OldId: ExpandMixins.java,v 1.24 2002/11/11 16:08:50 schinz Exp $
-// $Id$
-
-package scalac.transformer;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Iterator;
-
-import scalac.Global;
-import scalac.ast.Tree;
-import scalac.ast.Tree.Template;
-import scalac.ast.TreeList;
-import scalac.ast.TreeGen;
-import scalac.ast.TreeInfo;
-import scalac.ast.GenTreeCloner;
-import scalac.ast.TreeSymbolCloner;
-import scalac.ast.Transformer;
-import scalac.symtab.Modifiers;
-import scalac.symtab.Scope;
-import scalac.symtab.Scope.SymbolIterator;
-import scalac.symtab.Symbol;
-import scalac.symtab.SymbolCloner;
-import scalac.symtab.SymbolSubstTypeMap;
-import scalac.symtab.Type;
-import scalac.util.Name;
-import scalac.util.Debug;
-
-public class ClassExpander {
-
- //########################################################################
- // Private Fields
-
- /** The global environment */
- private final Global global;
-
- /** A tree generator */
- private final TreeGen gen;
-
- /** The expanding class */
- private final Symbol clasz;
-
- /** The parents of the expanding class */
- private final Type[] parents;
-
- /** The members of the expanding class */
- private final Scope members;
-
- /** The template of the expanding class */
- private final Template template;
-
- /** The body of the expanding class */
- private final LinkedList/*<Tree>*/ body;
-
- /** The type map to apply to inlined symbols and trees */
- private final SymbolSubstTypeMap map;
-
- /** The symbol cloner to clone inlined symbols */
- private final SymbolCloner cloner;
-
- /** The state of this class (used to prevent misuses) */
- private int state;
-
- //########################################################################
- // Public Constructors
-
- public ClassExpander(Global global, Symbol clasz, Template template) {
- this.global = global;
- this.gen = global.treeGen;
- this.clasz = clasz;
- this.parents = Type.cloneArray(clasz.parents());
- this.members = clasz.members(); // !!! .cloneScope();
- this.template = gen.Template(template.pos, template.symbol(),
- Tree.cloneArray(template.parents), template.body);
- this.body = new LinkedList();
- this.map = new SymbolSubstTypeMap();
- 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);
- // 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);
- 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;
- return;
- default:
- throw Debug.abort("invalid base class type", parents[i]);
- }
- }
-
- public Template getTemplate() {
- assert 0 < state : "state = " + state;
- Transformer superFixer = new Transformer(global) {
- public Tree transform(Tree tree) {
- switch (tree) {
- case Select(Super(_, _), _):
- Symbol symbol = map.lookupSymbol(tree.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(this.superFixer.transform(
-superFixer.transform(template.body))));
- template.body = (Tree[])body.toArray(new Tree[body.size()]);
- // !!! *1 fix ExpandMixinsPhase.transformInfo and remove next line
- state = 0;
- return template;
- }
-
- //########################################################################
- // Private Methods
-
- private void inlineMixinVParams(Symbol[] params, Tree[] args, int fstPos) {
- for (int i = 0; i < params.length; i++) {
- Symbol member = cloner.cloneSymbol(params[i], true);
- member.flags &= ~Modifiers.PARAM;
- 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]);
- member.setType(map.apply(member.type()));
- body.add(fstPos + i, gen.ValDef(member, args[i]));
- }
- }
-
- private void createMixedInMemberSymbols(Scope symbols) {
- // The map names is used to implement an all or nothing
- // strategy for overloaded symbols.
- Map/*<Name,Name>*/ names = new HashMap();
- for (SymbolIterator i = symbols.iterator(true); i.hasNext();) {
- Symbol member = i.next();
- Name name = (Name)names.get(member.name);
- boolean shadowed = name == null &&
- members.lookup(member.name) != Symbol.NONE;
- Symbol clone = cloner.cloneSymbol(member, shadowed);
- if (member.isInitializer() && name == null)
- clone.name = Name.fromString(
- "$init$" + clone.name.toString().substring(6));
- if (name != null)
- clone.name = name;
- else
- names.put(member.name, clone.name);
- if (clone.name != member.name) clone.flags &= ~Modifiers.OVERRIDE;
- clone.setType(clone.type().cloneTypeNoSubst(cloner));
- members.enterOrOverload(clone);
- }
- // We need two loops because members may appear in their types.
- for (SymbolIterator i = symbols.iterator(true); i.hasNext();) {
- Symbol member = map.lookupSymbol(i.next());
- if (member == null) continue;
- member.setType(map.applyParams(member.type()));
- }
- }
-
- private void inlineMixedInCode(Template mixin, int fstPos) {
- cloner.owners.put(mixin.symbol(), template.symbol());
- 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) {
- body.add(fstPos + pos, mixinMemberCloner.transform(tree));
- ++pos;
- }
- }
- }
-
- private final GenTreeCloner mixinMemberCloner;
-
- private class MixinMemberCloner extends GenTreeCloner {
- private boolean initializer;
-
- public MixinMemberCloner(ClassExpander expander) {
- super(expander.global, expander.map, expander.cloner);
- }
-
- public Symbol getSymbolFor(Tree tree) {
- switch (tree) {
- case Select(Super(_, _), _):
- if (tree.symbol().isInitializer()) return tree.symbol();
- // !!! 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);
- }
- }
-
- public Tree transform(Tree tree) {
- switch (tree) {
- case DefDef(_, _, _, _, _, _):
- if (getSymbolFor(tree).isInitializer()) initializer = true;
- tree = super.transform(tree);
- initializer = false;
- return tree;
- case Apply(Select(Super(_, _), _), _):
- if (TreeInfo.methSymbol(tree).isInitializer() && !initializer)
- return Tree.Empty;
- break;
- }
- if (tree.hasSymbol() && tree.symbol().isParameter()) {
- Symbol symbol = getSymbolFor(tree);
- if (!symbol.isParameter()) {
- assert tree instanceof Tree.Ident: tree;
- return gen.Select(gen.This(tree.pos, clasz), symbol);
- }
- }
- return super.transform(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) {
- switch (tree) {
- case ClassDef(_, _, _, _, _, _):
- return 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 9fdd395db4..3dcdc54aac 100644
--- a/sources/scalac/transformer/ExpandMixinsPhase.java
+++ b/sources/scalac/transformer/ExpandMixinsPhase.java
@@ -9,8 +9,13 @@
package scalac.transformer;
+import java.util.Arrays;
+import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.LinkedList;
import scalac.Global;
import scalac.Phase;
@@ -18,13 +23,25 @@ import scalac.PhaseDescriptor;
import scalac.Unit;
import scalac.ast.Tree;
import scalac.ast.Tree.Template;
+import scalac.ast.TreeGen;
+import scalac.ast.TreeInfo;
+import scalac.ast.TreeList;
import scalac.ast.Traverser;
import scalac.ast.Transformer;
+import scalac.ast.GenTransformer;
+import scalac.ast.GenTreeCloner;
import scalac.symtab.Scope;
import scalac.symtab.Symbol;
import scalac.symtab.Type;
import scalac.util.Debug;
+import scalac.util.Name;
+import scalac.util.Names;
+import scalac.symtab.Modifiers;
+import scalac.symtab.Scope.SymbolIterator;
+import scalac.symtab.SymbolCloner;
+import scalac.symtab.SymbolSubstTypeMap;
+
// TODO do not copy hidden members which are not accessible via
// "super".
@@ -32,6 +49,7 @@ import scalac.util.Debug;
* A phase to expand mixins using code copying. We assume that links
* to outer classes have been made explicit by a previous phase.
*/
+// !!! needs to be cleaned
public class ExpandMixinsPhase extends Phase {
//########################################################################
@@ -40,16 +58,21 @@ public class ExpandMixinsPhase extends Phase {
/** A map from classes to their interface */
private final Map/*<Symbol,Symbol>*/ interfaces;
- /** A map from classes to their expanded template */
- private final Map/*<Symbol,Template>*/ expansions;
+ /** A map from classes to their type transformer */
+ private final Map/*<Symbol,TypeTransformer>*/ transformers;
+
+ /** A map from classes to their expanded body */
+ private final Map/*<Symbol,Tree[]>*/ expansions;
+
+ /** A map from classes to their original (unexpanded) body */
+ private final Map/*<Symbol,Tree[]>*/ bodies;
+
- /** A map from classes to their original (unexpanded) template */
- private final Map/*<Symbol,Template>*/ templates;
/** A traverser that collects class definitions */
private final Traverser collector;
/** A transformer that expands classes that have mixins */
- private final Transformer expander;
+ private final GenTransformer expander;
//########################################################################
// Public Constructors
@@ -59,95 +82,53 @@ public class ExpandMixinsPhase extends Phase {
super(global, descriptor);
Phase addinterfaces = global.PHASE.ADDINTERFACES.phase();
this.interfaces = ((AddInterfacesPhase)addinterfaces).classToIFace;
+ this.transformers = new HashMap();
this.expansions = new HashMap();
- this.templates = new HashMap();
- this.collector = new Collector();
- this.expander = new Expander(global);
+ this.bodies = new HashMap();
+ this.collector = new TreeCollector();
+ this.expander = new TreeExpander(global);
}
//########################################################################
// Public Methods
+ /** Applies this phase to the given compilation units. */
public void apply(Unit[] units) {
collector.traverse(units);
expander.apply(units);
- // !!! assert templates.isEmpty(): templates.keySet();
}
+ /** Applies this phase to the given type for the given symbol. */
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);
+ Symbol s = symbol;
+ while (true) {
+ if (symbol.isJava()) return type;
+ if (symbol.isPackage()) return type;
+ if (symbol.isInterface()) return type;
+ if (symbol.isClass()) {
+ // !!! System.out.println(Debug.show("!!! ", s, " -> ", symbol, " - ", getTypeExpander(symbol).clasz, " : " + type));
+ return getTypeExpander(symbol).apply(type);
}
+ symbol = symbol.isConstructor()
+ ? symbol.constructorClass()
+ : symbol.owner();
}
- return type;
}
//########################################################################
// Private Methods
- private Template getExpandedTemplate(Symbol clasz) {
- assert Debug.log("get expanded " + clasz + " in " + clasz.owner());
- Template template = (Template)expansions.get(clasz);
- if (template == null) {
- template = (Template)templates.remove(clasz);
- assert template != null : Debug.show(clasz);
- template = expandTemplate(clasz, expander.transform(template));
- expansions.put(clasz, template);
- }
- return template;
- }
-
- private Template expandTemplate(Symbol clasz, Template template) {
- assert Debug.log("expanding ", clasz);
- 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;
- assert Debug.log("expanding ", clasz, ": inlining ", parent);
- expander.inlineMixin(i, parents[i], (Symbol)interfaces.get(parent),
- getExpandedTemplate(parent));
- }
- return expander.getTemplate();
- }
-
//########################################################################
- // Private Class - Collector
+ // Private Class - Tree collector
- private class Collector extends Traverser {
+ /** A tree traverser that collects class definitions. */
+ private class TreeCollector extends Traverser {
public void traverse(Tree tree) {
switch(tree) {
- case ClassDef(_, _, _, _, _, Template template):
+ case ClassDef(_, _, _, _, _, Template(_, Tree[] body)):
Symbol clasz = tree.symbol();
- if (!clasz.isInterface()) templates.put(clasz, template);
- traverse(template.body);
+ if (!clasz.isInterface()) bodies.put(clasz, body);
+ traverse(body);
return;
case PackageDef(_, Template(_, Tree[] body)):
traverse(body);
@@ -157,33 +138,373 @@ public class ExpandMixinsPhase extends Phase {
}
//########################################################################
- // Private Class - Expander
+ // Private Class - Tree expander
- private class Expander extends Transformer {
- public Expander(Global global) {
+ /**
+ * A tree transformer that expands class definitions and removes
+ * compiled units.
+ */
+ private class TreeExpander extends GenTransformer {
+ public TreeExpander(Global global) {
super(global);
}
public void apply(Unit unit) {
if (unit.mixinOnly) {
- assert Debug.log("removing " +unit+ " after mixin expansion");
+ assert Debug.log("removing unit " + unit);
unit.body = Tree.EMPTY_ARRAY;
- } else
+ } else {
super.apply(unit);
+ }
}
public Tree transform(Tree tree) {
switch (tree) {
case ClassDef(_, _, _, _, _, _):
Symbol clasz = tree.symbol();
if (clasz.isInterface()) return super.transform(tree);
- return gen.ClassDef(clasz, getExpandedTemplate(clasz));
- case PackageDef(_, _):
- return super.transform(tree);
- case Template(_, _):
+ return gen.ClassDef(clasz, getExpandedBody(clasz));
+ default:
return super.transform(tree);
+ }
+ }
+ }
+
+ //########################################################################
+ // Private Class - Tree inliner
+
+ /**
+ * A Tree cloner that clones mixin bodies. It assumes that these
+ * bodies have already been expanded. References to mixin value
+ * parameters are replaced by references to newly-created inlined
+ * fields. The symbol of Super and This nodes is replaced by the
+ * symbol of the generated class. The symbol of super members is
+ * rebound if required. Note that as the input tree has already
+ * been expanded, it contains only super member to the first
+ * supertype of the mixin, all other super members have been
+ * removed during the expansion of the input tree.
+ */
+ private static class TreeInliner extends GenTreeCloner {
+ private final Symbol clasz;
+ private final Type supertype;
+ private boolean initializer;
+ public TreeInliner(Global global, TypeTransformer transformer) {
+ super(global, transformer, transformer.cloner);
+ // !!! global.nextPhase();
+ this.clasz = transformer.clasz;
+ // !!! global.prevPhase();
+ this.supertype = clasz.nextInfo().parents()[0];
+ }
+ public Symbol getSymbolFor(Tree tree) {
+ switch (tree) {
+ case Select(Super(_, _), _):
+ if (tree.symbol().isInitializer()) return tree.symbol(); // !!!
+ assert supertype.symbol().isSubClass(tree.symbol().owner()):
+ tree + " -- " + Debug.show(clasz);
+ global.nextPhase();
+ Symbol symbol = tree.symbol().overridingSymbol(supertype);
+ global.prevPhase();
+ assert !symbol.isNone(): tree + " -- " + Debug.show(clasz);
+ return symbol;
+ case Super(_, _):
+ case This(_):
+ return clasz;
default:
+ return super.getSymbolFor(tree);
+ }
+ }
+ public Tree transform(Tree tree) {
+ switch (tree) {
+ case DefDef(_, _, _, _, _, _):
+ if (getSymbolFor(tree).isInitializer()) initializer = true;
+ tree = super.transform(tree);
+ initializer = false;
return tree;
+ case Apply(Select(Super(_, _), _), _):
+ if (TreeInfo.methSymbol(tree).isInitializer() && !initializer)
+ return Tree.Empty;
+ break;
+ }
+ if (tree.hasSymbol() && tree.symbol().isParameter()) {
+ Symbol symbol = getSymbolFor(tree);
+ if (!symbol.isParameter()) {
+ assert tree instanceof Tree.Ident: tree;
+ return gen.Select(gen.This(tree.pos, clasz), symbol);
+ }
+ }
+ return super.transform(tree);
+ }
+ }
+
+ //########################################################################
+ // Private Class - Class tree expander
+
+ /**
+ * A tree transformer that expands a class definitions. Super
+ * members are rebound and/or rewritten into normal members.
+ */
+ private class ClassTreeExpander extends TreeExpander {
+ private final Symbol clasz;
+ private final Type[] parents;
+ private final Map clones;
+ public ClassTreeExpander(Global global, TypeTransformer transformer) {
+ super(global);
+ this.clasz = transformer.clasz;
+ this.parents = clasz.parents();
+ this.clones = transformer.cloner.clones;
+ }
+ private Symbol getSuperMember(Symbol member) {
+ for (int i = 0; i < parents.length; i++) {
+ global.nextPhase();
+ if (!parents[i].symbol().isSubClass(member.owner())) {
+ global.prevPhase(); // !!!
+ continue;
+ }
+ Symbol override = member.overridingSymbol(parents[i]);
+ global.prevPhase();
+ assert !override.isNone():
+ Debug.show(member, " -- ", clasz, " -- ", parents[i]);
+ if (i == 0) return override;
+ Symbol clone = (Symbol)clones.get(override);
+ assert clone != null:
+ Debug.show(member, " -- ", override, " -- ", clasz);
+ return clone;
+ }
+ // !!! double loop
+ for (int i = 0; i < parents.length; i++) {
+ if (!parents[i].symbol().isSubClass(member.owner())) continue;
+ //global.nextPhase();
+ Symbol override = member.overridingSymbol(parents[i]);
+ //global.prevPhase();
+ assert !override.isNone():
+ Debug.show(member, " -- ", clasz, " -- ", parents[i]);
+ if (i == 0) return override;
+ Symbol clone = (Symbol)clones.get(override);
+ assert clone != null:
+ Debug.show(member, " -- ", override, " -- ", clasz);
+ return clone;
}
+ throw Debug.abort(Debug.show(member, " -- ", clasz));
}
+ public Tree transform(Tree tree) {
+ switch (tree) {
+ case Select(Super(_, _), _):
+ Symbol symbol = getSuperMember(tree.symbol());
+ Tree qualifier = symbol.owner() == clasz
+ ? gen.This(tree.pos, clasz)
+ : gen.Super(tree.pos, clasz);
+ return gen.Select(tree.pos, qualifier, symbol);
+ default:
+ return super.transform(tree);
+ }
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /** Returns the type transformer to use for the given class. */
+ private TypeTransformer getTypeExpander(Symbol clasz) { // !!!
+ assert clasz.isClass() && !clasz.isInterface(): Debug.show(clasz);
+ TypeTransformer transformer =(TypeTransformer)transformers.get(clasz);
+ if (transformer == null) {
+ transformer = new TypeTransformer(global, clasz);
+ transformers.put(clasz, transformer);
+ }
+ return transformer;
+ }
+
+ /** Returns the expanded body of the given clasz. */
+ private Tree[] getExpandedBody(Symbol clasz) {
+ Tree[] body = (Tree[])expansions.get(clasz);
+ if (body == null) {
+ body = (Tree[])bodies.remove(clasz);
+ assert body != null: Debug.show(clasz);
+ TypeTransformer transformer = getTypeExpander(clasz);
+ TreeList list = new TreeList();
+ assert Debug.log("expanding tree ", clasz);
+ Type[] parents = clasz.parents();
+ TreeInliner inliner = new TreeInliner(global, transformer);
+ for (int i = 1; i < parents.length; i++) {
+ Symbol mixin = parents[i].symbol();
+ if (mixin.isInterface()) continue;
+ assert Debug.log("expanding tree ", clasz, ": inlining ", mixin);
+ list.append(inliner.transform(getExpandedBody(mixin)));
+ }
+ ClassTreeExpander expander = new ClassTreeExpander(global, transformer);
+ list.append(expander.transform(body));
+ body = list.toArray();
+ expansions.put(clasz, body);
+ }
+ return body;
+ }
+
+ //########################################################################
+ // Private Class - Collector
+
+ private class TypeTransformer extends Type.MapOnlyTypes {
+
+ public final Symbol clasz;
+ public final SymbolCloner cloner;
+ public final Map/*<Symbol,Type>*/ inlines;
+
+ public TypeTransformer(Global global, Symbol clasz) {
+ this.clasz = clasz;
+ this.cloner = new SymbolCloner(global.freshNameCreator);
+ this.inlines = new HashMap();
+ initialize();
+ }
+
+ private void initialize() {
+ Type[] parents = clasz.parents();
+ // !!! parents.length > 0
+ if (parents.length > 0) parents[0].symbol().nextInfo(); // force
+ assert Debug.log("expanding type ", clasz);
+ for (int i = parents.length - 1; 0 < i; i--) {
+ switch (parents[i]) {
+ case TypeRef(Type prefix, Symbol mixin, Type[] args):
+ if (mixin.isInterface()) continue;
+ mixin.nextInfo(); // force
+ assert Debug.log("expanding type ", clasz, ": inlining ", mixin);
+ cloner.owners.put(mixin, clasz);
+ cloner.owners.put(mixin.primaryConstructor(), clasz);
+ // map mixin type parameters to mixin type arguments
+ Symbol[] tparams = mixin.typeParams();
+ for (int j = 0; j < tparams.length; j++)
+ inlines.put(tparams[j], args[j]);
+
+ createMixedInMemberSymbols(mixin.nextInfo().members());
+ }
+ }
+ Set clones = new HashSet(cloner.clones.keySet());
+// cloner.clones.putAll(getTypeTransformerFor(parents[0].symbol()).cloner.clones); // !!! build closure
+
+ // !!! remove ?
+ for (Iterator i = cloner.clones.values().iterator(); i.hasNext();){
+ // !!! for (Iterator i = clones.iterator(); i.hasNext();){
+ Symbol clone = (Symbol)i.next();
+ clone.setInfo(apply(clone.info()));
+ }
+ }
+
+ private void createMixedInMemberSymbols(Scope symbols) {
+ Scope scope = clasz.members();
+ for (SymbolIterator i = symbols.iterator(true); i.hasNext();) {
+ Symbol member = i.next();
+ boolean shadowed = member.isPrivate() || member.isInitializer()
+ || member.overridingSymbol(clasz.thisType()) != member;
+ assert Debug.log("expanding type ", clasz, ": cloning ", member);
+ Symbol clone = cloner.cloneSymbol(member);
+ if (shadowed) clone.name = Names.MIXIN(member);
+ if (shadowed) clone.flags &= ~Modifiers.OVERRIDE;
+ if (shadowed) clone.flags &= ~Modifiers.ACCESSFLAGS;
+ if (shadowed) clone.flags |= Modifiers.PRIVATE;
+ scope.enterOrOverload(clone);
+ }
+ }
+
+
+ public Type apply(Type type) {
+ switch (type) {
+ case TypeRef(Type prefix, Symbol symbol, Type[] args):
+ Type inline = (Type)inlines.get(symbol);
+ if (inline != null) return inline;
+ args = map(args);
+ if (!symbol.isClassType()) {
+ Type oldpre = prefix; // !!!
+ prefix = apply(prefix);
+ Symbol rebind = prefix.rebind(symbol);
+ if (rebind != symbol) {
+ // !!! System.out.println("!!! prefix: " + Debug.show(oldpre, " -> ", prefix, " - ", clasz));
+ // !!! System.out.println("!!! symbol: " + Debug.show(symbol, " -> ", rebind));
+ symbol = rebind;
+ if (rebind.isClassType()) {
+ // !!! Same thing as in AsSeenFromMap => factorize
+ args = Type.asSeenFrom(
+ Symbol.type(symbol.owner().nextTypeParams()),
+ prefix,
+ symbol.owner());
+ {
+ Type p = prefix;
+ Symbol s = symbol.owner();
+ while (true) {
+ if (s.isPackage()) break;
+ if (s.isModuleClass()) {
+ s = s.owner();
+ p = p.prefix().baseType(s);
+ } else {
+ args = Type.cloneArray(args, 1);
+ args[args.length - 1] = p;
+ break;
+ }
+ }
+ }
+ prefix = Type.localThisType;
+ }
+ }
+ else prefix = oldpre; // !!!
+ // !!! else is needed for following example:
+ // trait Outer {
+ // type visitor;
+ // class Inner: visitor { def fun = 0; }
+ // }
+ }
+ return Type.TypeRef(prefix, symbol, args);
+ case SingleType(Type prefix, Symbol symbol):
+ // !!! prefix = apply(prefix);
+ // !!! symbol = prefix.rebind(symbol);
+ // !!! commented out because of following example:
+ // class Bar {
+ // val b: Bar = null;
+ // class Linker { def b: Bar.this.b.type = Bar.this.b; }
+ // }
+ Symbol clone = (Symbol)cloner.clones.get(symbol);
+ if (clone != null) symbol = clone;
+ return Type.singleType(prefix, symbol);
+ case ThisType(Symbol symbol):
+ if (symbol.isNone()) return type;
+ return clasz.thisType();
+ case CompoundType(Type[] parents, Scope members):
+ if (type.symbol() != clasz) return map(type);
+ if (parents.length <= 1) return type;
+ Symbol iface = (Symbol)interfaces.get(clasz);
+ if (iface == null) {
+ int i = 1;
+ while (i < parents.length && parents[i].symbol().isInterface()) i++;
+ if (i == parents.length) return type;
+ parents = Type.cloneArray(parents);
+ while (i < parents.length) {
+ if (!parents[i].symbol().isInterface())
+ parents[i] = Type.TypeRef(parents[i].prefix(), (Symbol)interfaces.get(parents[i].symbol()), parents[i].typeArgs());
+ i++;
+ }
+ return Type.compoundType(parents, members, clasz);
+ }
+ assert parents[parents.length - 1].symbol() == iface: type;
+ if (parents.length == 2) return type;
+ for (int i = 1; i < parents.length - 1; i++) {
+ Symbol mixin = parents[i].symbol();
+ Symbol imix = mixin.isInterface()
+ ? mixin
+ : (Symbol)interfaces.get(mixin);
+ assert iface.isSubClass(imix): type+" - "+i;
+ }
+ parents = new Type[] {parents[0], parents[parents.length - 1]};
+ return Type.compoundType(parents, members, clasz);
+ default:
+ return map(type);
+ }
+ }
+
}
//########################################################################