Mercurial > urweb
comparison src/mono_util.sml @ 26:4ab19c19665f
Closure conversion
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 10 Jun 2008 15:56:33 -0400 |
parents | |
children | 537db4ee89f4 |
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 MonoUtil :> MONO_UTIL = struct | |
29 | |
30 open Mono | |
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 | TRecord xts => | |
50 S.map2 (ListUtil.mapfold (fn (x, t) => | |
51 S.map2 (mft t, | |
52 fn t' => | |
53 (x, t'))) | |
54 xts, | |
55 fn xts' => (TRecord xts', loc)) | |
56 | TNamed _ => S.return2 cAll | |
57 in | |
58 mft | |
59 end | |
60 | |
61 fun map typ c = | |
62 case mapfold (fn c => fn () => S.Continue (typ c, ())) c () of | |
63 S.Return () => raise Fail "Mono_util.Typ.map" | |
64 | S.Continue (c, ()) => c | |
65 | |
66 fun fold typ s c = | |
67 case mapfold (fn c => fn s => S.Continue (c, typ (c, s))) c s of | |
68 S.Continue (_, s) => s | |
69 | S.Return _ => raise Fail "MonoUtil.Typ.fold: Impossible" | |
70 | |
71 fun exists typ k = | |
72 case mapfold (fn c => fn () => | |
73 if typ c then | |
74 S.Return () | |
75 else | |
76 S.Continue (c, ())) k () of | |
77 S.Return _ => true | |
78 | S.Continue _ => false | |
79 | |
80 end | |
81 | |
82 structure Exp = struct | |
83 | |
84 datatype binder = | |
85 NamedT of string * int * typ option | |
86 | RelE of string * typ | |
87 | NamedE of string * int * typ * exp option | |
88 | |
89 fun mapfoldB {typ = fc, exp = fe, bind} = | |
90 let | |
91 val mft = Typ.mapfold fc | |
92 | |
93 fun mfe ctx e acc = | |
94 S.bindP (mfe' ctx e acc, fe ctx) | |
95 | |
96 and mfe' ctx (eAll as (e, loc)) = | |
97 case e of | |
98 EPrim _ => S.return2 eAll | |
99 | ERel _ => S.return2 eAll | |
100 | ENamed _ => S.return2 eAll | |
101 | EApp (e1, e2) => | |
102 S.bind2 (mfe ctx e1, | |
103 fn e1' => | |
104 S.map2 (mfe ctx e2, | |
105 fn e2' => | |
106 (EApp (e1', e2'), loc))) | |
107 | EAbs (x, dom, ran, e) => | |
108 S.bind2 (mft dom, | |
109 fn dom' => | |
110 S.bind2 (mft ran, | |
111 fn ran' => | |
112 S.map2 (mfe (bind (ctx, RelE (x, dom'))) e, | |
113 fn e' => | |
114 (EAbs (x, dom', ran', e'), loc)))) | |
115 | |
116 | ERecord xes => | |
117 S.map2 (ListUtil.mapfold (fn (x, e) => | |
118 S.map2 (mfe ctx e, | |
119 fn e' => | |
120 (x, e'))) | |
121 xes, | |
122 fn xes' => | |
123 (ERecord xes', loc)) | |
124 | EField (e, x) => | |
125 S.map2 (mfe ctx e, | |
126 fn e' => | |
127 (EField (e', x), loc)) | |
128 in | |
129 mfe | |
130 end | |
131 | |
132 fun mapfold {typ = fc, exp = fe} = | |
133 mapfoldB {typ = fc, | |
134 exp = fn () => fe, | |
135 bind = fn ((), _) => ()} () | |
136 | |
137 fun mapB {typ, exp, bind} ctx e = | |
138 case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), | |
139 exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), | |
140 bind = bind} ctx e () of | |
141 S.Continue (e, ()) => e | |
142 | S.Return _ => raise Fail "MonoUtil.Exp.mapB: Impossible" | |
143 | |
144 fun map {typ, exp} e = | |
145 case mapfold {typ = fn c => fn () => S.Continue (typ c, ()), | |
146 exp = fn e => fn () => S.Continue (exp e, ())} e () of | |
147 S.Return () => raise Fail "Mono_util.Exp.map" | |
148 | S.Continue (e, ()) => e | |
149 | |
150 fun fold {typ, exp} s e = | |
151 case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), | |
152 exp = fn e => fn s => S.Continue (e, exp (e, s))} e s of | |
153 S.Continue (_, s) => s | |
154 | S.Return _ => raise Fail "MonoUtil.Exp.fold: Impossible" | |
155 | |
156 fun exists {typ, exp} k = | |
157 case mapfold {typ = fn c => fn () => | |
158 if typ c then | |
159 S.Return () | |
160 else | |
161 S.Continue (c, ()), | |
162 exp = fn e => fn () => | |
163 if exp e then | |
164 S.Return () | |
165 else | |
166 S.Continue (e, ())} k () of | |
167 S.Return _ => true | |
168 | S.Continue _ => false | |
169 | |
170 end | |
171 | |
172 structure Decl = struct | |
173 | |
174 datatype binder = datatype Exp.binder | |
175 | |
176 fun mapfoldB {typ = fc, exp = fe, decl = fd, bind} = | |
177 let | |
178 val mft = Typ.mapfold fc | |
179 | |
180 val mfe = Exp.mapfoldB {typ = fc, exp = fe, bind = bind} | |
181 | |
182 fun mfd ctx d acc = | |
183 S.bindP (mfd' ctx d acc, fd ctx) | |
184 | |
185 and mfd' ctx (dAll as (d, loc)) = | |
186 case d of | |
187 DVal (x, n, t, e) => | |
188 S.bind2 (mft t, | |
189 fn t' => | |
190 S.map2 (mfe ctx e, | |
191 fn e' => | |
192 (DVal (x, n, t', e'), loc))) | |
193 in | |
194 mfd | |
195 end | |
196 | |
197 fun mapfold {typ = fc, exp = fe, decl = fd} = | |
198 mapfoldB {typ = fc, | |
199 exp = fn () => fe, | |
200 decl = fn () => fd, | |
201 bind = fn ((), _) => ()} () | |
202 | |
203 fun fold {typ, exp, decl} s d = | |
204 case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), | |
205 exp = fn e => fn s => S.Continue (e, exp (e, s)), | |
206 decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of | |
207 S.Continue (_, s) => s | |
208 | S.Return _ => raise Fail "MonoUtil.Decl.fold: Impossible" | |
209 | |
210 end | |
211 | |
212 structure File = struct | |
213 | |
214 datatype binder = datatype Exp.binder | |
215 | |
216 fun mapfoldB (all as {bind, ...}) = | |
217 let | |
218 val mfd = Decl.mapfoldB all | |
219 | |
220 fun mff ctx ds = | |
221 case ds of | |
222 nil => S.return2 nil | |
223 | d :: ds' => | |
224 S.bind2 (mfd ctx d, | |
225 fn d' => | |
226 let | |
227 val b = | |
228 case #1 d' of | |
229 DVal (x, n, t, e) => NamedE (x, n, t, SOME e) | |
230 val ctx' = bind (ctx, b) | |
231 in | |
232 S.map2 (mff ctx' ds', | |
233 fn ds' => | |
234 d' :: ds') | |
235 end) | |
236 in | |
237 mff | |
238 end | |
239 | |
240 fun mapfold {typ = fc, exp = fe, decl = fd} = | |
241 mapfoldB {typ = fc, | |
242 exp = fn () => fe, | |
243 decl = fn () => fd, | |
244 bind = fn ((), _) => ()} () | |
245 | |
246 fun mapB {typ, exp, decl, bind} ctx ds = | |
247 case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), | |
248 exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), | |
249 decl = fn ctx => fn d => fn () => S.Continue (decl ctx d, ()), | |
250 bind = bind} ctx ds () of | |
251 S.Continue (ds, ()) => ds | |
252 | S.Return _ => raise Fail "MonoUtil.File.mapB: Impossible" | |
253 | |
254 fun fold {typ, exp, decl} s d = | |
255 case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), | |
256 exp = fn e => fn s => S.Continue (e, exp (e, s)), | |
257 decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of | |
258 S.Continue (_, s) => s | |
259 | S.Return _ => raise Fail "MonoUtil.File.fold: Impossible" | |
260 | |
261 end | |
262 | |
263 end |