001: package sisc.env;
002:
003: import java.io.*;
004: import sisc.data.*;
005: import java.util.Map;
006: import java.util.HashMap;
007: import java.util.Iterator;
008:
009: import sisc.io.ValueWriter;
010: import sisc.ser.Serializer;
011: import sisc.ser.Deserializer;
012: import sisc.util.ExpressionVisitor;
013:
014: public class MemorySymEnv extends Value implements SymbolicEnvironment,
015: NamedValue {
016:
017: protected static final float EXPFACT = 1.5F;
018: public Map symbolMap, sidecars;
019: public Value[] env;
020: public SymbolicEnvironment parent;
021: protected int nextFree;
022:
023: public MemorySymEnv(SymbolicEnvironment parent) {
024: this ();
025: this .parent = parent;
026: }
027:
028: public MemorySymEnv(SymbolicEnvironment parent, Symbol name) {
029: this (name);
030: this .parent = parent;
031: }
032:
033: public MemorySymEnv(Symbol name) {
034: this ();
035: setName(name);
036: }
037:
038: public MemorySymEnv() {
039: env = new Value[1];
040: nextFree = 0;
041: symbolMap = new HashMap(1);
042: sidecars = new HashMap(1);
043: }
044:
045: public Value asValue() {
046: return this ;
047: }
048:
049: //The following two methods are for internal use only, despite
050: //their public modifiers
051:
052: public SymbolicEnvironment getSidecarEnvironment(Symbol name) {
053: synchronized (sidecars) {
054: SymbolicEnvironment sc = (SymbolicEnvironment) sidecars
055: .get(name);
056: if (sc == null) {
057: SymbolicEnvironment mp = getParent();
058: SymbolicEnvironment p = (mp == null ? (SymbolicEnvironment) null
059: : mp.getSidecarEnvironment(name));
060: sidecars.put(name, sc = new MemorySymEnv(p));
061: }
062: return sc;
063: }
064: }
065:
066: public void setParent(SymbolicEnvironment e) {
067: parent = e;
068: for (Iterator i = sidecars.keySet().iterator(); i.hasNext();) {
069: Symbol key = (Symbol) i.next();
070: SymbolicEnvironment env = (SymbolicEnvironment) sidecars
071: .get(key);
072: env.setParent(parent.getSidecarEnvironment(key));
073: }
074: }
075:
076: public SymbolicEnvironment getParent() {
077: return parent;
078: }
079:
080: protected void expand() {
081: synchronized (symbolMap) {
082: Value[] newenv = new Value[(int) ((env.length * EXPFACT) + 1)];
083: System.arraycopy(env, 0, newenv, 0, env.length);
084: nextFree = env.length;
085: env = newenv;
086: }
087: }
088:
089: public void trim() {
090: synchronized (symbolMap) {
091: Value[] newenv = new Value[nextFree];
092: System.arraycopy(env, 0, newenv, 0, nextFree);
093: env = newenv;
094: }
095: }
096:
097: public void set(int envLoc, Value v) {
098: env[envLoc] = v;
099: }
100:
101: public int define(Symbol s, Value v) {
102: synchronized (symbolMap) {
103: int envLoc = getLoc(s);
104: if (envLoc == -1)
105: return store(s, v);
106: else {
107: set(envLoc, v);
108: return envLoc;
109: }
110: }
111: }
112:
113: protected int store(Symbol s, Value v) {
114: synchronized (symbolMap) {
115: if (nextFree >= env.length)
116: expand();
117:
118: //NB: the order of the following two statements is important;
119: //otherwise a lookup taking place concurrently might get garbage
120: env[nextFree] = v;
121: symbolMap.put(s, new Integer(nextFree));
122: return nextFree++;
123: }
124: }
125:
126: public int getLoc(Symbol s) {
127: synchronized (symbolMap) {
128: Integer i = (Integer) symbolMap.get(s);
129: if (i != null)
130: return i.intValue();
131: SymbolicEnvironment p = getParent();
132: if (p == null)
133: return -1;
134: Value v = p.lookup(s);
135: if (v == null)
136: return -1;
137: return store(s, v);
138: }
139: }
140:
141: public Value lookup(Symbol s) {
142: int pi = getLoc(s);
143: if (pi == -1)
144: return null;
145: return env[pi];
146: }
147:
148: public final Value lookup(int pi) {
149: return env[pi];
150: }
151:
152: public void undefine(Symbol s) {
153: synchronized (symbolMap) {
154: Integer i = (Integer) symbolMap.remove(s);
155: if (i == null)
156: return;
157: env[i.intValue()] = FALSE;
158: }
159: }
160:
161: public void display(ValueWriter w) throws IOException {
162: displayNamedOpaque(w, "environment");
163: }
164:
165: public void serialize(Serializer s) throws IOException {
166: s.writeInt(symbolMap.size());
167: for (Iterator i = symbolMap.keySet().iterator(); i.hasNext();) {
168: Symbol key = (Symbol) i.next();
169: s.writeExpression(key);
170: int loc = ((Integer) symbolMap.get(key)).intValue();
171: s.writeExpression(env[loc]);
172: }
173: serializeSidecar(s);
174: s.writeSymbolicEnvironment(getParent());
175: }
176:
177: public void serializeSidecar(Serializer s) throws IOException {
178: s.writeInt(sidecars.size());
179:
180: for (Iterator i = sidecars.keySet().iterator(); i.hasNext();) {
181: Symbol key = (Symbol) i.next();
182: s.writeExpression(key);
183: s.writeSymbolicEnvironment((SymbolicEnvironment) sidecars
184: .get(key));
185: }
186: }
187:
188: public void deserialize(Deserializer s) throws IOException {
189: int smsize = s.readInt();
190: env = new Value[smsize];
191: symbolMap = new HashMap(smsize);
192: for (int i = 0; i < smsize; i++) {
193: Symbol id = (Symbol) s.readExpression();
194: env[i] = (Value) s.readExpression();
195: symbolMap.put(id, new Integer(i));
196: }
197:
198: deserializeSidecar(s);
199: nextFree = smsize;
200:
201: parent = s.readSymbolicEnvironment();
202: }
203:
204: public void deserializeSidecar(Deserializer s) throws IOException {
205: int scsize = s.readInt();
206: for (int i = 0; i < scsize; i++) {
207: Expression e = s.readExpression();
208: Symbol key = (Symbol) e;
209: sidecars.put(key, s.readSymbolicEnvironment());
210: }
211: }
212:
213: public boolean visit(ExpressionVisitor v) {
214: if (!super .visit(v))
215: return false;
216: for (Iterator i = symbolMap.keySet().iterator(); i.hasNext();) {
217: Symbol key = (Symbol) i.next();
218: if (!v.visit(key))
219: return false;
220: int loc = ((Integer) symbolMap.get(key)).intValue();
221: if (!v.visit(env[loc]))
222: return false;
223: }
224: return visitSidecar(v);
225: }
226:
227: public boolean visitSidecar(ExpressionVisitor v) {
228: for (Iterator i = sidecars.keySet().iterator(); i.hasNext();) {
229: Symbol key = (Symbol) i.next();
230: if (!v.visit(key)
231: || !v
232: .visit((SymbolicEnvironment) sidecars
233: .get(key)))
234: return false;
235: }
236: return v.visit(parent);
237: }
238:
239: }
240:
241: /*
242: * The contents of this file are subject to the Mozilla Public
243: * License Version 1.1 (the "License"); you may not use this file
244: * except in compliance with the License. You may obtain a copy of
245: * the License at http://www.mozilla.org/MPL/
246: *
247: * Software distributed under the License is distributed on an "AS
248: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
249: * implied. See the License for the specific language governing
250: * rights and limitations under the License.
251: *
252: * The Original Code is the Second Interpreter of Scheme Code (SISC).
253: *
254: * The Initial Developer of the Original Code is Scott G. Miller.
255: * Portions created by Scott G. Miller are Copyright (C) 2000-2007
256: * Scott G. Miller. All Rights Reserved.
257: *
258: * Contributor(s):
259: * Matthias Radestock
260: *
261: * Alternatively, the contents of this file may be used under the
262: * terms of the GNU General Public License Version 2 or later (the
263: * "GPL"), in which case the provisions of the GPL are applicable
264: * instead of those above. If you wish to allow use of your
265: * version of this file only under the terms of the GPL and not to
266: * allow others to use your version of this file under the MPL,
267: * indicate your decision by deleting the provisions above and
268: * replace them with the notice and other provisions required by
269: * the GPL. If you do not delete the provisions above, a recipient
270: * may use your version of this file under either the MPL or the
271: * GPL.
272: */
|