summaryrefslogtreecommitdiff
path: root/sources/scalac/ast/TreeSymbolCloner.java
blob: 70b1b236c393e6a5d8affdfab0df83c715da32ae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    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;
        }
    }

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