summaryrefslogblamecommitdiff
path: root/sources/scalac/ast/TreeSymbolCloner.java
blob: 70b1b236c393e6a5d8affdfab0df83c715da32ae (plain) (tree)






































































































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

// $Id$

package scalac.ast;

import java.util.Map;
import java.util.HashMap;

import scalac.symtab.Symbol;
import scalac.symtab.SymbolCloner;
import scalac.util.Name;
import scalac.util.Debug;

/**
 * This class implements a tree traverser that clones specified
 * symbols it encounters.
 */
public class TreeSymbolCloner extends Traverser {

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

    // !!! replace Idents in patterns by ValDefs and remove this field
    /** Indicates whether we are in a pattern */
    private boolean inPattern = false;

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

    /** The symbol cloner used to clone symbols */
    public final SymbolCloner cloner;

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

    /** Initializes a new instance. */
    public TreeSymbolCloner(SymbolCloner cloner) {
        this.cloner = cloner;
    }

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

    /**
     * Returns true iff the symbol of the given tree symbol must be
     * cloned. The default implementation returns true iff the tree
     * defines a symbol and that symbol hasn't been cloned yet.
     */
    public boolean mustCloneSymbolOf(Tree tree) {
        // !!! replace Idents in patterns by ValDefs and remove this switch
        switch (tree) {
        case Ident(Name name):
            if (!inPattern || !name.isVariable()) return false; else break;
        default:
            if (!tree.definesSymbol()) return false; else break;
        }
        return !cloner.clones.containsKey(tree.symbol());
    }

    /**
     * Clones the given symbol. The default implementation invokes
     * getOwnerOfCloneOf to obtain the owner of the cloned symbol and
     * then invokes the symbol cloner to clone the symbol.
     */
    public Symbol cloneSymbol(Symbol symbol) {
        return cloner.cloneSymbol(symbol);
    }

    /**
     * Traverses the tree and clones symbols. The default
     * implemenation invokes cloneSymbol with the symbol of every tree
     * nodes for which mustCloneSymbolOf returns true.
     */
    public void traverse(Tree tree) {
        if (mustCloneSymbolOf(tree)) cloneSymbol(tree.symbol());
        // !!!replace Idents in patterns by ValDefs and remove this switch
        switch (tree) {
        case PatDef(_, Tree pat, Tree rhs):
            inPattern = true;
            traverse(pat);
            inPattern = false;
            traverse(rhs);
            return;
        case CaseDef(Tree pat, Tree guard, Tree body):
            inPattern = true;
            traverse(pat);
            inPattern = false;
            traverse(guard);
            traverse(body);
            return;
        default:
            super.traverse(tree);
            return;
        }
    }

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