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
|
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */
// $OldId: AddAccessorsPhase.java,v 1.1 2002/10/17 12:27:11 schinz Exp $
// $Id$
package scalac.transformer;
import java.util.Map;
import java.util.HashMap;
import scalac.Global;
import scalac.Phase;
import scalac.PhaseDescriptor;
import scalac.Unit;
import scalac.ast.Transformer;
import scalac.ast.Tree;
import scalac.ast.Tree.Template;
import scalac.ast.TreeList;
import scalac.symtab.Modifiers;
import scalac.symtab.Symbol;
import scalac.symtab.TermSymbol;
import scalac.symtab.Type;
import scalac.util.Name;
import scalac.util.Debug;
/**
* This phase adds private accessor fields and methods for all class
* constructor arguments which are accessed from within the class'
* methods, or nested classes.
*/
public class AddAccessorsPhase extends Phase {
//########################################################################
// Public Constructors
/** Initializes this instance. */
public AddAccessorsPhase(Global global, PhaseDescriptor descriptor) {
super(global, descriptor);
}
//########################################################################
// Public Methods
/** Applies this phase to the given compilation units. */
public void apply(Unit[] units) {
treeTransformer.apply(units);
}
//########################################################################
// Private Class - Tree transformer
/** The tree transformer */
private final Transformer treeTransformer = new Transformer(global) {
/** The parameter to accessor method map */
private final Map/*<Symbol,Symbol>*/ methods = new HashMap();
/** Creates an accessor field symbol for given parameter. */
private Symbol createAccessorField(Symbol param) {
int flags = Modifiers.PRIVATE | Modifiers.STABLE;
Name name = Name.fromString(param.name + "$");
Symbol owner = param.owner().constructorClass();
Symbol field = new TermSymbol(param.pos, name, owner, flags);
field.setType(param.type());
owner.members().enterOrOverload(field);
return field;
}
/** Creates an accessor method symbol for given parameter. */
private Symbol createAccessorMethod(Symbol param) {
int flags = Modifiers.PRIVATE | Modifiers.STABLE | Modifiers.ACCESSOR;
Name name = param.name;
Symbol owner = param.owner().constructorClass();
Symbol method = new TermSymbol(param.pos, name, owner, flags);
method.setType(Type.MethodType(Symbol.EMPTY_ARRAY, param.type()));
owner.members().enterOrOverload(method);
methods.put(param, method);
return method;
}
/** Transforms the given tree. */
public Tree transform(Tree tree) {
switch (tree) {
case ClassDef(_, _, _, _, _, Template impl): {
Symbol clasz = tree.symbol();
// transform parents and body
Tree[] parents = transform(impl.parents);
Tree[] body = transform(impl.body);
// create accessor field & method trees
TreeList accessors = new TreeList();
Symbol[] params = clasz.valueParams();
for (int i = 0; i < params.length; ++i) {
Symbol param = params[i];
Symbol method = (Symbol)methods.remove(param);
if (method == null) continue;
Symbol field = createAccessorField(param);
accessors.append(
gen.ValDef(
field,
gen.Ident(param.pos, param)));
accessors.append(
gen.DefDef(
method,
gen.Select(gen.This(param.pos, clasz), field)));
}
body = Tree.concat(accessors.toArray(), body);
impl = gen.Template(clasz.pos, impl.symbol(), parents, body);
return gen.ClassDef(clasz, impl);
}
case Select(Tree qualifier, _):
if (!tree.symbol().owner().isPrimaryConstructor()) break;
qualifier = transform(qualifier);
Symbol method = (Symbol)methods.get(tree.symbol());
if (method == null)
method = createAccessorMethod(tree.symbol());
return gen.Apply(gen.Select(tree.pos, qualifier, method));
}
return super.transform(tree);
}
};
//########################################################################
}
|