comparison src/unnest.sml @ 448:85819353a84f

First Unnest tests working
author Adam Chlipala <adamc@hcoop.net>
date Sat, 01 Nov 2008 15:58:55 -0400
parents
children 07f6576aeb0a
comparison
equal deleted inserted replaced
447:b77863cd0be2 448:85819353a84f
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 (* Remove nested function definitions *)
29
30 structure Unnest :> UNNEST = struct
31
32 open Elab
33
34 structure E = ElabEnv
35 structure U = ElabUtil
36
37 structure IS = IntBinarySet
38
39 val fvsCon = U.Con.foldB {kind = fn (_, st) => st,
40 con = fn (cb, c, cvs) =>
41 case c of
42 CRel n =>
43 if n >= cb then
44 IS.add (cvs, n - cb)
45 else
46 cvs
47 | _ => cvs,
48 bind = fn (cb, b) =>
49 case b of
50 U.Con.Rel _ => cb + 1
51 | _ => cb}
52 0 IS.empty
53
54 fun fvsExp nr = U.Exp.foldB {kind = fn (_, st) => st,
55 con = fn ((cb, eb), c, st as (cvs, evs)) =>
56 case c of
57 CRel n =>
58 if n >= cb then
59 (IS.add (cvs, n - cb), evs)
60 else
61 st
62 | _ => st,
63 exp = fn ((cb, eb), e, st as (cvs, evs)) =>
64 case e of
65 ERel n =>
66 if n >= eb then
67 (cvs, IS.add (evs, n - eb))
68 else
69 st
70 | _ => st,
71 bind = fn (ctx as (cb, eb), b) =>
72 case b of
73 U.Exp.RelC _ => (cb + 1, eb)
74 | U.Exp.RelE _ => (cb, eb + 1)
75 | _ => ctx}
76 (0, nr) (IS.empty, IS.empty)
77
78 fun positionOf (x : int) ls =
79 let
80 fun po n ls =
81 case ls of
82 [] => raise Fail "Unnest.positionOf"
83 | x' :: ls' =>
84 if x' = x then
85 n
86 else
87 po (n + 1) ls'
88 in
89 po 0 ls
90 handle Fail _ => raise Fail ("Unnset.positionOf("
91 ^ Int.toString x
92 ^ ", "
93 ^ String.concatWith ";" (map Int.toString ls)
94 ^ ")")
95 end
96
97 fun squishCon cfv =
98 U.Con.mapB {kind = fn k => k,
99 con = fn cb => fn c =>
100 case c of
101 CRel n =>
102 if n >= cb then
103 CRel (positionOf (n - cb) cfv + cb)
104 else
105 c
106 | _ => c,
107 bind = fn (cb, b) =>
108 case b of
109 U.Con.Rel _ => cb + 1
110 | _ => cb}
111 0
112
113 fun squishExp (nr, cfv, efv) =
114 U.Exp.mapB {kind = fn k => k,
115 con = fn (cb, eb) => fn c =>
116 case c of
117 CRel n =>
118 if n >= cb then
119 CRel (positionOf (n - cb) cfv + cb)
120 else
121 c
122 | _ => c,
123 exp = fn (cb, eb) => fn e =>
124 case e of
125 ERel n =>
126 if n >= eb then
127 ERel (positionOf (n - eb) efv + eb)
128 else
129 e
130 | _ => e,
131 bind = fn (ctx as (cb, eb), b) =>
132 case b of
133 U.Exp.RelC _ => (cb + 1, eb)
134 | U.Exp.RelE _ => (cb, eb + 1)
135 | _ => ctx}
136 (0, nr)
137
138 type state = {
139 maxName : int,
140 decls : decl list
141 }
142
143 fun kind (k, st) = (k, st)
144
145 fun exp ((ks, ts), e, st : state) =
146 case e of
147 ELet (eds, e) =>
148 let
149 val doSubst = foldl (fn (p, e) => E.subExpInExp p e)
150
151 val (eds, (maxName, ds, subs)) =
152 ListUtil.foldlMapConcat
153 (fn (ed, (maxName, ds, subs)) =>
154 case #1 ed of
155 EDVal _ => ([ed], (maxName, ds, map (fn (n, e) => (n + 1, E.liftExpInExp 0 e)) subs))
156 | EDValRec vis =>
157 let
158 val loc = #2 ed
159
160 val nr = length vis
161 val (cfv, efv) = foldl (fn ((_, t, e), (cfv, efv)) =>
162 let
163 val (cfv', efv') = fvsExp nr e
164 (*val () = Print.prefaces "fvsExp"
165 [("e", ElabPrint.p_exp E.empty e),
166 ("cfv", Print.PD.string
167 (Int.toString (IS.numItems cfv'))),
168 ("efv", Print.PD.string
169 (Int.toString (IS.numItems efv')))]*)
170 val cfv'' = fvsCon t
171 in
172 (IS.union (cfv, IS.union (cfv', cfv'')),
173 IS.union (efv, efv'))
174 end)
175 (IS.empty, IS.empty) vis
176
177 (*val () = print ("A: " ^ Int.toString (length ts) ^ ", " ^ Int.toString (length ks) ^ "\n")*)
178 val cfv = IS.foldl (fn (x, cfv) =>
179 let
180 (*val () = print (Int.toString x ^ "\n")*)
181 val (_, t) = List.nth (ts, x)
182 in
183 IS.union (cfv, fvsCon t)
184 end)
185 cfv efv
186 (*val () = print "B\n"*)
187
188 val (vis, maxName) =
189 ListUtil.foldlMap (fn ((x, t, e), maxName) =>
190 ((x, maxName, t, e),
191 maxName + 1))
192 maxName vis
193
194 fun apply e =
195 let
196 val e = IS.foldl (fn (x, e) =>
197 (ECApp (e, (CRel x, loc)), loc))
198 e cfv
199 in
200 IS.foldl (fn (x, e) =>
201 (EApp (e, (ERel x, loc)), loc))
202 e efv
203 end
204
205 val subs = map (fn (n, e) => (n + nr, E.liftExpInExp nr e)) subs
206
207 val subs' = ListUtil.mapi (fn (i, (_, n, _, _)) =>
208 let
209 val e = apply (ENamed n, loc)
210 in
211 (0, E.liftExpInExp (nr - i - 1) e)
212 end)
213 vis
214 val subs' = rev subs'
215
216 val cfv = IS.listItems cfv
217 val efv = IS.listItems efv
218 val efn = length efv
219
220 (*val subsInner = subs
221 @ map (fn (i, e) =>
222 (i + efn,
223 E.liftExpInExp efn e)) subs'*)
224
225 val subs = subs @ subs'
226
227 val vis = map (fn (x, n, t, e) =>
228 let
229 (*val () = Print.prefaces "preSubst"
230 [("e", ElabPrint.p_exp E.empty e)]*)
231 val e = doSubst e subs(*Inner*)
232
233 (*val () = Print.prefaces "squishCon"
234 [("t", ElabPrint.p_con E.empty t)]*)
235 val t = squishCon cfv t
236 (*val () = Print.prefaces "squishExp"
237 [("e", ElabPrint.p_exp E.empty e)]*)
238 val e = squishExp (nr, cfv, efv) e
239
240 val (e, t) = foldr (fn (ex, (e, t)) =>
241 let
242 val (name, t') = List.nth (ts, ex)
243 in
244 ((EAbs (name,
245 t',
246 t,
247 e), loc),
248 (TFun (t',
249 t), loc))
250 end)
251 (e, t) efv
252
253 val (e, t) = foldr (fn (cx, (e, t)) =>
254 let
255 val (name, k) = List.nth (ks, cx)
256 in
257 ((ECAbs (Explicit,
258 name,
259 k,
260 e), loc),
261 (TCFun (Explicit,
262 name,
263 k,
264 t), loc))
265 end)
266 (e, t) cfv
267 in
268 (x, n, t, e)
269 end)
270 vis
271
272 val d = (DValRec vis, #2 ed)
273 in
274 ([], (maxName, d :: ds, subs))
275 end)
276 (#maxName st, #decls st, []) eds
277 in
278 (ELet (eds, doSubst e subs),
279 {maxName = maxName,
280 decls = ds})
281 end
282
283 | _ => (e, st)
284
285 fun default (ctx, d, st) = (d, st)
286
287 fun bind ((ks, ts), b) =
288 case b of
289 U.Decl.RelC p => (p :: ks, map (fn (name, t) => (name, E.liftConInCon 0 t)) ts)
290 | U.Decl.RelE p => (ks, p :: ts)
291 | _ => (ks, ts)
292
293 val unnestDecl = U.Decl.foldMapB {kind = kind,
294 con = default,
295 exp = exp,
296 sgn_item = default,
297 sgn = default,
298 str = default,
299 decl = default,
300 bind = bind}
301 ([], [])
302
303 fun unnest file =
304 let
305 fun doDecl (all as (d, loc), st : state) =
306 let
307 fun default () = ([all], st)
308 fun explore () =
309 let
310 val (d, st) = unnestDecl st all
311 in
312 (rev (d :: #decls st),
313 {maxName = #maxName st,
314 decls = []})
315 end
316 in
317 case d of
318 DCon _ => default ()
319 | DDatatype _ => default ()
320 | DDatatypeImp _ => default ()
321 | DVal _ => explore ()
322 | DValRec _ => explore ()
323 | DSgn _ => default ()
324 | DStr (x, n, sgn, str) =>
325 let
326 val (str, st) = doStr (str, st)
327 in
328 ([(DStr (x, n, sgn, str), loc)], st)
329 end
330 | DFfiStr _ => default ()
331 | DConstraint _ => default ()
332 | DExport _ => default ()
333 | DTable _ => default ()
334 | DSequence _ => default ()
335 | DClass _ => default ()
336 | DDatabase _ => default ()
337 end
338
339 and doStr (all as (str, loc), st) =
340 let
341 fun default () = (all, st)
342 in
343 case str of
344 StrConst ds =>
345 let
346 val (ds, st) = ListUtil.foldlMapConcat doDecl st ds
347 in
348 ((StrConst ds, loc), st)
349 end
350 | StrVar _ => default ()
351 | StrProj _ => default ()
352 | StrFun (x, n, dom, ran, str) =>
353 let
354 val (str, st) = doStr (str, st)
355 in
356 ((StrFun (x, n, dom, ran, str), loc), st)
357 end
358 | StrApp _ => default ()
359 | StrError => raise Fail "Unnest: StrError"
360 end
361
362 val (ds, _) = ListUtil.foldlMapConcat doDecl
363 {maxName = U.File.maxName file + 1,
364 decls = []} file
365 in
366 ds
367 end
368
369 end