annotate src/elab_ops.sml @ 541:2bf2d0e0fb61

Type inference
author Adam Chlipala <adamc@hcoop.net>
date Sat, 06 Dec 2008 12:01:12 -0500
parents 11fc77fb8257
children 8998114760c1
rev   line source
adamc@81 1 (* Copyright (c) 2008, Adam Chlipala
adamc@81 2 * All rights reserved.
adamc@81 3 *
adamc@81 4 * Redistribution and use in source and binary forms, with or without
adamc@81 5 * modification, are permitted provided that the following conditions are met:
adamc@81 6 *
adamc@81 7 * - Redistributions of source code must retain the above copyright notice,
adamc@81 8 * this list of conditions and the following disclaimer.
adamc@81 9 * - Redistributions in binary form must reproduce the above copyright notice,
adamc@81 10 * this list of conditions and the following disclaimer in the documentation
adamc@81 11 * and/or other materials provided with the distribution.
adamc@81 12 * - The names of contributors may not be used to endorse or promote products
adamc@81 13 * derived from this software without specific prior written permission.
adamc@81 14 *
adamc@81 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
adamc@81 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
adamc@81 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
adamc@81 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
adamc@81 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
adamc@81 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
adamc@81 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
adamc@81 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
adamc@81 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
adamc@81 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
adamc@81 25 * POSSIBILITY OF SUCH DAMAGE.
adamc@81 26 *)
adamc@81 27
adamc@81 28 structure ElabOps :> ELAB_OPS = struct
adamc@81 29
adamc@81 30 open Elab
adamc@81 31
adamc@81 32 structure E = ElabEnv
adamc@81 33 structure U = ElabUtil
adamc@81 34
adamc@516 35 fun liftConInCon by =
adamc@516 36 U.Con.mapB {kind = fn k => k,
adamc@516 37 con = fn bound => fn c =>
adamc@516 38 case c of
adamc@516 39 CRel xn =>
adamc@516 40 if xn < bound then
adamc@516 41 c
adamc@516 42 else
adamc@516 43 CRel (xn + by)
adamc@516 44 (*| CUnif _ => raise SynUnif*)
adamc@516 45 | _ => c,
adamc@516 46 bind = fn (bound, U.Con.Rel _) => bound + 1
adamc@516 47 | (bound, _) => bound}
adamc@81 48
adamc@516 49 fun subConInCon' rep =
adamc@81 50 U.Con.mapB {kind = fn k => k,
adamc@516 51 con = fn (by, xn) => fn c =>
adamc@516 52 case c of
adamc@516 53 CRel xn' =>
adamc@516 54 (case Int.compare (xn', xn) of
adamc@516 55 EQUAL => #1 (liftConInCon by 0 rep)
adamc@516 56 | GREATER => CRel (xn' - 1)
adamc@516 57 | LESS => c)
adamc@516 58 (*| CUnif _ => raise SynUnif*)
adamc@516 59 | _ => c,
adamc@516 60 bind = fn ((by, xn), U.Con.Rel _) => (by+1, xn+1)
adamc@81 61 | (ctx, _) => ctx}
adamc@81 62
adamc@516 63 val liftConInCon = liftConInCon 1
adamc@516 64
adamc@516 65 fun subConInCon (xn, rep) = subConInCon' rep (0, xn)
adamc@516 66
adamc@81 67 fun subStrInSgn (m1, m2) =
adamc@81 68 U.Sgn.map {kind = fn k => k,
adamc@81 69 con = fn c as CModProj (m1', ms, x) =>
adamc@81 70 if m1 = m1' then
adamc@81 71 CModProj (m2, ms, x)
adamc@81 72 else
adamc@81 73 c
adamc@81 74 | c => c,
adamc@81 75 sgn_item = fn sgi => sgi,
adamc@81 76 sgn = fn sgn => sgn}
adamc@81 77
adamc@81 78
adamc@81 79 fun hnormCon env (cAll as (c, loc)) =
adamc@81 80 case c of
adamc@81 81 CUnif (_, _, _, ref (SOME c)) => hnormCon env c
adamc@81 82
adamc@81 83 | CNamed xn =>
adamc@81 84 (case E.lookupCNamed env xn of
adamc@81 85 (_, _, SOME c') => hnormCon env c'
adamc@81 86 | _ => cAll)
adamc@81 87
adamc@81 88 | CModProj (n, ms, x) =>
adamc@81 89 let
adamc@81 90 val (_, sgn) = E.lookupStrNamed env n
adamc@81 91 val (str, sgn) = foldl (fn (m, (str, sgn)) =>
adamc@81 92 case E.projectStr env {sgn = sgn, str = str, field = m} of
adamc@81 93 NONE => raise Fail "hnormCon: Unknown substructure"
adamc@81 94 | SOME sgn => ((StrProj (str, m), loc), sgn))
adamc@81 95 ((StrVar n, loc), sgn) ms
adamc@81 96 in
adamc@81 97 case E.projectCon env {sgn = sgn, str = str, field = x} of
adamc@81 98 NONE => raise Fail "kindof: Unknown con in structure"
adamc@81 99 | SOME (_, NONE) => cAll
adamc@81 100 | SOME (_, SOME c) => hnormCon env c
adamc@81 101 end
adamc@81 102
adamc@81 103 | CApp (c1, c2) =>
adamc@81 104 (case #1 (hnormCon env c1) of
adamc@81 105 CAbs (x, k, cb) =>
adamc@81 106 let
adamc@81 107 val sc = (hnormCon env (subConInCon (0, c2) cb))
adamc@81 108 handle SynUnif => cAll
adamc@81 109 (*val env' = E.pushCRel env x k*)
adamc@81 110 in
adamc@328 111 (*Print.eprefaces "Subst" [("x", Print.PD.string x),
adamc@328 112 ("cb", ElabPrint.p_con env' cb),
adamc@328 113 ("c2", ElabPrint.p_con env c2),
adamc@328 114 ("sc", ElabPrint.p_con env sc)];*)
adamc@81 115 sc
adamc@81 116 end
adamc@326 117 | c1' as CApp (c', i) =>
adamc@326 118 let
adamc@326 119 fun default () = (CApp ((c1', loc), hnormCon env c2), loc)
adamc@326 120 in
adamc@326 121 case #1 (hnormCon env c') of
adamc@326 122 CApp (c', f) =>
adamc@326 123 (case #1 (hnormCon env c') of
adamc@326 124 CFold ks =>
adamc@326 125 (case #1 (hnormCon env c2) of
adamc@326 126 CRecord (_, []) => hnormCon env i
adamc@326 127 | CRecord (k, (x, c) :: rest) =>
adamc@326 128 hnormCon env
adamc@326 129 (CApp ((CApp ((CApp (f, x), loc), c), loc),
adamc@81 130 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
adamc@326 131 (CRecord (k, rest), loc)), loc)), loc)
adamc@326 132 | CConcat ((CRecord (k, (x, c) :: rest), _), rest') =>
adamc@326 133 let
adamc@326 134 val rest'' = (CConcat ((CRecord (k, rest), loc), rest'), loc)
adamc@81 135
adamc@326 136 (*val ccc = (CApp ((CApp ((CApp (f, x), loc), c), loc),
adamc@326 137 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
adamc@326 138 rest''), loc)), loc)*)
adamc@326 139 in
adamc@326 140 (*eprefaces "Red to" [("ccc", p_con env ccc), ("ccc'", p_con env (hnormCon env ccc))];*)
adamc@326 141 hnormCon env
adamc@326 142 (CApp ((CApp ((CApp (f, x), loc), c), loc),
adamc@81 143 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
adamc@326 144 rest''), loc)), loc)
adamc@326 145 end
adamc@329 146 | _ =>
adamc@329 147 let
adamc@329 148 fun cunif () =
adamc@329 149 let
adamc@329 150 val r = ref NONE
adamc@329 151 in
adamc@329 152 (r, (CUnif (loc, (KType, loc), "_", r), loc))
adamc@329 153 end
adamc@329 154
adamc@329 155 val (nmR, nm) = cunif ()
adamc@329 156 val (vR, v) = cunif ()
adamc@329 157 val (rR, r) = cunif ()
adamc@329 158
adamc@329 159 val c = f
adamc@329 160 val c = (CApp (c, nm), loc)
adamc@329 161 val c = (CApp (c, v), loc)
adamc@329 162 val c = (CApp (c, r), loc)
adamc@329 163 fun unconstraint c =
adamc@329 164 case hnormCon env c of
adamc@345 165 (CDisjoint (_, _, _, c), _) => unconstraint c
adamc@329 166 | c => c
adamc@329 167 val c = unconstraint c
adamc@339 168
adamc@494 169 fun tryDistributivity () =
adamc@494 170 let
adamc@494 171 fun distribute (c1, c2) =
adamc@494 172 let
adamc@494 173 val c = (CFold ks, loc)
adamc@494 174 val c = (CApp (c, f), loc)
adamc@494 175 val c = (CApp (c, i), loc)
adamc@494 176
adamc@494 177 val c1 = (CApp (c, c1), loc)
adamc@494 178 val c2 = (CApp (c, c2), loc)
adamc@494 179 val c = (CConcat (c1, c2), loc)
adamc@494 180 in
adamc@494 181 hnormCon env c
adamc@494 182 end
adamc@494 183 in
adamc@494 184 case (hnormCon env i, hnormCon env c2, hnormCon env c) of
adamc@494 185 ((CRecord (_, []), _),
adamc@494 186 (CConcat (arg1, arg2), _),
adamc@494 187 (CConcat (c1, c2'), _)) =>
adamc@494 188 (case (hnormCon env c1, hnormCon env c2') of
adamc@494 189 ((CRecord (_, [(nm', v')]), _),
adamc@494 190 (CUnif (_, _, _, rR'), _)) =>
adamc@494 191 (case hnormCon env nm' of
adamc@494 192 (CUnif (_, _, _, nmR'), _) =>
adamc@494 193 if nmR' = nmR andalso rR' = rR then
adamc@494 194 distribute (arg1, arg2)
adamc@494 195 else
adamc@494 196 default ()
adamc@494 197 | _ => default ())
adamc@494 198 | _ => default ())
adamc@494 199 | _ => default ()
adamc@494 200 end
adamc@494 201
adamc@339 202 fun tryFusion () =
adamc@339 203 let
adamc@339 204 fun fuse (dom, new_v, r') =
adamc@339 205 let
adamc@339 206 val ran = #2 ks
adamc@339 207
adamc@339 208 val f = (CApp (f, (CRel 2, loc)), loc)
adamc@339 209 val f = (CApp (f, new_v), loc)
adamc@339 210 val f = (CApp (f, (CRel 0, loc)), loc)
adamc@339 211 val f = (CAbs ("acc", ran, f), loc)
adamc@339 212 val f = (CAbs ("v", dom, f), loc)
adamc@339 213 val f = (CAbs ("nm", (KName, loc), f), loc)
adamc@339 214
adamc@339 215 val c = (CFold (dom, ran), loc)
adamc@339 216 val c = (CApp (c, f), loc)
adamc@339 217 val c = (CApp (c, i), loc)
adamc@339 218 val c = (CApp (c, r'), loc)
adamc@339 219 in
adamc@339 220 hnormCon env c
adamc@339 221 end
adamc@339 222 in
adamc@339 223 case #1 (hnormCon env c2) of
adamc@339 224 CApp (f, r') =>
adamc@339 225 (case #1 (hnormCon env f) of
adamc@339 226 CApp (f, inner_i) =>
adamc@339 227 (case (#1 (hnormCon env f), #1 (hnormCon env inner_i)) of
adamc@339 228 (CApp (f, inner_f), CRecord (_, [])) =>
adamc@339 229 (case #1 (hnormCon env f) of
adamc@339 230 CFold (dom, _) =>
adamc@339 231 let
adamc@339 232 val c = inner_f
adamc@339 233 val c = (CApp (c, nm), loc)
adamc@339 234 val c = (CApp (c, v), loc)
adamc@339 235 val c = (CApp (c, r), loc)
adamc@339 236 val c = unconstraint c
adamc@339 237
adamc@339 238 (*val () = Print.prefaces "Onto something!"
adamc@339 239 [("c", ElabPrint.p_con env cAll),
adamc@339 240 ("c'", ElabPrint.p_con env c)]*)
adamc@339 241
adamc@339 242 in
adamc@339 243 case #1 (hnormCon env c) of
adamc@339 244 CConcat (first, rest) =>
adamc@339 245 (case (#1 (hnormCon env first),
adamc@339 246 #1 (hnormCon env rest)) of
adamc@339 247 (CRecord (_, [(nm', v')]),
adamc@339 248 CUnif (_, _, _, rR')) =>
adamc@339 249 (case #1 (hnormCon env nm') of
adamc@339 250 CUnif (_, _, _, nmR') =>
adamc@339 251 if rR' = rR andalso nmR' = nmR then
adamc@339 252 (nmR := SOME (CRel 2, loc);
adamc@339 253 vR := SOME (CRel 1, loc);
adamc@339 254 rR := SOME (CError, loc);
adamc@339 255 fuse (dom, v', r'))
adamc@339 256 else
adamc@494 257 tryDistributivity ()
adamc@494 258 | _ => tryDistributivity ())
adamc@494 259 | _ => tryDistributivity ())
adamc@494 260 | _ => tryDistributivity ()
adamc@339 261 end
adamc@494 262 | _ => tryDistributivity ())
adamc@494 263 | _ => tryDistributivity ())
adamc@494 264 | _ => tryDistributivity ())
adamc@494 265 | _ => tryDistributivity ()
adamc@339 266 end
adamc@494 267
adamc@329 268 in
adamc@329 269 (*Print.prefaces "Consider" [("c", ElabPrint.p_con env c)];*)
adamc@329 270 case (hnormCon env i, unconstraint c) of
adamc@329 271 ((CRecord (_, []), _),
adamc@329 272 (CConcat (c1, c2'), _)) =>
adamc@329 273 (case (hnormCon env c1, hnormCon env c2') of
adamc@329 274 ((CRecord (_, [(nm', v')]), _),
adamc@329 275 (CUnif (_, _, _, rR'), _)) =>
adamc@329 276 (case (hnormCon env nm', hnormCon env v') of
adamc@329 277 ((CUnif (_, _, _, nmR'), _),
adamc@329 278 (CUnif (_, _, _, vR'), _)) =>
adamc@329 279 if nmR' = nmR andalso vR' = vR andalso rR' = rR then
adamc@329 280 hnormCon env c2
adamc@329 281 else
adamc@339 282 tryFusion ()
adamc@339 283 | _ => tryFusion ())
adamc@339 284 | _ => tryFusion ())
adamc@339 285 | _ => tryFusion ()
adamc@329 286 end)
adamc@326 287 | _ => default ())
adamc@326 288 | _ => default ()
adamc@326 289 end
adamc@326 290 | c1' => (CApp ((c1', loc), hnormCon env c2), loc))
adamc@81 291
adamc@81 292 | CConcat (c1, c2) =>
adamc@81 293 (case (hnormCon env c1, hnormCon env c2) of
adamc@81 294 ((CRecord (k, xcs1), loc), (CRecord (_, xcs2), _)) =>
adamc@81 295 (CRecord (k, xcs1 @ xcs2), loc)
adamc@81 296 | ((CRecord (_, []), _), c2') => c2'
adamc@81 297 | ((CConcat (c11, c12), loc), c2') =>
adamc@81 298 hnormCon env (CConcat (c11, (CConcat (c12, c2'), loc)), loc)
adamc@209 299 | (c1', (CRecord (_, []), _)) => c1'
adamc@329 300 | (c1', c2') => (CConcat (c1', c2'), loc))
adamc@81 301
adamc@207 302 | CProj (c, n) =>
adamc@207 303 (case hnormCon env c of
adamc@207 304 (CTuple cs, _) => hnormCon env (List.nth (cs, n - 1))
adamc@207 305 | _ => cAll)
adamc@207 306
adamc@81 307 | _ => cAll
adamc@81 308
adamc@81 309 end