1 4 package gnu.mapping; 5 import java.io.*; 6 7 10 11 public class SimpleEnvironment extends Environment 12 { 13 NamedLocation[] table; 14 int log2Size; 15 private int mask; 16 17 int num_bindings; 18 int currentTimestamp; 19 20 21 public int size () { return num_bindings; } 22 23 public static Location getCurrentLocation (String name) 24 { 25 return getCurrent().getLocation(name, true); 26 } 27 28 public static Object 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 38 NamedLocation sharedTail; 39 40 public SimpleEnvironment () 41 { 42 this(64); 43 } 44 45 public SimpleEnvironment (String 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 property, int hash) 64 { 65 return lookupDirect(name, property, hash); 66 } 67 68 public NamedLocation lookupDirect (Symbol name, Object 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 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 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 property, Object 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 ("attempt to modify read-only location: " 109 + key + " in "+this+" loc:"+loc); 110 loc.set(newValue); 111 } 112 113 NamedLocation newLocation (Symbol name, Object 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 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 property, int hash, 135 Object 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 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 property, Object 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 property, Location loc) 168 { 169 throw new IllegalStateException ("prohibited define/redefine of " 170 +name+" in "+this); 171 } 172 173 public NamedLocation addLocation (Symbol name, Object property, Location loc) 174 { 175 return addLocation(name, property, 176 name.hashCode() ^ System.identityHashCode(property), loc); 177 } 178 179 NamedLocation addLocation (Symbol name, Object 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 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 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 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 267 public LocationEnumeration enumerateLocations() 268 { 269 LocationEnumeration it = new LocationEnumeration(table, 1 << log2Size); 270 it.env = this; 271 return it; 272 } 273 274 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 307 { 308 setSymbol(in.readObject()); 309 } 310 311 public Object readResolve() throws ObjectStreamException 312 { 313 String 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 323 public java.util.Set entrySet () 324 { 325 return new EnvironmentMappings(this); 326 } 327 328 329 public String toStringVerbose () 330 { 331 StringBuffer sbuf = new StringBuffer (); 332 toStringBase(sbuf); 333 return "#<environment "+getName()+" num:"+num_bindings 334 +" ts:"+currentTimestamp+sbuf+'>'; 335 } 336 337 protected void toStringBase (StringBuffer sbuf) { ; } 338 } 339 340 341 class EnvironmentMappings 342 extends java.util.AbstractSet 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 iterator () 351 { 352 return new LocationEnumeration(env); 353 } 354 } 355 356 | Popular Tags |