KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > ScopeExp


1 package gnu.expr;
2 import gnu.bytecode.*;
3
4 /**
5  * Abstract class for expressions that add local variable bindings.
6  * @author Per Bothner
7  */

8
9 public abstract class ScopeExp extends Expression
10 {
11   Declaration decls;
12   Declaration last;
13
14   private Scope scope;
15
16   public Declaration firstDecl () { return decls; }
17
18   public Scope getVarScope ()
19   {
20     Scope sc = scope;
21     if (sc == null)
22       scope = sc = new Scope();
23     return sc;
24   }
25
26   /** Clear bytecode resources for the ScopeExp.
27    * This potentially allows Kawa to generate code for the same (inlined,
28    * shared) ScopeExp multiple times - though we're not making use of that yet.
29    */

30   public void popScope (CodeAttr code)
31   {
32     for (Declaration decl = firstDecl(); decl != null; decl = decl.nextDecl())
33       decl.var = null;
34     code.popScope();
35     scope = null;
36   }
37
38   public void add (Declaration decl)
39   {
40     if (last == null)
41       decls = decl;
42     else
43       last.next = decl;
44     last = decl;
45     decl.context = this;
46   }
47
48   /** Add a Declaration at a specified position.
49    */

50   public void add (Declaration prev, Declaration decl)
51   {
52     if (prev == null)
53       { // Put first
54
decl.next = decls;
55         decls = decl;
56       }
57     else
58       {
59         decl.next = prev.next;
60         prev.next = decl;
61       }
62     if (last == prev)
63       last = decl;
64     decl.context = this;
65   }
66
67   /** Replace the <code>prev.next</code> by <code>newDecl</code>.
68    * If <code>prev==null</code>, replace the first decl. */

69   public void replaceFollowing (Declaration prev, Declaration newDecl)
70   {
71     Declaration oldDecl;
72     if (prev == null)
73       {
74     oldDecl = decls;
75     decls = newDecl;
76       }
77     else
78       {
79     oldDecl = prev.next;
80     prev.next = newDecl;
81       }
82     newDecl.next = oldDecl.next;
83     if (last == oldDecl)
84       last = newDecl;
85     oldDecl.next = null;
86     newDecl.context = this;
87   }
88
89   public void remove (Declaration decl)
90   {
91     Declaration prev = null;
92     for (Declaration cur = firstDecl(); cur != null; cur = cur.nextDecl())
93       {
94     if (cur == decl)
95       {
96         remove(prev, decl);
97         return;
98       }
99     prev = cur;
100       }
101   }
102
103   public void remove (Declaration prev, Declaration decl)
104   {
105     if (prev == null)
106       decls = decl.next;
107     else
108       prev.next = decl.next;
109     if (last == decl)
110       last = prev;
111   }
112
113   public ScopeExp () { }
114
115   /** The statically enclosing binding contour. */
116   public ScopeExp outer;
117
118   public LambdaExp currentLambda ()
119   {
120     ScopeExp exp = this;
121     for (;; exp = exp.outer)
122       {
123     if (exp == null)
124       return null;
125     if (exp instanceof LambdaExp)
126       return (LambdaExp) exp;
127       }
128   }
129
130   public ModuleExp currentModule ()
131   {
132     ScopeExp exp = this;
133     for (;; exp = exp.outer)
134       {
135     if (exp == null)
136       return null;
137     if (exp instanceof ModuleExp)
138       return (ModuleExp) exp;
139       }
140   }
141
142   /**
143    * Find a Declaration by name.
144    * @param sym the (interned) name of the Declaration sought
145    * @return the matching Declaration, if found; otherwise null
146    */

147   public Declaration lookup (Object JavaDoc sym)
148   {
149     if (sym != null)
150       {
151         for (Declaration decl = firstDecl();
152              decl != null; decl = decl.nextDecl())
153           {
154             if (sym.equals(decl.symbol))
155               return decl;
156           }
157       }
158     return null;
159   }
160
161   public Declaration lookup (Object JavaDoc sym, Language language, int namespace)
162   {
163     for (Declaration decl = firstDecl();
164          decl != null; decl = decl.nextDecl())
165       {
166     if (sym.equals(decl.symbol)
167         && language.hasNamespace(decl, namespace))
168       return decl;
169       }
170     return null;
171   }
172
173   /** Lookup a declaration, create a non-defining declaration if needed. */
174   public Declaration getNoDefine (Object JavaDoc name)
175   {
176     Declaration decl = lookup(name);
177     if (decl == null)
178       {
179     decl = addDeclaration(name);
180     decl.flags |= Declaration.NOT_DEFINING | Declaration.IS_UNKNOWN;
181       }
182     return decl;
183   }
184
185   /** Add a new Declaration, with a message if there is an existing one. */
186   public Declaration getDefine (Object JavaDoc name, char severity, Compilation parser)
187   {
188     Declaration decl = lookup(name);
189     if (decl == null)
190       decl = addDeclaration(name);
191     else if ((decl.flags & (Declaration.NOT_DEFINING | Declaration.IS_UNKNOWN))
192          != 0)
193       decl.flags &= ~ (Declaration.NOT_DEFINING|Declaration.IS_UNKNOWN);
194     else
195       {
196     Declaration newDecl = addDeclaration(name);
197         duplicateDeclarationError(decl, newDecl, parser);
198         decl = newDecl;
199       }
200     return decl;
201   }
202
203   public static void duplicateDeclarationError (Declaration oldDecl,
204                                                 Declaration newDecl,
205                                                 Compilation comp)
206   {
207     comp.error('e', newDecl, "duplicate declaration of '", "'");
208     comp.error('e', oldDecl, "(this is the previous declaration of '", "')");
209   }
210
211   /**
212    * Create a new declaration in the current Scope.
213    * @param name name (interned) to give to the new Declaration.
214    */

215   public final Declaration addDeclaration (Object JavaDoc name)
216   {
217     Declaration decl = new Declaration (name);
218     add(decl);
219     return decl;
220   }
221
222   /**
223    * Create a new declaration in the current Scope.
224    * @param name name (interned) to give to the new Declaration.
225    * @param type type of the new Declaration.
226    */

227   public final Declaration addDeclaration (Object JavaDoc name, Type type)
228   {
229     Declaration decl = new Declaration (name, type);
230     add(decl);
231     return decl;
232   }
233
234   /**
235    * Add a Declaration to the current Scope.
236    */

237   public final void addDeclaration (Declaration decl)
238   {
239     add(decl); // FIXME just use add
240
}
241
242   public int countDecls ()
243   {
244     int n = 0;
245     for (Declaration decl = firstDecl(); decl != null; decl = decl.nextDecl())
246       n++;
247     return n;
248   }
249
250   public static int nesting (ScopeExp sc)
251   {
252     int n = 0;
253     while (sc != null)
254       {
255     sc = sc.outer;
256     n++;
257       }
258     return n;
259   }
260
261   /** Size of evalFrame to allocate in interpreter. */
262   protected int frameSize;
263
264   /** Calculate offset and frameSize needed by interpreter. */
265   protected void setIndexes ()
266   {
267     int i = 0;
268     for (Declaration decl = firstDecl(); decl != null; decl = decl.nextDecl())
269       {
270         decl.evalIndex = i++;
271       }
272     frameSize = i;
273   }
274
275   protected Expression walk (ExpWalker walker)
276   {
277     return walker.walkScopeExp(this);
278   }
279
280   public String JavaDoc toString() { return getClass().getName()+"#"+id; }
281
282   static int counter;
283   /** Unique id number, to ease print-outs and debugging. */
284   public int id = ++counter;
285 }
286
Popular Tags