adamc@879
|
1 (* Copyright (c) 2009, Adam Chlipala
|
adamc@879
|
2 * All rights reserved.
|
adamc@879
|
3 *
|
adamc@879
|
4 * Redistribution and use in source and binary forms, with or without
|
adamc@879
|
5 * modification, are permitted provided that the following conditions are met:
|
adamc@879
|
6 *
|
adamc@879
|
7 * - Redistributions of source code must retain the above copyright notice,
|
adamc@879
|
8 * this list of conditions and the following disclaimer.
|
adamc@879
|
9 * - Redistributions in binary form must reproduce the above copyright notice,
|
adamc@879
|
10 * this list of conditions and the following disclaimer in the documentation
|
adamc@879
|
11 * and/or other materials provided with the distribution.
|
adamc@879
|
12 * - The names of contributors may not be used to endorse or promote products
|
adamc@879
|
13 * derived from this software without specific prior written permission.
|
adamc@879
|
14 *
|
adamc@879
|
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
adamc@879
|
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
adamc@879
|
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
adamc@879
|
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
adamc@879
|
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
adamc@879
|
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
adamc@879
|
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
adamc@879
|
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
adamc@879
|
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
adamc@879
|
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
adamc@879
|
25 * POSSIBILITY OF SUCH DAMAGE.
|
adamc@879
|
26 *)
|
adamc@879
|
27
|
adamc@879
|
28 structure Checknest :> CHECKNEST = struct
|
adamc@879
|
29
|
adamc@879
|
30 open Cjr
|
adamc@879
|
31
|
adamc@879
|
32 structure IS = IntBinarySet
|
adamc@879
|
33 structure IM = IntBinaryMap
|
adamc@879
|
34
|
adamc@879
|
35 fun expUses globals =
|
adamc@879
|
36 let
|
adamc@879
|
37 fun eu (e, _) =
|
adamc@879
|
38 case e of
|
adamc@879
|
39 EPrim _ => IS.empty
|
adamc@879
|
40 | ERel _ => IS.empty
|
adamc@879
|
41 | ENamed n => Option.getOpt (IM.find (globals, n), IS.empty)
|
adamc@879
|
42 | ECon (_, _, NONE) => IS.empty
|
adamc@879
|
43 | ECon (_, _, SOME e) => eu e
|
adamc@879
|
44 | ENone _ => IS.empty
|
adamc@879
|
45 | ESome (_, e) => eu e
|
adamc@879
|
46 | EFfi _ => IS.empty
|
adam@1663
|
47 | EFfiApp (_, _, es) => foldl IS.union IS.empty (map (eu o #1) es)
|
adamc@879
|
48 | EApp (e, es) => foldl IS.union (eu e) (map eu es)
|
adamc@879
|
49
|
adamc@879
|
50 | EUnop (_, e) => eu e
|
adamc@879
|
51 | EBinop (_, e1, e2) => IS.union (eu e1, eu e2)
|
adamc@879
|
52
|
adamc@879
|
53 | ERecord (_, xes) => foldl (fn ((_, e), s) => IS.union (eu e, s)) IS.empty xes
|
adamc@879
|
54 | EField (e, _) => eu e
|
adamc@879
|
55
|
adamc@879
|
56 | ECase (e, pes, _) => foldl (fn ((_, e), s) => IS.union (eu e, s)) (eu e) pes
|
adamc@879
|
57
|
adamc@879
|
58 | EError (e, _) => eu e
|
adam@1932
|
59 | EReturnBlob {blob = NONE, mimeType, ...} => eu mimeType
|
adam@1932
|
60 | EReturnBlob {blob = SOME blob, mimeType, ...} => IS.union (eu blob, eu mimeType)
|
adamc@1065
|
61 | ERedirect (e, _) => eu e
|
adamc@879
|
62
|
adamc@879
|
63 | EWrite e => eu e
|
adamc@879
|
64 | ESeq (e1, e2) => IS.union (eu e1, eu e2)
|
adamc@879
|
65 | ELet (_, _, e1, e2) => IS.union (eu e1, eu e2)
|
adamc@879
|
66
|
adamc@879
|
67 | EQuery {query, body, initial, prepared, ...} =>
|
adamc@879
|
68 let
|
adamc@879
|
69 val s = IS.union (eu query, IS.union (eu body, eu initial))
|
adamc@879
|
70 in
|
adamc@879
|
71 case prepared of
|
adamc@879
|
72 SOME {id, ...} => IS.add (s, id)
|
adamc@879
|
73 | _ => s
|
adamc@879
|
74 end
|
adamc@879
|
75 | EDml {dml, prepared, ...} =>
|
adamc@879
|
76 let
|
adamc@879
|
77 val s = eu dml
|
adamc@879
|
78 in
|
adamc@879
|
79 case prepared of
|
adamc@879
|
80 SOME {id, ...} => IS.add (s, id)
|
adamc@879
|
81 | _ => s
|
adamc@879
|
82 end
|
adamc@879
|
83 | ENextval {seq, prepared, ...} =>
|
adamc@879
|
84 let
|
adamc@879
|
85 val s = eu seq
|
adamc@879
|
86 in
|
adamc@879
|
87 case prepared of
|
adamc@879
|
88 SOME {id, ...} => IS.add (s, id)
|
adamc@879
|
89 | _ => s
|
adamc@879
|
90 end
|
adamc@1073
|
91 | ESetval {seq, count} => IS.union (eu seq, eu count)
|
adamc@879
|
92
|
adamc@1112
|
93 | EUnurlify (e, _, _) => eu e
|
adamc@879
|
94 in
|
adamc@879
|
95 eu
|
adamc@879
|
96 end
|
adamc@879
|
97
|
adamc@879
|
98 fun annotateExp globals =
|
adamc@879
|
99 let
|
adamc@879
|
100 fun ae (e as (_, loc)) =
|
adamc@879
|
101 case #1 e of
|
adamc@879
|
102 EPrim _ => e
|
adamc@879
|
103 | ERel _ => e
|
adamc@879
|
104 | ENamed n => e
|
adamc@879
|
105 | ECon (_, _, NONE) => e
|
adamc@879
|
106 | ECon (dk, pc, SOME e) => (ECon (dk, pc, SOME (ae e)), loc)
|
adamc@879
|
107 | ENone _ => e
|
adamc@879
|
108 | ESome (t, e) => (ESome (t, ae e), loc)
|
adamc@879
|
109 | EFfi _ => e
|
adam@1663
|
110 | EFfiApp (m, f, es) => (EFfiApp (m, f, map (fn (e, t) => (ae e, t)) es), loc)
|
adamc@879
|
111 | EApp (e, es) => (EApp (ae e, map ae es), loc)
|
adamc@879
|
112
|
adamc@879
|
113 | EUnop (uo, e) => (EUnop (uo, ae e), loc)
|
adamc@879
|
114 | EBinop (bo, e1, e2) => (EBinop (bo, ae e1, ae e2), loc)
|
adamc@879
|
115
|
adamc@879
|
116 | ERecord (n, xes) => (ERecord (n, map (fn (x, e) => (x, ae e)) xes), loc)
|
adamc@879
|
117 | EField (e, f) => (EField (ae e, f), loc)
|
adamc@879
|
118
|
adamc@879
|
119 | ECase (e, pes, ts) => (ECase (ae e, map (fn (p, e) => (p, ae e)) pes, ts), loc)
|
adamc@879
|
120
|
adamc@879
|
121 | EError (e, t) => (EError (ae e, t), loc)
|
adam@1932
|
122 | EReturnBlob {blob = NONE, mimeType, t} => (EReturnBlob {blob = NONE, mimeType = ae mimeType, t = t}, loc)
|
adam@1932
|
123 | EReturnBlob {blob = SOME blob, mimeType, t} => (EReturnBlob {blob = SOME (ae blob), mimeType = ae mimeType, t = t}, loc)
|
adamc@1065
|
124 | ERedirect (e, t) => (ERedirect (ae e, t), loc)
|
adamc@879
|
125
|
adamc@879
|
126 | EWrite e => (EWrite (ae e), loc)
|
adamc@879
|
127 | ESeq (e1, e2) => (ESeq (ae e1, ae e2), loc)
|
adamc@879
|
128 | ELet (x, t, e1, e2) => (ELet (x, t, ae e1, ae e2), loc)
|
adamc@879
|
129
|
adamc@879
|
130 | EQuery {exps, tables, rnum, state, query, body, initial, prepared} =>
|
adamc@879
|
131 (EQuery {exps = exps,
|
adamc@879
|
132 tables = tables,
|
adamc@879
|
133 rnum = rnum,
|
adamc@879
|
134 state = state,
|
adamc@879
|
135 query = ae query,
|
adamc@879
|
136 body = ae body,
|
adamc@879
|
137 initial = ae initial,
|
adamc@879
|
138 prepared = case prepared of
|
adamc@879
|
139 NONE => NONE
|
adamc@879
|
140 | SOME {id, query, ...} => SOME {id = id, query = query,
|
adamc@879
|
141 nested = IS.member (expUses globals body, id)}},
|
adamc@879
|
142 loc)
|
adam@1293
|
143 | EDml {dml, prepared, mode} =>
|
adamc@879
|
144 (EDml {dml = ae dml,
|
adam@1293
|
145 prepared = prepared,
|
adam@1293
|
146 mode = mode}, loc)
|
adamc@879
|
147
|
adamc@879
|
148 | ENextval {seq, prepared} =>
|
adamc@879
|
149 (ENextval {seq = ae seq,
|
adamc@879
|
150 prepared = prepared}, loc)
|
adamc@1073
|
151 | ESetval {seq, count} =>
|
adamc@1073
|
152 (ESetval {seq = ae seq,
|
adamc@1073
|
153 count = ae count}, loc)
|
adamc@879
|
154
|
adamc@1112
|
155 | EUnurlify (e, t, b) => (EUnurlify (ae e, t, b), loc)
|
adamc@879
|
156 in
|
adamc@879
|
157 ae
|
adamc@879
|
158 end
|
adamc@879
|
159
|
adamc@879
|
160 fun annotate (ds, syms) =
|
adamc@879
|
161 let
|
adamc@879
|
162 val globals =
|
adamc@879
|
163 foldl (fn ((d, _), globals) =>
|
adamc@879
|
164 case d of
|
adamc@879
|
165 DVal (_, n, _, e) => IM.insert (globals, n, expUses globals e)
|
adamc@879
|
166 | DFun (_, n, _, _, e) => IM.insert (globals, n, expUses globals e)
|
adamc@879
|
167 | DFunRec fs =>
|
adamc@879
|
168 let
|
adamc@879
|
169 val s = foldl (fn ((_, _, _, _, e), s) => IS.union (expUses globals e, s)) IS.empty fs
|
adamc@879
|
170 in
|
adamc@879
|
171 foldl (fn ((_, n, _, _, _), globals) => IM.insert (globals, n, s)) globals fs
|
adamc@879
|
172 end
|
adamc@879
|
173 | _ => globals) IM.empty ds
|
adamc@879
|
174
|
adamc@879
|
175 val ds =
|
adamc@879
|
176 map (fn d as (_, loc) =>
|
adamc@879
|
177 case #1 d of
|
adamc@879
|
178 DVal (x, n, t, e) => (DVal (x, n, t, annotateExp globals e), loc)
|
adamc@879
|
179 | DFun (x, n, ts, t, e) => (DFun (x, n, ts, t, annotateExp globals e), loc)
|
adamc@879
|
180 | DFunRec fs => (DFunRec
|
adamc@879
|
181 (map (fn (x, n, ts, t, e) => (x, n, ts, t, annotateExp globals e)) fs), loc)
|
adamc@879
|
182 | _ => d) ds
|
adamc@879
|
183 in
|
adamc@879
|
184 (ds, syms)
|
adamc@879
|
185 end
|
adamc@879
|
186
|
adamc@879
|
187 end
|