001: package jsint;
002:
003: /** Environments store mappings from symbols to locations.
004: * At compile time, we can lookup to see if a symbol names a location,
005: * and at run time we can get or set the value in a location.
006: * @author Peter Norvig, Copyright 1998, peter@norvig.com, <a href="license.txt">license</a>
007: * subsequently modified by Jscheme project members
008: * licensed under zlib licence (see license.txt)
009: **/
010:
011: public class Environment {
012:
013: /** The global environment. All info is in the Symbols themselves. **/
014: public static final Environment GLOBAL = new Environment(
015: Pair.EMPTY, null, null);
016:
017: /** The parent Environment: where you look if you can't find a variable. **/
018: private Environment parent;
019: /** A list of variables in this env. May be dotted or a lone symbol. **/
020: private Object vars;
021: /** An array of values in a 1-1 correspondance with the vars. **/
022: private Object[] vals;
023:
024: /** Create an Environment with local variables and values, and a parent
025: * Environment. **/
026: public Environment(Object vars, Object[] vals, Environment parent) {
027: this .vars = vars;
028: this .vals = vals;
029: this .parent = parent;
030: }
031:
032: public Object lookup(Symbol var) {
033: return lookup(var, 0, 0, vars);
034: }
035:
036: /** Lookup the symbol in the environment. Return either a
037: * LocalVariable a Symbol representing the global variable.
038: **/
039: public Object lookup(Symbol var, int up, int in, Object vars) {
040: if (this == GLOBAL)
041: return var;
042: else if (vars == var)
043: return new LocalVariable(up, in, var);
044: else if (!U.isPair(vars))
045: return parent.lookup(var, up + 1, 0, parent.vars);
046: else if (U.first(vars) == var)
047: return new LocalVariable(up, in, var);
048: else
049: return lookup(var, up, in + 1, U.rest(vars));
050: }
051:
052: /** Get the value of the LocalVariable in this Environment. **/
053: public Object get(LocalVariable var) {
054: return this .up(var.up).vals[var.in];
055: }
056:
057: /** Set the value of the LocalVariable in this Environment to a new value. **/
058: public Object set(LocalVariable var, Object newVal) {
059: return this .up(var.up).vals[var.in] = newVal;
060: }
061:
062: /** Go up a specified number of levels in the parent chain. **/
063: Environment up(int levels) {
064: return (levels == 0) ? this : this .parent.up(levels - 1);
065: }
066:
067: public String toString() {
068: return "{|" + toString0() + "|}";
069: }
070:
071: private String toString0() {
072: if (this == GLOBAL)
073: return "GLOBAL";
074: else
075: return U.stringify(vars)
076: + " "
077: + U.stringify(vals)
078: + ((parent == null) ? "" : "|" + parent.toString0());
079: }
080:
081: public void show(java.io.PrintWriter s) {
082: Environment e = this ;
083: while (e != GLOBAL) {
084: Object vars = e.vars;
085: Object[] vals = e.vals;
086: int i = 0;
087: while (U.isPair(vars)) {
088: show0(s, U.first(vars), vals[i]);
089: vars = U.rest(vars);
090: i = i + 1;
091: }
092: if (vars != Pair.EMPTY)
093: show0(s, vars, vals[i]);
094: e = e.parent;
095: }
096: }
097:
098: private void show0(java.io.PrintWriter s, Object var, Object val) {
099: String sval = U.stringify(val);
100: if (sval.length() > 100)
101: sval = sval.substring(0, 100) + "...";
102: s.println(" " + U.stringify(var) + " = " + sval);
103: }
104: }
|