class AttributeCache { private java.util.Map cache; public boolean has(java.lang.Object o) { return cache != null && cache.containsKey(o); } public java.lang.Object get(java.lang.Object o) { return cache.get(o).getValue(); } public void put(ASTNode home, java.lang.Object o, java.lang.Object val) { if(cache == null) { cache = new java.util.HashMap(); cache.put(o, new CachedValue(home, val)); } else { CachedValue v = cache.get(o); if(v == null) cache.put(o, new CachedValue(home, val)); else v.setValue(home, val); } } public void addDependent(java.lang.Object o, Caching.CacheRoot root) { cache.get(o).addDependent(root); } public int last_computed(java.lang.Object args) { if(cache == null) return -1; CachedValue v = cache.get(args); return v == null ? -1 : v.last_computed(); } public java.lang.Object[] getKeys() { if(cache == null) return new java.lang.Object[0]; return cache.keySet().toArray(); } public boolean hasExternalDependents(Object o, ASTNode home) { return cache.get(o).hasExternalDependents(home); } } class FinalAttributeCache extends AttributeCache { public void put(ASTNode home, java.lang.Object o, java.lang.Object val) { if(has(o)) throw new RuntimeException("trying to overwrite value of final attribute"); super.put(home, o, val); } public void addDependent(java.lang.Object o, Caching.CacheRoot root) { throw new RuntimeException("final attributes cannot have dependents"); } public boolean hasExternalDependents(Object o, ASTNode home) { return false; } }