Mercurial > urweb
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 |