annotate src/elab_ops.sml @ 1788:f57983ba2a36

Get regular forms working again
author Adam Chlipala <adam@chlipala.net>
date Sat, 21 Jul 2012 15:34:07 -0400
parents ec47f49c6aa3
children
rev   line source
adam@1718 1 (* Copyright (c) 2008, 2012, 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@623 35 fun liftKindInKind' by =
adamc@623 36 U.Kind.mapB {kind = fn bound => fn k =>
adamc@623 37 case k of
adamc@623 38 KRel xn =>
adamc@623 39 if xn < bound then
adamc@623 40 k
adamc@623 41 else
adamc@623 42 KRel (xn + by)
adamc@623 43 | _ => k,
adamc@623 44 bind = fn (bound, _) => bound + 1}
adamc@623 45
adamc@623 46 fun subKindInKind' rep =
adamc@623 47 U.Kind.mapB {kind = fn (by, xn) => fn k =>
adamc@623 48 case k of
adamc@623 49 KRel xn' =>
adamc@623 50 (case Int.compare (xn', xn) of
adamc@623 51 EQUAL => #1 (liftKindInKind' by 0 rep)
adamc@623 52 | GREATER => KRel (xn' - 1)
adamc@623 53 | LESS => k)
adamc@623 54 | _ => k,
adamc@623 55 bind = fn ((by, xn), _) => (by+1, xn+1)}
adamc@623 56
adamc@623 57 val liftKindInKind = liftKindInKind' 1
adamc@623 58
adamc@623 59 fun subKindInKind (xn, rep) = subKindInKind' rep (0, xn)
adamc@623 60
adamc@623 61 fun liftKindInCon by =
adamc@623 62 U.Con.mapB {kind = fn bound => fn k =>
adamc@623 63 case k of
adamc@623 64 KRel xn =>
adamc@623 65 if xn < bound then
adamc@623 66 k
adamc@623 67 else
adamc@623 68 KRel (xn + by)
adamc@623 69 | _ => k,
adamc@623 70 con = fn _ => fn c => c,
adamc@623 71 bind = fn (bound, U.Con.RelK _) => bound + 1
adamc@623 72 | (bound, _) => bound}
adamc@623 73
adamc@623 74 fun subKindInCon' rep =
adamc@623 75 U.Con.mapB {kind = fn (by, xn) => fn k =>
adamc@623 76 case k of
adamc@623 77 KRel xn' =>
adamc@623 78 (case Int.compare (xn', xn) of
adamc@623 79 EQUAL => #1 (liftKindInKind' by 0 rep)
adamc@623 80 | GREATER => KRel (xn' - 1)
adamc@623 81 | LESS => k)
adamc@623 82 | _ => k,
adamc@623 83 con = fn _ => fn c => c,
adamc@623 84 bind = fn ((by, xn), U.Con.RelK _) => (by+1, xn+1)
adamc@623 85 | (st, _) => st}
adamc@623 86
adamc@623 87 val liftKindInCon = liftKindInCon 1
adamc@623 88
adamc@623 89 fun subKindInCon (xn, rep) = subKindInCon' rep (0, xn)
adamc@623 90
adamc@516 91 fun liftConInCon by =
adamc@623 92 U.Con.mapB {kind = fn _ => fn k => k,
adamc@516 93 con = fn bound => fn c =>
adamc@516 94 case c of
adamc@516 95 CRel xn =>
adamc@516 96 if xn < bound then
adamc@516 97 c
adamc@516 98 else
adamc@516 99 CRel (xn + by)
adam@1303 100 | CUnif (nl, loc, k, s, r) => CUnif (nl+by, loc, k, s, r)
adamc@516 101 | _ => c,
adamc@623 102 bind = fn (bound, U.Con.RelC _) => bound + 1
adamc@516 103 | (bound, _) => bound}
adamc@81 104
adam@1303 105 exception SubUnif
adam@1303 106
adamc@516 107 fun subConInCon' rep =
adamc@623 108 U.Con.mapB {kind = fn _ => fn k => k,
adamc@516 109 con = fn (by, xn) => fn c =>
adamc@516 110 case c of
adamc@516 111 CRel xn' =>
adamc@516 112 (case Int.compare (xn', xn) of
adamc@516 113 EQUAL => #1 (liftConInCon by 0 rep)
adamc@516 114 | GREATER => CRel (xn' - 1)
adamc@516 115 | LESS => c)
adam@1303 116 | CUnif (0, _, _, _, _) => raise SubUnif
adam@1303 117 | CUnif (n, loc, k, s, r) => CUnif (n-1, loc, k, s, r)
adamc@516 118 | _ => c,
adamc@623 119 bind = fn ((by, xn), U.Con.RelC _) => (by+1, xn+1)
adamc@81 120 | (ctx, _) => ctx}
adamc@81 121
adamc@516 122 val liftConInCon = liftConInCon 1
adamc@516 123
adamc@516 124 fun subConInCon (xn, rep) = subConInCon' rep (0, xn)
adamc@516 125
adamc@81 126 fun subStrInSgn (m1, m2) =
adamc@81 127 U.Sgn.map {kind = fn k => k,
adamc@81 128 con = fn c as CModProj (m1', ms, x) =>
adamc@81 129 if m1 = m1' then
adamc@81 130 CModProj (m2, ms, x)
adamc@81 131 else
adamc@81 132 c
adamc@81 133 | c => c,
adamc@81 134 sgn_item = fn sgi => sgi,
adamc@81 135 sgn = fn sgn => sgn}
adamc@81 136
adamc@905 137 val occurs =
adamc@905 138 U.Con.existsB {kind = fn _ => false,
adamc@905 139 con = fn (n, c) =>
adamc@905 140 case c of
adamc@905 141 CRel n' => n' = n
adamc@905 142 | _ => false,
adamc@905 143 bind = fn (n, b) =>
adamc@905 144 case b of
adamc@905 145 U.Con.RelC _ => n + 1
adamc@905 146 | _ => n}
adamc@905 147 0
adamc@905 148
adamc@1034 149 val identity = ref 0
adamc@1034 150 val distribute = ref 0
adamc@1034 151 val fuse = ref 0
adamc@1034 152
adamc@1034 153 fun reset () = (identity := 0;
adamc@1034 154 distribute := 0;
adamc@1034 155 fuse := 0)
adamc@81 156
adamc@81 157 fun hnormCon env (cAll as (c, loc)) =
adamc@81 158 case c of
adam@1639 159 CUnif (nl, _, _, _, ref (Known c)) => (#1 (hnormCon env (E.mliftConInCon nl c)), loc)
adamc@81 160
adamc@81 161 | CNamed xn =>
adamc@81 162 (case E.lookupCNamed env xn of
adamc@81 163 (_, _, SOME c') => hnormCon env c'
adamc@81 164 | _ => cAll)
adamc@81 165
adamc@81 166 | CModProj (n, ms, x) =>
adamc@81 167 let
adamc@81 168 val (_, sgn) = E.lookupStrNamed env n
adamc@81 169 val (str, sgn) = foldl (fn (m, (str, sgn)) =>
adamc@81 170 case E.projectStr env {sgn = sgn, str = str, field = m} of
adamc@81 171 NONE => raise Fail "hnormCon: Unknown substructure"
adamc@81 172 | SOME sgn => ((StrProj (str, m), loc), sgn))
adamc@81 173 ((StrVar n, loc), sgn) ms
adamc@81 174 in
adamc@81 175 case E.projectCon env {sgn = sgn, str = str, field = x} of
adamc@81 176 NONE => raise Fail "kindof: Unknown con in structure"
adamc@81 177 | SOME (_, NONE) => cAll
adamc@81 178 | SOME (_, SOME c) => hnormCon env c
adamc@81 179 end
adamc@81 180
adamc@905 181 (* Eta reduction *)
adamc@905 182 | CAbs (x, k, b) =>
adamc@905 183 (case #1 (hnormCon (E.pushCRel env x k) b) of
adamc@905 184 CApp (f, (CRel 0, _)) =>
adamc@905 185 if occurs f then
adamc@905 186 cAll
adamc@905 187 else
adamc@905 188 hnormCon env (subConInCon (0, (CUnit, loc)) f)
adamc@905 189 | _ => cAll)
adamc@905 190
adamc@81 191 | CApp (c1, c2) =>
adamc@81 192 (case #1 (hnormCon env c1) of
adamc@81 193 CAbs (x, k, cb) =>
adamc@81 194 let
adamc@81 195 val sc = (hnormCon env (subConInCon (0, c2) cb))
adamc@81 196 handle SynUnif => cAll
adamc@81 197 (*val env' = E.pushCRel env x k*)
adamc@81 198 in
adamc@328 199 (*Print.eprefaces "Subst" [("x", Print.PD.string x),
adamc@328 200 ("cb", ElabPrint.p_con env' cb),
adamc@328 201 ("c2", ElabPrint.p_con env c2),
adamc@328 202 ("sc", ElabPrint.p_con env sc)];*)
adamc@81 203 sc
adamc@81 204 end
adamc@621 205 | c1' as CApp (c', f) =>
adamc@326 206 let
adamc@326 207 fun default () = (CApp ((c1', loc), hnormCon env c2), loc)
adamc@326 208 in
adamc@326 209 case #1 (hnormCon env c') of
adamc@621 210 CMap (ks as (k1, k2)) =>
adamc@621 211 (case #1 (hnormCon env c2) of
adamc@621 212 CRecord (_, []) => (CRecord (k2, []), loc)
adamc@621 213 | CRecord (_, (x, c) :: rest) =>
adamc@621 214 hnormCon env
adamc@621 215 (CConcat ((CRecord (k2, [(x, (CApp (f, c), loc))]), loc),
adamc@621 216 (CApp (c1, (CRecord (k2, rest), loc)), loc)), loc)
adamc@621 217 | CConcat ((CRecord (k, (x, c) :: rest), _), rest') =>
adamc@621 218 let
adamc@621 219 val rest'' = (CConcat ((CRecord (k, rest), loc), rest'), loc)
adamc@621 220 in
adamc@621 221 hnormCon env
adamc@621 222 (CConcat ((CRecord (k2, [(x, (CApp (f, c), loc))]), loc),
adamc@621 223 (CApp (c1, rest''), loc)), loc)
adamc@621 224 end
adamc@621 225 | _ =>
adamc@621 226 let
adamc@621 227 fun unconstraint c =
adamc@621 228 case hnormCon env c of
adamc@628 229 (TDisjoint (_, _, c), _) => unconstraint c
adamc@621 230 | c => c
adamc@81 231
adamc@1034 232 fun inc r = r := !r + 1
adamc@1034 233
adamc@621 234 fun tryDistributivity () =
adamc@621 235 case hnormCon env c2 of
adamc@621 236 (CConcat (c1, c2'), _) =>
adamc@621 237 let
adamc@621 238 val c = (CMap ks, loc)
adamc@621 239 val c = (CApp (c, f), loc)
adamc@621 240
adamc@621 241 val c1 = (CApp (c, c1), loc)
adamc@621 242 val c2 = (CApp (c, c2'), loc)
adamc@621 243 val c = (CConcat (c1, c2), loc)
adamc@621 244 in
adamc@1034 245 inc distribute;
adamc@621 246 hnormCon env c
adamc@621 247 end
adamc@621 248 | _ => default ()
adamc@329 249
adamc@621 250 fun tryFusion () =
adamc@621 251 case #1 (hnormCon env c2) of
adamc@621 252 CApp (f', r') =>
adamc@621 253 (case #1 (hnormCon env f') of
adamc@621 254 CApp (f', inner_f) =>
adamc@621 255 (case #1 (hnormCon env f') of
adamc@621 256 CMap (dom, _) =>
adamc@621 257 let
adamc@990 258 val inner_f = liftConInCon 0 inner_f
adamc@990 259 val f = liftConInCon 0 f
adamc@990 260
adamc@621 261 val f' = (CApp (inner_f, (CRel 0, loc)), loc)
adamc@621 262 val f' = (CApp (f, f'), loc)
adamc@621 263 val f' = (CAbs ("v", dom, f'), loc)
adamc@329 264
adamc@621 265 val c = (CMap (dom, k2), loc)
adamc@621 266 val c = (CApp (c, f'), loc)
adamc@621 267 val c = (CApp (c, r'), loc)
adamc@621 268 in
adamc@1034 269 inc fuse;
adamc@621 270 hnormCon env c
adamc@621 271 end
adamc@621 272 | _ => tryDistributivity ())
adamc@621 273 | _ => tryDistributivity ())
adamc@621 274 | _ => tryDistributivity ()
adamc@339 275
adamc@621 276 fun tryIdentity () =
adamc@621 277 let
adamc@621 278 fun cunif () =
adamc@621 279 let
adam@1639 280 val r = ref (Unknown (fn _ => true))
adamc@621 281 in
adam@1303 282 (r, (CUnif (0, loc, (KType, loc), "_", r), loc))
adamc@621 283 end
adamc@621 284
adamc@621 285 val (vR, v) = cunif ()
adamc@494 286
adamc@621 287 val c = (CApp (f, v), loc)
adamc@621 288 in
adamc@621 289 case unconstraint c of
adam@1303 290 (CUnif (_, _, _, _, vR'), _) =>
adamc@621 291 if vR' = vR then
adamc@1034 292 (inc identity;
adamc@1034 293 hnormCon env c2)
adamc@621 294 else
adamc@621 295 tryFusion ()
adamc@621 296 | _ => tryFusion ()
adamc@621 297 end
adamc@621 298 in
adamc@621 299 tryIdentity ()
adamc@621 300 end)
adamc@326 301 | _ => default ()
adamc@326 302 end
adamc@326 303 | c1' => (CApp ((c1', loc), hnormCon env c2), loc))
adamc@623 304
adamc@623 305 | CKApp (c1, k) =>
adamc@623 306 (case hnormCon env c1 of
adamc@623 307 (CKAbs (_, body), _) => hnormCon env (subKindInCon (0, k) body)
adamc@623 308 | _ => cAll)
adamc@621 309
adamc@81 310 | CConcat (c1, c2) =>
adamc@81 311 (case (hnormCon env c1, hnormCon env c2) of
adamc@81 312 ((CRecord (k, xcs1), loc), (CRecord (_, xcs2), _)) =>
adamc@81 313 (CRecord (k, xcs1 @ xcs2), loc)
adamc@81 314 | ((CRecord (_, []), _), c2') => c2'
adamc@81 315 | ((CConcat (c11, c12), loc), c2') =>
adamc@81 316 hnormCon env (CConcat (c11, (CConcat (c12, c2'), loc)), loc)
adamc@209 317 | (c1', (CRecord (_, []), _)) => c1'
adamc@329 318 | (c1', c2') => (CConcat (c1', c2'), loc))
adamc@81 319
adamc@207 320 | CProj (c, n) =>
adamc@207 321 (case hnormCon env c of
adamc@207 322 (CTuple cs, _) => hnormCon env (List.nth (cs, n - 1))
adamc@207 323 | _ => cAll)
adamc@207 324
adamc@81 325 | _ => cAll
adamc@81 326
adam@1714 327 fun reduceCon env (cAll as (c, loc)) =
adam@1714 328 case c of
adam@1714 329 TFun (c1, c2) => (TFun (reduceCon env c1, reduceCon env c2), loc)
adam@1714 330 | TCFun (exp, x, k, c) => (TCFun (exp, x, k, reduceCon env c), loc)
adam@1714 331 | TRecord c => (TRecord (reduceCon env c), loc)
adam@1714 332 | TDisjoint (c1, c2, c3) => (TDisjoint (reduceCon env c1, reduceCon env c2, reduceCon env c3), loc)
adam@1714 333
adam@1714 334 | CRel _ => cAll
adam@1714 335 | CNamed xn =>
adam@1714 336 (case E.lookupCNamed env xn of
adam@1714 337 (_, _, SOME c') => reduceCon env c'
adam@1714 338 | _ => cAll)
adam@1735 339 | CModProj (n, ms, x) =>
adam@1735 340 let
adam@1735 341 val (_, sgn) = E.lookupStrNamed env n
adam@1735 342 val (str, sgn) = foldl (fn (m, (str, sgn)) =>
adam@1735 343 case E.projectStr env {sgn = sgn, str = str, field = m} of
adam@1735 344 NONE => raise Fail "reduceCon: Unknown substructure"
adam@1735 345 | SOME sgn => ((StrProj (str, m), loc), sgn))
adam@1735 346 ((StrVar n, loc), sgn) ms
adam@1735 347 in
adam@1735 348 case E.projectCon env {sgn = sgn, str = str, field = x} of
adam@1735 349 NONE => raise Fail "reduceCon: kindof: Unknown con in structure"
adam@1735 350 | SOME (_, NONE) => cAll
adam@1735 351 | SOME (_, SOME c) => reduceCon env c
adam@1735 352 end
adam@1735 353
adam@1714 354 | CApp (c1, c2) =>
adam@1714 355 let
adam@1714 356 val c1 = reduceCon env c1
adam@1714 357 val c2 = reduceCon env c2
adam@1714 358 fun default () = (CApp (c1, c2), loc)
adam@1714 359 in
adam@1714 360 case #1 c1 of
adam@1714 361 CAbs (x, k, cb) =>
adam@1714 362 ((reduceCon env (subConInCon (0, c2) cb))
adam@1714 363 handle SynUnif => default ())
adam@1714 364 | CApp (c', f) =>
adam@1714 365 let
adam@1714 366 val c' = reduceCon env c'
adam@1714 367 val f = reduceCon env f
adam@1714 368 in
adam@1714 369 case #1 c' of
adam@1714 370 CMap (ks as (k1, k2)) =>
adam@1714 371 (case #1 c2 of
adam@1714 372 CRecord (_, []) => (CRecord (k2, []), loc)
adam@1714 373 | CRecord (_, (x, c) :: rest) =>
adam@1714 374 reduceCon env
adam@1714 375 (CConcat ((CRecord (k2, [(x, (CApp (f, c), loc))]), loc),
adam@1714 376 (CApp (c1, (CRecord (k2, rest), loc)), loc)), loc)
adam@1714 377 | CConcat ((CRecord (k, (x, c) :: rest), _), rest') =>
adam@1714 378 let
adam@1714 379 val rest'' = (CConcat ((CRecord (k, rest), loc), rest'), loc)
adam@1714 380 in
adam@1714 381 reduceCon env
adam@1714 382 (CConcat ((CRecord (k2, [(x, (CApp (f, c), loc))]), loc),
adam@1714 383 (CApp (c1, rest''), loc)), loc)
adam@1714 384 end
adam@1714 385 | _ =>
adam@1714 386 let
adam@1714 387 fun unconstraint c =
adam@1714 388 case reduceCon env c of
adam@1714 389 (TDisjoint (_, _, c), _) => unconstraint c
adam@1714 390 | c => c
adam@1714 391
adam@1714 392 fun inc r = r := !r + 1
adam@1714 393
adam@1714 394 fun tryDistributivity () =
adam@1714 395 case reduceCon env c2 of
adam@1714 396 (CConcat (c1, c2), _) =>
adam@1714 397 let
adam@1714 398 val c = (CMap ks, loc)
adam@1714 399 val c = (CApp (c, f), loc)
adam@1714 400
adam@1714 401 val c1 = (CApp (c, c1), loc)
adam@1714 402 val c2 = (CApp (c, c2), loc)
adam@1714 403 val c = (CConcat (c1, c2), loc)
adam@1714 404 in
adam@1714 405 inc distribute;
adam@1714 406 reduceCon env c
adam@1714 407 end
adam@1714 408 | _ => default ()
adam@1714 409
adam@1714 410 fun tryFusion () =
adam@1714 411 case #1 (reduceCon env c2) of
adam@1714 412 CApp (f', r') =>
adam@1714 413 (case #1 (reduceCon env f') of
adam@1714 414 CApp (f', inner_f) =>
adam@1714 415 (case #1 (reduceCon env f') of
adam@1714 416 CMap (dom, _) =>
adam@1714 417 let
adam@1714 418 val inner_f = liftConInCon 0 inner_f
adam@1714 419 val f = liftConInCon 0 f
adam@1714 420
adam@1714 421 val f' = (CApp (inner_f, (CRel 0, loc)), loc)
adam@1714 422 val f' = (CApp (f, f'), loc)
adam@1714 423 val f' = (CAbs ("v", dom, f'), loc)
adam@1714 424
adam@1714 425 val c = (CMap (dom, k2), loc)
adam@1714 426 val c = (CApp (c, f'), loc)
adam@1714 427 val c = (CApp (c, r'), loc)
adam@1714 428 in
adam@1714 429 inc fuse;
adam@1714 430 reduceCon env c
adam@1714 431 end
adam@1714 432 | _ => tryDistributivity ())
adam@1714 433 | _ => tryDistributivity ())
adam@1714 434 | _ => tryDistributivity ()
adam@1714 435
adam@1714 436 fun tryIdentity () =
adam@1714 437 let
adam@1714 438 fun cunif () =
adam@1714 439 let
adam@1714 440 val r = ref (Unknown (fn _ => true))
adam@1714 441 in
adam@1714 442 (r, (CUnif (0, loc, (KType, loc), "_", r), loc))
adam@1714 443 end
adam@1714 444
adam@1714 445 val (vR, v) = cunif ()
adam@1714 446
adam@1714 447 val c = (CApp (f, v), loc)
adam@1714 448 in
adam@1714 449 case unconstraint c of
adam@1714 450 (CUnif (_, _, _, _, vR'), _) =>
adam@1714 451 if vR' = vR then
adam@1714 452 (inc identity;
adam@1714 453 reduceCon env c2)
adam@1714 454 else
adam@1714 455 tryFusion ()
adam@1714 456 | _ => tryFusion ()
adam@1714 457 end
adam@1714 458 in
adam@1714 459 tryIdentity ()
adam@1714 460 end)
adam@1714 461 | _ => default ()
adam@1714 462 end
adam@1714 463 | _ => default ()
adam@1714 464 end
adam@1714 465 | CAbs (x, k, b) =>
adam@1714 466 let
adam@1714 467 val b = reduceCon (E.pushCRel env x k) b
adam@1714 468 fun default () = (CAbs (x, k, b), loc)
adam@1714 469 in
adam@1714 470 case #1 b of
adam@1714 471 CApp (f, (CRel 0, _)) =>
adam@1714 472 if occurs f then
adam@1714 473 default ()
adam@1714 474 else
adam@1714 475 reduceCon env (subConInCon (0, (CUnit, loc)) f)
adam@1714 476 | _ => default ()
adam@1714 477 end
adam@1714 478
adam@1714 479 | CKAbs (x, b) => (CKAbs (x, reduceCon (E.pushKRel env x) b), loc)
adam@1714 480 | CKApp (c1, k) =>
adam@1714 481 (case reduceCon env c1 of
adam@1714 482 (CKAbs (_, body), _) => reduceCon env (subKindInCon (0, k) body)
adam@1714 483 | c1 => (CKApp (c1, k), loc))
adam@1714 484 | TKFun (x, c) => (TKFun (x, reduceCon env c), loc)
adam@1714 485
adam@1714 486 | CName _ => cAll
adam@1714 487
adam@1714 488 | CRecord (k, xcs) => (CRecord (k, map (fn (x, c) => (reduceCon env x, reduceCon env c)) xcs), loc)
adam@1714 489 | CConcat (c1, c2) =>
adam@1714 490 let
adam@1714 491 val c1 = reduceCon env c1
adam@1714 492 val c2 = reduceCon env c2
adam@1714 493 in
adam@1714 494 case (c1, c2) of
adam@1714 495 ((CRecord (k, xcs1), loc), (CRecord (_, xcs2), _)) => (CRecord (k, xcs1 @ xcs2), loc)
adam@1714 496 | ((CRecord (_, []), _), _) => c2
adam@1714 497 | ((CConcat (c11, c12), loc), _) => reduceCon env (CConcat (c11, (CConcat (c12, c2), loc)), loc)
adam@1714 498 | (_, (CRecord (_, []), _)) => c1
adam@1718 499 | ((CRecord (k, xcs1), loc), (CConcat ((CRecord (_, xcs2), _), c2'), _)) => (CConcat ((CRecord (k, xcs1 @ xcs2), loc), c2'), loc)
adam@1714 500 | _ => (CConcat (c1, c2), loc)
adam@1714 501 end
adam@1714 502 | CMap _ => cAll
adam@1714 503
adam@1714 504 | CUnit => cAll
adam@1714 505
adam@1714 506 | CTuple cs => (CTuple (map (reduceCon env) cs), loc)
adam@1714 507 | CProj (c, n) =>
adam@1714 508 (case reduceCon env c of
adam@1714 509 (CTuple cs, _) => reduceCon env (List.nth (cs, n - 1))
adam@1714 510 | c => (CProj (c, n), loc))
adam@1714 511
adam@1714 512 | CError => cAll
adam@1714 513
adam@1714 514 | CUnif (nl, _, _, _, ref (Known c)) => reduceCon env (E.mliftConInCon nl c)
adam@1714 515 | CUnif _ => cAll
adam@1714 516
adamc@81 517 end