001: // Copyright (c) 2004 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.mapping;
005:
006: /** A Location is an abstract cell/location/variable with a value. */
007:
008: public abstract class Location {
009: /* DEBUGGING
010: static int counter;
011: public int id=++counter;
012: */
013:
014: public Location() {
015: }
016:
017: public Symbol getKeySymbol() {
018: return null;
019: }
020:
021: public Object getKeyProperty() {
022: return null;
023: }
024:
025: public String toString() {
026: StringBuffer sbuf = new StringBuffer();
027: sbuf.append(getClass().getName());
028: Symbol sym = getKeySymbol();
029: sbuf.append('[');
030: if (sym != null) {
031: sbuf.append(sym);
032: Object property = getKeyProperty();
033: // For a ThreadLocation the property defaults to "this".
034: // In that case we'd better not print the property ...
035: if (property != null && property != this ) {
036: sbuf.append('/');
037: sbuf.append(property);
038: }
039: }
040: /* DEBUGGING:
041: sbuf.append(" #:");
042: sbuf.append(id);
043: */
044: sbuf.append("]");
045: return sbuf.toString();
046: }
047:
048: /** Magic value used to indicate there is no property binding. */
049: public static final String UNBOUND = new String("(unbound)");
050:
051: public abstract Object get(Object defaultValue);
052:
053: /** Get the current value of this location.
054: * @exception UnboundLocationException the location does not have a value. */
055: public final Object get() {
056: Object unb = Location.UNBOUND;
057: Object val = get(unb);
058: if (val == unb)
059: throw new UnboundLocationException(this );
060: return val;
061: }
062:
063: public abstract void set(Object value);
064:
065: public void undefine() {
066: set(UNBOUND);
067: }
068:
069: /** Set a value, but return cookie so old value can be restored.
070: * This is intended for fluid-let where (in the case of multiple threads)
071: * a simple save-restore isn't always the right thing. */
072: public Object setWithSave(Object newValue, CallContext ctx) {
073: ctx.pushFluid(this );
074: Object old = get(UNBOUND);
075: set(newValue);
076: return old;
077: }
078:
079: /** Restore an old value.
080: * @param oldValue the return value from a prior setWithSave. */
081: public void setRestore(Object oldValue, CallContext ctx) {
082: // if (oldValue == UNBOUND) ???; // FIXME
083: set(oldValue);
084: ctx.popFluid();
085: }
086:
087: public boolean isBound() {
088: Object unb = Location.UNBOUND;
089: return get(unb) != unb;
090: }
091:
092: public boolean isConstant() {
093: return false;
094: }
095:
096: public Location getBase() {
097: return this ;
098: }
099:
100: public final Object getValue() {
101: return get(null);
102: }
103:
104: public final Object setValue(Object newValue) {
105: Object value = get(null);
106: set(newValue);
107: return value;
108: }
109:
110: /** True if directly entered in an Environment. (Only if NamedLocation.) */
111: public boolean entered() {
112: return false;
113: }
114:
115: public void print(java.io.PrintWriter ps) {
116: ps.print("#<location ");
117: Symbol name = getKeySymbol();
118: if (name != null)
119: ps.print(name);
120: Object unb = Location.UNBOUND;
121: Object value = get(unb);
122: if (value != unb) {
123: ps.print(" -> ");
124: ps.print(value);
125: } else
126: ps.print("(unbound)");
127: ps.print('>');
128: }
129:
130: // The compiler emits calls to this method.
131: public static Location make(Object init, String name) {
132: ThreadLocation loc = new ThreadLocation(name);
133: loc.setGlobal(init);
134: return loc;
135: }
136:
137: // The compiler emits calls to this method.
138: public static IndirectableLocation make(String name) {
139: Symbol sym = Namespace.EmptyNamespace.getSymbol(name.intern());
140: PlainLocation loc = new PlainLocation(sym, null);
141: loc.base = null;
142: loc.value = UNBOUND;
143: return loc;
144: }
145:
146: public static IndirectableLocation make(Symbol name) {
147: PlainLocation loc = new PlainLocation(name, null);
148: loc.base = null;
149: loc.value = UNBOUND;
150: return loc;
151: }
152: }
|