diff options
Diffstat (limited to 'sources/scalac/ast/TreeCopier.java')
-rw-r--r-- | sources/scalac/ast/TreeCopier.java | 91 |
1 files changed, 91 insertions, 0 deletions
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; + } +} |