KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > visit > TypeBuilder


1 package polyglot.visit;
2
3 import java.util.Stack JavaDoc;
4
5 import polyglot.ast.Node;
6 import polyglot.ast.NodeFactory;
7 import polyglot.frontend.Job;
8 import polyglot.main.Report;
9 import polyglot.types.*;
10 import polyglot.types.Package;
11 import polyglot.util.*;
12
13 /** Visitor which traverses the AST constructing type objects. */
14 public class TypeBuilder extends HaltingVisitor
15 {
16     protected ImportTable importTable;
17     protected Job job;
18     protected TypeSystem ts;
19     protected NodeFactory nf;
20     protected TypeBuilder outer;
21     protected boolean inCode; // true if the last scope pushed as not a class.
22
protected boolean global; // true if all scopes pushed have been classes.
23
protected ParsedClassType type; // last class pushed.
24

25     public TypeBuilder(Job job, TypeSystem ts, NodeFactory nf) {
26         this.job = job;
27         this.ts = ts;
28         this.nf = nf;
29         this.outer = null;
30     }
31
32     public TypeBuilder push() {
33         TypeBuilder tb = (TypeBuilder) this.copy();
34         tb.outer = this;
35         return tb;
36     }
37
38     public TypeBuilder pop() {
39         return outer;
40     }
41
42     public Job job() {
43         return job;
44     }
45
46     public ErrorQueue errorQueue() {
47         return job.compiler().errorQueue();
48     }
49
50     public NodeFactory nodeFactory() {
51         return nf;
52     }
53
54     public TypeSystem typeSystem() {
55         return ts;
56     }
57
58     public NodeVisitor begin() {
59         // Initialize the stack from the context.
60
Context context = job.context();
61
62         if (context == null) {
63             return this;
64         }
65
66         Stack JavaDoc s = new Stack JavaDoc();
67
68         for (ParsedClassType ct = context.currentClassScope(); ct != null; ) {
69             s.push(ct);
70
71             if (ct.isNested()) {
72                 ct = (ParsedClassType) ct.outer();
73             }
74             else {
75                 ct = null;
76             }
77         }
78
79         if (context.importTable() != null) {
80             setImportTable(context.importTable());
81         }
82
83         TypeBuilder tb = this;
84
85         while (! s.isEmpty()) {
86             ParsedClassType ct = (ParsedClassType) s.pop();
87
88             try {
89                 tb = tb.pushClass(ct);
90             }
91             catch (SemanticException e) {
92                 errorQueue().enqueue(ErrorInfo.SEMANTIC_ERROR,
93                                      e.getMessage(), ct.position());
94                 return null;
95             }
96
97             if (ct.isLocal() || ct.isAnonymous()) {
98                 tb = tb.pushCode();
99             }
100         }
101
102         return tb;
103     }
104
105     public NodeVisitor enter(Node n) {
106         try {
107         return n.del().buildTypesEnter(this);
108     }
109     catch (SemanticException e) {
110         Position position = e.position();
111
112         if (position == null) {
113         position = n.position();
114         }
115
116             if (e.getMessage() != null) {
117                 errorQueue().enqueue(ErrorInfo.SEMANTIC_ERROR,
118                                     e.getMessage(), position);
119             }
120                             
121             return this;
122     }
123     }
124
125     public Node leave(Node old, Node n, NodeVisitor v) {
126     try {
127         return n.del().buildTypes((TypeBuilder) v);
128     }
129     catch (SemanticException e) {
130         Position position = e.position();
131
132         if (position == null) {
133         position = n.position();
134         }
135
136             if (e.getMessage() != null) {
137                 errorQueue().enqueue(ErrorInfo.SEMANTIC_ERROR,
138                                     e.getMessage(), position);
139             }
140
141         return n;
142     }
143     }
144
145     public TypeBuilder pushCode() {
146         if (Report.should_report(Report.visit, 4))
147         Report.report(4, "TB pushing code: " + this);
148         TypeBuilder tb = push();
149         tb.inCode = true;
150         tb.global = false;
151         return tb;
152     }
153
154     protected TypeBuilder pushClass(ParsedClassType type) throws SemanticException {
155         if (Report.should_report(Report.visit, 4))
156         Report.report(4, "TB pushing class " + type + ": " + this);
157
158         TypeBuilder tb = push();
159         tb.type = type;
160         tb.inCode = false;
161
162     // Make sure the import table finds this class.
163
if (importTable() != null && type.isTopLevel()) {
164         tb.importTable().addClassImport(type.fullName());
165     }
166         
167         return tb;
168     }
169
170     protected ParsedClassType newClass(Position pos, Flags flags, String JavaDoc name)
171         throws SemanticException
172     {
173     TypeSystem ts = typeSystem();
174
175         ParsedClassType ct = ts.createClassType(this.job.source());
176
177     if (inCode) {
178             ct.kind(ClassType.LOCAL);
179         ct.outer(currentClass());
180         ct.flags(flags);
181         ct.name(name);
182         ct.position(pos);
183
184         if (currentPackage() != null) {
185             ct.package_(currentPackage());
186         }
187
188         return ct;
189     }
190     else if (currentClass() != null) {
191             ct.kind(ClassType.MEMBER);
192         ct.outer(currentClass());
193         ct.flags(flags);
194         ct.name(name);
195         ct.position(pos);
196
197         currentClass().addMemberClass(ct);
198
199         if (currentPackage() != null) {
200             ct.package_(currentPackage());
201         }
202
203             // if all the containing classes for this class are member
204
// classes or top level classes, then add this class to the
205
// parsed resolver.
206
ClassType container = ct.outer();
207             boolean allMembers = (container.isMember() || container.isTopLevel());
208             while (container.isMember()) {
209                 container = container.outer();
210                 allMembers = allMembers &&
211                         (container.isMember() || container.isTopLevel());
212             }
213
214             if (allMembers) {
215                 typeSystem().parsedResolver().addNamed(
216                     typeSystem().getTransformedClassName(ct), ct);
217             }
218
219         return ct;
220     }
221     else {
222             ct.kind(ClassType.TOP_LEVEL);
223         ct.flags(flags);
224         ct.name(name);
225         ct.position(pos);
226
227         if (currentPackage() != null) {
228             ct.package_(currentPackage());
229         }
230
231             Named dup = ((CachingResolver) typeSystem().systemResolver()).check(ct.fullName());
232
233             if (dup != null && dup.fullName().equals(ct.fullName())) {
234                 throw new SemanticException("Duplicate class \"" +
235                                             ct.fullName() + "\".", pos);
236             }
237
238             typeSystem().parsedResolver().addNamed(ct.fullName(), ct);
239             ((CachingResolver) typeSystem().systemResolver()).addNamed(ct.fullName(), ct);
240
241         return ct;
242     }
243     }
244
245     public TypeBuilder pushAnonClass(Position pos) throws SemanticException {
246         if (Report.should_report(Report.visit, 4))
247         Report.report(4, "TB pushing anon class: " + this);
248
249         if (! inCode) {
250             throw new InternalCompilerError(
251                 "Can only push an anonymous class within code.");
252         }
253
254     TypeSystem ts = typeSystem();
255
256         ParsedClassType ct = ts.createClassType(this.job().source());
257         ct.kind(ClassType.ANONYMOUS);
258         ct.outer(currentClass());
259         ct.position(pos);
260
261         if (currentPackage() != null) {
262             ct.package_(currentPackage());
263         }
264
265         return pushClass(ct);
266     }
267
268     public TypeBuilder pushClass(Position pos, Flags flags, String JavaDoc name)
269         throws SemanticException {
270
271         ParsedClassType t = newClass(pos, flags, name);
272         return pushClass(t);
273     }
274
275     public ParsedClassType currentClass() {
276         return this.type;
277     }
278
279     public Package JavaDoc currentPackage() {
280         if (importTable() == null) return null;
281     return importTable.package_();
282     }
283
284     public ImportTable importTable() {
285         return importTable;
286     }
287
288     public void setImportTable(ImportTable it) {
289         this.importTable = it;
290     }
291
292     public String JavaDoc toString() {
293         return "(TB " + type +
294                 (inCode ? " inCode" : "") +
295                 (global ? " global" : "") +
296                 (outer == null ? ")" : " " + outer.toString() + ")");
297     }
298 }
299
Popular Tags