Mercurial > urweb
comparison src/iflow.sml @ 2216:70ec9bb337be
Progress towards invalidation based on equalities of fields.
author | Ziv Scully <ziv@mit.edu> |
---|---|
date | Mon, 10 Nov 2014 22:04:40 -0500 |
parents | 4d64af730e35 |
children | 278e10629ba1 |
comparison
equal
deleted
inserted
replaced
2215:639e62ca2530 | 2216:70ec9bb337be |
---|---|
14 * | 14 * |
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
113 p_list p_exp es, | 113 p_list p_exp es, |
114 string ")"] | 114 string ")"] |
115 | PCon1 s => box [string (s ^ "("), | 115 | PCon1 s => box [string (s ^ "("), |
116 p_list p_exp es, | 116 p_list p_exp es, |
117 string ")"] | 117 string ")"] |
118 | Eq => p_bop "=" es | 118 | Cmp Eq => p_bop "=" es |
119 | Ne => p_bop "<>" es | 119 | Cmp Ne => p_bop "<>" es |
120 | Lt => p_bop "<" es | 120 | Cmp Lt => p_bop "<" es |
121 | Le => p_bop "<=" es | 121 | Cmp Le => p_bop "<=" es |
122 | Gt => p_bop ">" es | 122 | Cmp Gt => p_bop ">" es |
123 | Ge => p_bop ">=" es | 123 | Cmp Ge => p_bop ">=" es |
124 | 124 |
125 fun p_prop p = | 125 fun p_prop p = |
126 case p of | 126 case p of |
127 True => string "True" | 127 True => string "True" |
128 | False => string "False" | 128 | False => string "False" |
129 | Unknown => string "??" | 129 | Unknown => string "??" |
130 | And (p1, p2) => box [string "(", | 130 | Lop (And, p1, p2) => box [string "(", |
131 p_prop p1, | 131 p_prop p1, |
132 string ")", | 132 string ")", |
133 space, | 133 space, |
134 string "&&", | 134 string "&&", |
135 space, | 135 space, |
136 string "(", | 136 string "(", |
137 p_prop p2, | 137 p_prop p2, |
138 string ")"] | 138 string ")"] |
139 | Or (p1, p2) => box [string "(", | 139 | Lop (Or, p1, p2) => box [string "(", |
140 p_prop p1, | 140 p_prop p1, |
141 string ")", | 141 string ")", |
142 space, | 142 space, |
143 string "||", | 143 string "||", |
144 space, | 144 space, |
145 string "(", | 145 string "(", |
146 p_prop p2, | 146 p_prop p2, |
147 string ")"] | 147 string ")"] |
148 | Reln (r, es) => p_reln r es | 148 | Reln (r, es) => p_reln r es |
149 | Cond (e, p) => box [string "(", | 149 | Cond (e, p) => box [string "(", |
150 p_exp e, | 150 p_exp e, |
151 space, | 151 space, |
152 string "==", | 152 string "==", |
516 Rep = ref NONE, | 516 Rep = ref NONE, |
517 Cons = ref SM.empty, | 517 Cons = ref SM.empty, |
518 Variety = Nothing, | 518 Variety = Nothing, |
519 Known = ref (!(#Known (unNode r))), | 519 Known = ref (!(#Known (unNode r))), |
520 Ge = ref NONE}) | 520 Ge = ref NONE}) |
521 | 521 |
522 val r'' = ref (Node {Id = nodeId (), | 522 val r'' = ref (Node {Id = nodeId (), |
523 Rep = ref NONE, | 523 Rep = ref NONE, |
524 Cons = #Cons (unNode r), | 524 Cons = #Cons (unNode r), |
525 Variety = Recrd (ref (SM.insert (SM.empty, f, r')), false), | 525 Variety = Recrd (ref (SM.insert (SM.empty, f, r')), false), |
526 Known = #Known (unNode r), | 526 Known = #Known (unNode r), |
527 Ge = ref NONE}) | 527 Ge = ref NONE}) |
528 in | 528 in |
529 #Rep (unNode r) := SOME r''; | 529 #Rep (unNode r) := SOME r''; |
530 r' | 530 r' |
531 end | 531 end |
532 | _ => raise Contradiction | 532 | _ => raise Contradiction |
533 end | 533 end |
534 in | 534 in |
535 rep e | 535 rep e |
536 end | 536 end |
537 | 537 |
685 cons := SM.insert (!cons, f, r'); | 685 cons := SM.insert (!cons, f, r'); |
686 #Rep (unNode r) := SOME r' | 686 #Rep (unNode r) := SOME r' |
687 end | 687 end |
688 | _ => raise Contradiction | 688 | _ => raise Contradiction |
689 end | 689 end |
690 | (Eq, [e1, e2]) => | 690 | (Cmp Eq, [e1, e2]) => |
691 markEq (representative (db, e1), representative (db, e2)) | 691 markEq (representative (db, e1), representative (db, e2)) |
692 | (Ge, [e1, e2]) => | 692 | (Cmp Ge, [e1, e2]) => |
693 let | 693 let |
694 val r1 = representative (db, e1) | 694 val r1 = representative (db, e1) |
695 val r2 = representative (db, e2) | 695 val r2 = representative (db, e2) |
696 in | 696 in |
697 case !(#Ge (unNode (repOf r2))) of | 697 case !(#Ge (unNode (repOf r2))) of |
732 | _ => false) | 732 | _ => false) |
733 | (PCon1 f, [e]) => | 733 | (PCon1 f, [e]) => |
734 (case #Variety (unNode (representative (db, e))) of | 734 (case #Variety (unNode (representative (db, e))) of |
735 Dt1 (f', _) => f' = f | 735 Dt1 (f', _) => f' = f |
736 | _ => false) | 736 | _ => false) |
737 | (Eq, [e1, e2]) => | 737 | (Cmp Eq, [e1, e2]) => |
738 let | 738 let |
739 val r1 = representative (db, e1) | 739 val r1 = representative (db, e1) |
740 val r2 = representative (db, e2) | 740 val r2 = representative (db, e2) |
741 in | 741 in |
742 repOf r1 = repOf r2 | 742 repOf r1 = repOf r2 |
743 end | 743 end |
744 | (Ge, [e1, e2]) => | 744 | (Cmp Ge, [e1, e2]) => |
745 let | 745 let |
746 val r1 = representative (db, e1) | 746 val r1 = representative (db, e1) |
747 val r2 = representative (db, e2) | 747 val r2 = representative (db, e2) |
748 in | 748 in |
749 case (!(#Ge (unNode (repOf r1))), #Variety (unNode (repOf r2))) of | 749 case (!(#Ge (unNode (repOf r1))), #Variety (unNode (repOf r2))) of |
846 () | 846 () |
847 else | 847 else |
848 (hyps := (n', hs, ref false); | 848 (hyps := (n', hs, ref false); |
849 Cc.clear db; | 849 Cc.clear db; |
850 app (fn a => Cc.assert (db, a)) hs) | 850 app (fn a => Cc.assert (db, a)) hs) |
851 end | 851 end |
852 | 852 |
853 fun useKeys () = | 853 fun useKeys () = |
854 let | 854 let |
855 val changed = ref false | 855 val changed = ref false |
856 | 856 |
870 if tab' = tab andalso | 870 if tab' = tab andalso |
871 List.exists (List.all (fn f => | 871 List.exists (List.all (fn f => |
872 let | 872 let |
873 val r = | 873 val r = |
874 Cc.check (db, | 874 Cc.check (db, |
875 AReln (Eq, [Proj (r1, f), | 875 AReln (Cmp Eq, [Proj (r1, f), |
876 Proj (r2, f)])) | 876 Proj (r2, f)])) |
877 in | 877 in |
878 (*Print.prefaces "Fs" | 878 (*Print.prefaces "Fs" |
879 [("tab", | 879 [("tab", |
880 Print.PD.string tab), | 880 Print.PD.string tab), |
886 Print.PD.string | 886 Print.PD.string |
887 (Bool.toString r))];*) | 887 (Bool.toString r))];*) |
888 r | 888 r |
889 end)) ks then | 889 end)) ks then |
890 (changed := true; | 890 (changed := true; |
891 Cc.assert (db, AReln (Eq, [r1, r2])); | 891 Cc.assert (db, AReln (Cmp Eq, [r1, r2])); |
892 finder (hyps, acc)) | 892 finder (hyps, acc)) |
893 else | 893 else |
894 finder (hyps, a :: acc) | 894 finder (hyps, a :: acc) |
895 | a :: hyps => finder (hyps, a :: acc) | 895 | a :: hyps => finder (hyps, a :: acc) |
896 | 896 |
1113 val cname = "cookie/" ^ cname | 1113 val cname = "cookie/" ^ cname |
1114 val n = !hnames | 1114 val n = !hnames |
1115 val (_, hs, _) = !hyps | 1115 val (_, hs, _) = !hyps |
1116 in | 1116 in |
1117 hnames := n + 1; | 1117 hnames := n + 1; |
1118 hyps := (n, List.filter (fn AReln (Eq, [_, Func (Other f, [])]) => f <> cname | _ => true) hs, ref false) | 1118 hyps := (n, List.filter (fn AReln (Cmp Eq, [_, Func (Other f, [])]) => f <> cname | _ => true) hs, ref false) |
1119 end | 1119 end |
1120 | 1120 |
1121 fun check a = Cc.check (db, a) | 1121 fun check a = Cc.check (db, a) |
1122 | 1122 |
1123 fun debug () = | 1123 fun debug () = |
1136 | x :: ls => | 1136 | x :: ls => |
1137 let | 1137 let |
1138 val ls = removeDups ls | 1138 val ls = removeDups ls |
1139 in | 1139 in |
1140 if List.exists (fn x' => x' = x) ls then | 1140 if List.exists (fn x' => x' = x) ls then |
1141 ls | 1141 ls |
1142 else | 1142 else |
1143 x :: ls | 1143 x :: ls |
1144 end | 1144 end |
1145 | 1145 |
1146 fun deinj env e = | 1146 fun deinj env e = |
1169 | SqTrue => inl (Func (DtCon0 "Basis.bool.True", [])) | 1169 | SqTrue => inl (Func (DtCon0 "Basis.bool.True", [])) |
1170 | SqFalse => inl (Func (DtCon0 "Basis.bool.False", [])) | 1170 | SqFalse => inl (Func (DtCon0 "Basis.bool.False", [])) |
1171 | Null => inl (Func (DtCon0 "None", [])) | 1171 | Null => inl (Func (DtCon0 "None", [])) |
1172 | SqNot e => | 1172 | SqNot e => |
1173 inr (case expIn e of | 1173 inr (case expIn e of |
1174 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.False", [])]) | 1174 inl e => Reln (Cmp Eq, [e, Func (DtCon0 "Basis.bool.False", [])]) |
1175 | inr _ => Unknown) | 1175 | inr _ => Unknown) |
1176 | Field (v, f) => inl (Proj (rvOf v, f)) | 1176 | Field (v, f) => inl (Proj (rvOf v, f)) |
1177 | Computed _ => default () | 1177 | Computed _ => default () |
1178 | Binop (bo, e1, e2) => | 1178 | Binop (bo, e1, e2) => |
1179 let | 1179 let |
1180 val e1 = expIn e1 | 1180 val e1 = expIn e1 |
1181 val e2 = expIn e2 | 1181 val e2 = expIn e2 |
1182 in | 1182 in |
1183 inr (case (bo, e1, e2) of | 1183 inr (case (bo, e1, e2) of |
1184 (Exps f, inl e1, inl e2) => f (e1, e2) | 1184 (RCmp c, inl e1, inl e2) => Reln (Cmp c, [e1, e2]) |
1185 | (Props f, v1, v2) => | 1185 | (RLop l, v1, v2) => |
1186 let | 1186 let |
1187 fun pin v = | 1187 fun pin v = |
1188 case v of | 1188 case v of |
1189 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])]) | 1189 inl e => Reln (Cmp Eq, [e, Func (DtCon0 "Basis.bool.True", [])]) |
1190 | inr p => p | 1190 | inr p => p |
1191 in | 1191 in |
1192 f (pin v1, pin v2) | 1192 Lop (l, pin v1, pin v2) |
1193 end | 1193 end |
1194 | _ => Unknown) | 1194 | _ => Unknown) |
1195 end | 1195 end |
1196 | SqKnown e => | 1196 | SqKnown e => |
1197 (case expIn e of | 1197 (case expIn e of |
1203 | SOME e => e) | 1203 | SOME e => e) |
1204 | SqFunc (f, e) => | 1204 | SqFunc (f, e) => |
1205 (case expIn e of | 1205 (case expIn e of |
1206 inl e => inl (Func (Other f, [e])) | 1206 inl e => inl (Func (Other f, [e])) |
1207 | _ => default ()) | 1207 | _ => default ()) |
1208 | 1208 |
1209 | Unmodeled => inl (Func (Other "allow", [rv ()])) | 1209 | Unmodeled => inl (Func (Other "allow", [rv ()])) |
1210 end | 1210 end |
1211 in | 1211 in |
1212 expIn | 1212 expIn |
1213 end | 1213 end |
1217 fun go p k = | 1217 fun go p k = |
1218 case p of | 1218 case p of |
1219 True => (k () handle Cc.Contradiction => ()) | 1219 True => (k () handle Cc.Contradiction => ()) |
1220 | False => () | 1220 | False => () |
1221 | Unknown => () | 1221 | Unknown => () |
1222 | And (p1, p2) => go p1 (fn () => go p2 k) | 1222 | Lop (And, p1, p2) => go p1 (fn () => go p2 k) |
1223 | Or (p1, p2) => | 1223 | Lop (Or, p1, p2) => |
1224 let | 1224 let |
1225 val saved = save () | 1225 val saved = save () |
1226 in | 1226 in |
1227 go p1 k; | 1227 go p1 k; |
1228 restore saved; | 1228 restore saved; |
1349 case #Where r of | 1349 case #Where r of |
1350 NONE => final () | 1350 NONE => final () |
1351 | SOME e => | 1351 | SOME e => |
1352 let | 1352 let |
1353 val p = case expIn e of | 1353 val p = case expIn e of |
1354 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])]) | 1354 inl e => Reln (Cmp Eq, [e, Func (DtCon0 "Basis.bool.True", [])]) |
1355 | inr p => p | 1355 | inr p => p |
1356 | 1356 |
1357 val saved = #Save arg () | 1357 val saved = #Save arg () |
1358 in | 1358 in |
1359 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg} | 1359 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg} |
1363 handle Cc.Contradiction => () | 1363 handle Cc.Contradiction => () |
1364 | 1364 |
1365 fun normal () = doWhere normal' | 1365 fun normal () = doWhere normal' |
1366 in | 1366 in |
1367 (case #Select r of | 1367 (case #Select r of |
1368 [SqExp (Binop (Exps bo, Count, SqConst (Prim.Int 0)), f)] => | 1368 [SqExp (Binop (RCmp bo, Count, SqConst (Prim.Int 0)), f)] => |
1369 (case bo (Const (Prim.Int 1), Const (Prim.Int 2)) of | 1369 (case bo of |
1370 Reln (Gt, [Const (Prim.Int 1), Const (Prim.Int 2)]) => | 1370 Gt => |
1371 (case #Cont arg of | 1371 (case #Cont arg of |
1372 SomeCol _ => () | 1372 SomeCol _ => () |
1373 | AllCols k => | 1373 | AllCols k => |
1374 let | 1374 let |
1375 fun answer e = k (Recd [(f, e)]) | 1375 fun answer e = k (Recd [(f, e)]) |
1467 [] => k (Func (Other (m ^ "." ^ s), rev acc)) | 1467 [] => k (Func (Other (m ^ "." ^ s), rev acc)) |
1468 | (e, _) :: es => | 1468 | (e, _) :: es => |
1469 evalExp env e (fn e => doArgs (es, e :: acc)) | 1469 evalExp env e (fn e => doArgs (es, e :: acc)) |
1470 in | 1470 in |
1471 doArgs (es, []) | 1471 doArgs (es, []) |
1472 end | 1472 end |
1473 in | 1473 in |
1474 case #1 e of | 1474 case #1 e of |
1475 EPrim p => k (Const p) | 1475 EPrim p => k (Const p) |
1476 | ERel n => k (List.nth (env, n)) | 1476 | ERel n => k (List.nth (env, n)) |
1477 | ENamed _ => default () | 1477 | ENamed _ => default () |
1517 fun doArgs (args, modes, env') = | 1517 fun doArgs (args, modes, env') = |
1518 case (args, modes) of | 1518 case (args, modes) of |
1519 ([], []) => (evalExp env' (#body rf) (fn _ => ()); | 1519 ([], []) => (evalExp env' (#body rf) (fn _ => ()); |
1520 St.reinstate saved; | 1520 St.reinstate saved; |
1521 default ()) | 1521 default ()) |
1522 | 1522 |
1523 | (arg :: args, mode :: modes) => | 1523 | (arg :: args, mode :: modes) => |
1524 evalExp env arg (fn arg => | 1524 evalExp env arg (fn arg => |
1525 let | 1525 let |
1526 val v = case mode of | 1526 val v = case mode of |
1527 Arbitrary => Var (St.nextVar ()) | 1527 Arbitrary => Var (St.nextVar ()) |
1661 NextVar = Var o St.nextVar, | 1661 NextVar = Var o St.nextVar, |
1662 Add = fn a => St.assert [a], | 1662 Add = fn a => St.assert [a], |
1663 Save = St.stash, | 1663 Save = St.stash, |
1664 Restore = St.reinstate, | 1664 Restore = St.reinstate, |
1665 Cont = AllCols (fn x => | 1665 Cont = AllCols (fn x => |
1666 (St.assert [AReln (Eq, [r, x])]; | 1666 (St.assert [AReln (Cmp Eq, [r, x])]; |
1667 evalExp (acc :: r :: env) b k))} q | 1667 evalExp (acc :: r :: env) b k))} q |
1668 end) | 1668 end) |
1669 | EDml (e, _) => | 1669 | EDml (e, _) => |
1670 (case parse dml e of | 1670 (case parse dml e of |
1671 NONE => (print ("Warning: Information flow checker can't parse DML command at " | 1671 NONE => (print ("Warning: Information flow checker can't parse DML command at " |
1695 k (Recd []) | 1695 k (Recd []) |
1696 end | 1696 end |
1697 | Delete (tab, e) => | 1697 | Delete (tab, e) => |
1698 let | 1698 let |
1699 val old = St.nextVar () | 1699 val old = St.nextVar () |
1700 | 1700 |
1701 val expIn = expIn (Var o St.nextVar) env | 1701 val expIn = expIn (Var o St.nextVar) env |
1702 (fn "T" => Var old | 1702 (fn "T" => Var old |
1703 | _ => raise Fail "Iflow.evalExp: Bad field expression in DELETE") | 1703 | _ => raise Fail "Iflow.evalExp: Bad field expression in DELETE") |
1704 | 1704 |
1705 val p = case expIn e of | 1705 val p = case expIn e of |
1706 inl e => raise Fail "Iflow.evalExp: DELETE with non-boolean" | 1706 inl e => raise Fail "Iflow.evalExp: DELETE with non-boolean" |
1707 | inr p => p | 1707 | inr p => p |
1708 | 1708 |
1709 val saved = St.stash () | 1709 val saved = St.stash () |
1710 in | 1710 in |
1711 St.assert [AReln (Sql (tab ^ "$Old"), [Var old]), | 1711 St.assert [AReln (Sql (tab ^ "$Old"), [Var old]), |
1712 AReln (Sql (tab), [Var old])]; | 1712 AReln (Sql (tab), [Var old])]; |
1713 decomp {Save = St.stash, | 1713 decomp {Save = St.stash, |
1746 fs | 1746 fs |
1747 else | 1747 else |
1748 (f, Proj (Var old, f)) :: fs) fs fs' | 1748 (f, Proj (Var old, f)) :: fs) fs fs' |
1749 | 1749 |
1750 val p = case expIn e of | 1750 val p = case expIn e of |
1751 inl e => raise Fail "Iflow.evalExp: UPDATE with non-boolean" | 1751 inl e => raise Fail "Iflow.evalExp: UPDATE with non-boolean" |
1752 | inr p => p | 1752 | inr p => p |
1753 val saved = St.stash () | 1753 val saved = St.stash () |
1754 in | 1754 in |
1755 St.assert [AReln (Sql (tab ^ "$New"), [Recd fs]), | 1755 St.assert [AReln (Sql (tab ^ "$New"), [Recd fs]), |
1756 AReln (Sql (tab ^ "$Old"), [Var old]), | 1756 AReln (Sql (tab ^ "$Old"), [Var old]), |
1762 St.reinstate saved; | 1762 St.reinstate saved; |
1763 St.havocReln (Sql tab); | 1763 St.havocReln (Sql tab); |
1764 k (Recd [])) | 1764 k (Recd [])) |
1765 handle Cc.Contradiction => ()) | 1765 handle Cc.Contradiction => ()) |
1766 end) | 1766 end) |
1767 | 1767 |
1768 | ENextval (EPrim (Prim.String (_, seq)), _) => | 1768 | ENextval (EPrim (Prim.String (_, seq)), _) => |
1769 let | 1769 let |
1770 val nv = St.nextVar () | 1770 val nv = St.nextVar () |
1771 in | 1771 in |
1772 St.assert [AReln (Sql (String.extract (seq, 3, NONE)), [Var nv])]; | 1772 St.assert [AReln (Sql (String.extract (seq, 3, NONE)), [Var nv])]; |
1778 | EUnurlify ((EFfiApp ("Basis", "get_cookie", [((EPrim (Prim.String (_, cname)), _), _)]), _), _, _) => | 1778 | EUnurlify ((EFfiApp ("Basis", "get_cookie", [((EPrim (Prim.String (_, cname)), _), _)]), _), _, _) => |
1779 let | 1779 let |
1780 val e = Var (St.nextVar ()) | 1780 val e = Var (St.nextVar ()) |
1781 val e' = Func (Other ("cookie/" ^ cname), []) | 1781 val e' = Func (Other ("cookie/" ^ cname), []) |
1782 in | 1782 in |
1783 St.assert [AReln (Known, [e]), AReln (Eq, [e, e'])]; | 1783 St.assert [AReln (Known, [e]), AReln (Cmp Eq, [e, e'])]; |
1784 k e | 1784 k e |
1785 end | 1785 end |
1786 | 1786 |
1787 | EUnurlify _ => default () | 1787 | EUnurlify _ => default () |
1788 | EJavaScript _ => default () | 1788 | EJavaScript _ => default () |
2157 in | 2157 in |
2158 St.allowSend ([p], outs) | 2158 St.allowSend ([p], outs) |
2159 end | 2159 end |
2160 | _ => ()) | 2160 | _ => ()) |
2161 end | 2161 end |
2162 | 2162 |
2163 | _ => () | 2163 | _ => () |
2164 in | 2164 in |
2165 app decl (#1 file) | 2165 app decl (#1 file) |
2166 end | 2166 end |
2167 | 2167 |