comparison src/iflow.sml @ 1253:9d65866ab9ab

Some Iflow improvements for gradebook
author Adam Chlipala <adamc@hcoop.net>
date Thu, 06 May 2010 12:14:00 -0400
parents 2e4159a7d2d3
children 3d06e0f7a6f3
comparison
equal deleted inserted replaced
1252:2e4159a7d2d3 1253:9d65866ab9ab
240 val assert : database * atom -> unit 240 val assert : database * atom -> unit
241 val check : database * atom -> bool 241 val check : database * atom -> bool
242 242
243 val p_database : database Print.printer 243 val p_database : database Print.printer
244 244
245 val builtFrom : database * {UseKnown : bool, Base : exp list, Derived : exp} -> bool 245 val builtFrom : database * {Base : exp list, Derived : exp} -> bool
246 246
247 val p_repOf : database -> exp Print.printer 247 val p_repOf : database -> exp Print.printer
248 end = struct 248 end = struct
249 249
250 local 250 local
702 () 702 ()
703 else 703 else
704 raise Contradiction 704 raise Contradiction
705 | Nothing => 705 | Nothing =>
706 let 706 let
707 val cons = ref SM.empty
708
707 val r'' = ref (Node {Id = nodeId (), 709 val r'' = ref (Node {Id = nodeId (),
708 Rep = ref NONE, 710 Rep = ref NONE,
709 Cons = ref SM.empty, 711 Cons = cons,
710 Variety = Nothing, 712 Variety = Nothing,
711 Known = ref (!(#Known (unNode r))), 713 Known = ref (!(#Known (unNode r))),
712 Ge = ref NONE}) 714 Ge = ref NONE})
713 715
714 val r' = ref (Node {Id = nodeId (), 716 val r' = ref (Node {Id = nodeId (),
716 Cons = ref SM.empty, 718 Cons = ref SM.empty,
717 Variety = Dt1 (f, r''), 719 Variety = Dt1 (f, r''),
718 Known = #Known (unNode r), 720 Known = #Known (unNode r),
719 Ge = ref NONE}) 721 Ge = ref NONE})
720 in 722 in
723 cons := SM.insert (!cons, f, r');
721 #Rep (unNode r) := SOME r' 724 #Rep (unNode r) := SOME r'
722 end 725 end
723 | _ => raise Contradiction 726 | _ => raise Contradiction
724 end 727 end
725 | (Eq, [e1, e2]) => 728 | (Eq, [e1, e2]) =>
786 | _ => false 789 | _ => false
787 end 790 end
788 | _ => false) 791 | _ => false)
789 handle Undetermined => false 792 handle Undetermined => false
790 793
791 fun builtFrom (db, {UseKnown = uk, Base = bs, Derived = d}) = 794 fun builtFrom (db, {Base = bs, Derived = d}) =
792 let 795 let
793 val bs = map (fn b => representative (db, b)) bs 796 val bs = map (fn b => representative (db, b)) bs
794 797
795 fun loop d = 798 fun loop d =
796 let 799 let
797 val d = repOf d 800 val d = repOf d
798 in 801 in
799 (uk andalso !(#Known (unNode d))) 802 !(#Known (unNode d))
800 orelse List.exists (fn b => repOf b = d) bs 803 orelse List.exists (fn b => repOf b = d) bs
801 orelse (case #Variety (unNode d) of 804 orelse (case #Variety (unNode d) of
802 Dt0 _ => true 805 Dt0 _ => true
803 | Dt1 (_, d) => loop d 806 | Dt1 (_, d) => loop d
804 | Prim _ => true 807 | Prim _ => true
805 | Recrd (xes, _) => List.all loop (SM.listItems (!xes)) 808 | Recrd (xes, _) => List.all loop (SM.listItems (!xes))
806 | Nothing => false) 809 | Nothing => false)
810 orelse List.exists (fn r => List.exists (fn b => repOf b = repOf r) bs)
811 (SM.listItems (!(#Cons (unNode d))))
807 end 812 end
808 813
809 fun decomp e = 814 fun decomp e =
810 case e of 815 case e of
811 Func (Other _, es) => List.all decomp es 816 Func (Other _, es) => List.all decomp es
978 | Binop of Rel * sqexp * sqexp 983 | Binop of Rel * sqexp * sqexp
979 | SqKnown of sqexp 984 | SqKnown of sqexp
980 | Inj of Mono.exp 985 | Inj of Mono.exp
981 | SqFunc of string * sqexp 986 | SqFunc of string * sqexp
982 | Unmodeled 987 | Unmodeled
988 | Null
983 989
984 fun cmp s r = wrap (const s) (fn () => Exps (fn (e1, e2) => Reln (r, [e1, e2]))) 990 fun cmp s r = wrap (const s) (fn () => Exps (fn (e1, e2) => Reln (r, [e1, e2])))
985 991
986 val sqbrel = altL [cmp "=" Eq, 992 val sqbrel = altL [cmp "=" Eq,
987 cmp "<>" Ne, 993 cmp "<>" Ne,
1065 fun sqexp chs = 1071 fun sqexp chs =
1066 log "sqexp" 1072 log "sqexp"
1067 (altL [wrap prim SqConst, 1073 (altL [wrap prim SqConst,
1068 wrap (const "TRUE") (fn () => SqTrue), 1074 wrap (const "TRUE") (fn () => SqTrue),
1069 wrap (const "FALSE") (fn () => SqFalse), 1075 wrap (const "FALSE") (fn () => SqFalse),
1076 wrap (const "NULL") (fn () => Null),
1070 wrap field Field, 1077 wrap field Field,
1071 wrap uw_ident Computed, 1078 wrap uw_ident Computed,
1072 wrap known SqKnown, 1079 wrap known SqKnown,
1073 wrap func SqFunc, 1080 wrap func SqFunc,
1074 wrap unmodeled (fn () => Unmodeled), 1081 wrap unmodeled (fn () => Unmodeled),
1217 val assert : atom list -> unit 1224 val assert : atom list -> unit
1218 1225
1219 val addPath : check -> unit 1226 val addPath : check -> unit
1220 1227
1221 val allowSend : atom list * exp list -> unit 1228 val allowSend : atom list * exp list -> unit
1222 val send : bool -> check -> unit 1229 val send : check -> unit
1223 1230
1224 val allowInsert : atom list -> unit 1231 val allowInsert : atom list -> unit
1225 val insert : ErrorMsg.span -> unit 1232 val insert : ErrorMsg.span -> unit
1226 1233
1227 val allowDelete : atom list -> unit 1234 val allowDelete : atom list -> unit
1402 | ACond _ :: _ => false 1409 | ACond _ :: _ => false
1403 in 1410 in
1404 checkGoals goals IM.empty 1411 checkGoals goals IM.empty
1405 end 1412 end
1406 1413
1407 fun buildable uk (e, loc) = 1414 fun buildable (e, loc) =
1408 let 1415 let
1409 fun doPols pols acc = 1416 fun doPols pols acc =
1410 case pols of 1417 case pols of
1411 [] => ((*Print.prefaces "buildable" [("Base", Print.p_list p_exp acc), 1418 [] =>
1412 ("Derived", p_exp e), 1419 let
1413 ("Hyps", Print.p_list p_atom (#2 (!hyps)))];*) 1420 val b = Cc.builtFrom (db, {Base = acc, Derived = e})
1414 Cc.builtFrom (db, {UseKnown = uk, Base = acc, Derived = e})) 1421 in
1422 (*Print.prefaces "buildable" [("Base", Print.p_list p_exp acc),
1423 ("Derived", p_exp e),
1424 ("Hyps", Print.p_list p_atom (#2 (!hyps))),
1425 ("Good", Print.PD.string (Bool.toString b))];*)
1426 b
1427 end
1415 | (goals, es) :: pols => 1428 | (goals, es) :: pols =>
1416 checkGoals goals (fn unifs => doPols pols (map (simplify unifs) es @ acc)) 1429 checkGoals goals (fn unifs => doPols pols (map (simplify unifs) es @ acc))
1417 orelse doPols pols acc 1430 orelse doPols pols acc
1418 in 1431 in
1419 if doPols (!sendable) [] then 1432 if doPols (!sendable) [] then
1422 let 1435 let
1423 val (_, hs, _) = !hyps 1436 val (_, hs, _) = !hyps
1424 in 1437 in
1425 ErrorMsg.errorAt loc "The information flow policy may be violated here."; 1438 ErrorMsg.errorAt loc "The information flow policy may be violated here.";
1426 Print.prefaces "Situation" [("User learns", p_exp e), 1439 Print.prefaces "Situation" [("User learns", p_exp e),
1427 ("Hypotheses", Print.p_list p_atom hs)(*, 1440 ("Hypotheses", Print.p_list p_atom hs),
1428 ("E-graph", Cc.p_database db)*)] 1441 ("E-graph", Cc.p_database db)]
1429 end 1442 end
1430 end 1443 end
1431 1444
1432 fun checkPaths () = 1445 fun checkPaths () =
1433 let 1446 let
1438 case !r of 1451 case !r of
1439 NONE => () 1452 NONE => ()
1440 | SOME (hs, e) => 1453 | SOME (hs, e) =>
1441 (r := NONE; 1454 (r := NONE;
1442 setHyps hs; 1455 setHyps hs;
1443 buildable true e)) (!path); 1456 buildable e)) (!path);
1444 setHyps hs 1457 setHyps hs
1445 end 1458 end
1446 1459
1447 fun allowSend v = ((*Print.prefaces "Allow" [("goals", Print.p_list p_atom (#1 v)), 1460 fun allowSend v = ((*Print.prefaces "Allow" [("goals", Print.p_list p_atom (#1 v)),
1448 ("exps", Print.p_list p_exp (#2 v))];*) 1461 ("exps", Print.p_list p_exp (#2 v))];*)
1449 sendable := v :: !sendable) 1462 sendable := v :: !sendable)
1450 1463
1451 fun send uk (e, loc) = ((*Print.preface ("Send", p_exp e);*) 1464 fun send (e, loc) = ((*Print.preface ("Send[" ^ Bool.toString uk ^ "]", p_exp e);*)
1452 complete (); 1465 complete ();
1453 checkPaths (); 1466 checkPaths ();
1454 if isKnown e then 1467 if isKnown e then
1455 () 1468 ()
1456 else 1469 else
1457 buildable uk (e, loc)) 1470 buildable (e, loc))
1458 1471
1459 fun doable pols (loc : ErrorMsg.span) = 1472 fun doable pols (loc : ErrorMsg.span) =
1460 let 1473 let
1461 val pols = !pols 1474 val pols = !pols
1462 in 1475 in
1569 in 1582 in
1570 case e of 1583 case e of
1571 SqConst p => inl (Const p) 1584 SqConst p => inl (Const p)
1572 | SqTrue => inl (Func (DtCon0 "Basis.bool.True", [])) 1585 | SqTrue => inl (Func (DtCon0 "Basis.bool.True", []))
1573 | SqFalse => inl (Func (DtCon0 "Basis.bool.False", [])) 1586 | SqFalse => inl (Func (DtCon0 "Basis.bool.False", []))
1587 | Null => inl (Func (DtCon0 "None", []))
1574 | SqNot e => 1588 | SqNot e =>
1575 inr (case expIn e of 1589 inr (case expIn e of
1576 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.False", [])]) 1590 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.False", [])])
1577 | inr _ => Unknown) 1591 | inr _ => Unknown)
1578 | Field (v, f) => inl (Proj (rvOf v, f)) 1592 | Field (v, f) => inl (Proj (rvOf v, f))
1644 Env : exp list, 1658 Env : exp list,
1645 NextVar : unit -> exp, 1659 NextVar : unit -> exp,
1646 Add : atom -> unit, 1660 Add : atom -> unit,
1647 Save : unit -> 'a, 1661 Save : unit -> 'a,
1648 Restore : 'a -> unit, 1662 Restore : 'a -> unit,
1649 UsedExp : bool * exp -> unit,
1650 Cont : queryMode 1663 Cont : queryMode
1651 } 1664 }
1652 1665
1653 fun doQuery (arg : 'a doQuery) (e as (_, loc)) = 1666 fun doQuery (arg : 'a doQuery) (e as (_, loc)) =
1654 let 1667 let
1689 fun usedFields e = 1702 fun usedFields e =
1690 case e of 1703 case e of
1691 SqConst _ => [] 1704 SqConst _ => []
1692 | SqTrue => [] 1705 | SqTrue => []
1693 | SqFalse => [] 1706 | SqFalse => []
1707 | Null => []
1694 | SqNot e => usedFields e 1708 | SqNot e => usedFields e
1695 | Field (v, f) => [(false, Proj (rvOf v, f))] 1709 | Field (v, f) => [(false, Proj (rvOf v, f))]
1696 | Computed _ => [] 1710 | Computed _ => []
1697 | Binop (_, e1, e2) => usedFields e1 @ usedFields e2 1711 | Binop (_, e1, e2) => usedFields e1 @ usedFields e2
1698 | SqKnown _ => [] 1712 | SqKnown _ => []
1701 NONE => (ErrorMsg.errorAt loc "Expression injected into SQL is too complicated"; 1715 NONE => (ErrorMsg.errorAt loc "Expression injected into SQL is too complicated";
1702 []) 1716 [])
1703 | SOME e => [(true, e)]) 1717 | SOME e => [(true, e)])
1704 | SqFunc (_, e) => usedFields e 1718 | SqFunc (_, e) => usedFields e
1705 | Unmodeled => [] 1719 | Unmodeled => []
1706
1707 fun doUsed () = case #Where r of
1708 NONE => ()
1709 | SOME e =>
1710 app (#UsedExp arg) (usedFields e)
1711 1720
1712 fun normal' () = 1721 fun normal' () =
1713 case #Cont arg of 1722 case #Cont arg of
1714 SomeCol k => 1723 SomeCol k =>
1715 let 1724 let
1751 end 1760 end
1752 1761
1753 fun doWhere final = 1762 fun doWhere final =
1754 (addFrom (); 1763 (addFrom ();
1755 case #Where r of 1764 case #Where r of
1756 NONE => (doUsed (); final ()) 1765 NONE => final ()
1757 | SOME e => 1766 | SOME e =>
1758 let 1767 let
1759 val p = case expIn e of 1768 val p = case expIn e of
1760 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])]) 1769 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])])
1761 | inr p => p 1770 | inr p => p
1762 1771
1763 val saved = #Save arg () 1772 val saved = #Save arg ()
1764 in 1773 in
1765 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg} 1774 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg}
1766 p (fn () => (doUsed (); final ()) handle Cc.Contradiction => ()); 1775 p (fn () => final () handle Cc.Contradiction => ());
1767 #Restore arg saved 1776 #Restore arg saved
1768 end) 1777 end)
1769 handle Cc.Contradiction => () 1778 handle Cc.Contradiction => ()
1770 1779
1771 fun normal () = doWhere normal' 1780 fun normal () = doWhere normal'
1858 | _ => () 1867 | _ => ()
1859 else 1868 else
1860 (); 1869 ();
1861 k (Recd [])) 1870 k (Recd []))
1862 | e :: es => 1871 | e :: es =>
1863 evalExp env e (fn e => (St.send true (e, loc); doArgs es)) 1872 evalExp env e (fn e => (St.send (e, loc); doArgs es))
1864 in 1873 in
1865 doArgs es 1874 doArgs es
1866 end 1875 end
1867 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then 1876 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then
1868 default () 1877 default ()
1970 | EField (e, s) => evalExp env e (fn e => k (Proj (e, s))) 1979 | EField (e, s) => evalExp env e (fn e => k (Proj (e, s)))
1971 | ECase (e, pes, {result = res, ...}) => 1980 | ECase (e, pes, {result = res, ...}) =>
1972 evalExp env e (fn e => 1981 evalExp env e (fn e =>
1973 if List.all (fn (_, (EWrite (EPrim _, _), _)) => true 1982 if List.all (fn (_, (EWrite (EPrim _, _), _)) => true
1974 | _ => false) pes then 1983 | _ => false) pes then
1975 (St.send true (e, loc); 1984 (St.send (e, loc);
1976 k (Recd [])) 1985 k (Recd []))
1977 else 1986 else
1978 (St.addPath (e, loc); 1987 (St.addPath (e, loc);
1979 app (fn (p, pe) => 1988 app (fn (p, pe) =>
1980 let 1989 let
1990 end) pes)) 1999 end) pes))
1991 | EStrcat (e1, e2) => 2000 | EStrcat (e1, e2) =>
1992 evalExp env e1 (fn e1 => 2001 evalExp env e1 (fn e1 =>
1993 evalExp env e2 (fn e2 => 2002 evalExp env e2 (fn e2 =>
1994 k (Func (Other "cat", [e1, e2])))) 2003 k (Func (Other "cat", [e1, e2]))))
1995 | EError (e, _) => evalExp env e (fn e => St.send true (e, loc)) 2004 | EError (e, _) => evalExp env e (fn e => St.send (e, loc))
1996 | EReturnBlob {blob = b, mimeType = m, ...} => 2005 | EReturnBlob {blob = b, mimeType = m, ...} =>
1997 evalExp env b (fn b => 2006 evalExp env b (fn b =>
1998 (St.send true (b, loc); 2007 (St.send (b, loc);
1999 evalExp env m 2008 evalExp env m
2000 (fn m => St.send true (m, loc)))) 2009 (fn m => St.send (m, loc))))
2001 | ERedirect (e, _) => 2010 | ERedirect (e, _) =>
2002 evalExp env e (fn e => St.send true (e, loc)) 2011 evalExp env e (fn e => St.send (e, loc))
2003 | EWrite e => 2012 | EWrite e =>
2004 evalExp env e (fn e => (St.send true (e, loc); 2013 evalExp env e (fn e => (St.send (e, loc);
2005 k (Recd []))) 2014 k (Recd [])))
2006 | ESeq (e1, e2) => 2015 | ESeq (e1, e2) =>
2007 let 2016 let
2008 val path = St.stashPath () 2017 val path = St.stashPath ()
2009 in 2018 in
2065 doQuery {Env = env, 2074 doQuery {Env = env,
2066 NextVar = Var o St.nextVar, 2075 NextVar = Var o St.nextVar,
2067 Add = fn a => St.assert [a], 2076 Add = fn a => St.assert [a],
2068 Save = St.stash, 2077 Save = St.stash,
2069 Restore = St.reinstate, 2078 Restore = St.reinstate,
2070 UsedExp = fn (b, e) => St.send b (e, loc),
2071 Cont = AllCols (fn x => 2079 Cont = AllCols (fn x =>
2072 (St.assert [AReln (Eq, [r, x])]; 2080 (St.assert [AReln (Eq, [r, x])];
2073 evalExp (acc :: r :: env) b k))} q 2081 evalExp (acc :: r :: env) b k))} q
2074 end) 2082 end)
2075 | EDml e => 2083 | EDml e =>
2438 fun doQ k = doQuery {Env = [], 2446 fun doQ k = doQuery {Env = [],
2439 NextVar = rv, 2447 NextVar = rv,
2440 Add = fn a => atoms := a :: !atoms, 2448 Add = fn a => atoms := a :: !atoms,
2441 Save = fn () => !atoms, 2449 Save = fn () => !atoms,
2442 Restore = fn ls => atoms := ls, 2450 Restore = fn ls => atoms := ls,
2443 UsedExp = fn _ => (),
2444 Cont = SomeCol (fn r => k (rev (!atoms), r))} 2451 Cont = SomeCol (fn r => k (rev (!atoms), r))}
2445 2452
2446 fun untab (tab, nams) = List.filter (fn AReln (Sql tab', [Lvar lv]) => 2453 fun untab (tab, nams) = List.filter (fn AReln (Sql tab', [Lvar lv]) =>
2447 tab' <> tab 2454 tab' <> tab
2448 orelse List.all (fn Lvar lv' => lv' <> lv 2455 orelse List.all (fn Lvar lv' => lv' <> lv