summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorschinz <schinz@epfl.ch>2003-02-19 09:55:54 +0000
committerschinz <schinz@epfl.ch>2003-02-19 09:55:54 +0000
commit8ab0ae13ce49fb8d39a6c9af7873586da4e61c4a (patch)
tree69bb72f17b10f0f7a6adc553bf5ede8fde279b03 /sources
parent6cb8bc84c903322e4c87e545c23a648d7950fe9d (diff)
downloadscala-8ab0ae13ce49fb8d39a6c9af7873586da4e61c4a.tar.gz
scala-8ab0ae13ce49fb8d39a6c9af7873586da4e61c4a.tar.bz2
scala-8ab0ae13ce49fb8d39a6c9af7873586da4e61c4a.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scalac/ast/StrictTreeFactory.java317
-rw-r--r--sources/scalac/ast/SubstTransformer.java247
-rw-r--r--sources/scalac/ast/TreeCopier.java91
-rw-r--r--sources/scalac/symtab/SymbolMapApplier.java86
-rw-r--r--sources/scalac/transformer/AddInterfaces.java781
-rw-r--r--sources/scalac/transformer/AddInterfacesPhase.java54
-rw-r--r--sources/scalac/transformer/ExpandMixins.java426
-rw-r--r--sources/scalac/transformer/ExpandMixinsPhase.java45
8 files changed, 2047 insertions, 0 deletions
diff --git a/sources/scalac/ast/StrictTreeFactory.java b/sources/scalac/ast/StrictTreeFactory.java
new file mode 100644
index 0000000000..c68453424e
--- /dev/null
+++ b/sources/scalac/ast/StrictTreeFactory.java
@@ -0,0 +1,317 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $OldId: StrictTreeFactory.java,v 1.6 2002/04/19 10:57:23 gamboni Exp $
+// $Id$
+
+package scalac.ast;
+
+import scalac.util.Name;
+import Tree.*;
+
+public class StrictTreeFactory extends AbstractTreeCopyFactory {
+ protected final TreeFactory make;
+
+ public StrictTreeFactory(TreeFactory make) {
+ this.make = make;
+ }
+
+ public Tree Bad(Tree tree) {
+ return tree;
+ }
+
+ public Tree ClassDef(Tree tree,
+ int mods,
+ Name name,
+ TypeDef[] tparams,
+ ValDef[][] vparams,
+ Tree tpe,
+ Template impl) {
+ ClassDef t = (ClassDef)tree;
+ tree = make.ClassDef(t.pos, mods, name, tparams, vparams, tpe, impl);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree PackageDef(Tree tree,
+ Tree packaged,
+ Template impl) {
+ PackageDef t = (PackageDef)tree;
+ tree = make.PackageDef(t.pos, packaged, impl);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree ModuleDef(Tree tree,
+ int mods,
+ Name name,
+ Tree tpe,
+ Template impl) {
+ ModuleDef t = (ModuleDef)tree;
+ tree = make.ModuleDef(t.pos, mods, name, tpe, impl);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree ValDef(Tree tree,
+ int mods,
+ Name name,
+ Tree tpe,
+ Tree rhs) {
+ ValDef t = (ValDef)tree;
+ tree = make.ValDef(t.pos, mods, name, tpe, rhs);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree PatDef(Tree tree,
+ int mods,
+ Tree pat,
+ Tree rhs) {
+ PatDef t = (PatDef)tree;
+ tree = make.PatDef(t.pos, mods, pat, rhs);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree DefDef(Tree tree,
+ int mods,
+ Name name,
+ TypeDef[] tparams,
+ ValDef[][] vparams,
+ Tree tpe,
+ Tree rhs) {
+ DefDef t = (DefDef)tree;
+ tree = make.DefDef(t.pos, mods, name, tparams, vparams, tpe, rhs);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree TypeDef(Tree tree,
+ int mods,
+ Name name,
+ TypeDef[] tparams,
+ Tree rhs) {
+ TypeDef t = (TypeDef)tree;
+ tree = make.TypeDef(t.pos, mods, name, tparams, rhs);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Import(Tree tree,
+ Tree expr,
+ Name[] selectors) {
+ Import t = (Import)tree;
+ tree = make.Import(t.pos, expr, selectors);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree CaseDef(Tree tree,
+ Tree pat,
+ Tree guard,
+ Tree body) {
+ CaseDef t = (CaseDef)tree;
+ tree = make.CaseDef(t.pos, pat, guard, body);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Template Template(Tree tree,
+ Tree[] baseClasses,
+ Tree[] body) {
+ Template t = (Template)tree;
+ Template newTree = make.Template(t.pos, baseClasses, body);
+ attribute(newTree, t);
+ return newTree;
+ }
+
+ public Tree LabelDef(Tree tree,
+ Tree[] params,
+ Tree rhs) {
+ LabelDef t = (LabelDef)tree;
+ tree = make.LabelDef(t.pos,params,rhs);
+ attribute(tree,t);
+ return tree;
+ }
+
+ public Tree Block(Tree tree,
+ Tree[] stats) {
+ Block t = (Block)tree;
+ tree = make.Block(t.pos, stats);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Tuple(Tree tree,
+ Tree[] trees) {
+ Tuple t = (Tuple)tree;
+ tree = make.Tuple(t.pos, trees);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Visitor(Tree tree,
+ CaseDef[] cases) {
+ Visitor t = (Visitor)tree;
+ tree = make.Visitor(t.pos, cases);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Function(Tree tree,
+ ValDef[] vparams,
+ Tree body) {
+ Function t = (Function)tree;
+ tree = make.Function(t.pos, vparams, body);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Assign(Tree tree,
+ Tree lhs,
+ Tree rhs) {
+ Assign t = (Assign)tree;
+ tree = make.Assign(t.pos, lhs, rhs);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree If(Tree tree,
+ Tree cond,
+ Tree thenp,
+ Tree elsep) {
+ If t = (If)tree;
+ tree = make.If(t.pos, cond, thenp, elsep);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree New(Tree tree,
+ Template templ) {
+ New t = (New)tree;
+ tree = make.New(t.pos, templ);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Typed(Tree tree,
+ Tree expr,
+ Tree tpe) {
+ Typed t = (Typed)tree;
+ tree = make.Typed(t.pos, expr, tpe);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree TypeApply(Tree tree,
+ Tree fun,
+ Tree[] args) {
+ TypeApply t = (TypeApply)tree;
+ tree = make.TypeApply(t.pos, fun, args);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Apply(Tree tree,
+ Tree fun,
+ Tree[] args) {
+ Apply t = (Apply)tree;
+ tree = make.Apply(t.pos, fun, args);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree This(Tree tree, Tree qualifier) {
+ This t = (This)tree;
+ tree = make.This(t.pos, qualifier);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Super(Tree tree,
+ Tree tpe) {
+ Super t = (Super)tree;
+ tree = make.Super(t.pos, tpe);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Select(Tree tree,
+ Tree qualifier,
+ Name selector) {
+ Select t = (Select)tree;
+ tree = make.Select(t.pos, qualifier, selector);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Ident(Tree tree,
+ Name name) {
+ Ident t = (Ident)tree;
+ tree = make.Ident(t.pos, name);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree Literal(Tree tree,
+ Object value) {
+ Literal t = (Literal)tree;
+ tree = make.Literal(t.pos, value);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree SingletonType(Tree tree, Tree ref) {
+ SingletonType t = (SingletonType)tree;
+ tree = make.SingletonType(t.pos, ref);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree SelectFromType(Tree tree, Tree qualifier, Name selector) {
+ SelectFromType t = (SelectFromType)tree;
+ tree = make.SelectFromType(t.pos, qualifier, selector);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree FunType(Tree tree,
+ Tree[] argtpe,
+ Tree restpe) {
+ FunType t = (FunType)tree;
+ tree = make.FunType(t.pos, argtpe, restpe);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree CompoundType(Tree tree,
+ Tree[] baseTypes,
+ Tree[] refinements) {
+ CompoundType t = (CompoundType)tree;
+ tree = make.CompoundType(t.pos, baseTypes, refinements);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree CovariantType(Tree tree,
+ Tree clazz) {
+ CovariantType t = (CovariantType)tree;
+ tree = make.CovariantType(t.pos, clazz);
+ attribute(tree, t);
+ return tree;
+ }
+
+ public Tree AppliedType(Tree tree,
+ Tree tpe,
+ Tree[] args) {
+ AppliedType t = (AppliedType)tree;
+ tree = make.AppliedType(t.pos, tpe, args);
+ attribute(tree, t);
+ return tree;
+ }
+}
diff --git a/sources/scalac/ast/SubstTransformer.java b/sources/scalac/ast/SubstTransformer.java
new file mode 100644
index 0000000000..c7802d20d7
--- /dev/null
+++ b/sources/scalac/ast/SubstTransformer.java
@@ -0,0 +1,247 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $OldId: SubstTransformer.java,v 1.3 2002/04/19 10:55:15 schinz Exp $
+// $Id$
+
+package scalac.ast;
+
+import scalac.*;
+import scalac.ast.*;
+import scalac.symtab.*;
+import scalac.util.*;
+import scalac.typechecker.*;
+import Tree.*;
+
+import java.util.*;
+
+/**
+ * A transformer which performs symbol or type substitutions.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+public class SubstTransformer extends Transformer {
+ protected Map/*<Symbol,Symbol>*/ symbolMap = new HashMap();
+ protected SymbolMapApplier smApplier = new SymbolMapApplier(symbolMap);
+ protected LinkedList/*<Map<Symbol,Symbol>>*/ ssStack = new LinkedList();
+
+ protected Symbol[] typeMapFormals = Symbol.EMPTY_ARRAY;
+ protected Type[] typeMapActuals = Type.EMPTY_ARRAY;
+ protected LinkedList/*<Symbol[]>*/ tmfStack = new LinkedList();
+ protected LinkedList/*<Symbol[]>*/ tmaStack = new LinkedList();
+
+ final protected Type.Map typeMap =
+ new Type.Map() {
+ public Type apply(Type t) {
+ return t.subst(typeMapFormals, typeMapActuals);
+ }
+ };
+
+ protected final TreeCopyFactory simpleCopy;
+
+ public SubstTransformer(Global global,
+ PhaseDescriptor descr,
+ TreeFactory make) {
+ super(global, descr, make, new TCF(make));
+ this.simpleCopy = new StrictTreeFactory(make);
+
+ ((TCF)copy).setTransformer(this);
+ }
+
+ public boolean mustSubstituteSymbol(Tree tree) {
+ return true;
+ }
+
+ protected void updateSymbolSubst() {
+ symbolMap.clear();
+ Iterator ssIt = ssStack.iterator();
+ while (ssIt.hasNext()) {
+ Map/*<Symbol,Symbol>*/ map = (Map)ssIt.next();
+ symbolMap.putAll(map);
+ }
+ }
+
+ public void pushSymbolSubst(Map map) {
+ ssStack.addLast(map);
+ updateSymbolSubst();
+ }
+
+ public void popSymbolSubst() {
+ ssStack.removeLast();
+ updateSymbolSubst();
+ }
+
+ public void clearSymbolSubst() {
+ ssStack.clear();
+ updateSymbolSubst();
+ }
+
+ protected void updateTypeSubst() {
+ assert tmfStack.size() == tmaStack.size();
+
+ Map/*<Symbol,Type>*/ map = new HashMap();
+ Iterator tmfIt = tmfStack.iterator();
+ Iterator tmaIt = tmaStack.iterator();
+ while (tmfIt.hasNext()) {
+ assert tmaIt.hasNext();
+ Symbol[] formals = (Symbol[]) tmfIt.next();
+ Type[] actuals = (Type[]) tmaIt.next();
+ assert formals.length == actuals.length;
+ for (int i = 0; i < formals.length; ++i)
+ map.put(formals[i], actuals[i]);
+ }
+
+ typeMapFormals = new Symbol[map.size()];
+ typeMapActuals = new Type[map.size()];
+
+ Set/*<Map.Entry<Symbol,Type>>*/ entries = map.entrySet();
+ Iterator entriesIt = entries.iterator();
+ int i = 0;
+ while (entriesIt.hasNext()) {
+ Map.Entry entry = (Map.Entry)entriesIt.next();
+ typeMapFormals[i] = (Symbol)entry.getKey();
+ typeMapActuals[i] = (Type)entry.getValue();
+ ++i;
+ }
+ }
+
+ public void pushTypeSubst(Symbol[] from, Type[] to) {
+ assert from.length == to.length;
+ tmfStack.addLast(from);
+ tmaStack.addLast(to);
+ updateTypeSubst();
+ }
+
+ public void popTypeSubst() {
+ tmfStack.removeLast();
+ tmaStack.removeLast();
+ updateTypeSubst();
+ }
+
+ public void clearTypeSubst() {
+ tmfStack.clear();
+ tmaStack.clear();
+ updateTypeSubst();
+ }
+
+ public Tree transform(Tree tree) {
+ Tree newTree = super.transform(tree);
+ return syncTree(newTree);
+ }
+
+ // Update the tree so that:
+ // 1. names reflect the ones in symbols,
+ // 2. types reflect the ones in symbols.
+ // 3. modifiers reflect the ones in symbols.
+ public Tree syncTree(Tree tree) {
+ Name newName = null;
+ Type newType = null;
+ int newMods = -1;
+
+ if (tree.hasSymbol()) {
+ Symbol sym = tree.symbol();
+
+ newName = sym.name;
+ newType = smApplier.apply(typeMap.apply(sym.nextInfo()));
+ newMods = sym.flags;
+ }
+
+ switch (tree) {
+ case ClassDef(_, // fix Emacs :
+ _,
+ Tree.TypeDef[] tparams,
+ Tree.ValDef[][] vparams,
+ Tree tpe,
+ Tree.Template impl) :
+ return simpleCopy
+ .ClassDef(tree, newMods, newName, tparams, vparams, tpe, impl);
+
+ case ModuleDef(_, _, Tree tpe, Template impl):
+ return simpleCopy.ModuleDef(tree,
+ newMods,
+ newName,
+ gen.mkType(tpe.pos, newType),
+ impl);
+
+ case ValDef(int mods, Name name, Tree tpe, Tree rhs):
+ return simpleCopy.ValDef(tree,
+ newMods,
+ newName,
+ gen.mkType(tpe.pos, newType),
+ rhs);
+
+ case DefDef(_, // fix for Emacs :
+ Name name,
+ Tree.TypeDef[] tparams,
+ Tree.ValDef[][] vparams,
+ Tree tpe,
+ Tree rhs):
+ return simpleCopy.DefDef(tree,
+ newMods,
+ newName,
+ tparams,
+ vparams,
+ gen.mkType(tpe.pos, newType.resultType()),
+ rhs);
+
+ case Select(Tree qualifier, _):
+ return simpleCopy.Select(tree, qualifier, newName);
+
+ case Ident(_):
+ return simpleCopy.Ident(tree, newName);
+
+ // TODO add a case for TypeDef?
+
+ case Typed(Tree expr, Tree tpe): {
+ Type newType2 =
+ smApplier.apply(((Tree.Typed)tree).tpe.type);
+ return simpleCopy.Typed(tree,
+ expr,
+ gen.mkType(tpe.pos, newType2));
+ }
+
+ default:
+ return tree;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ public static class TCF extends StrictTreeFactory {
+ protected SubstTransformer transformer;
+ protected Map/*<Symbol,Symbol>*/ symbolMap;
+ protected SymbolMapApplier smApplier;
+ protected Type.Map typeMap;
+
+ public TCF(TreeFactory make) {
+ super(make);
+ }
+
+ public void setTransformer(SubstTransformer transformer) {
+ this.transformer = transformer;
+ this.symbolMap = transformer.symbolMap;
+ this.smApplier = transformer.smApplier;
+ this.typeMap = transformer.typeMap;
+ }
+
+ public void attribute(Tree newTree, Tree oldTree) {
+ if (oldTree.hasSymbol()) {
+ Symbol oldSym = oldTree.symbol();
+
+ if (transformer.mustSubstituteSymbol(oldTree)
+ && symbolMap.containsKey(oldSym)) {
+ newTree.setSymbol((Symbol)symbolMap.get(oldSym));
+ } else
+ newTree.setSymbol(oldTree.symbol());
+ }
+
+ newTree.type = smApplier.apply(typeMap.apply(oldTree.type));
+ }
+ }
+}
diff --git a/sources/scalac/ast/TreeCopier.java b/sources/scalac/ast/TreeCopier.java
new file mode 100644
index 0000000000..ad03cd6632
--- /dev/null
+++ b/sources/scalac/ast/TreeCopier.java
@@ -0,0 +1,91 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $OldId: TreeCopier.java,v 1.17 2002/06/13 12:04:12 schinz Exp $
+// $Id$
+
+package scalac.ast;
+
+import scalac.*;
+import scalac.util.Name;
+import scalac.symtab.*;
+import java.util.*;
+
+/**
+ * Superclass for tree copiers. Takes care of duplicating symbols and
+ * types when needed.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+public class TreeCopier extends SubstTransformer {
+ public TreeCopier(Global global,
+ PhaseDescriptor descr,
+ TreeFactory make) {
+ super(global, descr, make);
+ }
+
+ private boolean inPattern = false;
+
+ // Return true iff tree's symbol must be copied. By default,
+ // symbols which are defined are copied.
+ public boolean mustCopySymbol(Tree tree) {
+ switch (tree) {
+ case Ident(Name name):
+ return (inPattern && name.isVariable()) || tree.definesSymbol();
+ default:
+ return tree.definesSymbol();
+ }
+ }
+
+ public Tree copy(Tree tree) {
+ // Copy all symbols that have to be copied.
+ Traverser symCopier = new Traverser() {
+ public void traverse(Tree tree) {
+ if (tree.hasSymbol()) {
+ Symbol sym = tree.symbol();
+
+ if (sym != Symbol.NONE
+ && mustCopySymbol(tree)
+ && !symbolMap.containsKey(sym)) {
+ Symbol newSym = sym.cloneSymbol();
+
+ if (symbolMap.containsKey(newSym.owner()))
+ newSym.setOwner((Symbol)symbolMap.get(newSym.owner()));
+
+ symbolMap.put(sym, newSym);
+ }
+ }
+ switch (tree) {
+ case CaseDef(Tree pat, Tree guard, Tree body):
+ inPattern = true; traverse(pat); inPattern = false;
+ traverse(guard);
+ traverse(body);
+ break;
+ default:
+ super.traverse(tree);
+ }
+ }
+ };
+ symCopier.traverse(tree);
+
+ // Copy tree
+ Tree newTree = transform(tree);
+
+ // Update symbols
+ Iterator symbolsIt = symbolMap.entrySet().iterator();
+ while (symbolsIt.hasNext()) {
+ Map.Entry symPair = (Map.Entry)symbolsIt.next();
+ Symbol oldSym = (Symbol)symPair.getKey();
+ Symbol newSym = (Symbol)symPair.getValue();
+
+ newSym.setInfo(smApplier.apply(typeMap.apply(oldSym.info())));
+ }
+
+ return newTree;
+ }
+}
diff --git a/sources/scalac/symtab/SymbolMapApplier.java b/sources/scalac/symtab/SymbolMapApplier.java
new file mode 100644
index 0000000000..df46d83339
--- /dev/null
+++ b/sources/scalac/symtab/SymbolMapApplier.java
@@ -0,0 +1,86 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $OldId: SymbolMapApplier.java,v 1.6 2002/04/19 16:41:41 odersky Exp $
+// $Id$
+
+package scalac.symtab;
+
+import scalac.*;
+import scalac.symtab.*;
+import java.util.*;
+
+
+/**
+ * Apply a symbol substitution to various data (symbols and types).
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+public class SymbolMapApplier {
+ protected final Map map;
+
+ public SymbolMapApplier(Map map) {
+ this.map = map;
+ }
+
+ public Symbol apply(Symbol sym) {
+ return map.containsKey(sym) ? (Symbol)map.get(sym) : sym;
+ }
+
+ public Symbol[] apply(Symbol[] syms) {
+ Symbol[] newSyms = new Symbol[syms.length];
+ for (int i = 0; i < newSyms.length; ++i)
+ newSyms[i] = apply(syms[i]);
+ return newSyms;
+ }
+
+ public Type apply(Type type) {
+ switch (type) {
+ case ErrorType:
+ case AnyType:
+ case NoType:
+ return type;
+
+ case ThisType(Symbol sym):
+ return new Type.ThisType(apply(sym));
+
+ case TypeRef(Type prefix, Symbol sym, Type[] args):
+ return new Type.TypeRef(apply(prefix), apply(sym), apply(args));
+
+ case SingleType(Type pre, Symbol sym):
+ return Type.singleType(apply(pre), apply(sym));
+
+ case CompoundType(Type[] parts, Scope members):
+ return Type.compoundType(apply(parts), members, apply(type.symbol()));
+
+ case MethodType(Symbol[] params, Type restpe):
+ return new Type.MethodType(apply(params), apply(restpe));
+
+ case PolyType(Symbol[] tparams, Type restpe):
+ return new Type.PolyType(apply(tparams), apply(restpe));
+
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ return new Type.OverloadedType(apply(alts), apply(alttypes));
+
+ case CovarType(Type result):
+ return Type.CovarType(apply(result));
+
+ default:
+ throw new ApplicationError("unknown type " + type);
+ }
+ }
+
+ public Type[] apply(Type[] types) {
+ Type[] newTypes = new Type[types.length];
+ for (int i = 0; i < types.length; ++i)
+ newTypes[i] = apply(types[i]);
+ return newTypes;
+ }
+
+}
diff --git a/sources/scalac/transformer/AddInterfaces.java b/sources/scalac/transformer/AddInterfaces.java
new file mode 100644
index 0000000000..65c495a0f3
--- /dev/null
+++ b/sources/scalac/transformer/AddInterfaces.java
@@ -0,0 +1,781 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $OldId: AddInterfaces.java,v 1.40 2002/11/08 11:56:47 schinz Exp $
+// $Id$
+
+package scalac.transformer;
+
+import scalac.*;
+import scalac.util.*;
+import scalac.ast.*;
+import scalac.symtab.*;
+import Tree.*;
+
+import java.util.*;
+
+/**
+ * Add, for each class, an interface with the same name, to be used
+ * later by mixin expansion. More specifically:
+ *
+ * - at the end of the name of every class, the string "$class" is
+ * added,
+ *
+ * - an interface with the original name of the class is created, and
+ * contains all directly bound members of the class (as abstract
+ * members),
+ *
+ * - the interface is added to the mixin base classes of the class.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+class AddInterfaces extends SubstTransformer {
+ /** Mapping from class symbols to their interface symbol. */
+ public final Map/*<Symbol,Symbol>*/ classToInterface;
+
+ protected final Map/*<Symbol,Symbol>*/ ifaceToClass;
+ protected final SymbolMapApplier ifaceToClassApplier;
+ protected final Map/*<Symbol,Symbol>*/ ifaceMemberToClass;
+
+ // Mapping from class symbol to its type parameters mapping.
+ protected final Map/*<Symbol,Map<Symbol,Symbol>>*/ typeParamsMaps;
+
+ // Mapping from a class member symbol to its value and type
+ // parameters mapping.
+ protected final Map/*<Symbol,Map<Symbol,Symbol>>*/ funParamsMaps;
+
+ protected final Set/*<Symbol>*/ createdIFaces = new HashSet();
+
+ public AddInterfaces(Global global, AddInterfacesPhase descr) {
+ super(global, descr, global.make);
+ classToInterface = descr.classToInterface;
+ ifaceToClass = descr.interfaceToClass;
+ ifaceMemberToClass = descr.ifaceMemberToClass;
+
+ ifaceToClassApplier = new SymbolMapApplier(ifaceToClass);
+
+ typeParamsMaps = new HashMap();
+ funParamsMaps = new HashMap();
+ }
+
+ public void apply() {
+ // Phase 1: create all new symbols
+ ClassSymCreator creator = new ClassSymCreator(global);
+
+ for (int i = 0; i < global.units.length; ++i)
+ creator.traverse(global.units[i].body);
+
+ // Phase 2: transform the tree to add interfaces and use the
+ // new symbols where needed.
+ super.apply();
+ }
+
+ protected final static Tree.ValDef[][] EMPTY_PARAMS =
+ new Tree.ValDef[][]{ new Tree.ValDef[0] };
+
+ protected void uniqueName(Symbol sym, StringBuffer buf) {
+ Symbol owner = sym.owner();
+
+ if (owner != Symbol.NONE) {
+ uniqueName(owner, buf);
+ buf.append('$');
+ }
+
+ buf.append(sym.name.toString());
+ }
+
+ protected Name uniqueName(Symbol sym) {
+ StringBuffer buf = new StringBuffer();
+ uniqueName(sym, buf);
+ return Name.fromString(buf.toString());
+ }
+
+ protected final static String CLASS_SUFFIX = "$class";
+
+ protected boolean hasClassSuffix(Name name) {
+ return name.toString().endsWith(CLASS_SUFFIX);
+ }
+
+ protected Name className(Name interfaceName) {
+ assert !hasClassSuffix(interfaceName) : interfaceName;
+
+ String interfaceStr = interfaceName.toString();
+ return Name.fromString(interfaceStr + CLASS_SUFFIX);
+ }
+
+ // Modifiers for which we do not create interfaces.
+ protected int NO_INTERFACE_MODS = (Modifiers.MODUL | Modifiers.SYNTHETIC);
+
+ protected boolean needInterface(Symbol sym) {
+ return (sym.enclClass().flags & NO_INTERFACE_MODS) == 0;
+ }
+
+ protected boolean memberGoesInInterface(Symbol member) {
+ switch (member.kind) {
+ case Kinds.TYPE: case Kinds.ALIAS:
+ return true;
+ case Kinds.CLASS:
+ return needInterface(member);
+ case Kinds.VAL:
+ return member.isMethod();
+ default:
+ throw Debug.abort("unknown kind: " + member.kind);
+ }
+ }
+
+ protected Type removeValueParams(Type tp) {
+ switch (tp) {
+ case MethodType(Symbol[] vparams, Type result):
+ return new Type.MethodType(Symbol.EMPTY_ARRAY, result);
+ case PolyType(Symbol[] tps, Type result):
+ return new Type.PolyType(tps, removeValueParams(result));
+ default:
+ return tp;
+ }
+ }
+
+ protected Tree mkAbstract(Tree tree) {
+ Symbol symbol = tree.symbol();
+
+ if (symbol.isMethod())
+ return gen.DefDef(symbol, Tree.Empty);
+ else switch (symbol.kind) {
+ case Kinds.TYPE: case Kinds.ALIAS:
+ return tree;
+ case Kinds.CLASS:
+ return classInterface((ClassDef)tree);
+ default:
+ throw new ApplicationError("invalid symbol kind for me", symbol);
+ }
+ }
+
+ protected Symbol getClassSym(Symbol ifaceSym) {
+ assert !hasClassSuffix(ifaceSym.name) : ifaceSym.name;
+
+ if (!needInterface(ifaceSym)) {
+ return ifaceSym;
+ } else {
+ if (!ifaceToClass.containsKey(ifaceSym)) {
+ Symbol classSym;
+
+ Name ifaceName = ifaceSym.enclClass().fullName();
+ classSym = global.definitions.getClass(className(ifaceName));
+ if (ifaceSym.isPrimaryConstructor()) {
+ classSym = classSym.constructor();
+ }
+
+ if (classSym == Symbol.NONE && (ifaceSym.flags & Modifiers.JAVA) != 0) {
+ // Java symbols do not have corresponding classes
+ return ifaceSym;
+ }
+
+ assert classSym != Symbol.NONE : ifaceSym;
+
+ ifaceToClass.put(ifaceSym, classSym);
+ classToInterface.put(classSym, ifaceSym);
+ }
+
+ return (Symbol)ifaceToClass.get(ifaceSym);
+ }
+ }
+
+ protected Symbol[] vparams(Type tp) {
+ switch (tp) {
+ case MethodType(Symbol[] vparams, _):
+ return vparams;
+ case PolyType(_, Type result):
+ return vparams(result);
+ case OverloadedType(_, _):
+ throw global.fail("can't get vparams of this type", tp);
+ default:
+ return Symbol.EMPTY_ARRAY;
+ }
+ }
+
+ protected Type cloneSymbolsInMethodType(Type type,
+ SymbolMapApplier smApplier,
+ Map symbolMap) {
+ switch (type) {
+ case NoType:
+ case ThisType(_):
+ case TypeRef(_, _, _):
+ case SingleType(_, _):
+ case CompoundType(_, _):
+ return type;
+
+ case MethodType(Symbol[] vparams, Type result): {
+ Symbol[] newVParams = new Symbol[vparams.length];
+ for (int i = 0; i < vparams.length; ++i) {
+ newVParams[i] = vparams[i].cloneSymbol();
+ newVParams[i].setType(smApplier.apply(newVParams[i].info()));
+ symbolMap.put(vparams[i], newVParams[i]);
+ }
+ return new Type.MethodType(newVParams,
+ cloneSymbolsInMethodType(result,
+ smApplier,
+ symbolMap));
+ }
+
+ case PolyType(Symbol[] tparams, Type result): {
+ Symbol[] newTParams = new Symbol[tparams.length];
+ for (int i = 0; i < tparams.length; ++i) {
+ newTParams[i] = tparams[i].cloneSymbol();
+ symbolMap.put(tparams[i], newTParams[i]);
+ }
+ return new Type.PolyType(newTParams,
+ cloneSymbolsInMethodType(result,
+ smApplier,
+ symbolMap));
+ }
+
+ default:
+ throw global.fail("unexpected method type: " + Debug.toString(type));
+ }
+ }
+
+ // Return the interface corresponding to the given class.
+ protected Tree classInterface(ClassDef classDef) {
+ Template impl = classDef.impl;
+ Symbol ifaceSym = classDef.symbol();
+
+ // Create tree for interface.
+ List/*<Tree>*/ ifaceBody = new ArrayList();
+ Tree[] body = impl.body;
+ for (int i = 0; i < body.length; ++i) {
+ Tree elem = body[i];
+ if (elem.hasSymbol() && elem.symbol().owner() == ifaceSym) {
+ Symbol sym = elem.symbol();
+ if (memberGoesInInterface(elem.symbol()))
+ ifaceBody.add(mkAbstract(elem));
+ }
+ }
+
+ Tree[] parentConstr =
+ gen.mkParentConstrs(impl.pos, ifaceSym.nextInfo().parents(), null);
+ Template ifaceTmpl =
+ make.Template(impl.pos,
+ parentConstr,
+ (Tree[])ifaceBody.toArray(new Tree[ifaceBody.size()]));
+ ifaceTmpl.setSymbol(impl.symbol().cloneSymbol());
+ ifaceTmpl.setType(ifaceSym.nextInfo());
+
+ int ifaceMods = classDef.mods
+ | Modifiers.ABSTRACTCLASS
+ | Modifiers.INTERFACE
+ | Modifiers.STATIC;
+ ClassDef interfaceDef = (ClassDef)make.ClassDef(classDef.pos,
+ ifaceMods,
+ classDef.name,
+ classDef.tparams,
+ EMPTY_PARAMS,
+ classDef.tpe,
+ ifaceTmpl);
+ interfaceDef.setType(Type.NoType);
+ interfaceDef.setSymbol(ifaceSym);
+
+ createdIFaces.add(ifaceSym);
+
+ return interfaceDef;
+ }
+
+ protected Type fixClassSymbols(Type type) {
+ switch (type) {
+ case Type.NoType:
+ return type;
+ case ThisType(Symbol sym):
+ return new Type.ThisType(getClassSym(sym));
+ case TypeRef(Type pre, Symbol sym, Type[] args):
+ return new Type.TypeRef(fixClassSymbols(pre), getClassSym(sym), args);
+ case SingleType(Type pre, Symbol sym):
+ return Type.singleType(fixClassSymbols(pre), getClassSym(sym));
+ case CompoundType(Type[] parts, Scope members):
+ return Type.compoundType(fixClassSymbols(parts),
+ members,
+ getClassSym(type.symbol()));
+ case MethodType(Symbol[] vparams, Type result):
+ return new Type.MethodType(vparams, fixClassSymbols(result));
+ case PolyType(Symbol[] tparams, Type result):
+ return new Type.PolyType(tparams, fixClassSymbols(result));
+ default:
+ throw global.fail("unexpected type ",type);
+ }
+ }
+
+ protected Type[] fixClassSymbols(Type[] types) {
+ Type[] newTypes = new Type[types.length];
+ for (int i = 0; i < types.length; ++i)
+ newTypes[i] = fixClassSymbols(types[i]);
+ return newTypes;
+ }
+
+ protected Tree fixClassSymbols(Tree tree) {
+ switch (tree) {
+ case Apply(Tree fun, Tree[] args):
+ return copy.Apply(tree, fixClassSymbols(fun), args);
+ case TypeApply(Tree fun, Tree[] args):
+ return copy.TypeApply(tree, fixClassSymbols(fun), args);
+ case Select(Tree qualifier, Name selector): {
+ Symbol classSym = getClassSym(tree.symbol());
+ return copy.Select(tree, qualifier, classSym.name).setSymbol(classSym);
+ }
+ case Ident(Name name): {
+ Symbol classSym = getClassSym(tree.symbol());
+ return copy.Ident(tree, classSym.name).setSymbol(classSym);
+ }
+ default:
+ throw global.fail("unexpected tree",tree);
+ }
+ }
+
+ protected LinkedList/*<List<Tree>>*/ bodyStack = new LinkedList();
+
+ public Tree[] transform(Tree[] trees) {
+ List newTrees = new ArrayList();
+
+ bodyStack.addFirst(newTrees);
+
+ for (int i = 0; i < trees.length; ++i)
+ newTrees.add(transform(trees[i]));
+
+ bodyStack.removeFirst();
+
+ return (Tree[]) newTrees.toArray(new Tree[newTrees.size()]);
+ }
+
+ public TypeDef[] transform(TypeDef[] ts) {
+ return super.transform(ts);
+ }
+
+ public Tree transform(Tree tree) {
+ if (tree.hasSymbol()) {
+ Symbol sym = tree.symbol();
+ if (sym != Symbol.NONE) {
+ Symbol owner = sym.owner();
+ if (ifaceMemberToClass.containsKey(owner)) {
+ sym.setOwner((Symbol)ifaceMemberToClass.get(owner));
+ }
+ }
+ }
+
+ switch (tree) {
+ case ClassDef(int mods,
+ Name name,
+ TypeDef[] tparams,
+ ValDef[][] vparams,
+ Tree tpe,
+ Template impl) : {
+ global.log("adding interface for " + tree.symbol()
+ + " (need one? " + needInterface(tree.symbol()) + ")");
+
+ Symbol interfaceSym = tree.symbol();
+
+ if (needInterface(interfaceSym)) {
+ ClassDef classDef = (ClassDef) tree;
+
+ // First insert interface for class in enclosing body...
+ if (! createdIFaces.contains(interfaceSym)) {
+ Tree interfaceDef = classInterface(classDef);
+ List/*<Tree>*/ enclosingBody = (List)bodyStack.getFirst();
+ enclosingBody.add(interfaceDef);
+ }
+
+ // ...then transform the class.
+ Symbol classSym = getClassSym(interfaceSym);
+
+ assert typeParamsMaps.containsKey(classSym) : classSym;
+ Map/*<Symbol,Symbol>*/ tparamsMap = (Map)typeParamsMaps.get(classSym);
+ SymbolMapApplier tparamsSM = new SymbolMapApplier(tparamsMap);
+
+ // Make the class implement the interface, and make sure
+ // to use class symbols for base classes.
+ Type interfaceBaseType = tparamsSM.apply(interfaceSym.type());
+ Type[] newBaseTypes;
+
+ // 1. modify type of class symbol
+ Type newClassInfo;
+ switch (classSym.nextInfo()) {
+ case CompoundType(Type[] baseTypes, Scope members): {
+ newBaseTypes = new Type[baseTypes.length + 1];
+ newBaseTypes[0] = fixClassSymbols(baseTypes[0]);
+ newBaseTypes[1] = interfaceBaseType;
+ for (int i = 2; i < newBaseTypes.length; ++i)
+ newBaseTypes[i] = fixClassSymbols(baseTypes[i-1]);
+ newClassInfo = Type.compoundType(newBaseTypes, members, classSym);
+ classSym.updateInfo(newClassInfo);
+ } break;
+
+ default:
+ throw global.fail("invalid info() for class", classSym);
+ }
+
+ // 2. modify tree accordingly
+ pushSymbolSubst(tparamsMap);
+ Tree[] parents = transform(impl.parents);
+
+ Tree[] newParents = new Tree[parents.length + 1];
+ newParents[0] = parents[0];
+ newParents[1] = gen.mkParentConstr(impl.pos, interfaceBaseType, null);
+ for (int i = 2; i < newParents.length; ++i)
+ newParents[i] = parents[i-1];
+
+ // Use new member symbols for class members.
+ Tree[] body = impl.body;
+ for (int i = 0; i < body.length; ++i) {
+ Tree member = body[i];
+ if (member.hasSymbol()) {
+ Symbol sym = member.symbol();
+ if (sym.kind != Kinds.CLASS
+ && ifaceMemberToClass.containsKey(sym))
+ member.setSymbol((Symbol)ifaceMemberToClass.get(sym));
+ }
+ }
+
+ // Transform body
+ List newBody = new LinkedList();
+ for (int i = 0; i < body.length; ++i) {
+ switch (body[i]) {
+ case TypeDef(_, _, _, _):
+ break;
+ default:
+ newBody.add(transform(body[i]));
+ }
+ }
+ Template newImpl =
+ copy.Template(impl,
+ newParents,
+ (Tree[])newBody.toArray(new Tree[newBody.size()]));
+ newImpl.setType(newClassInfo);
+
+ Tree newTree =
+ copy.ClassDef(classDef,
+ classSym.flags,
+ classSym.name.toTypeName(),
+ transform(tparams),
+ transform(vparams),
+ transform(tpe),
+ newImpl)
+ .setSymbol(classSym);
+
+ popSymbolSubst();
+
+ return newTree;
+ } else {
+ // No interface needed, we just adapt the class type
+ // to use class symbols.
+ Symbol classSym = interfaceSym;
+ classSym.updateInfo(fixClassSymbols(classSym.info()));
+ return super.transform(tree);
+ }
+ }
+
+ case Template(Tree[] parents, Tree[] body): {
+ return copy.Template(tree, transform(parents), transform(body))
+ .setType(fixClassSymbols(tree.type));
+ }
+
+ case DefDef(_, _, _, _, _, _): {
+ Symbol sym = tree.symbol();
+ if (funParamsMaps.containsKey(sym)) {
+ Map funParamsMap = (Map)funParamsMaps.get(sym);
+ pushSymbolSubst(funParamsMap);
+ Tree newTree = super.transform(tree);
+ popSymbolSubst();
+ return newTree;
+ }
+ return super.transform(tree);
+ }
+
+ case Select(Super(_), Name selector): {
+ // Use class member symbol for "super" references.
+ Symbol sym = tree.symbol();
+ if (needInterface(sym.classOwner())) {
+ assert ifaceMemberToClass.containsKey(sym);
+ Symbol classSym = (Symbol)ifaceMemberToClass.get(sym);
+ return super.transform(tree).setSymbol(classSym);
+ } else
+ return super.transform(tree);
+ }
+
+ default: {
+ Tree newTree = super.transform(tree);
+
+ // Use class symbols for constructor calls.
+ switch (newTree) {
+ case New(Template templ):
+ return copy.New(newTree, templ)
+ .setType(templ.parents[0].type);
+
+ case Apply(TypeApply(Tree fun, Tree[] targs), Tree[] vargs): {
+ Tree tFun = ((Tree.Apply)newTree).fun;
+ if (fun.symbol().isPrimaryConstructor())
+ return copy.Apply(newTree, tFun, vargs)
+ .setType(fixClassSymbols(newTree.type));
+ else
+ return newTree;
+ }
+
+ case Apply(Tree fun, Tree[] args): {
+ Symbol sym = fun.symbol();
+
+ if (sym.isPrimaryConstructor()) {
+ fun.setSymbol(getClassSym(sym));
+ fun.setType(fixClassSymbols(fun.type));
+ return (copy.Apply(newTree, super.syncTree(fun), args))
+ .setType(fixClassSymbols(newTree.type));
+ } else
+ return newTree;
+ }
+
+ case TypeApply(Tree fun, Tree[] args): {
+ if (fun.symbol().isPrimaryConstructor()) {
+ fun.setSymbol(getClassSym(fun.symbol()));
+ fun.setType(fixClassSymbols(fun.type));
+ return (copy.TypeApply(newTree, super.syncTree(fun), args))
+ .setType(fixClassSymbols(newTree.type));
+ } else
+ return newTree;
+ }
+ default:
+ return newTree;
+ }
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ // Class
+ protected class ClassSymCreator extends Traverser {
+ // Mapping from interface type parameters to class type
+ // parameters.
+ final HashMap/*<Symbol,Symbol>*/ tparamsMap = new HashMap();
+
+ public ClassSymCreator(Global global) {
+ super(global);
+ }
+
+ protected Symbol cloneAndMaybeRenameSymbol(Symbol sym) {
+ assert !sym.isPrimaryConstructor() : sym;
+
+ Symbol clone = sym.cloneSymbol();
+ if (clone.kind == Kinds.CLASS) {
+ clone.name = className(clone.name);
+ Symbol constrClone = clone.constructor();
+ constrClone.name = className(constrClone.name);
+ }
+ return clone;
+ }
+
+ protected void makeClassSymbol(Symbol ifaceSym) {
+ Symbol classSym = cloneAndMaybeRenameSymbol(ifaceSym);
+ ifaceToClass.put(ifaceSym, classSym);
+ ifaceToClass.put(ifaceSym.constructor(), classSym.constructor());
+ }
+
+ public void traverse(Tree tree) {
+ switch(tree) {
+ case ClassDef(_, _, _, _, _, Template impl): {
+ Symbol ifaceSym = tree.symbol();
+
+ if (!needInterface(ifaceSym)) {
+ super.traverse(impl);
+ break;
+ }
+
+ // The class needs an interface. Create new symbols
+ // for the class itself, its constructor, its type
+ // parameters and its members. Then modify what was
+ // the class symbol to turn it into an interface
+ // symbol.
+
+ // At the end of this part, one inconsistency remains:
+ // the base types of the new class symbols still refer
+ // to interface symbols. This is fixed later, when
+ // symbols exist for *all* classes.
+
+ Symbol ifaceConstrSym = ifaceSym.constructor();
+ ifaceConstrSym.updateInfo(removeValueParams(ifaceConstrSym.info()));
+
+ if (! ifaceToClass.containsKey(ifaceSym))
+ makeClassSymbol(ifaceSym);
+ Symbol classSym = (Symbol)ifaceToClass.get(ifaceSym);
+ Symbol classConstrSym = classSym.constructor();
+
+ if (ifaceToClass.containsKey(classSym.owner())) {
+ Symbol newOwner = (Symbol)ifaceToClass.get(classSym.owner());
+ classSym.setOwner(newOwner);
+ classConstrSym.setOwner(newOwner);
+ }
+
+ Symbol[] ifaceTParams = ifaceSym.typeParams();
+ if (ifaceTParams.length > 0) {
+ for (int i = 0; i < ifaceTParams.length; ++i) {
+ Symbol classTParam = ifaceTParams[i].cloneSymbol();
+ classTParam.setOwner(classConstrSym);
+ tparamsMap.put(ifaceTParams[i], classTParam);
+ }
+ }
+ assert !typeParamsMaps.containsKey(classSym);
+ Map cloneMap = new HashMap();
+ cloneMap.putAll(tparamsMap);
+ typeParamsMaps.put(classSym, cloneMap);
+
+ SymbolMapApplier tparamsSM = new SymbolMapApplier(cloneMap);
+
+ classConstrSym.setInfo(tparamsSM.apply(classConstrSym.info()));
+ Symbol[] vparams = vparams(classConstrSym.nextInfo());
+ for (int i = 0; i < vparams.length; ++i)
+ vparams[i].updateInfo(tparamsSM.apply(vparams[i].info()));
+
+ Scope newIFaceMembers = new Scope();
+ Scope classMembers = new Scope();
+ Scope.SymbolIterator symIt = ifaceSym.members().iterator();
+ while (symIt.hasNext()) {
+ Symbol ifaceMemberSym = symIt.next();
+
+ ifaceMemberSym.updateInfo(tparamsSM.apply(ifaceMemberSym.info()));
+
+ if (! memberGoesInInterface(ifaceMemberSym)) {
+ ifaceMemberSym.setOwner(classSym);
+ classMembers.enter(ifaceMemberSym);
+ continue;
+ }
+
+ // When encountering a constructor of a nested
+ // class, clone its class to make sure the
+ // constructor is cloned correctly.
+ if (ifaceMemberSym.isPrimaryConstructor()
+ && !ifaceToClass.containsKey(ifaceMemberSym)) {
+ makeClassSymbol(ifaceMemberSym.primaryConstructorClass());
+ }
+
+ // Make private members public and give them a
+ // unique name.
+ if (Modifiers.Helper.isPrivate(ifaceMemberSym.flags)) {
+ ifaceMemberSym.name = uniqueName(ifaceMemberSym);
+ ifaceMemberSym.flags ^= Modifiers.PRIVATE;
+ }
+ ifaceMemberSym.flags &= ~Modifiers.PROTECTED;
+
+ newIFaceMembers.enter(ifaceMemberSym);
+
+ // Type members are moved to the interface.
+ // Therefore, no symbol has to be created for
+ // their class equivalent.
+ if (ifaceMemberSym.kind == Kinds.TYPE
+ || ifaceMemberSym.kind == Kinds.ALIAS)
+ continue;
+
+ Symbol[] alternatives = ifaceMemberSym.alternatives();
+ Symbol classMemberSym = null;
+
+ for (int a = 0; a < alternatives.length; ++a) {
+ Symbol iSym = alternatives[a];
+ Symbol cSym;
+
+ if (Modifiers.Helper.isPrivate(iSym.flags)) {
+ iSym.name = uniqueName(iSym);
+ iSym.flags ^= Modifiers.PRIVATE;
+ }
+ iSym.flags &= ~Modifiers.PROTECTED;
+
+ if (ifaceToClass.containsKey(iSym))
+ cSym = (Symbol)ifaceToClass.get(iSym);
+ else
+ cSym = cloneAndMaybeRenameSymbol(iSym);
+
+ iSym.updateInfo(tparamsSM.apply(iSym.info()));
+ cSym.setInfo(tparamsSM.apply(cSym.info()));
+
+ Symbol[] vpms = vparams(iSym.nextInfo());
+ for (int p = 0; p < vpms.length; ++p)
+ vpms[p].updateInfo(tparamsSM.apply(vpms[p].info()));
+
+ // Clone parameter symbols for methods.
+ if (cSym.isMethod()) {
+ Map funSymMap = new HashMap();
+ Type newInfo = cloneSymbolsInMethodType(cSym.info(),
+ tparamsSM,
+ funSymMap);
+ if (! funSymMap.isEmpty())
+ funParamsMaps.put(cSym, funSymMap);
+ }
+
+ cSym.setOwner(classSym);
+ classMemberSym = (classMemberSym == null
+ ? cSym
+ : classMemberSym.overloadWith(cSym));
+
+ if (iSym.kind == Kinds.CLASS) {
+ ifaceToClass.put(iSym, cSym);
+ ifaceToClass.put(iSym.constructor(), cSym.constructor());
+ } else {
+ iSym.flags |= Modifiers.ABSTRACT;
+ ifaceMemberToClass.put(iSym, cSym);
+ }
+ }
+ if (!ifaceMemberToClass.containsKey(ifaceMemberSym)
+ && ifaceMemberSym.kind != Kinds.CLASS)
+ ifaceMemberToClass.put(ifaceMemberSym, classMemberSym);
+ classMembers.enter(classMemberSym);
+ }
+
+ switch (classSym.info()) {
+ case CompoundType(Type[] parts, Scope members):
+ classSym.setInfo(Type.compoundType(tparamsSM.apply(parts),
+ classMembers,
+ classSym));
+ break;
+
+ default:
+ global.fail("unexpected type for class", ifaceSym.info());
+ }
+
+ Type cConstrType = classConstrSym.info();
+ classConstrSym.updateInfo(cConstrType.subst(new Symbol[]{ifaceSym},
+ new Symbol[]{classSym}));
+
+ ifaceSym.flags |=
+ (Modifiers.ABSTRACTCLASS | Modifiers.INTERFACE | Modifiers.STATIC);
+
+ classToInterface.put(classSym, ifaceSym);
+ super.traverse(impl);
+
+ if (ifaceTParams.length > 0)
+ for (int i = 0; i < ifaceTParams.length; ++i)
+ tparamsMap.remove(ifaceTParams[i]);
+
+ // Remove Java classes from interface base classes.
+ switch (ifaceSym.info()) {
+ case CompoundType(Type[] basetypes, Scope members):
+ ArrayList newBT_L = new ArrayList(basetypes.length);
+ for (int i = 0; i < basetypes.length; ++i)
+ if (! basetypes[i].symbol().isJava())
+ newBT_L.add(basetypes[i]);
+ Type[] newBT;
+ if (newBT_L.size() != basetypes.length)
+ newBT = (Type[]) newBT_L.toArray(new Type[newBT_L.size()]);
+ else
+ newBT = basetypes;
+ ifaceSym.updateInfo(Type.compoundType(newBT,
+ newIFaceMembers,
+ ifaceSym));
+ break;
+
+ default:
+ Debug.abort("unexpected type for class", ifaceSym.info());
+ }
+ } break;
+
+ default:
+ super.traverse(tree);
+ }
+ }
+ }
+}
diff --git a/sources/scalac/transformer/AddInterfacesPhase.java b/sources/scalac/transformer/AddInterfacesPhase.java
new file mode 100644
index 0000000000..47b30761c0
--- /dev/null
+++ b/sources/scalac/transformer/AddInterfacesPhase.java
@@ -0,0 +1,54 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $OldId: AddInterfacesPhase.java,v 1.9 2002/04/19 10:55:15 schinz Exp $
+// $Id$
+
+package scalac.transformer;
+
+import scalac.*;
+import scalac.checkers.*;
+import java.util.*;
+
+
+public class AddInterfacesPhase extends PhaseDescriptor {
+ /** Mapping from class symbols to their interface symbol.
+ */
+ public final Map/*<Symbol,Symbol>*/ classToInterface = new HashMap();
+
+ /** Mapping from interface symbols to class symbols.
+ */
+ protected final Map/*<Symbol,Symbol>*/ interfaceToClass = new HashMap();
+
+ /** Mapping from interface member symbols to class member symbols.
+ */
+ protected final Map/*<Symbol,Symbol>*/ ifaceMemberToClass = new HashMap();
+
+ public String name () {
+ return "addinterfaces";
+ }
+
+ public String description () {
+ return "add one interface per class";
+ }
+
+ public String taskDescription() {
+ return "added interfaces";
+ }
+
+ public Phase createPhase(Global global) {
+ return new AddInterfaces(global, this);
+ }
+
+ public Checker[] postCheckers(Global global) {
+ return new Checker[] {
+ new CheckSymbols(global),
+ new CheckTypes(global),
+ new CheckOwners(global)
+ };
+ }
+}
diff --git a/sources/scalac/transformer/ExpandMixins.java b/sources/scalac/transformer/ExpandMixins.java
new file mode 100644
index 0000000000..088f392f63
--- /dev/null
+++ b/sources/scalac/transformer/ExpandMixins.java
@@ -0,0 +1,426 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ 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 scalac.*;
+import scalac.util.*;
+import scalac.ast.*;
+import scalac.symtab.*;
+import java.util.*;
+import java.util.Arrays;
+import Tree.*;
+
+/**
+ * A transformer to expand mixins using code copying. We assume that
+ * links to outer classes have been made explicit by a previous phase.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+// [...] do not copy hidden members which are not accessible via
+// "super"
+// [...] handle overloaded symbols
+
+public class ExpandMixins extends Transformer {
+ // Mapping from (class) symbols to their definition.
+ protected final Map/*<Symbol,Tree>*/ classDefs;
+
+ protected final FreshNameCreator freshNameCreator;
+ protected final Map interfaceToClass;
+ protected final Map classToInterface;
+
+ protected final static int PRIVATE_FINAL = Modifiers.FINAL | Modifiers.PRIVATE;
+
+ protected final TreeCopier treeCopier;
+ protected final Definitions defs;
+
+ public ExpandMixins(Global global, ExpandMixinsPhase descr) {
+ super(global, descr);
+ defs = global.definitions;
+
+ classToInterface = global.PHASE.ADDINTERFACES.classToInterface;
+ interfaceToClass = global.PHASE.ADDINTERFACES.interfaceToClass;
+
+ classDefs = descr.classDefs;
+
+ freshNameCreator = global.freshNameCreator;
+
+ treeCopier = new TreeCopier(global, descr, global.make) {
+ // Substitute symbols refering to this class only.
+ public boolean mustSubstituteSymbol(Tree tree) {
+ switch (tree) {
+ case Ident(_):
+ case Select(This(_), _):
+ return true;
+
+ default:
+ return mustCopySymbol(tree);
+ }
+ }
+ };
+ }
+
+ public void apply() {
+ ClassDefCollector collector = new ClassDefCollector(classDefs);
+
+ for (int i = 0; i < global.units.length; i++) {
+ Unit unit = global.units[i];
+ for (int j = 0; j < unit.body.length; ++j)
+ collector.traverse(unit.body[j]);
+ }
+
+ super.apply();
+ }
+
+ protected void typeSubst(Type type, ArrayList f, ArrayList a) {
+ switch (type) {
+ case TypeRef(Type pre, Symbol sym, Type[] args): {
+ Symbol s;
+ if (interfaceToClass.containsKey(sym))
+ s = (Symbol)interfaceToClass.get(sym);
+ else
+ s = sym;
+
+ f.addAll(Arrays.asList(s.typeParams()));
+ a.addAll(Arrays.asList(args));
+ typeSubst(pre, f, a);
+ } break;
+ default:
+ ; // nothing to do
+ }
+ }
+
+ protected Object[] typeSubst(Type type) {
+ ArrayList/*<Symbol[]>*/ f = new ArrayList();
+ ArrayList/*<Type[]>*/ a = new ArrayList();
+ typeSubst(type, f, a);
+ return new Object[] {
+ f.toArray(new Symbol[f.size()]), a.toArray(new Type[a.size()])
+ };
+ }
+
+ protected void getArgsSection(Tree tree, List s) {
+ switch(tree) {
+ case Apply(Tree fun, Tree[] args):
+ getArgsSection(fun, s);
+ s.add(args);
+ break;
+
+ default:
+ ; // nothing to do
+ }
+ }
+
+ protected Tree[][] getArgsSection(Tree tree) {
+ List s = new ArrayList();
+ getArgsSection(tree, s);
+ return (Tree[][])s.toArray(new Tree[s.size()][]);
+ }
+
+ protected Symbol renameSymbol(Map symbolMap, Symbol oldSymbol) {
+ Name newName = freshNameCreator.newName(oldSymbol.name);
+ Symbol newSymbol = oldSymbol.cloneSymbol();
+ newSymbol.name = newName;
+ symbolMap.put(oldSymbol, newSymbol);
+
+ return newSymbol;
+ }
+
+ protected Map/*<Template,Template>*/ expansions = new HashMap();
+
+ protected Template getMixinExpandedTemplate(Template tree, Symbol owner) {
+ if (! expansions.containsKey(tree))
+ expansions.put(tree, expandMixins(tree, owner));
+ return (Template)expansions.get(tree);
+ }
+
+ protected Template expandMixins(Template tree, Symbol owner) {
+ Type templType = tree.type;
+
+ List/*<Tree>*/ newBody = new ArrayList();
+ Scope newMembers = new Scope();
+
+ Map mixedInSymbols/*<Symbol,Symbol>*/ = new HashMap();
+
+ Symbol newTemplSymbol = tree.symbol().cloneSymbol();
+
+ // Start by copying the statement sequence.
+ Tree[] body = tree.body;
+ for (int i = 0; i < body.length; ++i) {
+ Tree stat = body[i];
+ newBody.add(transform(stat));
+
+ if (stat.hasSymbol()) {
+ Symbol sym = stat.symbol();
+ newMembers.enter(sym);
+ }
+ }
+
+ Type[] baseTypes = tree.type.parents();
+ global.log("baseTypes = <" + ArrayApply.toString(baseTypes) + ">");
+
+ // Then go over the mixins and mix them in.
+ for (int bcIndex = tree.parents.length - 1; bcIndex > 0; --bcIndex) {
+ Tree bc = tree.parents[bcIndex];
+
+ Symbol bcSym = baseTypes[bcIndex].symbol();
+ Type bcType = bcSym.type();
+
+ if ((bcSym.flags & Modifiers.INTERFACE) != 0)
+ continue;
+
+ assert classDefs.containsKey(bcSym) : bcSym;
+ ClassDef bcDef = (ClassDef)classDefs.get(bcSym);
+
+ Map symbolMap/*<Symbol,Symbol>*/ = new HashMap();
+
+ // Create substitution for mixin's type parameters.
+ Object[] ts = typeSubst(baseTypes[bcIndex]);
+ assert ts.length == 2;
+ final Symbol[] tpFormals = (Symbol[])ts[0];
+ final Type[] tpActuals = (Type[])ts[1];
+ assert tpFormals.length == tpActuals.length;
+ Type.Map typeMap = new Type.Map() {
+ public Type apply(Type t) {
+ return t.subst(tpFormals, tpActuals);
+ }
+ };
+
+ // Create private fields for mixin's value parameters.
+ Tree[][] actuals = getArgsSection(bc);
+ assert bcDef.vparams.length == actuals.length;
+ for (int s = 0; s < bcDef.vparams.length; ++s) {
+ ValDef[] sectionF = bcDef.vparams[s];
+ Tree[] sectionA = actuals[s];
+
+ assert sectionF.length == sectionA.length;
+
+ for (int p = 0; p < sectionF.length; ++p) {
+ // We do not need to copy the actual parameters,
+ // since they are removed from their original
+ // location anyway.
+ ValDef formal = sectionF[p];
+ Tree actual = sectionA[p];
+
+ Symbol memberSymbol =
+ renameSymbol(symbolMap, formal.symbol());
+ memberSymbol.setOwner(owner);
+ Type memberType = typeMap.apply(formal.tpe.type());
+ memberSymbol.updateInfo(memberType);
+
+ Tree memberDef = gen.ValDef(memberSymbol, actual);
+ newBody.add(memberDef);
+ }
+ }
+
+ Template mixin = getMixinExpandedTemplate(bcDef.impl, bcSym);
+ Tree[] mixinBody = mixin.body;
+ Set/*<Tree>*/ leftOutMembers = new HashSet();
+
+ // Pass 1: compute members to rename.
+ for (int m = 0; m < mixinBody.length; ++m) {
+ Tree member = mixinBody[m];
+
+ if (!member.hasSymbol())
+ continue;
+
+ Symbol memSym = member.symbol();
+ Name memName = memSym.name;
+
+ // Check if we have to import this member. To do this,
+ // we lookup the member both in the template and in
+ // the mixin, and if the result is the same, we import
+ // the member (otherwise it means it's shadowed).
+
+ Symbol memSymT = templType.lookupNonPrivate(memName);
+ Symbol memSymM = bcType.lookupNonPrivate(memName);
+
+ if (memSymT != memSymM) {
+ if ((memSym.flags & Modifiers.ABSTRACT) != 0)
+ leftOutMembers.add(member);
+ else
+ renameSymbol(symbolMap, memSym);
+ }
+ }
+
+ // Pass 2: copy members
+ for (int m = 0; m < mixinBody.length; ++m) {
+ Tree member = mixinBody[m];
+
+ if (leftOutMembers.contains(member))
+ continue;
+
+ treeCopier.pushSymbolSubst(symbolMap);
+ treeCopier.pushTypeSubst(tpFormals, tpActuals);
+ Tree newMember = treeCopier.copy(member);
+ treeCopier.popTypeSubst();
+ treeCopier.popSymbolSubst();
+
+ newBody.add(newMember);
+
+ if (newMember.hasSymbol()) {
+ Symbol sym = newMember.symbol();
+
+ sym.setOwner(owner);
+ newMembers.enter(sym);
+
+ mixedInSymbols.put(member.symbol(), newMember.symbol());
+ }
+ }
+ }
+
+ // Modify mixin base classes to refer to interfaces instead of
+ // real classes.
+ Type[] newBaseTypes = new Type[baseTypes.length];
+ Tree[] newBaseClasses = new Tree[tree.parents.length];
+ newBaseTypes[0] = baseTypes[0];
+ newBaseClasses[0] = tree.parents[0];
+ for (int i = 1; i < baseTypes.length; ++i) {
+ switch (baseTypes[i]) {
+ case TypeRef(Type pre, Symbol sym, Type[] args): {
+ if (!Modifiers.Helper.isInterface(sym.flags) && i > 0) {
+ assert classToInterface.containsKey(sym) : sym;
+ sym = (Symbol)classToInterface.get(sym);
+ }
+
+ newBaseClasses[i] =
+ gen.mkParentConstr(tree.pos,
+ new Type.TypeRef(pre, sym, args),
+ null);
+ newBaseTypes[i] = new Type.TypeRef(pre, sym, args);
+ } break;
+
+ default:
+ throw global.fail("invalid base class type", baseTypes[i]);
+ }
+ }
+
+ // Use correct symbols for mixed-in members.
+ SymbolFixer symbolFixer = new SymbolFixer(global, descr, mixedInSymbols);
+ Tree[] fixedBody =
+ symbolFixer.transform((Tree[])newBody.toArray(new Tree[newBody.size()]));
+ Template newTree = make.Template(tree.pos, newBaseClasses, fixedBody);
+ newTree.setSymbol(newTemplSymbol);
+ newTree.setType(Type.compoundType(newBaseTypes, newMembers, owner));
+
+ return newTree;
+ }
+
+ public Tree transform(Tree tree) {
+ switch (tree) {
+ case ClassDef(int mods,
+ Name name,
+ TypeDef[] tparams,
+ ValDef[][] vparams,
+ Tree tpe,
+ Template impl):
+ if (Modifiers.Helper.isInterface(mods))
+ return super.transform(tree);
+ else {
+ global.log("expanding " + name);
+ Tree.ClassDef newClass = (Tree.ClassDef)
+ copy.ClassDef(tree,
+ mods,
+ name,
+ super.transform(tparams),
+ super.transform(vparams),
+ super.transform(tpe),
+ getMixinExpandedTemplate(impl, tree.symbol()));
+ newClass.symbol().setInfo(newClass.impl.type);
+ return newClass;
+ }
+
+ default:
+ Tree newTree = super.transform(tree);
+
+ switch (newTree) {
+ case Apply(Select(Tree qualifier, Name selector), Tree[] args): {
+ Tree fun = ((Tree.Apply)newTree).fun;
+ Symbol funOwnerSym = fun.symbol().owner();
+ Symbol qualSym = qualifier.type.symbol();
+ if (! (qualifier instanceof Tree.Super
+ || qualSym.isSubClass(funOwnerSym))) {
+ Type ownerTp = funOwnerSym.type();
+ Tree castQualifier =
+ Tree.Apply(Tree.TypeApply(Tree.Select(qualifier, Names.as),
+ new Tree[] {
+ gen.mkType(qualifier.pos, ownerTp)
+ }),
+ Tree.EMPTY_ARRAY);
+ return copy.Apply(newTree,
+ copy.Select(fun, castQualifier, selector),
+ args);
+ } else
+ return newTree;
+ }
+ default:
+ return newTree;
+ }
+ }
+ }
+
+ //########################################################################
+
+ // Return a hash table associating class definitions to (class) symbols.
+ protected static class ClassDefCollector extends Traverser {
+ private Map map;
+
+ public ClassDefCollector(Map map) {
+ this.map = map;
+ }
+
+ public void traverse(Tree tree) {
+ switch(tree) {
+ case ClassDef(_, _, _, _, _, _):
+ map.put(tree.symbol(), tree);
+ break;
+
+ default:
+ ; // nothing to do
+ }
+ super.traverse(tree);
+ }
+ }
+
+ //########################################################################
+
+ protected static class SymbolFixer extends Transformer {
+ protected final Map/*<Symbol,Symbol>*/ mixedInSymbols;
+
+ public SymbolFixer(Global global, PhaseDescriptor descr, Map mixedInSymbols) {
+ super(global, descr);
+ this.mixedInSymbols = mixedInSymbols;
+ }
+
+ public Tree transform(Tree tree) {
+ switch (tree) {
+ case Ident(_): {
+ Symbol sym = tree.symbol();
+ if (mixedInSymbols.containsKey(sym))
+ return gen.Ident((Symbol)mixedInSymbols.get(sym));
+ else
+ return super.transform(tree);
+ }
+
+ case Select(Super(Tree tpe), Name selector): {
+ Symbol sym = tree.symbol();
+ if (mixedInSymbols.containsKey(sym))
+ return gen.Ident((Symbol)mixedInSymbols.get(sym));
+ else
+ return super.transform(tree);
+ }
+
+ default:
+ return super.transform(tree);
+ }
+ }
+ }
+}
diff --git a/sources/scalac/transformer/ExpandMixinsPhase.java b/sources/scalac/transformer/ExpandMixinsPhase.java
new file mode 100644
index 0000000000..fe9bfc259f
--- /dev/null
+++ b/sources/scalac/transformer/ExpandMixinsPhase.java
@@ -0,0 +1,45 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ 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 scalac.*;
+import scalac.checkers.*;
+
+import java.util.*;
+
+public class ExpandMixinsPhase extends PhaseDescriptor {
+ /** Mapping from class symbols to class definitions */
+ public Map/*<Symbol,Tree>*/ classDefs = new HashMap();
+
+ public String name () {
+ return "expandmixins";
+ }
+
+ public String description () {
+ return "expand mixins by code copying";
+ }
+
+ public String taskDescription() {
+ return "expanded mixins";
+ }
+
+ public Phase createPhase(Global global) {
+ return new ExpandMixins(global, this);
+ }
+
+ public Checker[] postCheckers(Global global) {
+ return new Checker[] {
+ new CheckSymbols(global),
+ new CheckTypes(global),
+ new CheckOwners(global)
+ };
+ }
+}