annotate src/specialize.sml @ 443:bd9ee9aeca2f

Especialize
author Adam Chlipala <adamc@hcoop.net>
date Thu, 30 Oct 2008 16:58:54 -0400
parents e21d0dddda09
children d20d6afc1206
rev   line source
adamc@193 1 (* Copyright (c) 2008, Adam Chlipala
adamc@193 2 * All rights reserved.
adamc@193 3 *
adamc@193 4 * Redistribution and use in source and binary forms, with or without
adamc@193 5 * modification, are permitted provided that the following conditions are met:
adamc@193 6 *
adamc@193 7 * - Redistributions of source code must retain the above copyright notice,
adamc@193 8 * this list of conditions and the following disclaimer.
adamc@193 9 * - Redistributions in binary form must reproduce the above copyright notice,
adamc@193 10 * this list of conditions and the following disclaimer in the documentation
adamc@193 11 * and/or other materials provided with the distribution.
adamc@193 12 * - The names of contributors may not be used to endorse or promote products
adamc@193 13 * derived from this software without specific prior written permission.
adamc@193 14 *
adamc@193 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
adamc@193 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
adamc@193 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
adamc@193 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
adamc@193 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
adamc@193 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
adamc@193 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
adamc@193 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
adamc@193 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
adamc@193 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
adamc@193 25 * POSSIBILITY OF SUCH DAMAGE.
adamc@193 26 *)
adamc@193 27
adamc@315 28 (* Simplify a Core program by repeating polymorphic definitions of datatypes *)
adamc@193 29
adamc@193 30 structure Specialize :> SPECIALIZE = struct
adamc@193 31
adamc@193 32 open Core
adamc@193 33
adamc@193 34 structure E = CoreEnv
adamc@193 35 structure U = CoreUtil
adamc@193 36
adamc@193 37 val liftConInCon = E.liftConInCon
adamc@193 38 val subConInCon = E.subConInCon
adamc@193 39
adamc@193 40 structure CK = struct
adamc@193 41 type ord_key = con list
adamc@193 42 val compare = Order.joinL U.Con.compare
adamc@193 43 end
adamc@193 44
adamc@193 45 structure CM = BinaryMapFn(CK)
adamc@193 46 structure IM = IntBinaryMap
adamc@193 47
adamc@193 48 type datatyp' = {
adamc@193 49 name : int,
adamc@193 50 constructors : int IM.map
adamc@193 51 }
adamc@193 52
adamc@193 53 type datatyp = {
adamc@193 54 name : string,
adamc@193 55 params : int,
adamc@193 56 constructors : (string * int * con option) list,
adamc@193 57 specializations : datatyp' CM.map
adamc@193 58 }
adamc@193 59
adamc@193 60 type state = {
adamc@193 61 count : int,
adamc@193 62 datatypes : datatyp IM.map,
adamc@193 63 constructors : int IM.map,
adamc@315 64 decls : decl list
adamc@193 65 }
adamc@193 66
adamc@193 67 fun kind (k, st) = (k, st)
adamc@193 68
adamc@193 69 val isOpen = U.Con.exists {kind = fn _ => false,
adamc@193 70 con = fn c =>
adamc@193 71 case c of
adamc@193 72 CRel _ => true
adamc@193 73 | _ => false}
adamc@193 74
adamc@193 75 fun considerSpecialization (st : state, n, args, dt : datatyp) =
adamc@193 76 case CM.find (#specializations dt, args) of
adamc@193 77 SOME dt' => (#name dt', #constructors dt', st)
adamc@193 78 | NONE =>
adamc@193 79 let
adamc@194 80 (*val () = Print.prefaces "Args" [("args", Print.p_list (CorePrint.p_con CoreEnv.empty) args)]*)
adamc@194 81
adamc@193 82 val n' = #count st
adamc@193 83
adamc@194 84 val nxs = length args - 1
adamc@193 85 fun sub t = ListUtil.foldli (fn (i, arg, t) =>
adamc@194 86 subConInCon (nxs - i, arg) t) t args
adamc@193 87
adamc@193 88 val (cons, (count, cmap)) =
adamc@193 89 ListUtil.foldlMap (fn ((x, n, to), (count, cmap)) =>
adamc@193 90 let
adamc@193 91 val to = Option.map sub to
adamc@193 92 in
adamc@193 93 ((x, count, to),
adamc@193 94 (count + 1,
adamc@193 95 IM.insert (cmap, n, count)))
adamc@193 96 end) (n' + 1, IM.empty) (#constructors dt)
adamc@193 97
adamc@193 98 val st = {count = count,
adamc@193 99 datatypes = IM.insert (#datatypes st, n,
adamc@193 100 {name = #name dt,
adamc@193 101 params = #params dt,
adamc@193 102 constructors = #constructors dt,
adamc@193 103 specializations = CM.insert (#specializations dt,
adamc@193 104 args,
adamc@193 105 {name = n',
adamc@193 106 constructors = cmap})}),
adamc@193 107 constructors = #constructors st,
adamc@193 108 decls = #decls st}
adamc@193 109
adamc@193 110 val (cons, st) = ListUtil.foldlMap (fn ((x, n, NONE), st) => ((x, n, NONE), st)
adamc@193 111 | ((x, n, SOME t), st) =>
adamc@193 112 let
adamc@193 113 val (t, st) = specCon st t
adamc@193 114 in
adamc@193 115 ((x, n, SOME t), st)
adamc@193 116 end) st cons
adamc@193 117
adamc@193 118 val d = (DDatatype (#name dt ^ "_s",
adamc@193 119 n',
adamc@193 120 [],
adamc@193 121 cons), #2 (List.hd args))
adamc@193 122 in
adamc@193 123 (n', cmap, {count = #count st,
adamc@193 124 datatypes = #datatypes st,
adamc@193 125 constructors = #constructors st,
adamc@193 126 decls = d :: #decls st})
adamc@193 127 end
adamc@193 128
adamc@193 129 and con (c, st : state) =
adamc@193 130 let
adamc@193 131 fun findApp (c, args) =
adamc@193 132 case c of
adamc@193 133 CApp ((c', _), arg) => findApp (c', arg :: args)
adamc@193 134 | CNamed n => SOME (n, args)
adamc@193 135 | _ => NONE
adamc@193 136 in
adamc@193 137 case findApp (c, []) of
adamc@193 138 SOME (n, args as (_ :: _)) =>
adamc@193 139 if List.exists isOpen args then
adamc@193 140 (c, st)
adamc@193 141 else
adamc@193 142 (case IM.find (#datatypes st, n) of
adamc@193 143 NONE => (c, st)
adamc@193 144 | SOME dt =>
adamc@193 145 if length args <> #params dt then
adamc@193 146 (c, st)
adamc@193 147 else
adamc@193 148 let
adamc@193 149 val (n, _, st) = considerSpecialization (st, n, args, dt)
adamc@193 150 in
adamc@193 151 (CNamed n, st)
adamc@193 152 end)
adamc@193 153 | _ => (c, st)
adamc@193 154 end
adamc@193 155
adamc@193 156 and specCon st = U.Con.foldMap {kind = kind, con = con} st
adamc@193 157
adamc@193 158 fun pat (p, st) =
adamc@193 159 case #1 p of
adamc@193 160 PWild => (p, st)
adamc@193 161 | PVar _ => (p, st)
adamc@193 162 | PPrim _ => (p, st)
adamc@193 163 | PCon (dk, PConVar pn, args as (_ :: _), po) =>
adamc@193 164 let
adamc@193 165 val (po, st) =
adamc@193 166 case po of
adamc@193 167 NONE => (NONE, st)
adamc@193 168 | SOME p =>
adamc@193 169 let
adamc@193 170 val (p, st) = pat (p, st)
adamc@193 171 in
adamc@193 172 (SOME p, st)
adamc@193 173 end
adamc@193 174 val p = (PCon (dk, PConVar pn, args, po), #2 p)
adamc@193 175 in
adamc@193 176 if List.exists isOpen args then
adamc@193 177 (p, st)
adamc@193 178 else
adamc@193 179 case IM.find (#constructors st, pn) of
adamc@193 180 NONE => (p, st)
adamc@193 181 | SOME n =>
adamc@193 182 case IM.find (#datatypes st, n) of
adamc@193 183 NONE => (p, st)
adamc@193 184 | SOME dt =>
adamc@193 185 let
adamc@193 186 val (n, cmap, st) = considerSpecialization (st, n, args, dt)
adamc@193 187 in
adamc@193 188 case IM.find (cmap, pn) of
adamc@193 189 NONE => raise Fail "Specialize: Missing datatype constructor (pat)"
adamc@193 190 | SOME pn' => ((PCon (dk, PConVar pn', [], po), #2 p), st)
adamc@193 191 end
adamc@193 192 end
adamc@193 193 | PCon _ => (p, st)
adamc@193 194 | PRecord xps =>
adamc@193 195 let
adamc@193 196 val (xps, st) = ListUtil.foldlMap (fn ((x, p, t), st) =>
adamc@193 197 let
adamc@193 198 val (p, st) = pat (p, st)
adamc@193 199 in
adamc@193 200 ((x, p, t), st)
adamc@193 201 end)
adamc@193 202 st xps
adamc@193 203 in
adamc@193 204 ((PRecord xps, #2 p), st)
adamc@193 205 end
adamc@193 206
adamc@193 207 fun exp (e, st) =
adamc@193 208 case e of
adamc@193 209 ECon (dk, PConVar pn, args as (_ :: _), eo) =>
adamc@193 210 if List.exists isOpen args then
adamc@193 211 (e, st)
adamc@193 212 else
adamc@193 213 (case IM.find (#constructors st, pn) of
adamc@193 214 NONE => (e, st)
adamc@193 215 | SOME n =>
adamc@193 216 case IM.find (#datatypes st, n) of
adamc@193 217 NONE => (e, st)
adamc@193 218 | SOME dt =>
adamc@193 219 let
adamc@193 220 val (n, cmap, st) = considerSpecialization (st, n, args, dt)
adamc@193 221 in
adamc@193 222 case IM.find (cmap, pn) of
adamc@193 223 NONE => raise Fail "Specialize: Missing datatype constructor"
adamc@193 224 | SOME pn' => (ECon (dk, PConVar pn', [], eo), st)
adamc@193 225 end)
adamc@193 226 | ECase (e, pes, r) =>
adamc@193 227 let
adamc@193 228 val (pes, st) = ListUtil.foldlMap (fn ((p, e), st) =>
adamc@193 229 let
adamc@193 230 val (p, st) = pat (p, st)
adamc@193 231 in
adamc@193 232 ((p, e), st)
adamc@193 233 end) st pes
adamc@193 234 in
adamc@193 235 (ECase (e, pes, r), st)
adamc@193 236 end
adamc@193 237 | _ => (e, st)
adamc@193 238
adamc@193 239 fun decl (d, st) = (d, st)
adamc@193 240
adamc@193 241 val specDecl = U.Decl.foldMap {kind = kind, con = con, exp = exp, decl = decl}
adamc@193 242
adamc@193 243 fun specialize file =
adamc@193 244 let
adamc@193 245 fun doDecl (all as (d, _), st : state) =
adamc@194 246 let
adamc@194 247 (*val () = Print.preface ("decl:", CorePrint.p_decl CoreEnv.empty all)*)
adamc@194 248 in
adamc@194 249 case d of
adamc@194 250 DDatatype (x, n, xs, xnts) =>
adamc@194 251 ([all], {count = #count st,
adamc@194 252 datatypes = IM.insert (#datatypes st, n,
adamc@194 253 {name = x,
adamc@194 254 params = length xs,
adamc@194 255 constructors = xnts,
adamc@194 256 specializations = CM.empty}),
adamc@194 257 constructors = foldl (fn ((_, n', _), constructors) =>
adamc@194 258 IM.insert (constructors, n', n))
adamc@194 259 (#constructors st) xnts,
adamc@194 260 decls = []})
adamc@194 261 | _ =>
adamc@194 262 let
adamc@194 263 val (d, st) = specDecl st all
adamc@194 264 in
adamc@194 265 (rev (d :: #decls st),
adamc@194 266 {count = #count st,
adamc@194 267 datatypes = #datatypes st,
adamc@194 268 constructors = #constructors st,
adamc@194 269 decls = []})
adamc@194 270 end
adamc@194 271 end
adamc@193 272
adamc@193 273 val (ds, _) = ListUtil.foldlMapConcat doDecl
adamc@193 274 {count = U.File.maxName file + 1,
adamc@193 275 datatypes = IM.empty,
adamc@193 276 constructors = IM.empty,
adamc@193 277 decls = []} file
adamc@193 278 in
adamc@193 279 ds
adamc@193 280 end
adamc@193 281
adamc@193 282
adamc@193 283 end