comparison src/iflow.sml @ 1243:e754dc92c47c

Parsing boolean SQL constants and fixing a related prover bug
author Adam Chlipala <adamc@hcoop.net>
date Sun, 18 Apr 2010 10:56:39 -0400
parents 4ed556678214
children 1eedc9086e6c
comparison
equal deleted inserted replaced
1242:4ed556678214 1243:e754dc92c47c
298 298
299 fun p_rep n = 299 fun p_rep n =
300 case !(#Rep (unNode n)) of 300 case !(#Rep (unNode n)) of
301 SOME n => p_rep n 301 SOME n => p_rep n
302 | NONE => 302 | NONE =>
303 box [string (Int.toString 0(*Unsafe.cast n*) ^ ":"), 303 box [(*string (Int.toString (Unsafe.cast n) ^ ":"),
304 space, 304 space,*)
305 case #Variety (unNode n) of 305 case #Variety (unNode n) of
306 Nothing => string "?" 306 Nothing => string "?"
307 | Dt0 s => string ("Dt0(" ^ s ^ ")") 307 | Dt0 s => string ("Dt0(" ^ s ^ ")")
308 | Dt1 (s, n) => box[string ("Dt1(" ^ s ^ ","), 308 | Dt1 (s, n) => box[string ("Dt1(" ^ s ^ ","),
309 space, 309 space,
535 end 535 end
536 536
537 fun p_repOf db e = p_rep (representative (db, e)) 537 fun p_repOf db e = p_rep (representative (db, e))
538 538
539 fun assert (db, a) = 539 fun assert (db, a) =
540 case a of 540 let
541 ACond _ => () 541 fun markEq (r1, r2) =
542 | AReln x =>
543 case x of
544 (Known, [e]) =>
545 ((*Print.prefaces "Before" [("e", p_exp e),
546 ("db", p_database db)];*)
547 markKnown (representative (db, e))(*;
548 Print.prefaces "After" [("e", p_exp e),
549 ("db", p_database db)]*))
550 | (PCon0 f, [e]) =>
551 let 542 let
552 val r = representative (db, e) 543 val r1 = repOf r1
544 val r2 = repOf r2
553 in 545 in
554 case #Variety (unNode r) of 546 if r1 = r2 then
555 Dt0 f' => if f = f' then 547 ()
556 () 548 else case (#Variety (unNode r1), #Variety (unNode r2)) of
557 else 549 (Prim p1, Prim p2) => if Prim.equal (p1, p2) then
558 raise Contradiction 550 ()
559 | Nothing => 551 else
560 let 552 raise Contradiction
561 val r' = ref (Node {Rep = ref NONE, 553 | (Dt0 f1, Dt0 f2) => if f1 = f2 then
562 Cons = ref SM.empty, 554 ()
563 Variety = Dt0 f, 555 else
564 Known = ref false}) 556 raise Contradiction
565 in 557 | (Dt1 (f1, r1), Dt1 (f2, r2)) => if f1 = f2 then
566 #Rep (unNode r) := SOME r' 558 markEq (r1, r2)
567 end 559 else
568 | _ => raise Contradiction 560 raise Contradiction
561 | (Recrd (xes1, _), Recrd (xes2, _)) =>
562 let
563 fun unif (xes1, xes2) =
564 SM.appi (fn (x, r1) =>
565 case SM.find (!xes2, x) of
566 NONE => xes2 := SM.insert (!xes2, x, r1)
567 | SOME r2 => markEq (r1, r2)) (!xes1)
568 in
569 unif (xes1, xes2);
570 unif (xes2, xes1)
571 end
572 | (Nothing, _) => mergeNodes (r1, r2)
573 | (_, Nothing) => mergeNodes (r2, r1)
574 | _ => raise Contradiction
569 end 575 end
570 | (PCon1 f, [e]) => 576
577 and mergeNodes (r1, r2) =
578 (#Rep (unNode r1) := SOME r2;
579 if !(#Known (unNode r1)) then
580 markKnown r2
581 else
582 ();
583 if !(#Known (unNode r2)) then
584 markKnown r1
585 else
586 ();
587 #Cons (unNode r2) := SM.unionWith #1 (!(#Cons (unNode r2)), !(#Cons (unNode r1)));
588
589 compactFuncs ())
590
591 and compactFuncs () =
571 let 592 let
572 val r = representative (db, e) 593 fun loop funcs =
594 case funcs of
595 [] => []
596 | (fr as ((f, rs), r)) :: rest =>
597 let
598 val rest = List.filter (fn ((f' : string, rs'), r') =>
599 if f' = f
600 andalso ListPair.allEq (fn (r1, r2) =>
601 repOf r1 = repOf r2)
602 (rs, rs') then
603 (markEq (r, r');
604 false)
605 else
606 true) rest
607 in
608 fr :: loop rest
609 end
573 in 610 in
574 case #Variety (unNode r) of 611 #Funcs db := loop (!(#Funcs db))
575 Dt1 (f', e') => if f = f' then
576 ()
577 else
578 raise Contradiction
579 | Nothing =>
580 let
581 val r'' = ref (Node {Rep = ref NONE,
582 Cons = ref SM.empty,
583 Variety = Nothing,
584 Known = ref (!(#Known (unNode r)))})
585
586 val r' = ref (Node {Rep = ref NONE,
587 Cons = ref SM.empty,
588 Variety = Dt1 (f, r''),
589 Known = #Known (unNode r)})
590 in
591 #Rep (unNode r) := SOME r'
592 end
593 | _ => raise Contradiction
594 end 612 end
595 | (Eq, [e1, e2]) => 613 in
596 let 614 case a of
597 fun markEq (r1, r2) = 615 ACond _ => ()
598 let 616 | AReln x =>
599 val r1 = repOf r1 617 case x of
600 val r2 = repOf r2 618 (Known, [e]) =>
601 in 619 ((*Print.prefaces "Before" [("e", p_exp e),
602 if r1 = r2 then 620 ("db", p_database db)];*)
603 () 621 markKnown (representative (db, e))(*;
604 else case (#Variety (unNode r1), #Variety (unNode r2)) of 622 Print.prefaces "After" [("e", p_exp e),
605 (Prim p1, Prim p2) => if Prim.equal (p1, p2) then 623 ("db", p_database db)]*))
606 () 624 | (PCon0 f, [e]) =>
607 else 625 let
608 raise Contradiction 626 val r = representative (db, e)
609 | (Dt0 f1, Dt0 f2) => if f1 = f2 then 627 in
610 () 628 case #Variety (unNode r) of
611 else 629 Dt0 f' => if f = f' then
612 raise Contradiction 630 ()
613 | (Dt1 (f1, r1), Dt1 (f2, r2)) => if f1 = f2 then 631 else
614 markEq (r1, r2) 632 raise Contradiction
615 else 633 | Nothing =>
616 raise Contradiction 634 (case SM.find (!(#Con0s db), f) of
617 | (Recrd (xes1, _), Recrd (xes2, _)) => 635 SOME r' => markEq (r, r')
618 let 636 | NONE =>
619 fun unif (xes1, xes2) = 637 let
620 SM.appi (fn (x, r1) => 638 val r' = ref (Node {Rep = ref NONE,
621 case SM.find (!xes2, x) of 639 Cons = ref SM.empty,
622 NONE => xes2 := SM.insert (!xes2, x, r1) 640 Variety = Dt0 f,
623 | SOME r2 => markEq (r1, r2)) (!xes1) 641 Known = ref false})
624 in 642 in
625 unif (xes1, xes2); 643 #Rep (unNode r) := SOME r';
626 unif (xes2, xes1) 644 #Con0s db := SM.insert (!(#Con0s db), f, r')
627 end 645 end)
628 | (Nothing, _) => mergeNodes (r1, r2) 646 | _ => raise Contradiction
629 | (_, Nothing) => mergeNodes (r2, r1) 647 end
630 | _ => raise Contradiction 648 | (PCon1 f, [e]) =>
631 end 649 let
632 650 val r = representative (db, e)
633 and mergeNodes (r1, r2) = 651 in
634 (#Rep (unNode r1) := SOME r2; 652 case #Variety (unNode r) of
635 if !(#Known (unNode r1)) then 653 Dt1 (f', e') => if f = f' then
636 markKnown r2 654 ()
637 else 655 else
638 (); 656 raise Contradiction
639 if !(#Known (unNode r2)) then 657 | Nothing =>
640 markKnown r1 658 let
641 else 659 val r'' = ref (Node {Rep = ref NONE,
642 (); 660 Cons = ref SM.empty,
643 #Cons (unNode r2) := SM.unionWith #1 (!(#Cons (unNode r2)), !(#Cons (unNode r1))); 661 Variety = Nothing,
644 662 Known = ref (!(#Known (unNode r)))})
645 compactFuncs ()) 663
646 664 val r' = ref (Node {Rep = ref NONE,
647 and compactFuncs () = 665 Cons = ref SM.empty,
648 let 666 Variety = Dt1 (f, r''),
649 fun loop funcs = 667 Known = #Known (unNode r)})
650 case funcs of 668 in
651 [] => [] 669 #Rep (unNode r) := SOME r'
652 | (fr as ((f, rs), r)) :: rest => 670 end
653 let 671 | _ => raise Contradiction
654 val rest = List.filter (fn ((f' : string, rs'), r') => 672 end
655 if f' = f 673 | (Eq, [e1, e2]) =>
656 andalso ListPair.allEq (fn (r1, r2) =>
657 repOf r1 = repOf r2)
658 (rs, rs') then
659 (markEq (r, r');
660 false)
661 else
662 true) rest
663 in
664 fr :: loop rest
665 end
666 in
667 #Funcs db := loop (!(#Funcs db))
668 end
669 in
670 markEq (representative (db, e1), representative (db, e2)) 674 markEq (representative (db, e1), representative (db, e2))
671 end 675 | _ => ()
672 | _ => () 676 end
673 677
674 fun check (db, a) = 678 fun check (db, a) =
675 case a of 679 case a of
676 ACond _ => false 680 ACond _ => false
677 | AReln x => 681 | AReln x =>
949 Exps of exp * exp -> prop 953 Exps of exp * exp -> prop
950 | Props of prop * prop -> prop 954 | Props of prop * prop -> prop
951 955
952 datatype sqexp = 956 datatype sqexp =
953 SqConst of Prim.t 957 SqConst of Prim.t
958 | SqTrue
959 | SqFalse
954 | Field of string * string 960 | Field of string * string
955 | Computed of string 961 | Computed of string
956 | Binop of Rel * sqexp * sqexp 962 | Binop of Rel * sqexp * sqexp
957 | SqKnown of sqexp 963 | SqKnown of sqexp
958 | Inj of Mono.exp 964 | Inj of Mono.exp
1019 Exp (EFfiApp ("Basis", f, [e]), _) :: chs => 1025 Exp (EFfiApp ("Basis", f, [e]), _) :: chs =>
1020 if String.isPrefix "sqlify" f then 1026 if String.isPrefix "sqlify" f then
1021 SOME (e, chs) 1027 SOME (e, chs)
1022 else 1028 else
1023 NONE 1029 NONE
1030 | Exp (ECase (e, [((PCon (_, PConFfi {mod = "Basis", con = "True", ...}, NONE), _),
1031 (EPrim (Prim.String "TRUE"), _)),
1032 ((PCon (_, PConFfi {mod = "Basis", con = "False", ...}, NONE), _),
1033 (EPrim (Prim.String "FALSE"), _))], _), _) :: chs =>
1034 SOME (e, chs)
1035
1024 | _ => NONE 1036 | _ => NONE
1025 1037
1026 fun constK s = wrap (const s) (fn () => s) 1038 fun constK s = wrap (const s) (fn () => s)
1027 1039
1028 val funcName = altL [constK "COUNT", 1040 val funcName = altL [constK "COUNT",
1032 constK "AVG"] 1044 constK "AVG"]
1033 1045
1034 fun sqexp chs = 1046 fun sqexp chs =
1035 log "sqexp" 1047 log "sqexp"
1036 (altL [wrap prim SqConst, 1048 (altL [wrap prim SqConst,
1049 wrap (const "TRUE") (fn () => SqTrue),
1050 wrap (const "FALSE") (fn () => SqFalse),
1037 wrap field Field, 1051 wrap field Field,
1038 wrap uw_ident Computed, 1052 wrap uw_ident Computed,
1039 wrap known SqKnown, 1053 wrap known SqKnown,
1040 wrap func SqFunc, 1054 wrap func SqFunc,
1041 wrap (const "COUNT(*)") (fn () => Count), 1055 wrap (const "COUNT(*)") (fn () => Count),
1102 Query1 of query1 1116 Query1 of query1
1103 | Union of query * query 1117 | Union of query * query
1104 1118
1105 val orderby = log "orderby" 1119 val orderby = log "orderby"
1106 (wrap (follow (ws (const "ORDER BY ")) 1120 (wrap (follow (ws (const "ORDER BY "))
1107 (list sqexp)) 1121 (follow (list sqexp)
1108 ignore) 1122 (opt (ws (const "DESC")))))
1123 ignore)
1109 1124
1110 fun query chs = log "query" 1125 fun query chs = log "query"
1111 (wrap 1126 (wrap
1112 (follow 1127 (follow
1113 (alt (wrap (follow (const "((") 1128 (alt (wrap (follow (const "((")
1264 orelse tryAll unifs hyps 1279 orelse tryAll unifs hyps
1265 | _ :: hyps => tryAll unifs hyps 1280 | _ :: hyps => tryAll unifs hyps
1266 in 1281 in
1267 tryAll unifs hyps 1282 tryAll unifs hyps
1268 end 1283 end
1269 | AReln (r, es) :: goals => 1284 | (g as AReln (r, es)) :: goals =>
1270 Cc.check (db, AReln (r, map (simplify unifs) es)) 1285 Cc.check (db, AReln (r, map (simplify unifs) es))
1271 andalso checkGoals goals unifs 1286 andalso checkGoals goals unifs
1272 | ACond _ :: _ => false 1287 | ACond _ :: _ => false
1273 in 1288 in
1274 checkGoals goals IM.empty 1289 checkGoals goals IM.empty
1350 let 1365 let
1351 val (_, hs) = !hyps 1366 val (_, hs) = !hyps
1352 in 1367 in
1353 ErrorMsg.errorAt loc "The information flow policy may be violated here."; 1368 ErrorMsg.errorAt loc "The information flow policy may be violated here.";
1354 Print.prefaces "Situation" [("Hypotheses", Print.p_list p_atom hs), 1369 Print.prefaces "Situation" [("Hypotheses", Print.p_list p_atom hs),
1355 ("User learns", p_exp e)] 1370 ("User learns", p_exp e),
1371 ("E-graph", Cc.p_database db)]
1356 end 1372 end
1357 end 1373 end
1358 1374
1359 fun checkPaths () = 1375 fun checkPaths () =
1360 let 1376 let
1369 buildable true e)) (!path); 1385 buildable true e)) (!path);
1370 setHyps hs 1386 setHyps hs
1371 end 1387 end
1372 1388
1373 fun allowSend v = ((*Print.prefaces "Allow" [("goals", Print.p_list p_atom (#1 v)), 1389 fun allowSend v = ((*Print.prefaces "Allow" [("goals", Print.p_list p_atom (#1 v)),
1374 ("exps", Print.p_list p_exp (#2 v))];*) 1390 ("exps", Print.p_list p_exp (#2 v))];*)
1375 sendable := v :: !sendable) 1391 sendable := v :: !sendable)
1376 1392
1377 fun send uk (e, loc) = ((*Print.preface ("Send", p_exp e);*) 1393 fun send uk (e, loc) = ((*Print.preface ("Send", p_exp e);*)
1378 checkPaths (); 1394 checkPaths ();
1379 if isKnown e then 1395 if isKnown e then
1472 let 1488 let
1473 fun default () = inl (rv ()) 1489 fun default () = inl (rv ())
1474 in 1490 in
1475 case e of 1491 case e of
1476 SqConst p => inl (Const p) 1492 SqConst p => inl (Const p)
1493 | SqTrue => inl (Func (DtCon0 "Basis.bool.True", []))
1494 | SqFalse => inl (Func (DtCon0 "Basis.bool.False", []))
1477 | Field (v, f) => inl (Proj (rvOf v, f)) 1495 | Field (v, f) => inl (Proj (rvOf v, f))
1478 | Computed _ => default () 1496 | Computed _ => default ()
1479 | Binop (bo, e1, e2) => 1497 | Binop (bo, e1, e2) =>
1480 let 1498 let
1481 val e1 = expIn e1 1499 val e1 = expIn e1
1482 val e2 = expIn e2 1500 val e2 = expIn e2
1483 in 1501 in
1484 inr (case (bo, e1, e2) of 1502 inr (case (bo, e1, e2) of
1485 (Exps f, inl e1, inl e2) => f (e1, e2) 1503 (Exps f, inl e1, inl e2) => f (e1, e2)
1486 | (Props f, inr p1, inr p2) => f (p1, p2) 1504 | (Props f, v1, v2) =>
1505 let
1506 fun pin v =
1507 case v of
1508 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])])
1509 | inr p => p
1510 in
1511 f (pin v1, pin v2)
1512 end
1487 | _ => Unknown) 1513 | _ => Unknown)
1488 end 1514 end
1489 | SqKnown e => 1515 | SqKnown e =>
1490 (case expIn e of 1516 (case expIn e of
1491 inl e => inr (Reln (Known, [e])) 1517 inl e => inr (Reln (Known, [e]))
1578 fun addFrom () = app (fn (t, v) => #Add arg (AReln (Sql t, [rvOf v]))) (#From r) 1604 fun addFrom () = app (fn (t, v) => #Add arg (AReln (Sql t, [rvOf v]))) (#From r)
1579 1605
1580 fun usedFields e = 1606 fun usedFields e =
1581 case e of 1607 case e of
1582 SqConst _ => [] 1608 SqConst _ => []
1609 | SqTrue => []
1610 | SqFalse => []
1583 | Field (v, f) => [(false, Proj (rvOf v, f))] 1611 | Field (v, f) => [(false, Proj (rvOf v, f))]
1584 | Computed _ => [] 1612 | Computed _ => []
1585 | Binop (_, e1, e2) => usedFields e1 @ usedFields e2 1613 | Binop (_, e1, e2) => usedFields e1 @ usedFields e2
1586 | SqKnown _ => [] 1614 | SqKnown _ => []
1587 | Inj e => 1615 | Inj e =>
1641 fun doWhere final = 1669 fun doWhere final =
1642 (addFrom (); 1670 (addFrom ();
1643 case #Where r of 1671 case #Where r of
1644 NONE => (doUsed (); final ()) 1672 NONE => (doUsed (); final ())
1645 | SOME e => 1673 | SOME e =>
1646 case expIn e of 1674 let
1647 inl _ => (doUsed (); final ()) 1675 val p = case expIn e of
1648 | inr p => 1676 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])])
1649 let 1677 | inr p => p
1650 val saved = #Save arg () 1678
1651 in 1679 val saved = #Save arg ()
1652 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg} 1680 in
1653 p (fn () => (doUsed (); final ()) handle Cc.Contradiction => ()); 1681 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg}
1654 #Restore arg saved 1682 p (fn () => (doUsed (); final ()) handle Cc.Contradiction => ());
1655 end) 1683 #Restore arg saved
1684 end)
1656 handle Cc.Contradiction => () 1685 handle Cc.Contradiction => ()
1657 1686
1658 fun normal () = doWhere normal' 1687 fun normal () = doWhere normal'
1659 in 1688 in
1660 (case #Select r of 1689 (case #Select r of