Mercurial > urweb
comparison src/scriptcheck.sml @ 693:655bcc9b77e0
_Really_ implement embedded closure GC; extend Scriptcheck to figure out when client IDs must be assigned
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 04 Apr 2009 14:03:39 -0400 |
parents | f73913d97a40 |
children | 500e93aa436f |
comparison
equal
deleted
inserted
replaced
692:09df0c85f306 | 693:655bcc9b77e0 |
---|---|
33 type ord_key = string | 33 type ord_key = string |
34 val compare = String.compare | 34 val compare = String.compare |
35 end) | 35 end) |
36 structure IS = IntBinarySet | 36 structure IS = IntBinarySet |
37 | 37 |
38 val csBasis = SS.addList (SS.empty, | 38 val pullBasis = SS.addList (SS.empty, |
39 ["new_client_source", | 39 ["new_client_source", |
40 "get_client_source", | 40 "get_client_source", |
41 "set_client_source", | 41 "set_client_source"]) |
42 "new_channel", | |
43 "subscribe", | |
44 "send", | |
45 "recv"]) | |
46 | 42 |
43 val pushBasis = SS.addList (SS.empty, | |
44 ["new_channel", | |
45 "self"]) | |
46 | |
47 val scriptWords = ["<script", | 47 val scriptWords = ["<script", |
48 " onclick=", | 48 " onclick=", |
49 " onload="] | 49 " onload="] |
50 | |
51 val pushWords = ["rv("] | |
50 | 52 |
51 fun classify (ds, ps) = | 53 fun classify (ds, ps) = |
52 let | 54 let |
53 fun inString {needle, haystack} = | 55 fun inString {needle, haystack} = |
54 let | 56 let |
55 val (_, suffix) = Substring.position needle (Substring.full haystack) | 57 val (_, suffix) = Substring.position needle (Substring.full haystack) |
56 in | 58 in |
57 not (Substring.isEmpty suffix) | 59 not (Substring.isEmpty suffix) |
58 end | 60 end |
59 | 61 |
60 fun hasClient csids = | 62 fun hasClient {basis, words} csids = |
61 let | 63 let |
62 fun hasClient e = | 64 fun hasClient e = |
63 case #1 e of | 65 case #1 e of |
64 EPrim (Prim.String s) => List.exists (fn n => inString {needle = n, haystack = s}) scriptWords | 66 EPrim (Prim.String s) => List.exists (fn n => inString {needle = n, haystack = s}) words |
65 | EPrim _ => false | 67 | EPrim _ => false |
66 | ERel _ => false | 68 | ERel _ => false |
67 | ENamed n => IS.member (csids, n) | 69 | ENamed n => IS.member (csids, n) |
68 | ECon (_, _, NONE) => false | 70 | ECon (_, _, NONE) => false |
69 | ECon (_, _, SOME e) => hasClient e | 71 | ECon (_, _, SOME e) => hasClient e |
70 | ENone _ => false | 72 | ENone _ => false |
71 | ESome (_, e) => hasClient e | 73 | ESome (_, e) => hasClient e |
72 | EFfi ("Basis", x) => SS.member (csBasis, x) | 74 | EFfi ("Basis", x) => SS.member (basis, x) |
73 | EFfi _ => false | 75 | EFfi _ => false |
74 | EFfiApp ("Basis", x, es) => SS.member (csBasis, x) | 76 | EFfiApp ("Basis", x, es) => SS.member (basis, x) |
75 orelse List.exists hasClient es | 77 orelse List.exists hasClient es |
76 | EFfiApp (_, _, es) => List.exists hasClient es | 78 | EFfiApp (_, _, es) => List.exists hasClient es |
77 | EApp (e, es) => hasClient e orelse List.exists hasClient es | 79 | EApp (e, es) => hasClient e orelse List.exists hasClient es |
78 | EUnop (_, e) => hasClient e | 80 | EUnop (_, e) => hasClient e |
79 | EBinop (_, e1, e2) => hasClient e1 orelse hasClient e2 | 81 | EBinop (_, e1, e2) => hasClient e1 orelse hasClient e2 |
91 | EUnurlify (e, _) => hasClient e | 93 | EUnurlify (e, _) => hasClient e |
92 in | 94 in |
93 hasClient | 95 hasClient |
94 end | 96 end |
95 | 97 |
96 fun decl ((d, _), csids) = | 98 fun decl ((d, _), (pull_ids, push_ids)) = |
97 let | 99 let |
98 val hasClient = hasClient csids | 100 val hasClientPull = hasClient {basis = pullBasis, words = scriptWords} pull_ids |
101 val hasClientPush = hasClient {basis = pushBasis, words = pushWords} push_ids | |
99 in | 102 in |
100 case d of | 103 case d of |
101 DVal (_, n, _, e) => if hasClient e then | 104 DVal (_, n, _, e) => (if hasClientPull e then |
102 IS.add (csids, n) | 105 IS.add (pull_ids, n) |
103 else | 106 else |
104 csids | 107 pull_ids, |
105 | DFun (_, n, _, _, e) => if hasClient e then | 108 if hasClientPush e then |
106 IS.add (csids, n) | 109 IS.add (push_ids, n) |
107 else | 110 else |
108 csids | 111 push_ids) |
109 | DFunRec xes => if List.exists (fn (_, _, _, _, e) => hasClient e) xes then | 112 | DFun (_, n, _, _, e) => (if hasClientPull e then |
110 foldl (fn ((_, n, _, _, _), csids) => IS.add (csids, n)) | 113 IS.add (pull_ids, n) |
111 csids xes | 114 else |
112 else | 115 pull_ids, |
113 csids | 116 if hasClientPush e then |
114 | _ => csids | 117 IS.add (push_ids, n) |
118 else | |
119 push_ids) | |
120 | DFunRec xes => (if List.exists (fn (_, _, _, _, e) => hasClientPull e) xes then | |
121 foldl (fn ((_, n, _, _, _), pull_ids) => IS.add (pull_ids, n)) | |
122 pull_ids xes | |
123 else | |
124 pull_ids, | |
125 if List.exists (fn (_, _, _, _, e) => hasClientPush e) xes then | |
126 foldl (fn ((_, n, _, _, _), push_ids) => IS.add (push_ids, n)) | |
127 push_ids xes | |
128 else | |
129 push_ids) | |
130 | _ => (pull_ids, push_ids) | |
115 end | 131 end |
116 | 132 |
117 val csids = foldl decl IS.empty ds | 133 val (pull_ids, push_ids) = foldl decl (IS.empty, IS.empty) ds |
118 | 134 |
119 val ps = map (fn (ek, x, n, ts, t, _) => | 135 val ps = map (fn (ek, x, n, ts, t, _) => |
120 (ek, x, n, ts, t, | 136 (ek, x, n, ts, t, |
121 if IS.member (csids, n) then | 137 if IS.member (push_ids, n) then |
122 ServerAndClient | 138 ServerAndPullAndPush |
139 else if IS.member (pull_ids, n) then | |
140 ServerAndPull | |
123 else | 141 else |
124 ServerOnly)) ps | 142 ServerOnly)) ps |
125 in | 143 in |
126 (ds, ps) | 144 (ds, ps) |
127 end | 145 end |