Mercurial > urweb
comparison src/flat_util.sml @ 26:4ab19c19665f
Closure conversion
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 10 Jun 2008 15:56:33 -0400 |
parents | |
children | 104d43266b33 |
comparison
equal
deleted
inserted
replaced
25:0a762c73824d | 26:4ab19c19665f |
---|---|
1 (* Copyright (c) 2008, Adam Chlipala | |
2 * All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are met: | |
6 * | |
7 * - Redistributions of source code must retain the above copyright notice, | |
8 * this list of conditions and the following disclaimer. | |
9 * - Redistributions in binary form must reproduce the above copyright notice, | |
10 * this list of conditions and the following disclaimer in the documentation | |
11 * and/or other materials provided with the distribution. | |
12 * - The names of contributors may not be used to endorse or promote products | |
13 * derived from this software without specific prior written permission. | |
14 * | |
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 | |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
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 | |
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 | |
25 * POSSIBILITY OF SUCH DAMAGE. | |
26 *) | |
27 | |
28 structure FlatUtil :> FLAT_UTIL = struct | |
29 | |
30 open Flat | |
31 | |
32 structure S = Search | |
33 | |
34 structure Typ = struct | |
35 | |
36 fun mapfold fc = | |
37 let | |
38 fun mft c acc = | |
39 S.bindP (mft' c acc, fc) | |
40 | |
41 and mft' (cAll as (c, loc)) = | |
42 case c of | |
43 TFun (t1, t2) => | |
44 S.bind2 (mft t1, | |
45 fn t1' => | |
46 S.map2 (mft t2, | |
47 fn t2' => | |
48 (TFun (t1', t2'), loc))) | |
49 | TCode (t1, t2) => | |
50 S.bind2 (mft t1, | |
51 fn t1' => | |
52 S.map2 (mft t2, | |
53 fn t2' => | |
54 (TCode (t1', t2'), loc))) | |
55 | TRecord xts => | |
56 S.map2 (ListUtil.mapfold (fn (x, t) => | |
57 S.map2 (mft t, | |
58 fn t' => | |
59 (x, t'))) | |
60 xts, | |
61 fn xts' => (TRecord xts', loc)) | |
62 | TNamed _ => S.return2 cAll | |
63 in | |
64 mft | |
65 end | |
66 | |
67 fun map typ c = | |
68 case mapfold (fn c => fn () => S.Continue (typ c, ())) c () of | |
69 S.Return () => raise Fail "Flat_util.Typ.map" | |
70 | S.Continue (c, ()) => c | |
71 | |
72 fun fold typ s c = | |
73 case mapfold (fn c => fn s => S.Continue (c, typ (c, s))) c s of | |
74 S.Continue (_, s) => s | |
75 | S.Return _ => raise Fail "FlatUtil.Typ.fold: Impossible" | |
76 | |
77 fun exists typ k = | |
78 case mapfold (fn c => fn () => | |
79 if typ c then | |
80 S.Return () | |
81 else | |
82 S.Continue (c, ())) k () of | |
83 S.Return _ => true | |
84 | S.Continue _ => false | |
85 | |
86 end | |
87 | |
88 structure Exp = struct | |
89 | |
90 datatype binder = | |
91 NamedT of string * int * typ option | |
92 | RelE of string * typ | |
93 | NamedE of string * int * typ * exp option | |
94 | |
95 fun mapfoldB {typ = fc, exp = fe, bind} = | |
96 let | |
97 val mft = Typ.mapfold fc | |
98 | |
99 fun mfe ctx e acc = | |
100 S.bindP (mfe' ctx e acc, fe ctx) | |
101 | |
102 and mfe' ctx (eAll as (e, loc)) = | |
103 case e of | |
104 EPrim _ => S.return2 eAll | |
105 | ERel _ => S.return2 eAll | |
106 | ENamed _ => S.return2 eAll | |
107 | ECode _ => S.return2 eAll | |
108 | EApp (e1, e2) => | |
109 S.bind2 (mfe ctx e1, | |
110 fn e1' => | |
111 S.map2 (mfe ctx e2, | |
112 fn e2' => | |
113 (EApp (e1', e2'), loc))) | |
114 | |
115 | ERecord xes => | |
116 S.map2 (ListUtil.mapfold (fn (x, e) => | |
117 S.map2 (mfe ctx e, | |
118 fn e' => | |
119 (x, e'))) | |
120 xes, | |
121 fn xes' => | |
122 (ERecord xes', loc)) | |
123 | EField (e, x) => | |
124 S.map2 (mfe ctx e, | |
125 fn e' => | |
126 (EField (e', x), loc)) | |
127 | |
128 | ELet (xes, e) => | |
129 S.bind2 (ListUtil.mapfold (fn (x, e) => | |
130 S.map2 (mfe ctx e, | |
131 fn e' => | |
132 (x, e'))) | |
133 xes, | |
134 fn xes' => | |
135 S.map2 (mfe ctx e, | |
136 fn e' => | |
137 (ELet (xes', e'), loc))) | |
138 in | |
139 mfe | |
140 end | |
141 | |
142 fun mapfold {typ = fc, exp = fe} = | |
143 mapfoldB {typ = fc, | |
144 exp = fn () => fe, | |
145 bind = fn ((), _) => ()} () | |
146 | |
147 fun mapB {typ, exp, bind} ctx e = | |
148 case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), | |
149 exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), | |
150 bind = bind} ctx e () of | |
151 S.Continue (e, ()) => e | |
152 | S.Return _ => raise Fail "FlatUtil.Exp.mapB: Impossible" | |
153 | |
154 fun map {typ, exp} e = | |
155 case mapfold {typ = fn c => fn () => S.Continue (typ c, ()), | |
156 exp = fn e => fn () => S.Continue (exp e, ())} e () of | |
157 S.Return () => raise Fail "Flat_util.Exp.map" | |
158 | S.Continue (e, ()) => e | |
159 | |
160 fun fold {typ, exp} s e = | |
161 case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), | |
162 exp = fn e => fn s => S.Continue (e, exp (e, s))} e s of | |
163 S.Continue (_, s) => s | |
164 | S.Return _ => raise Fail "FlatUtil.Exp.fold: Impossible" | |
165 | |
166 fun exists {typ, exp} k = | |
167 case mapfold {typ = fn c => fn () => | |
168 if typ c then | |
169 S.Return () | |
170 else | |
171 S.Continue (c, ()), | |
172 exp = fn e => fn () => | |
173 if exp e then | |
174 S.Return () | |
175 else | |
176 S.Continue (e, ())} k () of | |
177 S.Return _ => true | |
178 | S.Continue _ => false | |
179 | |
180 end | |
181 | |
182 structure Decl = struct | |
183 | |
184 datatype binder = datatype Exp.binder | |
185 | |
186 fun mapfoldB {typ = fc, exp = fe, decl = fd, bind} = | |
187 let | |
188 val mft = Typ.mapfold fc | |
189 | |
190 val mfe = Exp.mapfoldB {typ = fc, exp = fe, bind = bind} | |
191 | |
192 fun mfd ctx d acc = | |
193 S.bindP (mfd' ctx d acc, fd ctx) | |
194 | |
195 and mfd' ctx (dAll as (d, loc)) = | |
196 case d of | |
197 DVal (x, n, t, e) => | |
198 S.bind2 (mft t, | |
199 fn t' => | |
200 S.map2 (mfe ctx e, | |
201 fn e' => | |
202 (DVal (x, n, t', e'), loc))) | |
203 | DFun (n, x, dom, ran, e) => | |
204 S.bind2 (mft dom, | |
205 fn dom' => | |
206 S.bind2 (mft ran, | |
207 fn ran' => | |
208 S.map2 (mfe ctx e, | |
209 fn e' => | |
210 (DFun (n, x, dom', ran', e'), loc)))) | |
211 in | |
212 mfd | |
213 end | |
214 | |
215 fun mapfold {typ = fc, exp = fe, decl = fd} = | |
216 mapfoldB {typ = fc, | |
217 exp = fn () => fe, | |
218 decl = fn () => fd, | |
219 bind = fn ((), _) => ()} () | |
220 | |
221 fun fold {typ, exp, decl} s d = | |
222 case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), | |
223 exp = fn e => fn s => S.Continue (e, exp (e, s)), | |
224 decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of | |
225 S.Continue (_, s) => s | |
226 | S.Return _ => raise Fail "FlatUtil.Decl.fold: Impossible" | |
227 | |
228 end | |
229 | |
230 structure File = struct | |
231 | |
232 datatype binder = | |
233 NamedT of string * int * typ option | |
234 | RelE of string * typ | |
235 | NamedE of string * int * typ * exp option | |
236 | F of int * string * Flat.typ * Flat.typ * Flat.exp | |
237 | |
238 fun mapfoldB (all as {bind, ...}) = | |
239 let | |
240 val mfd = Decl.mapfoldB all | |
241 | |
242 fun mff ctx ds = | |
243 case ds of | |
244 nil => S.return2 nil | |
245 | d :: ds' => | |
246 S.bind2 (mfd ctx d, | |
247 fn d' => | |
248 let | |
249 val b = | |
250 case #1 d' of | |
251 DVal (x, n, t, e) => NamedE (x, n, t, SOME e) | |
252 | DFun v => F v | |
253 val ctx' = bind (ctx, b) | |
254 in | |
255 S.map2 (mff ctx' ds', | |
256 fn ds' => | |
257 d' :: ds') | |
258 end) | |
259 in | |
260 mff | |
261 end | |
262 | |
263 fun mapfold {typ = fc, exp = fe, decl = fd} = | |
264 mapfoldB {typ = fc, | |
265 exp = fn () => fe, | |
266 decl = fn () => fd, | |
267 bind = fn ((), _) => ()} () | |
268 | |
269 fun mapB {typ, exp, decl, bind} ctx ds = | |
270 case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), | |
271 exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), | |
272 decl = fn ctx => fn d => fn () => S.Continue (decl ctx d, ()), | |
273 bind = bind} ctx ds () of | |
274 S.Continue (ds, ()) => ds | |
275 | S.Return _ => raise Fail "FlatUtil.File.mapB: Impossible" | |
276 | |
277 fun fold {typ, exp, decl} s d = | |
278 case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), | |
279 exp = fn e => fn s => S.Continue (e, exp (e, s)), | |
280 decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of | |
281 S.Continue (_, s) => s | |
282 | S.Return _ => raise Fail "FlatUtil.File.fold: Impossible" | |
283 | |
284 end | |
285 | |
286 end |