Mercurial > urweb
comparison src/cloconv.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 Cloconv :> CLOCONV = struct | |
29 | |
30 structure L = Mono | |
31 structure L' = Flat | |
32 | |
33 structure IS = IntBinarySet | |
34 | |
35 structure U = FlatUtil | |
36 structure E = FlatEnv | |
37 | |
38 open Print.PD | |
39 open Print | |
40 | |
41 val liftExpInExp = | |
42 U.Exp.mapB {typ = fn t => t, | |
43 exp = fn bound => fn e => | |
44 case e of | |
45 L'.ERel xn => | |
46 if xn < bound then | |
47 e | |
48 else | |
49 L'.ERel (xn + 1) | |
50 | _ => e, | |
51 bind = fn (bound, U.Exp.RelE _) => bound + 1 | |
52 | (bound, _) => bound} | |
53 val subExpInExp = | |
54 U.Exp.mapB {typ = fn t => t, | |
55 exp = fn (xn, rep) => fn e => | |
56 case e of | |
57 L'.ERel xn' => | |
58 if xn = xn' then | |
59 #1 rep | |
60 else | |
61 e | |
62 | _ => e, | |
63 bind = fn ((xn, rep), U.Exp.RelE _) => (xn+1, liftExpInExp 0 rep) | |
64 | (ctx, _) => ctx} | |
65 | |
66 | |
67 fun ccTyp (t, loc) = | |
68 case t of | |
69 L.TFun (t1, t2) => (L'.TFun (ccTyp t1, ccTyp t2), loc) | |
70 | L.TRecord xts => (L'.TRecord (map (fn (x, t) => (x, ccTyp t)) xts), loc) | |
71 | L.TNamed n => (L'.TNamed n, loc) | |
72 | |
73 structure Ds :> sig | |
74 type t | |
75 | |
76 val empty : t | |
77 | |
78 val exp : t -> string * int * L'.typ * L'.exp -> t | |
79 val func : t -> string * L'.typ * L'.typ * L'.exp -> t * int | |
80 val decls : t -> L'.decl list | |
81 | |
82 val enter : t -> t | |
83 val used : t * int -> t | |
84 val leave : t -> t | |
85 val listUsed : t -> int list | |
86 end = struct | |
87 | |
88 type t = int * L'.decl list * IS.set | |
89 | |
90 val empty = (0, [], IS.empty) | |
91 | |
92 fun exp (fc, ds, vm) (v as (_, _, _, (_, loc))) = (fc, (L'.DVal v, loc) :: ds, vm) | |
93 | |
94 fun func (fc, ds, vm) (x, dom, ran, e as (_, loc)) = | |
95 ((fc+1, (L'.DFun (fc, x, dom, ran, e), loc) :: ds, vm), fc) | |
96 | |
97 fun decls (_, ds, _) = rev ds | |
98 | |
99 fun enter (fc, ds, vm) = (fc, ds, IS.map (fn n => n + 1) vm) | |
100 fun used ((fc, ds, vm), n) = (fc, ds, IS.add (vm, n)) | |
101 fun leave (fc, ds, vm) = (fc, ds, IS.map (fn n => n - 1) (IS.delete (vm, 0) handle NotFound => vm)) | |
102 | |
103 fun listUsed (_, _, vm) = IS.listItems vm | |
104 | |
105 end | |
106 | |
107 | |
108 fun ccExp env ((e, loc), D) = | |
109 case e of | |
110 L.EPrim p => ((L'.EPrim p, loc), D) | |
111 | L.ERel n => ((L'.ERel n, loc), Ds.used (D, n)) | |
112 | L.ENamed n => ((L'.ENamed n, loc), D) | |
113 | L.EApp (e1, e2) => | |
114 let | |
115 val (e1, D) = ccExp env (e1, D) | |
116 val (e2, D) = ccExp env (e2, D) | |
117 in | |
118 ((L'.ELet ([("closure", e1), | |
119 ("arg", liftExpInExp 0 e2), | |
120 ("code", (L'.EField ((L'.ERel 1, loc), "func"), loc)), | |
121 ("env", (L'.EField ((L'.ERel 2, loc), "env"), loc))], | |
122 (L'.EApp ((L'.ERel 1, loc), | |
123 (L'.ERecord [("env", (L'.ERel 0, loc)), | |
124 ("arg", (L'.ERel 2, loc))], loc)), loc)), loc), D) | |
125 end | |
126 | L.EAbs (x, dom, ran, e) => | |
127 let | |
128 val dom = ccTyp dom | |
129 val ran = ccTyp ran | |
130 val (e, D) = ccExp (E.pushERel env x dom) (e, Ds.enter D) | |
131 val ns = Ds.listUsed D | |
132 val ns = List.filter (fn n => n <> 0) ns | |
133 val D = Ds.leave D | |
134 | |
135 (*val () = Print.preface ("Before", FlatPrint.p_exp FlatEnv.basis e) | |
136 val () = List.app (fn (x, t) => preface ("Bound", box [string x, | |
137 space, | |
138 string ":", | |
139 space, | |
140 FlatPrint.p_typ env t])) | |
141 (E.listERels env) | |
142 val () = List.app (fn n => preface ("Free", FlatPrint.p_exp (E.pushERel env x dom) | |
143 (L'.ERel n, loc))) ns*) | |
144 val body = foldl (fn (n, e) => | |
145 subExpInExp (n, (L'.EField ((L'.ERel 1, loc), "fv" ^ Int.toString n), loc)) e) | |
146 e ns | |
147 (*val () = Print.preface (" After", FlatPrint.p_exp FlatEnv.basis body)*) | |
148 val body = (L'.ELet ([("env", (L'.EField ((L'.ERel 0, loc), "env"), loc)), | |
149 ("arg", (L'.EField ((L'.ERel 1, loc), "arg"), loc))], | |
150 body), loc) | |
151 | |
152 val envT = (L'.TRecord (map (fn n => ("fv" ^ Int.toString n, #2 (E.lookupERel env (n-1)))) ns), loc) | |
153 val (D, fi) = Ds.func D (x, (L'.TRecord [("env", envT), ("arg", dom)], loc), ran, body) | |
154 in | |
155 ((L'.ERecord [("code", (L'.ECode fi, loc)), | |
156 ("env", (L'.ERecord (map (fn n => ("fv" ^ Int.toString n, | |
157 (L'.ERel (n-1), loc))) ns), loc))], loc), D) | |
158 end | |
159 | |
160 | L.ERecord xes => | |
161 let | |
162 val (xes, D) = ListUtil.foldlMap (fn ((x, e), D) => | |
163 let | |
164 val (e, D) = ccExp env (e, D) | |
165 in | |
166 ((x, e), D) | |
167 end) D xes | |
168 in | |
169 ((L'.ERecord xes, loc), D) | |
170 end | |
171 | L.EField (e1, x) => | |
172 let | |
173 val (e1, D) = ccExp env (e1, D) | |
174 in | |
175 ((L'.EField (e1, x), loc), D) | |
176 end | |
177 | |
178 fun ccDecl ((d, loc), D) = | |
179 case d of | |
180 L.DVal (x, n, t, e) => | |
181 let | |
182 val t = ccTyp t | |
183 val (e, D) = ccExp E.basis (e, D) | |
184 in | |
185 Ds.exp D (x, n, t, e) | |
186 end | |
187 | |
188 fun cloconv ds = | |
189 let | |
190 val D = foldl ccDecl Ds.empty ds | |
191 in | |
192 Ds.decls D | |
193 end | |
194 | |
195 end |