comparison src/iflow.sml @ 1215:360f1ed0a969

Implemented proper congruence closure, to the point where tests/policy works
author Adam Chlipala <adamc@hcoop.net>
date Thu, 08 Apr 2010 12:46:21 -0400
parents 648e6b087dfb
children 09caa8c780e5
comparison
equal deleted inserted replaced
1214:648e6b087dfb 1215:360f1ed0a969
30 open Mono 30 open Mono
31 31
32 structure IS = IntBinarySet 32 structure IS = IntBinarySet
33 structure IM = IntBinaryMap 33 structure IM = IntBinaryMap
34 34
35 structure SS = BinarySetFn(struct 35 structure SK = struct
36 type ord_key = string 36 type ord_key = string
37 val compare = String.compare 37 val compare = String.compare
38 end) 38 end
39
40 structure SS = BinarySetFn(SK)
41 structure SM = BinaryMapFn(SK)
39 42
40 val writers = ["htmlifyInt_w", 43 val writers = ["htmlifyInt_w",
41 "htmlifyFloat_w", 44 "htmlifyFloat_w",
42 "htmlifyString_w", 45 "htmlifyString_w",
43 "htmlifyBool_w", 46 "htmlifyBool_w",
54 57
55 val writers = SS.addList (SS.empty, writers) 58 val writers = SS.addList (SS.empty, writers)
56 59
57 type lvar = int 60 type lvar = int
58 61
62 datatype func =
63 DtCon0 of string
64 | DtCon1 of string
65 | UnCon of string
66 | Other of string
67
59 datatype exp = 68 datatype exp =
60 Const of Prim.t 69 Const of Prim.t
61 | Var of int 70 | Var of int
62 | Lvar of lvar 71 | Lvar of lvar
63 | Func of string * exp list 72 | Func of func * exp list
64 | Recd of (string * exp) list 73 | Recd of (string * exp) list
65 | Proj of exp * string 74 | Proj of exp * string
66 | Finish 75 | Finish
67 76
68 datatype reln = 77 datatype reln =
69 Known 78 Known
70 | Sql of string 79 | Sql of string
71 | DtCon of string 80 | PCon0 of string
81 | PCon1 of string
72 | Eq 82 | Eq
73 | Ne 83 | Ne
74 | Lt 84 | Lt
75 | Le 85 | Le
76 | Gt 86 | Gt
83 | And of prop * prop 93 | And of prop * prop
84 | Or of prop * prop 94 | Or of prop * prop
85 | Reln of reln * exp list 95 | Reln of reln * exp list
86 | Cond of exp * prop 96 | Cond of exp * prop
87 97
98 val unif = ref (IM.empty : exp IM.map)
99
100 fun reset () = unif := IM.empty
101 fun save () = !unif
102 fun restore x = unif := x
103
88 local 104 local
89 open Print 105 open Print
90 val string = PD.string 106 val string = PD.string
91 in 107 in
92 108
109 fun p_func f =
110 string (case f of
111 DtCon0 s => s
112 | DtCon1 s => s
113 | UnCon s => "un" ^ s
114 | Other s => s)
115
93 fun p_exp e = 116 fun p_exp e =
94 case e of 117 case e of
95 Const p => Prim.p_t p 118 Const p => Prim.p_t p
96 | Var n => string ("x" ^ Int.toString n) 119 | Var n => string ("x" ^ Int.toString n)
97 | Lvar n => string ("X" ^ Int.toString n) 120 | Lvar n =>
98 | Func (f, es) => box [string (f ^ "("), 121 (case IM.find (!unif, n) of
122 NONE => string ("X" ^ Int.toString n)
123 | SOME e => p_exp e)
124 | Func (f, es) => box [p_func f,
125 string "(",
99 p_list p_exp es, 126 p_list p_exp es,
100 string ")"] 127 string ")"]
101 | Recd xes => box [string "{", 128 | Recd xes => box [string "{",
102 p_list (fn (x, e) => box [string x, 129 p_list (fn (x, e) => box [string x,
103 space, 130 space,
127 string ")"] 154 string ")"]
128 | _ => raise Fail "Iflow.p_reln: Known") 155 | _ => raise Fail "Iflow.p_reln: Known")
129 | Sql s => box [string (s ^ "("), 156 | Sql s => box [string (s ^ "("),
130 p_list p_exp es, 157 p_list p_exp es,
131 string ")"] 158 string ")"]
132 | DtCon s => box [string (s ^ "("), 159 | PCon0 s => box [string (s ^ "("),
160 p_list p_exp es,
161 string ")"]
162 | PCon1 s => box [string (s ^ "("),
133 p_list p_exp es, 163 p_list p_exp es,
134 string ")"] 164 string ")"]
135 | Eq => p_bop "=" es 165 | Eq => p_bop "=" es
136 | Ne => p_bop "<>" es 166 | Ne => p_bop "<>" es
137 | Lt => p_bop "<" es 167 | Lt => p_bop "<" es
196 fun isFinish e = 226 fun isFinish e =
197 case e of 227 case e of
198 Finish => true 228 Finish => true
199 | _ => false 229 | _ => false
200 230
201 val unif = ref (IM.empty : exp IM.map)
202
203 fun reset () = unif := IM.empty
204 fun save () = !unif
205 fun restore x = unif := x
206
207 fun simplify e = 231 fun simplify e =
208 case e of 232 case e of
209 Const _ => e 233 Const _ => e
210 | Var _ => e 234 | Var _ => e
211 | Lvar n => 235 | Lvar n =>
212 (case IM.find (!unif, n) of 236 (case IM.find (!unif, n) of
213 NONE => e 237 NONE => e
214 | SOME e => simplify e) 238 | SOME e => simplify e)
215 | Func (f, es) => 239 | Func (f, es) => Func (f, map simplify es)
216 let 240 | Recd xes => Recd (map (fn (x, e) => (x, simplify e)) xes)
217 val es = map simplify es 241 | Proj (e, s) => Proj (simplify e, s)
218
219 fun default () = Func (f, es)
220 in
221 if List.exists isFinish es then
222 Finish
223 else if String.isPrefix "un" f then
224 case es of
225 [Func (f', [e])] => if f' = String.extract (f, 2, NONE) then
226 e
227 else
228 default ()
229 | _ => default ()
230 else
231 default ()
232 end
233 | Recd xes =>
234 let
235 val xes = map (fn (x, e) => (x, simplify e)) xes
236 in
237 if List.exists (isFinish o #2) xes then
238 Finish
239 else
240 Recd xes
241 end
242 | Proj (e, s) =>
243 (case simplify e of
244 Recd xes =>
245 getOpt (ListUtil.search (fn (x, e') => if x = s then SOME e' else NONE) xes, Recd xes)
246 | e' =>
247 if isFinish e' then
248 Finish
249 else
250 Proj (e', s))
251 | Finish => Finish 242 | Finish => Finish
252 243
253 datatype atom = 244 datatype atom =
254 AReln of reln * exp list 245 AReln of reln * exp list
255 | ACond of exp * prop 246 | ACond of exp * prop
256 247
257 fun p_atom a = 248 fun p_atom a =
258 p_prop (case a of 249 p_prop (case a of
259 AReln x => Reln x 250 AReln x => Reln x
260 | ACond x => Cond x) 251 | ACond x => Cond x)
252
253 fun lvarIn lv =
254 let
255 fun lvi e =
256 case e of
257 Const _ => false
258 | Var _ => false
259 | Lvar lv' => lv' = lv
260 | Func (_, es) => List.exists lvi es
261 | Recd xes => List.exists (lvi o #2) xes
262 | Proj (e, _) => lvi e
263 | Finish => false
264 in
265 lvi
266 end
267
268 fun lvarInP lv =
269 let
270 fun lvi p =
271 case p of
272 True => false
273 | False => false
274 | Unknown => true
275 | And (p1, p2) => lvi p1 orelse lvi p2
276 | Or (p1, p2) => lvi p1 orelse lvi p2
277 | Reln (_, es) => List.exists (lvarIn lv) es
278 | Cond (e, p) => lvarIn lv e orelse lvi p
279 in
280 lvi
281 end
282
283 fun varIn lv =
284 let
285 fun lvi e =
286 case e of
287 Const _ => false
288 | Lvar _ => false
289 | Var lv' => lv' = lv
290 | Func (_, es) => List.exists lvi es
291 | Recd xes => List.exists (lvi o #2) xes
292 | Proj (e, _) => lvi e
293 | Finish => false
294 in
295 lvi
296 end
297
298 fun varInP lv =
299 let
300 fun lvi p =
301 case p of
302 True => false
303 | False => false
304 | Unknown => false
305 | And (p1, p2) => lvi p1 orelse lvi p2
306 | Or (p1, p2) => lvi p1 orelse lvi p2
307 | Reln (_, es) => List.exists (varIn lv) es
308 | Cond (e, p) => varIn lv e orelse lvi p
309 in
310 lvi
311 end
312
313 fun eq' (e1, e2) =
314 case (e1, e2) of
315 (Const p1, Const p2) => Prim.equal (p1, p2)
316 | (Var n1, Var n2) => n1 = n2
317
318 | (Lvar n1, _) =>
319 (case IM.find (!unif, n1) of
320 SOME e1 => eq' (e1, e2)
321 | NONE =>
322 case e2 of
323 Lvar n2 =>
324 (case IM.find (!unif, n2) of
325 SOME e2 => eq' (e1, e2)
326 | NONE => n1 = n2
327 orelse (unif := IM.insert (!unif, n2, e1);
328 true))
329 | _ =>
330 if lvarIn n1 e2 then
331 false
332 else
333 (unif := IM.insert (!unif, n1, e2);
334 true))
335
336 | (_, Lvar n2) =>
337 (case IM.find (!unif, n2) of
338 SOME e2 => eq' (e1, e2)
339 | NONE =>
340 if lvarIn n2 e1 then
341 false
342 else
343 ((*Print.prefaces "unif" [("n2", Print.PD.string (Int.toString n2)),
344 ("e1", p_exp e1)];*)
345 unif := IM.insert (!unif, n2, e1);
346 true))
347
348 | (Func (f1, es1), Func (f2, es2)) => f1 = f2 andalso ListPair.allEq eq' (es1, es2)
349 | (Recd xes1, Recd xes2) => ListPair.allEq (fn ((x1, e1), (x2, e2)) => x1 = x2 andalso eq' (e1, e2)) (xes1, xes2)
350 | (Proj (e1, s1), Proj (e2, s2)) => eq' (e1, e2) andalso s1 = s2
351 | (Finish, Finish) => true
352 | _ => false
353
354 fun eq (e1, e2) =
355 let
356 val saved = save ()
357 in
358 if eq' (simplify e1, simplify e2) then
359 true
360 else
361 (restore saved;
362 false)
363 end
364
365 val debug = ref false
366
367 fun eeq (e1, e2) =
368 case (e1, e2) of
369 (Const p1, Const p2) => Prim.equal (p1, p2)
370 | (Var n1, Var n2) => n1 = n2
371 | (Lvar n1, Lvar n2) => n1 = n2
372 | (Func (f1, es1), Func (f2, es2)) => f1 = f2 andalso ListPair.allEq eeq (es1, es2)
373 | (Recd xes1, Recd xes2) => length xes1 = length xes2 andalso
374 List.all (fn (x2, e2) =>
375 List.exists (fn (x1, e1) => x1 = x2 andalso eeq (e1, e2)) xes2) xes1
376 | (Proj (e1, x1), Proj (e2, x2)) => eeq (e1, e2) andalso x1 = x2
377 | (Finish, Finish) => true
378 | _ => false
379
380 (* Congruence closure *)
381 structure Cc :> sig
382 type database
383 type representative
384
385 exception Contradiction
386 exception Undetermined
387
388 val database : unit -> database
389 val representative : database * exp -> representative
390
391 val assert : database * atom -> unit
392 val check : database * atom -> bool
393
394 val p_database : database Print.printer
395 end = struct
396
397 exception Contradiction
398 exception Undetermined
399
400 structure CM = BinaryMapFn(struct
401 type ord_key = Prim.t
402 val compare = Prim.compare
403 end)
404
405 datatype node = Node of {Rep : node ref option ref,
406 Cons : node ref SM.map ref,
407 Variety : variety,
408 Known : bool ref}
409
410 and variety =
411 Dt0 of string
412 | Dt1 of string * node ref
413 | Prim of Prim.t
414 | Recrd of node ref SM.map ref
415 | VFinish
416 | Nothing
417
418 type representative = node ref
419
420 val finish = ref (Node {Rep = ref NONE,
421 Cons = ref SM.empty,
422 Variety = VFinish,
423 Known = ref false})
424
425 type database = {Vars : representative IM.map ref,
426 Consts : representative CM.map ref,
427 Con0s : representative SM.map ref,
428 Records : (representative SM.map * representative) list ref,
429 Funcs : ((string * representative list) * representative) list ref }
430
431 fun database () = {Vars = ref IM.empty,
432 Consts = ref CM.empty,
433 Con0s = ref SM.empty,
434 Records = ref [],
435 Funcs = ref []}
436
437 fun unNode n =
438 case !n of
439 Node r => r
440
441 open Print
442 val string = PD.string
443 val newline = PD.newline
444
445 fun p_rep n =
446 case !(#Rep (unNode n)) of
447 SOME n => p_rep n
448 | NONE =>
449 case #Variety (unNode n) of
450 Nothing => string ("?" ^ Int.toString (Unsafe.cast n))
451 | Dt0 s => string ("Dt0(" ^ s ^ ")")
452 | Dt1 (s, n) => box[string ("Dt1(" ^ s ^ ","),
453 space,
454 p_rep n,
455 string ")"]
456 | Prim p => Prim.p_t p
457 | Recrd (ref m) => box [string "{",
458 p_list (fn (x, n) => box [string x,
459 space,
460 string "=",
461 space,
462 p_rep n]) (SM.listItemsi m),
463 string "}"]
464 | VFinish => string "FINISH"
465
466 fun p_database (db : database) =
467 box [string "Vars:",
468 newline,
469 p_list_sep newline (fn (i, n) => box [string ("x" ^ Int.toString i),
470 space,
471 string "=",
472 space,
473 p_rep n]) (IM.listItemsi (!(#Vars db)))]
474
475 fun repOf (n : representative) : representative =
476 case !(#Rep (unNode n)) of
477 NONE => n
478 | SOME r =>
479 let
480 val r = repOf r
481 in
482 #Rep (unNode n) := SOME r;
483 r
484 end
485
486 fun markKnown r =
487 (#Known (unNode r) := true;
488 case #Variety (unNode r) of
489 Dt1 (_, r) => markKnown r
490 | Recrd xes => SM.app markKnown (!xes)
491 | _ => ())
492
493 fun representative (db : database, e) =
494 let
495 fun rep e =
496 case e of
497 Const p => (case CM.find (!(#Consts db), p) of
498 SOME r => repOf r
499 | NONE =>
500 let
501 val r = ref (Node {Rep = ref NONE,
502 Cons = ref SM.empty,
503 Variety = Prim p,
504 Known = ref false})
505 in
506 #Consts db := CM.insert (!(#Consts db), p, r);
507 r
508 end)
509 | Var n => (case IM.find (!(#Vars db), n) of
510 SOME r => repOf r
511 | NONE =>
512 let
513 val r = ref (Node {Rep = ref NONE,
514 Cons = ref SM.empty,
515 Variety = Nothing,
516 Known = ref false})
517 in
518 #Vars db := IM.insert (!(#Vars db), n, r);
519 r
520 end)
521 | Lvar n =>
522 (case IM.find (!unif, n) of
523 NONE => raise Undetermined
524 | SOME e => rep e)
525 | Func (DtCon0 f, []) => (case SM.find (!(#Con0s db), f) of
526 SOME r => repOf r
527 | NONE =>
528 let
529 val r = ref (Node {Rep = ref NONE,
530 Cons = ref SM.empty,
531 Variety = Dt0 f,
532 Known = ref false})
533 in
534 #Con0s db := SM.insert (!(#Con0s db), f, r);
535 r
536 end)
537 | Func (DtCon0 _, _) => raise Fail "Iflow.rep: DtCon0"
538 | Func (DtCon1 f, [e]) =>
539 let
540 val r = rep e
541 in
542 case SM.find (!(#Cons (unNode r)), f) of
543 SOME r => repOf r
544 | NONE =>
545 let
546 val r' = ref (Node {Rep = ref NONE,
547 Cons = ref SM.empty,
548 Variety = Dt1 (f, r),
549 Known = ref false})
550 in
551 #Cons (unNode r) := SM.insert (!(#Cons (unNode r)), f, r');
552 r'
553 end
554 end
555 | Func (DtCon1 _, _) => raise Fail "Iflow.rep: DtCon1"
556 | Func (UnCon f, [e]) =>
557 let
558 val r = rep e
559 in
560 case #Variety (unNode r) of
561 Dt1 (f', n) => if f' = f then
562 repOf n
563 else
564 raise Contradiction
565 | Nothing =>
566 let
567 val cons = ref SM.empty
568 val r' = ref (Node {Rep = ref NONE,
569 Cons = cons,
570 Variety = Nothing,
571 Known = ref false})
572
573 val r'' = ref (Node {Rep = ref NONE,
574 Cons = #Cons (unNode r),
575 Variety = Dt1 (f, r'),
576 Known = #Known (unNode r)})
577 in
578 cons := SM.insert (!cons, f, r'');
579 #Rep (unNode r) := SOME r'';
580 r'
581 end
582 | VFinish => r
583 | _ => raise Contradiction
584 end
585 | Func (UnCon _, _) => raise Fail "Iflow.rep: UnCon"
586 | Func (Other f, es) =>
587 let
588 val rs = map rep es
589 in
590 case List.find (fn (x : string * representative list, _) => x = (f, rs)) (!(#Funcs db)) of
591 NONE =>
592 let
593 val r = ref (Node {Rep = ref NONE,
594 Cons = ref SM.empty,
595 Variety = Nothing,
596 Known = ref false})
597 in
598 #Funcs db := ((f, rs), r) :: (!(#Funcs db));
599 r
600 end
601 | SOME (_, r) => repOf r
602 end
603 | Recd xes =>
604 let
605 val xes = map (fn (x, e) => (x, rep e)) xes
606 val len = length xes
607 in
608 case List.find (fn (xes', _) =>
609 SM.numItems xes' = len
610 andalso List.all (fn (x, n) =>
611 case SM.find (xes', x) of
612 NONE => false
613 | SOME n' => n = repOf n') xes)
614 (!(#Records db)) of
615 SOME (_, r) => repOf r
616 | NONE =>
617 let
618 val xes = foldl SM.insert' SM.empty xes
619
620 val r' = ref (Node {Rep = ref NONE,
621 Cons = ref SM.empty,
622 Variety = Recrd (ref xes),
623 Known = ref false})
624 in
625 #Records db := (xes, r') :: (!(#Records db));
626 r'
627 end
628 end
629 | Proj (e, f) =>
630 let
631 val r = rep e
632 in
633 case #Variety (unNode r) of
634 Recrd xes =>
635 (case SM.find (!xes, f) of
636 SOME r => repOf r
637 | NONE =>let
638 val r = ref (Node {Rep = ref NONE,
639 Cons = ref SM.empty,
640 Variety = Nothing,
641 Known = ref false})
642 in
643 xes := SM.insert (!xes, f, r);
644 r
645 end)
646 | Nothing =>
647 let
648 val r' = ref (Node {Rep = ref NONE,
649 Cons = ref SM.empty,
650 Variety = Nothing,
651 Known = ref false})
652
653 val r'' = ref (Node {Rep = ref NONE,
654 Cons = #Cons (unNode r),
655 Variety = Recrd (ref (SM.insert (SM.empty, f, r'))),
656 Known = #Known (unNode r)})
657 in
658 #Rep (unNode r) := SOME r'';
659 r'
660 end
661 | VFinish => r
662 | _ => raise Contradiction
663 end
664 | Finish => finish
665 in
666 rep e
667 end
668
669 fun assert (db, a) =
670 case a of
671 ACond _ => ()
672 | AReln x =>
673 case x of
674 (Known, [e]) => markKnown (representative (db, e))
675 | (PCon0 f, [e]) =>
676 let
677 val r = representative (db, e)
678 in
679 case #Variety (unNode r) of
680 Dt0 f' => if f = f' then
681 ()
682 else
683 raise Contradiction
684 | Nothing =>
685 let
686 val r' = ref (Node {Rep = ref NONE,
687 Cons = ref SM.empty,
688 Variety = Dt0 f,
689 Known = ref false})
690 in
691 #Rep (unNode r) := SOME r'
692 end
693 | _ => raise Contradiction
694 end
695 | (PCon1 f, [e]) =>
696 let
697 val r = representative (db, e)
698 in
699 case #Variety (unNode r) of
700 Dt1 (f', e') => if f = f' then
701 ()
702 else
703 raise Contradiction
704 | Nothing =>
705 let
706 val r'' = ref (Node {Rep = ref NONE,
707 Cons = ref SM.empty,
708 Variety = Nothing,
709 Known = ref false})
710
711 val r' = ref (Node {Rep = ref NONE,
712 Cons = ref SM.empty,
713 Variety = Dt1 (f, r''),
714 Known = ref false})
715 in
716 #Rep (unNode r) := SOME r'
717 end
718 | _ => raise Contradiction
719 end
720 | (Eq, [e1, e2]) =>
721 let
722 fun markEq (r1, r2) =
723 if r1 = r2 then
724 ()
725 else case (#Variety (unNode r1), #Variety (unNode r2)) of
726 (Prim p1, Prim p2) => if Prim.equal (p1, p2) then
727 ()
728 else
729 raise Contradiction
730 | (Dt0 f1, Dt0 f2) => if f1 = f2 then
731 ()
732 else
733 raise Contradiction
734 | (Dt1 (f1, r1), Dt1 (f2, r2)) => if f1 = f2 then
735 markEq (r1, r2)
736 else
737 raise Contradiction
738 | (Recrd xes1, Recrd xes2) =>
739 let
740 fun unif (xes1, xes2) =
741 SM.appi (fn (x, r1) =>
742 case SM.find (xes2, x) of
743 NONE => ()
744 | SOME r2 => markEq (r1, r2)) xes1
745 in
746 unif (!xes1, !xes2);
747 unif (!xes2, !xes1)
748 end
749 | (VFinish, VFinish) => ()
750 | (Nothing, _) =>
751 (#Rep (unNode r1) := SOME r2;
752 if !(#Known (unNode r1)) andalso not (!(#Known (unNode r2))) then
753 markKnown r2
754 else
755 ();
756 #Cons (unNode r2) := SM.unionWith #1 (!(#Cons (unNode r2)), !(#Cons (unNode r1)));
757 compactFuncs ())
758 | (_, Nothing) =>
759 (#Rep (unNode r2) := SOME r1;
760 if !(#Known (unNode r2)) andalso not (!(#Known (unNode r1))) then
761 markKnown r1
762 else
763 ();
764 #Cons (unNode r1) := SM.unionWith #1 (!(#Cons (unNode r1)), !(#Cons (unNode r2)));
765 compactFuncs ())
766 | _ => raise Contradiction
767
768 and compactFuncs () =
769 let
770 fun loop funcs =
771 case funcs of
772 [] => []
773 | (fr as ((f, rs), r)) :: rest =>
774 let
775 val rest = List.filter (fn ((f' : string, rs'), r') =>
776 if f' = f
777 andalso ListPair.allEq (fn (r1, r2) =>
778 repOf r1 = repOf r2)
779 (rs, rs') then
780 (markEq (r, r');
781 false)
782 else
783 true) rest
784 in
785 fr :: loop rest
786 end
787 in
788 #Funcs db := loop (!(#Funcs db))
789 end
790 in
791 markEq (representative (db, e1), representative (db, e2))
792 end
793 | _ => ()
794
795 fun check (db, a) =
796 case a of
797 ACond _ => false
798 | AReln x =>
799 case x of
800 (Known, [e]) => !(#Known (unNode (representative (db, e))))
801 | (PCon0 f, [e]) =>
802 (case #Variety (unNode (representative (db, e))) of
803 Dt0 f' => f' = f
804 | _ => false)
805 | (PCon1 f, [e]) =>
806 (case #Variety (unNode (representative (db, e))) of
807 Dt1 (f', _) => f' = f
808 | _ => false)
809 | (Eq, [e1, e2]) =>
810 let
811 val r1 = representative (db, e1)
812 val r2 = representative (db, e2)
813 in
814 repOf r1 = repOf r2
815 end
816 | _ => false
817
818 end
261 819
262 fun decomp fals or = 820 fun decomp fals or =
263 let 821 let
264 fun decomp p k = 822 fun decomp p k =
265 case p of 823 case p of
276 | Cond x => k [ACond x] 834 | Cond x => k [ACond x]
277 in 835 in
278 decomp 836 decomp
279 end 837 end
280 838
281 fun lvarIn lv =
282 let
283 fun lvi e =
284 case e of
285 Const _ => false
286 | Var _ => false
287 | Lvar lv' => lv' = lv
288 | Func (_, es) => List.exists lvi es
289 | Recd xes => List.exists (lvi o #2) xes
290 | Proj (e, _) => lvi e
291 | Finish => false
292 in
293 lvi
294 end
295
296 fun lvarInP lv =
297 let
298 fun lvi p =
299 case p of
300 True => false
301 | False => false
302 | Unknown => true
303 | And (p1, p2) => lvi p1 orelse lvi p2
304 | Or (p1, p2) => lvi p1 orelse lvi p2
305 | Reln (_, es) => List.exists (lvarIn lv) es
306 | Cond (e, p) => lvarIn lv e orelse lvi p
307 in
308 lvi
309 end
310
311 fun varIn lv =
312 let
313 fun lvi e =
314 case e of
315 Const _ => false
316 | Lvar _ => false
317 | Var lv' => lv' = lv
318 | Func (_, es) => List.exists lvi es
319 | Recd xes => List.exists (lvi o #2) xes
320 | Proj (e, _) => lvi e
321 | Finish => false
322 in
323 lvi
324 end
325
326 fun varInP lv =
327 let
328 fun lvi p =
329 case p of
330 True => false
331 | False => false
332 | Unknown => false
333 | And (p1, p2) => lvi p1 orelse lvi p2
334 | Or (p1, p2) => lvi p1 orelse lvi p2
335 | Reln (_, es) => List.exists (varIn lv) es
336 | Cond (e, p) => varIn lv e orelse lvi p
337 in
338 lvi
339 end
340
341 fun eq' (e1, e2) =
342 case (e1, e2) of
343 (Const p1, Const p2) => Prim.equal (p1, p2)
344 | (Var n1, Var n2) => n1 = n2
345
346 | (Lvar n1, _) =>
347 (case IM.find (!unif, n1) of
348 SOME e1 => eq' (e1, e2)
349 | NONE =>
350 case e2 of
351 Lvar n2 =>
352 (case IM.find (!unif, n2) of
353 SOME e2 => eq' (e1, e2)
354 | NONE => n1 = n2
355 orelse (unif := IM.insert (!unif, n2, e1);
356 true))
357 | _ =>
358 if lvarIn n1 e2 then
359 false
360 else
361 (unif := IM.insert (!unif, n1, e2);
362 true))
363
364 | (_, Lvar n2) =>
365 (case IM.find (!unif, n2) of
366 SOME e2 => eq' (e1, e2)
367 | NONE =>
368 if lvarIn n2 e1 then
369 false
370 else
371 ((*Print.prefaces "unif" [("n2", Print.PD.string (Int.toString n2)),
372 ("e1", p_exp e1)];*)
373 unif := IM.insert (!unif, n2, e1);
374 true))
375
376 | (Func (f1, es1), Func (f2, es2)) => f1 = f2 andalso ListPair.allEq eq' (es1, es2)
377 | (Recd xes1, Recd xes2) => ListPair.allEq (fn ((x1, e1), (x2, e2)) => x1 = x2 andalso eq' (e1, e2)) (xes1, xes2)
378 | (Proj (e1, s1), Proj (e2, s2)) => eq' (e1, e2) andalso s1 = s2
379 | (Finish, Finish) => true
380 | _ => false
381
382 fun eq (e1, e2) =
383 let
384 val saved = save ()
385 in
386 if eq' (simplify e1, simplify e2) then
387 true
388 else
389 (restore saved;
390 false)
391 end
392
393 val debug = ref false
394
395 fun eeq (e1, e2) =
396 case (e1, e2) of
397 (Const p1, Const p2) => Prim.equal (p1, p2)
398 | (Var n1, Var n2) => n1 = n2
399 | (Lvar n1, Lvar n2) => n1 = n2
400 | (Func (f1, es1), Func (f2, es2)) => f1 = f2 andalso ListPair.allEq eeq (es1, es2)
401 | (Recd xes1, Recd xes2) => length xes1 = length xes2 andalso
402 List.all (fn (x2, e2) =>
403 List.exists (fn (x1, e1) => x1 = x2 andalso eeq (e1, e2)) xes2) xes1
404 | (Proj (e1, x1), Proj (e2, x2)) => eeq (e1, e2) andalso x1 = x2
405 | (Finish, Finish) => true
406 | _ => false
407
408 (* Congruence closure *)
409 structure Cc :> sig
410 type t
411 val empty : t
412 val assert : t * exp * exp -> t
413 val query : t * exp * exp -> bool
414 val allPeers : t * exp -> exp list
415 val p_t : t Print.printer
416 end = struct
417
418 fun eq (e1, e2) = eeq (simplify e1, simplify e2)
419
420 type t = (exp * exp) list
421
422 val empty = []
423
424 fun lookup (t, e) =
425 case List.find (fn (e', _) => eq (e', e)) t of
426 NONE => e
427 | SOME (_, e2) => lookup (t, e2)
428
429 fun allPeers (t, e) =
430 let
431 val r = lookup (t, e)
432 in
433 r :: List.mapPartial (fn (e1, e2) =>
434 let
435 val r' = lookup (t, e2)
436 in
437 if eq (r, r') then
438 SOME e1
439 else
440 NONE
441 end) t
442 end
443
444 open Print
445
446 val p_t = p_list (fn (e1, e2) => box [p_exp (simplify e1),
447 space,
448 PD.string "->",
449 space,
450 p_exp (simplify e2)])
451
452 fun query (t, e1, e2) =
453 let
454 fun doUn e =
455 case e of
456 Func (f, [e1]) =>
457 if String.isPrefix "un" f then
458 let
459 val s = String.extract (f, 2, NONE)
460 in
461 case ListUtil.search (fn e =>
462 case e of
463 Func (f', [e']) =>
464 if f' = s then
465 SOME e'
466 else
467 NONE
468 | _ => NONE) (allPeers (t, e1)) of
469 NONE => e
470 | SOME e => doUn e
471 end
472 else
473 e
474 | _ => e
475
476 val e1' = doUn (lookup (t, doUn (simplify e1)))
477 val e2' = doUn (lookup (t, doUn (simplify e2)))
478 in
479 (*prefaces "CC query" [("e1", p_exp (simplify e1)),
480 ("e2", p_exp (simplify e2)),
481 ("e1'", p_exp (simplify e1')),
482 ("e2'", p_exp (simplify e2')),
483 ("t", p_t t)];*)
484 eq (e1', e2')
485 end
486
487 fun assert (t, e1, e2) =
488 let
489 val r1 = lookup (t, e1)
490 val r2 = lookup (t, e2)
491 in
492 if eq (r1, r2) then
493 t
494 else
495 let
496 fun doUn (t, e1, e2) =
497 case e1 of
498 Func (f, [e]) => if String.isPrefix "un" f then
499 let
500 val s = String.extract (f, 2, NONE)
501 in
502 foldl (fn (e', t) =>
503 case e' of
504 Func (f', [e']) =>
505 if f' = s then
506 assert (assert (t, e', e1), e', e2)
507 else
508 t
509 | _ => t) t (allPeers (t, e))
510 end
511 else
512 t
513 | _ => t
514
515 fun doProj (t, e1, e2) =
516 foldl (fn ((e1', e2'), t) =>
517 let
518 fun doOne (e, t) =
519 case e of
520 Proj (e', f) =>
521 if query (t, e1, e') then
522 assert (t, e, Proj (e2, f))
523 else
524 t
525 | _ => t
526 in
527 doOne (e1', doOne (e2', t))
528 end) t t
529
530 val t = (r1, r2) :: t
531 val t = doUn (t, r1, r2)
532 val t = doUn (t, r2, r1)
533 val t = doProj (t, r1, r2)
534 val t = doProj (t, r2, r1)
535 in
536 t
537 end
538 end
539
540 end
541
542 fun rimp cc ((r1, es1), (r2, es2)) =
543 case (r1, r2) of
544 (Sql r1', Sql r2') =>
545 r1' = r2' andalso
546 (case (es1, es2) of
547 ([e1], [e2]) => eq (e1, e2)
548 | _ => false)
549 | (Eq, Eq) =>
550 (case (es1, es2) of
551 ([x1, y1], [x2, y2]) =>
552 let
553 val saved = save ()
554 in
555 if eq (x1, x2) andalso eq (y1, y2) then
556 true
557 else
558 (restore saved;
559 if eq (x1, y2) andalso eq (y1, x2) then
560 true
561 else
562 (restore saved;
563 false))
564 end
565 | _ => false)
566 | (Known, Known) =>
567 (case (es1, es2) of
568 ([Var v], [e2]) =>
569 let
570 fun matches e =
571 case e of
572 Var v' => v' = v
573 | Proj (e, _) => matches e
574 | Func (f, [e]) => String.isPrefix "un" f andalso matches e
575 | _ => false
576 in
577 (*Print.prefaces "Checking peers" [("e2", p_exp e2),
578 ("peers", Print.p_list p_exp (Cc.allPeers (cc, e2))),
579 ("db", Cc.p_t cc)];*)
580 List.exists matches (Cc.allPeers (cc, e2))
581 end
582 | _ => false)
583 | _ => false
584
585 fun imply (p1, p2) = 839 fun imply (p1, p2) =
586 let 840 (reset ();
587 fun doOne doKnown = 841 decomp true (fn (e1, e2) => e1 andalso e2 ()) p1
588 decomp true (fn (e1, e2) => e1 andalso e2 ()) p1 842 (fn hyps =>
589 (fn hyps => 843 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2
590 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2 844 (fn goals =>
591 (fn goals => 845 let
592 let 846 fun gls goals onFail acc =
593 val cc = foldl (fn (p, cc) => 847 case goals of
594 case p of 848 [] =>
595 AReln (Eq, [e1, e2]) => Cc.assert (cc, e1, e2) 849 (let
596 | _ => cc) Cc.empty hyps 850 val cc = Cc.database ()
597 851 val () = app (fn a => Cc.assert (cc, a)) hyps
598 fun gls goals onFail = 852 in
599 case goals of 853 (List.all (fn a =>
600 [] => true 854 if Cc.check (cc, a) then
601 | ACond _ :: _ => false 855 true
602 | AReln g :: goals => 856 else
603 case (doKnown, g) of 857 ((*Print.prefaces "Can't prove"
604 (false, (Known, _)) => gls goals onFail 858 [("a", p_atom a),
605 | _ => 859 ("hyps", Print.p_list p_atom hyps),
606 let 860 ("db", Cc.p_database cc)];*)
607 fun hps hyps = 861 false)) acc
608 case hyps of 862 orelse onFail ())
609 [] => ((*Print.prefaces "Fail" [("g", p_prop (Reln g)), 863 handle Cc.Contradiction => onFail ()
610 ("db", Cc.p_t cc)];*) 864 end handle Cc.Undetermined => onFail ())
611 onFail ()) 865 | AReln (Sql gf, [ge]) :: goals =>
612 | ACond _ :: hyps => hps hyps 866 let
613 | AReln h :: hyps => 867 fun hps hyps =
614 let 868 case hyps of
615 val saved = save () 869 [] => onFail ()
616 in 870 | AReln (Sql hf, [he]) :: hyps =>
617 if rimp cc (h, g) then 871 if gf = hf then
618 let 872 let
619 val changed = IM.numItems (!unif) 873 val saved = save ()
620 <> IM.numItems saved 874 in
621 in 875 if eq (ge, he) then
622 gls goals (fn () => (restore saved; 876 let
623 changed (*andalso 877 val changed = IM.numItems (!unif)
624 (Print.preface ("Retry", 878 <> IM.numItems saved
625 p_prop 879 in
626 (Reln g) 880 gls goals (fn () => (restore saved;
627 ); true)*) 881 changed
628 andalso hps hyps)) 882 andalso hps hyps))
629 end 883 acc
630 else 884 end
631 hps hyps 885 else
632 end 886 hps hyps
633 in 887 end
634 (case g of 888 else
635 (Eq, [e1, e2]) => Cc.query (cc, e1, e2) 889 hps hyps
636 | _ => false) 890 | _ :: hyps => hps hyps
637 orelse hps hyps 891 in
638 end 892 hps hyps
639 in 893 end
640 if List.exists (fn AReln (DtCon c1, [e]) => 894 | g :: goals => gls goals onFail (g :: acc)
641 List.exists (fn AReln (DtCon c2, [e']) => 895 in
642 c1 <> c2 andalso 896 gls goals (fn () => false) []
643 Cc.query (cc, e, e') 897 end handle Cc.Contradiction => true)))
644 | _ => false) hyps
645 orelse List.exists (fn Func (c2, []) => c1 <> c2
646 | Finish => true
647 | _ => false)
648 (Cc.allPeers (cc, e))
649 | _ => false) hyps
650 orelse gls goals (fn () => false) then
651 true
652 else
653 ((*Print.prefaces "Can't prove"
654 [("hyps", Print.p_list p_atom hyps),
655 ("goals", Print.p_list p_atom goals)];*)
656 false)
657 end))
658 in
659 reset ();
660 doOne false;
661 doOne true
662 end
663 898
664 fun patCon pc = 899 fun patCon pc =
665 case pc of 900 case pc of
666 PConVar n => "C" ^ Int.toString n 901 PConVar n => "C" ^ Int.toString n
667 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c 902 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c
951 1186
952 val query = log "query" 1187 val query = log "query"
953 (wrap (follow (follow select from) (opt wher)) 1188 (wrap (follow (follow select from) (opt wher))
954 (fn ((fs, ts), wher) => {Select = fs, From = ts, Where = wher})) 1189 (fn ((fs, ts), wher) => {Select = fs, From = ts, Where = wher}))
955 1190
956 fun removeDups ls = 1191 fun removeDups (ls : (string * string) list) =
957 case ls of 1192 case ls of
958 [] => [] 1193 [] => []
959 | x :: ls => 1194 | x :: ls =>
960 let 1195 let
961 val ls = removeDups ls 1196 val ls = removeDups ls
1027 in 1262 in
1028 inl (deinj e) 1263 inl (deinj e)
1029 end 1264 end
1030 | SqFunc (f, e) => 1265 | SqFunc (f, e) =>
1031 inl (case expIn e of 1266 inl (case expIn e of
1032 inl e => Func (f, [e]) 1267 inl e => Func (Other f, [e])
1033 | _ => raise Fail ("Iflow: non-expresion passed to function " ^ f)) 1268 | _ => raise Fail ("Iflow: non-expresion passed to function " ^ f))
1034 | Count => inl count 1269 | Count => inl count
1035 1270
1036 val p = case #Where r of 1271 val p = case #Where r of
1037 NONE => p 1272 NONE => p
1079 fun evalPat env e (pt, _) = 1314 fun evalPat env e (pt, _) =
1080 case pt of 1315 case pt of
1081 PWild => (env, True) 1316 PWild => (env, True)
1082 | PVar _ => (e :: env, True) 1317 | PVar _ => (e :: env, True)
1083 | PPrim _ => (env, True) 1318 | PPrim _ => (env, True)
1084 | PCon (_, pc, NONE) => (env, Reln (DtCon (patCon pc), [e])) 1319 | PCon (_, pc, NONE) => (env, Reln (PCon0 (patCon pc), [e]))
1085 | PCon (_, pc, SOME pt) => 1320 | PCon (_, pc, SOME pt) =>
1086 let 1321 let
1087 val (env, p) = evalPat env (Func ("un" ^ patCon pc, [e])) pt 1322 val (env, p) = evalPat env (Func (UnCon (patCon pc), [e])) pt
1088 in 1323 in
1089 (env, And (p, Reln (DtCon (patCon pc), [e]))) 1324 (env, And (p, Reln (PCon1 (patCon pc), [e])))
1090 end 1325 end
1091 | PRecord xpts => 1326 | PRecord xpts =>
1092 foldl (fn ((x, pt, _), (env, p)) => 1327 foldl (fn ((x, pt, _), (env, p)) =>
1093 let 1328 let
1094 val (env, p') = evalPat env (Proj (e, x)) pt 1329 val (env, p') = evalPat env (Proj (e, x)) pt
1095 in 1330 in
1096 (env, And (p', p)) 1331 (env, And (p', p))
1097 end) (env, True) xpts 1332 end) (env, True) xpts
1098 | PNone _ => (env, Reln (DtCon "None", [e])) 1333 | PNone _ => (env, Reln (PCon0 "None", [e]))
1099 | PSome (_, pt) => 1334 | PSome (_, pt) =>
1100 let 1335 let
1101 val (env, p) = evalPat env (Func ("unSome", [e])) pt 1336 val (env, p) = evalPat env (Func (UnCon "Some", [e])) pt
1102 in 1337 in
1103 (env, And (p, Reln (DtCon "Some", [e]))) 1338 (env, And (p, Reln (PCon1 "Some", [e])))
1104 end 1339 end
1105 1340
1106 fun peq (p1, p2) = 1341 fun peq (p1, p2) =
1107 case (p1, p2) of 1342 case (p1, p2) of
1108 (True, True) => true 1343 (True, True) => true
1143 in 1378 in
1144 case #1 e of 1379 case #1 e of
1145 EPrim p => (Const p, st) 1380 EPrim p => (Const p, st)
1146 | ERel n => (List.nth (env, n), st) 1381 | ERel n => (List.nth (env, n), st)
1147 | ENamed _ => default () 1382 | ENamed _ => default ()
1148 | ECon (_, pc, NONE) => (Func (patCon pc, []), st) 1383 | ECon (_, pc, NONE) => (Func (DtCon0 (patCon pc), []), st)
1149 | ECon (_, pc, SOME e) => 1384 | ECon (_, pc, SOME e) =>
1150 let 1385 let
1151 val (e, st) = evalExp env (e, st) 1386 val (e, st) = evalExp env (e, st)
1152 in 1387 in
1153 (Func (patCon pc, [e]), st) 1388 (Func (DtCon1 (patCon pc), [e]), st)
1154 end 1389 end
1155 | ENone _ => (Func ("None", []), st) 1390 | ENone _ => (Func (DtCon0 "None", []), st)
1156 | ESome (_, e) => 1391 | ESome (_, e) =>
1157 let 1392 let
1158 val (e, st) = evalExp env (e, st) 1393 val (e, st) = evalExp env (e, st)
1159 in 1394 in
1160 (Func ("Some", [e]), st) 1395 (Func (DtCon1 "Some", [e]), st)
1161 end 1396 end
1162 | EFfi _ => default () 1397 | EFfi _ => default ()
1163 1398
1164 | EFfiApp (m, s, es) => 1399 | EFfiApp (m, s, es) =>
1165 if m = "Basis" andalso SS.member (writers, s) then 1400 if m = "Basis" andalso SS.member (writers, s) then
1172 default () 1407 default ()
1173 else 1408 else
1174 let 1409 let
1175 val (es, st) = ListUtil.foldlMap (evalExp env) st es 1410 val (es, st) = ListUtil.foldlMap (evalExp env) st es
1176 in 1411 in
1177 (Func (m ^ "." ^ s, es), st) 1412 (Func (Other (m ^ "." ^ s), es), st)
1178 end 1413 end
1179 1414
1180 | EApp (e1, e2) => 1415 | EApp (e1, e2) =>
1181 let 1416 let
1182 val (e1, st) = evalExp env (e1, st) 1417 val (e1, st) = evalExp env (e1, st)
1189 | EAbs _ => default () 1424 | EAbs _ => default ()
1190 | EUnop (s, e1) => 1425 | EUnop (s, e1) =>
1191 let 1426 let
1192 val (e1, st) = evalExp env (e1, st) 1427 val (e1, st) = evalExp env (e1, st)
1193 in 1428 in
1194 (Func (s, [e1]), st) 1429 (Func (Other s, [e1]), st)
1195 end 1430 end
1196 | EBinop (s, e1, e2) => 1431 | EBinop (s, e1, e2) =>
1197 let 1432 let
1198 val (e1, st) = evalExp env (e1, st) 1433 val (e1, st) = evalExp env (e1, st)
1199 val (e2, st) = evalExp env (e2, st) 1434 val (e2, st) = evalExp env (e2, st)
1200 in 1435 in
1201 (Func (s, [e1, e2]), st) 1436 (Func (Other s, [e1, e2]), st)
1202 end 1437 end
1203 | ERecord xets => 1438 | ERecord xets =>
1204 let 1439 let
1205 val (xes, st) = ListUtil.foldlMap (fn ((x, e, _), st) => 1440 val (xes, st) = ListUtil.foldlMap (fn ((x, e, _), st) =>
1206 let 1441 let
1239 | EStrcat (e1, e2) => 1474 | EStrcat (e1, e2) =>
1240 let 1475 let
1241 val (e1, st) = evalExp env (e1, st) 1476 val (e1, st) = evalExp env (e1, st)
1242 val (e2, st) = evalExp env (e2, st) 1477 val (e2, st) = evalExp env (e2, st)
1243 in 1478 in
1244 (Func ("cat", [e1, e2]), st) 1479 (Func (Other "cat", [e1, e2]), st)
1245 end 1480 end
1246 | EError _ => (Finish, st) 1481 | EError _ => (Finish, st)
1247 | EReturnBlob {blob = b, mimeType = m, ...} => 1482 | EReturnBlob {blob = b, mimeType = m, ...} =>
1248 let 1483 let
1249 val (b, st) = evalExp env (b, st) 1484 val (b, st) = evalExp env (b, st)
1277 end 1512 end
1278 | EClosure (n, es) => 1513 | EClosure (n, es) =>
1279 let 1514 let
1280 val (es, st) = ListUtil.foldlMap (evalExp env) st es 1515 val (es, st) = ListUtil.foldlMap (evalExp env) st es
1281 in 1516 in
1282 (Func ("Cl" ^ Int.toString n, es), st) 1517 (Func (Other ("Cl" ^ Int.toString n), es), st)
1283 end 1518 end
1284 1519
1285 | EQuery {query = q, body = b, initial = i, ...} => 1520 | EQuery {query = q, body = b, initial = i, ...} =>
1286 let 1521 let
1287 val (_, st) = evalExp env (q, st) 1522 val (_, st) = evalExp env (q, st)
1407 fun doAll e = 1642 fun doAll e =
1408 case e of 1643 case e of
1409 Const _ => () 1644 Const _ => ()
1410 | Var _ => doOne e 1645 | Var _ => doOne e
1411 | Lvar _ => raise Fail "Iflow.doAll: Lvar" 1646 | Lvar _ => raise Fail "Iflow.doAll: Lvar"
1412 | Func (f, es) => if String.isPrefix "un" f then 1647 | Func (UnCon _, [e]) => doOne e
1413 doOne e 1648 | Func (_, es) => app doAll es
1414 else
1415 app doAll es
1416 | Recd xes => app (doAll o #2) xes 1649 | Recd xes => app (doAll o #2) xes
1417 | Proj _ => doOne e 1650 | Proj _ => doOne e
1418 | Finish => () 1651 | Finish => ()
1419 in 1652 in
1420 doAll e 1653 doAll e