diff options
Diffstat (limited to 'sources/scalac/transformer/Erasure.java')
-rw-r--r-- | sources/scalac/transformer/Erasure.java | 759 |
1 files changed, 0 insertions, 759 deletions
diff --git a/sources/scalac/transformer/Erasure.java b/sources/scalac/transformer/Erasure.java deleted file mode 100644 index 67a462b1f4..0000000000 --- a/sources/scalac/transformer/Erasure.java +++ /dev/null @@ -1,759 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $OldId: Erasure.java,v 1.48 2003/01/16 14:21:19 schinz Exp $ -// $Id$ - -package scalac.transformer; - -import java.util.Iterator; -import java.util.Map; -import java.util.HashMap; -import java.util.Set; -import java.util.HashSet; - -import scalac.Global; -import scalac.Phase; -import scalac.CompilationUnit; -import scalac.ast.Tree; -import scalac.ast.Tree.Ident; -import scalac.ast.Tree.Template; -import scalac.ast.Tree.AbsTypeDef; -import scalac.ast.Tree.AliasTypeDef; -import scalac.ast.Tree.ValDef; -import scalac.ast.TreeList; -import scalac.ast.GenTransformer; -import scalac.atree.AConstant; -import scalac.symtab.Definitions; -import scalac.symtab.Kinds; -import scalac.symtab.Type; -import scalac.symtab.TypeTags; -import scalac.symtab.Modifiers; -import scalac.symtab.Scope; -import scalac.symtab.Scope.SymbolIterator; -import scalac.symtab.SymSet; -import scalac.symtab.Symbol; -import scalac.symtab.SymbolTablePrinter; -import scalac.backend.Primitive; -import scalac.backend.Primitives; -import scalac.util.Name; -import scalac.util.Names; -import scalac.util.Debug; - -/** A transformer for type erasure and bridge building - * - * @author Martin Odersky - * @version 1.0 - * - * What it does: - * (1) Map every type to its erasure. - * (2) If method A overrides a method B, and the erased type ETA of A is - * different from the erased type ETB of B seen as a member of A's class, - * add a bridge method with the same name as A,B, with signature ETB - * which calls A after casting parameters. - */ -public class Erasure extends GenTransformer implements Modifiers { - - //######################################################################## - // Private Constants - - /** The unboxed types */ - private static final Type - UNBOXED_UNIT = Type.unboxedType(TypeTags.UNIT), - UNBOXED_BOOLEAN = Type.unboxedType(TypeTags.BOOLEAN), - UNBOXED_BYTE = Type.unboxedType(TypeTags.BYTE), - UNBOXED_SHORT = Type.unboxedType(TypeTags.SHORT), - UNBOXED_CHAR = Type.unboxedType(TypeTags.CHAR), - UNBOXED_INT = Type.unboxedType(TypeTags.INT), - UNBOXED_LONG = Type.unboxedType(TypeTags.LONG), - UNBOXED_FLOAT = Type.unboxedType(TypeTags.FLOAT), - UNBOXED_DOUBLE = Type.unboxedType(TypeTags.DOUBLE); - - //######################################################################## - // Private Fields - - /** The global definitions */ - private final Definitions definitions; - - /** The global primitives */ - private final Primitives primitives; - - /** The current unit */ - private CompilationUnit unit; - - private final boolean forMSIL; - - //######################################################################## - // Public Constructors - - /** Initializes this instance. */ - public Erasure(Global global) { - super(global); - this.definitions = global.definitions; - this.primitives = global.primitives; - this.forMSIL = global.target == global.TARGET_MSIL; - } - - //######################################################################## - // Public Methods - - /** Transforms the given unit. */ - public void apply(CompilationUnit unit) { - this.unit = unit; - super.apply(unit); - } - - /** Transforms the given tree. */ - public Tree transform(Tree tree) { - switch (tree) { - - case ClassDef(_, _, _, _, _, Template(_, Tree[] body)): - Symbol clasz = tree.symbol(); - TreeList members = new TreeList(transform(body)); - addBridges(clasz, members); - return gen.ClassDef(clasz, members.toArray()); - - case ValDef(_, _, _, Tree rhs): - Symbol field = tree.symbol(); - if (rhs != Tree.Empty) rhs = transform(rhs, field.nextType()); - return gen.ValDef(field, rhs); - - case DefDef(_, _, _, _, _, Tree rhs): - Symbol method = tree.symbol(); - if (rhs != Tree.Empty) - rhs = transform(rhs, method.nextType().resultType()); - return gen.DefDef(method, rhs); - - case LabelDef(_, Ident[] params, Tree body): - Symbol label = tree.symbol(); - body = transform(body, label.nextType().resultType()); - return gen.LabelDef(label, Tree.symbolOf(params), body); - - case Assign(Tree lhs, Tree rhs): - lhs = transform(lhs); - rhs = transform(rhs, lhs.type); - return gen.Assign(tree.pos, lhs, rhs); - - case Return(Tree expr): - Symbol method = tree.symbol(); - Type type = method.nextType().resultType(); - return gen.Return(tree.pos, method, transform(expr, type)); - - case New(Tree init): - if (tree.getType().symbol() == definitions.ARRAY_CLASS) { - switch (init) { - case Apply(_, Tree[] args): - assert args.length == 1: tree; - Type element = getArrayElementType(tree.getType()).erasure(); - Tree size = transform(args[0]); - return genNewUnboxedArray(tree.pos, element, size); - default: - throw Debug.abort("illegal case", tree); - } - } - return gen.New(tree.pos, transform(init)); - - case Create(_, _): - return gen.Create(tree.pos, Tree.Empty, tree.symbol()); - - case Apply(TypeApply(Tree fun, Tree[] targs), Tree[] vargs): - fun = transform(fun); - vargs = transform(vargs); - Symbol symbol = fun.symbol(); - if (symbol == definitions.ANY_AS_ERASED) { - assert targs.length == 1 && vargs.length == 0: tree; - return coerce(getQualifier(fun), targs[0].getType().erasure()); - } - if (symbol == definitions.ANY_IS_ERASED) { - assert targs.length == 1 && vargs.length == 0: tree; - Type type = targs[0].type.erasure(); - if (isUnboxedSimpleType(type)) type = targs[0].type; - return gen.mkIsInstanceOf(tree.pos, getQualifier(fun), type); - } - return genApply(tree.pos, fun, vargs); - - case Apply(Tree fun, Tree[] vargs): - fun = transform(fun); - vargs = transform(vargs); - switch (fun) { - case Select(Apply(Tree bfun, Tree[] bargs), _): - Symbol bsym = bfun.symbol(); - if (primitives.getPrimitive(bsym) != Primitive.BOX) break; - assert bargs.length == 1: fun; - switch (primitives.getPrimitive(fun.symbol())) { - case COERCE: - assert vargs.length == 0: tree; - Tree value = bargs[0]; - return coerce(value, fun.type().resultType()); - case LENGTH: - assert vargs.length == 0: tree; - Tree array = bargs[0]; - return genUnboxedArrayLength(tree.pos, array); - case APPLY: - assert vargs.length == 1: tree; - Tree array = bargs[0]; - Tree index = vargs[0]; - return genUnboxedArrayGet(tree.pos, array, index); - case UPDATE: - assert vargs.length == 2: tree; - Tree array = bargs[0]; - Tree index = vargs[0]; - Tree value = vargs[1]; - return genUnboxedArraySet(tree.pos, array, index, value); - } - } - return genApply(tree.pos, fun, vargs); - - case Select(Tree qualifier, _): - Symbol symbol = tree.symbol(); - Type prefix = qualifier.type().baseType(symbol.owner()).erasure(); - assert prefix != Type.NoType: tree + " -- " + Debug.show(symbol); - qualifier = transform(qualifier); - qualifier = coerce(qualifier, prefix); - - // Might end up with "box(unbox(...))". That's needed by backend. - if (isUnboxedType(prefix)) qualifier = box(qualifier, true); - return gen.Select(tree.pos, qualifier, symbol); - - case Literal(AConstant.ZERO): - return gen.mkNullLit(tree.pos); - - case Block(_, _): - case If(_, _, _): - case Switch(_, _, _, _): - return transform(tree, tree.getType().fullErasure()); - - default: - return super.transform(tree); - } - } - - //######################################################################## - // Private Methods - Tree transformation - - /** Transforms the given trees with given prototype. */ - private Tree[] transform(Tree[] trees, Type pt) { - for (int i = 0; i < trees.length; i++) { - Tree tree = transform(trees[i], pt); - if (tree == trees[i]) continue; - Tree[] array = new Tree[trees.length]; - for (int j = 0; j < i ; j++) array[j] = trees[j]; - array[i] = tree; - while (++i < trees.length) array[i] = transform(trees[i], pt); - return array; - } - return trees; - } - - /** Transforms the given tree with given prototype. */ - private Tree transform(Tree tree, Type pt) { - switch (tree) { - - case Block(Tree[] stats, Tree value): - return gen.Block(tree.pos, transform(stats), transform(value, pt)); - - case If(Tree cond, Tree thenp, Tree elsep): - cond = transform(cond, UNBOXED_BOOLEAN); - thenp = transform(thenp, pt); - elsep = transform(elsep, pt); - return gen.If(tree.pos, cond, thenp, elsep, pt); - - case Switch(Tree test, int[] tags, Tree[] bodies, Tree otherwise): - test = transform(test, UNBOXED_INT); - bodies = transform(bodies, pt); - otherwise = transform(otherwise, pt); - return gen.Switch(tree.pos, test, tags, bodies, otherwise, pt); - - case Return(_): - // !!! why do we build a block here? - Tree value = transform(gen.mkDefaultValue(tree.pos, pt), pt); - return gen.mkBlock(transform(tree), value); - - case LabelDef(_, _, _): - case Assign(_, _): - case New(_): - case Apply(_, _): - case Super(_, _): - case This(_): - case Select(_, _): - case Ident(_): - case Literal(_): - return coerce(transform(tree), pt); - - default: - throw Debug.abort("illegal case", tree); - } - } - - /** Transforms Unit literal with given prototype. */ - private Tree transformUnit(int pos, Type pt) { - Tree unit = pt.isSameAs(UNBOXED_UNIT) - ? gen.mkUnitLit(pos) - : gen.mkApply__(gen.mkGlobalRef(pos, primitives.BOX_UVALUE)); - return coerce(unit, pt); - } - - /** Coerces the given tree to the given type. */ - private Tree coerce(Tree tree, Type pt) { - if (isSubType(tree.type(), pt)) { - if (tree.type().symbol() == definitions.ARRAY_CLASS) { - if (pt.symbol() != definitions.ARRAY_CLASS) { - Symbol symbol = primitives.UNBOX__ARRAY; - Tree unboxtree = gen.mkGlobalRef(tree.pos, symbol); - tree = gen.mkApply_V(unboxtree, new Tree[] {tree}); - return coerce(tree, pt); - } - } - return tree; - } - if (isUnboxedSimpleType(tree.type())) { - if (isUnboxedSimpleType(pt)) return convert(tree, pt); - Type to = pt.erasure(); - if (!isUnboxedSimpleType(to) || isSameAs(to, tree.type())) - return box(tree); - else - return coerce(convert(tree, to), pt); - } else if (isUnboxedArrayType(tree.type())) { - if (!isUnboxedArrayType(pt)) return check(box(tree), pt); - } else if (isUnboxedSimpleType(pt)) { - Type from = tree.type().erasure(); - if (isUnboxedSimpleType(from)) - return convert(unbox(tree, from), pt); - else - return unbox(coerce(tree, boxUnboxedType(pt)), pt); - } else if (isUnboxedArrayType(pt)) { - if (tree.type.symbol() == definitions.ARRAY_CLASS) - return coerce(unbox(tree, pt), pt); - } else if (pt.symbol() == definitions.ARRAY_CLASS) { - Tree boxtree = gen.mkGlobalRef(tree.pos, primitives.BOX__ARRAY); - return gen.mkApply_V(boxtree, new Tree[]{tree}); - } - return gen.mkAsInstanceOf(tree, pt); - } - - /** Checks that the given tree is of the given type. */ - private Tree check(Tree tree, Type pt) { - assert isSubType(tree.type(), pt): tree +" - "+ tree.type() +" - "+pt; - return tree; - } - - - /** Boxes the given tree. */ - private Tree box(Tree tree) { - return box(tree, false); - } - - /** Boxes the given tree. */ - private Tree box(Tree tree, boolean force) { - switch (tree) { - case Apply(Tree fun, Tree[] args): - if (primitives.getPrimitive(fun.symbol()) == Primitive.UNBOX) { - assert args.length == 1: tree; - if (!force) return args[0]; - } - } - Symbol symbol = primitives.getBoxValueSymbol(tree.getType()); - Tree boxtree = gen.mkGlobalRef(tree.pos, symbol); - return tree.getType().equals(UNBOXED_UNIT) - ? gen.mkBlock(tree, gen.mkApply__(boxtree)) - : gen.mkApply_V(boxtree, new Tree[]{tree}); - } - - /** Unboxes the given tree to the given type. */ - private Tree unbox(Tree tree, Type pt) { - switch (tree) { - case Apply(Tree fun, Tree[] args): - if (primitives.getPrimitive(fun.symbol()) == Primitive.BOX) { - assert args.length == 1: tree; - return args[0]; - } - } - Symbol symbol = primitives.getUnboxValueSymbol(pt); - return gen.mkApply_V( - gen.mkGlobalRef(tree.pos, symbol), new Tree[]{tree}); - } - - /** Converts the given tree to the given type. */ - private Tree convert(Tree tree, Type to) { - Symbol symbol = primitives.getConvertSymbol(tree.type(), to); - return gen.mkApply_V( - gen.mkGlobalRef(tree.pos, symbol), new Tree[]{tree}); - } - - //######################################################################## - // Private Methods - Tree generation - - /** Generates given bridge method forwarding to given method. */ - private Tree genBridgeMethod(Symbol bridge, Symbol method) { - Type type = bridge.nextType(); - Tree body = genApply(bridge.pos, - gen.Select(gen.This(bridge.pos, bridge.owner()), method), - gen.mkLocalRefs(bridge.pos, type.valueParams())); - return gen.DefDef(bridge, coerce(body, type.resultType())); - } - - /** Generates an application with given function and arguments. */ - private Tree genApply(int pos, Tree fun, Tree[] args) { - switch (fun.getType()) { - case MethodType(Symbol[] params, Type result): - Tree[] args1 = args; - for (int i = 0; i < args.length; i++) { - Tree arg = args[i]; - Tree arg1 = coerce(arg, params[i].nextType()); - if (arg1 != arg && args1 == args) { - args1 = new Tree[args.length]; - for (int j = 0; j < i; j++) args1[j] = args[j]; - } - args1[i] = arg1; - } - return gen.mkApply_V(pos, fun, args1); - default: - throw Debug.abort("illegal type " + fun.getType() + " for " + fun); - } - } - - /** - * Generates a new unboxed array of given size and with elements - * of given type. - */ - private Tree genNewUnboxedArray(int pos, Type element, Tree size) { - if (global.target == global.TARGET_INT) { - Tree[] targs = {gen.mkType(pos, element)}; - Tree[] vargs = {coerce(size, UNBOXED_INT)}; - Tree fun = gen.mkGlobalRef(pos, primitives.NEW_OARRAY); - return gen.mkApplyTV(fun, targs, vargs); - } - switch (element) { - case UnboxedType(int kind): return genNewUnboxedArray(pos, kind, size); - } - String name = primitives.getNameForClassForName(element); - Tree[] args = { coerce(size, UNBOXED_INT), gen.mkStringLit(pos,name) }; - Tree array = - gen.mkApply_V(gen.mkGlobalRef(pos,primitives.NEW_OARRAY), args); - return gen.mkAsInstanceOf(array, Type.UnboxedArrayType(element)); - } - - /** - * Generates a new unboxed array of given size and with elements - * of given unboxed type kind. - */ - private Tree genNewUnboxedArray(int pos, int kind, Tree size) { - Symbol symbol = primitives.getNewArraySymbol(kind); - Tree[] args = { coerce(size, UNBOXED_INT) }; - return gen.mkApply_V(gen.mkGlobalRef(pos, symbol), args); - } - - /** Generates an unboxed array length operation. */ - private Tree genUnboxedArrayLength(int pos, Tree array) { - assert isUnboxedArrayType(array.getType()): array; - Symbol symbol = primitives.getArrayLengthSymbol(array.getType()); - Tree[] args = { array }; - return gen.mkApply_V(gen.mkGlobalRef(pos, symbol), args); - } - - /** Generates an unboxed array get operation. */ - private Tree genUnboxedArrayGet(int pos, Tree array, Tree index) { - assert isUnboxedArrayType(array.getType()): array; - Symbol symbol = primitives.getArrayGetSymbol(array.getType()); - index = coerce(index, UNBOXED_INT); - Tree[] args = { array, index }; - return gen.mkApply_V(gen.mkGlobalRef(pos, symbol), args); - } - - /** Generates an unboxed array set operation. */ - private Tree genUnboxedArraySet(int pos, Tree array,Tree index,Tree value){ - assert isUnboxedArrayType(array.getType()): array; - Symbol symbol = primitives.getArraySetSymbol(array.getType()); - index = coerce(index, UNBOXED_INT); - value = coerce(value, getArrayElementType(array.getType())); - Tree[] args = { array, index, value }; - return gen.mkApply_V(gen.mkGlobalRef(pos, symbol), args); - } - - //######################################################################## - // Private Methods - Queries - - /** Returns the qualifier of the given tree. */ - private Tree getQualifier(Tree tree) { - switch (tree) { - case Select(Tree qualifier, _): - return qualifier; - default: - throw Debug.abort("no qualifier for tree", tree); - } - } - - /** Are the given erased types in a subtyping relation? */ - private boolean isSubType(Type tp1, Type tp2) { - global.nextPhase(); - boolean result = tp1.isSubType(tp2); - global.prevPhase(); - return result; - } - - /** Are the given erased types in an equality relation? */ - private boolean isSameAs(Type tp1, Type tp2) { - global.nextPhase(); - boolean result = tp1.isSameAs(tp2); - global.prevPhase(); - return result; - } - - /** Is the given type an unboxed type? */ - private boolean isUnboxedType(Type type) { - switch (type) { - case UnboxedType(_) : return true; - case UnboxedArrayType(_): return true; - default : return false; - } - } - - /** Is the given type an unboxed simple type? */ - private boolean isUnboxedSimpleType(Type type) { - switch (type) { - case UnboxedType(_) : return true; - default : return false; - } - } - - /** Is the given type an unboxed array type? */ - private boolean isUnboxedArrayType(Type type) { - switch (type) { - case UnboxedArrayType(_): return true; - default : return false; - } - } - - /** Returns the boxed version of the given unboxed type. */ - private Type boxUnboxedType(Type type) { - switch (type) { - case UnboxedType(TypeTags.UNIT): - return definitions.UNIT_CLASS.type(); - case UnboxedType(TypeTags.BOOLEAN): - return definitions.BOOLEAN_CLASS.type(); - case UnboxedType(TypeTags.BYTE): - return definitions.BYTE_CLASS.type(); - case UnboxedType(TypeTags.SHORT): - return definitions.SHORT_CLASS.type(); - case UnboxedType(TypeTags.CHAR): - return definitions.CHAR_CLASS.type(); - case UnboxedType(TypeTags.INT): - return definitions.INT_CLASS.type(); - case UnboxedType(TypeTags.LONG): - return definitions.LONG_CLASS.type(); - case UnboxedType(TypeTags.FLOAT): - return definitions.FLOAT_CLASS.type(); - case UnboxedType(TypeTags.DOUBLE): - return definitions.DOUBLE_CLASS.type(); - case UnboxedArrayType(Type element): - return Type.appliedType( - definitions.ARRAY_CLASS.type(), new Type[] {element}); - default: - throw Debug.abort("illegal case", type); - } - } - - /** Returns the element type of the given array type. */ - private Type getArrayElementType(Type type) { - switch (type) { - case TypeRef(_, Symbol symbol, Type[] args): - if (symbol != definitions.ARRAY_CLASS) break; - assert args.length == 1: type; - return args[0]; - case UnboxedArrayType(Type element): - return element; - } - throw Debug.abort("non-array type", type); - } - -////////////////////////////////////////////////////////////////////////////////// -// Bridge Building -///////////////////////////////////////////////////////////////////////////////// - - private TreeList bridges; - private HashMap bridgeSyms; - - /** Add bridge which Java-overrides `sym1' and which forwards to `sym' - */ - public void addBridge(Symbol owner, Symbol sym, Symbol sym1) { - Type bridgeType = sym1.nextType(); - - // create bridge symbol and add to bridgeSyms(sym) - // or return if bridge with required type already exists for sym. - SymSet bridgesOfSym = (SymSet) bridgeSyms.get(sym); - if (bridgesOfSym == null) bridgesOfSym = SymSet.EMPTY; - Symbol[] brs = bridgesOfSym.toArray(); - for (int i = 0; i < brs.length; i++) { - if (isSameAs(brs[i].type(), bridgeType)) return; - } - Symbol bridgeSym = sym.cloneSymbol(); - bridgeSym.flags |= (SYNTHETIC | BRIDGE); - bridgeSym.flags &= ~(JAVA | DEFERRED); - bridgesOfSym = bridgesOfSym.incl(bridgeSym); - bridgeSyms.put(sym, bridgesOfSym); - bridgeSym.setOwner(owner); - - // check that there is no overloaded symbol with same erasure as bridge - // todo: why only check for overloaded? - Symbol overSym = owner.members().lookup(sym.name); - switch (overSym.nextType()) { - case OverloadedType(Symbol[] alts, Type[] alttypes): - for (int i = 0; i < alts.length; i++) { - if (sym != alts[i] && isSameAs(bridgeType, alttypes[i])) { - unit.error(sym.pos, "overlapping overloaded alternatives; " + - "overridden " + sym1 + sym1.locationString() + - " has same erasure as " + alts[i] + - alttypes[i] + alts[i].locationString()); - } - } - } - - switch (bridgeType) { - case MethodType(Symbol[] params, Type restp): - // assign to bridge symbol its bridge type - // where owner of all parameters is bridge symbol itself. - Symbol[] params1 = new Symbol[params.length]; - for (int i = 0; i < params.length; i++) { - params1[i] = params[i].cloneSymbol(bridgeSym); - } - bridgeSym.setType(Type.MethodType(params1, restp)); - - bridges.append(genBridgeMethod(bridgeSym, sym)); - } - - } - - /** Add an "empty bridge" (abstract method declaration) to satisfy - * CLR's requirement that classes should provide declaration - * for all methods of the interfaces they implement - */ - /* - public void addEmptyBridge(Symbol owner, Symbol method) { - Type bridgeType = method.nextType(); - Symbol bridgeSym = method.cloneSymbol(owner); - bridgeSym.flags = bridgeSym.flags & ~JAVA | SYNTHETIC | DEFERRED; - //bridgeSym.setOwner(owner); - switch (bridgeType) { - case MethodType(Symbol[] params, Type restp): - // assign to bridge symbol its bridge type - // where owner of all parameters is bridge symbol itself. - Symbol[] params1 = new Symbol[params.length]; - for (int i = 0; i < params.length; i++) { - params1[i] = params[i].cloneSymbol(bridgeSym); - } - bridgeSym.setType(Type.MethodType(params1, restp)); - Tree bridge = gen.DefDef(bridgeSym, Tree.Empty); - bridges.append(bridge); - } - } - */ - - private final Map interfaces/*<Symbol,Set<Symbol>>*/ = new HashMap(); - - private Set getInterfacesOf(Symbol clasz) { - assert clasz.isClass(): Debug.show(clasz); - Set set = (Set)interfaces.get(clasz); - if (set == null) { - set = new HashSet(); - interfaces.put(clasz, set); - Type parents[] = clasz.parents(); - for (int i = 0; i < parents.length; i++) - set.addAll(getInterfacesOf(parents[i].symbol())); - if (clasz.isInterface()) set.add(clasz); - } - return set; - } - - private void addInterfaceBridges_(Symbol clasz) { - assert clasz.isClass() && !clasz.isInterface(): Debug.show(clasz); - assert clasz.parents().length > 0: Debug.show(clasz)+": "+clasz.info(); - Symbol svper = clasz.parents()[0].symbol(); - assert svper.isClass() && !svper.isInterface(): Debug.show(clasz); - Set interfaces = new HashSet(getInterfacesOf(clasz)); - interfaces.removeAll(getInterfacesOf(svper)); - for (Iterator i = interfaces.iterator(); i.hasNext(); ) { - Symbol inter = (Symbol)i.next(); - addInterfaceBridgesAux(clasz, inter.members()); - } - } - - private void addInterfaceBridgesAux(Symbol owner, Scope symbols) { - for (Scope.SymbolIterator i = symbols.iterator(); - i.hasNext();) { - Symbol member = i.next(); - if (!member.isTerm() || !member.isDeferred()) continue; - addInterfaceBridges(owner, member); - } - } - - - private Symbol getOverriddenMethod(Symbol method) { - Type[] parents = method.owner().parents(); - if (parents.length == 0) return Symbol.NONE; - return method.overriddenSymbol(parents[0]); - } - - public void addBridgeMethodsTo(Symbol method) { - assert method.owner().isClass() && !method.owner().isInterface(); - Symbol overridden = getOverriddenMethod(method); - if (!overridden.isNone() && !isSameAs(overridden.nextType(), method.nextType())) - addBridge(method.owner(), method, overridden); - } - - public void addInterfaceBridges(Symbol owner, Symbol method) { - assert owner.isClass() && !owner.isInterface(): Debug.show(owner); - Symbol overriding = method.overridingSymbol(owner.thisType()); - if (overriding == method) { - Symbol overridden = method.overriddenSymbol(owner.thisType().parents()[0], owner); - if (!overridden.isNone() && !isSameAs(overridden.nextType(), method.nextType())) - addBridge(owner, method, overridden); - // moved this into the TypeCreator class of the MSIL backend - //if (forMSIL && (overridden.isNone() || overridden.owner() != owner)) - // addEmptyBridge(owner, method); - } else if (!overriding.isNone() && !isSameAs(overriding.nextType(), method.nextType())) - addBridge(owner, overriding, method); - } - - private void addBridges(Symbol clasz, TreeList members) { - TreeList savedBridges = bridges; - HashMap savedBridgeSyms = bridgeSyms; - bridges = new TreeList(); - bridgeSyms = new HashMap(); - - int length = members.length(); - if (!clasz.isInterface()) { - for (int i = 0; i < length; i++) { - switch (members.get(i)) { - case DefDef(_, _, _, _, _, Tree rhs): - addBridgeMethodsTo(members.get(i).symbol()); - } - } - addInterfaceBridges_(clasz); - } - - members.append(bridges); - if (bridges.length() > 0) { - Type info = clasz.nextInfo(); - switch (info) { - case CompoundType(Type[] parts, Scope members_): - members_ = members_.cloneScope(); - for (int i = 0; i < bridges.length(); i++) { - Tree bridge = (Tree)bridges.get(i); - members_.enterOrOverload(bridge.symbol()); - } - clasz.updateInfo(Type.compoundType(parts, members_, info.symbol())); - break; - default: - throw Debug.abort("class = " + Debug.show(clasz) + ", " + - "info = " + Debug.show(info)); - } - } - bridgeSyms = savedBridgeSyms; - bridges = savedBridges; - } - - -} |