comparison src/iflow.sml @ 1217:4d206e603300

Abstract type for evalExp state; handle WHERE conditions soundly
author Adam Chlipala <adamc@hcoop.net>
date Sat, 10 Apr 2010 10:24:13 -0400
parents 09caa8c780e5
children 48d2ca496d2c
comparison
equal deleted inserted replaced
1216:09caa8c780e5 1217:4d206e603300
835 in 835 in
836 decomp 836 decomp
837 end 837 end
838 838
839 fun imply (p1, p2) = 839 fun imply (p1, p2) =
840 (reset (); 840 decomp true (fn (e1, e2) => e1 andalso e2 ()) p1
841 (*Print.prefaces "Bigger go" [("p1", p_prop p1), 841 (fn hyps =>
842 ("p2", p_prop p2)];*) 842 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2
843 decomp true (fn (e1, e2) => e1 andalso e2 ()) p1 843 (fn goals =>
844 (fn hyps => 844 let
845 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2 845 fun gls goals onFail acc =
846 (fn goals => 846 case goals of
847 let 847 [] =>
848 fun gls goals onFail acc = 848 (let
849 case goals of 849 val cc = Cc.database ()
850 [] => 850 val () = app (fn a => Cc.assert (cc, a)) hyps
851 (let 851 in
852 val cc = Cc.database () 852 (List.all (fn a =>
853 val () = app (fn a => Cc.assert (cc, a)) hyps 853 if Cc.check (cc, a) then
854 in 854 true
855 (List.all (fn a => 855 else
856 if Cc.check (cc, a) then 856 ((*Print.prefaces "Can't prove"
857 true 857 [("a", p_atom a),
858 ("hyps", Print.p_list p_atom hyps),
859 ("db", Cc.p_database cc)];*)
860 false)) acc)
861 handle Cc.Contradiction => false
862 end handle Cc.Undetermined => false)
863 orelse onFail ()
864 | (g as AReln (Sql gf, [ge])) :: goals =>
865 let
866 fun hps hyps =
867 case hyps of
868 [] => gls goals onFail (g :: acc)
869 | (h as AReln (Sql hf, [he])) :: hyps =>
870 if gf = hf then
871 let
872 val saved = save ()
873 in
874 if eq (ge, he) then
875 let
876 val changed = IM.numItems (!unif)
877 <> IM.numItems saved
878 in
879 gls goals (fn () => (restore saved;
880 changed
881 andalso hps hyps))
882 acc
883 end
858 else 884 else
859 ((*Print.prefaces "Can't prove" 885 hps hyps
860 [("a", p_atom a), 886 end
861 ("hyps", Print.p_list p_atom hyps), 887 else
862 ("db", Cc.p_database cc)];*) 888 hps hyps
863 false)) acc 889 | _ :: hyps => hps hyps
864 orelse onFail ()) 890 in
865 handle Cc.Contradiction => onFail () 891 hps hyps
866 end handle Cc.Undetermined => ((*print "Undetermined\n";*) onFail ())) 892 end
867 | (g as AReln (Sql gf, [ge])) :: goals => 893 | g :: goals => gls goals onFail (g :: acc)
868 let 894 in
869 fun hps hyps = 895 reset ();
870 case hyps of 896 (*Print.prefaces "Big go" [("hyps", Print.p_list p_atom hyps),
871 [] => gls goals onFail (g :: acc) 897 ("goals", Print.p_list p_atom goals)];*)
872 | AReln (Sql hf, [he]) :: hyps => 898 gls goals (fn () => false) []
873 if gf = hf then 899 end handle Cc.Contradiction => true))
874 let
875 val saved = save ()
876 in
877 if eq (ge, he) then
878 let
879 val changed = IM.numItems (!unif)
880 <> IM.numItems saved
881 in
882 gls goals (fn () => (restore saved;
883 changed
884 andalso hps hyps))
885 acc
886 end
887 else
888 hps hyps
889 end
890 else
891 hps hyps
892 | _ :: hyps => hps hyps
893 in
894 hps hyps
895 end
896 | g :: goals => gls goals onFail (g :: acc)
897 in
898 (*Print.prefaces "Big go" [("hyps", Print.p_list p_atom hyps),
899 ("goals", Print.p_list p_atom goals)];*)
900 gls goals (fn () => false) []
901 end handle Cc.Contradiction => true)))
902 900
903 fun patCon pc = 901 fun patCon pc =
904 case pc of 902 case pc of
905 PConVar n => "C" ^ Int.toString n 903 PConVar n => "C" ^ Int.toString n
906 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c 904 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c
1213 1211
1214 fun queryProp env rvN rv oe e = 1212 fun queryProp env rvN rv oe e =
1215 let 1213 let
1216 fun default () = (print ("Warning: Information flow checker can't parse SQL query at " 1214 fun default () = (print ("Warning: Information flow checker can't parse SQL query at "
1217 ^ ErrorMsg.spanToString (#2 e) ^ "\n"); 1215 ^ ErrorMsg.spanToString (#2 e) ^ "\n");
1218 (rvN, Unknown, [])) 1216 (rvN, Unknown, Unknown, []))
1219 in 1217 in
1220 case parse query e of 1218 case parse query e of
1221 NONE => default () 1219 NONE => default ()
1222 | SOME r => 1220 | SOME r =>
1223 let 1221 let
1281 case expIn e of 1279 case expIn e of
1282 inr p' => And (p, p') 1280 inr p' => And (p, p')
1283 | _ => p 1281 | _ => p
1284 1282
1285 fun normal () = 1283 fun normal () =
1286 (rvN, 1284 (And (p, case oe of
1287 And (p, case oe of
1288 SomeCol oe => 1285 SomeCol oe =>
1289 foldl (fn (si, p) => 1286 foldl (fn (si, p) =>
1290 let 1287 let
1291 val p' = case si of 1288 val p' = case si of
1292 SqField (v, f) => Reln (Eq, [oe, Proj (rvOf v, f)]) 1289 SqField (v, f) => Reln (Eq, [oe, Proj (rvOf v, f)])
1310 | inl e => Reln (Eq, [Proj (oe, f), e]) 1307 | inl e => Reln (Eq, [Proj (oe, f), e])
1311 in 1308 in
1312 And (p, p') 1309 And (p, p')
1313 end) 1310 end)
1314 True (#Select r)), 1311 True (#Select r)),
1315 case #Where r of 1312 True)
1316 NONE => [] 1313
1317 | SOME e => map (fn (v, f) => Proj (rvOf v, f)) (usedFields e)) 1314 val (p, wp) =
1318 in 1315 case #Select r of
1319 case #Select r of 1316 [SqExp (Binop (Exps bo, Count, SqConst (Prim.Int 0)), f)] =>
1320 [SqExp (Binop (Exps bo, Count, SqConst (Prim.Int 0)), f)] => 1317 (case bo (Const (Prim.Int 1), Const (Prim.Int 2)) of
1321 (case bo (Const (Prim.Int 1), Const (Prim.Int 2)) of 1318 Reln (Gt, [Const (Prim.Int 1), Const (Prim.Int 2)]) =>
1322 Reln (Gt, [Const (Prim.Int 1), Const (Prim.Int 2)]) => 1319 let
1323 let 1320 val oe = case oe of
1324 val oe = case oe of 1321 SomeCol oe => oe
1325 SomeCol oe => oe 1322 | AllCols oe => Proj (oe, f)
1326 | AllCols oe => Proj (oe, f) 1323 in
1327 in 1324 (Or (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.False", [])]),
1328 (rvN, 1325 And (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]),
1329 Or (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.False", [])]), 1326 p)),
1330 And (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]), 1327 Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]))
1331 p)), 1328 end
1332 []) 1329 | _ => normal ())
1333 end 1330 | _ => normal ()
1334 | _ => normal ()) 1331 in
1335 | _ => normal () 1332 (rvN, p, wp, case #Where r of
1333 NONE => []
1334 | SOME e => map (fn (v, f) => Proj (rvOf v, f)) (usedFields e))
1336 end 1335 end
1337 handle Default => default () 1336 handle Default => default ()
1338 end 1337 end
1339 1338
1340 fun evalPat env e (pt, _) = 1339 fun evalPat env e (pt, _) =
1387 | _ => p2 1386 | _ => p2
1388 in 1387 in
1389 rr 1388 rr
1390 end 1389 end
1391 1390
1392 fun evalExp env (e as (_, loc), st as (nv, p, sent)) = 1391 structure St :> sig
1392 type t
1393 val create : {Var : int,
1394 Ambient : prop} -> t
1395
1396 val curVar : t -> int
1397 val nextVar : t -> t * int
1398
1399 val ambient : t -> prop
1400 val setAmbient : t * prop -> t
1401
1402 type check = ErrorMsg.span * exp * prop
1403
1404 val path : t -> check list
1405 val addPath : t * check -> t
1406
1407 val sent : t -> check list
1408 val addSent : t * check -> t
1409 val setSent : t * check list -> t
1410 end = struct
1411
1412 type check = ErrorMsg.span * exp * prop
1413
1414 type t = {Var : int,
1415 Ambient : prop,
1416 Path : check list,
1417 Sent : check list}
1418
1419 fun create {Var = v, Ambient = p} = {Var = v,
1420 Ambient = p,
1421 Path = [],
1422 Sent = []}
1423
1424 fun curVar (t : t) = #Var t
1425 fun nextVar (t : t) = ({Var = #Var t + 1,
1426 Ambient = #Ambient t,
1427 Path = #Path t,
1428 Sent = #Sent t}, #Var t)
1429
1430 fun ambient (t : t) = #Ambient t
1431 fun setAmbient (t : t, p) = {Var = #Var t,
1432 Ambient = p,
1433 Path = #Path t,
1434 Sent = #Sent t}
1435
1436 fun path (t : t) = #Path t
1437 fun addPath (t : t, c) = {Var = #Var t,
1438 Ambient = #Ambient t,
1439 Path = c :: #Path t,
1440 Sent = #Sent t}
1441
1442 fun sent (t : t) = #Sent t
1443 fun addSent (t : t, c) = {Var = #Var t,
1444 Ambient = #Ambient t,
1445 Path = #Path t,
1446 Sent = c :: #Sent t}
1447 fun setSent (t : t, cs) = {Var = #Var t,
1448 Ambient = #Ambient t,
1449 Path = #Path t,
1450 Sent = cs}
1451
1452 end
1453
1454 fun evalExp env (e as (_, loc), st) =
1393 let 1455 let
1394 fun default () = 1456 fun default () =
1395 ((*Print.preface ("Default" ^ Int.toString nv, 1457 let
1396 MonoPrint.p_exp MonoEnv.empty e);*) 1458 val (st, nv) = St.nextVar st
1397 (Var nv, (nv+1, p, sent))) 1459 in
1398 1460 (Var nv, st)
1399 fun addSent (p, e, sent) = 1461 end
1462
1463 fun addSent (p, e, st) =
1400 if isKnown e then 1464 if isKnown e then
1401 sent 1465 st
1402 else 1466 else
1403 (loc, e, p) :: sent 1467 St.addSent (st, (loc, e, p))
1404 in 1468 in
1405 case #1 e of 1469 case #1 e of
1406 EPrim p => (Const p, st) 1470 EPrim p => (Const p, st)
1407 | ERel n => (List.nth (env, n), st) 1471 | ERel n => (List.nth (env, n), st)
1408 | ENamed _ => default () 1472 | ENamed _ => default ()
1425 | EFfiApp (m, s, es) => 1489 | EFfiApp (m, s, es) =>
1426 if m = "Basis" andalso SS.member (writers, s) then 1490 if m = "Basis" andalso SS.member (writers, s) then
1427 let 1491 let
1428 val (es, st) = ListUtil.foldlMap (evalExp env) st es 1492 val (es, st) = ListUtil.foldlMap (evalExp env) st es
1429 in 1493 in
1430 (Recd [], (#1 st, p, foldl (fn (e, sent) => addSent (#2 st, e, sent)) sent es)) 1494 (Recd [], foldl (fn (e, st) => addSent (St.ambient st, e, st)) st es)
1431 end 1495 end
1432 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then 1496 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then
1433 default () 1497 default ()
1434 else 1498 else
1435 let 1499 let
1479 (Proj (e, s), st) 1543 (Proj (e, s), st)
1480 end 1544 end
1481 | ECase (e, pes, _) => 1545 | ECase (e, pes, _) =>
1482 let 1546 let
1483 val (e, st) = evalExp env (e, st) 1547 val (e, st) = evalExp env (e, st)
1484 val r = #1 st 1548 val (st, r) = St.nextVar st
1485 val st = (r + 1, #2 st, #3 st) 1549 val orig = St.ambient st
1486 val orig = #2 st
1487 1550
1488 val st = foldl (fn ((pt, pe), st) => 1551 val st = foldl (fn ((pt, pe), st) =>
1489 let 1552 let
1490 val (env, pp) = evalPat env e pt 1553 val (env, pp) = evalPat env e pt
1491 val (pe, st') = evalExp env (pe, (#1 st, And (orig, pp), #3 st)) 1554 val (pe, st') = evalExp env (pe, St.setAmbient (st, And (orig, pp)))
1492 (*val () = Print.prefaces "Case" [("loc", Print.PD.string 1555 (*val () = Print.prefaces "Case" [("loc", Print.PD.string
1493 (ErrorMsg.spanToString (#2 pt))), 1556 (ErrorMsg.spanToString (#2 pt))),
1494 ("env", Print.p_list p_exp env), 1557 ("env", Print.p_list p_exp env),
1495 ("sent", Print.p_list_sep Print.PD.newline 1558 ("sent", Print.p_list_sep Print.PD.newline
1496 (fn (loc, e, p) => 1559 (fn (loc, e, p) =>
1504 Print.space, 1567 Print.space,
1505 p_prop p]) 1568 p_prop p])
1506 (List.take (#3 st', length (#3 st') 1569 (List.take (#3 st', length (#3 st')
1507 - length (#3 st))))]*) 1570 - length (#3 st))))]*)
1508 1571
1509 val this = And (removeRedundant orig (#2 st'), Reln (Eq, [Var r, pe])) 1572 val this = And (removeRedundant orig (St.ambient st'),
1573 Reln (Eq, [Var r, pe]))
1510 in 1574 in
1511 (#1 st', Or (#2 st, this), #3 st') 1575 St.setAmbient (st', Or (St.ambient st, this))
1512 end) (#1 st, False, #3 st) pes 1576 end) (St.setAmbient (st, False)) pes
1513 in 1577 in
1514 (Var r, (#1 st, And (orig, #2 st), #3 st)) 1578 (Var r, St.setAmbient (st, And (orig, St.ambient st)))
1515 end 1579 end
1516 | EStrcat (e1, e2) => 1580 | EStrcat (e1, e2) =>
1517 let 1581 let
1518 val (e1, st) = evalExp env (e1, st) 1582 val (e1, st) = evalExp env (e1, st)
1519 val (e2, st) = evalExp env (e2, st) 1583 val (e2, st) = evalExp env (e2, st)
1524 | EReturnBlob {blob = b, mimeType = m, ...} => 1588 | EReturnBlob {blob = b, mimeType = m, ...} =>
1525 let 1589 let
1526 val (b, st) = evalExp env (b, st) 1590 val (b, st) = evalExp env (b, st)
1527 val (m, st) = evalExp env (m, st) 1591 val (m, st) = evalExp env (m, st)
1528 in 1592 in
1529 (Finish, (#1 st, p, addSent (#2 st, b, addSent (#2 st, m, sent)))) 1593 (Finish, addSent (St.ambient st, b, addSent (St.ambient st, m, st)))
1530 end 1594 end
1531 | ERedirect (e, _) => 1595 | ERedirect (e, _) =>
1532 let 1596 let
1533 val (e, st) = evalExp env (e, st) 1597 val (e, st) = evalExp env (e, st)
1534 in 1598 in
1535 (Finish, (#1 st, p, addSent (#2 st, e, sent))) 1599 (Finish, addSent (St.ambient st, e, st))
1536 end 1600 end
1537 | EWrite e => 1601 | EWrite e =>
1538 let 1602 let
1539 val (e, st) = evalExp env (e, st) 1603 val (e, st) = evalExp env (e, st)
1540 in 1604 in
1541 (Recd [], (#1 st, p, addSent (#2 st, e, sent))) 1605 (Recd [], addSent (St.ambient st, e, st))
1542 end 1606 end
1543 | ESeq (e1, e2) => 1607 | ESeq (e1, e2) =>
1544 let 1608 let
1545 val (_, st) = evalExp env (e1, st) 1609 val (_, st) = evalExp env (e1, st)
1546 in 1610 in
1562 | EQuery {query = q, body = b, initial = i, ...} => 1626 | EQuery {query = q, body = b, initial = i, ...} =>
1563 let 1627 let
1564 val (_, st) = evalExp env (q, st) 1628 val (_, st) = evalExp env (q, st)
1565 val (i, st) = evalExp env (i, st) 1629 val (i, st) = evalExp env (i, st)
1566 1630
1567 val r = #1 st 1631 val (st', r) = St.nextVar st
1568 val acc = #1 st + 1 1632 val (st', acc) = St.nextVar st'
1569 val st' = (#1 st + 2, #2 st, #3 st)
1570 1633
1571 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st') 1634 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st')
1572 1635
1573 val (rvN, qp, used) = 1636 val (st', qp, qwp, used) =
1574 queryProp env 1637 queryProp env
1575 (#1 st') (fn rvN => (rvN + 1, Var rvN)) 1638 st' (fn st' =>
1639 let
1640 val (st', rv) = St.nextVar st'
1641 in
1642 (st', Var rv)
1643 end)
1576 (AllCols (Var r)) q 1644 (AllCols (Var r)) q
1577 1645
1578 val p' = And (qp, #2 st') 1646 val p' = And (qp, St.ambient st')
1579 1647
1580 val (nvs, p, res) = if varInP acc (#2 st') then 1648 val (st, res) = if varInP acc (St.ambient st') then
1581 (#1 st + 1, #2 st, Var r) 1649 let
1582 else 1650 val (st, r) = St.nextVar st
1583 let 1651 in
1584 val out = rvN 1652 (st, Var r)
1585 1653 end
1586 val p = Or (Reln (Eq, [Var out, i]), 1654 else
1587 And (Reln (Eq, [Var out, b]), 1655 let
1588 p')) 1656 val (st, out) = St.nextVar st'
1589 in 1657
1590 (out + 1, p, Var out) 1658 val p = Or (Reln (Eq, [Var out, i]),
1591 end 1659 And (Reln (Eq, [Var out, b]),
1592 1660 p'))
1593 val sent = map (fn (loc, e, p) => (loc, e, And (qp, p))) (#3 st') 1661 in
1662 (St.setAmbient (st, p), Var out)
1663 end
1664
1665 val sent = map (fn (loc, e, p) => (loc, e, And (qp, p))) (St.sent st')
1666
1667 val p' = And (p', qwp)
1594 val sent = map (fn e => (loc, e, p')) used @ sent 1668 val sent = map (fn e => (loc, e, p')) used @ sent
1595 in 1669 in
1596 (res, (nvs, p, sent)) 1670 (res, St.setSent (st, sent))
1597 end 1671 end
1598 | EDml _ => default () 1672 | EDml _ => default ()
1599 | ENextval _ => default () 1673 | ENextval _ => default ()
1600 | ESetval _ => default () 1674 | ESetval _ => default ()
1601 1675
1602 | EUnurlify ((EFfiApp ("Basis", "get_cookie", _), _), _, _) => 1676 | EUnurlify ((EFfiApp ("Basis", "get_cookie", _), _), _, _) =>
1603 (Var nv, (nv + 1, And (p, Reln (Known, [Var nv])), sent)) 1677 let
1678 val (st, nv) = St.nextVar st
1679 in
1680 (Var nv, St.setAmbient (st, And (St.ambient st, Reln (Known, [Var nv]))))
1681 end
1604 1682
1605 | EUnurlify _ => default () 1683 | EUnurlify _ => default ()
1606 | EJavaScript _ => default () 1684 | EJavaScript _ => default ()
1607 | ESignalReturn _ => default () 1685 | ESignalReturn _ => default ()
1608 | ESignalBind _ => default () 1686 | ESignalBind _ => default ()
1642 p) 1720 p)
1643 | _ => (e, env, nv, p) 1721 | _ => (e, env, nv, p)
1644 1722
1645 val (e, env, nv, p) = deAbs (e, [], 1, True) 1723 val (e, env, nv, p) = deAbs (e, [], 1, True)
1646 1724
1647 val (e, (_, p, sent)) = evalExp env (e, (nv, p, [])) 1725 val (_, st) = evalExp env (e, St.create {Var = nv,
1726 Ambient = p})
1648 in 1727 in
1649 (sent @ vals, pols) 1728 (St.sent st @ vals, pols)
1650 end 1729 end
1651 1730
1652 | DPolicy (PolClient e) => (vals, #2 (queryProp [] 0 (fn rvN => (rvN + 1, Lvar rvN)) 1731 | DPolicy (PolClient e) => (vals, #2 (queryProp [] 0 (fn rvN => (rvN + 1, Lvar rvN))
1653 (SomeCol (Var 0)) e) :: pols) 1732 (SomeCol (Var 0)) e) :: pols)
1654 1733