summaryrefslogblamecommitdiff
path: root/sources/scalac/ast/TreeCloner.java
blob: 8d96c1b23e83c3ec50eb5e6939b6c30bdd2a64b5 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

                                                                          
                                                                          










                                                                          
                                  
                                        
                          



                                                                   





                                                                      















                                                                              




                                                                




























                                                                              
                                           











                                                                              



















                                                                              




                                                              





















                                                                              
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002-2005, LAMP/EPFL         **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.ast;

import java.util.Map;

import scalac.Global;
import scalac.symtab.Symbol;
import scalac.symtab.SymbolCloner;
import scalac.symtab.SymbolSubstTypeMap;
import scalac.symtab.Type;
import scalac.util.Debug;

/**
 * This class implements a deep tree cloner. It provides support to
 * change tree symbols and tree types on the fly. This cloner never
 * clones symbols, but its default implementation of getSymbolFor
 * requires that all symbols that are defined by the tree to be cloned
 * are present in the symbol substitution. This implies that if the
 * tree to clone contains definitions, it must first be traversed to
 * map all defined symbols. To do this, one can use TreeSymbolCloner.
 */
public class TreeCloner extends Transformer {

    //########################################################################
    // Private Fields

    /** The symbol substitution to apply to tree symbols */
    private final Map/*<Symbol,Symbol>*/ symbols;

    /** The type map to apply to tree types */
    private final Type.Map types;

    //########################################################################
    // Public Constructors

    /** Initializes a new instance. */
    public TreeCloner(Global global, SymbolSubstTypeMap types) {
        this(global, types.getSymbols(), types);
    }

    /** Initializes a new instance. */
    public TreeCloner(Global global, Map symbols, Type.Map types) {
        super(global, global.make, new StrictTreeCopier(global.make));
        this.symbols = symbols;
        this.types = types;
    }

    //########################################################################
    // Public Methods

    /**
     * Returns the symbol for the given cloned tree. The default
     * implementation returns the result of the application of the
     * symbol substitution to the given tree's symbol. If there is no
     * mapping for that symbol returns that same symbol.
     */
    public Symbol getSymbolFor(Tree tree) {
        Symbol oldsym = tree.symbol();
        Symbol newsym = (Symbol)symbols.get(oldsym);
        // cloned definitions must have a cloned symbol
        assert newsym != null || !tree.definesSymbol() : Debug.show(oldsym);
        return newsym != null ? newsym : oldsym;
    }

    /**
     * Returns the type for the given cloned tree. The default
     * implementation returns the result of the application of the
     * type map to the given tree's type.
     */
    public Type getTypeFor(Tree tree) {
        return types.apply(tree.getType());
    }

    /** Traverses the given tree and returns a deeply cloned one. */
    public Tree transform(Tree tree) {
        tree = super.transform(tree);
        if (tree.hasSymbol()) tree.setSymbol(getSymbolFor(tree));
        tree.setType(getTypeFor(tree));
        return tree;
    }

    //########################################################################
}


/** !!! */
public class GenTreeCloner extends GenTransformer {

    //########################################################################
    // Public Fields

    /** The symbol cloner */
    public final SymbolCloner cloner;

    //########################################################################
    // Public Constructors

    /** Initializes a new instance. */
    public GenTreeCloner(Global global, Type.Map map, SymbolCloner cloner) {
        super(global, map);
        this.cloner = cloner;
    }

    public GenTreeCloner(Global global, SymbolCloner cloner) {
        super(global, cloner.getTypeMap());
        this.cloner = cloner;
    }

    //########################################################################
    // Public Methods

    public Symbol getSymbolFor(Tree tree) {
        switch (tree) {
        case ValDef(_, _, _, _):
            if (tree.symbol().owner().isClass()) break;
            Symbol symbol = cloner.cloneSymbol(tree.symbol());
            symbol.setType(transform(symbol.type()));
            return symbol;
        case LabelDef(_, _, _):
            Symbol symbol = cloner.cloneSymbol(tree.symbol());
            symbol.setType(transform(symbol.type()));
            return symbol;
        }
        Symbol symbol = (Symbol)cloner.clones.get(tree.symbol());
        assert !tree.definesSymbol() || symbol != null: tree;
        return symbol != null ? symbol : tree.symbol();
    }

    //########################################################################
}