summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2003-09-08 01:12:33 +0000
committerpaltherr <paltherr@epfl.ch>2003-09-08 01:12:33 +0000
commit139d9a3f87ad08f379fa774612a40b512c8c94de (patch)
treee70d7573afad49da83f651ed08ab747d49b00b72 /sources
parent129deca8fd3c256fcf510067502b7d4c9ac7d56b (diff)
downloadscala-139d9a3f87ad08f379fa774612a40b512c8c94de.tar.gz
scala-139d9a3f87ad08f379fa774612a40b512c8c94de.tar.bz2
scala-139d9a3f87ad08f379fa774612a40b512c8c94de.zip
- Rewrote ExplicitOuterClassesPhase to add type...
- Rewrote ExplicitOuterClassesPhase to add type links for outer tparams
Diffstat (limited to 'sources')
-rw-r--r--sources/scalac/transformer/ExplicitOuterClasses.java295
-rw-r--r--sources/scalac/transformer/ExplicitOuterClassesPhase.java421
2 files changed, 362 insertions, 354 deletions
diff --git a/sources/scalac/transformer/ExplicitOuterClasses.java b/sources/scalac/transformer/ExplicitOuterClasses.java
deleted file mode 100644
index 6a64127b5c..0000000000
--- a/sources/scalac/transformer/ExplicitOuterClasses.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-\* */
-
-// $Id$
-// $OldId: ExplicitOuterClasses.java,v 1.22 2002/10/17 12:31:56 schinz Exp $
-
-package scalac.transformer;
-
-import java.util.*;
-
-import scalac.*;
-import scalac.ast.*;
-import scalac.util.*;
-import scalac.parser.*;
-import scalac.symtab.*;
-import scalac.typechecker.*;
-import Tree.*;
-
-/**
- * Make links from nested classes to their enclosing class explicit.
- *
- * @author Michel Schinz
- * @version 1.0
- */
-
-public class ExplicitOuterClasses extends Transformer {
- protected final ExplicitOuterClassesPhase phase;
-
- // Mapping from class constructor symbols to owner field symbols.
- protected final HashMap/*<Symbol,Symbol>*/ outerMap;
-
- public ExplicitOuterClasses(Global global, ExplicitOuterClassesPhase phase) {
- super(global);
- this.phase = phase;
- this.outerMap = phase.outerMap;
- }
-
- protected LinkedList/*<Symbol>*/ classStack = new LinkedList();
- protected LinkedList/*<Symbol>*/ outerLinks = new LinkedList();
-
- /**
- * Return the number of outer links to follow to find the given
- * symbol.
- */
- protected int outerLevel(Symbol sym) {
- Iterator classIt = classStack.iterator();
- for (int level = 0; classIt.hasNext(); ++level) {
- Symbol classSym = (Symbol)classIt.next();
- if (classSym == sym)
- return level;
- }
- return -1;
- }
-
- /**
- * Return a tree referencing the "level"th outer class.
- */
- protected Tree outerRef(int level) {
- assert level >= 0 : level;
-
- if (level == 0) {
- Symbol thisSym = (Symbol)classStack.getFirst();
- return gen.This(thisSym.pos, thisSym);
- } else {
- Iterator outerIt = outerLinks.iterator();
- Tree root = gen.Ident((Symbol)outerIt.next());
-
- for (int l = 1; l < level; ++l) {
- Symbol outerSym = (Symbol)outerIt.next();
- root = gen.mkStable(gen.Select(root, outerSym));
- }
-
- return root;
- }
- }
-
- protected LinkedList/*<HashMap<Symbol,Symbol>>*/ superSymsStack =
- new LinkedList();
-
- protected Symbol outerSuperSym(int level, Symbol funSym) {
- assert level > 0 : level;
-
- HashMap symMap = (HashMap)superSymsStack.get(level);
- Symbol outerSuperSym = (Symbol)symMap.get(funSym);
- if (outerSuperSym == null) {
- Name outerSuperName =
- Name.fromString("super$" + funSym.name.toString());
- outerSuperSym = new TermSymbol(funSym.pos,
- outerSuperName,
- (Symbol)classStack.get(level),
- Modifiers.PRIVATE);
-
- global.log("created forwarding symbol: " + Debug.show(outerSuperSym));
-
- outerSuperSym.setInfo(funSym.info().cloneType(funSym, outerSuperSym));
- symMap.put(funSym, outerSuperSym);
- }
- return outerSuperSym;
- }
-
- public Tree transform(Tree tree) {
- switch (tree) {
- case ClassDef(int mods, _, _, _, _, _) : {
- // Add outer link
- ClassDef classDef = (ClassDef) tree;
- Symbol classSym = classDef.symbol();
- ValDef[][] newVParams;
-
- classStack.addFirst(classSym);
- superSymsStack.addFirst(new HashMap());
- if (classStack.size() == 1 || Modifiers.Helper.isStatic(mods)) {
- outerLinks.addFirst(null);
- newVParams = classDef.vparams;
- } else {
- // Add the outer parameter to the tree (it is added to
- // the type by transformInfo).
- Symbol constSym = classSym.primaryConstructor();
- Symbol outerSym = phase.outerSym(constSym);
- assert (outerSym.owner() == constSym) : outerSym;
- outerLinks.addFirst(outerSym);
-
- ValDef[][] vparams = classDef.vparams;
- ValDef[] newVParamsI;
- if (vparams.length == 0)
- newVParamsI = new ValDef[] { gen.mkParam(outerSym) };
- else {
- newVParamsI = new ValDef[vparams[0].length + 1];
- newVParamsI[0] = gen.mkParam(outerSym);
- System.arraycopy(vparams[0], 0, newVParamsI, 1, vparams[0].length);
- }
- newVParams = new ValDef[][] { newVParamsI };
-
- classSym.flags |= Modifiers.STATIC;
- }
-
- // Add forwarding "super" methods and add them to the
- // class members.
- Scope newMembers = new Scope(classSym.members());
- TreeList newBody = new TreeList(transform(classDef.impl.body));
- HashMap/*<Symbol,Symbol>*/ symMap =
- (HashMap)superSymsStack.removeFirst();
- Iterator symIt = symMap.entrySet().iterator();
- while (symIt.hasNext()) {
- Map.Entry symPair = (Map.Entry)symIt.next();
- Symbol funSym = (Symbol)symPair.getKey();
- Symbol fwdSym = (Symbol)symPair.getValue();
-
- Symbol[] argsSym = fwdSym.valueParams();
- Tree[] args = new Tree[argsSym.length];
- for (int i = 0; i < argsSym.length; ++i)
- args[i] = gen.mkRef(argsSym[i].pos, argsSym[i]);
- Tree fwdBody =
- gen.Apply(gen.Select(gen.Super(classSym.pos, classSym),
- funSym),
- args);
-
- newBody.append(gen.DefDef(fwdSym, fwdBody));
- newMembers.enter(fwdSym);
- }
- classSym.updateInfo(Type.compoundType(classSym.parents(),
- newMembers,
- classSym));
-
- Tree[] newParents = transform(classDef.impl.parents);
-
- outerLinks.removeFirst();
- classStack.removeFirst();
-
- return copy.ClassDef(classDef,
- classSym,
- transform(classDef.tparams),
- transform(newVParams),
- transform(classDef.tpe),
- copy.Template(classDef.impl,
- newParents,
- newBody.toArray()));
- }
-
- case DefDef(_, _, _, _, _, Tree rhs): {
- Symbol sym = tree.symbol();
- if (sym.isConstructor()) {
- // Temporarily set the outer link to the one passed to
- // that constructor, to transform RHS.
- Symbol mainOuterLink = (Symbol)outerLinks.removeFirst();
- outerLinks.addFirst(phase.outerSym(sym));
- Tree newRhs = transform(rhs);
- outerLinks.removeFirst();
- outerLinks.addFirst(mainOuterLink);
-
- return gen.DefDef(tree.pos, sym, newRhs);
- } else
- return super.transform(tree);
- }
-
- case Ident(_): {
- if (! tree.symbol().name.isTermName())
- return super.transform(tree);
-
- // Follow "outer" links to fetch data in outer classes.
- int level = outerLevel(tree.symbol().classOwner());
- if (level > 0) {
- Tree root = outerRef(level);
- return gen.mkStable(gen.Select(root, tree.symbol()));
- } else {
- return super.transform(tree);
- }
- }
-
- case This(_): {
- // If "this" refers to some outer class, replace it by
- // explicit reference to it.
- int level = outerLevel(tree.symbol());
- if (level > 0)
- return outerRef(level);
- else
- return super.transform(tree);
- }
-
- case Select(Super(_, _), Name selector): {
- // If "super" refers to an outer class, access the value
- // (a method) through outer link(s).
- int level = outerLevel(((Select)tree).qualifier.symbol());
- if (level > 0)
- return gen.Select(outerRef(level),
- outerSuperSym(level, tree.symbol()));
- else
- return super.transform(tree);
- }
-
- case Apply(Tree fun, Tree[] args): {
- // Add outer parameter to constructor calls.
- Tree realFun;
- Tree[] typeArgs;
-
- switch (fun) {
- case TypeApply(Tree fun2, Tree[] tArgs):
- realFun = fun2; typeArgs = tArgs; break;
- default:
- realFun = fun; typeArgs = null; break;
- }
-
- Tree newFun = null, newArg = null;
-
- if (realFun.hasSymbol() && realFun.symbol().isConstructor()) {
- switch (transform(realFun)) {
- case Select(Tree qualifier, _): {
- if (! (qualifier.hasSymbol()
- && Modifiers.Helper.isNoVal(qualifier.symbol().flags))) {
- newFun = make.Ident(qualifier.pos, realFun.symbol())
- .setType(realFun.type());
- newArg = qualifier;
- }
- } break;
-
- case Ident(_): {
- int level = outerLevel(realFun.symbol().owner());
- if (level >= 0) {
- newFun = realFun;
- newArg = outerRef(level);
- }
- } break;
-
- default:
- throw global.fail("unexpected node in constructor call");
- }
-
- if (newFun != null && newArg != null) {
- Tree[] newArgs = new Tree[args.length + 1];
- newArgs[0] = newArg;
- System.arraycopy(args, 0, newArgs, 1, args.length);
-
- Tree finalFun;
- if (typeArgs != null)
- finalFun = copy.TypeApply(fun, newFun, typeArgs);
- else
- finalFun = newFun;
-
- finalFun.type =
- phase.addOuterValueParam(finalFun.type, realFun.symbol());
- return copy.Apply(tree, finalFun, transform(newArgs));
- } else
- return super.transform(tree);
-
- } else
- return super.transform(tree);
- }
-
- default:
- return super.transform(tree);
- }
- }
-}
diff --git a/sources/scalac/transformer/ExplicitOuterClassesPhase.java b/sources/scalac/transformer/ExplicitOuterClassesPhase.java
index 2819c14ef7..590502f35c 100644
--- a/sources/scalac/transformer/ExplicitOuterClassesPhase.java
+++ b/sources/scalac/transformer/ExplicitOuterClassesPhase.java
@@ -5,94 +5,397 @@
\* */
// $Id$
-// $OldId: ExplicitOuterClassesPhase.java,v 1.8 2002/08/21 14:08:18 paltherr Exp $
package scalac.transformer;
-import scalac.*;
-import scalac.checkers.*;
-import scalac.symtab.*;
-import scalac.util.*;
+import java.util.Map;
import java.util.HashMap;
+import java.util.Iterator;
+import scalac.Global;
+import scalac.Phase;
+import scalac.PhaseDescriptor;
+import scalac.Unit;
+import scalac.ast.Transformer;
+import scalac.ast.Tree;
+import scalac.ast.Tree.Template;
+import scalac.symtab.Modifiers;
+import scalac.symtab.Symbol;
+import scalac.symtab.TermSymbol;
+import scalac.symtab.Type;
+import scalac.util.Debug;
+import scalac.util.Name;
+import scalac.util.Names;
+
+/**
+ * This phase does the following:
+ *
+ * - In every nested class, adds to each of its constructor a new
+ * value parameter that contains a link to the outer class.
+ *
+ * - In every nested class, adds to each of its constructor a new type
+ * parameter for every type parameter appearing in outer classes.
+ *
+ * - In every class, adds a forwarding "super" method for every method
+ * that is accessed via "super" in a nested class.
+ *
+ * - Adds all missing qualifiers.
+ */
public class ExplicitOuterClassesPhase extends Phase {
- // Mapping from class constructor symbols to owner field symbols.
- protected final HashMap/*<Symbol,Symbol>*/ outerMap = new HashMap();
+
+ //########################################################################
+ // Public Constructors
/** Initializes this instance. */
public ExplicitOuterClassesPhase(Global global,PhaseDescriptor descriptor){
super(global, descriptor);
}
+ //########################################################################
+ // Public Methods
+
+ /** Applies this phase to the given type for the given symbol. */
+ public Type transformInfo(Symbol symbol, Type type) {
+ if (symbol.isJava() || symbol == Symbol.NONE) return type;
+ //System.out.println("!!! debug1 = " + Debug.show(symbol));
+ //if (symbol.name.toString().equals("x")) new Error("!!!").printStackTrace();
+ type = typeTransformer.apply(type);
+ if (symbol.isConstructor() && !symbol.isOverloaded()) {
+ Symbol[] tparams = type.typeParams();
+ Symbol[] vparams = type.valueParams();
+ Type result = type.resultType();
+ // Add outer value link
+ if (hasOuterValueLink(symbol)) {
+ Name name = Names.OUTER(symbol);
+ Symbol vlink = new TermSymbol(symbol.pos, name, symbol, 0);
+ vlink.setInfo(getOuterClass(symbol).typeOfThis()); // !!!
+ vparams = Symbol.cloneArray(1, vparams);
+ vparams[0] = vlink;
+ }
+ // Add outer type links
+ if (hasOuterTypeLinks(symbol)) {
+ Symbol[] oldtparams = nextTypeParams(getOuterClass(symbol));
+ Symbol[] tlinks = Symbol.cloneArray(oldtparams);
+ for (int i = 0; i < tlinks.length; i++) {
+ tlinks[i] = oldtparams[i].cloneSymbol(symbol);
+ tlinks[i].name = Names.OUTER(symbol, oldtparams[i]);
+ }
+ tparams = Symbol.concat(tlinks, tparams);
+ result = Type.getSubst(oldtparams, tlinks, true).apply(result);
+ }
+ type = Type.MethodType(vparams, result);
+ if (tparams.length != 0) type = Type.PolyType(tparams, type);
+ } else {
+ Symbol owner = symbol.isConstructor()
+ ? symbol.constructorClass()
+ : symbol.owner().isConstructor()
+ ? symbol.owner()
+ : symbol.enclClass();
+ //System.out.println("!!! debug2 = " + Debug.show(symbol) + " - " + Debug.show(owner) + " --- " + (owner == Symbol.NONE) + " -- #" + owner.name + "#");
+ //if (onwer.isJava() && owner != Symbol.NONE && owner.name.length() > 0) // !!!
+ if (owner.isClass() || owner.isConstructor())
+ type = getOuterTypeSubst(owner, true).apply(type);
+ }
+
+ /*
+
+ String s1 = Debug.show(symbol);
+ String s2 = symbol.info().toString();
+ //global.nextPhase();
+ String s3 = type.toString();
+ //global.prevPhase();
+ System.out.println("!!! symbol = " + s1);
+ System.out.println("!!! type = " + s2 + " -- " + System.identityHashCode(s2));
+ System.out.println("!!! new = " + s3 + " -- " + System.identityHashCode(s3));
+ System.out.println("!!!");
+
+ */
+
+ return type;
+ }
+
/** Applies this phase to the given compilation units. */
public void apply(Unit[] units) {
- for (int i = 0; i < units.length; i++)
- new ExplicitOuterClasses(global, this).apply(units[i]);
+ treeTransformer.apply(units);
}
- public Checker[] postCheckers(Global global) {
- return new Checker[] {
- new CheckSymbols(global),
- new CheckTypes(global),
- new CheckOwners(global),
- new CheckNames(global)
- };
+ //########################################################################
+ // Private Methods - Outer class
+
+ /** Returns the outer class of the given class or constructor. */
+ private Symbol getOuterClass(Symbol symbol) {
+ assert symbol.isClass() || symbol.isConstructor(): Debug.show(symbol);
+ return symbol.owner();
}
- public Type transformInfo(Symbol sym, Type tp) {
- if (sym != Symbol.NONE
- && sym.isConstructor()
- && sym.owner().isClass()
- && !(sym.isJava() || sym.owner().isRoot())) {
- return addOuterValueParam(tp, sym);
- } else
- return tp;
+ /** Has the given class or constructor an outer value link? */
+ private boolean hasOuterValueLink(Symbol symbol) {
+ assert symbol.isClass() || symbol.isConstructor(): Debug.show(symbol);
+ return !symbol.isJava() && getOuterClass(symbol).isClass();
}
- /**
- * Return the symbol for the outer parameter corresponding to the
- * given constructor.
- */
- protected Symbol outerSym(Symbol constSym) {
- if (! outerMap.containsKey(constSym)) {
- Symbol ownerSym = constSym.enclClass();
- Name outerName =
- Global.instance.freshNameCreator.newName(Names.OUTER_PREFIX);
- Symbol outerSym =
- new TermSymbol(constSym.pos, outerName, constSym, 0);
- outerSym.setInfo(ownerSym.type());
-
- outerMap.put(constSym, outerSym);
- }
- return (Symbol)outerMap.get(constSym);
+ /** Returns the outer link of the given class or constructor. */
+ private Symbol getOuterValueLink(Symbol symbol) {
+ if (!hasOuterValueLink(symbol)) return Symbol.NONE;
+ if (symbol.isClass()) symbol = symbol.primaryConstructor();
+ return nextValueParams(symbol)[0];
+ }
+
+ /** Has the given class or constructor outer type links? */
+ private boolean hasOuterTypeLinks(Symbol symbol) {
+ assert symbol.isClass() || symbol.isConstructor(): Debug.show(symbol);
+ if (symbol.isJava()) return false;
+ Symbol outer = getOuterClass(symbol);
+ return outer.isClass() && nextTypeParams(outer).length != 0;
+ }
+
+ /** Returns the type substitution for the given class or constructor. */
+ private Type.Map getOuterTypeSubst(Symbol symbol, boolean update) {
+ if (!hasOuterTypeLinks(symbol)) return Type.IdMap;
+ Symbol[] oldtparams = nextTypeParams(getOuterClass(symbol));
+ Symbol[] newtparams = nextTypeParams(symbol);
+ Symbol[] tlinks = new Symbol[oldtparams.length];
+ for (int i = 0; i < tlinks.length; i++) tlinks[i] = newtparams[i];
+ return Type.getSubst(oldtparams, tlinks, update);
}
/**
- * Add the given value parameter to the type, which must be the
- * type of a method, as the first argument.
+ * Extracts from given prefix the outer type arguments for the
+ * given class or constructor.
*/
- protected Type addOuterValueParam(Type oldType, Symbol constr) {
- switch (oldType) {
- case MethodType(Symbol[] vparams, Type result): {
- Symbol[] newVParams = new Symbol[vparams.length + 1];
- newVParams[0] = outerSym(constr);
- System.arraycopy(vparams, 0, newVParams, 1, vparams.length);
- return new Type.MethodType(newVParams, result);
+ private Type[] getOuterTypeArgs(Type prefix, Symbol symbol) {
+ if (!hasOuterTypeLinks(symbol)) return Type.EMPTY_ARRAY;
+ Symbol outer = getOuterClass(symbol);
+ global.nextPhase();
+ Type[] targs = prefix.baseType(outer).widen().typeArgs();
+ global.prevPhase();
+ assert targs.length == nextTypeParams(outer).length:
+ "\nsymbol = " + Debug.show(symbol) +
+ "\nprefix = " + prefix;
+ return targs;
+ }
+
+ //########################################################################
+ // Private Methods - Helper methods
+
+ /** Returns the given symbol's type parameters in next phase. */
+ private Symbol[] nextTypeParams(Symbol symbol) {
+ global.nextPhase();
+ Symbol[] tparams = symbol.typeParams();
+ global.prevPhase();
+ return tparams;
+ }
+
+ /** Returns the given symbol's value parameters in next phase. */
+ private Symbol[] nextValueParams(Symbol symbol) {
+ global.nextPhase();
+ Symbol[] vparams = symbol.valueParams();
+ global.prevPhase();
+ return vparams;
+ }
+
+ //########################################################################
+ // Private Class - Type transformer
+
+ /** The type transformer */
+ private final Type.Map typeTransformer = new Type.MapOnlyTypes() {
+ public Type apply(Type type) {
+ switch (type) {
+ case TypeRef(Type prefix, Symbol symbol, Type[] targs):
+ if (!symbol.isClass()) break;
+ prefix = apply(prefix);
+ targs = Type.concat(getOuterTypeArgs(prefix, symbol), targs);
+ return Type.TypeRef(prefix, symbol, targs);
+ }
+ return map(type);
}
+ };
- case PolyType(Symbol[] tparams, Type result):
- return new Type.PolyType(tparams,
- addOuterValueParam(result, constr));
+ //########################################################################
+ // Private Class - Tree transformer
- case OverloadedType(Symbol[] alts, Type[] altTypes): {
- Type[] newAltTypes = new Type[altTypes.length];
- for (int i = 0; i < newAltTypes.length; ++i)
- newAltTypes[i] = addOuterValueParam(altTypes[i], alts[i]);
- return new Type.OverloadedType(alts, newAltTypes);
+ /** The tree transformer */
+ private final Transformer treeTransformer = new Transformer(global) {
+
+ /** The current context */
+ private Context context;
+
+ /** Transforms the given tree. */
+ public Tree transform(Tree tree) {
+ switch (tree) {
+
+ case ClassDef(_, _, _, _, _, Template impl):
+ Symbol clasz = tree.symbol();
+ context = new Context(context, clasz, new HashMap());
+ Tree[] parents = transform(impl.parents);
+ Tree[] members = transform(impl.body);
+ members = Tree.concat(members, genSuperMethods());
+ context = context.outer;
+ if (context != null) clasz.flags |= Modifiers.STATIC;
+ return gen.ClassDef(clasz, parents, impl.symbol(), members);
+
+ case DefDef(_, _, _, _, _, Tree rhs):
+ Symbol symbol = tree.symbol();
+ if (!symbol.isConstructor()) break;
+ Context backup = context;
+ context = context.getConstructorContext(symbol);
+ rhs = transform(rhs);
+ context = backup;
+ return gen.DefDef(tree.pos, symbol, rhs);
+
+ case This(_):
+ return genOuterRef(tree.pos, tree.symbol());
+
+ case Ident(_):
+ Symbol symbol = tree.symbol();
+ Symbol owner = symbol.owner();
+ if (owner.isClass()) {
+ // !!! A this node is missing here. This should
+ // never happen if all trees were correct.
+ Tree qualifier = genOuterRef(tree.pos, owner);
+ return gen.mkStable(gen.Select(qualifier, symbol));
+ }
+ if (!owner.isConstructor()) break;
+ Symbol clasz = owner.constructorClass();
+ if (clasz == context.clasz) break;
+ Tree qualifier = genOuterRef(tree.pos, clasz);
+ return gen.mkStable(gen.Select(qualifier, symbol));
+
+ case Select(Super(_, _), _):
+ Tree qualifier = ((Tree.Select)tree).qualifier;
+ Symbol clasz = qualifier.symbol();
+ if (clasz == context.clasz) break;
+ Symbol symbol = getSuperMethod(clasz, tree.symbol());
+ qualifier = genOuterRef(qualifier.pos, clasz);
+ return gen.mkStable(gen.Select(tree.pos, qualifier, symbol));
+
+ case Apply(Tree vfun, Tree[] vargs):
+ switch (vfun) {
+ case TypeApply(Tree tfun, Tree[] targs):
+ if (!tfun.symbol().isConstructor()) break;
+ return transform(tree, vargs, vfun, targs, tfun);
+ default:
+ if (!vfun.symbol().isConstructor()) break;
+ return transform(tree, vargs, vfun, Tree.EMPTY_ARRAY,vfun);
+ }
+ }
+
+ Type type = typeTransformer.apply(tree.type());
+ if (context != null) type = context.subst.apply(type);
+ return super.transform(tree).setType(type);
+ }
+
+ /* Add outer type and value arguments to constructor calls. */
+ private Tree transform(Tree vapply, Tree[] vargs, Tree tapply,
+ Tree[] targs, Tree tree)
+ {
+ Symbol symbol = tree.symbol();
+ targs = transform(targs);
+ vargs = transform(vargs);
+ switch (transform(tree)) {
+ case Select(Tree qualifier, _):
+ if (hasOuterValueLink(symbol)) {
+ vargs = Tree.cloneArray(1, vargs);
+ vargs[0] = qualifier;
+ }
+ Type[] types = getOuterTypeArgs(qualifier.type(), symbol);
+ if (types.length != 0) {
+ targs = Tree.cloneArray(types.length, targs);
+ for (int i = 0; i < types.length; i++)
+ targs[i] = gen.mkType(tapply.pos, types[i]);
+ }
+ }
+ tree = gen.Ident(tree.pos, symbol);
+ if (targs.length != 0) tree = gen.TypeApply(tapply.pos,tree,targs);
+ return gen.Apply(vapply.pos, tree, vargs);
+ }
+
+ /**
+ * Returns the forwarding "super" method of the given class
+ * that invokes the given method. If the symbol does not yet
+ * exist, it is created and added to the class members.
+ */
+ private Symbol getSuperMethod(Symbol clasz, Symbol method) {
+ Context context = this.context;
+ for (; context.clasz != clasz; context = context.outer)
+ assert context.outer != null : Debug.show(clasz);
+ Symbol forward = (Symbol)context.supers.get(method);
+ if (forward == null) {
+ Name name = Names.SUPER(method);
+ int flags = Modifiers.PRIVATE | Modifiers.FINAL;
+ forward = new TermSymbol(method.pos, name, clasz, flags);
+ forward.setInfo(method.nextType().cloneType(method, forward));
+ context.supers.put(method, forward);
+ clasz.nextInfo().members().enter(forward);
+ assert Debug.log("created forwarding method: ", forward);
+ }
+ return forward;
}
- default:
- throw Global.instance.fail("invalid type", oldType);
+ /** Generates the trees of the forwarding "super" methods. */
+ private Tree[] genSuperMethods() {
+ if (context.supers.size() == 0) return Tree.EMPTY_ARRAY;
+ Tree[] trees = new Tree[context.supers.size()];
+ Iterator entries = context.supers.entrySet().iterator();
+ for (int i = 0; i < trees.length; i++) {
+ Map.Entry entry = (Map.Entry)entries.next();
+ Symbol method = (Symbol)entry.getKey();
+ Symbol forward = (Symbol)entry.getValue();
+ int pos = forward.pos;
+ Tree[] targs = gen.mkTypeIdents(pos, nextTypeParams(forward));
+ Tree[] vargs = gen.mkIdents(pos, nextValueParams(forward));
+ Tree fun = gen.Select(gen.Super(pos, context.clasz), method);
+ trees[i] = gen.DefDef(forward, gen.mkApply(fun, targs, vargs));
+ }
+ return trees;
}
+
+ /** Returns a tree referencing the given outer class. */
+ private Tree genOuterRef(int pos, Symbol clasz) {
+ if (context.clasz == clasz) return gen.This(pos, clasz);
+ Tree tree = gen.mkStable(gen.Ident(pos, context.link));
+ for (Context context = this.context.outer;;context =context.outer){
+ assert context != null: Debug.show(clasz);
+ if (context.clasz == clasz) return tree;
+ tree = gen.mkStable(gen.Select(tree, context.link));
+ }
+ }
+
+ };
+
+ //########################################################################
+ // Private Class - Tree transformer context
+
+ /** This class represents the tree transformation context. */
+ private class Context {
+
+ /** The outer context */
+ public final Context outer;
+ /** The class symbol */
+ public final Symbol clasz;
+ /** The super methods (maps invoked to forwarding methods) */
+ public final Map/*<Symbol,Symbol>*/ supers;
+ /** The outer type parameter substitution */
+ public final Type.Map subst;
+ /** The link to the outer class */
+ public final Symbol link;
+
+ /** Initializes this instance. */
+ public Context(Context outer, Symbol symbol, Map supers) {
+ this.outer = outer;
+ this.clasz = symbol.constructorClass();
+ this.supers = supers;
+ this.subst = getOuterTypeSubst(symbol, false);
+ this.link = getOuterValueLink(symbol);
+ }
+
+ /** Returns a context for the given constructor. */
+ public Context getConstructorContext(Symbol constructor) {
+ assert constructor.constructorClass() == clasz;
+ return new Context(outer, constructor, supers);
+ }
+
}
+
+ //########################################################################
}