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
|
adamc@879
|
47 | EFfiApp (_, _, es) => foldl IS.union IS.empty (map eu 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
|
adamc@879
|
59 | EReturnBlob {blob, mimeType, ...} => IS.union (eu blob, eu mimeType)
|
adamc@879
|
60
|
adamc@879
|
61 | EWrite e => eu e
|
adamc@879
|
62 | ESeq (e1, e2) => IS.union (eu e1, eu e2)
|
adamc@879
|
63 | ELet (_, _, e1, e2) => IS.union (eu e1, eu e2)
|
adamc@879
|
64
|
adamc@879
|
65 | EQuery {query, body, initial, prepared, ...} =>
|
adamc@879
|
66 let
|
adamc@879
|
67 val s = IS.union (eu query, IS.union (eu body, eu initial))
|
adamc@879
|
68 in
|
adamc@879
|
69 case prepared of
|
adamc@879
|
70 SOME {id, ...} => IS.add (s, id)
|
adamc@879
|
71 | _ => s
|
adamc@879
|
72 end
|
adamc@879
|
73 | EDml {dml, prepared, ...} =>
|
adamc@879
|
74 let
|
adamc@879
|
75 val s = eu dml
|
adamc@879
|
76 in
|
adamc@879
|
77 case prepared of
|
adamc@879
|
78 SOME {id, ...} => IS.add (s, id)
|
adamc@879
|
79 | _ => s
|
adamc@879
|
80 end
|
adamc@879
|
81 | ENextval {seq, prepared, ...} =>
|
adamc@879
|
82 let
|
adamc@879
|
83 val s = eu seq
|
adamc@879
|
84 in
|
adamc@879
|
85 case prepared of
|
adamc@879
|
86 SOME {id, ...} => IS.add (s, id)
|
adamc@879
|
87 | _ => s
|
adamc@879
|
88 end
|
adamc@879
|
89
|
adamc@879
|
90 | EUnurlify (e, _) => eu e
|
adamc@879
|
91 in
|
adamc@879
|
92 eu
|
adamc@879
|
93 end
|
adamc@879
|
94
|
adamc@879
|
95 fun annotateExp globals =
|
adamc@879
|
96 let
|
adamc@879
|
97 fun ae (e as (_, loc)) =
|
adamc@879
|
98 case #1 e of
|
adamc@879
|
99 EPrim _ => e
|
adamc@879
|
100 | ERel _ => e
|
adamc@879
|
101 | ENamed n => e
|
adamc@879
|
102 | ECon (_, _, NONE) => e
|
adamc@879
|
103 | ECon (dk, pc, SOME e) => (ECon (dk, pc, SOME (ae e)), loc)
|
adamc@879
|
104 | ENone _ => e
|
adamc@879
|
105 | ESome (t, e) => (ESome (t, ae e), loc)
|
adamc@879
|
106 | EFfi _ => e
|
adamc@879
|
107 | EFfiApp (m, f, es) => (EFfiApp (m, f, map ae es), loc)
|
adamc@879
|
108 | EApp (e, es) => (EApp (ae e, map ae es), loc)
|
adamc@879
|
109
|
adamc@879
|
110 | EUnop (uo, e) => (EUnop (uo, ae e), loc)
|
adamc@879
|
111 | EBinop (bo, e1, e2) => (EBinop (bo, ae e1, ae e2), loc)
|
adamc@879
|
112
|
adamc@879
|
113 | ERecord (n, xes) => (ERecord (n, map (fn (x, e) => (x, ae e)) xes), loc)
|
adamc@879
|
114 | EField (e, f) => (EField (ae e, f), loc)
|
adamc@879
|
115
|
adamc@879
|
116 | ECase (e, pes, ts) => (ECase (ae e, map (fn (p, e) => (p, ae e)) pes, ts), loc)
|
adamc@879
|
117
|
adamc@879
|
118 | EError (e, t) => (EError (ae e, t), loc)
|
adamc@879
|
119 | EReturnBlob {blob, mimeType, t} => (EReturnBlob {blob = ae blob, mimeType = ae mimeType, t = t}, loc)
|
adamc@879
|
120
|
adamc@879
|
121 | EWrite e => (EWrite (ae e), loc)
|
adamc@879
|
122 | ESeq (e1, e2) => (ESeq (ae e1, ae e2), loc)
|
adamc@879
|
123 | ELet (x, t, e1, e2) => (ELet (x, t, ae e1, ae e2), loc)
|
adamc@879
|
124
|
adamc@879
|
125 | EQuery {exps, tables, rnum, state, query, body, initial, prepared} =>
|
adamc@879
|
126 (EQuery {exps = exps,
|
adamc@879
|
127 tables = tables,
|
adamc@879
|
128 rnum = rnum,
|
adamc@879
|
129 state = state,
|
adamc@879
|
130 query = ae query,
|
adamc@879
|
131 body = ae body,
|
adamc@879
|
132 initial = ae initial,
|
adamc@879
|
133 prepared = case prepared of
|
adamc@879
|
134 NONE => NONE
|
adamc@879
|
135 | SOME {id, query, ...} => SOME {id = id, query = query,
|
adamc@879
|
136 nested = IS.member (expUses globals body, id)}},
|
adamc@879
|
137 loc)
|
adamc@879
|
138 | EDml {dml, prepared} =>
|
adamc@879
|
139 (EDml {dml = ae dml,
|
adamc@879
|
140 prepared = prepared}, loc)
|
adamc@879
|
141
|
adamc@879
|
142 | ENextval {seq, prepared} =>
|
adamc@879
|
143 (ENextval {seq = ae seq,
|
adamc@879
|
144 prepared = prepared}, loc)
|
adamc@879
|
145
|
adamc@879
|
146 | EUnurlify (e, t) => (EUnurlify (ae e, t), loc)
|
adamc@879
|
147 in
|
adamc@879
|
148 ae
|
adamc@879
|
149 end
|
adamc@879
|
150
|
adamc@879
|
151 fun annotate (ds, syms) =
|
adamc@879
|
152 let
|
adamc@879
|
153 val globals =
|
adamc@879
|
154 foldl (fn ((d, _), globals) =>
|
adamc@879
|
155 case d of
|
adamc@879
|
156 DVal (_, n, _, e) => IM.insert (globals, n, expUses globals e)
|
adamc@879
|
157 | DFun (_, n, _, _, e) => IM.insert (globals, n, expUses globals e)
|
adamc@879
|
158 | DFunRec fs =>
|
adamc@879
|
159 let
|
adamc@879
|
160 val s = foldl (fn ((_, _, _, _, e), s) => IS.union (expUses globals e, s)) IS.empty fs
|
adamc@879
|
161 in
|
adamc@879
|
162 foldl (fn ((_, n, _, _, _), globals) => IM.insert (globals, n, s)) globals fs
|
adamc@879
|
163 end
|
adamc@879
|
164 | _ => globals) IM.empty ds
|
adamc@879
|
165
|
adamc@879
|
166 val ds =
|
adamc@879
|
167 map (fn d as (_, loc) =>
|
adamc@879
|
168 case #1 d of
|
adamc@879
|
169 DVal (x, n, t, e) => (DVal (x, n, t, annotateExp globals e), loc)
|
adamc@879
|
170 | DFun (x, n, ts, t, e) => (DFun (x, n, ts, t, annotateExp globals e), loc)
|
adamc@879
|
171 | DFunRec fs => (DFunRec
|
adamc@879
|
172 (map (fn (x, n, ts, t, e) => (x, n, ts, t, annotateExp globals e)) fs), loc)
|
adamc@879
|
173 | _ => d) ds
|
adamc@879
|
174 in
|
adamc@879
|
175 (ds, syms)
|
adamc@879
|
176 end
|
adamc@879
|
177
|
adamc@879
|
178 end
|