comparison src/elaborate.sml @ 403:8084fa9216de

New implicit argument handling
author Adam Chlipala <adamc@hcoop.net>
date Tue, 21 Oct 2008 16:41:11 -0400
parents ebf27030ae3b
children 06fcddcd20d3
comparison
equal deleted inserted replaced
402:ebf27030ae3b 403:8084fa9216de
1 (* Copyright (c) 2008, Adam Chlipala 1 (* Copyright (c) 2008, Adam Chlipala
2 * All rights reserved. 2 * All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met: 5 * modification, are permitted provided that the following conditions are met:
6 * 6 *
7 * - Redistributions of source code must retain the above copyright notice, 7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer. 8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice, 9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation 10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution. 11 * and/or other materials provided with the distribution.
12 * - The names of contributors may not be used to endorse or promote products 12 * - The names of contributors may not be used to endorse or promote products
13 * derived from this software without specific prior written permission. 13 * derived from this software without specific prior written permission.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE. 25 * POSSIBILITY OF SUCH DAMAGE.
26 *) 26 *)
27 27
28 structure Elaborate :> ELABORATE = struct 28 structure Elaborate :> ELABORATE = struct
29 29
30 structure P = Prim 30 structure P = Prim
31 structure L = Source 31 structure L = Source
32 structure L' = Elab 32 structure L' = Elab
33 structure E = ElabEnv 33 structure E = ElabEnv
34 structure U = ElabUtil 34 structure U = ElabUtil
35 structure D = Disjoint 35 structure D = Disjoint
36 36
37 open Print 37 open Print
38 open ElabPrint 38 open ElabPrint
39 open ElabErr 39 open ElabErr
40 40
41 structure IM = IntBinaryMap 41 structure IM = IntBinaryMap
42 42
43 structure SK = struct 43 structure SK = struct
44 type ord_key = string 44 type ord_key = string
45 val compare = String.compare 45 val compare = String.compare
46 end 46 end
47 47
48 structure SS = BinarySetFn(SK) 48 structure SS = BinarySetFn(SK)
49 structure SM = BinaryMapFn(SK) 49 structure SM = BinaryMapFn(SK)
50 50
51 val basis_r = ref 0 51 val basis_r = ref 0
52 52
53 fun elabExplicitness e = 53 fun elabExplicitness e =
54 case e of 54 case e of
55 L.Explicit => L'.Explicit 55 L.Explicit => L'.Explicit
56 | L.Implicit => L'.Implicit 56 | L.Implicit => L'.Implicit
57 57
58 fun occursKind r = 58 fun occursKind r =
59 U.Kind.exists (fn L'.KUnif (_, _, r') => r = r' 59 U.Kind.exists (fn L'.KUnif (_, _, r') => r = r'
60 | _ => false) 60 | _ => false)
61 61
62 exception KUnify' of kunify_error 62 exception KUnify' of kunify_error
63 63
64 fun unifyKinds' (k1All as (k1, _)) (k2All as (k2, _)) = 64 fun unifyKinds' (k1All as (k1, _)) (k2All as (k2, _)) =
65 let 65 let
66 fun err f = raise KUnify' (f (k1All, k2All)) 66 fun err f = raise KUnify' (f (k1All, k2All))
67 in 67 in
68 case (k1, k2) of 68 case (k1, k2) of
69 (L'.KType, L'.KType) => () 69 (L'.KType, L'.KType) => ()
70 | (L'.KUnit, L'.KUnit) => () 70 | (L'.KUnit, L'.KUnit) => ()
71 71
72 | (L'.KArrow (d1, r1), L'.KArrow (d2, r2)) => 72 | (L'.KArrow (d1, r1), L'.KArrow (d2, r2)) =>
73 (unifyKinds' d1 d2; 73 (unifyKinds' d1 d2;
74 unifyKinds' r1 r2) 74 unifyKinds' r1 r2)
75 | (L'.KName, L'.KName) => () 75 | (L'.KName, L'.KName) => ()
76 | (L'.KRecord k1, L'.KRecord k2) => unifyKinds' k1 k2 76 | (L'.KRecord k1, L'.KRecord k2) => unifyKinds' k1 k2
77 | (L'.KTuple ks1, L'.KTuple ks2) => 77 | (L'.KTuple ks1, L'.KTuple ks2) =>
78 ((ListPair.appEq (fn (k1, k2) => unifyKinds' k1 k2) (ks1, ks2)) 78 ((ListPair.appEq (fn (k1, k2) => unifyKinds' k1 k2) (ks1, ks2))
79 handle ListPair.UnequalLengths => err KIncompatible) 79 handle ListPair.UnequalLengths => err KIncompatible)
80 80
81 | (L'.KError, _) => () 81 | (L'.KError, _) => ()
82 | (_, L'.KError) => () 82 | (_, L'.KError) => ()
83 83
84 | (L'.KUnif (_, _, ref (SOME k1All)), _) => unifyKinds' k1All k2All 84 | (L'.KUnif (_, _, ref (SOME k1All)), _) => unifyKinds' k1All k2All
85 | (_, L'.KUnif (_, _, ref (SOME k2All))) => unifyKinds' k1All k2All 85 | (_, L'.KUnif (_, _, ref (SOME k2All))) => unifyKinds' k1All k2All
86 86
87 | (L'.KUnif (_, _, r1), L'.KUnif (_, _, r2)) => 87 | (L'.KUnif (_, _, r1), L'.KUnif (_, _, r2)) =>
88 if r1 = r2 then 88 if r1 = r2 then
89 () 89 ()
90 else 90 else
91 r1 := SOME k2All 91 r1 := SOME k2All
92 92
93 | (L'.KUnif (_, _, r), _) => 93 | (L'.KUnif (_, _, r), _) =>
94 if occursKind r k2All then 94 if occursKind r k2All then
95 err KOccursCheckFailed 95 err KOccursCheckFailed
96 else 96 else
97 r := SOME k2All 97 r := SOME k2All
98 | (_, L'.KUnif (_, _, r)) => 98 | (_, L'.KUnif (_, _, r)) =>
99 if occursKind r k1All then 99 if occursKind r k1All then
100 err KOccursCheckFailed 100 err KOccursCheckFailed
101 else 101 else
102 r := SOME k1All 102 r := SOME k1All
103 103
104 | _ => err KIncompatible 104 | _ => err KIncompatible
105 end 105 end
106 106
107 exception KUnify of L'.kind * L'.kind * kunify_error 107 exception KUnify of L'.kind * L'.kind * kunify_error
108 108
109 fun unifyKinds k1 k2 = 109 fun unifyKinds k1 k2 =
110 unifyKinds' k1 k2 110 unifyKinds' k1 k2
111 handle KUnify' err => raise KUnify (k1, k2, err) 111 handle KUnify' err => raise KUnify (k1, k2, err)
112 112
113 fun checkKind env c k1 k2 = 113 fun checkKind env c k1 k2 =
114 unifyKinds k1 k2 114 unifyKinds k1 k2
115 handle KUnify (k1, k2, err) => 115 handle KUnify (k1, k2, err) =>
116 conError env (WrongKind (c, k1, k2, err)) 116 conError env (WrongKind (c, k1, k2, err))
117 117
118 val dummy = ErrorMsg.dummySpan 118 val dummy = ErrorMsg.dummySpan
119 119
120 val ktype = (L'.KType, dummy) 120 val ktype = (L'.KType, dummy)
121 val kname = (L'.KName, dummy) 121 val kname = (L'.KName, dummy)
122 val ktype_record = (L'.KRecord ktype, dummy) 122 val ktype_record = (L'.KRecord ktype, dummy)
123 123
124 val cerror = (L'.CError, dummy) 124 val cerror = (L'.CError, dummy)
125 val kerror = (L'.KError, dummy) 125 val kerror = (L'.KError, dummy)
126 val eerror = (L'.EError, dummy) 126 val eerror = (L'.EError, dummy)
127 val sgnerror = (L'.SgnError, dummy) 127 val sgnerror = (L'.SgnError, dummy)
128 val strerror = (L'.StrError, dummy) 128 val strerror = (L'.StrError, dummy)
129 129
130 val int = ref cerror 130 val int = ref cerror
131 val float = ref cerror 131 val float = ref cerror
132 val string = ref cerror 132 val string = ref cerror
133 val table = ref cerror 133 val table = ref cerror
134 134
135 local 135 local
136 val count = ref 0 136 val count = ref 0
137 in 137 in
138 138
139 fun resetKunif () = count := 0 139 fun resetKunif () = count := 0
140 140
141 fun kunif loc = 141 fun kunif loc =
142 let 142 let
143 val n = !count 143 val n = !count
144 val s = if n <= 26 then 144 val s = if n <= 26 then
145 str (chr (ord #"A" + n)) 145 str (chr (ord #"A" + n))
146 else 146 else
147 "U" ^ Int.toString (n - 26) 147 "U" ^ Int.toString (n - 26)
148 in 148 in
149 count := n + 1; 149 count := n + 1;
150 (L'.KUnif (loc, s, ref NONE), dummy) 150 (L'.KUnif (loc, s, ref NONE), dummy)
151 end 151 end
152 152
153 end 153 end
154 154
155 local 155 local
156 val count = ref 0 156 val count = ref 0
157 in 157 in
158 158
159 fun resetCunif () = count := 0 159 fun resetCunif () = count := 0
160 160
161 fun cunif (loc, k) = 161 fun cunif (loc, k) =
162 let 162 let
163 val n = !count 163 val n = !count
164 val s = if n <= 26 then 164 val s = if n <= 26 then
165 str (chr (ord #"A" + n)) 165 str (chr (ord #"A" + n))
166 else 166 else
167 "U" ^ Int.toString (n - 26) 167 "U" ^ Int.toString (n - 26)
168 in 168 in
169 count := n + 1; 169 count := n + 1;
170 (L'.CUnif (loc, k, s, ref NONE), dummy) 170 (L'.CUnif (loc, k, s, ref NONE), dummy)
171 end 171 end
172 172
173 end 173 end
174 174
175 fun elabKind (k, loc) = 175 fun elabKind (k, loc) =
176 case k of 176 case k of
177 L.KType => (L'.KType, loc) 177 L.KType => (L'.KType, loc)
178 | L.KArrow (k1, k2) => (L'.KArrow (elabKind k1, elabKind k2), loc) 178 | L.KArrow (k1, k2) => (L'.KArrow (elabKind k1, elabKind k2), loc)
179 | L.KName => (L'.KName, loc) 179 | L.KName => (L'.KName, loc)
180 | L.KRecord k => (L'.KRecord (elabKind k), loc) 180 | L.KRecord k => (L'.KRecord (elabKind k), loc)
181 | L.KUnit => (L'.KUnit, loc) 181 | L.KUnit => (L'.KUnit, loc)
182 | L.KTuple ks => (L'.KTuple (map elabKind ks), loc) 182 | L.KTuple ks => (L'.KTuple (map elabKind ks), loc)
183 | L.KWild => kunif loc 183 | L.KWild => kunif loc
184 184
185 fun foldKind (dom, ran, loc)= 185 fun foldKind (dom, ran, loc)=
186 (L'.KArrow ((L'.KArrow ((L'.KName, loc), 186 (L'.KArrow ((L'.KArrow ((L'.KName, loc),
187 (L'.KArrow (dom, 187 (L'.KArrow (dom,
188 (L'.KArrow (ran, ran), loc)), loc)), loc), 188 (L'.KArrow (ran, ran), loc)), loc)), loc),
189 (L'.KArrow (ran, 189 (L'.KArrow (ran,
190 (L'.KArrow ((L'.KRecord dom, loc), 190 (L'.KArrow ((L'.KRecord dom, loc),
191 ran), loc)), loc)), loc) 191 ran), loc)), loc)), loc)
192 192
193 fun hnormKind (kAll as (k, _)) = 193 fun hnormKind (kAll as (k, _)) =
194 case k of 194 case k of
195 L'.KUnif (_, _, ref (SOME k)) => hnormKind k 195 L'.KUnif (_, _, ref (SOME k)) => hnormKind k
196 | _ => kAll 196 | _ => kAll
197 197
198 fun elabCon (env, denv) (c, loc) = 198 fun elabCon (env, denv) (c, loc) =
199 case c of 199 case c of
200 L.CAnnot (c, k) => 200 L.CAnnot (c, k) =>
201 let 201 let
202 val k' = elabKind k 202 val k' = elabKind k
203 val (c', ck, gs) = elabCon (env, denv) c 203 val (c', ck, gs) = elabCon (env, denv) c
204 in 204 in
205 checkKind env c' ck k'; 205 checkKind env c' ck k';
206 (c', k', gs) 206 (c', k', gs)
207 end 207 end
208 208
209 | L.TFun (t1, t2) => 209 | L.TFun (t1, t2) =>
210 let 210 let
211 val (t1', k1, gs1) = elabCon (env, denv) t1 211 val (t1', k1, gs1) = elabCon (env, denv) t1
212 val (t2', k2, gs2) = elabCon (env, denv) t2 212 val (t2', k2, gs2) = elabCon (env, denv) t2
213 in 213 in
214 checkKind env t1' k1 ktype; 214 checkKind env t1' k1 ktype;
215 checkKind env t2' k2 ktype; 215 checkKind env t2' k2 ktype;
216 ((L'.TFun (t1', t2'), loc), ktype, gs1 @ gs2) 216 ((L'.TFun (t1', t2'), loc), ktype, gs1 @ gs2)
217 end 217 end
218 | L.TCFun (e, x, k, t) => 218 | L.TCFun (e, x, k, t) =>
219 let 219 let
220 val e' = elabExplicitness e 220 val e' = elabExplicitness e
221 val k' = elabKind k 221 val k' = elabKind k
222 val env' = E.pushCRel env x k' 222 val env' = E.pushCRel env x k'
223 val (t', tk, gs) = elabCon (env', D.enter denv) t 223 val (t', tk, gs) = elabCon (env', D.enter denv) t
224 in 224 in
225 checkKind env t' tk ktype; 225 checkKind env t' tk ktype;
226 ((L'.TCFun (e', x, k', t'), loc), ktype, gs) 226 ((L'.TCFun (e', x, k', t'), loc), ktype, gs)
227 end 227 end
228 | L.CDisjoint (c1, c2, c) => 228 | L.CDisjoint (c1, c2, c) =>
229 let 229 let
230 val (c1', k1, gs1) = elabCon (env, denv) c1 230 val (c1', k1, gs1) = elabCon (env, denv) c1
231 val (c2', k2, gs2) = elabCon (env, denv) c2 231 val (c2', k2, gs2) = elabCon (env, denv) c2
232 232
233 val ku1 = kunif loc 233 val ku1 = kunif loc
234 val ku2 = kunif loc 234 val ku2 = kunif loc
235 235
236 val (denv', gs3) = D.assert env denv (c1', c2') 236 val (denv', gs3) = D.assert env denv (c1', c2')
237 val (c', k, gs4) = elabCon (env, denv') c 237 val (c', k, gs4) = elabCon (env, denv') c
238 in 238 in
239 checkKind env c1' k1 (L'.KRecord ku1, loc); 239 checkKind env c1' k1 (L'.KRecord ku1, loc);
240 checkKind env c2' k2 (L'.KRecord ku2, loc); 240 checkKind env c2' k2 (L'.KRecord ku2, loc);
241 241
242 ((L'.CDisjoint (L'.Instantiate, c1', c2', c'), loc), k, gs1 @ gs2 @ gs3 @ gs4) 242 ((L'.CDisjoint (L'.Instantiate, c1', c2', c'), loc), k, gs1 @ gs2 @ gs3 @ gs4)
243 end 243 end
244 | L.TRecord c => 244 | L.TRecord c =>
245 let 245 let
246 val (c', ck, gs) = elabCon (env, denv) c 246 val (c', ck, gs) = elabCon (env, denv) c
247 val k = (L'.KRecord ktype, loc) 247 val k = (L'.KRecord ktype, loc)
248 in 248 in
249 checkKind env c' ck k; 249 checkKind env c' ck k;
250 ((L'.TRecord c', loc), ktype, gs) 250 ((L'.TRecord c', loc), ktype, gs)
251 end 251 end
252 252
253 | L.CVar ([], s) => 253 | L.CVar ([], s) =>
254 (case E.lookupC env s of 254 (case E.lookupC env s of
255 E.NotBound => 255 E.NotBound =>
256 (conError env (UnboundCon (loc, s)); 256 (conError env (UnboundCon (loc, s));
257 (cerror, kerror, [])) 257 (cerror, kerror, []))
258 | E.Rel (n, k) => 258 | E.Rel (n, k) =>
259 ((L'.CRel n, loc), k, []) 259 ((L'.CRel n, loc), k, [])
260 | E.Named (n, k) => 260 | E.Named (n, k) =>
261 ((L'.CNamed n, loc), k, [])) 261 ((L'.CNamed n, loc), k, []))
262 | L.CVar (m1 :: ms, s) => 262 | L.CVar (m1 :: ms, s) =>
263 (case E.lookupStr env m1 of 263 (case E.lookupStr env m1 of
264 NONE => (conError env (UnboundStrInCon (loc, m1)); 264 NONE => (conError env (UnboundStrInCon (loc, m1));
265 (cerror, kerror, []))
266 | SOME (n, sgn) =>
267 let
268 val (str, sgn) = foldl (fn (m, (str, sgn)) =>
269 case E.projectStr env {sgn = sgn, str = str, field = m} of
270 NONE => (conError env (UnboundStrInCon (loc, m));
271 (strerror, sgnerror))
272 | SOME sgn => ((L'.StrProj (str, m), loc), sgn))
273 ((L'.StrVar n, loc), sgn) ms
274
275 val k = case E.projectCon env {sgn = sgn, str = str, field = s} of
276 NONE => (conError env (UnboundCon (loc, s));
277 kerror)
278 | SOME (k, _) => k
279 in
280 ((L'.CModProj (n, ms, s), loc), k, [])
281 end)
282
283 | L.CApp (c1, c2) =>
284 let
285 val (c1', k1, gs1) = elabCon (env, denv) c1
286 val (c2', k2, gs2) = elabCon (env, denv) c2
287 val dom = kunif loc
288 val ran = kunif loc
289 in
290 checkKind env c1' k1 (L'.KArrow (dom, ran), loc);
291 checkKind env c2' k2 dom;
292 ((L'.CApp (c1', c2'), loc), ran, gs1 @ gs2)
293 end
294 | L.CAbs (x, ko, t) =>
295 let
296 val k' = case ko of
297 NONE => kunif loc
298 | SOME k => elabKind k
299 val env' = E.pushCRel env x k'
300 val (t', tk, gs) = elabCon (env', D.enter denv) t
301 in
302 ((L'.CAbs (x, k', t'), loc),
303 (L'.KArrow (k', tk), loc),
304 gs)
305 end
306
307 | L.CName s =>
308 ((L'.CName s, loc), kname, [])
309
310 | L.CRecord xcs =>
311 let
312 val k = kunif loc
313
314 val (xcs', gs) = ListUtil.foldlMap (fn ((x, c), gs) =>
315 let
316 val (x', xk, gs1) = elabCon (env, denv) x
317 val (c', ck, gs2) = elabCon (env, denv) c
318 in
319 checkKind env x' xk kname;
320 checkKind env c' ck k;
321 ((x', c'), gs1 @ gs2 @ gs)
322 end) [] xcs
323
324 val rc = (L'.CRecord (k, xcs'), loc)
325 (* Add duplicate field checking later. *)
326
327 fun prove (xcs, ds) =
328 case xcs of
329 [] => ds
330 | xc :: rest =>
331 let
332 val r1 = (L'.CRecord (k, [xc]), loc)
333 val ds = foldl (fn (xc', ds) =>
334 let
335 val r2 = (L'.CRecord (k, [xc']), loc)
336 in
337 D.prove env denv (r1, r2, loc) @ ds
338 end)
339 ds rest
340 in
341 prove (rest, ds)
342 end
343 in
344 (rc, (L'.KRecord k, loc), prove (xcs', gs))
345 end
346 | L.CConcat (c1, c2) =>
347 let
348 val (c1', k1, gs1) = elabCon (env, denv) c1
349 val (c2', k2, gs2) = elabCon (env, denv) c2
350 val ku = kunif loc
351 val k = (L'.KRecord ku, loc)
352 in
353 checkKind env c1' k1 k;
354 checkKind env c2' k2 k;
355 ((L'.CConcat (c1', c2'), loc), k,
356 D.prove env denv (c1', c2', loc) @ gs1 @ gs2)
357 end
358 | L.CFold =>
359 let
360 val dom = kunif loc
361 val ran = kunif loc
362 in
363 ((L'.CFold (dom, ran), loc),
364 foldKind (dom, ran, loc),
365 [])
366 end
367
368 | L.CUnit => ((L'.CUnit, loc), (L'.KUnit, loc), [])
369
370 | L.CTuple cs =>
371 let
372 val (cs', ks, gs) = foldl (fn (c, (cs', ks, gs)) =>
373 let
374 val (c', k, gs') = elabCon (env, denv) c
375 in
376 (c' :: cs', k :: ks, gs' @ gs)
377 end) ([], [], []) cs
378 in
379 ((L'.CTuple (rev cs'), loc), (L'.KTuple (rev ks), loc), gs)
380 end
381 | L.CProj (c, n) =>
382 let
383 val (c', k, gs) = elabCon (env, denv) c
384 in
385 case hnormKind k of
386 (L'.KTuple ks, _) =>
387 if n <= 0 orelse n > length ks then
388 (conError env (ProjBounds (c', n));
265 (cerror, kerror, [])) 389 (cerror, kerror, []))
266 | SOME (n, sgn) => 390 else
391 ((L'.CProj (c', n), loc), List.nth (ks, n - 1), gs)
392 | k => (conError env (ProjMismatch (c', k));
393 (cerror, kerror, []))
394 end
395
396 | L.CWild k =>
397 let
398 val k' = elabKind k
399 in
400 (cunif (loc, k'), k', [])
401 end
402
403 fun kunifsRemain k =
404 case k of
405 L'.KUnif (_, _, ref NONE) => true
406 | _ => false
407 fun cunifsRemain c =
408 case c of
409 L'.CUnif (loc, _, _, ref NONE) => SOME loc
410 | _ => NONE
411
412 val kunifsInDecl = U.Decl.exists {kind = kunifsRemain,
413 con = fn _ => false,
414 exp = fn _ => false,
415 sgn_item = fn _ => false,
416 sgn = fn _ => false,
417 str = fn _ => false,
418 decl = fn _ => false}
419
420 val cunifsInDecl = U.Decl.search {kind = fn _ => NONE,
421 con = cunifsRemain,
422 exp = fn _ => NONE,
423 sgn_item = fn _ => NONE,
424 sgn = fn _ => NONE,
425 str = fn _ => NONE,
426 decl = fn _ => NONE}
427
428 fun occursCon r =
429 U.Con.exists {kind = fn _ => false,
430 con = fn L'.CUnif (_, _, _, r') => r = r'
431 | _ => false}
432
433 exception CUnify' of cunify_error
434
435 exception SynUnif = E.SynUnif
436
437 open ElabOps
438
439 type record_summary = {
440 fields : (L'.con * L'.con) list,
441 unifs : (L'.con * L'.con option ref) list,
442 others : L'.con list
443 }
444
445 fun summaryToCon {fields, unifs, others} =
446 let
447 val c = (L'.CRecord (ktype, []), dummy)
448 val c = List.foldr (fn (c', c) => (L'.CConcat (c', c), dummy)) c others
449 val c = List.foldr (fn ((c', _), c) => (L'.CConcat (c', c), dummy)) c unifs
450 in
451 (L'.CConcat ((L'.CRecord (ktype, fields), dummy), c), dummy)
452 end
453
454 fun p_summary env s = p_con env (summaryToCon s)
455
456 exception CUnify of L'.con * L'.con * cunify_error
457
458 fun kindof env (c, loc) =
459 case c of
460 L'.TFun _ => ktype
461 | L'.TCFun _ => ktype
462 | L'.TRecord _ => ktype
463
464 | L'.CRel xn => #2 (E.lookupCRel env xn)
465 | L'.CNamed xn => #2 (E.lookupCNamed env xn)
466 | L'.CModProj (n, ms, x) =>
467 let
468 val (_, sgn) = E.lookupStrNamed env n
469 val (str, sgn) = foldl (fn (m, (str, sgn)) =>
470 case E.projectStr env {sgn = sgn, str = str, field = m} of
471 NONE => raise Fail "kindof: Unknown substructure"
472 | SOME sgn => ((L'.StrProj (str, m), loc), sgn))
473 ((L'.StrVar n, loc), sgn) ms
474 in
475 case E.projectCon env {sgn = sgn, str = str, field = x} of
476 NONE => raise Fail "kindof: Unknown con in structure"
477 | SOME (k, _) => k
478 end
479
480 | L'.CApp (c, _) =>
481 (case hnormKind (kindof env c) of
482 (L'.KArrow (_, k), _) => k
483 | (L'.KError, _) => kerror
484 | k => raise CUnify' (CKindof (k, c)))
485 | L'.CAbs (x, k, c) => (L'.KArrow (k, kindof (E.pushCRel env x k) c), loc)
486 | L'.CDisjoint (_, _, _, c) => kindof env c
487
488 | L'.CName _ => kname
489
490 | L'.CRecord (k, _) => (L'.KRecord k, loc)
491 | L'.CConcat (c, _) => kindof env c
492 | L'.CFold (dom, ran) => foldKind (dom, ran, loc)
493
494 | L'.CUnit => (L'.KUnit, loc)
495
496 | L'.CTuple cs => (L'.KTuple (map (kindof env) cs), loc)
497 | L'.CProj (c, n) =>
498 (case hnormKind (kindof env c) of
499 (L'.KTuple ks, _) => List.nth (ks, n - 1)
500 | k => raise CUnify' (CKindof (k, c)))
501
502 | L'.CError => kerror
503 | L'.CUnif (_, k, _, _) => k
504
505 val hnormCon = D.hnormCon
506
507 datatype con_summary =
508 Nil
509 | Cons
510 | Unknown
511
512 fun compatible cs =
513 case cs of
514 (Unknown, _) => false
515 | (_, Unknown) => false
516 | (s1, s2) => s1 = s2
517
518 fun summarizeCon (env, denv) c =
519 let
520 val (c, gs) = hnormCon (env, denv) c
521 in
522 case #1 c of
523 L'.CRecord (_, []) => (Nil, gs)
524 | L'.CRecord (_, _ :: _) => (Cons, gs)
525 | L'.CConcat ((L'.CRecord (_, _ :: _), _), _) => (Cons, gs)
526 | L'.CDisjoint (_, _, _, c) =>
267 let 527 let
268 val (str, sgn) = foldl (fn (m, (str, sgn)) => 528 val (s, gs') = summarizeCon (env, denv) c
269 case E.projectStr env {sgn = sgn, str = str, field = m} of
270 NONE => (conError env (UnboundStrInCon (loc, m));
271 (strerror, sgnerror))
272 | SOME sgn => ((L'.StrProj (str, m), loc), sgn))
273 ((L'.StrVar n, loc), sgn) ms
274
275 val k = case E.projectCon env {sgn = sgn, str = str, field = s} of
276 NONE => (conError env (UnboundCon (loc, s));
277 kerror)
278 | SOME (k, _) => k
279 in 529 in
280 ((L'.CModProj (n, ms, s), loc), k, []) 530 (s, gs @ gs')
281 end) 531 end
282 532 | _ => (Unknown, gs)
283 | L.CApp (c1, c2) => 533 end
284 let 534
285 val (c1', k1, gs1) = elabCon (env, denv) c1 535 fun p_con_summary s =
286 val (c2', k2, gs2) = elabCon (env, denv) c2 536 Print.PD.string (case s of
287 val dom = kunif loc 537 Nil => "Nil"
288 val ran = kunif loc 538 | Cons => "Cons"
289 in 539 | Unknown => "Unknown")
290 checkKind env c1' k1 (L'.KArrow (dom, ran), loc); 540
291 checkKind env c2' k2 dom; 541 exception SummaryFailure
292 ((L'.CApp (c1', c2'), loc), ran, gs1 @ gs2) 542
293 end 543 fun unifyRecordCons (env, denv) (c1, c2) =
294 | L.CAbs (x, ko, t) => 544 let
295 let 545 fun rkindof c =
296 val k' = case ko of 546 case hnormKind (kindof env c) of
297 NONE => kunif loc 547 (L'.KRecord k, _) => k
298 | SOME k => elabKind k 548 | (L'.KError, _) => kerror
299 val env' = E.pushCRel env x k' 549 | k => raise CUnify' (CKindof (k, c))
300 val (t', tk, gs) = elabCon (env', D.enter denv) t 550
301 in 551 val k1 = rkindof c1
302 ((L'.CAbs (x, k', t'), loc), 552 val k2 = rkindof c2
303 (L'.KArrow (k', tk), loc), 553
304 gs) 554 val (r1, gs1) = recordSummary (env, denv) c1
305 end 555 val (r2, gs2) = recordSummary (env, denv) c2
306 556 in
307 | L.CName s => 557 unifyKinds k1 k2;
308 ((L'.CName s, loc), kname, []) 558 unifySummaries (env, denv) (k1, r1, r2);
309 559 gs1 @ gs2
310 | L.CRecord xcs => 560 end
311 let 561
312 val k = kunif loc 562 and recordSummary (env, denv) c =
313 563 let
314 val (xcs', gs) = ListUtil.foldlMap (fn ((x, c), gs) => 564 val (c, gs) = hnormCon (env, denv) c
315 let 565
316 val (x', xk, gs1) = elabCon (env, denv) x 566 val (sum, gs') =
317 val (c', ck, gs2) = elabCon (env, denv) c 567 case c of
318 in 568 (L'.CRecord (_, xcs), _) => ({fields = xcs, unifs = [], others = []}, [])
319 checkKind env x' xk kname; 569 | (L'.CConcat (c1, c2), _) =>
320 checkKind env c' ck k; 570 let
321 ((x', c'), gs1 @ gs2 @ gs) 571 val (s1, gs1) = recordSummary (env, denv) c1
322 end) [] xcs 572 val (s2, gs2) = recordSummary (env, denv) c2
323 573 in
324 val rc = (L'.CRecord (k, xcs'), loc) 574 ({fields = #fields s1 @ #fields s2,
325 (* Add duplicate field checking later. *) 575 unifs = #unifs s1 @ #unifs s2,
326 576 others = #others s1 @ #others s2},
327 fun prove (xcs, ds) = 577 gs1 @ gs2)
328 case xcs of 578 end
329 [] => ds 579 | (L'.CUnif (_, _, _, ref (SOME c)), _) => recordSummary (env, denv) c
330 | xc :: rest => 580 | c' as (L'.CUnif (_, _, _, r), _) => ({fields = [], unifs = [(c', r)], others = []}, [])
331 let 581 | c' => ({fields = [], unifs = [], others = [c']}, [])
332 val r1 = (L'.CRecord (k, [xc]), loc) 582 in
333 val ds = foldl (fn (xc', ds) => 583 (sum, gs @ gs')
334 let 584 end
335 val r2 = (L'.CRecord (k, [xc']), loc) 585
336 in 586 and consEq (env, denv) (c1, c2) =
337 D.prove env denv (r1, r2, loc) @ ds 587 let
338 end) 588 val gs = unifyCons (env, denv) c1 c2
339 ds rest 589 in
340 in 590 List.all (fn (loc, env, denv, c1, c2) =>
341 prove (rest, ds) 591 case D.prove env denv (c1, c2, loc) of
342 end 592 [] => true
343 in 593 | _ => false) gs
344 (rc, (L'.KRecord k, loc), prove (xcs', gs)) 594 end
345 end 595 handle CUnify _ => false
346 | L.CConcat (c1, c2) => 596
347 let 597 and consNeq env (c1, c2) =
348 val (c1', k1, gs1) = elabCon (env, denv) c1 598 case (#1 (ElabOps.hnormCon env c1), #1 (ElabOps.hnormCon env c2)) of
349 val (c2', k2, gs2) = elabCon (env, denv) c2 599 (L'.CName x1, L'.CName x2) => x1 <> x2
350 val ku = kunif loc 600 | _ => false
351 val k = (L'.KRecord ku, loc) 601
352 in 602 and unifySummaries (env, denv) (k, s1 : record_summary, s2 : record_summary) =
353 checkKind env c1' k1 k; 603 let
354 checkKind env c2' k2 k; 604 val loc = #2 k
355 ((L'.CConcat (c1', c2'), loc), k, 605 (*val () = eprefaces "Summaries" [("#1", p_summary env s1),
356 D.prove env denv (c1', c2', loc) @ gs1 @ gs2) 606 ("#2", p_summary env s2)]*)
357 end 607
358 | L.CFold => 608 fun eatMatching p (ls1, ls2) =
359 let 609 let
360 val dom = kunif loc 610 fun em (ls1, ls2, passed1) =
361 val ran = kunif loc 611 case ls1 of
362 in 612 [] => (rev passed1, ls2)
363 ((L'.CFold (dom, ran), loc), 613 | h1 :: t1 =>
364 foldKind (dom, ran, loc), 614 let
615 fun search (ls2', passed2) =
616 case ls2' of
617 [] => em (t1, ls2, h1 :: passed1)
618 | h2 :: t2 =>
619 if p (h1, h2) then
620 em (t1, List.revAppend (passed2, t2), passed1)
621 else
622 search (t2, h2 :: passed2)
623 in
624 search (ls2, [])
625 end
626 in
627 em (ls1, ls2, [])
628 end
629
630 val (fs1, fs2) = eatMatching (fn ((x1, c1), (x2, c2)) =>
631 not (consNeq env (x1, x2))
632 andalso consEq (env, denv) (c1, c2)
633 andalso consEq (env, denv) (x1, x2))
634 (#fields s1, #fields s2)
635 (*val () = eprefaces "Summaries2" [("#1", p_summary env {fields = fs1, unifs = #unifs s1, others = #others s1}),
636 ("#2", p_summary env {fields = fs2, unifs = #unifs s2, others = #others s2})]*)
637 val (unifs1, unifs2) = eatMatching (fn ((_, r1), (_, r2)) => r1 = r2) (#unifs s1, #unifs s2)
638 val (others1, others2) = eatMatching (consEq (env, denv)) (#others s1, #others s2)
639 (*val () = eprefaces "Summaries3" [("#1", p_summary env {fields = fs1, unifs = unifs1, others = others1}),
640 ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*)
641
642 fun unifFields (fs, others, unifs) =
643 case (fs, others, unifs) of
644 ([], [], _) => ([], [], unifs)
645 | (_, _, []) => (fs, others, [])
646 | (_, _, (_, r) :: rest) =>
647 let
648 val r' = ref NONE
649 val kr = (L'.KRecord k, dummy)
650 val cr' = (L'.CUnif (dummy, kr, "recd", r'), dummy)
651
652 val prefix = case (fs, others) of
653 ([], other :: others) =>
654 List.foldl (fn (other, c) =>
655 (L'.CConcat (c, other), dummy))
656 other others
657 | (fs, []) =>
658 (L'.CRecord (k, fs), dummy)
659 | (fs, others) =>
660 List.foldl (fn (other, c) =>
661 (L'.CConcat (c, other), dummy))
662 (L'.CRecord (k, fs), dummy) others
663 in
664 r := SOME (L'.CConcat (prefix, cr'), dummy);
665 ([], [], (cr', r') :: rest)
666 end
667
668 val (fs1, others1, unifs2) = unifFields (fs1, others1, unifs2)
669 val (fs2, others2, unifs1) = unifFields (fs2, others2, unifs1)
670
671 (*val () = eprefaces "Summaries4" [("#1", p_summary env {fields = fs1, unifs = unifs1, others = others1}),
672 ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*)
673
674 fun isGuessable (other, fs) =
675 let
676 val gs = guessFold (env, denv) (other, (L'.CRecord (k, fs), loc), [], SummaryFailure)
677 in
678 List.all (fn (loc, env, denv, c1, c2) =>
679 case D.prove env denv (c1, c2, loc) of
680 [] => true
681 | _ => false) gs
682 end
683 handle SummaryFailure => false
684
685 val (fs1, fs2, others1, others2) =
686 case (fs1, fs2, others1, others2) of
687 ([], _, [other1], []) =>
688 if isGuessable (other1, fs2) then
689 ([], [], [], [])
690 else
691 (fs1, fs2, others1, others2)
692 | (_, [], [], [other2]) =>
693 if isGuessable (other2, fs1) then
694 ([], [], [], [])
695 else
696 (fs1, fs2, others1, others2)
697 | _ => (fs1, fs2, others1, others2)
698
699 (*val () = eprefaces "Summaries5" [("#1", p_summary env {fields = fs1, unifs = unifs1, others = others1}),
700 ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*)
701
702 val clear = case (fs1, others1, fs2, others2) of
703 ([], [], [], []) => true
704 | _ => false
705 val empty = (L'.CRecord (k, []), dummy)
706
707 fun unsummarize {fields, unifs, others} =
708 let
709 val c = (L'.CRecord (k, fields), loc)
710
711 val c = foldl (fn ((c1, _), c2) => (L'.CConcat (c1, c2), loc))
712 c unifs
713 in
714 foldl (fn (c1, c2) => (L'.CConcat (c1, c2), loc))
715 c others
716 end
717
718 fun pairOffUnifs (unifs1, unifs2) =
719 case (unifs1, unifs2) of
720 ([], _) =>
721 if clear then
722 List.app (fn (_, r) => r := SOME empty) unifs2
723 else
724 raise CUnify' (CRecordFailure (unsummarize s1, unsummarize s2))
725 | (_, []) =>
726 if clear then
727 List.app (fn (_, r) => r := SOME empty) unifs1
728 else
729 raise CUnify' (CRecordFailure (unsummarize s1, unsummarize s2))
730 | ((c1, _) :: rest1, (_, r2) :: rest2) =>
731 (r2 := SOME c1;
732 pairOffUnifs (rest1, rest2))
733 in
734 pairOffUnifs (unifs1, unifs2)
735 (*before eprefaces "Summaries'" [("#1", p_summary env s1),
736 ("#2", p_summary env s2)]*)
737 end
738
739 and guessFold (env, denv) (c1, c2, gs, ex) =
740 let
741 val loc = #2 c1
742
743 fun unfold (dom, ran, f, i, r, c) =
744 let
745 val nm = cunif (loc, (L'.KName, loc))
746 val v = cunif (loc, dom)
747 val rest = cunif (loc, (L'.KRecord dom, loc))
748 val acc = (L'.CFold (dom, ran), loc)
749 val acc = (L'.CApp (acc, f), loc)
750 val acc = (L'.CApp (acc, i), loc)
751 val acc = (L'.CApp (acc, rest), loc)
752
753 val (iS, gs3) = summarizeCon (env, denv) i
754
755 val app = (L'.CApp (f, nm), loc)
756 val app = (L'.CApp (app, v), loc)
757 val app = (L'.CApp (app, acc), loc)
758 val (appS, gs4) = summarizeCon (env, denv) app
759
760 val (cS, gs5) = summarizeCon (env, denv) c
761 in
762 (*prefaces "Summaries" [("iS", p_con_summary iS),
763 ("appS", p_con_summary appS),
764 ("cS", p_con_summary cS)];*)
765
766 if compatible (iS, appS) then
767 raise ex
768 else if compatible (cS, iS) then
769 let
770 (*val () = prefaces "Same?" [("i", p_con env i),
771 ("c", p_con env c)]*)
772 val gs6 = unifyCons (env, denv) i c
773 (*val () = TextIO.print "Yes!\n"*)
774
775 val gs7 = unifyCons (env, denv) r (L'.CRecord (dom, []), loc)
776 in
777 gs @ gs3 @ gs5 @ gs6 @ gs7
778 end
779 else if compatible (cS, appS) then
780 let
781 (*val () = prefaces "Same?" [("app", p_con env app),
782 ("c", p_con env c),
783 ("app'", p_con env (#1 (hnormCon (env, denv) app)))]*)
784 val gs6 = unifyCons (env, denv) app c
785 (*val () = TextIO.print "Yes!\n"*)
786
787 val singleton = (L'.CRecord (dom, [(nm, v)]), loc)
788 val concat = (L'.CConcat (singleton, rest), loc)
789 (*val () = prefaces "Pre-crew" [("r", p_con env r),
790 ("concat", p_con env concat)]*)
791 val gs7 = unifyCons (env, denv) r concat
792 in
793 (*prefaces "The crew" [("nm", p_con env nm),
794 ("v", p_con env v),
795 ("rest", p_con env rest)];*)
796
797 gs @ gs3 @ gs4 @ gs5 @ gs6 @ gs7
798 end
799 else
800 raise ex
801 end
802 handle _ => raise ex
803 in
804 case (#1 c1, #1 c2) of
805 (L'.CApp ((L'.CApp ((L'.CApp ((L'.CFold (dom, ran), _), f), _), i), _), r), _) =>
806 unfold (dom, ran, f, i, r, c2)
807 | (_, L'.CApp ((L'.CApp ((L'.CApp ((L'.CFold (dom, ran), _), f), _), i), _), r)) =>
808 unfold (dom, ran, f, i, r, c1)
809 | _ => raise ex
810 end
811
812 and unifyCons' (env, denv) c1 c2 =
813 case (#1 c1, #1 c2) of
814 (L'.CDisjoint (_, x1, y1, t1), L'.CDisjoint (_, x2, y2, t2)) =>
815 let
816 val gs1 = unifyCons' (env, denv) x1 x2
817 val gs2 = unifyCons' (env, denv) y1 y2
818 val (denv', gs3) = D.assert env denv (x1, y1)
819 val gs4 = unifyCons' (env, denv') t1 t2
820 in
821 gs1 @ gs2 @ gs3 @ gs4
822 end
823 | _ =>
824 let
825 val (c1, gs1) = hnormCon (env, denv) c1
826 val (c2, gs2) = hnormCon (env, denv) c2
827 in
828 let
829 val gs3 = unifyCons'' (env, denv) c1 c2
830 in
831 gs1 @ gs2 @ gs3
832 end
833 handle ex => guessFold (env, denv) (c1, c2, gs1 @ gs2, ex)
834 end
835
836 and unifyCons'' (env, denv) (c1All as (c1, loc)) (c2All as (c2, _)) =
837 let
838 fun err f = raise CUnify' (f (c1All, c2All))
839
840 fun isRecord () = unifyRecordCons (env, denv) (c1All, c2All)
841 in
842 (*eprefaces "unifyCons''" [("c1All", p_con env c1All),
843 ("c2All", p_con env c2All)];*)
844
845 case (c1, c2) of
846 (L'.CUnit, L'.CUnit) => []
847
848 | (L'.TFun (d1, r1), L'.TFun (d2, r2)) =>
849 unifyCons' (env, denv) d1 d2
850 @ unifyCons' (env, denv) r1 r2
851 | (L'.TCFun (expl1, x1, d1, r1), L'.TCFun (expl2, _, d2, r2)) =>
852 if expl1 <> expl2 then
853 err CExplicitness
854 else
855 (unifyKinds d1 d2;
856 unifyCons' (E.pushCRel env x1 d1, D.enter denv) r1 r2)
857 | (L'.TRecord r1, L'.TRecord r2) => unifyCons' (env, denv) r1 r2
858
859 | (L'.CRel n1, L'.CRel n2) =>
860 if n1 = n2 then
861 []
862 else
863 err CIncompatible
864 | (L'.CNamed n1, L'.CNamed n2) =>
865 if n1 = n2 then
866 []
867 else
868 err CIncompatible
869
870 | (L'.CApp (d1, r1), L'.CApp (d2, r2)) =>
871 (unifyCons' (env, denv) d1 d2;
872 unifyCons' (env, denv) r1 r2)
873 | (L'.CAbs (x1, k1, c1), L'.CAbs (_, k2, c2)) =>
874 (unifyKinds k1 k2;
875 unifyCons' (E.pushCRel env x1 k1, D.enter denv) c1 c2)
876
877 | (L'.CName n1, L'.CName n2) =>
878 if n1 = n2 then
879 []
880 else
881 err CIncompatible
882
883 | (L'.CModProj (n1, ms1, x1), L'.CModProj (n2, ms2, x2)) =>
884 if n1 = n2 andalso ms1 = ms2 andalso x1 = x2 then
885 []
886 else
887 err CIncompatible
888
889 | (L'.CTuple cs1, L'.CTuple cs2) =>
890 ((ListPair.foldlEq (fn (c1, c2, gs) =>
891 let
892 val gs' = unifyCons' (env, denv) c1 c2
893 in
894 gs' @ gs
895 end) [] (cs1, cs2))
896 handle ListPair.UnequalLengths => err CIncompatible)
897
898 | (L'.CProj ((L'.CUnif (_, _, _, ref (SOME c1)), loc), n1), _) =>
899 unifyCons' (env, denv) (L'.CProj (c1, n1), loc) c2All
900 | (_, L'.CProj ((L'.CUnif (_, _, _, ref (SOME c2)), loc), n2)) =>
901 unifyCons' (env, denv) c1All (L'.CProj (c2, n2), loc)
902 | (L'.CProj ((L'.CUnif (_, (L'.KTuple ks, _), _, r), loc), n), _) =>
903 let
904 val us = map (fn k => cunif (loc, k)) ks
905 in
906 r := SOME (L'.CTuple us, loc);
907 unifyCons' (env, denv) (List.nth (us, n - 1)) c2All
908 end
909 | (_, L'.CProj ((L'.CUnif (_, (L'.KTuple ks, _), _, r), loc), n)) =>
910 let
911 val us = map (fn k => cunif (loc, k)) ks
912 in
913 r := SOME (L'.CTuple us, loc);
914 unifyCons' (env, denv) c1All (List.nth (us, n - 1))
915 end
916 | (L'.CProj (c1, n1), L'.CProj (c2, n2)) =>
917 if n1 = n2 then
918 unifyCons' (env, denv) c1 c2
919 else
920 err CIncompatible
921
922 | (L'.CError, _) => []
923 | (_, L'.CError) => []
924
925 | (L'.CRecord _, _) => isRecord ()
926 | (_, L'.CRecord _) => isRecord ()
927 | (L'.CConcat _, _) => isRecord ()
928 | (_, L'.CConcat _) => isRecord ()
929
930 | (L'.CUnif (_, k1, _, r1), L'.CUnif (_, k2, _, r2)) =>
931 if r1 = r2 then
932 []
933 else
934 (unifyKinds k1 k2;
935 r1 := SOME c2All;
936 [])
937
938 | (L'.CUnif (_, _, _, r), _) =>
939 if occursCon r c2All then
940 err COccursCheckFailed
941 else
942 (r := SOME c2All;
943 [])
944 | (_, L'.CUnif (_, _, _, r)) =>
945 if occursCon r c1All then
946 err COccursCheckFailed
947 else
948 (r := SOME c1All;
949 [])
950
951 | (L'.CFold (dom1, ran1), L'.CFold (dom2, ran2)) =>
952 (unifyKinds dom1 dom2;
953 unifyKinds ran1 ran2;
954 [])
955
956 | _ => err CIncompatible
957 end
958
959 and unifyCons (env, denv) c1 c2 =
960 unifyCons' (env, denv) c1 c2
961 handle CUnify' err => raise CUnify (c1, c2, err)
962 | KUnify args => raise CUnify (c1, c2, CKind args)
963
964 fun checkCon (env, denv) e c1 c2 =
965 unifyCons (env, denv) c1 c2
966 handle CUnify (c1, c2, err) =>
967 (expError env (Unify (e, c1, c2, err));
365 []) 968 [])
366 end 969
367 970 fun checkPatCon (env, denv) p c1 c2 =
368 | L.CUnit => ((L'.CUnit, loc), (L'.KUnit, loc), []) 971 unifyCons (env, denv) c1 c2
369 972 handle CUnify (c1, c2, err) =>
370 | L.CTuple cs => 973 (expError env (PatUnify (p, c1, c2, err));
371 let
372 val (cs', ks, gs) = foldl (fn (c, (cs', ks, gs)) =>
373 let
374 val (c', k, gs') = elabCon (env, denv) c
375 in
376 (c' :: cs', k :: ks, gs' @ gs)
377 end) ([], [], []) cs
378 in
379 ((L'.CTuple (rev cs'), loc), (L'.KTuple (rev ks), loc), gs)
380 end
381 | L.CProj (c, n) =>
382 let
383 val (c', k, gs) = elabCon (env, denv) c
384 in
385 case hnormKind k of
386 (L'.KTuple ks, _) =>
387 if n <= 0 orelse n > length ks then
388 (conError env (ProjBounds (c', n));
389 (cerror, kerror, []))
390 else
391 ((L'.CProj (c', n), loc), List.nth (ks, n - 1), gs)
392 | k => (conError env (ProjMismatch (c', k));
393 (cerror, kerror, []))
394 end
395
396 | L.CWild k =>
397 let
398 val k' = elabKind k
399 in
400 (cunif (loc, k'), k', [])
401 end
402
403 fun kunifsRemain k =
404 case k of
405 L'.KUnif (_, _, ref NONE) => true
406 | _ => false
407 fun cunifsRemain c =
408 case c of
409 L'.CUnif (loc, _, _, ref NONE) => SOME loc
410 | _ => NONE
411
412 val kunifsInDecl = U.Decl.exists {kind = kunifsRemain,
413 con = fn _ => false,
414 exp = fn _ => false,
415 sgn_item = fn _ => false,
416 sgn = fn _ => false,
417 str = fn _ => false,
418 decl = fn _ => false}
419
420 val cunifsInDecl = U.Decl.search {kind = fn _ => NONE,
421 con = cunifsRemain,
422 exp = fn _ => NONE,
423 sgn_item = fn _ => NONE,
424 sgn = fn _ => NONE,
425 str = fn _ => NONE,
426 decl = fn _ => NONE}
427
428 fun occursCon r =
429 U.Con.exists {kind = fn _ => false,
430 con = fn L'.CUnif (_, _, _, r') => r = r'
431 | _ => false}
432
433 exception CUnify' of cunify_error
434
435 exception SynUnif = E.SynUnif
436
437 open ElabOps
438
439 type record_summary = {
440 fields : (L'.con * L'.con) list,
441 unifs : (L'.con * L'.con option ref) list,
442 others : L'.con list
443 }
444
445 fun summaryToCon {fields, unifs, others} =
446 let
447 val c = (L'.CRecord (ktype, []), dummy)
448 val c = List.foldr (fn (c', c) => (L'.CConcat (c', c), dummy)) c others
449 val c = List.foldr (fn ((c', _), c) => (L'.CConcat (c', c), dummy)) c unifs
450 in
451 (L'.CConcat ((L'.CRecord (ktype, fields), dummy), c), dummy)
452 end
453
454 fun p_summary env s = p_con env (summaryToCon s)
455
456 exception CUnify of L'.con * L'.con * cunify_error
457
458 fun kindof env (c, loc) =
459 case c of
460 L'.TFun _ => ktype
461 | L'.TCFun _ => ktype
462 | L'.TRecord _ => ktype
463
464 | L'.CRel xn => #2 (E.lookupCRel env xn)
465 | L'.CNamed xn => #2 (E.lookupCNamed env xn)
466 | L'.CModProj (n, ms, x) =>
467 let
468 val (_, sgn) = E.lookupStrNamed env n
469 val (str, sgn) = foldl (fn (m, (str, sgn)) =>
470 case E.projectStr env {sgn = sgn, str = str, field = m} of
471 NONE => raise Fail "kindof: Unknown substructure"
472 | SOME sgn => ((L'.StrProj (str, m), loc), sgn))
473 ((L'.StrVar n, loc), sgn) ms
474 in
475 case E.projectCon env {sgn = sgn, str = str, field = x} of
476 NONE => raise Fail "kindof: Unknown con in structure"
477 | SOME (k, _) => k
478 end
479
480 | L'.CApp (c, _) =>
481 (case hnormKind (kindof env c) of
482 (L'.KArrow (_, k), _) => k
483 | (L'.KError, _) => kerror
484 | k => raise CUnify' (CKindof (k, c)))
485 | L'.CAbs (x, k, c) => (L'.KArrow (k, kindof (E.pushCRel env x k) c), loc)
486 | L'.CDisjoint (_, _, _, c) => kindof env c
487
488 | L'.CName _ => kname
489
490 | L'.CRecord (k, _) => (L'.KRecord k, loc)
491 | L'.CConcat (c, _) => kindof env c
492 | L'.CFold (dom, ran) => foldKind (dom, ran, loc)
493
494 | L'.CUnit => (L'.KUnit, loc)
495
496 | L'.CTuple cs => (L'.KTuple (map (kindof env) cs), loc)
497 | L'.CProj (c, n) =>
498 (case hnormKind (kindof env c) of
499 (L'.KTuple ks, _) => List.nth (ks, n - 1)
500 | k => raise CUnify' (CKindof (k, c)))
501
502 | L'.CError => kerror
503 | L'.CUnif (_, k, _, _) => k
504
505 val hnormCon = D.hnormCon
506
507 datatype con_summary =
508 Nil
509 | Cons
510 | Unknown
511
512 fun compatible cs =
513 case cs of
514 (Unknown, _) => false
515 | (_, Unknown) => false
516 | (s1, s2) => s1 = s2
517
518 fun summarizeCon (env, denv) c =
519 let
520 val (c, gs) = hnormCon (env, denv) c
521 in
522 case #1 c of
523 L'.CRecord (_, []) => (Nil, gs)
524 | L'.CRecord (_, _ :: _) => (Cons, gs)
525 | L'.CConcat ((L'.CRecord (_, _ :: _), _), _) => (Cons, gs)
526 | L'.CDisjoint (_, _, _, c) =>
527 let
528 val (s, gs') = summarizeCon (env, denv) c
529 in
530 (s, gs @ gs')
531 end
532 | _ => (Unknown, gs)
533 end
534
535 fun p_con_summary s =
536 Print.PD.string (case s of
537 Nil => "Nil"
538 | Cons => "Cons"
539 | Unknown => "Unknown")
540
541 exception SummaryFailure
542
543 fun unifyRecordCons (env, denv) (c1, c2) =
544 let
545 fun rkindof c =
546 case hnormKind (kindof env c) of
547 (L'.KRecord k, _) => k
548 | (L'.KError, _) => kerror
549 | k => raise CUnify' (CKindof (k, c))
550
551 val k1 = rkindof c1
552 val k2 = rkindof c2
553
554 val (r1, gs1) = recordSummary (env, denv) c1
555 val (r2, gs2) = recordSummary (env, denv) c2
556 in
557 unifyKinds k1 k2;
558 unifySummaries (env, denv) (k1, r1, r2);
559 gs1 @ gs2
560 end
561
562 and recordSummary (env, denv) c =
563 let
564 val (c, gs) = hnormCon (env, denv) c
565
566 val (sum, gs') =
567 case c of
568 (L'.CRecord (_, xcs), _) => ({fields = xcs, unifs = [], others = []}, [])
569 | (L'.CConcat (c1, c2), _) =>
570 let
571 val (s1, gs1) = recordSummary (env, denv) c1
572 val (s2, gs2) = recordSummary (env, denv) c2
573 in
574 ({fields = #fields s1 @ #fields s2,
575 unifs = #unifs s1 @ #unifs s2,
576 others = #others s1 @ #others s2},
577 gs1 @ gs2)
578 end
579 | (L'.CUnif (_, _, _, ref (SOME c)), _) => recordSummary (env, denv) c
580 | c' as (L'.CUnif (_, _, _, r), _) => ({fields = [], unifs = [(c', r)], others = []}, [])
581 | c' => ({fields = [], unifs = [], others = [c']}, [])
582 in
583 (sum, gs @ gs')
584 end
585
586 and consEq (env, denv) (c1, c2) =
587 let
588 val gs = unifyCons (env, denv) c1 c2
589 in
590 List.all (fn (loc, env, denv, c1, c2) =>
591 case D.prove env denv (c1, c2, loc) of
592 [] => true
593 | _ => false) gs
594 end
595 handle CUnify _ => false
596
597 and consNeq env (c1, c2) =
598 case (#1 (ElabOps.hnormCon env c1), #1 (ElabOps.hnormCon env c2)) of
599 (L'.CName x1, L'.CName x2) => x1 <> x2
600 | _ => false
601
602 and unifySummaries (env, denv) (k, s1 : record_summary, s2 : record_summary) =
603 let
604 val loc = #2 k
605 (*val () = eprefaces "Summaries" [("#1", p_summary env s1),
606 ("#2", p_summary env s2)]*)
607
608 fun eatMatching p (ls1, ls2) =
609 let
610 fun em (ls1, ls2, passed1) =
611 case ls1 of
612 [] => (rev passed1, ls2)
613 | h1 :: t1 =>
614 let
615 fun search (ls2', passed2) =
616 case ls2' of
617 [] => em (t1, ls2, h1 :: passed1)
618 | h2 :: t2 =>
619 if p (h1, h2) then
620 em (t1, List.revAppend (passed2, t2), passed1)
621 else
622 search (t2, h2 :: passed2)
623 in
624 search (ls2, [])
625 end
626 in
627 em (ls1, ls2, [])
628 end
629
630 val (fs1, fs2) = eatMatching (fn ((x1, c1), (x2, c2)) =>
631 not (consNeq env (x1, x2))
632 andalso consEq (env, denv) (c1, c2)
633 andalso consEq (env, denv) (x1, x2))
634 (#fields s1, #fields s2)
635 (*val () = eprefaces "Summaries2" [("#1", p_summary env {fields = fs1, unifs = #unifs s1, others = #others s1}),
636 ("#2", p_summary env {fields = fs2, unifs = #unifs s2, others = #others s2})]*)
637 val (unifs1, unifs2) = eatMatching (fn ((_, r1), (_, r2)) => r1 = r2) (#unifs s1, #unifs s2)
638 val (others1, others2) = eatMatching (consEq (env, denv)) (#others s1, #others s2)
639 (*val () = eprefaces "Summaries3" [("#1", p_summary env {fields = fs1, unifs = unifs1, others = others1}),
640 ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*)
641
642 fun unifFields (fs, others, unifs) =
643 case (fs, others, unifs) of
644 ([], [], _) => ([], [], unifs)
645 | (_, _, []) => (fs, others, [])
646 | (_, _, (_, r) :: rest) =>
647 let
648 val r' = ref NONE
649 val kr = (L'.KRecord k, dummy)
650 val cr' = (L'.CUnif (dummy, kr, "recd", r'), dummy)
651
652 val prefix = case (fs, others) of
653 ([], other :: others) =>
654 List.foldl (fn (other, c) =>
655 (L'.CConcat (c, other), dummy))
656 other others
657 | (fs, []) =>
658 (L'.CRecord (k, fs), dummy)
659 | (fs, others) =>
660 List.foldl (fn (other, c) =>
661 (L'.CConcat (c, other), dummy))
662 (L'.CRecord (k, fs), dummy) others
663 in
664 r := SOME (L'.CConcat (prefix, cr'), dummy);
665 ([], [], (cr', r') :: rest)
666 end
667
668 val (fs1, others1, unifs2) = unifFields (fs1, others1, unifs2)
669 val (fs2, others2, unifs1) = unifFields (fs2, others2, unifs1)
670
671 (*val () = eprefaces "Summaries4" [("#1", p_summary env {fields = fs1, unifs = unifs1, others = others1}),
672 ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*)
673
674 fun isGuessable (other, fs) =
675 let
676 val gs = guessFold (env, denv) (other, (L'.CRecord (k, fs), loc), [], SummaryFailure)
677 in
678 List.all (fn (loc, env, denv, c1, c2) =>
679 case D.prove env denv (c1, c2, loc) of
680 [] => true
681 | _ => false) gs
682 end
683 handle SummaryFailure => false
684
685 val (fs1, fs2, others1, others2) =
686 case (fs1, fs2, others1, others2) of
687 ([], _, [other1], []) =>
688 if isGuessable (other1, fs2) then
689 ([], [], [], [])
690 else
691 (fs1, fs2, others1, others2)
692 | (_, [], [], [other2]) =>
693 if isGuessable (other2, fs1) then
694 ([], [], [], [])
695 else
696 (fs1, fs2, others1, others2)
697 | _ => (fs1, fs2, others1, others2)
698
699 (*val () = eprefaces "Summaries5" [("#1", p_summary env {fields = fs1, unifs = unifs1, others = others1}),
700 ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*)
701
702 val clear = case (fs1, others1, fs2, others2) of
703 ([], [], [], []) => true
704 | _ => false
705 val empty = (L'.CRecord (k, []), dummy)
706
707 fun unsummarize {fields, unifs, others} =
708 let
709 val c = (L'.CRecord (k, fields), loc)
710
711 val c = foldl (fn ((c1, _), c2) => (L'.CConcat (c1, c2), loc))
712 c unifs
713 in
714 foldl (fn (c1, c2) => (L'.CConcat (c1, c2), loc))
715 c others
716 end
717
718 fun pairOffUnifs (unifs1, unifs2) =
719 case (unifs1, unifs2) of
720 ([], _) =>
721 if clear then
722 List.app (fn (_, r) => r := SOME empty) unifs2
723 else
724 raise CUnify' (CRecordFailure (unsummarize s1, unsummarize s2))
725 | (_, []) =>
726 if clear then
727 List.app (fn (_, r) => r := SOME empty) unifs1
728 else
729 raise CUnify' (CRecordFailure (unsummarize s1, unsummarize s2))
730 | ((c1, _) :: rest1, (_, r2) :: rest2) =>
731 (r2 := SOME c1;
732 pairOffUnifs (rest1, rest2))
733 in
734 pairOffUnifs (unifs1, unifs2)
735 (*before eprefaces "Summaries'" [("#1", p_summary env s1),
736 ("#2", p_summary env s2)]*)
737 end
738
739 and guessFold (env, denv) (c1, c2, gs, ex) =
740 let
741 val loc = #2 c1
742
743 fun unfold (dom, ran, f, i, r, c) =
744 let
745 val nm = cunif (loc, (L'.KName, loc))
746 val v = cunif (loc, dom)
747 val rest = cunif (loc, (L'.KRecord dom, loc))
748 val acc = (L'.CFold (dom, ran), loc)
749 val acc = (L'.CApp (acc, f), loc)
750 val acc = (L'.CApp (acc, i), loc)
751 val acc = (L'.CApp (acc, rest), loc)
752
753 val (iS, gs3) = summarizeCon (env, denv) i
754
755 val app = (L'.CApp (f, nm), loc)
756 val app = (L'.CApp (app, v), loc)
757 val app = (L'.CApp (app, acc), loc)
758 val (appS, gs4) = summarizeCon (env, denv) app
759
760 val (cS, gs5) = summarizeCon (env, denv) c
761 in
762 (*prefaces "Summaries" [("iS", p_con_summary iS),
763 ("appS", p_con_summary appS),
764 ("cS", p_con_summary cS)];*)
765
766 if compatible (iS, appS) then
767 raise ex
768 else if compatible (cS, iS) then
769 let
770 (*val () = prefaces "Same?" [("i", p_con env i),
771 ("c", p_con env c)]*)
772 val gs6 = unifyCons (env, denv) i c
773 (*val () = TextIO.print "Yes!\n"*)
774
775 val gs7 = unifyCons (env, denv) r (L'.CRecord (dom, []), loc)
776 in
777 gs @ gs3 @ gs5 @ gs6 @ gs7
778 end
779 else if compatible (cS, appS) then
780 let
781 (*val () = prefaces "Same?" [("app", p_con env app),
782 ("c", p_con env c),
783 ("app'", p_con env (#1 (hnormCon (env, denv) app)))]*)
784 val gs6 = unifyCons (env, denv) app c
785 (*val () = TextIO.print "Yes!\n"*)
786
787 val singleton = (L'.CRecord (dom, [(nm, v)]), loc)
788 val concat = (L'.CConcat (singleton, rest), loc)
789 (*val () = prefaces "Pre-crew" [("r", p_con env r),
790 ("concat", p_con env concat)]*)
791 val gs7 = unifyCons (env, denv) r concat
792 in
793 (*prefaces "The crew" [("nm", p_con env nm),
794 ("v", p_con env v),
795 ("rest", p_con env rest)];*)
796
797 gs @ gs3 @ gs4 @ gs5 @ gs6 @ gs7
798 end
799 else
800 raise ex
801 end
802 handle _ => raise ex
803 in
804 case (#1 c1, #1 c2) of
805 (L'.CApp ((L'.CApp ((L'.CApp ((L'.CFold (dom, ran), _), f), _), i), _), r), _) =>
806 unfold (dom, ran, f, i, r, c2)
807 | (_, L'.CApp ((L'.CApp ((L'.CApp ((L'.CFold (dom, ran), _), f), _), i), _), r)) =>
808 unfold (dom, ran, f, i, r, c1)
809 | _ => raise ex
810 end
811
812 and unifyCons' (env, denv) c1 c2 =
813 case (#1 c1, #1 c2) of
814 (L'.CDisjoint (_, x1, y1, t1), L'.CDisjoint (_, x2, y2, t2)) =>
815 let
816 val gs1 = unifyCons' (env, denv) x1 x2
817 val gs2 = unifyCons' (env, denv) y1 y2
818 val (denv', gs3) = D.assert env denv (x1, y1)
819 val gs4 = unifyCons' (env, denv') t1 t2
820 in
821 gs1 @ gs2 @ gs3 @ gs4
822 end
823 | _ =>
824 let
825 val (c1, gs1) = hnormCon (env, denv) c1
826 val (c2, gs2) = hnormCon (env, denv) c2
827 in
828 let
829 val gs3 = unifyCons'' (env, denv) c1 c2
830 in
831 gs1 @ gs2 @ gs3
832 end
833 handle ex => guessFold (env, denv) (c1, c2, gs1 @ gs2, ex)
834 end
835
836 and unifyCons'' (env, denv) (c1All as (c1, loc)) (c2All as (c2, _)) =
837 let
838 fun err f = raise CUnify' (f (c1All, c2All))
839
840 fun isRecord () = unifyRecordCons (env, denv) (c1All, c2All)
841 in
842 (*eprefaces "unifyCons''" [("c1All", p_con env c1All),
843 ("c2All", p_con env c2All)];*)
844
845 case (c1, c2) of
846 (L'.CUnit, L'.CUnit) => []
847
848 | (L'.TFun (d1, r1), L'.TFun (d2, r2)) =>
849 unifyCons' (env, denv) d1 d2
850 @ unifyCons' (env, denv) r1 r2
851 | (L'.TCFun (expl1, x1, d1, r1), L'.TCFun (expl2, _, d2, r2)) =>
852 if expl1 <> expl2 then
853 err CExplicitness
854 else
855 (unifyKinds d1 d2;
856 unifyCons' (E.pushCRel env x1 d1, D.enter denv) r1 r2)
857 | (L'.TRecord r1, L'.TRecord r2) => unifyCons' (env, denv) r1 r2
858
859 | (L'.CRel n1, L'.CRel n2) =>
860 if n1 = n2 then
861 []
862 else
863 err CIncompatible
864 | (L'.CNamed n1, L'.CNamed n2) =>
865 if n1 = n2 then
866 []
867 else
868 err CIncompatible
869
870 | (L'.CApp (d1, r1), L'.CApp (d2, r2)) =>
871 (unifyCons' (env, denv) d1 d2;
872 unifyCons' (env, denv) r1 r2)
873 | (L'.CAbs (x1, k1, c1), L'.CAbs (_, k2, c2)) =>
874 (unifyKinds k1 k2;
875 unifyCons' (E.pushCRel env x1 k1, D.enter denv) c1 c2)
876
877 | (L'.CName n1, L'.CName n2) =>
878 if n1 = n2 then
879 []
880 else
881 err CIncompatible
882
883 | (L'.CModProj (n1, ms1, x1), L'.CModProj (n2, ms2, x2)) =>
884 if n1 = n2 andalso ms1 = ms2 andalso x1 = x2 then
885 []
886 else
887 err CIncompatible
888
889 | (L'.CTuple cs1, L'.CTuple cs2) =>
890 ((ListPair.foldlEq (fn (c1, c2, gs) =>
891 let
892 val gs' = unifyCons' (env, denv) c1 c2
893 in
894 gs' @ gs
895 end) [] (cs1, cs2))
896 handle ListPair.UnequalLengths => err CIncompatible)
897
898 | (L'.CProj ((L'.CUnif (_, _, _, ref (SOME c1)), loc), n1), _) =>
899 unifyCons' (env, denv) (L'.CProj (c1, n1), loc) c2All
900 | (_, L'.CProj ((L'.CUnif (_, _, _, ref (SOME c2)), loc), n2)) =>
901 unifyCons' (env, denv) c1All (L'.CProj (c2, n2), loc)
902 | (L'.CProj ((L'.CUnif (_, (L'.KTuple ks, _), _, r), loc), n), _) =>
903 let
904 val us = map (fn k => cunif (loc, k)) ks
905 in
906 r := SOME (L'.CTuple us, loc);
907 unifyCons' (env, denv) (List.nth (us, n - 1)) c2All
908 end
909 | (_, L'.CProj ((L'.CUnif (_, (L'.KTuple ks, _), _, r), loc), n)) =>
910 let
911 val us = map (fn k => cunif (loc, k)) ks
912 in
913 r := SOME (L'.CTuple us, loc);
914 unifyCons' (env, denv) c1All (List.nth (us, n - 1))
915 end
916 | (L'.CProj (c1, n1), L'.CProj (c2, n2)) =>
917 if n1 = n2 then
918 unifyCons' (env, denv) c1 c2
919 else
920 err CIncompatible
921
922 | (L'.CError, _) => []
923 | (_, L'.CError) => []
924
925 | (L'.CRecord _, _) => isRecord ()
926 | (_, L'.CRecord _) => isRecord ()
927 | (L'.CConcat _, _) => isRecord ()
928 | (_, L'.CConcat _) => isRecord ()
929
930 | (L'.CUnif (_, k1, _, r1), L'.CUnif (_, k2, _, r2)) =>
931 if r1 = r2 then
932 []
933 else
934 (unifyKinds k1 k2;
935 r1 := SOME c2All;
936 [])
937
938 | (L'.CUnif (_, _, _, r), _) =>
939 if occursCon r c2All then
940 err COccursCheckFailed
941 else
942 (r := SOME c2All;
943 [])
944 | (_, L'.CUnif (_, _, _, r)) =>
945 if occursCon r c1All then
946 err COccursCheckFailed
947 else
948 (r := SOME c1All;
949 [])
950
951 | (L'.CFold (dom1, ran1), L'.CFold (dom2, ran2)) =>
952 (unifyKinds dom1 dom2;
953 unifyKinds ran1 ran2;
954 []) 974 [])
955 975
956 | _ => err CIncompatible 976 fun primType env p =
957 end 977 case p of
958 978 P.Int _ => !int
959 and unifyCons (env, denv) c1 c2 = 979 | P.Float _ => !float
960 unifyCons' (env, denv) c1 c2 980 | P.String _ => !string
961 handle CUnify' err => raise CUnify (c1, c2, err) 981
962 | KUnify args => raise CUnify (c1, c2, CKind args) 982 fun recCons (k, nm, v, rest, loc) =
963 983 (L'.CConcat ((L'.CRecord (k, [(nm, v)]), loc),
964 fun checkCon (env, denv) e c1 c2 = 984 rest), loc)
965 unifyCons (env, denv) c1 c2 985
966 handle CUnify (c1, c2, err) => 986 fun foldType (dom, loc) =
967 (expError env (Unify (e, c1, c2, err)); 987 (L'.TCFun (L'.Explicit, "ran", (L'.KArrow ((L'.KRecord dom, loc), (L'.KType, loc)), loc),
968 []) 988 (L'.TFun ((L'.TCFun (L'.Explicit, "nm", (L'.KName, loc),
969 989 (L'.TCFun (L'.Explicit, "v", dom,
970 fun checkPatCon (env, denv) p c1 c2 = 990 (L'.TCFun (L'.Explicit, "rest", (L'.KRecord dom, loc),
971 unifyCons (env, denv) c1 c2 991 (L'.TFun ((L'.CApp ((L'.CRel 3, loc), (L'.CRel 0, loc)), loc),
972 handle CUnify (c1, c2, err) => 992 (L'.CDisjoint (L'.Instantiate,
973 (expError env (PatUnify (p, c1, c2, err)); 993 (L'.CRecord
974 []) 994 ((L'.KUnit, loc),
975 995 [((L'.CRel 2, loc),
976 fun primType env p = 996 (L'.CUnit, loc))]), loc),
977 case p of 997 (L'.CRel 0, loc),
978 P.Int _ => !int 998 (L'.CApp ((L'.CRel 3, loc),
979 | P.Float _ => !float 999 recCons (dom,
980 | P.String _ => !string 1000 (L'.CRel 2, loc),
981 1001 (L'.CRel 1, loc),
982 fun recCons (k, nm, v, rest, loc) = 1002 (L'.CRel 0, loc),
983 (L'.CConcat ((L'.CRecord (k, [(nm, v)]), loc), 1003 loc)), loc)),
984 rest), loc) 1004 loc)), loc)),
985 1005 loc)), loc)), loc),
986 fun foldType (dom, loc) = 1006 (L'.TFun ((L'.CApp ((L'.CRel 0, loc), (L'.CRecord (dom, []), loc)), loc),
987 (L'.TCFun (L'.Explicit, "ran", (L'.KArrow ((L'.KRecord dom, loc), (L'.KType, loc)), loc), 1007 (L'.TCFun (L'.Explicit, "r", (L'.KRecord dom, loc),
988 (L'.TFun ((L'.TCFun (L'.Explicit, "nm", (L'.KName, loc), 1008 (L'.CApp ((L'.CRel 1, loc), (L'.CRel 0, loc)), loc)), loc)),
989 (L'.TCFun (L'.Explicit, "v", dom, 1009 loc)), loc)), loc)
990 (L'.TCFun (L'.Explicit, "rest", (L'.KRecord dom, loc), 1010
991 (L'.TFun ((L'.CApp ((L'.CRel 3, loc), (L'.CRel 0, loc)), loc), 1011 datatype constraint =
992 (L'.CDisjoint (L'.Instantiate, 1012 Disjoint of D.goal
993 (L'.CRecord 1013 | TypeClass of E.env * L'.con * L'.exp option ref * ErrorMsg.span
994 ((L'.KUnit, loc), 1014
995 [((L'.CRel 2, loc), 1015 val enD = map Disjoint
996 (L'.CUnit, loc))]), loc), 1016
997 (L'.CRel 0, loc), 1017 fun elabHead (env, denv) infer (e as (_, loc)) t =
998 (L'.CApp ((L'.CRel 3, loc), 1018 let
999 recCons (dom, 1019 fun unravel (t, e) =
1000 (L'.CRel 2, loc), 1020 let
1001 (L'.CRel 1, loc), 1021 val (t, gs) = hnormCon (env, denv) t
1002 (L'.CRel 0, loc), 1022 in
1003 loc)), loc)), 1023 case t of
1004 loc)), loc)), 1024 (L'.TCFun (L'.Implicit, x, k, t'), _) =>
1005 loc)), loc)), loc), 1025 let
1006 (L'.TFun ((L'.CApp ((L'.CRel 0, loc), (L'.CRecord (dom, []), loc)), loc), 1026 val u = cunif (loc, k)
1007 (L'.TCFun (L'.Explicit, "r", (L'.KRecord dom, loc), 1027
1008 (L'.CApp ((L'.CRel 1, loc), (L'.CRel 0, loc)), loc)), loc)), 1028 val t'' = subConInCon (0, u) t'
1009 loc)), loc)), loc) 1029 val (e, t, gs') = unravel (t'', (L'.ECApp (e, u), loc))
1010 1030 in
1011 datatype constraint = 1031 (*prefaces "Unravel" [("t'", p_con env t'),
1012 Disjoint of D.goal 1032 ("t''", p_con env t'')];*)
1013 | TypeClass of E.env * L'.con * L'.exp option ref * ErrorMsg.span 1033 (e, t, enD gs @ gs')
1014 1034 end
1015 val enD = map Disjoint 1035 | (L'.TFun (dom as (L'.CApp (cl, _), _), ran), _) =>
1016 1036 let
1017 fun elabHead (env, denv) (e as (_, loc)) t = 1037 val cl = #1 (hnormCon (env, denv) cl)
1018 let 1038 in
1019 fun unravel (t, e) = 1039 if infer <> L.TypesOnly andalso E.isClass env cl then
1020 let 1040 let
1021 val (t, gs) = hnormCon (env, denv) t 1041 val r = ref NONE
1022 in 1042 val (e, t, gs') = unravel (ran, (L'.EApp (e, (L'.EUnif r, loc)), loc))
1023 case t of 1043 in
1024 (L'.TCFun (L'.Implicit, x, k, t'), _) => 1044 (e, t, TypeClass (env, dom, r, loc) :: enD gs @ gs')
1025 let 1045 end
1026 val u = cunif (loc, k) 1046 else
1027 1047 (e, t, enD gs)
1028 val t'' = subConInCon (0, u) t' 1048 end
1029 val (e, t, gs') = unravel (t'', (L'.ECApp (e, u), loc))
1030 in
1031 (*prefaces "Unravel" [("t'", p_con env t'),
1032 ("t''", p_con env t'')];*)
1033 (e, t, enD gs @ gs')
1034 end
1035 | _ => (e, t, enD gs) 1049 | _ => (e, t, enD gs)
1036 end 1050 end
1037 in 1051 in
1038 unravel (t, e) 1052 case infer of
1053 L.DontInfer => (e, t, [])
1054 | _ => unravel (t, e)
1039 end 1055 end
1040 1056
1041 fun elabPat (pAll as (p, loc), (env, denv, bound)) = 1057 fun elabPat (pAll as (p, loc), (env, denv, bound)) =
1042 let 1058 let
1043 val perror = (L'.PWild, loc) 1059 val perror = (L'.PWild, loc)
1391 in 1407 in
1392 (e', t', gs1 @ enD gs2 @ enD gs3) 1408 (e', t', gs1 @ enD gs2 @ enD gs3)
1393 end 1409 end
1394 1410
1395 | L.EPrim p => ((L'.EPrim p, loc), primType env p, []) 1411 | L.EPrim p => ((L'.EPrim p, loc), primType env p, [])
1396 | L.EVar ([], s) => 1412 | L.EVar ([], s, infer) =>
1397 (case E.lookupE env s of 1413 (case E.lookupE env s of
1398 E.NotBound => 1414 E.NotBound =>
1399 (expError env (UnboundExp (loc, s)); 1415 (expError env (UnboundExp (loc, s));
1400 (eerror, cerror, [])) 1416 (eerror, cerror, []))
1401 | E.Rel (n, t) => ((L'.ERel n, loc), t, []) 1417 | E.Rel (n, t) => elabHead (env, denv) infer (L'.ERel n, loc) t
1402 | E.Named (n, t) => 1418 | E.Named (n, t) => elabHead (env, denv) infer (L'.ENamed n, loc) t)
1403 if Char.isUpper (String.sub (s, 0)) then 1419 | L.EVar (m1 :: ms, s, infer) =>
1404 elabHead (env, denv) (L'.ENamed n, loc) t
1405 else
1406 ((L'.ENamed n, loc), t, []))
1407 | L.EVar (m1 :: ms, s) =>
1408 (case E.lookupStr env m1 of 1420 (case E.lookupStr env m1 of
1409 NONE => (expError env (UnboundStrInExp (loc, m1)); 1421 NONE => (expError env (UnboundStrInExp (loc, m1));
1410 (eerror, cerror, [])) 1422 (eerror, cerror, []))
1411 | SOME (n, sgn) => 1423 | SOME (n, sgn) =>
1412 let 1424 let
1420 val t = case E.projectVal env {sgn = sgn, str = str, field = s} of 1432 val t = case E.projectVal env {sgn = sgn, str = str, field = s} of
1421 NONE => (expError env (UnboundExp (loc, s)); 1433 NONE => (expError env (UnboundExp (loc, s));
1422 cerror) 1434 cerror)
1423 | SOME t => t 1435 | SOME t => t
1424 in 1436 in
1425 ((L'.EModProj (n, ms, s), loc), t, []) 1437 elabHead (env, denv) infer (L'.EModProj (n, ms, s), loc) t
1426 end) 1438 end)
1427 1439
1428 | L.EWild => 1440 | L.EWild =>
1429 let 1441 let
1430 val r = ref NONE 1442 val r = ref NONE
1434 end 1446 end
1435 1447
1436 | L.EApp (e1, e2) => 1448 | L.EApp (e1, e2) =>
1437 let 1449 let
1438 val (e1', t1, gs1) = elabExp (env, denv) e1 1450 val (e1', t1, gs1) = elabExp (env, denv) e1
1439 val (e1', t1, gs2) = elabHead (env, denv) e1' t1 1451 val (e2', t2, gs2) = elabExp (env, denv) e2
1440 val (e2', t2, gs3) = elabExp (env, denv) e2
1441 1452
1442 val dom = cunif (loc, ktype) 1453 val dom = cunif (loc, ktype)
1443 val ran = cunif (loc, ktype) 1454 val ran = cunif (loc, ktype)
1444 val t = (L'.TFun (dom, ran), dummy) 1455 val t = (L'.TFun (dom, ran), dummy)
1445 1456
1446 val gs4 = checkCon (env, denv) e1' t1 t 1457 val gs3 = checkCon (env, denv) e1' t1 t
1447 val gs5 = checkCon (env, denv) e2' t2 dom 1458 val gs4 = checkCon (env, denv) e2' t2 dom
1448 1459
1449 val gs = gs1 @ gs2 @ gs3 @ enD gs4 @ enD gs5 1460 val gs = gs1 @ gs2 @ enD gs3 @ enD gs4
1450 in 1461 in
1451 ((L'.EApp (e1', e2'), loc), ran, gs) 1462 ((L'.EApp (e1', e2'), loc), ran, gs)
1452 end 1463 end
1453 | L.EAbs (x, to, e) => 1464 | L.EAbs (x, to, e) =>
1454 let 1465 let
1470 end 1481 end
1471 | L.ECApp (e, c) => 1482 | L.ECApp (e, c) =>
1472 let 1483 let
1473 val (e', et, gs1) = elabExp (env, denv) e 1484 val (e', et, gs1) = elabExp (env, denv) e
1474 val oldEt = et 1485 val oldEt = et
1475 val (e', et, gs2) = elabHead (env, denv) e' et 1486 val (c', ck, gs2) = elabCon (env, denv) c
1476 val (c', ck, gs3) = elabCon (env, denv) c 1487 val ((et', _), gs3) = hnormCon (env, denv) et
1477 val ((et', _), gs4) = hnormCon (env, denv) et
1478 in 1488 in
1479 case et' of 1489 case et' of
1480 L'.CError => (eerror, cerror, []) 1490 L'.CError => (eerror, cerror, [])
1481 | L'.TCFun (_, x, k, eb) => 1491 | L'.TCFun (_, x, k, eb) =>
1482 let 1492 let
1489 ("et", p_con env oldEt), 1499 ("et", p_con env oldEt),
1490 ("x", PD.string x), 1500 ("x", PD.string x),
1491 ("eb", p_con (E.pushCRel env x k) eb), 1501 ("eb", p_con (E.pushCRel env x k) eb),
1492 ("c", p_con env c'), 1502 ("c", p_con env c'),
1493 ("eb'", p_con env eb')];*) 1503 ("eb'", p_con env eb')];*)
1494 ((L'.ECApp (e', c'), loc), eb', gs1 @ gs2 @ enD gs3 @ enD gs4) 1504 ((L'.ECApp (e', c'), loc), eb', gs1 @ enD gs2 @ enD gs3)
1495 end 1505 end
1496 1506
1497 | _ => 1507 | _ =>
1498 (expError env (WrongForm ("constructor function", e', et)); 1508 (expError env (WrongForm ("constructor function", e', et));
1499 (eerror, cerror, [])) 1509 (eerror, cerror, []))