1 (* Title: Pure/envir.ML |
1 (* Title: Pure/envir.ML |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
4 Copyright 1988 University of Cambridge |
4 Copyright 1988 University of Cambridge |
5 |
5 |
6 Environments. They don't take account that typ is part of variable |
6 Environments. The type of a term variable / sort of a type variable is |
7 name. Therefore we check elsewhere that two variables with same names |
7 part of its name. The lookup function must apply type substitutions, |
8 and different types cannot occur. |
8 since they may change the identity of a variable. |
9 *) |
9 *) |
10 |
10 |
11 signature ENVIR = |
11 signature ENVIR = |
12 sig |
12 sig |
13 datatype env = Envir of {asol: term Vartab.table, iTs: typ Vartab.table, maxidx: int} |
13 type tenv |
14 val type_env: env -> typ Vartab.table |
14 datatype env = Envir of {asol: tenv, iTs: Type.tyenv, maxidx: int} |
|
15 val type_env: env -> Type.tyenv |
15 exception SAME |
16 exception SAME |
16 val genvars: string -> env * typ list -> env * term list |
17 val genvars: string -> env * typ list -> env * term list |
17 val genvar: string -> env * typ -> env * term |
18 val genvar: string -> env * typ -> env * term |
18 val lookup: env * indexname -> term option |
19 val lookup: env * (indexname * typ) -> term option |
19 val update: (indexname * term) * env -> env |
20 val lookup': (Type.tyenv * tenv) * (indexname * typ) -> term option |
|
21 val update: ((indexname * typ) * term) * env -> env |
20 val empty: int -> env |
22 val empty: int -> env |
21 val is_empty: env -> bool |
23 val is_empty: env -> bool |
22 val above: int * env -> bool |
24 val above: int * env -> bool |
23 val vupdate: (indexname * term) * env -> env |
25 val vupdate: ((indexname * typ) * term) * env -> env |
24 val alist_of: env -> (indexname * term) list |
26 val alist_of: env -> (indexname * (typ * term)) list |
25 val norm_term: env -> term -> term |
27 val norm_term: env -> term -> term |
26 val norm_term_same: env -> term -> term |
28 val norm_term_same: env -> term -> term |
27 val norm_type: typ Vartab.table -> typ -> typ |
29 val norm_type: Type.tyenv -> typ -> typ |
28 val norm_type_same: typ Vartab.table -> typ -> typ |
30 val norm_type_same: Type.tyenv -> typ -> typ |
29 val norm_types_same: typ Vartab.table -> typ list -> typ list |
31 val norm_types_same: Type.tyenv -> typ list -> typ list |
30 val beta_norm: term -> term |
32 val beta_norm: term -> term |
31 val head_norm: env -> term -> term |
33 val head_norm: env -> term -> term |
32 val fastype: env -> typ list -> term -> typ |
34 val fastype: env -> typ list -> term -> typ |
|
35 val typ_subst_TVars: Type.tyenv -> typ -> typ |
|
36 val subst_TVars: Type.tyenv -> term -> term |
|
37 val subst_Vars: tenv -> term -> term |
|
38 val subst_vars: Type.tyenv * tenv -> term -> term |
33 end; |
39 end; |
34 |
40 |
35 structure Envir : ENVIR = |
41 structure Envir : ENVIR = |
36 struct |
42 struct |
37 |
43 |
38 (*updating can destroy environment in 2 ways!! |
44 (*updating can destroy environment in 2 ways!! |
39 (1) variables out of range (2) circular assignments |
45 (1) variables out of range (2) circular assignments |
40 *) |
46 *) |
|
47 type tenv = (typ * term) Vartab.table |
|
48 |
41 datatype env = Envir of |
49 datatype env = Envir of |
42 {maxidx: int, (*maximum index of vars*) |
50 {maxidx: int, (*maximum index of vars*) |
43 asol: term Vartab.table, (*table of assignments to Vars*) |
51 asol: tenv, (*table of assignments to Vars*) |
44 iTs: typ Vartab.table} (*table of assignments to TVars*) |
52 iTs: Type.tyenv} (*table of assignments to TVars*) |
45 |
53 |
46 fun type_env (Envir {iTs, ...}) = iTs; |
54 fun type_env (Envir {iTs, ...}) = iTs; |
47 |
55 |
48 (*Generate a list of distinct variables. |
56 (*Generate a list of distinct variables. |
49 Increments index to make them distinct from ALL present variables. *) |
57 Increments index to make them distinct from ALL present variables. *) |
58 (*Generate a variable.*) |
66 (*Generate a variable.*) |
59 fun genvar name (env,T) : env * term = |
67 fun genvar name (env,T) : env * term = |
60 let val (env',[v]) = genvars name (env,[T]) |
68 let val (env',[v]) = genvars name (env,[T]) |
61 in (env',v) end; |
69 in (env',v) end; |
62 |
70 |
63 fun lookup (Envir{asol,...}, xname) : term option = Vartab.lookup (asol, xname); |
71 (* de-reference TVars. When dealing with environments produced by *) |
64 |
72 (* matching instead of unification, there is no need to chase *) |
65 fun update ((xname, t), Envir{maxidx, asol, iTs}) = |
73 (* assigned TVars. In this case, set b to false. *) |
66 Envir{maxidx=maxidx, asol=Vartab.update_new ((xname,t), asol), iTs=iTs}; |
74 fun devar b iTs (T as TVar vT) = (case Type.lookup (iTs, vT) of |
|
75 NONE => T |
|
76 | SOME T' => if b then devar true iTs T' else T') |
|
77 | devar b iTs T = T; |
|
78 |
|
79 fun eq_type b iTs (T, T') = |
|
80 (case (devar b iTs T, devar b iTs T') of |
|
81 (Type (s, Ts), Type (s', Ts')) => |
|
82 s = s' andalso ListPair.all (eq_type b iTs) (Ts, Ts') |
|
83 | (U, U') => U = U'); |
|
84 |
|
85 fun var_clash ixn T T' = raise TYPE ("Variable " ^ |
|
86 quote (Syntax.string_of_vname ixn) ^ " has two distinct types", |
|
87 [T', T], []); |
|
88 |
|
89 fun gen_lookup f asol (xname, T) = |
|
90 (case Vartab.lookup (asol, xname) of |
|
91 NONE => NONE |
|
92 | SOME (U, t) => if f (T, U) then SOME t |
|
93 else var_clash xname T U); |
|
94 |
|
95 (* version ignoring type substitutions *) |
|
96 fun lookup1 asol = gen_lookup op = asol; |
|
97 |
|
98 fun gen_lookup2 b (iTs, asol) = |
|
99 if Vartab.is_empty iTs then lookup1 asol |
|
100 else gen_lookup (eq_type b iTs) asol; |
|
101 |
|
102 fun lookup2 env = gen_lookup2 true env; |
|
103 |
|
104 fun lookup (Envir {asol, iTs, ...}, p) = lookup2 (iTs, asol) p; |
|
105 |
|
106 (* version for matching algorithms, does not chase TVars *) |
|
107 fun lookup' (env, p) = gen_lookup2 false env p; |
|
108 |
|
109 fun update (((xname, T), t), Envir {maxidx, asol, iTs}) = |
|
110 Envir{maxidx=maxidx, asol=Vartab.update_new ((xname, (T, t)), asol), iTs=iTs}; |
67 |
111 |
68 (*The empty environment. New variables will start with the given index+1.*) |
112 (*The empty environment. New variables will start with the given index+1.*) |
69 fun empty m = Envir{maxidx=m, asol=Vartab.empty, iTs=Vartab.empty}; |
113 fun empty m = Envir{maxidx=m, asol=Vartab.empty, iTs=Vartab.empty}; |
70 |
114 |
71 (*Test for empty environment*) |
115 (*Test for empty environment*) |
78 | (SOME (_, i), NONE) => i > lim |
122 | (SOME (_, i), NONE) => i > lim |
79 | (NONE, SOME (_, i')) => i' > lim |
123 | (NONE, SOME (_, i')) => i' > lim |
80 | (SOME (_, i), SOME (_, i')) => i > lim andalso i' > lim); |
124 | (SOME (_, i), SOME (_, i')) => i > lim andalso i' > lim); |
81 |
125 |
82 (*Update, checking Var-Var assignments: try to suppress higher indexes*) |
126 (*Update, checking Var-Var assignments: try to suppress higher indexes*) |
83 fun vupdate((a,t), env) = case t of |
127 fun vupdate ((aU as (a, U), t), env as Envir {iTs, ...}) = case t of |
84 Var(name',T) => |
128 Var (nT as (name', T)) => |
85 if a=name' then env (*cycle!*) |
129 if a = name' then env (*cycle!*) |
86 else if xless(a, name') then |
130 else if xless(a, name') then |
87 (case lookup(env,name') of (*if already assigned, chase*) |
131 (case lookup (env, nT) of (*if already assigned, chase*) |
88 NONE => update((name', Var(a,T)), env) |
132 NONE => update ((nT, Var (a, T)), env) |
89 | SOME u => vupdate((a,u), env)) |
133 | SOME u => vupdate ((aU, u), env)) |
90 else update((a,t), env) |
134 else update ((aU, t), env) |
91 | _ => update((a,t), env); |
135 | _ => update ((aU, t), env); |
92 |
136 |
93 |
137 |
94 (*Convert environment to alist*) |
138 (*Convert environment to alist*) |
95 fun alist_of (Envir{asol,...}) = Vartab.dest asol; |
139 fun alist_of (Envir{asol,...}) = Vartab.dest asol; |
96 |
140 |
101 |
145 |
102 (*raised when norm has no effect on a term, to do sharing instead of copying*) |
146 (*raised when norm has no effect on a term, to do sharing instead of copying*) |
103 exception SAME; |
147 exception SAME; |
104 |
148 |
105 fun norm_term1 same (asol,t) : term = |
149 fun norm_term1 same (asol,t) : term = |
106 let fun norm (Var (w,T)) = |
150 let fun norm (Var wT) = |
107 (case Vartab.lookup (asol, w) of |
151 (case lookup1 asol wT of |
108 SOME u => (norm u handle SAME => u) |
152 SOME u => (norm u handle SAME => u) |
109 | NONE => raise SAME) |
153 | NONE => raise SAME) |
110 | norm (Abs(a,T,body)) = Abs(a, T, norm body) |
154 | norm (Abs(a,T,body)) = Abs(a, T, norm body) |
111 | norm (Abs(_,_,body) $ t) = normh(subst_bound (t, body)) |
155 | norm (Abs(_,_,body) $ t) = normh(subst_bound (t, body)) |
112 | norm (f $ t) = |
156 | norm (f $ t) = |
118 and normh t = norm t handle SAME => t |
162 and normh t = norm t handle SAME => t |
119 in (if same then norm else normh) t end |
163 in (if same then norm else normh) t end |
120 |
164 |
121 fun normT iTs (Type (a, Ts)) = Type (a, normTs iTs Ts) |
165 fun normT iTs (Type (a, Ts)) = Type (a, normTs iTs Ts) |
122 | normT iTs (TFree _) = raise SAME |
166 | normT iTs (TFree _) = raise SAME |
123 | normT iTs (TVar(v, _)) = (case Vartab.lookup (iTs, v) of |
167 | normT iTs (TVar vS) = (case Type.lookup (iTs, vS) of |
124 SOME U => normTh iTs U |
168 SOME U => normTh iTs U |
125 | NONE => raise SAME) |
169 | NONE => raise SAME) |
126 and normTh iTs T = ((normT iTs T) handle SAME => T) |
170 and normTh iTs T = ((normT iTs T) handle SAME => T) |
127 and normTs iTs [] = raise SAME |
171 and normTs iTs [] = raise SAME |
128 | normTs iTs (T :: Ts) = |
172 | normTs iTs (T :: Ts) = |
131 |
175 |
132 fun norm_term2 same (asol, iTs, t) : term = |
176 fun norm_term2 same (asol, iTs, t) : term = |
133 let fun norm (Const (a, T)) = Const(a, normT iTs T) |
177 let fun norm (Const (a, T)) = Const(a, normT iTs T) |
134 | norm (Free (a, T)) = Free(a, normT iTs T) |
178 | norm (Free (a, T)) = Free(a, normT iTs T) |
135 | norm (Var (w, T)) = |
179 | norm (Var (w, T)) = |
136 (case Vartab.lookup (asol, w) of |
180 (case lookup2 (iTs, asol) (w, T) of |
137 SOME u => normh u |
181 SOME u => normh u |
138 | NONE => Var(w, normT iTs T)) |
182 | NONE => Var(w, normT iTs T)) |
139 | norm (Abs (a, T, body)) = |
183 | norm (Abs (a, T, body)) = |
140 (Abs (a, normT iTs T, normh body) handle SAME => Abs (a, T, norm body)) |
184 (Abs (a, normT iTs T, normh body) handle SAME => Abs (a, T, norm body)) |
141 | norm (Abs(_, _, body) $ t) = normh (subst_bound (t, body)) |
185 | norm (Abs(_, _, body) $ t) = normh (subst_bound (t, body)) |
167 |
211 |
168 (*Put a term into head normal form for unification.*) |
212 (*Put a term into head normal form for unification.*) |
169 |
213 |
170 fun head_norm env t = |
214 fun head_norm env t = |
171 let |
215 let |
172 fun hnorm (Var (v, T)) = (case lookup (env, v) of |
216 fun hnorm (Var vT) = (case lookup (env, vT) of |
173 SOME u => head_norm env u |
217 SOME u => head_norm env u |
174 | NONE => raise SAME) |
218 | NONE => raise SAME) |
175 | hnorm (Abs (a, T, body)) = Abs (a, T, hnorm body) |
219 | hnorm (Abs (a, T, body)) = Abs (a, T, hnorm body) |
176 | hnorm (Abs (_, _, body) $ t) = |
220 | hnorm (Abs (_, _, body) $ t) = |
177 head_norm env (subst_bound (t, body)) |
221 head_norm env (subst_bound (t, body)) |
187 fun fastype (Envir {iTs, ...}) = |
231 fun fastype (Envir {iTs, ...}) = |
188 let val funerr = "fastype: expected function type"; |
232 let val funerr = "fastype: expected function type"; |
189 fun fast Ts (f $ u) = |
233 fun fast Ts (f $ u) = |
190 (case fast Ts f of |
234 (case fast Ts f of |
191 Type ("fun", [_, T]) => T |
235 Type ("fun", [_, T]) => T |
192 | TVar(ixn, _) => |
236 | TVar ixnS => |
193 (case Vartab.lookup (iTs, ixn) of |
237 (case Type.lookup (iTs, ixnS) of |
194 SOME (Type ("fun", [_, T])) => T |
238 SOME (Type ("fun", [_, T])) => T |
195 | _ => raise TERM (funerr, [f $ u])) |
239 | _ => raise TERM (funerr, [f $ u])) |
196 | _ => raise TERM (funerr, [f $ u])) |
240 | _ => raise TERM (funerr, [f $ u])) |
197 | fast Ts (Const (_, T)) = T |
241 | fast Ts (Const (_, T)) = T |
198 | fast Ts (Free (_, T)) = T |
242 | fast Ts (Free (_, T)) = T |
201 handle Subscript => raise TERM ("fastype: Bound", [Bound i])) |
245 handle Subscript => raise TERM ("fastype: Bound", [Bound i])) |
202 | fast Ts (Var (_, T)) = T |
246 | fast Ts (Var (_, T)) = T |
203 | fast Ts (Abs (_, T, u)) = T --> fast (T :: Ts) u |
247 | fast Ts (Abs (_, T, u)) = T --> fast (T :: Ts) u |
204 in fast end; |
248 in fast end; |
205 |
249 |
|
250 |
|
251 (*Substitute for type Vars in a type*) |
|
252 fun typ_subst_TVars iTs T = if Vartab.is_empty iTs then T else |
|
253 let fun subst(Type(a, Ts)) = Type(a, map subst Ts) |
|
254 | subst(T as TFree _) = T |
|
255 | subst(T as TVar ixnS) = |
|
256 (case Type.lookup (iTs, ixnS) of NONE => T | SOME(U) => U) |
|
257 in subst T end; |
|
258 |
|
259 (*Substitute for type Vars in a term*) |
|
260 val subst_TVars = map_term_types o typ_subst_TVars; |
|
261 |
|
262 (*Substitute for Vars in a term *) |
|
263 fun subst_Vars itms t = if Vartab.is_empty itms then t else |
|
264 let fun subst (v as Var ixnT) = getOpt (lookup1 itms ixnT, v) |
|
265 | subst (Abs (a, T, t)) = Abs (a, T, subst t) |
|
266 | subst (f $ t) = subst f $ subst t |
|
267 | subst t = t |
|
268 in subst t end; |
|
269 |
|
270 (*Substitute for type/term Vars in a term *) |
|
271 fun subst_vars (env as (iTs, itms)) = |
|
272 if Vartab.is_empty iTs then subst_Vars itms else |
|
273 let fun subst (Const (a, T)) = Const(a, typ_subst_TVars iTs T) |
|
274 | subst (Free (a, T)) = Free (a, typ_subst_TVars iTs T) |
|
275 | subst (Var (ixn, T)) = (case lookup' (env, (ixn, T)) of |
|
276 NONE => Var (ixn, typ_subst_TVars iTs T) |
|
277 | SOME t => t) |
|
278 | subst (b as Bound _) = b |
|
279 | subst (Abs (a, T, t)) = Abs(a, typ_subst_TVars iTs T, subst t) |
|
280 | subst (f $ t) = subst f $ subst t |
|
281 in subst end; |
|
282 |
206 end; |
283 end; |