001: package sisc.data;
002:
003: import java.util.*;
004: import java.io.*;
005: import sisc.ser.*;
006: import sisc.exprs.fp.OptimismUnwarrantedException;
007: import sisc.interpreter.*;
008: import sisc.util.Util;
009: import sisc.util.ExpressionVisitor;
010: import sisc.util.ExpressionVisitee;
011:
012: /**
013: * The base class for any and all expressions. An expression is anything
014: * in Scheme that can evaluate to a value.
015: *
016: * In SISC, an expression can be <i>annotated</i>. An annotation is
017: * any key/value pair attached to an expression for the duration of its
018: * lifetime. Annotations are used to implement procedure properties
019: * and source-tracked debugging.
020: */
021: public abstract class Expression extends Util implements
022: Externalizable, ExpressionVisitee {
023:
024: protected static Set EMPTYSET = new TreeSet();
025:
026: public Map annotations;
027:
028: public synchronized Value getAnnotation(Symbol key, Value def) {
029: if (annotations == null)
030: return def;
031: Value res = (Value) annotations.get(key);
032: return (res == null) ? def : res;
033: }
034:
035: public Value getAnnotation(Symbol key) {
036: return getAnnotation(key, FALSE);
037: }
038:
039: public synchronized Value setAnnotation(Symbol key, Value val,
040: Value def) {
041: if (annotations == null)
042: annotations = new HashMap(0);
043: Value res = (Value) annotations.put(key, val);
044: return (res == null) ? def : res;
045: }
046:
047: public Value setAnnotation(Symbol key, Value val) {
048: return setAnnotation(key, val, FALSE);
049: }
050:
051: public synchronized Set getAnnotationKeys() {
052: if (annotations == null)
053: return EMPTYSET;
054: return annotations.keySet();
055: }
056:
057: public synchronized Pair getAnnotations() {
058: Pair res = EMPTYLIST;
059: if (annotations == null)
060: return res;
061: for (Iterator i = annotations.entrySet().iterator(); i
062: .hasNext();) {
063: Map.Entry en = (Map.Entry) i.next();
064: res = new Pair(new Pair((Value) en.getKey(), (Value) en
065: .getValue()), res);
066: }
067: return res;
068: }
069:
070: public void serializeAnnotations(Serializer s) throws IOException {
071: if (annotations == null) {
072: s.writeInt(0);
073: } else {
074: s.writeInt(annotations.size());
075: for (Iterator i = annotations.entrySet().iterator(); i
076: .hasNext();) {
077: Map.Entry en = (Map.Entry) i.next();
078: s.writeExpression((Expression) en.getKey());
079: s.writeExpression((Expression) en.getValue());
080: }
081: }
082: }
083:
084: public void deserializeAnnotations(Deserializer s)
085: throws IOException {
086: int ac = s.readInt();
087: if (ac == 0)
088: return;
089: annotations = new HashMap(ac);
090: for (; ac > 0; ac--) {
091: Expression key = s.readExpression();
092: Expression val = s.readExpression();
093: annotations.put(key, val);
094: }
095: }
096:
097: public boolean visitAnnotations(ExpressionVisitor v) {
098: if (annotations == null)
099: return true;
100: for (Iterator i = annotations.entrySet().iterator(); i
101: .hasNext();) {
102: Map.Entry en = (Map.Entry) i.next();
103: if (!v.visit((Expression) en.getKey()))
104: return false;
105: if (!v.visit((Expression) en.getValue()))
106: return false;
107: }
108: return true;
109: }
110:
111: /**
112: * The following helpers set the 'name annotation, which is used for
113: * naming procedures, environments, etc.
114: */
115: public void setName(Symbol s) {
116: setAnnotation(NAME, s);
117: }
118:
119: public Symbol getName() {
120: return (Symbol) getAnnotation(NAME, null);
121: }
122:
123: /**
124: * All expressions can be evaluated to some Scheme value. This function
125: * implements the exact manner in which an expression is evaluated.
126: * An expression, when evaluated, performs some action that results
127: * in its value being placed in the <tt>acc</tt> register of the given
128: * Interpreter.
129: *
130: * An expression that immediately evaluates to a value (i.e. does not
131: * require that an additional expression be evaluated to obtain its
132: * value) <i>must</i> clear the <tt>nxp</tt> register by setting it to
133: * null.
134: * Otherwise, <tt>nxp</tt> should be set to the expression that is to
135: * be evaluated next before this method returns.
136: *
137: * @exception ContinuationException
138: * @param r the Interpreter
139: */
140: public abstract void eval(Interpreter r)
141: throws ContinuationException;
142:
143: /**
144: * If an expression implements the Immediate interface, it must
145: * override getValue, which returns as a Value, the immediate value
146: * of this expression.
147: *
148: * @exception ContinuationException
149: * @param r the Interpreter
150: * @return the immediate value of this expression, or null if the value
151: * cannot be obtained immediately.
152: */
153: public Value getValue(Interpreter r) throws ContinuationException,
154: OptimismUnwarrantedException {
155: return null;
156: }
157:
158: /**
159: * A debugging function, express returns a Scheme value that describes
160: * this expression. See examples in sisc.exprs.*
161: */
162: public abstract Value express();
163:
164: /**
165: * All Expressions must implement a default (no-argument) constructor.
166: * Those that wish to be serialized to a heap must implement both this
167: * and the deserialize method. The Expression may use any method of
168: * the Serializer, which implements java.io.DataOutput
169: * to write its state.
170: *
171: * @exception IOException
172: * @param s the Serializer
173: */
174: public void serialize(Serializer s) throws IOException {
175: }
176:
177: /**
178: * All Expressions must implement a default (no-argument) constructor.
179: * Those that wish to b serialized to a heap must implement both this
180: * and the serialize method. The Expression may use any method of the
181: * DataInput stream and the Deserializer serialization context
182: * to read its state.
183: *
184: * @exception IOException
185: * @param s the Deserializer
186: */
187: public void deserialize(Deserializer s) throws IOException {
188: }
189:
190: public void writeExternal(ObjectOutput out) throws IOException {
191: Serializer s = JavaSerializer.create(out);
192: serialize(s);
193: serializeAnnotations(s);
194: }
195:
196: public void readExternal(ObjectInput in) throws IOException {
197: Deserializer d = JavaDeserializer.create(in);
198: deserialize(d);
199: deserializeAnnotations(d);
200: }
201:
202: public Object readResolve() throws ObjectStreamException {
203: return (this instanceof Singleton) ? ((Singleton) this )
204: .singletonValue() : this ;
205: }
206:
207: public boolean visit(ExpressionVisitor v) {
208: return true;
209: }
210:
211: }
212: /*
213: * The contents of this file are subject to the Mozilla Public
214: * License Version 1.1 (the "License"); you may not use this file
215: * except in compliance with the License. You may obtain a copy of
216: * the License at http://www.mozilla.org/MPL/
217: *
218: * Software distributed under the License is distributed on an "AS
219: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
220: * implied. See the License for the specific language governing
221: * rights and limitations under the License.
222: *
223: * The Original Code is the Second Interpreter of Scheme Code (SISC).
224: *
225: * The Initial Developer of the Original Code is Scott G. Miller.
226: * Portions created by Scott G. Miller are Copyright (C) 2000-2007
227: * Scott G. Miller. All Rights Reserved.
228: *
229: * Contributor(s):
230: * Matthias Radestock
231: *
232: * Alternatively, the contents of this file may be used under the
233: * terms of the GNU General Public License Version 2 or later (the
234: * "GPL"), in which case the provisions of the GPL are applicable
235: * instead of those above. If you wish to allow use of your
236: * version of this file only under the terms of the GPL and not to
237: * allow others to use your version of this file under the MPL,
238: * indicate your decision by deleting the provisions above and
239: * replace them with the notice and other provisions required by
240: * the GPL. If you do not delete the provisions above, a recipient
241: * may use your version of this file under either the MPL or the
242: * GPL.
243: */
|