KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mapping > SimpleEnvironment


1 // Copyright (c) 1996-2000, 2001, 2002, 2004 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.mapping;
5 import java.io.*;
6
7 /** Concrete implementation of <code>Environment</code>.
8  * (Should consider merging this code with Table2D.)
9  */

10
11 public class SimpleEnvironment extends Environment
12 {
13   NamedLocation[] table;
14   int log2Size;
15   private int mask;
16   /** Doesn't count inherited bindings. */
17   int num_bindings;
18   int currentTimestamp;
19
20   /** Size does not include inherited Locations. */
21   public int size () { return num_bindings; }
22
23   public static Location getCurrentLocation (String JavaDoc name)
24   {
25     return getCurrent().getLocation(name, true);
26   }
27
28   public static Object JavaDoc lookup_global (Symbol name)
29        throws UnboundLocationException
30   {
31     Location binding = getCurrent().lookup(name);
32     if (binding == null)
33       throw new UnboundLocationException(name);
34     return binding.get();
35   }
36
37   /** A special "end-of-list" value added for the sake of getEnvironment. */
38   NamedLocation sharedTail;
39
40   public SimpleEnvironment ()
41   {
42     this(64);
43   }
44
45   public SimpleEnvironment (String JavaDoc name)
46   {
47     this();
48     setName(name);
49   }
50
51   public SimpleEnvironment (int capacity)
52   {
53     log2Size = 4;
54     while (capacity > (1 << log2Size))
55       log2Size++;
56     capacity = 1 << log2Size;
57     table = new NamedLocation[capacity];
58     mask = capacity - 1;
59
60     sharedTail = new PlainLocation(null, null, this);
61   }
62
63   public NamedLocation lookup (Symbol name, Object JavaDoc property, int hash)
64   {
65     return lookupDirect(name, property, hash);
66   }
67
68   public NamedLocation lookupDirect (Symbol name, Object JavaDoc property, int hash)
69   {
70     int index = hash & this.mask;
71     for (NamedLocation loc = table[index];
72      loc != null; loc = loc.next)
73       {
74     if (loc.matches(name, property))
75       return loc;
76       }
77     return null;
78   }
79
80   public synchronized NamedLocation
81   getLocation (Symbol name, Object JavaDoc property, int hash, boolean create)
82   {
83     NamedLocation loc = lookup(name, property, hash);
84     if (loc != null)
85       return loc;
86     if (! create)
87       return null;
88     return addUnboundLocation(name, property, hash);
89   }
90
91   protected NamedLocation addUnboundLocation(Symbol name, Object JavaDoc property,
92                          int hash)
93   {
94     int index = hash & mask;
95     NamedLocation loc = newEntry(name, property, index);
96     loc.base = null;
97     loc.value = Location.UNBOUND;
98     return loc;
99   }
100
101   public void put(Symbol key, Object JavaDoc property, Object JavaDoc newValue)
102   {
103     boolean create = (flags & CAN_IMPLICITLY_DEFINE) != 0;
104     Location loc = getLocation(key, property, create);
105     if (loc == null)
106       throw new UnboundLocationException(key);
107     else if (loc.isConstant())
108       throw new IllegalStateException JavaDoc("attempt to modify read-only location: "
109                       + key + " in "+this+" loc:"+loc);
110     loc.set(newValue);
111   }
112
113   // Rename to newEntry? FIXME
114
NamedLocation newLocation (Symbol name, Object JavaDoc property)
115   {
116     if ((flags & THREAD_SAFE) != 0)
117       return new SharedLocation(name, property, currentTimestamp);
118     else
119       return new PlainLocation(name, property);
120   }
121
122   NamedLocation newEntry (Symbol name, Object JavaDoc property, int index)
123   {
124     NamedLocation loc = newLocation(name, property);
125     NamedLocation first = table[index];
126     loc.next = first == null ? sharedTail : first;
127     table[index] = loc;
128     num_bindings++;
129     if (num_bindings >= table.length)
130       rehash();
131     return loc;
132   }
133
134   public NamedLocation define (Symbol sym, Object JavaDoc property, int hash,
135                    Object JavaDoc newValue)
136   {
137     int index = hash & mask;
138     NamedLocation first = table[index];
139     NamedLocation loc = first;
140     for (;;)
141       {
142     if (loc == null)
143       {
144         // FIXME increment numBindings?
145
loc = newEntry(sym, property, index);
146         loc.set(newValue);
147         return loc;
148       }
149     else if (loc.matches(sym, property))
150       {
151         if (! (loc.isBound() ? getCanDefine() : getCanRedefine()))
152           redefineError(sym, property, loc);
153         loc.base = null;
154         loc.value = newValue;
155         return loc;
156       }
157     loc = loc.next;
158       }
159   }
160
161   public void define (Symbol sym, Object JavaDoc property, Object JavaDoc newValue)
162   {
163     int hash = sym.hashCode() ^ System.identityHashCode(property);
164     define(sym, property, hash, newValue);
165   }
166
167   protected void redefineError (Symbol name, Object JavaDoc property, Location loc)
168   {
169     throw new IllegalStateException JavaDoc("prohibited define/redefine of "
170                                     +name+" in "+this);
171   }
172
173   public NamedLocation addLocation (Symbol name, Object JavaDoc property, Location loc)
174   {
175     return addLocation(name, property,
176                name.hashCode() ^ System.identityHashCode(property), loc);
177   }
178
179   // FIXME rename to define
180
NamedLocation addLocation (Symbol name, Object JavaDoc property, int hash, Location loc)
181   {
182     if (loc instanceof ThreadLocation
183         && ((ThreadLocation) loc).property == property)
184       loc = ((ThreadLocation) loc).getLocation();
185     NamedLocation nloc = lookupDirect(name, property, hash);
186     if (loc == nloc)
187       return nloc;
188     boolean bound = (nloc != null);
189     if (! bound)
190       nloc = addUnboundLocation(name, property, hash);
191     if ((flags & CAN_DEFINE+CAN_REDEFINE) != CAN_DEFINE+CAN_REDEFINE)
192       {
193     if (bound)
194       bound = nloc.isBound();
195     // We do this redundant testing to avoid invoking isBound,
196
// which may be expensive and/or cause needless errors, such in the
197
// case of a lazy ClassMemberLocation referring to a missing class.
198
if (bound
199         ? ((flags & CAN_REDEFINE) == 0)
200         : ((flags & CAN_DEFINE) == 0) && loc.isBound());
201       redefineError(name, property, nloc);
202       }
203     if ((flags & Environment.INDIRECT_DEFINES) != 0)
204       nloc.base = ((SimpleEnvironment) ((InheritingEnvironment) this).getParent(0)).addLocation(name, property, hash, loc);
205     else
206       nloc.base = loc;
207     nloc.value = IndirectableLocation.INDIRECT_FLUIDS;
208     return nloc;
209   }
210
211   void rehash ()
212   {
213     NamedLocation[] oldTable = table;
214     int oldCapacity = oldTable.length;
215     int newCapacity = 2 * oldCapacity;
216     NamedLocation[] newTable = new NamedLocation[newCapacity];
217     int newMask = newCapacity - 1;
218     for (int i = oldCapacity; --i >= 0;)
219       {
220     for (NamedLocation element = oldTable[i];
221          element != null && element != sharedTail; )
222       {
223         NamedLocation next = element.next;
224         Symbol name = element.name;
225         Object JavaDoc property = element.property;
226         int hash = name.hashCode() ^ System.identityHashCode(property);
227         int j = hash & newMask;
228         NamedLocation head = newTable[j];
229         if (head == null)
230           head = sharedTail;
231         element.next = head;
232         newTable[j] = element;
233         element = next;
234       }
235       }
236     table = newTable;
237     log2Size++;
238     mask = newMask;
239   }
240
241   public Location unlink (Symbol symbol, Object JavaDoc property, int hash)
242   {
243     int index = hash & this.mask;
244     NamedLocation prev = null;
245     NamedLocation loc = table[index];
246     while (loc != null)
247       {
248     NamedLocation next = loc.next;
249     if (loc.matches(symbol, property))
250       {
251             if (! getCanRedefine())
252               redefineError(symbol, property, loc);
253         if (prev == null)
254           table[index] = next;
255         else
256           prev.next = loc;
257         num_bindings--;
258         return loc;
259       }
260     prev = loc;
261     loc = next;
262       }
263     return null;
264   }
265
266   /** Does not enumerate inherited Locations. */
267   public LocationEnumeration enumerateLocations()
268   {
269     LocationEnumeration it = new LocationEnumeration(table, 1 << log2Size);
270     it.env = this;
271     return it;
272   }
273
274   /** Does enumerate inherited Locations. */
275   public LocationEnumeration enumerateAllLocations()
276   {
277     return enumerateLocations();
278   }
279
280   protected boolean hasMoreElements (LocationEnumeration it)
281   {
282     for (;;)
283       {
284     if (it.curLoc == null)
285       {
286         if (--it.index < 0)
287           return false;
288         it.curLoc = it.bindings[it.index];
289         if (it.curLoc == null)
290           continue;
291       }
292     if (it.curLoc.name == null)
293       it.curLoc = it.curLoc.next;
294     else
295       break;
296       }
297     return true;
298   }
299
300   public void writeExternal(ObjectOutput out) throws IOException
301   {
302     out.writeObject(getSymbol());
303   }
304
305   public void readExternal(ObjectInput in)
306     throws IOException, ClassNotFoundException JavaDoc
307   {
308     setSymbol(in.readObject());
309   }
310
311   public Object JavaDoc readResolve() throws ObjectStreamException
312   {
313     String JavaDoc name = getName();
314     Environment env = (Environment) envTable.get(name);
315     if (env != null)
316       return env;
317     envTable.put(name, this);
318     return this;
319    
320   }
321
322   /* #ifdef JAVA2 */
323   public java.util.Set JavaDoc entrySet ()
324   {
325     return new EnvironmentMappings(this);
326   }
327   /* #endif */
328
329   public String JavaDoc toStringVerbose ()
330   {
331     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
332     toStringBase(sbuf);
333     return "#<environment "+getName()+" num:"+num_bindings
334       +" ts:"+currentTimestamp+sbuf+'>';
335   }
336
337   protected void toStringBase (StringBuffer JavaDoc sbuf) { ; }
338 }
339
340 /* #ifdef JAVA2 */
341 class EnvironmentMappings
342   extends java.util.AbstractSet JavaDoc /* <Location> */
343 {
344   SimpleEnvironment env;
345
346   public EnvironmentMappings (SimpleEnvironment env) { this.env = env; }
347
348   public int size() { return env.size(); }
349
350   public java.util.Iterator JavaDoc iterator ()
351   {
352     return new LocationEnumeration(env);
353   }
354 }
355 /* #endif */
356
Popular Tags