summaryrefslogtreecommitdiff
path: root/sources/scalac/ast/Transformer.java.tmpl
blob: 69aef7dfcae7180a2e5263c02bda012846ad82f2 (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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.ast;

import scalac.Global;
import scalac.Unit;
import scalac.symtab.Type;
{#Imports#}

/**
 * A default transformer class. This class traverses the abstract
 * syntax tree but does not do any transformations.
 */
public class Transformer {

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

    /** The global environment */
    public final Global global;

    /** The tree factory */
    public final TreeFactory make;

    /** The tree copier */
    public final TreeCopier copy;

    /** A tree generator */
    public final TreeGen gen;

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

    public Transformer(Global global) {
        this(global, global.make);
    }

    public Transformer(Global global, TreeFactory make) {
        this(global, make, new LazyTreeCopier(make));
    }

    public Transformer(Global global, TreeFactory make, TreeCopier  copy) {
        this.global = global;
        this.make = make;
        this.copy = copy;
        this.gen = global.treeGen;
    }

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

    public void apply(Unit[] units) {
        for (int i = 0; i < units.length; i++) apply(units[i]);
    }

    public void apply(Unit unit) {
        unit.global.log("transforming " + unit);
        unit.body = transform(unit.body);
    }

    public Tree transform(Tree tree) {
        {#TreeSwitch#}
    }

    public Template transform(Template tree) {
        return (Template)transform((Tree)tree);
    }

    {#TransformArrays#}

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


public class GenTransformer {

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

    /** The global environment */
    public final Global global;

    /** The type map */
    public final Type.Map map;

    /** A tree generator */
    public final TreeGen gen;

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

    /** Initializes this instance with an identity type map. */
    public GenTransformer(Global global) {
        this(global, Type.IdMap);
    }

    /** Initializes this instance with given type map. */
    public GenTransformer(Global global, Type.Map map) {
        this.global = global;
        this.gen = global.treeGen;
        this.map = map;
    }

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

    /** Transforms the given units. */
    public void apply(Unit[] units) {
        for (int i = 0; i < units.length; i++) apply(units[i]);
    }

    /** Transforms the given unit. */
    public void apply(Unit unit) {
        unit.global.log("transforming " + unit);
        unit.body = transform(unit.body);
    }

    /** Transforms the given symbol. */
    public Symbol getSymbolFor(Tree tree) {
        return tree.symbol();
    }

    /** Transforms the given types. */
    public Type[] transform(Type[] types) {
        for (int i = 0; i < types.length; i++) {
            Type type = transform(types[i]);
            if (type == types[i]) continue;
            Type[] clones = new Type[types.length];
            for (int j = 0; j < i; j++) clones[j] = types[j];
            clones[i] = type;
            for (; i < types.length; i++) clones[i] = transform(types[i]);
            return clones;
        }
        return types;
    }

    /** Transforms the given type. */
    public Type transform(Type type) {
        return map.apply(type);
    }

    /** Transforms the given tree. */
    public Tree transform(Tree tree) {
        switch (tree) {

        // case Bad():

        case Empty:
            return tree;

        case ClassDef(_, _, _, _, _, Template impl):
            Symbol symbol = getSymbolFor(tree);
            if (global.currentPhase.id < global.PHASE.ADDCONSTRUCTORS.id()) {
                Symbol impl_symbol = getSymbolFor(impl);
                Tree[] parents = transform(impl.parents);
                Tree[] body = transform(impl.body);
                return gen.ClassDef(symbol, parents, impl_symbol, body);
            } else {
                Tree[] body = transform(impl.body);
                return gen.ClassDef(symbol, body);
            }

        case PackageDef(Tree packaged, Template(Tree[] parents, Tree[] body)):
            Symbol symbol = getSymbolFor(packaged);
            assert parents.length == 0: tree;
            return gen.PackageDef(symbol, transform(body));

        // case ModuleDef(_, _, _, Template impl):

        case ValDef(_, _, _, Tree rhs):
            Symbol symbol = getSymbolFor(tree);
            return gen.ValDef(symbol, transform(rhs));

        // case PatDef(int mods, Tree pat, Tree rhs):

        case DefDef(_, _, _, _, _, Tree rhs):
            Symbol symbol = getSymbolFor(tree);
            return gen.DefDef(symbol, transform(rhs));

        case AbsTypeDef(_, _, _, _):
            Symbol symbol = getSymbolFor(tree);
            return gen.AbsTypeDef(symbol);

        case AliasTypeDef(_, _, _, _):
            Symbol symbol = getSymbolFor(tree);
            return gen.AliasTypeDef(symbol);

        case Import(Tree expr, Name[] selectors):
            return gen.Import(tree.pos, transform(expr), selectors);

        case CaseDef(Tree pat, Tree guard, Tree body):
            pat = transform(pat);
            guard = transform(guard);
            body = transform(body);
            return gen.CaseDef(pat, guard, body);

        // case Template(Tree[] parents, Tree[] body):

        case LabelDef(_, Ident[] params, Tree rhs):
            Symbol symbol = getSymbolFor(tree);
            return gen.LabelDef(symbol, transform(params), transform(rhs));

        case Block(Tree[] stats):
            return gen.Block(tree.pos, transform(stats));

        // case Sequence(Tree[] trees):
        // case Alternative(Tree[] trees):
        // case Bind(Name name, Tree rhs):
        // case Visitor(CaseDef[] cases):
        // case Function(ValDef[] vparams, Tree body):

        case Assign(Tree lhs, Tree rhs):
            return gen.Assign(tree.pos, transform(lhs), transform(rhs));

        case If(Tree cond, Tree thenp, Tree elsep):
            cond = transform(cond);
            thenp = transform(thenp);
            elsep = transform(elsep);
            return gen.If(tree.pos, cond, thenp, elsep);

        case Switch(Tree test, int[] tags, Tree[] bodies, Tree otherwise):
            test = transform(test);
            bodies = transform(bodies);
            otherwise = transform(otherwise);
            return gen.Switch(tree.pos, test, tags, bodies, otherwise);

        case Return(Tree expr):
            Symbol symbol = getSymbolFor(tree);
            return gen.Return(tree.pos, symbol, transform(expr));

        // case Throw(Tree expr):

        case New(Template(Tree[] base, Tree[] body)):
            assert base.length == 1 && body.length == 0: tree;
            return gen.New(tree.pos, transform(base[0]));

        case Typed(Tree expr, Tree tpe):
            return gen.Typed(tree.pos, transform(expr), transform(tpe));

        case TypeApply(Tree fun, Tree[] args):
            return gen.TypeApply(transform(fun), transform(args));

        case Apply(Tree fun, Tree[] args):
            return gen.Apply(transform(fun), transform(args));

        case Super(_, _):
            Symbol symbol = getSymbolFor(tree);
            return gen.Super(tree.pos, symbol);

        case This(_):
            Symbol symbol = getSymbolFor(tree);
            return gen.This(tree.pos, symbol);

        case Select(Tree qualifier, _):
            Symbol symbol = getSymbolFor(tree);
            return gen.Select(tree.pos, transform(qualifier), symbol);

        case Ident(_):
            Symbol symbol = getSymbolFor(tree);
            return gen.Ident(tree.pos, symbol);

        case Literal(AConstant value):
            return gen.Literal(tree.pos, value);

        case TypeTerm():
            return gen.mkType(tree.pos, transform(tree.type()));

        // case SingletonType(Tree ref):
        // case SelectFromType(Tree qualifier, Name selector):
        // case FunType(Tree[] argtpes, Tree restpe):
        // case CompoundType(Tree[] parents, Tree[] refinements):
        // case AppliedType(Tree tpe, Tree[] args):
        // case Try(Tree block, Tree catcher, Tree finalizer):

        default:
            throw Debug.abort("illegal case", tree);
        }
    }

    {#TransformArrays#}

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