Mercurial > urweb
comparison src/iflow.sml @ 1231:5fa8ae2a34e3
Avoid pointless rebuilding of hypothesis E-graphs
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 13 Apr 2010 09:25:45 -0400 |
parents | 8768145eed1e |
children | efbefd6e3f6c |
comparison
equal
deleted
inserted
replaced
1230:8768145eed1e | 1231:5fa8ae2a34e3 |
---|---|
957 decomp | 957 decomp |
958 end | 958 end |
959 | 959 |
960 val tabs = ref (SM.empty : (string list * string list list) SM.map) | 960 val tabs = ref (SM.empty : (string list * string list list) SM.map) |
961 | 961 |
962 fun imply (hyps, goals, outs) = | 962 fun ccOf hyps = |
963 let | |
964 val cc = Cc.database () | |
965 val () = app (fn a => Cc.assert (cc, a)) hyps | |
966 | |
967 (* Take advantage of table key information *) | |
968 fun findKeys hyps = | |
969 case hyps of | |
970 [] => () | |
971 | AReln (Sql tab, [r1]) :: hyps => | |
972 (case SM.find (!tabs, tab) of | |
973 NONE => findKeys hyps | |
974 | SOME (_, []) => findKeys hyps | |
975 | SOME (_, ks) => | |
976 let | |
977 fun finder hyps = | |
978 case hyps of | |
979 [] => () | |
980 | AReln (Sql tab', [r2]) :: hyps => | |
981 (if tab' = tab andalso | |
982 List.exists (List.all (fn f => | |
983 let | |
984 val r = | |
985 Cc.check (cc, | |
986 AReln (Eq, [Proj (r1, f), | |
987 Proj (r2, f)])) | |
988 in | |
989 (*Print.prefaces "Fs" | |
990 [("tab", | |
991 Print.PD.string tab), | |
992 ("r1", | |
993 p_exp (Proj (r1, f))), | |
994 ("r2", | |
995 p_exp (Proj (r2, f))), | |
996 ("r", | |
997 Print.PD.string | |
998 (Bool.toString r))];*) | |
999 r | |
1000 end)) ks then | |
1001 ((*Print.prefaces "Key match" [("tab", Print.PD.string tab), | |
1002 ("r1", p_exp r1), | |
1003 ("r2", p_exp r2), | |
1004 ("rp1", Cc.p_repOf cc r1), | |
1005 ("rp2", Cc.p_repOf cc r2)];*) | |
1006 Cc.assert (cc, AReln (Eq, [r1, r2]))) | |
1007 else | |
1008 (); | |
1009 finder hyps) | |
1010 | _ :: hyps => finder hyps | |
1011 in | |
1012 finder hyps; | |
1013 findKeys hyps | |
1014 end) | |
1015 | _ :: hyps => findKeys hyps | |
1016 in | |
1017 findKeys hyps; | |
1018 cc | |
1019 end | |
1020 | |
1021 fun imply (cc, hyps, goals, outs) = | |
963 let | 1022 let |
964 fun gls goals onFail acc = | 1023 fun gls goals onFail acc = |
965 case goals of | 1024 case goals of |
966 [] => | 1025 [] => |
967 (let | 1026 ((List.all (fn a => |
968 val cc = Cc.database () | 1027 if Cc.check (cc, a) then |
969 val () = app (fn a => Cc.assert (cc, a)) hyps | 1028 true |
970 | 1029 else |
971 (* Take advantage of table key information *) | 1030 ((*Print.prefaces "Can't prove" |
972 fun findKeys hyps = | 1031 [("a", p_atom a), |
973 case hyps of | 1032 ("hyps", Print.p_list p_atom hyps), |
974 [] => () | 1033 ("db", Cc.p_database cc)];*) |
975 | AReln (Sql tab, [r1]) :: hyps => | 1034 false)) acc |
976 (case SM.find (!tabs, tab) of | 1035 andalso ((*Print.preface ("Finding", Cc.p_database cc);*) true) |
977 NONE => findKeys hyps | 1036 andalso (case outs of |
978 | SOME (_, []) => findKeys hyps | 1037 NONE => true |
979 | SOME (_, ks) => | 1038 | SOME outs => Cc.builtFrom (cc, {Derived = Var 0, |
980 let | 1039 Base = outs}))) |
981 fun finder hyps = | 1040 handle Cc.Contradiction => false |
982 case hyps of | 1041 | Cc.Undetermined => false) |
983 [] => () | |
984 | AReln (Sql tab', [r2]) :: hyps => | |
985 (if tab' = tab andalso | |
986 List.exists (List.all (fn f => | |
987 let | |
988 val r = | |
989 Cc.check (cc, | |
990 AReln (Eq, [Proj (r1, f), | |
991 Proj (r2, f)])) | |
992 in | |
993 (*Print.prefaces "Fs" | |
994 [("tab", | |
995 Print.PD.string tab), | |
996 ("r1", | |
997 p_exp (Proj (r1, f))), | |
998 ("r2", | |
999 p_exp (Proj (r2, f))), | |
1000 ("r", | |
1001 Print.PD.string | |
1002 (Bool.toString r))];*) | |
1003 r | |
1004 end)) ks then | |
1005 ((*Print.prefaces "Key match" [("tab", Print.PD.string tab), | |
1006 ("r1", p_exp r1), | |
1007 ("r2", p_exp r2), | |
1008 ("rp1", Cc.p_repOf cc r1), | |
1009 ("rp2", Cc.p_repOf cc r2)];*) | |
1010 Cc.assert (cc, AReln (Eq, [r1, r2]))) | |
1011 else | |
1012 (); | |
1013 finder hyps) | |
1014 | _ :: hyps => finder hyps | |
1015 in | |
1016 finder hyps; | |
1017 findKeys hyps | |
1018 end) | |
1019 | _ :: hyps => findKeys hyps | |
1020 in | |
1021 findKeys hyps; | |
1022 | |
1023 (*Print.preface ("db", Cc.p_database cc);*) | |
1024 (List.all (fn a => | |
1025 if Cc.check (cc, a) then | |
1026 true | |
1027 else | |
1028 ((*Print.prefaces "Can't prove" | |
1029 [("a", p_atom a), | |
1030 ("hyps", Print.p_list p_atom hyps), | |
1031 ("db", Cc.p_database cc)];*) | |
1032 false)) acc | |
1033 andalso ((*Print.preface ("Finding", Cc.p_database cc);*) true) | |
1034 andalso (case outs of | |
1035 NONE => true | |
1036 | SOME outs => Cc.builtFrom (cc, {Derived = Var 0, | |
1037 Base = outs}))) | |
1038 handle Cc.Contradiction => false | |
1039 end handle Cc.Undetermined => false) | |
1040 orelse onFail () | 1042 orelse onFail () |
1041 | (g as AReln (Sql gf, [ge])) :: goals => | 1043 | (g as AReln (Sql gf, [ge])) :: goals => |
1042 let | 1044 let |
1043 fun hps hyps = | 1045 fun hps hyps = |
1044 case hyps of | 1046 case hyps of |
1071 in | 1073 in |
1072 reset (); | 1074 reset (); |
1073 (*Print.prefaces "Big go" [("hyps", Print.p_list p_atom hyps), | 1075 (*Print.prefaces "Big go" [("hyps", Print.p_list p_atom hyps), |
1074 ("goals", Print.p_list p_atom goals)];*) | 1076 ("goals", Print.p_list p_atom goals)];*) |
1075 gls goals (fn () => false) [] | 1077 gls goals (fn () => false) [] |
1076 end handle Cc.Contradiction => true | 1078 end |
1077 | 1079 |
1078 fun patCon pc = | 1080 fun patCon pc = |
1079 case pc of | 1081 case pc of |
1080 PConVar n => "C" ^ Int.toString n | 1082 PConVar n => "C" ^ Int.toString n |
1081 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c | 1083 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c |
2469 | 2471 |
2470 fun doDml (cmds, pols) = | 2472 fun doDml (cmds, pols) = |
2471 app (fn (loc, p) => | 2473 app (fn (loc, p) => |
2472 if decompH p | 2474 if decompH p |
2473 (fn hyps => | 2475 (fn hyps => |
2474 List.exists (fn p' => | 2476 let |
2475 if decompG p' | 2477 val cc = ccOf hyps |
2476 (fn goals => imply (hyps, goals, NONE)) then | 2478 in |
2477 ((*reset (); | 2479 List.exists (fn p' => |
2478 Print.prefaces "Match" [("hyp", p_prop p), | 2480 if decompG p' |
2479 ("goal", p_prop p')];*) | 2481 (fn goals => imply (cc, hyps, goals, NONE)) then |
2480 true) | 2482 ((*reset (); |
2481 else | 2483 Print.prefaces "Match" [("hyp", p_prop p), |
2482 false) | 2484 ("goal", p_prop p')];*) |
2483 pols) then | 2485 true) |
2486 else | |
2487 false) | |
2488 pols | |
2489 end handle Cc.Contradiction => true) then | |
2484 () | 2490 () |
2485 else | 2491 else |
2486 (ErrorMsg.errorAt loc "The information flow policy may be violated here."; | 2492 (ErrorMsg.errorAt loc "The information flow policy may be violated here."; |
2487 Print.preface ("The state satisifies this predicate:", p_prop p))) cmds | 2493 Print.preface ("The state satisifies this predicate:", p_prop p))) cmds |
2488 in | 2494 in |
2493 val p = And (p, Reln (Eq, [Var 0, e])) | 2499 val p = And (p, Reln (Eq, [Var 0, e])) |
2494 in | 2500 in |
2495 if decompH p | 2501 if decompH p |
2496 (fn hyps => | 2502 (fn hyps => |
2497 let | 2503 let |
2504 val cc = ccOf hyps | |
2505 | |
2498 val avail = foldl (fn (AReln (Sql tab, _), avail) => SS.add (avail, tab) | 2506 val avail = foldl (fn (AReln (Sql tab, _), avail) => SS.add (avail, tab) |
2499 | (_, avail) => avail) SS.empty hyps | 2507 | (_, avail) => avail) SS.empty hyps |
2500 | 2508 |
2501 fun tryCombos (maxLv, pols, g, outs) = | 2509 fun tryCombos (maxLv, pols, g, outs) = |
2502 case pols of | 2510 case pols of |
2503 [] => | 2511 [] => |
2504 decompG g | 2512 decompG g |
2505 (fn goals => imply (hyps, goals, SOME outs)) | 2513 (fn goals => imply (cc, hyps, goals, SOME outs)) |
2506 | (g1, outs1) :: pols => | 2514 | (g1, outs1) :: pols => |
2507 let | 2515 let |
2508 val g1 = bumpLvarsP (maxLv + 1) g1 | 2516 val g1 = bumpLvarsP (maxLv + 1) g1 |
2509 val outs1 = map (bumpLvars (maxLv + 1)) outs1 | 2517 val outs1 = map (bumpLvars (maxLv + 1)) outs1 |
2510 fun skip () = tryCombos (maxLv, pols, g, outs) | 2518 fun skip () = tryCombos (maxLv, pols, g, outs) |
2522 else | 2530 else |
2523 skip () | 2531 skip () |
2524 end | 2532 end |
2525 in | 2533 in |
2526 (fl <> Control Where | 2534 (fl <> Control Where |
2527 andalso imply (hyps, [AReln (Known, [Var 0])], SOME [Var 0])) | 2535 andalso imply (cc, hyps, [AReln (Known, [Var 0])], SOME [Var 0])) |
2528 orelse List.exists (fn (p', outs) => | 2536 orelse List.exists (fn (p', outs) => |
2529 decompG p' | 2537 decompG p' |
2530 (fn goals => imply (hyps, goals, SOME outs))) | 2538 (fn goals => imply (cc, hyps, goals, |
2539 SOME outs))) | |
2531 client | 2540 client |
2532 orelse tryCombos (0, client, True, []) | 2541 orelse tryCombos (0, client, True, []) |
2533 orelse (reset (); | 2542 orelse (reset (); |
2534 Print.preface ("Untenable hypotheses" | 2543 Print.preface ("Untenable hypotheses" |
2535 ^ (case fl of | 2544 ^ (case fl of |
2536 Control Where => " (WHERE clause)" | 2545 Control Where => " (WHERE clause)" |
2537 | Control Case => " (case discriminee)" | 2546 | Control Case => " (case discriminee)" |
2538 | Data => " (returned data value)"), | 2547 | Data => " (returned data value)"), |
2539 Print.p_list p_atom hyps); | 2548 Print.p_list p_atom hyps); |
2540 false) | 2549 false) |
2541 end) then | 2550 end handle Cc.Contradiction => true) then |
2542 () | 2551 () |
2543 else | 2552 else |
2544 ErrorMsg.errorAt loc "The information flow policy may be violated here." | 2553 ErrorMsg.errorAt loc "The information flow policy may be violated here." |
2545 end | 2554 end |
2546 | 2555 |
2575 handle ex => (Settings.setMonoInline oldInline; | 2584 handle ex => (Settings.setMonoInline oldInline; |
2576 raise ex) | 2585 raise ex) |
2577 end | 2586 end |
2578 | 2587 |
2579 end | 2588 end |
2580 |