KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > types > Context_c


1 package polyglot.ext.jl.types;
2
3 import java.util.HashMap JavaDoc;
4 import java.util.List JavaDoc;
5 import java.util.Collection JavaDoc;
6 import java.util.Map JavaDoc;
7
8 import polyglot.main.Report;
9 import polyglot.types.*;
10 import polyglot.types.Package;
11 import polyglot.util.CollectionUtil;
12 import polyglot.util.Enum;
13 import polyglot.util.InternalCompilerError;
14
15 /**
16  * This class maintains a context for looking up named variables, types,
17  * and methods.
18  * It's implemented as a stack of Context objects. Each Context
19  * points to an outer context. To enter a new scope, call one of the
20  * pushXXX methods. To leave a scope, just follow the outer() pointer.
21  * NodeVisitors handle leaving scope automatically.
22  * Each context object contains maps from names to variable, type, and
23  * method objects declared in that scope.
24  */

25 public class Context_c implements Context
26 {
27     protected Context outer;
28     protected TypeSystem ts;
29
30     public static class Kind extends Enum JavaDoc {
31     public Kind(String JavaDoc name) {
32         super(name);
33     }
34     }
35
36     public static final Kind BLOCK = new Kind("block");
37     public static final Kind CLASS = new Kind("class");
38     public static final Kind CODE = new Kind("code");
39     public static final Kind OUTER = new Kind("outer");
40     public static final Kind SOURCE = new Kind("source");
41     
42     public Context_c(TypeSystem ts) {
43         this.ts = ts;
44         this.outer = null;
45         this.kind = OUTER;
46     }
47
48     public boolean isBlock() { return kind == BLOCK; }
49     public boolean isClass() { return kind == CLASS; }
50     public boolean isCode() { return kind == CODE; }
51     public boolean isOuter() { return kind == OUTER; }
52     public boolean isSource() { return kind == SOURCE; }
53
54     public TypeSystem typeSystem() {
55         return ts;
56     }
57
58     public Object JavaDoc copy() {
59         try {
60             return super.clone();
61         }
62         catch (CloneNotSupportedException JavaDoc e) {
63             throw new InternalCompilerError("Java clone() weirdness.");
64         }
65     }
66
67     protected Context_c push() {
68         Context_c v = (Context_c) this.copy();
69         v.outer = this;
70         v.types = null;
71         v.vars = null;
72         return v;
73     }
74
75     /**
76      * The import table for the file
77      */

78     protected ImportTable it;
79     protected Kind kind;
80     protected ClassType type;
81     protected ParsedClassType scope;
82     protected CodeInstance code;
83     protected Map JavaDoc types;
84     protected Map JavaDoc vars;
85     protected boolean inCode;
86
87     /**
88      * Is the context static?
89      */

90     protected boolean staticContext;
91
92     public Resolver outerResolver() {
93         if (it != null) {
94             return it;
95         }
96         return ts.systemResolver();
97     }
98
99     public ImportTable importTable() {
100         return it;
101     }
102
103     /** The current package, or null if not in a package. */
104     public Package JavaDoc package_() {
105         return importTable().package_();
106     }
107
108     /**
109      * Returns whether the particular symbol is defined locally. If it isn't
110      * in this scope, we ask the parent scope, but don't traverse to enclosing
111      * classes.
112      */

113     public boolean isLocal(String JavaDoc name) {
114         if (isClass()) {
115             return false;
116         }
117         
118         if ((isBlock() || isCode()) &&
119             (findVariableInThisScope(name) != null || findInThisScope(name) != null)) {
120             return true;
121         }
122
123         if (outer == null) {
124             return false;
125         }
126
127         return outer.isLocal(name);
128     }
129      
130     /**
131      * Looks up a method with name "name" and arguments compatible with
132      * "argTypes".
133      */

134     public MethodInstance findMethod(String JavaDoc name, List JavaDoc argTypes) throws SemanticException {
135         if (Report.should_report(TOPICS, 3))
136           Report.report(3, "find-method " + name + argTypes + " in " + this);
137
138         // Check for any method with the appropriate name.
139
// If found, stop the search since it shadows any enclosing
140
// classes method of the same name.
141
if (this.currentClass() != null &&
142             ts.hasMethodNamed(this.currentClass(), name)) {
143             if (Report.should_report(TOPICS, 3))
144               Report.report(3, "find-method " + name + argTypes + " -> " +
145                                 this.currentClass());
146
147             // Found a class which has a method of the right name.
148
// Now need to check if the method is of the correct type.
149
return ts.findMethod(this.currentClass(),
150                                  name, argTypes, this.currentClass());
151         }
152
153         if (outer != null) {
154             return outer.findMethod(name, argTypes);
155         }
156
157         throw new SemanticException("Method " + name + " not found.");
158     }
159
160     /**
161      * Gets a local of a particular name.
162      */

163     public LocalInstance findLocal(String JavaDoc name) throws SemanticException {
164     VarInstance vi = findVariableSilent(name);
165
166     if (vi instanceof LocalInstance) {
167         return (LocalInstance) vi;
168     }
169
170         throw new SemanticException("Local " + name + " not found.");
171     }
172
173     /**
174      * Finds the class which added a field to the scope.
175      */

176     public ClassType findFieldScope(String JavaDoc name) throws SemanticException {
177         if (Report.should_report(TOPICS, 3))
178           Report.report(3, "find-field-scope " + name + " in " + this);
179
180     VarInstance vi = findVariableInThisScope(name);
181
182         if (vi instanceof FieldInstance) {
183             if (Report.should_report(TOPICS, 3))
184               Report.report(3, "find-field-scope " + name + " in " + vi);
185             return type;
186         }
187
188         if (vi == null && outer != null) {
189             return outer.findFieldScope(name);
190         }
191
192         throw new SemanticException("Field " + name + " not found.");
193     }
194
195     /** Finds the class which added a method to the scope.
196      */

197     public ClassType findMethodScope(String JavaDoc name) throws SemanticException {
198         if (Report.should_report(TOPICS, 3))
199           Report.report(3, "find-method-scope " + name + " in " + this);
200
201         if (this.currentClass() != null &&
202             ts.hasMethodNamed(this.currentClass(), name)) {
203             if (Report.should_report(TOPICS, 3))
204               Report.report(3, "find-method-scope " + name + " -> " +
205                                 this.currentClass());
206             return this.currentClass();
207         }
208
209         if (outer != null) {
210             return outer.findMethodScope(name);
211         }
212
213         throw new SemanticException("Method " + name + " not found.");
214     }
215
216     /**
217      * Gets a field of a particular name.
218      */

219     public FieldInstance findField(String JavaDoc name) throws SemanticException {
220     VarInstance vi = findVariableSilent(name);
221
222     if (vi instanceof FieldInstance) {
223         FieldInstance fi = (FieldInstance) vi;
224
225         if (! ts.isAccessible(fi, this)) {
226                 throw new SemanticException("Field " + name + " not accessible.");
227         }
228
229             if (Report.should_report(TOPICS, 3))
230               Report.report(3, "find-field " + name + " -> " + fi);
231         return fi;
232     }
233
234         throw new NoMemberException(NoMemberException.FIELD, "Field " + name + " not found.");
235     }
236
237     /**
238      * Gets a local or field of a particular name.
239      */

240     public VarInstance findVariable(String JavaDoc name) throws SemanticException {
241     VarInstance vi = findVariableSilent(name);
242
243     if (vi != null) {
244             if (Report.should_report(TOPICS, 3))
245               Report.report(3, "find-var " + name + " -> " + vi);
246             return vi;
247     }
248
249         throw new SemanticException("Variable " + name + " not found.");
250     }
251
252     /**
253      * Gets a local or field of a particular name.
254      */

255     public VarInstance findVariableSilent(String JavaDoc name) {
256         if (Report.should_report(TOPICS, 3))
257           Report.report(3, "find-var " + name + " in " + this);
258
259         VarInstance vi = findVariableInThisScope(name);
260
261         if (vi != null) {
262             if (Report.should_report(TOPICS, 3))
263               Report.report(3, "find-var " + name + " -> " + vi);
264             return vi;
265         }
266
267         if (outer != null) {
268             return outer.findVariableSilent(name);
269         }
270
271         return null;
272     }
273
274     protected String JavaDoc mapsToString() {
275         return "types=" + types + " vars=" + vars;
276     }
277
278     public String JavaDoc toString() {
279         return "(" + kind + " " + mapsToString() + " " + outer + ")";
280     }
281
282     public Context pop() {
283         return outer;
284     }
285
286     /**
287      * Finds the definition of a particular type.
288      */

289     public Named find(String JavaDoc name) throws SemanticException {
290         if (Report.should_report(TOPICS, 3))
291           Report.report(3, "find-type " + name + " in " + this);
292
293         if (isOuter()) return outerResolver().find(name);
294         if (isSource()) return it.find(name);
295
296         Named type = findInThisScope(name);
297
298         if (type != null) {
299             if (Report.should_report(TOPICS, 3))
300               Report.report(3, "find " + name + " -> " + type);
301             return type;
302         }
303
304         if (outer != null) {
305             return outer.find(name);
306         }
307
308         throw new SemanticException("Type " + name + " not found.");
309     }
310
311     /**
312      * Push a source file scope.
313      */

314     public Context pushSource(ImportTable it) {
315         Context_c v = push();
316         v.kind = SOURCE;
317         v.it = it;
318         v.inCode = false;
319         v.staticContext = false;
320         return v;
321     }
322
323     /**
324      * Pushes on a class scoping.
325      * @param classScope The class whose scope is being entered. This is
326      * the object associated with the class declaration and is returned by
327      * currentClassScope. This is a mutable class type since for some
328      * passes (e.g., addMembers), the object returned by currentClassScope
329      * is modified.
330      * @param type The type to be returned by currentClass(). For JL, this
331      * type is the same as classScope. For other languages, it may differ
332      * since currentClassScope might not represent a type.
333      * @return A new context with a new scope and which maps the short name
334      * of type to type.
335      */

336     public Context pushClass(ParsedClassType classScope, ClassType type) {
337         if (Report.should_report(TOPICS, 4))
338           Report.report(4, "push class " + classScope + " " + classScope.position());
339         Context_c v = push();
340         v.kind = CLASS;
341         v.scope = classScope;
342         v.type = type;
343         v.inCode = false;
344         v.staticContext = false;
345
346         if (! type.isAnonymous()) {
347             v.addNamed(type);
348         }
349
350         return v;
351     }
352
353     /**
354      * pushes an additional block-scoping level.
355      */

356     public Context pushBlock() {
357         if (Report.should_report(TOPICS, 4))
358           Report.report(4, "push block");
359         Context_c v = push();
360         v.kind = BLOCK;
361         return v;
362     }
363
364     /**
365      * pushes an additional static scoping level.
366      */

367     public Context pushStatic() {
368         if (Report.should_report(TOPICS, 4))
369           Report.report(4, "push static");
370         Context_c v = push();
371         v.staticContext = true;
372         return v;
373     }
374
375     /**
376      * enters a method
377      */

378     public Context pushCode(CodeInstance ci) {
379         if (Report.should_report(TOPICS, 4))
380           Report.report(4, "push code " + ci + " " + ci.position());
381         Context_c v = push();
382         v.kind = CODE;
383         v.code = ci;
384         v.inCode = true;
385         v.staticContext = ci.flags().isStatic();
386         return v;
387     }
388
389     /**
390      * Gets the current method
391      */

392     public CodeInstance currentCode() {
393         return code;
394     }
395
396     /**
397      * Return true if in a method's scope and not in a local class within the
398      * innermost method.
399      */

400     public boolean inCode() {
401         return inCode;
402     }
403
404     
405     /**
406      * Returns whether the current context is a static context.
407      * A statement of expression occurs in a static context if and only if the
408      * inner-most method, constructor, instance initializer, static initializer,
409      * field initializer, or explicit constructor statement enclosing the
410      * statement or expressions is a static method, static initializer, the
411      * variable initializer of a static variable, or an explicity constructor
412      * invocation statment. (Java Language Spec, 2nd Edition, 8.1.2)
413      */

414     public boolean inStaticContext() {
415         return staticContext;
416     }
417
418     /**
419      * Gets current class
420      */

421     public ClassType currentClass() {
422         return type;
423     }
424
425     /**
426      * Gets current class
427      */

428     public ParsedClassType currentClassScope() {
429         return scope;
430     }
431
432     /**
433      * Adds a symbol to the current scoping level.
434      */

435     public void addVariable(VarInstance vi) {
436         if (Report.should_report(TOPICS, 3))
437           Report.report(3, "Adding " + vi + " to context.");
438         addVariableToThisScope(vi);
439     }
440
441     /**
442      * Adds a method to the current scoping level.
443      * Actually, this does nothing now.
444      * @deprecated
445      */

446     public void addMethod(MethodInstance mi) {
447         if (Report.should_report(TOPICS, 3))
448           Report.report(3, "Adding " + mi + " to context.");
449     }
450
451     /**
452      * Adds a named type object to the current scoping level.
453      */

454     public void addNamed(Named t) {
455         if (Report.should_report(TOPICS, 3))
456           Report.report(3, "Adding type " + t + " to context.");
457         addNamedToThisScope(t);
458     }
459
460     public Named findInThisScope(String JavaDoc name) {
461         Named t = null;
462         if (types != null) {
463             t = (Named) types.get(name);
464         }
465         if (t == null && isClass()) {
466             if (! this.type.isAnonymous() &&
467                 this.type.name().equals(name)) {
468                 return this.type;
469             }
470             else {
471                 try {
472                     return ts.findMemberClass(this.type, name, this.type);
473                 }
474                 catch (SemanticException e) {
475                 }
476             }
477         }
478         return t;
479     }
480
481     public void addNamedToThisScope(Named type) {
482         if (types == null) types = new HashMap JavaDoc();
483         types.put(type.name(), type);
484     }
485
486     public ClassType findMethodContainerInThisScope(String JavaDoc name) {
487         if (isClass() && ts.hasMethodNamed(this.currentClass(), name)) {
488             return this.type;
489         }
490         return null;
491     }
492
493     public VarInstance findVariableInThisScope(String JavaDoc name) {
494         VarInstance vi = null;
495         if (vars != null) {
496             vi = (VarInstance) vars.get(name);
497         }
498         if (vi == null && isClass()) {
499             try {
500                 return ts.findField(this.type, name, this.type);
501             }
502             catch (SemanticException e) {
503                 return null;
504             }
505         }
506         return vi;
507     }
508
509     public void addVariableToThisScope(VarInstance var) {
510         if (vars == null) vars = new HashMap JavaDoc();
511         vars.put(var.name(), var);
512     }
513
514     private static final Collection JavaDoc TOPICS =
515                 CollectionUtil.list(Report.types, Report.context);
516
517 }
518
Popular Tags