Mercurial > urweb
comparison src/expl_util.sml @ 38:d16ef24de78b
Explify
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Thu, 19 Jun 2008 10:06:59 -0400 |
parents | |
children | 3c1ce1b4eb3d |
comparison
equal
deleted
inserted
replaced
37:367f058aba23 | 38:d16ef24de78b |
---|---|
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 ExplUtil :> EXPL_UTIL = struct | |
29 | |
30 open Expl | |
31 | |
32 structure S = Search | |
33 | |
34 structure Kind = struct | |
35 | |
36 fun mapfold f = | |
37 let | |
38 fun mfk k acc = | |
39 S.bindP (mfk' k acc, f) | |
40 | |
41 and mfk' (kAll as (k, loc)) = | |
42 case k of | |
43 KType => S.return2 kAll | |
44 | |
45 | KArrow (k1, k2) => | |
46 S.bind2 (mfk k1, | |
47 fn k1' => | |
48 S.map2 (mfk k2, | |
49 fn k2' => | |
50 (KArrow (k1', k2'), loc))) | |
51 | |
52 | KName => S.return2 kAll | |
53 | |
54 | KRecord k => | |
55 S.map2 (mfk k, | |
56 fn k' => | |
57 (KRecord k', loc)) | |
58 in | |
59 mfk | |
60 end | |
61 | |
62 fun exists f k = | |
63 case mapfold (fn k => fn () => | |
64 if f k then | |
65 S.Return () | |
66 else | |
67 S.Continue (k, ())) k () of | |
68 S.Return _ => true | |
69 | S.Continue _ => false | |
70 | |
71 end | |
72 | |
73 structure Con = struct | |
74 | |
75 datatype binder = | |
76 Rel of string * Expl.kind | |
77 | Named of string * Expl.kind | |
78 | |
79 fun mapfoldB {kind = fk, con = fc, bind} = | |
80 let | |
81 val mfk = Kind.mapfold fk | |
82 | |
83 fun mfc ctx c acc = | |
84 S.bindP (mfc' ctx c acc, fc ctx) | |
85 | |
86 and mfc' ctx (cAll as (c, loc)) = | |
87 case c of | |
88 TFun (c1, c2) => | |
89 S.bind2 (mfc ctx c1, | |
90 fn c1' => | |
91 S.map2 (mfc ctx c2, | |
92 fn c2' => | |
93 (TFun (c1', c2'), loc))) | |
94 | TCFun (x, k, c) => | |
95 S.bind2 (mfk k, | |
96 fn k' => | |
97 S.map2 (mfc (bind (ctx, Rel (x, k))) c, | |
98 fn c' => | |
99 (TCFun (x, k', c'), loc))) | |
100 | TRecord c => | |
101 S.map2 (mfc ctx c, | |
102 fn c' => | |
103 (TRecord c', loc)) | |
104 | |
105 | CRel _ => S.return2 cAll | |
106 | CNamed _ => S.return2 cAll | |
107 | CModProj _ => S.return2 cAll | |
108 | CApp (c1, c2) => | |
109 S.bind2 (mfc ctx c1, | |
110 fn c1' => | |
111 S.map2 (mfc ctx c2, | |
112 fn c2' => | |
113 (CApp (c1', c2'), loc))) | |
114 | CAbs (x, k, c) => | |
115 S.bind2 (mfk k, | |
116 fn k' => | |
117 S.map2 (mfc (bind (ctx, Rel (x, k))) c, | |
118 fn c' => | |
119 (CAbs (x, k', c'), loc))) | |
120 | |
121 | CName _ => S.return2 cAll | |
122 | |
123 | CRecord (k, xcs) => | |
124 S.bind2 (mfk k, | |
125 fn k' => | |
126 S.map2 (ListUtil.mapfold (fn (x, c) => | |
127 S.bind2 (mfc ctx x, | |
128 fn x' => | |
129 S.map2 (mfc ctx c, | |
130 fn c' => | |
131 (x', c')))) | |
132 xcs, | |
133 fn xcs' => | |
134 (CRecord (k', xcs'), loc))) | |
135 | CConcat (c1, c2) => | |
136 S.bind2 (mfc ctx c1, | |
137 fn c1' => | |
138 S.map2 (mfc ctx c2, | |
139 fn c2' => | |
140 (CConcat (c1', c2'), loc))) | |
141 in | |
142 mfc | |
143 end | |
144 | |
145 fun mapfold {kind = fk, con = fc} = | |
146 mapfoldB {kind = fk, | |
147 con = fn () => fc, | |
148 bind = fn ((), _) => ()} () | |
149 | |
150 fun mapB {kind, con, bind} ctx c = | |
151 case mapfoldB {kind = fn k => fn () => S.Continue (kind k, ()), | |
152 con = fn ctx => fn c => fn () => S.Continue (con ctx c, ()), | |
153 bind = bind} ctx c () of | |
154 S.Continue (c, ()) => c | |
155 | S.Return _ => raise Fail "ExplUtil.Con.mapB: Impossible" | |
156 | |
157 fun map {kind, con} s = | |
158 case mapfold {kind = fn k => fn () => S.Continue (kind k, ()), | |
159 con = fn c => fn () => S.Continue (con c, ())} s () of | |
160 S.Return () => raise Fail "ExplUtil.Con.map: Impossible" | |
161 | S.Continue (s, ()) => s | |
162 | |
163 fun exists {kind, con} k = | |
164 case mapfold {kind = fn k => fn () => | |
165 if kind k then | |
166 S.Return () | |
167 else | |
168 S.Continue (k, ()), | |
169 con = fn c => fn () => | |
170 if con c then | |
171 S.Return () | |
172 else | |
173 S.Continue (c, ())} k () of | |
174 S.Return _ => true | |
175 | S.Continue _ => false | |
176 | |
177 end | |
178 | |
179 structure Exp = struct | |
180 | |
181 datatype binder = | |
182 RelC of string * Expl.kind | |
183 | NamedC of string * Expl.kind | |
184 | RelE of string * Expl.con | |
185 | NamedE of string * Expl.con | |
186 | |
187 fun mapfoldB {kind = fk, con = fc, exp = fe, bind} = | |
188 let | |
189 val mfk = Kind.mapfold fk | |
190 | |
191 fun bind' (ctx, b) = | |
192 let | |
193 val b' = case b of | |
194 Con.Rel x => RelC x | |
195 | Con.Named x => NamedC x | |
196 in | |
197 bind (ctx, b') | |
198 end | |
199 val mfc = Con.mapfoldB {kind = fk, con = fc, bind = bind'} | |
200 | |
201 fun mfe ctx e acc = | |
202 S.bindP (mfe' ctx e acc, fe ctx) | |
203 | |
204 and mfe' ctx (eAll as (e, loc)) = | |
205 case e of | |
206 EPrim _ => S.return2 eAll | |
207 | ERel _ => S.return2 eAll | |
208 | ENamed _ => S.return2 eAll | |
209 | EModProj _ => S.return2 eAll | |
210 | EApp (e1, e2) => | |
211 S.bind2 (mfe ctx e1, | |
212 fn e1' => | |
213 S.map2 (mfe ctx e2, | |
214 fn e2' => | |
215 (EApp (e1', e2'), loc))) | |
216 | EAbs (x, dom, ran, e) => | |
217 S.bind2 (mfc ctx dom, | |
218 fn dom' => | |
219 S.bind2 (mfc ctx ran, | |
220 fn ran' => | |
221 S.map2 (mfe (bind (ctx, RelE (x, dom'))) e, | |
222 fn e' => | |
223 (EAbs (x, dom', ran', e'), loc)))) | |
224 | |
225 | ECApp (e, c) => | |
226 S.bind2 (mfe ctx e, | |
227 fn e' => | |
228 S.map2 (mfc ctx c, | |
229 fn c' => | |
230 (ECApp (e', c'), loc))) | |
231 | ECAbs (x, k, e) => | |
232 S.bind2 (mfk k, | |
233 fn k' => | |
234 S.map2 (mfe (bind (ctx, RelC (x, k))) e, | |
235 fn e' => | |
236 (ECAbs (x, k', e'), loc))) | |
237 | |
238 | ERecord xes => | |
239 S.map2 (ListUtil.mapfold (fn (x, e, t) => | |
240 S.bind2 (mfc ctx x, | |
241 fn x' => | |
242 S.bind2 (mfe ctx e, | |
243 fn e' => | |
244 S.map2 (mfc ctx t, | |
245 fn t' => | |
246 (x', e', t'))))) | |
247 xes, | |
248 fn xes' => | |
249 (ERecord xes', loc)) | |
250 | EField (e, c, {field, rest}) => | |
251 S.bind2 (mfe ctx e, | |
252 fn e' => | |
253 S.bind2 (mfc ctx c, | |
254 fn c' => | |
255 S.bind2 (mfc ctx field, | |
256 fn field' => | |
257 S.map2 (mfc ctx rest, | |
258 fn rest' => | |
259 (EField (e', c', {field = field', rest = rest'}), loc))))) | |
260 in | |
261 mfe | |
262 end | |
263 | |
264 fun mapfold {kind = fk, con = fc, exp = fe} = | |
265 mapfoldB {kind = fk, | |
266 con = fn () => fc, | |
267 exp = fn () => fe, | |
268 bind = fn ((), _) => ()} () | |
269 | |
270 fun exists {kind, con, exp} k = | |
271 case mapfold {kind = fn k => fn () => | |
272 if kind k then | |
273 S.Return () | |
274 else | |
275 S.Continue (k, ()), | |
276 con = fn c => fn () => | |
277 if con c then | |
278 S.Return () | |
279 else | |
280 S.Continue (c, ()), | |
281 exp = fn e => fn () => | |
282 if exp e then | |
283 S.Return () | |
284 else | |
285 S.Continue (e, ())} k () of | |
286 S.Return _ => true | |
287 | S.Continue _ => false | |
288 | |
289 end | |
290 | |
291 structure Sgn = struct | |
292 | |
293 datatype binder = | |
294 RelC of string * Expl.kind | |
295 | NamedC of string * Expl.kind | |
296 | Str of string * Expl.sgn | |
297 | |
298 fun mapfoldB {kind, con, sgn_item, sgn, bind} = | |
299 let | |
300 fun bind' (ctx, b) = | |
301 let | |
302 val b' = case b of | |
303 Con.Rel x => RelC x | |
304 | Con.Named x => NamedC x | |
305 in | |
306 bind (ctx, b') | |
307 end | |
308 val con = Con.mapfoldB {kind = kind, con = con, bind = bind'} | |
309 | |
310 val kind = Kind.mapfold kind | |
311 | |
312 fun sgi ctx si acc = | |
313 S.bindP (sgi' ctx si acc, sgn_item ctx) | |
314 | |
315 and sgi' ctx (si, loc) = | |
316 case si of | |
317 SgiConAbs (x, n, k) => | |
318 S.map2 (kind k, | |
319 fn k' => | |
320 (SgiConAbs (x, n, k'), loc)) | |
321 | SgiCon (x, n, k, c) => | |
322 S.bind2 (kind k, | |
323 fn k' => | |
324 S.map2 (con ctx c, | |
325 fn c' => | |
326 (SgiCon (x, n, k', c'), loc))) | |
327 | SgiVal (x, n, c) => | |
328 S.map2 (con ctx c, | |
329 fn c' => | |
330 (SgiVal (x, n, c'), loc)) | |
331 | SgiStr (x, n, s) => | |
332 S.map2 (sg ctx s, | |
333 fn s' => | |
334 (SgiStr (x, n, s'), loc)) | |
335 | |
336 and sg ctx s acc = | |
337 S.bindP (sg' ctx s acc, sgn ctx) | |
338 | |
339 and sg' ctx (sAll as (s, loc)) = | |
340 case s of | |
341 SgnConst sgis => | |
342 S.map2 (ListUtil.mapfoldB (fn (ctx, si) => | |
343 (case #1 si of | |
344 SgiConAbs (x, _, k) => | |
345 bind (ctx, NamedC (x, k)) | |
346 | SgiCon (x, _, k, _) => | |
347 bind (ctx, NamedC (x, k)) | |
348 | SgiVal _ => ctx | |
349 | SgiStr (x, _, sgn) => | |
350 bind (ctx, Str (x, sgn)), | |
351 sgi ctx si)) ctx sgis, | |
352 fn sgis' => | |
353 (SgnConst sgis', loc)) | |
354 | |
355 | SgnVar _ => S.return2 sAll | |
356 in | |
357 sg | |
358 end | |
359 | |
360 fun mapfold {kind, con, sgn_item, sgn} = | |
361 mapfoldB {kind = kind, | |
362 con = fn () => con, | |
363 sgn_item = fn () => sgn_item, | |
364 sgn = fn () => sgn, | |
365 bind = fn ((), _) => ()} () | |
366 | |
367 fun map {kind, con, sgn_item, sgn} s = | |
368 case mapfold {kind = fn k => fn () => S.Continue (kind k, ()), | |
369 con = fn c => fn () => S.Continue (con c, ()), | |
370 sgn_item = fn si => fn () => S.Continue (sgn_item si, ()), | |
371 sgn = fn s => fn () => S.Continue (sgn s, ())} s () of | |
372 S.Return () => raise Fail "Expl_util.Sgn.map" | |
373 | S.Continue (s, ()) => s | |
374 | |
375 end | |
376 | |
377 end |