From 6b60fc73e6936956e251f3086e4345c5d5bb2835 Mon Sep 17 00:00:00 2001 From: paltherr Date: Sun, 28 Mar 2004 16:46:51 +0000 Subject: - Added creation of general access methods in E... - Added creation of general access methods in ExplicitOuter --- .../transformer/ExplicitOuterClassesPhase.java | 99 ++++++++++++++-------- sources/scalac/util/Names.java | 12 ++- 2 files changed, 73 insertions(+), 38 deletions(-) diff --git a/sources/scalac/transformer/ExplicitOuterClassesPhase.java b/sources/scalac/transformer/ExplicitOuterClassesPhase.java index 334b6ec153..2e8322c713 100644 --- a/sources/scalac/transformer/ExplicitOuterClassesPhase.java +++ b/sources/scalac/transformer/ExplicitOuterClassesPhase.java @@ -348,10 +348,11 @@ public class ExplicitOuterClassesPhase extends Phase { case ClassDef(_, _, _, _, _, Template impl): Symbol clasz = tree.symbol(); - context = new Context(context, clasz, new HashMap()); + context = new Context(context, clasz, new HashMap(), new HashMap()); Tree[] parents = transform(impl.parents); Tree[] body = transform(impl.body); - body = Tree.concat(body, genSuperMethods()); + body = Tree.concat(body, genAccessMethods(false)); + body = Tree.concat(body, genAccessMethods(true)); context = context.outer; return gen.ClassDef(clasz, parents, impl.symbol(), body); @@ -397,21 +398,27 @@ public class ExplicitOuterClassesPhase extends Phase { Symbol symbol = tree.symbol(); if (symbol.owner().isStaticOwner()) // !!! qualifier ignored return gen.mkGlobalRef(tree.pos, symbol); + Symbol access; switch (qualifier) { case Super(_, _): Symbol clasz = qualifier.symbol(); if (clasz == context.clasz) { + access = symbol; qualifier = gen.Super(tree.pos, qualifier.symbol()); } else { + access = getAccessSymbol(symbol, clasz); qualifier = genOuterRef(qualifier.pos, clasz); - symbol = getSuperMethod(clasz, symbol); } break; default: + access = getAccessSymbol(symbol, null); qualifier = transform(qualifier); break; } - return gen.Select(tree.pos, qualifier, symbol); + tree = gen.Select(tree.pos, qualifier, access); + if (access != symbol && !symbol.isMethod()) + tree = gen.mkApply__(tree); + return tree; case Ident(_): Symbol symbol = tree.symbol(); @@ -475,41 +482,60 @@ public class ExplicitOuterClassesPhase extends Phase { } /** - * 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. + * Returns the symbol to access the specified member from the + * current context. If "svper" is non null, the member is + * selected from the superclass of the specified class. The + * returned symbol may be the same as the given one. */ - private Symbol getSuperMethod(Symbol clasz, Symbol method) { + private Symbol getAccessSymbol(Symbol member, Symbol svper) { + if (member.isPublic() && svper == null) return member; 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 = clasz.newMethod(method.pos, flags, name); - forward.setInfo(method.nextType().cloneType(method, forward)); - context.supers.put(method, forward); - clasz.nextInfo().members().enter(forward); - assert Debug.log("created forwarding method: ", forward); + for (; context != null; context = context.outer) + if (svper != null + ? context.clasz == svper + : context.clasz.isSubClass(member.owner())) break; + assert context != null: Debug.show(this.context, " - ", member); + if (context == this.context) return member; + Map table = svper != null ? context.supers : context.selfs; + Symbol access = (Symbol)table.get(member); + if (access == null) { + // !!! generate static access methods ? + Name name = Names.ACCESS(member, svper != null); + access = context.clasz.newAccessMethod(member.pos, name); + global.nextPhase(); + Type info = member.isMethod() + ? member.info().cloneType(member, access) + : Type.MethodType(Symbol.EMPTY_ARRAY, member.info()); + access.setInfo(info); + global.prevPhase(); + table.put(member, access); + context.clasz.nextInfo().members().enter(access); + assert Debug.log("created access method: ", access); } - return forward; + return access; } - /** 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(); + /** Generates the trees of the access methods. */ + private Tree[] genAccessMethods(boolean withSuper) { + Map table = withSuper ? context.supers : context.selfs; + if (table.size() == 0) return Tree.EMPTY_ARRAY; + Tree[] trees = new Tree[table.size()]; + Iterator entries = table.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.mkTypeRefs(pos, forward.nextTypeParams()); - Tree[] vargs = gen.mkLocalRefs(pos, forward.nextValueParams()); - Tree fun = gen.Select(gen.Super(pos, context.clasz), method); - trees[i] = gen.DefDef(forward, gen.mkApplyTV(fun,targs,vargs)); + Symbol member = (Symbol)entry.getKey(); + Symbol access = (Symbol)entry.getValue(); + int pos = access.pos; + Tree qualifier = withSuper + ? gen.Super(pos, context.clasz) + : gen.This(pos, context.clasz); + Tree select = gen.Select(qualifier, member); + Tree[] targs = gen.mkTypeRefs(pos, access.nextTypeParams()); + Tree[] vargs = gen.mkLocalRefs(pos, access.nextValueParams()); + Tree body = member.isMethod() + ? gen.mkApplyTV(select, targs, vargs) + : select; + trees[i] = gen.DefDef(access, body); } return trees; } @@ -563,23 +589,26 @@ public class ExplicitOuterClassesPhase extends Phase { public final Context outer; /** The current class symbol */ public final Symbol clasz; - /** The super methods (maps invoked to forwarding methods) */ + /** The self access methods (maps members to accessors) */ + public final Map/**/ selfs; + /** The super access methods (maps members to accessors) */ public final Map/**/ supers; public final TypeContext context; /** Initializes this instance. */ - public Context(Context outer, Symbol symbol, Map supers) { + public Context(Context outer, Symbol symbol, Map selfs, Map supers){ this.context = getTypeContextFor(symbol); this.outer = outer; this.clasz = symbol.constructorClass(); + this.selfs = selfs; this.supers = supers; } /** Returns a context for the given constructor. */ public Context getConstructorContext(Symbol constructor) { assert constructor.constructorClass() == clasz; - return new Context(outer, constructor, supers); + return new Context(outer, constructor, selfs, supers); } } diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java index da461290c9..ab2970e521 100644 --- a/sources/scalac/util/Names.java +++ b/sources/scalac/util/Names.java @@ -8,15 +8,20 @@ package scalac.util; import scalac.symtab.Symbol; +import scalac.symtab.SymbolNameWriter; import scalac.symtab.ClassSymbol; public class Names { + private static final SymbolNameWriter writer = + new SymbolNameWriter().setAllSeparators('$').setRootSeparator('\0'); + private static final String ALIAS_PREFIX = "alias$"; private static final String LOCAL_PREFIX = "local$"; private static final String MIXIN_PREFIX = "mixin$"; private static final String OUTER_PREFIX = "outer$"; private static final String SUPER_PREFIX = "super$"; + private static final String ACCESS_PREFIX = "access$"; private static final String TUPLE_FIELD_PREFIX = "_"; private static final String TYPE_PREFIX = "type$"; @@ -51,8 +56,10 @@ public class Names { return name; } - public static Name SUPER(Symbol method) { - return Name.fromString(SUPER_PREFIX + method.name); + public static Name ACCESS(Symbol member, boolean svper) { + assert member.isTerm() && member.owner().isClass(): Debug.show(member); + String prefix = svper ? ACCESS_PREFIX + SUPER_PREFIX : ACCESS_PREFIX; + return Name.fromString(writer.toString(prefix, member)); } public static Name TUPLE_FIELD(int index) { @@ -205,4 +212,3 @@ public class Names { return NameTransformer.encode(Name.fromString(string)); } } - -- cgit v1.2.3