/* ____ ____ ____ ____ ______ *\ ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2005, LAMP/EPFL ** ** /_____/\____/\___/\____/____/ ** \* */ // $Id$ package scalac.symtab; import java.util.HashMap; import java.util.Map; import scalac.util.Debug; /** * This class implements a symbol cloner. It automatically determines * the new owner of cloned symbols, clones their type and keeps track * of all cloned symbols. Clone a type means clone all symbol declared * in that type (for example parameters of a MethodType). */ public class SymbolCloner { //######################################################################## // Public Fields /** A table that maps owners of symbols to owners of cloned symbols */ public final Map/* into which cloned symbols are stored */ public final Map/* " + Debug.show(clones.get(symbol)); Symbol clone = symbol.cloneSymbol(getOwnerFor(symbol)); clones.put(symbol, clone); return clone; } /** Clones the given symbols but not their types. */ public Symbol[] cloneSymbolsWithoutTypes(Symbol[] symbols) { if (symbols.length == 0) return Symbol.EMPTY_ARRAY; Symbol[] clones = new Symbol[symbols.length]; for (int i = 0; i < clones.length; i++) clones[i] = cloneSymbolWithoutType(symbols[i]); return clones; } /** Clones the given scope but not the type of its members. */ public Scope cloneScopeWithoutTypes(Scope scope) { Scope clone = new Scope(); for (Scope.SymbolIterator i = scope.iterator(); i.hasNext(); ) { clone.enterOrOverload(cloneSymbolWithoutType(i.next())); } return clone; } /** Clones the given symbol and its type. */ public Symbol cloneSymbol(Symbol symbol) { Symbol clone = cloneSymbolWithoutType(symbol); clone.setType(cloneType(symbol.info())); return clone; } /** Clones the given symbols and their types. */ public Symbol[] cloneSymbols(Symbol[] symbols) { Symbol[] clones = cloneSymbolsWithoutTypes(symbols); for (int i = 0; i < clones.length; i++) clones[i].setType(cloneType(symbols[i].info())); return clones; } /** Clones the given scope and the type of its members. */ public Scope cloneScope(Scope scope) { Scope clone = cloneScopeWithoutTypes(scope); for (Scope.SymbolIterator i = scope.iterator(); i.hasNext(); ) { Symbol member = i.next(); member.setType(cloneType(member.info())); } return clone; } /** Clones the given type. */ public Type cloneType(Type type) { return cloner.apply(type); } /** Clones the given types. */ public Type[] cloneTypes(Type[] types) { Type[] clones = new Type[types.length]; for (int i = 0; i < types.length; i++) clones[i] = cloner.apply(types[i]); return clones; } //######################################################################## // Public Methods - Mapping symbols /** * Returns the clone of the specified symbol if it has been cloned * and the specified symbol otherwise. */ public Symbol mapSymbol(Symbol symbol) { Object clone = clones.get(symbol); return clone != null ? (Symbol)clone : symbol; } /** Replaces all cloned symbols by clones in given type. */ public Type mapType(Type type) { return mapper.apply(type); } /** Returns the type map built during symbol cloning. */ // used in scalac/ast/TreeCloner.java public Type.Map getTypeMap() { return cloner; } //######################################################################## // Private Method private Symbol getCompoundClone(Symbol symbol) { assert symbol.isCompoundSym(): Debug.show(symbol); assert !owners.containsKey(symbol): Debug.show(symbol); assert !clones.containsKey(symbol): Debug.show(symbol) + " -> " + Debug.show(clones.get(symbol)); Symbol owner = (Symbol)clones.get(symbol.owner()); if (owner == null) owner = (Symbol)owners.get(symbol.owner()); if (owner == null) owner = symbol.owner(); Symbol clone = symbol.cloneSymbol(owner); clones.put(symbol, clone); return clone; } //######################################################################## // Private Class - Type mapper /** The type mapper Type.Map */ private final Type.Map mapper = new TypeMapper(); private class TypeMapper extends Type.Map { public Type apply(Type type) { switch (type) { case ErrorType: case NoType: case NoPrefix: return type; case ThisType(Symbol symbol): Symbol clone = (Symbol)clones.get(symbol); if (clone == null) return type; return Type.ThisType(clone); case SingleType(Type prefix, Symbol symbol): Symbol clone = (Symbol)clones.get(symbol); if (clone == null) return map(type); return Type.singleType(apply(prefix), clone); case ConstantType(_, _): return map(type); case TypeRef(Type prefix, Symbol symbol, Type[] args): Symbol clone = (Symbol)clones.get(symbol); if (clone == null) return map(type); return Type.typeRef(apply(prefix), clone, map(args)); case CompoundType(Type[] parts, Scope members): Symbol clone = (Symbol)clones.get(type.symbol()); // !!! if (clone == null) return map(type); if (clone == null) clone = type.symbol(); return Type.compoundType(map(parts), members, clone); case MethodType(Symbol[] vparams, Type result): return Type.MethodType(vparams, apply(result)); case PolyType(Symbol[] tparams, Type result): return Type.PolyType(tparams, apply(result)); case UnboxedType(_): return type; case UnboxedArrayType(_): return map(type); default: throw Debug.abort("illegal case", type); } }} //######################################################################## // Private Class - Type cloner /** The type cloner Type.Map */ private final Type.Map cloner = new TypeCloner(); private class TypeCloner extends TypeMapper { public Type apply(Type type){ switch (type) { case CompoundType(Type[] parts, Scope members): Symbol clone = /* !!! getCompoundClone */(type.symbol()); return Type.compoundType(map(parts), /* !!! cloneScope */(members), clone); case MethodType(Symbol[] vparams, Type result): Symbol[] clones = cloneSymbols(vparams); return Type.MethodType(clones, apply(result)); case PolyType(Symbol[] tparams, Type result): Symbol[] clones = cloneSymbols(tparams); return Type.PolyType(clones, apply(result)); default: return super.apply(type); } }} //######################################################################## }