Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/csharp/llk/ast/ScopeStack.java


1   //
2   // Copyright(c) 2002, Chris Leung
3   //
4   
5   package com.port80.eclipse.csharp.llk.ast;
6   
7   import java.util.ArrayList;
8   import java.util.List;
9   import java.util.Set;
10  
11  import com.port80.eclipse.csharp.llk.parser.ASTCompilationUnit;
12  import com.port80.eclipse.csharp.llk.parser.ASTRootContext;
13  import com.port80.eclipse.csharp.llk.parser.ILLKMain;
14  
15  /** 
16   * Scope stack is used by the parser to keep track of the current
17   *  lexical scopes and performs symbol lookups.
18   *
19   *  . Scope stack from bottom to top:
20   *  RootContext scope
21   *  CompilationUnit scope
22   *  TopLevelClass scope
23   *  class/block/method...etc. scopes
24   *  ...
25   *
26   *  . When a variable is encountered in the statement, its type is
27   *    determined by searching the scopes from the top of the scope stack
28   *    downwards until it found the variable declaration/definition.  If
29   *    a scope belongs to an IType (parent!=null), IType would
30   *    search the super-class and/or super-interfaces.
31   */
32  public class ScopeStack implements IScopeStack {
33  
34    ////////////////////////////////////////////////////////////////////////
35  
36    private static final String NAME="ScopeStack";
37    private static final boolean DEBUG = false;
38  
39    ////////////////////////////////////////////////////////////////////////
40  
41    protected ILLKMain main;
42    protected ILLKScope top = null; /** Current top of stack object. */
43    protected int classLevel = 0; /** Number of IType on stack. */
44    protected List stack = new ArrayList();
45  
46    // Constructors ////////////////////////////////////////////////////////
47    //
48  
49    public ScopeStack(ILLKMain main) {
50      this.main = main;
51    }
52  
53    // Stack interface /////////////////////////////////////////////////////
54    //
55    public void push(Object o) {
56      if (o == null)
57        main.error("o==null");
58      if (!(o instanceof ILLKScope))
59        main.error(NAME+".push(): Expected o instanceof IScope: " + o);
60      if (o instanceof Type)
61        classLevel++;
62      if (size() == 0 && !(o instanceof ASTRootContext))
63        main.error(NAME+".push(): Expected RootContext:" + o);
64      if (size() == 1 && !(o instanceof ASTCompilationUnit))
65        main.error(NAME+".push(): Expected ASTCompilationUnit:" + o);
66      stack.add(o);
67      top = (ILLKScope) o;
68    }
69  
70    public ILLKScope pop() {
71      ILLKScope ret = top;
72      if (ret == null)
73        main.error("ASSERT: top != null");
74      if (ret instanceof Type) {
75        if (--classLevel < 0)
76          main.error("classLevel >= 0: " + classLevel + ": " + ret);
77      }
78      stack.remove(stack.size() - 1);
79      if (size() == 0)
80        top = null;
81      else
82        top = (ILLKScope) stack.get(stack.size() - 1);
83      return ret;
84    }
85  
86    public boolean empty() {
87      return size() == 0;
88    }
89  
90    public ILLKScope peek() {
91      return top;
92    }
93  
94    public int size() {
95      return stack.size();
96    }
97  
98    public ILLKScope get(int i) {
99      return (ILLKScope) stack.get(i);
100   }
101 
102   ////////////////////////////////////////////////////////////////////////
103   //
104 
105   public ASTRootContext getRootContext() {
106     return (ASTRootContext) get(0);
107   }
108 
109   public ASTCompilationUnit getCompilationUnit() {
110     return (ASTCompilationUnit) get(1);
111   }
112 
113   public boolean isClassScope() {
114     return (top != null && top instanceof Type);
115   }
116 
117   public int getClassLevel() {
118     return classLevel;
119   }
120 
121   public Type getCurrentClass() {
122     for (int i = stack.size() - 1; i >= 0; i--) {
123       Object o = stack.get(i);
124       if (o instanceof Type)
125         return (Type) o;
126     }
127     return null;
128   }
129 
130   public Type getTopLevelClass() {
131     for (int i = 0; i < stack.size(); i++) {
132       Object o = stack.get(i);
133       if (o instanceof Type)
134         return (Type) o;
135     }
136     return null;
137   }
138 
139   //////////////////// IScope interface ////////////////////
140 
141   public String getName() {
142     return top.getName();
143   }
144 
145   public Set keySet() {
146     return top.keySet();
147   }
148 
149   public ISymbol putSymbol(ISymbol sym) {
150     return top.putSymbol(sym);
151   }
152 
153   public ISymbol putType(String key, ISymbol sym) {
154     return top.putType(key, sym);
155   }
156 
157   public ISymbol putVar(String key, ISymbol sym) {
158     return top.putVar(key, sym);
159   }
160 
161   public ISymbol putMethod(String key, ISymbol sym) {
162     return top.putMethod(key, sym);
163   }
164 
165   public void putSymbolList(List aList) {
166     top.putSymbolList(aList);
167   }
168 
169   public ISymbol getVar(String varname) {
170     ILLKScope scope;
171     ISymbol ret;
172     for (int i = stack.size() - 1; i >= 0; i--) {
173       scope = (ILLKScope) stack.get(i);
174       ret = scope.getVar(varname);
175       if (ret != null) {
176         if (DEBUG)
177           System.err.println("ScopeStackBase.getVarSymbol(" + varname + ")=" + ret);
178         return ret;
179       }
180     }
181     if (DEBUG)
182       System.err.println("ScopeStackBase.getVarSymbol(" + varname + ") not found.");
183     return null;
184   }
185 
186   public ISymbol getMethod(String sig) {
187     ILLKScope scope;
188     ISymbol ret;
189     for (int i = stack.size() - 1; i >= 0; i--) {
190       scope = (ILLKScope) stack.get(i);
191       ret = scope.getMethod(sig);
192       if (ret != null) {
193         if (DEBUG)
194           System.err.println("ScopeStackBase.getMethodSymbol(" + sig + ")=" + ret);
195         return ret;
196       }
197     }
198     if (DEBUG)
199       System.err.println("ScopeStackBase.getMethodSymbol(" + sig + ") not found.");
200     return null;
201   }
202 
203   /** 
204    * Lookup a type symbol.
205    *
206    *  . Accept both simple type name and qualified type name.  To lookup a qualified
207    *    type name, the first prefix in the qualified name is lookup as a simple name.
208    *    Follow suffices are then lookup its prefix's scope.  If the first prefix is
209    *    not found, try again with the second prefix is concatenated to the first.
210    *    If none of the prefix are found, return error (null).
211    *
212    *  . Looking up a simple type name is rather complicated because it involve search
213    *    through the scope stack, the package and the import list.
214    *
215    *  . If a class symbol is not declared in this compilation unit, search 
216    *    the oneTypeImportList, then the package scope, then onDemandImportList
217    *
218    *  @param typename A simple name, qualified name or canonical name.
219    *  @return The type object of the symbol. 
220    */
221   public ISymbol getType(String typename) {
222     ISymbol ret;
223     int index;
224     //    index = typename.indexOf("[L");
225     //    if (index >= 0) {
226     //      // Try load the member type of an array first.
227     //      if (typename.startsWith("[L"))
228     //        typename = typename.substring(2);
229     //      else
230     //        typename = typename.substring(1);
231     //      ret = getTypeSymbol(typename);
232     //      if (ret == null) {
233     //        Msg.warn("ScopeStackBase.getSymbol(): member class of array not found: " + typename);
234     //        return null;
235     //      }
236     //      typename = ((IType) ret).getCanonicalName();
237     //      if (typename.startsWith("["))
238     //        typename = "[" + typename;
239     //      else
240     //        typename = "[L" + typename;
241     //      ISymbol sym = getSimpleTypeSymbol(typename);
242     //      if (sym != null)
243     //        return sym;
244     //      // Create array type from membertype.
245     //      ret = IType.newArrayInstance((IType) ret);
246     //      getCompilationUnit().putTypeSymbol(((IType) ret).getCanonicalName(), ret);
247     //      return ret;
248     //    }
249     //
250     index = typename.indexOf('.');
251     if (index < 0) {
252       // Lookup as simple name.
253       ret = (ISymbol) getSimpleType(typename);
254       if (ret != null)
255         return ret;
256     } else {
257       // Lookup as qualified name.
258       ILLKScope type = null;
259       String enclose = null;
260       String classname = typename;
261       while ((index = classname.indexOf('.')) >= 0) {
262         if (enclose == null)
263           enclose = classname.substring(0, index);
264         else
265           enclose += "." + classname.substring(0, index);
266         classname = classname.substring(index + 1);
267         if (DEBUG)
268           System.err.println(
269             "ScopeStackBase.getTypeSymbol(): enclose="
270               + enclose
271               + ", classname="
272               + classname);
273         if (!(enclose.length() != 0 && classname.length() != 0))
274           main.error("ASSERT: enclose.length() != 0 && classname.length() != 0");
275         if (type == null) {
276           type = (ILLKScope) getSimpleType(enclose);
277           if (type == null)
278             type = (ILLKScope) importType(enclose);
279           if (type == null)
280             return null;
281         } else {
282           type = (ILLKScope) type.getType(enclose);
283           if (type == null)
284             return null;
285         }
286       }
287       ret = type.getType(classname);
288     }
289     return ret;
290   }
291 
292   public void dumpScope(String indent) {
293     for (int i = 0; i < stack.size(); i++) {
294       ILLKScope sc = (ILLKScope) stack.get(i);
295       sc.dumpScope(indent);
296     }
297   }
298 
299   ////////////////////////////////////////////////////////////////////////
300 
301   public ISymbol getSimpleType(String typename) {
302     ISymbol ret = ASTRootContext.getPrimitiveType(typename);
303     if (ret != null)
304       return ret;
305     for (int i = stack.size() - 1; i >= 0; i--) {
306       ILLKScope scope = (ILLKScope) stack.get(i);
307       ret = scope.getType(typename);
308       if (ret != null) {
309         if (DEBUG)
310           System.err.println(
311             "ScopeStackBase.getSimpleTypeSymbol(" + typename + ")=" + ret);
312         return ret;
313       }
314     }
315     return null;
316   }
317 
318   public ISymbol importType(String typename) {
319     //    ISymbol ret;
320     //    String prefix;
321     //    String tname;
322     //    while (true) {
323     //      List oneTypeImport = getCompilationUnit().getOneTypeImport();
324     //      List oneTypeSimple = getCompilationUnit().getOneTypeSimple();
325     //      for (int i = 0; i < oneTypeImport.size(); i++) {
326     //        tname = (String) oneTypeSimple.get(i);
327     //        if (typename.equals(tname)) {
328     //          tname = (String) oneTypeImport.get(i);
329     //          return (ISymbol) findClass(tname);
330     //        }
331     //      }
332     //      // Look in package.
333     //      String packagename = getCompilationUnit().getPackageName();
334     //      prefix = (packagename == null) ? typename : packagename + "." + typename;
335     //      ret = (ISymbol) findClass(prefix);
336     //      if (ret != null)
337     //        break;
338     //      // Lookup as fully qualified name.
339     //      ret = (ISymbol) findClass(typename);
340     //      if (ret != null)
341     //        break;
342     //      // Look in onDemandImportList
343     //      List onDemandImportList = getCompilationUnit().getOnDemandImport();
344     //      for (int i = 0;(ret == null) && (i < onDemandImportList.size()); i++) {
345     //        prefix = (String) onDemandImportList.get(i);
346     //        ret = (ISymbol) findClass(prefix + "." + typename);
347     //        if (ret != null)
348     //          break;
349     //      }
350     //      if (ret != null)
351     //        break;
352     //      // Look in java.lang
353     //      ret = findClass("java.lang." + typename);
354     //      break;
355     //    }
356     //    //
357     //    // Class found, make an IType, import symbols and put it into the symbol table.
358     //    //
359     //    // To avoid search for the full class path again, cache the short class name in 
360     //    // the compilation unit scope.
361     //    if (DEBUG)
362     //      System.err.println("ScopeStackBase.importType(" + typename + ")=" + ret);
363     //    return ret;
364     return null;
365   }
366 
367   // Import class methods ////////////////////////////////////////////////
368 
369   /** 
370    * Find a class with specified canonical name in this compilation unit.
371    * Load one from the system if not found.
372    */
373   public Type findClass(String canonical_name) {
374     //    Msg.trace("findClass(String): " + canonical_name);
375     //    if (canonical_name.indexOf("[L") >= 0)
376     //      main.error("findClass(String): canonicalname.indexOf(\"[L\")>=0");
377     //    ISymbol sym = getCompilationUnit().getTypeSymbol(canonical_name);
378     //    if (sym != null)
379     //      return (IType) sym;
380     //    sym = getRootContext().getTypeSymbol(canonical_name);
381     //    if (sym != null)
382     //      return (IType) sym;
383     //    //
384     //    //    try {
385     //    //      Class c = Class.forName(canonicalname);
386     //    //      return loadClass(c);
387     //    //    } catch (ClassNotFoundException e) {
388     //    //      main.error("findClass(String): class not found: " + canonicalname);
389     //    //    } catch (Exception e) {
390     //    //      main.error("findClass(String): class name=" + canonicalname, e);
391     //    //    }
392     return null;
393   }
394 
395   /** Find the class definition (IType) for a Class.  Create one if
396    *  not yet exist.
397    */
398   public Type findClass(Class c) {
399     //    String canonicalname = X.cleanClassname(c.getName());
400     //    Msg.trace("findClass(Class): " + canonicalname);
401     //    ISymbol sym = getCompilationUnit().getTypeSymbol(canonicalname);
402     //    if (sym != null)
403     //      return (IType) sym;
404     //    sym = getRootContext().getTypeSymbol(canonicalname);
405     //    if (sym != null)
406     //      return (IType) sym;
407     //    return loadClass(c);
408     return null;
409   }
410 
411   public Type loadClass(Class c) {
412     //    String canonicalname = X.cleanClassname(c.getName());
413     //    Msg.trace("loadClass(Class): " + canonicalname);
414     //    // FIXME: we may need to load array classes here.
415     //    IType ret = TypeFactory.newInstance(c, this);
416     //    // Load the nested classes.
417     //    Msg.trace("loadClass(Class): ret=" + ret);
418     //    getCompilationUnit().putTypeSymbol(ret.getCanonicalName(), (ISymbol) ret);
419     //    Class[] cs = c.getDeclaredClasses();
420     //    for (int i = 0; i < cs.length; i++) {
421     //      IType nest = IType.newInstance(cs[i], this);
422     //      ret.putTypeSymbol(nest.getSimpleName(), (ISymbol) nest);
423     //      getCompilationUnit().putTypeSymbol(nest.getCanonicalName(), (ISymbol) nest);
424     //      Msg.trace("loadClass(Class): nested=" + nest);
425     //    }
426     //    return ret;
427     return null;
428   }
429 
430   public Type loadClass(String name) {
431     return null;
432   }
433 
434   ////////////////////////////////////////////////////////////////////////
435 
436   //  /** Convert from class[][] to [[Lclass format. */
437   //  private String toJavaArrayTypeName(String arraytypename) {
438   //    int index;
439   //    String classname = arraytypename;
440   //    int dim = 0;
441   //    while ((index = classname.lastIndexOf('[')) >= 0) {
442   //      classname = classname.substring(index + 1);
443   //      dim++;
444   //    }
445   //    if (dim != 0) {
446   //      classname = "L" + classname;
447   //      for (int i = 0; i < dim; i++) {
448   //        classname = "[" + classname;
449   //      }
450   //    }
451   //    return classname;
452   //  }
453 
454   ////////////////////////////////////////////////////////////////////////
455 }