|
|
1.1 root 1: (* Copyright 1989 by AT&T Bell Laboratories *)
2: structure Env : ENV =
3: struct
4: open PrintUtil ErrorMsg Symbol Access (* also uses: IntStrMap, Basics *)
5: type binding = Basics.binding
6:
7: type info = {path: int list, strenv: Basics.strenv}
8: type symtable = binding IntStrMap.intstrmap
9: type key = int * string
10:
11: val debugLook = System.Control.debugLook
12: val debugCollect = System.Control.debugCollect
13:
14: val defaultInfo = {path = []:int list, strenv = Basics.DIR}
15:
16: fun name(_,s) = s
17:
18: exception Unbound
19: and Unboundrec
20: exception UnboundTable = System.Unsafe.Assembly.UnboundTable
21:
22: datatype 'a locality = LOCAL of 'a | GLOBAL of 'a
23:
24: datatype env
25: = TBL of
26: {info: info, table: symtable, prev: env ref, isopen: bool}
27: | REC of env ref
28: | STR of env ref
29: | NIL
30:
31: fun prevEnv(TBL{prev,...}) = prev
32: | prevEnv(REC prev) = prev
33: | prevEnv(STR prev) = prev
34: | prevEnv _ = impossible "prevEnv"
35:
36: fun printEnv(TBL{prev,...}) = (print "TBL\n "; printEnv(!prev))
37: | printEnv(REC prev) = (print "REC\n "; printEnv(!prev))
38: | printEnv(STR prev) = (print "STR\n "; printEnv(!prev))
39: | printEnv(NIL) = ()
40:
41: fun printEnvs(e) = (print "Env:\n "; printEnv e)
42:
43: fun eqEnv(NIL,NIL) = true
44: | eqEnv(REC r, REC r') = r = r'
45: | eqEnv(STR r, STR r') = r = r'
46: | eqEnv(TBL{prev=r,...}, TBL{prev=r',...}) = r = r'
47: | eqEnv _ = false
48:
49: fun appenv f (newenv,oldenv) =
50: let fun loop env =
51: if eqEnv(env,oldenv)
52: then ()
53: else case env
54: of TBL{table,prev=ref env',...} => (IntStrMap.app f table; loop env')
55: | REC(ref env') => loop env'
56: | STR(ref env') => loop env'
57: | NIL => ()
58: in loop newenv
59: end
60:
61: (* the global variable containing the current environment *)
62: val env = ref(NIL)
63: fun current() = !env
64:
65: fun closeCurrentNewEnv() =
66: case current()
67: of TBL{info,table,prev,isopen=true} =>
68: TBL{info=info,table=table,prev=prev,isopen=false}
69: | _ => impossible "Env.closeCurrentNewEnv()"
70:
71: fun newTable() = IntStrMap.new(32, UnboundTable) : symtable
72:
73: fun openOld (info: info, table: symtable) : unit =
74: env := TBL{info=info, table=table, prev=ref(!env), isopen=false}
75:
76: fun openNew (info: info, table: symtable) : unit =
77: env := TBL{info=info, table=table, prev=ref(!env), isopen=true}
78:
79: fun openRec () : unit =
80: env := REC(ref(!env))
81:
82: fun openStr () : unit =
83: env := STR(ref(!env))
84:
85: fun popSTR(STR(ref e)) = e
86: | popSTR(TBL{prev=ref e,...}) = popSTR e
87: | popSTR(REC(ref e)) = popSTR e
88: | popSTR NIL = impossible "popSTR"
89:
90: fun closeStr () = env := popSTR(!env)
91:
92: fun openScope () : env =
93: let val oldenv = !env
94: in env := TBL{info=defaultInfo,table=newTable(),prev=ref oldenv,isopen=true};
95: oldenv
96: end
97:
98: fun resetEnv (e) = env := e
99:
100: fun add (binder) =
101: case !env
102: of TBL{table,isopen=true,...} => IntStrMap.add table binder
103: | e =>
104: let val table = newTable() : symtable
105: in IntStrMap.add table binder;
106: env := TBL{info=defaultInfo,table=table,prev=ref e,isopen=true}
107: end
108:
109: fun collectTable (collector) =
110: let fun save (REC(ref e)) = save e
111: | save (TBL{info,table,prev=ref e,...}) =
112: (save e;
113: IntStrMap.app (fn (binder) => collector(binder,info)) table)
114: | save (STR(ref e)) = env := e
115: | save _ = impossible "Env.collectTable.save"
116: in save(!env)
117: end
118:
119: fun splice (local':env, in':env) =
120: (* remove bindings between env in' and env local' *)
121: prevEnv(in') := local'
122:
123: fun lookEnv (e:env, (key: key)) =
124: let fun look1 (TBL{info,table,prev=ref e,...}) =
125: ((IntStrMap.map table key, info)
126: handle UnboundTable => look1 e)
127: | look1 (REC(ref e)) = look1 e
128: | look1 (STR(ref e)) = look1 e
129: | look1 NIL =
130: (ErrorMsg.flaggedmsg debugLook
131: ("lookEnv failed (global): "^name(key)^"\n");
132: raise Unbound)
133: in look1(e)
134: end
135:
136: fun look k = lookEnv (!env, k)
137:
138: fun lookStrLocal (key: key) =
139: let fun look1 (TBL{info,table,prev=ref e,...}) =
140: ((IntStrMap.map table key, info)
141: handle UnboundTable => look1 e)
142: | look1 (REC(ref e)) = look1 e
143: | look1 (STR(ref e)) =
144: (ErrorMsg.flaggedmsg debugLook
145: ("lookStrLocal failed (structure): "^name(key)^"\n");
146: raise Unbound)
147: | look1 NIL =
148: (ErrorMsg.flaggedmsg debugLook
149: ("lookStrLocal failed (global): "^name(key)^"\n");
150: raise Unbound)
151: in look1(!env)
152: end
153:
154: fun lookRec (key : key) =
155: (* searches global env for index id
156: marks result as LOCAL or GLOBAL depending on whether binding is
157: found within rec boundary or not
158: used for initial var/con lookup in expressions (namespace=0) *)
159: let fun look1 (TBL{info,table,prev=ref e,...}) =
160: (LOCAL(IntStrMap.map table key, info)
161: handle UnboundTable => look1 e)
162: | look1 (REC(ref e)) =
163: (GLOBAL(lookEnv(e,key))
164: handle Unbound => raise Unboundrec)
165: | look1 (STR(ref e)) = look1 e
166: | look1 NIL =
167: (ErrorMsg.flaggedmsg debugLook
168: ("lookRec failed : "^name(key)^"\n");
169: raise Unbound)
170: in look1(!env)
171: end
172:
173: fun lookRecLocal (key: key) =
174: (* searches global env upto nearest rec boundary
175: used when attempting to patch variables in expressions *)
176: let fun look1 (TBL{info,table,prev=ref e,...}) =
177: ((IntStrMap.map table key, info)
178: handle UnboundTable => look1 e)
179: | look1 (REC(ref e)) = raise Unboundrec
180: | look1 (STR(ref e)) = look1 e
181: | look1 NIL = raise Unbound
182: in look1(!env)
183: end
184:
185: (* environment management for toplevel loop *)
186: val restoreEnv : env ref = ref NIL
187: fun restore () = resetEnv(!restoreEnv)
188: fun commit () = restoreEnv := openScope()
189: fun previous () = !restoreEnv
190:
191: (* consolidating adjacent open tables *)
192: fun consolidateEnv(e as TBL{table,prev=ref(pre),isopen=true,...}) =
193: (case pre
194: of TBL{isopen=true,...} =>
195: let val ans as (_, adder) = consolidateEnv pre
196: in IntStrMap.app adder table; ans
197: end
198: | _ => (e,IntStrMap.add table))
199: | consolidateEnv(e) = (e,(fn x => ()))
200:
201: fun consolidate () =
202: env := let val (x,_) = consolidateEnv(!env) in x end
203:
204: fun foldEnv (f: env * 'a -> 'a) (newenv:env) (oldenv:env) (base:'a) : 'a =
205: if eqEnv(newenv,oldenv)
206: then base
207: else f(newenv, foldEnv f (!(prevEnv newenv)) oldenv base)
208:
209: fun collectEnv(newenv, oldenv) =
210: foldEnv (fn (TBL{table,...},acc) =>
211: (IntStrMap.app (IntStrMap.add acc) table; acc)
212: | (REC _,acc) => acc
213: | (STR _,acc) => acc
214: | (NIL,acc) => acc
215: ) newenv oldenv (newTable())
216:
217: fun reset() = (env := NIL; restoreEnv := NIL)
218:
219: fun popModule(oldenv:env): symtable =
220: (* Extract prefix of environment above oldenv (corresponding
221: to module bindings). oldenv will normally be pervasiveEnv.
222: Then reset env to savedEnv. *)
223: collectEnv(!env,oldenv)
224:
225: end (* EnvFunc *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.