author | wenzelm |
Wed, 16 Apr 1997 18:25:46 +0200 | |
changeset 2964 | 557a11310988 |
parent 2753 | bcde71e5f371 |
child 2979 | db6941221197 |
permissions | -rw-r--r-- |
256 | 1 |
(* Title: Pure/type.ML |
0 | 2 |
ID: $Id$ |
416 | 3 |
Author: Tobias Nipkow & Lawrence C Paulson |
0 | 4 |
|
2964 | 5 |
Type signatures, unification of types, interface to type inference. |
0 | 6 |
*) |
7 |
||
8 |
signature TYPE = |
|
2964 | 9 |
sig |
10 |
(*TFrees vs TVars*) |
|
621 | 11 |
val no_tvars: typ -> typ |
12 |
val varifyT: typ -> typ |
|
13 |
val unvarifyT: typ -> typ |
|
14 |
val varify: term * string list -> term |
|
2964 | 15 |
val freeze_vars: typ -> typ |
16 |
val thaw_vars: typ -> typ |
|
17 |
val freeze: term -> term |
|
18 |
||
19 |
(*type signatures*) |
|
0 | 20 |
type type_sig |
200 | 21 |
val rep_tsig: type_sig -> |
256 | 22 |
{classes: class list, |
2964 | 23 |
classrel: (class * class list) list, |
256 | 24 |
default: sort, |
963 | 25 |
tycons: (string * int) list, |
621 | 26 |
abbrs: (string * (string list * typ)) list, |
963 | 27 |
arities: (string * (class * sort list) list) list} |
0 | 28 |
val defaultS: type_sig -> sort |
2964 | 29 |
val logical_types: type_sig -> string list |
30 |
||
31 |
val subsort: type_sig -> sort * sort -> bool |
|
32 |
val eq_sort: type_sig -> sort * sort -> bool |
|
33 |
val norm_sort: type_sig -> sort -> sort |
|
34 |
val nonempty_sort: type_sig -> sort list -> sort -> bool |
|
35 |
val rem_sorts: typ -> typ |
|
36 |
||
416 | 37 |
val tsig0: type_sig |
621 | 38 |
val ext_tsig_classes: type_sig -> (class * class list) list -> type_sig |
2964 | 39 |
val ext_tsig_classrel: type_sig -> (class * class) list -> type_sig |
422 | 40 |
val ext_tsig_defsort: type_sig -> sort -> type_sig |
582 | 41 |
val ext_tsig_types: type_sig -> (string * int) list -> type_sig |
621 | 42 |
val ext_tsig_abbrs: type_sig -> (string * string list * typ) list -> type_sig |
963 | 43 |
val ext_tsig_arities: type_sig -> (string * sort list * sort)list -> type_sig |
256 | 44 |
val merge_tsigs: type_sig * type_sig -> type_sig |
2964 | 45 |
|
46 |
val typ_errors: type_sig -> typ * string list -> string list |
|
256 | 47 |
val cert_typ: type_sig -> typ -> typ |
48 |
val norm_typ: type_sig -> typ -> typ |
|
2964 | 49 |
|
256 | 50 |
val inst_term_tvars: type_sig * (indexname * typ) list -> term -> term |
2964 | 51 |
|
52 |
(*type matching*) |
|
53 |
exception TYPE_MATCH |
|
256 | 54 |
val typ_match: type_sig -> (indexname * typ) list * (typ * typ) |
55 |
-> (indexname * typ) list |
|
2964 | 56 |
val typ_instance: type_sig * typ * typ -> bool |
57 |
||
58 |
(*type unification*) |
|
59 |
exception TUNIFY |
|
1435
aefcd255ed4a
Removed bug in type unification. Negative indexes are not used any longer.
nipkow
parents:
1392
diff
changeset
|
60 |
val unify: type_sig -> int -> (indexname * typ) list -> (typ * typ) |
aefcd255ed4a
Removed bug in type unification. Negative indexes are not used any longer.
nipkow
parents:
1392
diff
changeset
|
61 |
-> (indexname * typ) list * int |
450 | 62 |
val raw_unify: typ * typ -> bool |
0 | 63 |
|
2964 | 64 |
(*type inference*) |
65 |
val get_sort: type_sig -> (indexname -> sort option) -> (indexname * sort) list |
|
66 |
-> indexname -> sort |
|
67 |
val constrain: term -> typ -> term |
|
68 |
val infer_types: type_sig * (string -> typ option) * (indexname -> typ option) |
|
69 |
* (indexname -> sort option) * string list * bool * typ list * term list |
|
70 |
-> term list * (indexname * typ) list |
|
71 |
end; |
|
72 |
||
73 |
structure Type: TYPE = |
|
0 | 74 |
struct |
75 |
||
2964 | 76 |
|
621 | 77 |
(*** TFrees vs TVars ***) |
78 |
||
79 |
(*disallow TVars*) |
|
80 |
fun no_tvars T = |
|
81 |
if null (typ_tvars T) then T |
|
82 |
else raise_type "Illegal schematic type variable(s)" [T] []; |
|
83 |
||
2964 | 84 |
(* varify, unvarify *) |
621 | 85 |
|
2964 | 86 |
val varifyT = map_type_tfree (fn (a, S) => TVar ((a, 0), S)); |
87 |
||
621 | 88 |
fun unvarifyT (Type (a, Ts)) = Type (a, map unvarifyT Ts) |
89 |
| unvarifyT (TVar ((a, 0), S)) = TFree (a, S) |
|
90 |
| unvarifyT T = T; |
|
91 |
||
92 |
fun varify (t, fixed) = |
|
93 |
let |
|
94 |
val fs = add_term_tfree_names (t, []) \\ fixed; |
|
95 |
val ixns = add_term_tvar_ixns (t, []); |
|
96 |
val fmap = fs ~~ variantlist (fs, map #1 ixns) |
|
2964 | 97 |
fun thaw (f as (a, S)) = |
98 |
(case assoc (fmap, a) of |
|
99 |
None => TFree f |
|
100 |
| Some b => TVar ((b, 0), S)); |
|
101 |
in |
|
102 |
map_term_types (map_type_tfree thaw) t |
|
103 |
end; |
|
104 |
||
105 |
||
106 |
(* thaw, freeze *) |
|
621 | 107 |
|
2964 | 108 |
val thaw_vars = |
109 |
let |
|
110 |
fun thaw (f as (a, S)) = |
|
111 |
(case explode a of |
|
112 |
"?" :: "'" :: vn => |
|
113 |
let val ((b, i), _) = Syntax.scan_varname vn in |
|
114 |
TVar (("'" ^ b, i), S) |
|
115 |
end |
|
116 |
| _ => TFree f) |
|
117 |
in map_type_tfree thaw end; |
|
118 |
||
119 |
val freeze_vars = |
|
120 |
map_type_tvar (fn (v, S) => TFree (Syntax.string_of_vname v, S)); |
|
621 | 121 |
|
122 |
||
2964 | 123 |
local |
124 |
fun nextname (pref, c) = |
|
125 |
if c = "z" then (pref ^ "a", "a") |
|
126 |
else (pref, chr (ord c + 1)); |
|
416 | 127 |
|
2964 | 128 |
fun newtvars used = |
129 |
let |
|
130 |
fun new ([], _, vmap) = vmap |
|
131 |
| new (ixn :: ixns, p as (pref, c), vmap) = |
|
132 |
let val nm = pref ^ c in |
|
133 |
if nm mem_string used then new (ixn :: ixns, nextname p, vmap) |
|
134 |
else new (ixns, nextname p, (ixn, nm) :: vmap) |
|
135 |
end |
|
136 |
in new end; |
|
416 | 137 |
|
2964 | 138 |
(*Turn all TVars which satisfy p into new (if freeze then TFrees else TVars). |
139 |
Note that if t contains frozen TVars there is the possibility that a TVar is |
|
140 |
turned into one of those. This is sound but not complete.*) |
|
416 | 141 |
|
2964 | 142 |
fun convert used freeze p t = |
143 |
let |
|
144 |
val used = |
|
145 |
if freeze then add_term_tfree_names (t, used) |
|
146 |
else used union (map #1 (filter_out p (add_term_tvar_ixns (t, [])))); |
|
147 |
val ixns = filter p (add_term_tvar_ixns (t, [])); |
|
148 |
val vmap = newtvars used (ixns, ("'", "a"), []); |
|
149 |
fun conv (var as (ixn, S)) = |
|
150 |
(case assoc (vmap, ixn) of |
|
151 |
None => TVar(var) |
|
152 |
| Some a => if freeze then TFree (a, S) else TVar ((a, 0), S)); |
|
153 |
in |
|
154 |
map_term_types (map_type_tvar conv) t |
|
155 |
end; |
|
156 |
in |
|
157 |
fun freeze t = convert (add_term_tfree_names(t,[])) true (K true) t; |
|
158 |
end; |
|
256 | 159 |
|
160 |
||
161 |
||
416 | 162 |
(*** type signatures ***) |
256 | 163 |
|
2964 | 164 |
(* type type_sig *) |
165 |
||
256 | 166 |
(* |
167 |
classes: |
|
2964 | 168 |
list of all declared classes; |
0 | 169 |
|
2964 | 170 |
classrel: |
171 |
(see Pure/sorts.ML) |
|
256 | 172 |
|
173 |
default: |
|
2964 | 174 |
default sort attached to all unconstrained type vars; |
256 | 175 |
|
963 | 176 |
tycons: |
2964 | 177 |
association list of all declared types with the number of their |
256 | 178 |
arguments; |
179 |
||
180 |
abbrs: |
|
2964 | 181 |
association list of type abbreviations; |
256 | 182 |
|
963 | 183 |
arities: |
2964 | 184 |
(see Pure/sorts.ML) |
0 | 185 |
*) |
186 |
||
256 | 187 |
datatype type_sig = |
188 |
TySg of { |
|
189 |
classes: class list, |
|
2964 | 190 |
classrel: (class * class list) list, |
256 | 191 |
default: sort, |
963 | 192 |
tycons: (string * int) list, |
621 | 193 |
abbrs: (string * (string list * typ)) list, |
2964 | 194 |
arities: (string * (class * sort list) list) list}; |
256 | 195 |
|
189 | 196 |
fun rep_tsig (TySg comps) = comps; |
0 | 197 |
|
256 | 198 |
fun defaultS (TySg {default, ...}) = default; |
199 |
||
2964 | 200 |
fun logical_types (TySg {classrel, arities, tycons, ...}) = |
201 |
let |
|
202 |
fun log_class c = Sorts.class_le classrel (c, logicC); |
|
203 |
fun log_type t = exists (log_class o #1) (assocs arities t); |
|
204 |
in |
|
205 |
filter log_type (map #1 tycons) |
|
206 |
end; |
|
207 |
||
208 |
||
209 |
(* sorts *) |
|
210 |
||
211 |
(* FIXME declared!? *) |
|
212 |
||
213 |
fun subsort (TySg {classrel, ...}) = Sorts.sort_le classrel; |
|
214 |
fun eq_sort (TySg {classrel, ...}) = Sorts.sort_eq classrel; |
|
215 |
fun norm_sort (TySg {classrel, ...}) = Sorts.norm_sort classrel; |
|
216 |
||
217 |
fun nonempty_sort (tsig as TySg {classrel, arities, ...}) hyps S = |
|
218 |
Sorts.nonempty_sort classrel arities hyps S; |
|
219 |
||
220 |
fun rem_sorts (Type (a, tys)) = Type (a, map rem_sorts tys) |
|
221 |
| rem_sorts (TFree (x, _)) = TFree (x, []) |
|
222 |
| rem_sorts (TVar (xi, _)) = TVar (xi, []); |
|
223 |
||
256 | 224 |
|
582 | 225 |
(* error messages *) |
256 | 226 |
|
416 | 227 |
fun undcl_class c = "Undeclared class " ^ quote c; |
2233
f919bdd5f9b6
Removed or eta-expanded some declarations that are illegal under value
paulson
parents:
2182
diff
changeset
|
228 |
fun err_undcl_class s = error (undcl_class s); |
0 | 229 |
|
422 | 230 |
fun err_dup_classes cs = |
231 |
error ("Duplicate declaration of class(es) " ^ commas_quote cs); |
|
416 | 232 |
|
233 |
fun undcl_type c = "Undeclared type constructor " ^ quote c; |
|
256 | 234 |
|
582 | 235 |
fun err_neg_args c = |
236 |
error ("Negative number of arguments of type constructor " ^ quote c); |
|
237 |
||
416 | 238 |
fun err_dup_tycon c = |
239 |
error ("Duplicate declaration of type constructor " ^ quote c); |
|
240 |
||
621 | 241 |
fun dup_tyabbrs ts = |
242 |
"Duplicate declaration of type abbreviation(s) " ^ commas_quote ts; |
|
416 | 243 |
|
244 |
fun ty_confl c = "Conflicting type constructor and abbreviation " ^ quote c; |
|
0 | 245 |
|
246 |
||
2964 | 247 |
(* FIXME err_undcl_class! *) |
0 | 248 |
(* 'leq' checks the partial order on classes according to the |
2964 | 249 |
statements in the association list 'a' (i.e. 'classrel') |
0 | 250 |
*) |
251 |
||
256 | 252 |
fun less a (C, D) = case assoc (a, C) of |
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
253 |
Some ss => D mem_string ss |
621 | 254 |
| None => err_undcl_class C; |
0 | 255 |
|
256 | 256 |
fun leq a (C, D) = C = D orelse less a (C, D); |
0 | 257 |
|
258 |
||
259 |
||
2964 | 260 |
(* FIXME *) |
200 | 261 |
(*Instantiation of type variables in types*) |
262 |
(*Pre: instantiations obey restrictions! *) |
|
263 |
fun inst_typ tye = |
|
949
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
264 |
let fun inst(var as (v, _)) = case assoc(tye, v) of |
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
265 |
Some U => inst_typ tye U |
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
266 |
| None => TVar(var) |
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
267 |
in map_type_tvar inst end; |
0 | 268 |
|
269 |
||
2964 | 270 |
fun check_has_sort (TySg {classrel, arities, ...}, T, S) = |
271 |
if Sorts.sort_le classrel ((Sorts.least_sort classrel arities T), S) then () |
|
272 |
else raise TYPE ("Type not of sort " ^ Sorts.str_of_sort S, [T], []); |
|
0 | 273 |
|
274 |
||
275 |
(*Instantiation of type variables in types *) |
|
256 | 276 |
fun inst_typ_tvars(tsig, tye) = |
949
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
277 |
let fun inst(var as (v, S)) = case assoc(tye, v) of |
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
278 |
Some U => (check_has_sort(tsig, U, S); U) |
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
279 |
| None => TVar(var) |
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
280 |
in map_type_tvar inst end; |
0 | 281 |
|
282 |
(*Instantiation of type variables in terms *) |
|
2617 | 283 |
fun inst_term_tvars (_,[]) t = t |
284 |
| inst_term_tvars arg t = map_term_types (inst_typ_tvars arg) t; |
|
200 | 285 |
|
286 |
||
1484 | 287 |
(* norm_typ *) |
200 | 288 |
|
1484 | 289 |
fun norm_typ (TySg {abbrs, ...}) ty = |
256 | 290 |
let |
621 | 291 |
val idx = maxidx_of_typ ty + 1; |
292 |
||
293 |
fun expand (Type (a, Ts)) = |
|
256 | 294 |
(case assoc (abbrs, a) of |
621 | 295 |
Some (vs, U) => |
296 |
expand (inst_typ (map (rpair idx) vs ~~ Ts) (incr_tvar idx U)) |
|
297 |
| None => Type (a, map expand Ts)) |
|
298 |
| expand T = T |
|
256 | 299 |
in |
621 | 300 |
expand ty |
256 | 301 |
end; |
302 |
||
303 |
||
304 |
||
305 |
||
306 |
||
307 |
(** build type signatures **) |
|
308 |
||
2964 | 309 |
fun make_tsig (classes, classrel, default, tycons, abbrs, arities) = |
310 |
TySg {classes = classes, classrel = classrel, default = default, |
|
963 | 311 |
tycons = tycons, abbrs = abbrs, arities = arities}; |
416 | 312 |
|
313 |
val tsig0 = make_tsig ([], [], [], [], [], []); |
|
256 | 314 |
|
0 | 315 |
|
1215
a206f722bef9
added nonempty_sort (a somewhat braindead version!);
wenzelm
parents:
963
diff
changeset
|
316 |
|
a206f722bef9
added nonempty_sort (a somewhat braindead version!);
wenzelm
parents:
963
diff
changeset
|
317 |
|
416 | 318 |
(* typ_errors *) |
256 | 319 |
|
416 | 320 |
(*check validity of (not necessarily normal) type; accumulate error messages*) |
256 | 321 |
|
416 | 322 |
fun typ_errors tsig (typ, errors) = |
256 | 323 |
let |
963 | 324 |
val TySg {classes, tycons, abbrs, ...} = tsig; |
416 | 325 |
|
326 |
fun class_err (errs, c) = |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
327 |
if c mem_string classes then errs |
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
328 |
else undcl_class c ins_string errs; |
256 | 329 |
|
330 |
val sort_err = foldl class_err; |
|
0 | 331 |
|
256 | 332 |
fun typ_errs (Type (c, Us), errs) = |
333 |
let |
|
334 |
val errs' = foldr typ_errs (Us, errs); |
|
335 |
fun nargs n = |
|
336 |
if n = length Us then errs' |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
337 |
else ("Wrong number of arguments: " ^ quote c) ins_string errs'; |
256 | 338 |
in |
963 | 339 |
(case assoc (tycons, c) of |
256 | 340 |
Some n => nargs n |
341 |
| None => |
|
342 |
(case assoc (abbrs, c) of |
|
343 |
Some (vs, _) => nargs (length vs) |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
344 |
| None => undcl_type c ins_string errs)) |
256 | 345 |
end |
346 |
| typ_errs (TFree (_, S), errs) = sort_err (errs, S) |
|
416 | 347 |
| typ_errs (TVar ((x, i), S), errs) = |
348 |
if i < 0 then |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
349 |
("Negative index for TVar " ^ quote x) ins_string sort_err (errs, S) |
416 | 350 |
else sort_err (errs, S); |
256 | 351 |
in |
416 | 352 |
typ_errs (typ, errors) |
256 | 353 |
end; |
354 |
||
355 |
||
356 |
(* cert_typ *) |
|
357 |
||
2964 | 358 |
(*check and normalize typ wrt. tsig*) (*exception TYPE*) |
359 |
fun cert_typ tsig T = |
|
360 |
(case typ_errors tsig (T, []) of |
|
361 |
[] => norm_typ tsig T |
|
362 |
| errs => raise_type (cat_lines errs) [T] []); |
|
256 | 363 |
|
364 |
||
365 |
||
422 | 366 |
(** merge type signatures **) |
256 | 367 |
|
422 | 368 |
(*'assoc_union' merges two association lists if the contents associated |
369 |
the keys are lists*) |
|
0 | 370 |
|
422 | 371 |
fun assoc_union (as1, []) = as1 |
372 |
| assoc_union (as1, (key, l2) :: as2) = |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
373 |
(case assoc_string (as1, key) of |
2964 | 374 |
Some l1 => assoc_union |
375 |
(overwrite (as1, (key, l1 union_string l2)), as2) |
|
422 | 376 |
| None => assoc_union ((key, l2) :: as1, as2)); |
0 | 377 |
|
378 |
||
2964 | 379 |
(* merge classrel *) |
0 | 380 |
|
2964 | 381 |
fun merge_classrel (classrel1, classrel2) = |
382 |
let val classrel = transitive_closure (assoc_union (classrel1, classrel2)) |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
383 |
in |
2964 | 384 |
if exists (op mem_string) classrel then |
422 | 385 |
error ("Cyclic class structure!") (* FIXME improve msg, raise TERM *) |
2964 | 386 |
else classrel |
416 | 387 |
end; |
388 |
||
389 |
||
422 | 390 |
(* coregularity *) |
0 | 391 |
|
392 |
(* 'is_unique_decl' checks if there exists just one declaration t:(Ss)C *) |
|
393 |
||
963 | 394 |
fun is_unique_decl ars (t,(C,w)) = case assoc (ars, C) of |
0 | 395 |
Some(w1) => if w = w1 then () else |
256 | 396 |
error("There are two declarations\n" ^ |
2964 | 397 |
Sorts.str_of_arity(t, w, [C]) ^ " and\n" ^ |
398 |
Sorts.str_of_arity(t, w1, [C]) ^ "\n" ^ |
|
0 | 399 |
"with the same result class.") |
400 |
| None => (); |
|
401 |
||
963 | 402 |
(* 'coreg' checks if there are two declarations t:(Ss1)C1 and t:(Ss2)C2 |
0 | 403 |
such that C1 >= C2 then Ss1 >= Ss2 (elementwise) *) |
404 |
||
963 | 405 |
fun coreg_err(t, (C1,w1), (C2,w2)) = |
2964 | 406 |
error("Declarations " ^ Sorts.str_of_arity(t, w1, [C1]) ^ " and " |
407 |
^ Sorts.str_of_arity(t, w2, [C2]) ^ " are in conflict"); |
|
0 | 408 |
|
2964 | 409 |
fun coreg classrel (t, Cw1) = |
410 |
let |
|
411 |
fun check1(Cw1 as (C1,w1), Cw2 as (C2,w2)) = |
|
412 |
if leq classrel (C1,C2) then |
|
413 |
if Sorts.sorts_le classrel (w1,w2) then () |
|
414 |
else coreg_err(t, Cw1, Cw2) |
|
415 |
else () |
|
416 |
fun check(Cw2) = (check1(Cw1,Cw2); check1(Cw2,Cw1)) |
|
963 | 417 |
in seq check end; |
0 | 418 |
|
2964 | 419 |
fun add_arity classrel ars (tCw as (_,Cw)) = |
420 |
(is_unique_decl ars tCw; coreg classrel tCw ars; Cw ins ars); |
|
0 | 421 |
|
256 | 422 |
fun varying_decls t = |
423 |
error ("Type constructor " ^ quote t ^ " has varying number of arguments"); |
|
0 | 424 |
|
425 |
||
963 | 426 |
(* 'merge_arities' builds the union of two 'arities' lists; |
422 | 427 |
it only checks the two restriction conditions and inserts afterwards |
428 |
all elements of the second list into the first one *) |
|
429 |
||
2964 | 430 |
fun merge_arities classrel = |
431 |
let fun test_ar t (ars1, sw) = add_arity classrel ars1 (t,sw); |
|
422 | 432 |
|
963 | 433 |
fun merge_c (arities1, (c as (t, ars2))) = case assoc (arities1, t) of |
434 |
Some(ars1) => |
|
435 |
let val ars = foldl (test_ar t) (ars1, ars2) |
|
436 |
in overwrite (arities1, (t,ars)) end |
|
437 |
| None => c::arities1 |
|
422 | 438 |
in foldl merge_c end; |
439 |
||
963 | 440 |
fun add_tycons (tycons, tn as (t,n)) = |
441 |
(case assoc (tycons, t) of |
|
442 |
Some m => if m = n then tycons else varying_decls t |
|
443 |
| None => tn :: tycons); |
|
422 | 444 |
|
445 |
fun merge_abbrs (abbrs1, abbrs2) = |
|
621 | 446 |
let val abbrs = abbrs1 union abbrs2 in |
447 |
(case gen_duplicates eq_fst abbrs of |
|
422 | 448 |
[] => abbrs |
621 | 449 |
| dups => raise_term (dup_tyabbrs (map fst dups)) []) |
422 | 450 |
end; |
451 |
||
452 |
||
453 |
(* 'merge_tsigs' takes the above declared functions to merge two type |
|
454 |
signatures *) |
|
455 |
||
2964 | 456 |
fun merge_tsigs(TySg{classes=classes1, default=default1, classrel=classrel1, |
963 | 457 |
tycons=tycons1, arities=arities1, abbrs=abbrs1}, |
2964 | 458 |
TySg{classes=classes2, default=default2, classrel=classrel2, |
963 | 459 |
tycons=tycons2, arities=arities2, abbrs=abbrs2}) = |
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
460 |
let val classes' = classes1 union_string classes2; |
2964 | 461 |
val classrel' = merge_classrel (classrel1, classrel2); |
963 | 462 |
val tycons' = foldl add_tycons (tycons1, tycons2) |
2964 | 463 |
val arities' = merge_arities classrel' (arities1, arities2); |
464 |
val default' = Sorts.norm_sort classrel' (default1 @ default2); |
|
422 | 465 |
val abbrs' = merge_abbrs(abbrs1, abbrs2); |
2964 | 466 |
in make_tsig(classes', classrel', default', tycons', abbrs', arities') end; |
422 | 467 |
|
468 |
||
469 |
||
470 |
(*** extend type signatures ***) |
|
471 |
||
2964 | 472 |
(** add classes and classrel relations **) |
422 | 473 |
|
474 |
fun add_classes classes cs = |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
475 |
(case cs inter_string classes of |
422 | 476 |
[] => cs @ classes |
477 |
| dups => err_dup_classes cs); |
|
478 |
||
479 |
||
2964 | 480 |
(*'add_classrel' adds a tuple consisting of a new class (the new class has |
422 | 481 |
already been inserted into the 'classes' list) and its superclasses (they |
2964 | 482 |
must be declared in 'classes' too) to the 'classrel' list of the given type |
422 | 483 |
signature; furthermore all inherited superclasses according to the |
484 |
superclasses brought with are inserted and there is a check that there are |
|
485 |
no cycles (i.e. C <= D <= C, with C <> D);*) |
|
486 |
||
2964 | 487 |
fun add_classrel classes (classrel, (s, ges)) = |
621 | 488 |
let |
2964 | 489 |
fun upd (classrel, s') = |
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
490 |
if s' mem_string classes then |
2964 | 491 |
let val ges' = the (assoc (classrel, s)) |
492 |
in case assoc (classrel, s') of |
|
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
493 |
Some sups => if s mem_string sups |
422 | 494 |
then error(" Cycle :" ^ s^" <= "^ s'^" <= "^ s ) |
2964 | 495 |
else overwrite |
496 |
(classrel, (s, sups union_string ges')) |
|
497 |
| None => classrel |
|
621 | 498 |
end |
499 |
else err_undcl_class s' |
|
2964 | 500 |
in foldl upd (classrel @ [(s, ges)], ges) end; |
422 | 501 |
|
502 |
||
503 |
(* 'extend_classes' inserts all new classes into the corresponding |
|
2964 | 504 |
lists ('classes', 'classrel') if possible *) |
422 | 505 |
|
2964 | 506 |
fun extend_classes (classes, classrel, new_classes) = |
621 | 507 |
let |
508 |
val classes' = add_classes classes (map fst new_classes); |
|
2964 | 509 |
val classrel' = foldl (add_classrel classes') (classrel, new_classes); |
510 |
in (classes', classrel') end; |
|
422 | 511 |
|
512 |
||
621 | 513 |
(* ext_tsig_classes *) |
514 |
||
515 |
fun ext_tsig_classes tsig new_classes = |
|
516 |
let |
|
2964 | 517 |
val TySg {classes, classrel, default, tycons, abbrs, arities} = tsig; |
518 |
val (classes',classrel') = extend_classes (classes,classrel,new_classes); |
|
621 | 519 |
in |
2964 | 520 |
make_tsig (classes', classrel', default, tycons, abbrs, arities) |
621 | 521 |
end; |
522 |
||
523 |
||
2964 | 524 |
(* ext_tsig_classrel *) |
422 | 525 |
|
2964 | 526 |
fun ext_tsig_classrel tsig pairs = |
422 | 527 |
let |
2964 | 528 |
val TySg {classes, classrel, default, tycons, abbrs, arities} = tsig; |
422 | 529 |
|
530 |
(* FIXME clean! *) |
|
2964 | 531 |
val classrel' = |
532 |
merge_classrel (classrel, map (fn (c1, c2) => (c1, [c2])) pairs); |
|
422 | 533 |
in |
2964 | 534 |
make_tsig (classes, classrel', default, tycons, abbrs, arities) |
422 | 535 |
end; |
536 |
||
537 |
||
538 |
(* ext_tsig_defsort *) |
|
539 |
||
2964 | 540 |
fun ext_tsig_defsort(TySg{classes,classrel,tycons,abbrs,arities,...}) default = |
541 |
make_tsig (classes, classrel, default, tycons, abbrs, arities); |
|
422 | 542 |
|
543 |
||
544 |
||
621 | 545 |
(** add types **) |
582 | 546 |
|
2964 | 547 |
fun ext_tsig_types (TySg {classes, classrel, default, tycons, abbrs, arities}) ts = |
582 | 548 |
let |
549 |
fun check_type (c, n) = |
|
550 |
if n < 0 then err_neg_args c |
|
963 | 551 |
else if is_some (assoc (tycons, c)) then err_dup_tycon c |
2233
f919bdd5f9b6
Removed or eta-expanded some declarations that are illegal under value
paulson
parents:
2182
diff
changeset
|
552 |
else if is_some (assoc (abbrs, c)) then error (ty_confl c) |
582 | 553 |
else (); |
554 |
in |
|
555 |
seq check_type ts; |
|
2964 | 556 |
make_tsig (classes, classrel, default, ts @ tycons, abbrs, |
963 | 557 |
map (rpair [] o #1) ts @ arities) |
582 | 558 |
end; |
559 |
||
560 |
||
561 |
||
562 |
(** add type abbreviations **) |
|
563 |
||
564 |
fun abbr_errors tsig (a, (lhs_vs, rhs)) = |
|
565 |
let |
|
963 | 566 |
val TySg {tycons, abbrs, ...} = tsig; |
621 | 567 |
val rhs_vs = map (#1 o #1) (typ_tvars rhs); |
582 | 568 |
|
569 |
val dup_lhs_vars = |
|
570 |
(case duplicates lhs_vs of |
|
571 |
[] => [] |
|
621 | 572 |
| vs => ["Duplicate variables on lhs: " ^ commas_quote vs]); |
582 | 573 |
|
574 |
val extra_rhs_vars = |
|
575 |
(case gen_rems (op =) (rhs_vs, lhs_vs) of |
|
576 |
[] => [] |
|
621 | 577 |
| vs => ["Extra variables on rhs: " ^ commas_quote vs]); |
582 | 578 |
|
579 |
val tycon_confl = |
|
963 | 580 |
if is_none (assoc (tycons, a)) then [] |
582 | 581 |
else [ty_confl a]; |
582 |
||
583 |
val dup_abbr = |
|
584 |
if is_none (assoc (abbrs, a)) then [] |
|
585 |
else ["Duplicate declaration of abbreviation"]; |
|
586 |
in |
|
587 |
dup_lhs_vars @ extra_rhs_vars @ tycon_confl @ dup_abbr @ |
|
588 |
typ_errors tsig (rhs, []) |
|
589 |
end; |
|
590 |
||
621 | 591 |
fun prep_abbr tsig (a, vs, raw_rhs) = |
592 |
let |
|
593 |
fun err msgs = (seq writeln msgs; |
|
594 |
error ("The error(s) above occurred in type abbreviation " ^ quote a)); |
|
595 |
||
596 |
val rhs = rem_sorts (varifyT (no_tvars raw_rhs)) |
|
597 |
handle TYPE (msg, _, _) => err [msg]; |
|
598 |
val abbr = (a, (vs, rhs)); |
|
599 |
in |
|
582 | 600 |
(case abbr_errors tsig abbr of |
621 | 601 |
[] => abbr |
602 |
| msgs => err msgs) |
|
582 | 603 |
end; |
604 |
||
2964 | 605 |
fun add_abbr (tsig as TySg{classes,classrel,default,tycons,arities,abbrs}, |
963 | 606 |
abbr) = |
621 | 607 |
make_tsig |
2964 | 608 |
(classes,classrel,default,tycons, prep_abbr tsig abbr :: abbrs, arities); |
621 | 609 |
|
610 |
fun ext_tsig_abbrs tsig raw_abbrs = foldl add_abbr (tsig, raw_abbrs); |
|
582 | 611 |
|
612 |
||
613 |
||
422 | 614 |
(** add arities **) |
615 |
||
0 | 616 |
(* 'coregular' checks |
963 | 617 |
- the two restrictions 'is_unique_decl' and 'coreg' |
256 | 618 |
- if the classes in the new type declarations are known in the |
0 | 619 |
given type signature |
620 |
- if one type constructor has always the same number of arguments; |
|
256 | 621 |
if one type declaration has passed all checks it is inserted into |
963 | 622 |
the 'arities' association list of the given type signatrure *) |
0 | 623 |
|
2964 | 624 |
fun coregular (classes, classrel, tycons) = |
2182
29e56f003599
Removal of polymorphic equality via mem, subset, eq_set, etc
paulson
parents:
2148
diff
changeset
|
625 |
let fun ex C = if C mem_string classes then () else err_undcl_class(C); |
0 | 626 |
|
963 | 627 |
fun addar(arities, (t, (w, C))) = case assoc(tycons, t) of |
0 | 628 |
Some(n) => if n <> length w then varying_decls(t) else |
963 | 629 |
((seq o seq) ex w; ex C; |
630 |
let val ars = the (assoc(arities, t)) |
|
2964 | 631 |
val ars' = add_arity classrel ars (t,(C,w)) |
963 | 632 |
in overwrite(arities, (t,ars')) end) |
2233
f919bdd5f9b6
Removed or eta-expanded some declarations that are illegal under value
paulson
parents:
2182
diff
changeset
|
633 |
| None => error (undcl_type t); |
0 | 634 |
|
963 | 635 |
in addar end; |
0 | 636 |
|
637 |
||
963 | 638 |
(* 'close' extends the 'arities' association list after all new type |
0 | 639 |
declarations have been inserted successfully: |
640 |
for every declaration t:(Ss)C , for all classses D with C <= D: |
|
641 |
if there is no declaration t:(Ss')C' with C < C' and C' <= D |
|
963 | 642 |
then insert the declaration t:(Ss)D into 'arities' |
0 | 643 |
this means, if there exists a declaration t:(Ss)C and there is |
644 |
no declaration t:(Ss')D with C <=D then the declaration holds |
|
256 | 645 |
for all range classes more general than C *) |
646 |
||
2964 | 647 |
fun close classrel arities = |
648 |
let fun check sl (l, (s, dom)) = case assoc (classrel, s) of |
|
621 | 649 |
Some sups => |
256 | 650 |
let fun close_sup (l, sup) = |
2964 | 651 |
if exists (fn s'' => less classrel (s, s'') andalso |
652 |
leq classrel (s'', sup)) sl |
|
0 | 653 |
then l |
256 | 654 |
else (sup, dom)::l |
655 |
in foldl close_sup (l, sups) end |
|
0 | 656 |
| None => l; |
256 | 657 |
fun ext (s, l) = (s, foldl (check (map #1 l)) (l, l)); |
963 | 658 |
in map ext arities end; |
0 | 659 |
|
422 | 660 |
|
621 | 661 |
(* ext_tsig_arities *) |
256 | 662 |
|
2964 | 663 |
fun norm_domain classrel = |
664 |
let fun one_min (f, (doms, ran)) = (f, (map (Sorts.norm_sort classrel) doms, ran)) |
|
665 |
in map one_min end; |
|
666 |
||
621 | 667 |
fun ext_tsig_arities tsig sarities = |
416 | 668 |
let |
2964 | 669 |
val TySg {classes, classrel, default, tycons, arities, abbrs} = tsig; |
963 | 670 |
val arities1 = |
2964 | 671 |
List.concat |
2672
85d7e800d754
Replaced "flat" by the Basis Library function List.concat
paulson
parents:
2617
diff
changeset
|
672 |
(map (fn (t, ss, cs) => map (fn c => (t, (ss, c))) cs) sarities); |
2964 | 673 |
val arities2 = foldl (coregular (classes, classrel, tycons)) |
674 |
(arities, norm_domain classrel arities1) |
|
675 |
|> close classrel; |
|
416 | 676 |
in |
2964 | 677 |
make_tsig (classes, classrel, default, tycons, abbrs, arities2) |
416 | 678 |
end; |
0 | 679 |
|
680 |
||
416 | 681 |
|
2964 | 682 |
(*** type unification and friends ***) |
0 | 683 |
|
2964 | 684 |
(** matching **) |
0 | 685 |
|
2964 | 686 |
exception TYPE_MATCH; |
0 | 687 |
|
2964 | 688 |
fun typ_match tsig = |
689 |
let |
|
690 |
fun match (subs, (TVar (v, S), T)) = |
|
691 |
(case assoc (subs, v) of |
|
692 |
None => ((v, (check_has_sort (tsig, T, S); T)) :: subs |
|
693 |
handle TYPE _ => raise TYPE_MATCH) |
|
694 |
| Some U => if U = T then subs else raise TYPE_MATCH) |
|
695 |
| match (subs, (Type (a, Ts), Type (b, Us))) = |
|
696 |
if a <> b then raise TYPE_MATCH |
|
697 |
else foldl match (subs, Ts ~~ Us) |
|
698 |
| match (subs, (TFree x, TFree y)) = |
|
699 |
if x = y then subs else raise TYPE_MATCH |
|
700 |
| match _ = raise TYPE_MATCH; |
|
701 |
in match end; |
|
0 | 702 |
|
2964 | 703 |
fun typ_instance (tsig, T, U) = |
704 |
(typ_match tsig ([], (U, T)); true) handle TYPE_MATCH => false; |
|
705 |
||
0 | 706 |
|
2964 | 707 |
|
708 |
(** unification **) |
|
709 |
||
0 | 710 |
exception TUNIFY; |
711 |
||
712 |
||
2964 | 713 |
(* occurs check *) |
0 | 714 |
|
2964 | 715 |
fun occurs v tye = |
716 |
let |
|
717 |
fun occ (Type (_, Ts)) = exists occ Ts |
|
718 |
| occ (TFree _) = false |
|
719 |
| occ (TVar (w, _)) = |
|
720 |
eq_ix (v, w) orelse |
|
721 |
(case assoc (tye, w) of |
|
722 |
None => false |
|
723 |
| Some U => occ U); |
|
0 | 724 |
in occ end; |
725 |
||
2964 | 726 |
|
727 |
(* chase variable assignments *) |
|
728 |
||
729 |
(*if devar returns a type var then it must be unassigned*) |
|
730 |
fun devar (T as TVar (v, _), tye) = |
|
731 |
(case assoc (tye, v) of |
|
732 |
Some U => devar (U, tye) |
|
733 |
| None => T) |
|
256 | 734 |
| devar (T, tye) = T; |
0 | 735 |
|
1627 | 736 |
|
2964 | 737 |
(* add_env *) |
0 | 738 |
|
2964 | 739 |
(*avoids chains 'a |-> 'b |-> 'c ...*) |
740 |
fun add_env (p, []) = [p] |
|
741 |
| add_env (vT as (v, T), (xU as (x, TVar (w, S))) :: ps) = |
|
742 |
(if eq_ix (v, w) then (x, T) else xU) :: add_env (vT, ps) |
|
743 |
| add_env (v, x :: xs) = x :: add_env (v, xs); |
|
0 | 744 |
|
745 |
||
2964 | 746 |
(* unify *) |
747 |
||
748 |
fun unify (tsig as TySg {classrel, arities, ...}) maxidx tyenv TU = |
|
749 |
let |
|
750 |
val tyvar_count = ref maxidx; |
|
751 |
fun gen_tyvar S = TVar (("'a", inc tyvar_count), S); |
|
752 |
||
753 |
fun mg_domain a S = |
|
754 |
Sorts.mg_domain classrel arities a S handle TYPE _ => raise TUNIFY; |
|
755 |
||
756 |
fun meet ((_, []), tye) = tye |
|
757 |
| meet ((TVar (xi, S'), S), tye) = |
|
758 |
if Sorts.sort_le classrel (S', S) then tye |
|
759 |
else add_env ((xi, gen_tyvar (Sorts.inter_sort classrel (S', S))), tye) |
|
760 |
| meet ((TFree (_, S'), S), tye) = |
|
761 |
if Sorts.sort_le classrel (S', S) then tye |
|
762 |
else raise TUNIFY |
|
763 |
| meet ((Type (a, Ts), S), tye) = meets ((Ts, mg_domain a S), tye) |
|
764 |
and meets (([], []), tye) = tye |
|
765 |
| meets ((T :: Ts, S :: Ss), tye) = |
|
766 |
meets ((Ts, Ss), meet ((devar (T, tye), S), tye)) |
|
767 |
| meets _ = sys_error "meets"; |
|
768 |
||
769 |
fun unif ((ty1, ty2), tye) = |
|
770 |
(case (devar (ty1, tye), devar (ty2, tye)) of |
|
771 |
(T as TVar (v, S1), U as TVar (w, S2)) => |
|
772 |
if eq_ix (v, w) then tye |
|
773 |
else if Sorts.sort_le classrel (S1, S2) then add_env ((w, T), tye) |
|
774 |
else if Sorts.sort_le classrel (S2, S1) then add_env ((v, U), tye) |
|
775 |
else |
|
776 |
let val S = gen_tyvar (Sorts.inter_sort classrel (S1, S2)) in |
|
777 |
add_env ((v, S), add_env ((w, S), tye)) |
|
778 |
end |
|
779 |
| (TVar (v, S), T) => |
|
780 |
if occurs v tye T then raise TUNIFY |
|
781 |
else meet ((T, S), add_env ((v, T), tye)) |
|
782 |
| (T, TVar (v, S)) => |
|
783 |
if occurs v tye T then raise TUNIFY |
|
784 |
else meet ((T, S), add_env ((v, T), tye)) |
|
785 |
| (Type (a, Ts), Type (b, Us)) => |
|
786 |
if a <> b then raise TUNIFY |
|
787 |
else foldr unif (Ts ~~ Us, tye) |
|
788 |
| (T, U) => if T = U then tye else raise TUNIFY); |
|
789 |
in |
|
790 |
(unif (TU, tyenv), ! tyvar_count) |
|
791 |
end; |
|
0 | 792 |
|
793 |
||
2964 | 794 |
(* raw_unify *) |
0 | 795 |
|
2964 | 796 |
(*purely structural unification -- ignores sorts*) |
450 | 797 |
fun raw_unify (ty1, ty2) = |
1435
aefcd255ed4a
Removed bug in type unification. Negative indexes are not used any longer.
nipkow
parents:
1392
diff
changeset
|
798 |
(unify tsig0 0 [] (rem_sorts ty1, rem_sorts ty2); true) |
450 | 799 |
handle TUNIFY => false; |
800 |
||
801 |
||
0 | 802 |
|
2964 | 803 |
(** type inference **) |
1435
aefcd255ed4a
Removed bug in type unification. Negative indexes are not used any longer.
nipkow
parents:
1392
diff
changeset
|
804 |
|
2964 | 805 |
(* constraints *) |
2587 | 806 |
|
807 |
fun get_sort tsig def_sort env xi = |
|
808 |
(case (assoc (env, xi), def_sort xi) of |
|
809 |
(None, None) => defaultS tsig |
|
810 |
| (None, Some S) => S |
|
811 |
| (Some S, None) => S |
|
812 |
| (Some S, Some S') => |
|
813 |
if eq_sort tsig (S, S') then S |
|
814 |
else error ("Sort constraint inconsistent with default for type variable " ^ |
|
815 |
quote (Syntax.string_of_vname' xi))); |
|
816 |
||
2964 | 817 |
fun constrain t T = |
818 |
if T = dummyT then t |
|
819 |
else Const ("_type_constraint_", T) $ t; |
|
0 | 820 |
|
821 |
||
2964 | 822 |
(* decode_types *) |
0 | 823 |
|
2964 | 824 |
(*transform parse tree into raw term (idempotent)*) |
825 |
fun decode_types tsig is_const def_type def_sort tm = |
|
826 |
let |
|
827 |
fun get_type xi = if_none (def_type xi) dummyT; |
|
828 |
val sort_env = Syntax.raw_term_sorts (eq_sort tsig) tm; |
|
829 |
||
830 |
fun decodeT t = |
|
831 |
cert_typ tsig (Syntax.typ_of_term (get_sort tsig def_sort sort_env) t); |
|
0 | 832 |
|
2964 | 833 |
fun decode (Const ("_constrain", _) $ t $ typ) = |
834 |
constrain (decode t) (decodeT typ) |
|
835 |
| decode (Const ("_constrainAbs", _) $ (abs as Abs (x, T, t)) $ typ) = |
|
836 |
if T = dummyT then Abs (x, decodeT typ, decode t) |
|
837 |
else constrain abs (decodeT typ --> dummyT) |
|
838 |
| decode (Abs (x, T, t)) = Abs (x, T, decode t) |
|
839 |
| decode (t $ u) = decode t $ decode u |
|
840 |
| decode (t as Free (x, T)) = |
|
841 |
if is_const x then Const (x, T) |
|
842 |
else if T = dummyT then Free (x, get_type (x, ~1)) |
|
843 |
else constrain t (get_type (x, ~1)) |
|
844 |
| decode (t as Var (xi, T)) = |
|
845 |
if T = dummyT then Var (xi, get_type xi) |
|
846 |
else constrain t (get_type xi) |
|
847 |
| decode (t as Bound _) = t |
|
848 |
| decode (t as Const _) = t; |
|
849 |
in |
|
850 |
decode tm |
|
851 |
end; |
|
0 | 852 |
|
853 |
||
2964 | 854 |
(* infer_types *) |
949
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
855 |
|
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
856 |
(* |
2964 | 857 |
Given [T1,...,Tn] and [t1,...,tn], ensure that the type of ti |
858 |
unifies with Ti (for i=1,...,n). |
|
859 |
||
860 |
tsig: type signature |
|
861 |
const_type: term signature |
|
862 |
def_type: partial map from indexnames to types (constrains Frees, Vars) |
|
863 |
def_sort: partial map from indexnames to sorts (constrains TFrees, TVars) |
|
864 |
used: list of already used type variables |
|
865 |
freeze: if true then generated parameters are turned into TFrees, else TVars |
|
949
83c588d6fee9
Changed treatment of during type inference internally generated type
nipkow
parents:
621
diff
changeset
|
866 |
*) |
0 | 867 |
|
2964 | 868 |
(*user-supplied inference parameters*) |
869 |
fun q_is_param (x, _) = |
|
870 |
(case explode x of |
|
871 |
"?" :: _ => true |
|
872 |
| _ => false); |
|
0 | 873 |
|
2964 | 874 |
fun infer_types (tsig, const_type, def_type, def_sort, used, freeze, pat_Ts, raw_ts) = |
565 | 875 |
let |
2964 | 876 |
val TySg {classrel, arities, ...} = tsig; |
877 |
val pat_Ts' = map (cert_typ tsig) pat_Ts; |
|
878 |
val raw_ts' = |
|
879 |
map (decode_types tsig (is_some o const_type) def_type def_sort) raw_ts; |
|
880 |
val (ts, Ts, unifier) = |
|
881 |
TypeInfer.infer_types const_type classrel arities used freeze |
|
882 |
q_is_param raw_ts' pat_Ts'; |
|
565 | 883 |
in |
2964 | 884 |
(ts, unifier) |
565 | 885 |
end; |
0 | 886 |
|
887 |
end; |