comparison src/specialize.sml @ 193:8a70e2919e86

Specialization of single-parameter datatypes
author Adam Chlipala <adamc@hcoop.net>
date Fri, 08 Aug 2008 17:55:51 -0400
parents
children df5fd8f6913a
comparison
equal deleted inserted replaced
192:9bbf4d383381 193:8a70e2919e86
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 (* Simplify a Core program algebraically *)
29
30 structure Specialize :> SPECIALIZE = struct
31
32 open Core
33
34 structure E = CoreEnv
35 structure U = CoreUtil
36
37 val liftConInCon = E.liftConInCon
38 val subConInCon = E.subConInCon
39
40 structure CK = struct
41 type ord_key = con list
42 val compare = Order.joinL U.Con.compare
43 end
44
45 structure CM = BinaryMapFn(CK)
46 structure IM = IntBinaryMap
47
48 type datatyp' = {
49 name : int,
50 constructors : int IM.map
51 }
52
53 type datatyp = {
54 name : string,
55 params : int,
56 constructors : (string * int * con option) list,
57 specializations : datatyp' CM.map
58 }
59
60 type state = {
61 count : int,
62 datatypes : datatyp IM.map,
63 constructors : int IM.map,
64 decls : decl list
65 }
66
67 fun kind (k, st) = (k, st)
68
69 val isOpen = U.Con.exists {kind = fn _ => false,
70 con = fn c =>
71 case c of
72 CRel _ => true
73 | _ => false}
74
75 fun considerSpecialization (st : state, n, args, dt : datatyp) =
76 case CM.find (#specializations dt, args) of
77 SOME dt' => (#name dt', #constructors dt', st)
78 | NONE =>
79 let
80 val n' = #count st
81
82 fun sub t = ListUtil.foldli (fn (i, arg, t) =>
83 subConInCon (i, arg) t) t args
84
85 val (cons, (count, cmap)) =
86 ListUtil.foldlMap (fn ((x, n, to), (count, cmap)) =>
87 let
88 val to = Option.map sub to
89 in
90 ((x, count, to),
91 (count + 1,
92 IM.insert (cmap, n, count)))
93 end) (n' + 1, IM.empty) (#constructors dt)
94
95 val st = {count = count,
96 datatypes = IM.insert (#datatypes st, n,
97 {name = #name dt,
98 params = #params dt,
99 constructors = #constructors dt,
100 specializations = CM.insert (#specializations dt,
101 args,
102 {name = n',
103 constructors = cmap})}),
104 constructors = #constructors st,
105 decls = #decls st}
106
107 val (cons, st) = ListUtil.foldlMap (fn ((x, n, NONE), st) => ((x, n, NONE), st)
108 | ((x, n, SOME t), st) =>
109 let
110 val (t, st) = specCon st t
111 in
112 ((x, n, SOME t), st)
113 end) st cons
114
115 val d = (DDatatype (#name dt ^ "_s",
116 n',
117 [],
118 cons), #2 (List.hd args))
119 in
120 (n', cmap, {count = #count st,
121 datatypes = #datatypes st,
122 constructors = #constructors st,
123 decls = d :: #decls st})
124 end
125
126 and con (c, st : state) =
127 let
128 fun findApp (c, args) =
129 case c of
130 CApp ((c', _), arg) => findApp (c', arg :: args)
131 | CNamed n => SOME (n, args)
132 | _ => NONE
133 in
134 case findApp (c, []) of
135 SOME (n, args as (_ :: _)) =>
136 if List.exists isOpen args then
137 (c, st)
138 else
139 (case IM.find (#datatypes st, n) of
140 NONE => (c, st)
141 | SOME dt =>
142 if length args <> #params dt then
143 (c, st)
144 else
145 let
146 val (n, _, st) = considerSpecialization (st, n, args, dt)
147 in
148 (CNamed n, st)
149 end)
150 | _ => (c, st)
151 end
152
153 and specCon st = U.Con.foldMap {kind = kind, con = con} st
154
155 fun pat (p, st) =
156 case #1 p of
157 PWild => (p, st)
158 | PVar _ => (p, st)
159 | PPrim _ => (p, st)
160 | PCon (dk, PConVar pn, args as (_ :: _), po) =>
161 let
162 val (po, st) =
163 case po of
164 NONE => (NONE, st)
165 | SOME p =>
166 let
167 val (p, st) = pat (p, st)
168 in
169 (SOME p, st)
170 end
171 val p = (PCon (dk, PConVar pn, args, po), #2 p)
172 in
173 if List.exists isOpen args then
174 (p, st)
175 else
176 case IM.find (#constructors st, pn) of
177 NONE => (p, st)
178 | SOME n =>
179 case IM.find (#datatypes st, n) of
180 NONE => (p, st)
181 | SOME dt =>
182 let
183 val (n, cmap, st) = considerSpecialization (st, n, args, dt)
184 in
185 case IM.find (cmap, pn) of
186 NONE => raise Fail "Specialize: Missing datatype constructor (pat)"
187 | SOME pn' => ((PCon (dk, PConVar pn', [], po), #2 p), st)
188 end
189 end
190 | PCon _ => (p, st)
191 | PRecord xps =>
192 let
193 val (xps, st) = ListUtil.foldlMap (fn ((x, p, t), st) =>
194 let
195 val (p, st) = pat (p, st)
196 in
197 ((x, p, t), st)
198 end)
199 st xps
200 in
201 ((PRecord xps, #2 p), st)
202 end
203
204 fun exp (e, st) =
205 case e of
206 ECon (dk, PConVar pn, args as (_ :: _), eo) =>
207 if List.exists isOpen args then
208 (e, st)
209 else
210 (case IM.find (#constructors st, pn) of
211 NONE => (e, st)
212 | SOME n =>
213 case IM.find (#datatypes st, n) of
214 NONE => (e, st)
215 | SOME dt =>
216 let
217 val (n, cmap, st) = considerSpecialization (st, n, args, dt)
218 in
219 case IM.find (cmap, pn) of
220 NONE => raise Fail "Specialize: Missing datatype constructor"
221 | SOME pn' => (ECon (dk, PConVar pn', [], eo), st)
222 end)
223 | ECase (e, pes, r) =>
224 let
225 val (pes, st) = ListUtil.foldlMap (fn ((p, e), st) =>
226 let
227 val (p, st) = pat (p, st)
228 in
229 ((p, e), st)
230 end) st pes
231 in
232 (ECase (e, pes, r), st)
233 end
234 | _ => (e, st)
235
236 fun decl (d, st) = (d, st)
237
238 val specDecl = U.Decl.foldMap {kind = kind, con = con, exp = exp, decl = decl}
239
240 fun specialize file =
241 let
242 fun doDecl (all as (d, _), st : state) =
243 case d of
244 DDatatype (x, n, xs, xnts) =>
245 ([all], {count = #count st,
246 datatypes = IM.insert (#datatypes st, n,
247 {name = x,
248 params = length xs,
249 constructors = xnts,
250 specializations = CM.empty}),
251 constructors = foldl (fn ((_, n', _), constructors) =>
252 IM.insert (constructors, n', n))
253 (#constructors st) xnts,
254 decls = []})
255 | _ =>
256 let
257 val (d, st) = specDecl st all
258 in
259 (rev (d :: #decls st),
260 {count = #count st,
261 datatypes = #datatypes st,
262 constructors = #constructors st,
263 decls = []})
264 end
265
266 val (ds, _) = ListUtil.foldlMapConcat doDecl
267 {count = U.File.maxName file + 1,
268 datatypes = IM.empty,
269 constructors = IM.empty,
270 decls = []} file
271 in
272 ds
273 end
274
275
276 end