Mercurial > urweb
comparison src/defunc.sml @ 484:685b41e85634
Defunctionalization gets CommentBlog working
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sun, 09 Nov 2008 16:54:42 -0500 |
parents | |
children | 3ce20b0b6914 |
comparison
equal
deleted
inserted
replaced
483:a0f47540d8ad | 484:685b41e85634 |
---|---|
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 Defunc :> DEFUNC = struct | |
29 | |
30 open Core | |
31 | |
32 structure E = CoreEnv | |
33 structure U = CoreUtil | |
34 | |
35 structure IS = IntBinarySet | |
36 | |
37 val functionInside = U.Con.exists {kind = fn _ => false, | |
38 con = fn TFun _ => true | |
39 | CFfi ("Basis", "transaction") => true | |
40 | _ => false} | |
41 | |
42 val freeVars = U.Exp.foldB {kind = fn (_, xs) => xs, | |
43 con = fn (_, _, xs) => xs, | |
44 exp = fn (bound, e, xs) => | |
45 case e of | |
46 ERel x => | |
47 if x >= bound then | |
48 IS.add (xs, x - bound) | |
49 else | |
50 xs | |
51 | _ => xs, | |
52 bind = fn (bound, b) => | |
53 case b of | |
54 U.Exp.RelE _ => bound + 1 | |
55 | _ => bound} | |
56 0 IS.empty | |
57 | |
58 fun positionOf (v : int, ls) = | |
59 let | |
60 fun pof (pos, ls) = | |
61 case ls of | |
62 [] => raise Fail "Defunc.positionOf" | |
63 | v' :: ls' => | |
64 if v = v' then | |
65 pos | |
66 else | |
67 pof (pos + 1, ls') | |
68 in | |
69 pof (0, ls) | |
70 end | |
71 | |
72 fun squish fvs = | |
73 U.Exp.mapB {kind = fn k => k, | |
74 con = fn _ => fn c => c, | |
75 exp = fn bound => fn e => | |
76 case e of | |
77 ERel x => | |
78 if x >= bound then | |
79 ERel (positionOf (x - bound, fvs) + bound) | |
80 else | |
81 e | |
82 | _ => e, | |
83 bind = fn (bound, b) => | |
84 case b of | |
85 U.Exp.RelE _ => bound + 1 | |
86 | _ => bound} | |
87 0 | |
88 | |
89 fun default (_, x, st) = (x, st) | |
90 | |
91 datatype 'a search = | |
92 Yes | |
93 | No | |
94 | Maybe of 'a | |
95 | |
96 structure EK = struct | |
97 type ord_key = exp | |
98 val compare = U.Exp.compare | |
99 end | |
100 | |
101 structure EM = BinaryMapFn(EK) | |
102 | |
103 type state = { | |
104 maxName : int, | |
105 funcs : int EM.map, | |
106 vis : (string * int * con * exp * string) list | |
107 } | |
108 | |
109 fun exp (env, e, st) = | |
110 case e of | |
111 ERecord xes => | |
112 let | |
113 val (xes, st) = | |
114 ListUtil.foldlMap | |
115 (fn (tup as (fnam as (CName x, loc), e, xt), st) => | |
116 if x <> "Link" andalso x <> "Action" then | |
117 (tup, st) | |
118 else | |
119 let | |
120 fun needsAttention (e, _) = | |
121 case e of | |
122 ENamed f => Maybe (#2 (E.lookupENamed env f)) | |
123 | EApp (f, _) => | |
124 (case needsAttention f of | |
125 No => No | |
126 | Yes => Yes | |
127 | Maybe t => | |
128 case t of | |
129 (TFun (dom, _), _) => | |
130 if functionInside dom then | |
131 Yes | |
132 else | |
133 No | |
134 | _ => No) | |
135 | _ => No | |
136 | |
137 fun headSymbol (e, _) = | |
138 case e of | |
139 ENamed f => f | |
140 | EApp (e, _) => headSymbol e | |
141 | _ => raise Fail "Defunc: headSymbol" | |
142 | |
143 fun rtype (e, _) = | |
144 case e of | |
145 ENamed f => #2 (E.lookupENamed env f) | |
146 | EApp (f, _) => | |
147 (case rtype f of | |
148 (TFun (_, ran), _) => ran | |
149 | _ => raise Fail "Defunc: rtype [1]") | |
150 | _ => raise Fail "Defunc: rtype [2]" | |
151 in | |
152 (*Print.prefaces "Found one!" | |
153 [("e", CorePrint.p_exp env e)];*) | |
154 case needsAttention e of | |
155 Yes => | |
156 let | |
157 (*val () = print "Yes\n"*) | |
158 val f = headSymbol e | |
159 | |
160 val fvs = IS.listItems (freeVars e) | |
161 | |
162 val e = squish fvs e | |
163 val (e, t) = foldl (fn (n, (e, t)) => | |
164 let | |
165 val (x, xt) = E.lookupERel env n | |
166 in | |
167 ((EAbs (x, xt, t, e), loc), | |
168 (TFun (xt, t), loc)) | |
169 end) | |
170 (e, rtype e) fvs | |
171 | |
172 val (f', st) = | |
173 case EM.find (#funcs st, e) of | |
174 SOME f' => (f', st) | |
175 | NONE => | |
176 let | |
177 val (fx, _, _, tag) = E.lookupENamed env f | |
178 val f' = #maxName st | |
179 | |
180 val vi = (fx, f', t, e, tag) | |
181 in | |
182 (f', {maxName = f' + 1, | |
183 funcs = EM.insert (#funcs st, e, f'), | |
184 vis = vi :: #vis st}) | |
185 end | |
186 | |
187 val e = foldr (fn (n, e) => | |
188 (EApp (e, (ERel n, loc)), loc)) | |
189 (ENamed f', loc) fvs | |
190 in | |
191 (*app (fn n => Print.prefaces | |
192 "Free" | |
193 [("n", CorePrint.p_exp env (ERel n, ErrorMsg.dummySpan))]) | |
194 fvs; | |
195 Print.prefaces "Squished" | |
196 [("e", CorePrint.p_exp CoreEnv.empty e)];*) | |
197 | |
198 ((fnam, e, xt), st) | |
199 end | |
200 | _ => (tup, st) | |
201 end | |
202 | (tup, st) => (tup, st)) | |
203 st xes | |
204 in | |
205 (ERecord xes, st) | |
206 end | |
207 | _ => (e, st) | |
208 | |
209 fun bind (env, b) = | |
210 case b of | |
211 U.Decl.RelC (x, k) => E.pushCRel env x k | |
212 | U.Decl.NamedC (x, n, k, co) => E.pushCNamed env x n k co | |
213 | U.Decl.RelE (x, t) => E.pushERel env x t | |
214 | U.Decl.NamedE (x, n, t, eo, s) => E.pushENamed env x n t eo s | |
215 | |
216 fun doDecl env = U.Decl.foldMapB {kind = fn x => x, | |
217 con = default, | |
218 exp = exp, | |
219 decl = default, | |
220 bind = bind} | |
221 env | |
222 | |
223 fun defunc file = | |
224 let | |
225 fun doDecl' (d, (env, st)) = | |
226 let | |
227 val env = E.declBinds env d | |
228 | |
229 val (d, st) = doDecl env st d | |
230 | |
231 val ds = | |
232 case #vis st of | |
233 [] => [d] | |
234 | vis => | |
235 case d of | |
236 (DValRec vis', loc) => [(DValRec (vis' @ vis), loc)] | |
237 | _ => [(DValRec vis, #2 d), d] | |
238 in | |
239 (ds, | |
240 (env, | |
241 {maxName = #maxName st, | |
242 funcs = #funcs st, | |
243 vis = []})) | |
244 end | |
245 | |
246 val (file, _) = ListUtil.foldlMapConcat doDecl' | |
247 (E.empty, | |
248 {maxName = U.File.maxName file + 1, | |
249 funcs = EM.empty, | |
250 vis = []}) | |
251 file | |
252 in | |
253 file | |
254 end | |
255 | |
256 end |