summaryrefslogtreecommitdiff
path: root/sources/scalac/transformer/ExpandMixinsPhase.java
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac/transformer/ExpandMixinsPhase.java')
-rw-r--r--sources/scalac/transformer/ExpandMixinsPhase.java473
1 files changed, 0 insertions, 473 deletions
diff --git a/sources/scalac/transformer/ExpandMixinsPhase.java b/sources/scalac/transformer/ExpandMixinsPhase.java
deleted file mode 100644
index 969080039a..0000000000
--- a/sources/scalac/transformer/ExpandMixinsPhase.java
+++ /dev/null
@@ -1,473 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-\* */
-
-// $OldId: ExpandMixinsPhase.java,v 1.8 2002/05/02 10:59:35 schinz Exp $
-// $Id$
-
-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;
-import scalac.PhaseDescriptor;
-import scalac.CompilationUnit;
-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".
-
-/**
- * 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 {
-
- //########################################################################
- // Private Fields
-
- /** A map from classes to their interface */
- private final Map/*<Symbol,Symbol>*/ interfaces;
-
- /** 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 members to their original member */
- private final Map/*<Symbol,Symbol>*/ origins;
-
-
- /** A transformer that expands classes that have mixins */
- private final GenTransformer expander;
-
- //########################################################################
- // Public Constructors
-
- /** Initializes this instance. */
- public ExpandMixinsPhase(Global global, PhaseDescriptor descriptor) {
- super(global, descriptor);
- Phase addinterfaces = global.PHASE.ADDINTERFACES.phase();
- this.interfaces = ((AddInterfacesPhase)addinterfaces).classToIFace;
- this.transformers = new HashMap();
- this.expansions = new HashMap();
- this.bodies = ((AddInterfacesPhase)addinterfaces).classToBody;
- this.origins = new HashMap();
- this.expander = new TreeExpander(global);
- }
-
- //########################################################################
- // Public Methods
-
- /** Applies this phase to the given compilation unit. */
- public void apply(CompilationUnit unit) {
- expander.apply(unit);
- }
-
- /** Applies this phase to the given type for the given symbol. */
- public Type transformInfo(Symbol symbol, Type type) {
- while (true) {
- if (symbol.isJava()) return type;
- if (symbol.isInterface()) return type;
- if (symbol.isCompoundSym()) return type; // !!! check
- if (symbol.isClass()) {
- return getTypeExpander(symbol).apply(type);
- }
- symbol = symbol.isConstructor()
- ? symbol.constructorClass()
- : symbol.owner();
- }
- }
-
- //########################################################################
- // Private Methods
-
- //########################################################################
- // Private Class - Tree expander
-
- /**
- * 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(CompilationUnit unit) {
- if (unit.mixinOnly) {
- assert Debug.log("removing unit " + unit);
- unit.body = Tree.EMPTY_ARRAY;
- } 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, 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().overriddenSymbol(supertype);
- assert !symbol.isNone(): Debug.show(tree, clasz, supertype);
- global.prevPhase();
- return symbol;
- case Super(_, _):
- case This(_):
- return clasz;
- default:
- return super.getSymbolFor(tree);
- }
- }
- public Tree transform(Tree tree) {
- switch (tree) {
- case ValDef(_, _, _, _):
- if (tree.symbol().hasStaticAttribute())
- return Tree.Empty;
- break;
- case DefDef(_, _, _, _, _, _):
- Symbol symbol = getSymbolFor(tree);
- if (symbol.owner() != clasz || symbol.hasStaticAttribute())
- return Tree.Empty;
- if (symbol.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(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 Type[] parents;
- public final SymbolCloner cloner;
- public final Map/*<Symbol,Type>*/ inlines;
-
- public TypeTransformer(Symbol clasz) {
- this.clasz = clasz;
- this.parents = clasz.parents();
- this.cloner = new SymbolCloner();
- 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 Symbol getMemberOrigin(Symbol member) {
- Object origin = origins.get(member);
- return origin == null ? member : (Symbol)origin;
- }
-
- private void createMixedInMemberSymbols(Scope symbols) {
- Scope scope = clasz.members();
- for (SymbolIterator i = symbols.iterator(); i.hasNext();) {
- Symbol member = i.next();
- boolean shadowed = member.isPrivate() || member.isInitializer()
- || member.overridingSymbol(clasz.thisType()) != member;
- Symbol origin = getMemberOrigin(member);
- if (!shadowed && origin != null) {
- Symbol overridden = member.overriddenSymbol(parents[0]);
- if (origin == getMemberOrigin(overridden)) {
- cloner.clones.put(member, overridden);
- continue;
- }
- }
- // !!! when the symbol is shadowed, inlining could be
- // avoided if the original definition is accessible
- // through super
- 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);
- origins.put(clone, origin != null ? origin : member);
- }
- }
-
-
- 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;
- if (symbol.isParameter()) {
- Symbol clone = (Symbol)cloner.clones.get(symbol);
- if (clone != null) {
- assert prefix == Type.NoPrefix && args.length == 0:
- type;
- return Type.typeRef(prefix, clone, args);
- }
- }
- return map(type);
- case SingleType(Type prefix, Symbol symbol):
- Symbol clone = (Symbol)cloner.clones.get(symbol);
- prefix = apply(prefix);
- return Type.singleType(prefix, clone != null ? clone : symbol);
- case ThisType(_):
- 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);
- }
- }
-
- }
-
- //########################################################################
-}