01: // Copyright (c) 2004 Per M.A. Bothner.
02: // This is free software; for terms and warranty disclaimer see ./COPYING.
03:
04: package gnu.mapping;
05:
06: public abstract class IndirectableLocation extends Location {
07: /** If <code>value==DIRECT_ON_SET</code>, break indirection on a <code>set</code>. */
08: protected static final Object DIRECT_ON_SET = new String(
09: "(direct-on-set)");
10:
11: /** If <code>value</code> has this value, force indirection even
12: * for the <code>setWithSave</code> operation.
13: * Ignoring the restore aspect of a <code>fluid-let</code>, it is normally
14: * treated as closer to a <code>define</code> than to a <code>set</code>,
15: * in that we break the sharing with another <code>Environment</code>.
16: * Setting <code>value</code> to <code>INDIRECT_FLUIDS</code> means we do
17: * <em>not</em> want to break the indirection in this case. */
18: protected static final Object INDIRECT_FLUIDS = new String(
19: "(indirect-fluids)");
20:
21: /** If non-null, operations are forwarded to the base location. */
22: protected Location base;
23:
24: /** If <code>base</code> is null, the current value stored in
25: * this <code>Location</code>.
26: * If <code>base</code> is non-null, then <code>value</code> is generally
27: * ignored. However, the special value <code>DIRECT_ON_SET</code> means that
28: * writes change change <code>value</code> directly, instead of setting
29: * the value of <code>base</code>.
30: */
31: protected Object value;
32:
33: public Symbol getKeySymbol() {
34: return base != null ? base.getKeySymbol() : null;
35: }
36:
37: public Object getKeyProperty() {
38: return base != null ? base.getKeyProperty() : null;
39: }
40:
41: public boolean isConstant() {
42: return base != null && base.isConstant();
43: }
44:
45: public Location getBase() {
46: return base == null ? this : base.getBase();
47: }
48:
49: public Location getBaseForce() {
50: if (base == null)
51: return new PlainLocation(getKeySymbol(), getKeyProperty(),
52: value);
53: else
54: return base;
55: }
56:
57: public void setBase(Location base) {
58: this .base = base;
59: this .value = null;
60: }
61:
62: /** Define this Location as an alias for some other Location. */
63: public void setAlias(Location base) {
64: this .base = base;
65: this .value = INDIRECT_FLUIDS;
66: }
67:
68: public void undefine() {
69: base = null;
70: value = UNBOUND;
71: }
72:
73: public Environment getEnvironment() {
74: return (base instanceof NamedLocation ? ((NamedLocation) base)
75: .getEnvironment() : null);
76: }
77: }
|