(* Meta Theorem Prover abstraction : Version 1.3 *) (* Author: Frank Pfenning, Carsten Schuermann *) functor MTPAbstract ((*! structure IntSyn' : INTSYN !*) (*! structure FunSyn' : FUNSYN !*) (*! sharing FunSyn'.IntSyn = IntSyn' !*) structure StateSyn' : STATESYN (*! sharing StateSyn'.FunSyn = FunSyn' !*) structure Whnf : WHNF (*! sharing Whnf.IntSyn = IntSyn' !*) structure Constraints : CONSTRAINTS (*! sharing Constraints.IntSyn = IntSyn' !*) structure Unify : UNIFY (*! sharing Unify.IntSyn = IntSyn' !*) structure Subordinate : SUBORDINATE (*! sharing Subordinate.IntSyn = IntSyn' !*) structure TypeCheck : TYPECHECK (*! sharing TypeCheck.IntSyn = IntSyn' !*) structure FunTypeCheck : FUNTYPECHECK (*! sharing FunTypeCheck.FunSyn = FunSyn' !*) sharing FunTypeCheck.StateSyn = StateSyn' structure Abstract : ABSTRACT (*! sharing Abstract.IntSyn = IntSyn' !*) ) : MTPABSTRACT = struct (*! structure IntSyn = IntSyn' !*) (*! structure FunSyn = FunSyn' !*) structure StateSyn = StateSyn' exception Error of string datatype ApproxFor = (* Approximat formula *) Head of IntSyn.dctx * (FunSyn.For * IntSyn.Sub) * int (* AF ::= F [s] *) | Block of (IntSyn.dctx * IntSyn.Sub * int * IntSyn.Dec list) * ApproxFor (* | (t, G2), AF *) local structure I = IntSyn structure F = FunSyn structure S = StateSyn structure C = Constraints (* Intermediate Data Structure *) datatype EBVar = EV of I.Exp option ref * I.Exp * S.Tag * int (* y ::= (X , {G2} V) if {G1, G2 |- X : V |G1| = d *) | BV of I.Dec * S.Tag (* We write {{K}} for the context of K, where EVars and BVars have been translated to declarations and their occurrences to BVars. We write {{U}}_K, {{S}}_K for the corresponding translation of an expression or spine. Just like contexts G, any K is implicitly assumed to be well-formed and in dependency order. We write K ||- U if all EVars and BVars in U are collected in K. In particular, . ||- U means U contains no EVars or BVars. Similarly, for spines K ||- S and other syntactic categories. Collection and abstraction raise Error if there are unresolved constraints after simplification. *) (* checkEmpty Cnstr = () raises Error exception if constraints Cnstr cannot be simplified to the empty constraint *) fun checkEmpty (nil) = () | checkEmpty (cnstrL) = (case C.simplify cnstrL of nil => () | _ => raise Error "Typing ambiguous -- unresolved constraints") (* eqEVar X Y = B where B iff X and Y represent same variable *) fun eqEVar (I.EVar (r1, _, _, _)) (EV (r2, _, _, _)) = (r1 = r2) | eqEVar _ _ = false (* exists P K = B where B iff K = K1, Y, K2 s.t. P Y holds *) fun exists P K = let fun exists' (I.Null) = false | exists' (I.Decl(K',Y)) = P(Y) orelse exists' (K') in exists' K end fun or (I.Maybe, _) = I.Maybe | or (_, I.Maybe) = I.Maybe | or (I.Meta, _) = I.Meta | or (_, I.Meta) = I.Meta | or (I.No, I.No) = I.No (* occursInExp (k, U) = DP, Invariant: If U in nf then DP = No iff k does not occur in U DP = Maybe iff k occurs in U some place not as an argument to a Skonst DP = Meta iff k occurs in U and only as arguments to Skonsts *) fun occursInExp (k, I.Uni _) = I.No | occursInExp (k, I.Pi (DP, V)) = or (occursInDecP (k, DP), occursInExp (k+1, V)) | occursInExp (k, I.Root (H, S)) = occursInHead (k, H, occursInSpine (k, S)) | occursInExp (k, I.Lam (D, V)) = or (occursInDec (k, D), occursInExp (k+1, V)) (* no case for Redex, EVar, EClo *) and occursInHead (k, I.BVar (k'), DP) = if (k = k') then I.Maybe else DP | occursInHead (k, I.Const _, DP) = DP | occursInHead (k, I.Def _, DP) = DP | occursInHead (k, I.Skonst _, I.No) = I.No | occursInHead (k, I.Skonst _, I.Meta) = I.Meta | occursInHead (k, I.Skonst _, I.Maybe) = I.Meta (* no case for FVar *) and occursInSpine (_, I.Nil) = I.No | occursInSpine (k, I.App (U, S)) = or (occursInExp (k, U), occursInSpine (k, S)) (* no case for SClo *) and occursInDec (k, I.Dec (_, V)) = occursInExp (k, V) and occursInDecP (k, (D, _)) = occursInDec (k, D) (* piDepend ((D,P), V) = Pi ((D,P'), V) where P' = Maybe if D occurs in V, P' = No otherwise *) (* optimize to have fewer traversals? -cs *) (* pre-Twelf 1.2 code walk Fri May 8 11:17:10 1998 *) fun piDepend (DPV as ((D, I.No), V)) = I.Pi DPV | piDepend (DPV as ((D, I.Meta), V)) = I.Pi DPV | piDepend ((D, I.Maybe), V) = I.Pi ((D, occursInExp (1, V)), V) (* weaken (depth, G, a) = (w') *) fun weaken (I.Null, a) = I.id | weaken (I.Decl (G', D as I.Dec (name, V)), a) = let val w' = weaken (G', a) in if Subordinate.belowEq (I.targetFam V, a) then I.dot1 w' else I.comp (w', I.shift) end (* raiseType (G, V) = {{G}} V Invariant: If G |- V : L then . |- {{G}} V : L All abstractions are potentially dependent. *) fun raiseType (I.Null, V) = V | raiseType (I.Decl (G, D), V) = raiseType (G, I.Pi ((D, I.Maybe), V)) fun restore (0, Gp) = (Gp, I.Null) | restore (n, I.Decl (G, D)) = let val (Gp', GX') = restore (n - 1, G) in (Gp', I.Decl (GX', D)) end fun concat (Gp, I.Null) = Gp | concat (Gp, I.Decl (G, D)) = I.Decl (concat (Gp, G), D) (* collectExpW (T, d, G, (U, s), K) = K' Invariant: If G |- s : G1 G1 |- U : V (U,s) in whnf No circularities in U (enforced by extended occurs-check for BVars in Unify) and K' = K, K'' where K'' contains all EVars and BVars in (U,s) *) (* Possible optimization: Calculate also the normal form of the term *) fun collectExpW (T, d, G, (I.Uni L, s), K) = K | collectExpW (T, d, G, (I.Pi ((D, _), V), s), K) = collectExp (T, d, I.Decl (G, I.decSub (D, s)), (V, I.dot1 s), collectDec (T, d, G, (D, s), K)) | collectExpW (T, d, G, (I.Root (_ , S), s), K) = collectSpine (S.decrease T, d, G, (S, s), K) | collectExpW (T, d, G, (I.Lam (D, U), s), K) = collectExp (T, d, I.Decl (G, I.decSub (D, s)), (U, I.dot1 s), collectDec (T, d, G, (D, s), K)) | collectExpW (T, d, G, (X as I.EVar (r, GdX, V, cnstrs), s), K) = if exists (eqEVar X) K then collectSub (T, d, G, s, K) else let val (Gp, GX) = restore (I.ctxLength GdX - d, GdX) (* optimization possible for d = 0 *) val _ = checkEmpty (!cnstrs) val w = weaken (GX, I.targetFam V) val iw = Whnf.invert w val GX' = Whnf.strengthen (iw, GX) val X' as I.EVar (r', _, _, _) = I.newEVar (concat (Gp, GX'), I.EClo (V, iw)) val _ = Unify.instantiateEVar (r, I.EClo (X', w), nil) val V' = raiseType (GX', I.EClo (V, iw)) in collectSub (T, d, G, I.comp (w, s), I.Decl (collectExp (T, d, Gp, (V', I.id), K), EV (r', V', T, d))) end | collectExpW (T, d, G, (I.FgnExp csfe, s), K) = I.FgnExpStd.fold csfe (fn (U, K') => collectExp (T, d, G, (U, s), K')) K (* hack - should consult cs -rv *) (* No other cases can occur due to whnf invariant *) (* collectExp (T, d, G, (U, s), K) = K' same as collectExpW but (U,s) need not to be in whnf *) and collectExp (T, d, G, Us, K) = collectExpW (T, d, G, Whnf.whnf Us, K) (* collectSpine (T, d, G, (S, s), K) = K' Invariant: If G |- s : G1 G1 |- S : V > P then K' = K, K'' where K'' contains all EVars and BVars in (S, s) *) and collectSpine (T, d, G, (I.Nil, _), K) = K | collectSpine (T, d, G, (I.SClo(S, s'), s), K) = collectSpine (T, d, G, (S, I.comp (s', s)), K) | collectSpine (T, d, G, (I.App (U, S), s), K) = collectSpine (T, d, G, (S, s), collectExp (T, d, G, (U, s), K)) (* collectDec (T, d, G, (x:V, s), K) = K' Invariant: If G |- s : G1 G1 |- V : L then K' = K, K'' where K'' contains all EVars and BVars in (V, s) *) and collectDec (T, d, G, (I.Dec (_, V), s), K) = collectExp (T, d, G, (V, s), K) (* collectSub (T, d, G, s, K) = K' Invariant: If G |- s : G1 then K' = K, K'' where K'' contains all EVars and BVars in s *) and collectSub (T, d, G, I.Shift _, K) = K | collectSub (T, d, G, I.Dot (I.Idx _, s), K) = collectSub (T, d, G, s, K) | collectSub (T, d, G, I.Dot (I.Exp (U), s), K) = collectSub (T, d, G, s, collectExp (T, d, G, (U, I.id), K)) (* abstractEVar (K, depth, X) = C' Invariant: If G |- X : V and |G| = depth and X occurs in K at kth position (starting at 1) then C' = BVar (depth + k) and {{K}}, G |- C' : V *) fun abstractEVar (I.Decl (K', EV (r', _, _, d)), depth, X as I.EVar (r, _, _, _)) = if r = r' then (I.BVar (depth+1), d) else abstractEVar (K', depth+1, X) | abstractEVar (I.Decl (K', BV _), depth, X) = abstractEVar (K', depth+1, X) (* lookupBV (A, i) = k' Invariant: If A ||- V and G |- V type and G [x] A |- i : V' then ex a substititution G x A |- s : G [x] A and G x A |- k' : V'' and G x A |- V' [s] = V'' : type *) fun lookupBV (K, i) = let fun lookupBV' (I.Decl (K, EV (r, V, _, _)), i, k) = lookupBV' (K, i, k+1) | lookupBV' (I.Decl (K, BV _), 1, k) = k | lookupBV' (I.Decl (K, BV _), i, k) = lookupBV' (K, i-1, k+1) (* lookupBV' I.Null cannot occur by invariant *) in lookupBV' (K, i, 1) end (* abstractExpW (K, depth, (U, s)) = U' U' = {{U[s]}}_K Invariant: If G |- s : G1 G1 |- U : V (U,s) is in whnf and K is internal context in dependency order and |G| = depth and K ||- U and K ||- V then {{K}}, G |- U' : V' and . ||- U' and . ||- V' and U' is in nf *) fun abstractExpW (K, depth, (U as I.Uni (L), s)) = U | abstractExpW (K, depth, (I.Pi ((D, P), V), s)) = piDepend ((abstractDec (K, depth, (D, s)), P), abstractExp (K, depth + 1, (V, I.dot1 s))) | abstractExpW (K, depth, (I.Root (H as I.BVar k, S), s)) = (* s = id *) if k > depth then let val k' = lookupBV (K, k-depth) in I.Root (I.BVar (k'+depth), abstractSpine (K, depth, (S, s))) end else I.Root (H, abstractSpine (K, depth, (S, s))) | abstractExpW (K, depth, (I.Root (H, S) ,s)) = I.Root (H, abstractSpine (K, depth, (S, s))) | abstractExpW (K, depth, (I.Lam (D, U), s)) = I.Lam (abstractDec (K, depth, (D, s)), abstractExp (K, depth + 1, (U, I.dot1 s))) | abstractExpW (K, depth, (X as I.EVar (_, G, _, _), s)) = let val (H, d) = abstractEVar (K, depth, X) in I.Root (H, abstractSub (I.ctxLength G - d, K, depth, s, I.Nil)) end | abstractExpW (K, depth, (I.FgnExp csfe, s)) = I.FgnExpStd.Map.apply csfe (fn U => abstractExp (K, depth, (U, s))) (* hack - should consult cs -rv *) (* abstractExp (K, depth, (U, s)) = U' same as abstractExpW, but (U,s) need not to be in whnf *) and abstractExp (K, depth, Us) = abstractExpW (K, depth, Whnf.whnf Us) (* abstractSub (K, depth, s, S) = S' (implicit raising) S' = {{s}}_K @@ S Invariant: If G |- s : G1 and |G| = depth and K ||- s then {{K}}, G |- S' : {G1}.W > W (for some W) and . ||- S' *) and abstractSub (n, K, depth, I.Shift (k), S) = if n > 0 then abstractSub (n, K, depth, I.Dot (I.Idx (k+1), I.Shift (k+1)), S) else (* n = 0 *) S | abstractSub (n, K, depth, I.Dot (I.Idx (k), s), S) = let val H = if k > depth then let val k' = lookupBV (K, k-depth) in I.BVar (k'+depth) end else I.BVar (k) in abstractSub (n-1, K, depth, s, I.App (I.Root (H, I.Nil), S)) end | abstractSub (n, K, depth, I.Dot (I.Exp (U), s), S) = abstractSub (n-1, K, depth, s, I.App (abstractExp (K, depth, (U, I.id)), S)) (* abstractSpine (K, depth, (S, s)) = S' where S' = {{S[s]}}_K Invariant: If G |- s : G1 G1 |- S : V > P and K ||- S and |G| = depth then {{K}}, G |- S' : V' > P' and . ||- S' *) and abstractSpine (K, depth, (I.Nil, _)) = I.Nil | abstractSpine (K, depth, (I.SClo (S, s'), s)) = abstractSpine (K, depth, (S, I.comp (s', s))) | abstractSpine (K, depth, (I.App (U, S), s)) = I.App (abstractExp (K, depth, (U ,s)), abstractSpine (K, depth, (S, s))) (* abstractDec (K, depth, (x:V, s)) = x:V' where V = {{V[s]}}_K Invariant: If G |- s : G1 G1 |- V : L and K ||- V and |G| = depth then {{K}}, G |- V' : L and . ||- V' *) and abstractDec (K, depth, (I.Dec (x, V), s)) = I.Dec (x, abstractExp (K, depth, (V, s))) (* getlevel (V) = L if G |- V : L Invariant: G |- V : L' for some L' *) fun getLevel (I.Uni _) = I.Kind | getLevel (I.Pi (_, U)) = getLevel U | getLevel (I.Root _) = I.Type | getLevel (I.Redex (U, _)) = getLevel U | getLevel (I.Lam (_, U)) = getLevel U | getLevel (I.EClo (U,_)) = getLevel U (* checkType (V) = () if G |- V : type Invariant: G |- V : L' for some L' *) fun checkType V = (case getLevel V of I.Type => () | _ => raise Error "Typing ambiguous -- free type variable") (* abstractCtx (K, V) = V' where V' = {{K}} V Invariant: If {{K}} |- V : L and . ||- V then V' = {{K}} V and . |- V' : L and . ||- V' *) fun abstractCtx (I.Null) = (I.Null, I.Null) | abstractCtx (I.Decl (K', EV (_, V', T as S.Lemma (b), _))) = let val V'' = abstractExp (K', 0, (V', I.id)) val _ = checkType V'' val (G', B') = abstractCtx K' val D' = I.Dec (NONE, V'') in (I.Decl (G', D'), I.Decl (B', T)) end | abstractCtx (I.Decl (K', EV (_, V', T as S.None, _))) = let val V'' = abstractExp (K', 0, (V', I.id)) val _ = checkType V'' val (G', B') = abstractCtx K' val D' = I.Dec (NONE, V'') in (I.Decl (G', D'), I.Decl (B', S.None)) end | abstractCtx (I.Decl (K', BV (D, T))) = let val D' = abstractDec (K', 0, (D, I.id)) val (G', B') = abstractCtx K' in (I.Decl (G', D'), I.Decl (B', T)) end (* abstractGlobalSub (K, s, B) = s' Invariant: If K > G aux context and G |- s : G' then K |- s' : G' *) fun abstractGlobalSub (K, I.Shift _, I.Null) = I.Shift (I.ctxLength K) | abstractGlobalSub (K, I.Shift n, B as I.Decl _) = abstractGlobalSub (K, I.Dot (I.Idx (n+1), I.Shift (n+1)), B) | abstractGlobalSub (K, I.Dot (I.Idx k, s'), I.Decl (B, T as S.Parameter _)) = I.Dot (I.Idx (lookupBV (K, k)), abstractGlobalSub (K, s', B)) | abstractGlobalSub (K, I.Dot (I.Exp U, s'), I.Decl (B, T as S.Lemma _)) = I.Dot (I.Exp (abstractExp (K, 0, (U, I.id))), abstractGlobalSub (K, s', B)) (* collectGlobalSub (G0, s, B, collect) = collect' Invariant: If |- G0 ctx and |- G ctx and G |- B tags and G0 |- s : G and collect is a function which maps (d, K) (d expresses the number of parameters in K, |- K aux ctx) to K' (|- K' aux ctx, which collects all EVars in K) *) fun collectGlobalSub (G0, I.Shift _, I.Null, collect) = collect | collectGlobalSub (G0, s, B as I.Decl (_, S.Parameter (SOME l)), collect) = let val F.LabelDec (name, _, G2) = F.labelLookup l in skip (G0, List.length G2, s, B, collect) end | collectGlobalSub (G0, I.Dot (I.Exp (U), s), I.Decl (B, T), collect) = collectGlobalSub (G0, s, B, fn (d, K) => collect (d, collectExp (T, d, G0, (U, I.id), K))) (* no cases for (G0, s, B as I.Decl (_, S.Parameter NONE), collect) *) and skip (G0, 0, s, B, collect) = collectGlobalSub (G0, s, B, collect) | skip (I.Decl (G0, D), n, s, I.Decl (B, T as S.Parameter _), collect) = skip (G0, n-1, I.invDot1 s, B, fn (d, K) => collect (d+1, I.Decl (K, BV (D, T)))) (* abstractNew ((G0, B0), s, B) = ((G', B'), s') Invariant: If . |- G0 ctx and G0 |- B0 tags and G0 |- s : G and G |- B tags then . |- G' = G1, Gp, G2 and G' |- B' tags and G' |- s' : G *) fun abstractNew ((G0, B0), s, B) = let val cf = collectGlobalSub (G0, s, B, fn (_, K') => K') val K = cf (0, I.Null) in (abstractCtx K, abstractGlobalSub (K, s, B)) end (* abstractSub (t, B1, (G0, B0), s, B) = ((G', B'), s') Invariant: If . |- t : G1 and G1 |- B1 tags and G0 |- B0 tags and G0 |- s : G and G |- B tags then . |- G' = G1, G0, G2 and B' |- G' tags and G' |- s' : G *) fun abstractSubAll (t, B1, (G0, B0), s, B) = let (* skip'' (K, (G, B)) = K' Invariant: If G = x1:V1 .. xn:Vn and G |- B = ... tags then K' = K, BV (x1) .. BV (xn) *) fun skip'' (K, (I.Null, I.Null)) = K | skip'' (K, (I.Decl (G0, D), I.Decl(B0, T))) = I.Decl (skip'' (K, (G0, B0)), BV (D, T)) val collect2 = collectGlobalSub (G0, s, B, fn (_, K') => K') val collect0 = collectGlobalSub (I.Null, t, B1, fn (_, K') => K') val K0 = collect0 (0, I.Null) val K1 = skip'' (K0, (G0, B0)) val d = I.ctxLength G0 val K = collect2 (d, K1) in (abstractCtx K, abstractGlobalSub (K, s, B)) end (* abstractFor (K, depth, (F, s)) = F' F' = {{F[s]}}_K Invariant: If G |- s : G1 G1 |- U : V (U,s) is in whnf and K is internal context in dependency order and |G| = depth and K ||- U and K ||- V then {{K}}, G |- U' : V' and . ||- U' and . ||- V' and U' is in nf *) fun abstractFor (K, depth, (F.All (F.Prim D, F), s)) = F.All (F.Prim (abstractDec (K, depth, (D, s))), abstractFor (K, depth+1, (F, I.dot1 s))) | abstractFor (K, depth, (F.Ex (D, F), s)) = F.Ex (abstractDec (K, depth, (D, s)), abstractFor (K, depth+1, (F, I.dot1 s))) | abstractFor (K, depth, (F.True, s)) = F.True | abstractFor (K, depth, (F.And (F1, F2), s)) = F.And (abstractFor (K, depth, (F1, s)), abstractFor (K, depth, (F2, s))) (* abstract (Gx, F) = F' Invariant: If G, Gx |- F formula then G |- F' = {{Gx}} F formula *) fun allClo (I.Null, F) = F | allClo (I.Decl (Gx, D), F) = allClo (Gx, F.All (F.Prim D, F)) fun convert (I.Null) = I.Null | convert (I.Decl (G, D)) = I.Decl (convert G, BV (D, S.Parameter NONE)) fun createEmptyB 0 = I.Null | createEmptyB (n) = I.Decl (createEmptyB (n-1), S.None) fun lower (_, 0) = I.Null | lower (I.Decl (G, D), n) = I.Decl (lower (G, n-1), D) fun split (G, 0) = (G, I.Null) | split (I.Decl (G, D), n) = let val (G1, G2) = split (G, n-1) in (G1, I.Decl (G2, D)) end (* shift G = s' Invariant: Forall contexts G0: If |- G0, G ctx then G0, V, G |- s' : G0, G *) fun shift (I.Null) = I.shift | shift (I.Decl (G, _)) = I.dot1 (shift G) (* ctxSub (G, s) = G' Invariant: If G2 |- s : G1 and G1 |- G ctx then G2 |- G' = G[s] ctx *) fun ctxSub (nil, s) = nil | ctxSub (D :: G, s) = I.decSub (D, s) :: ctxSub (G, I.dot1 s) (* weaken2 (G, a, i, S) = w' Invariant: G |- w' : Gw Gw < G G |- S : {Gw} V > V *) fun weaken2 (I.Null, a, i) = (I.id, fn S => S) | weaken2 (I.Decl (G', D as I.Dec (name, V)), a, i) = let val (w', S') = weaken2 (G', a, i+1) in if Subordinate.belowEq (I.targetFam V, a) then (I.dot1 w', fn S => I.App (I.Root (I.BVar i, I.Nil), S)) else (I.comp (w', I.shift), S') end (* raiseType (G, V) = {{G}} V Invariant: If G |- V : L then . |- {{G}} V : L All abstractions are potentially dependent. *) fun raiseType (I.Null, V) = V | raiseType (I.Decl (G, D), V) = raiseType (G, Abstract.piDepend ((Whnf.normalizeDec (D, I.id), I.Maybe), V)) (* raiseFor (G, F, w, sc) = F' Invariant: If G0 |- G ctx and G0, G, GF |- F for and G0, {G} GF [...] |- w : G0 and sc maps (G0, GA |- w : G0, |GA|) to (G0, GA, G[..] |- s : G0, G, GF) then G0, {G} GF |- F' for *) fun raiseFor (k, Gorig, F as F.True, w, sc) = F | raiseFor (k, Gorig, F.Ex (I.Dec (name, V), F), w, sc) = let val G = F.listToCtx (ctxSub (F.ctxToList Gorig, w)) val g = I.ctxLength G val s = sc (w, k) (* G0, {G}GF[..], G |- s : G0, G, GF *) val V' = I.EClo (V, s) (* G0, {G}GF[..], G |- V' : type *) val (nw, S) = weaken2 (G, I.targetFam V, 1) (* G0, {G}GF[..], G |- nw : G0, {G}GF[..], Gw Gw < G *) val iw = Whnf.invert nw (* G0, {G}GF[..], Gw |- iw : G0, {G}GF[..], G *) val Gw = Whnf.strengthen (iw, G) (* Generalize the invariant for Whnf.strengthen --cs *) val V'' = Whnf.normalize (V', iw) (* G0, {G}GF[..], Gw |- V'' = V'[iw] : type*) val V''' = Whnf.normalize (raiseType (Gw, V''), I.id) (* G0, {G}GF[..] |- V''' = {Gw} V'' : type*) val S''' = S I.Nil (* G0, {G}GF[..], G[..] |- S''' : {Gw} V''[..] > V''[..] *) (* G0, {G}GF[..], G |- s : G0, G, GF *) val sc' = fn (w', k') => let (* G0, GA |- w' : G0 *) val s' = sc (w', k') (* G0, GA, G[..] |- s' : G0, G, GF *) in I.Dot (I.Exp (I.Root (I.BVar (g+k'-k), S''')), s') (* G0, GA, G[..] |- (g+k'-k). S', s' : G0, G, GF, V *) end val F' = raiseFor (k+1, Gorig, F, I.comp (w, I.shift), sc') in F.Ex (I.Dec (name, V'''), F') end | raiseFor (k, Gorig, F.All (F.Prim (I.Dec (name, V)), F), w, sc) = let (* val G = F.listToCtx (ctxSub (F.ctxToList Gorig, w)) val g = I.ctxLength G val s = sc (w, k) (* G0, {G}GF[..], G |- s : G0, G, GF *) val V' = Whnf.normalize (raiseType (G, Whnf.normalize (V, s)), I.id) (* G0, {G}GF[..] |- V' = {G}(V[s]) : type *) val S' = spine g (* G0, {G}GF[..] |- S' > {G}(V[s]) > V[s] *) val sc' = fn (w', k') => let (* G0, GA |- w' : G0 *) val s' = sc (w', k') (* G0, GA, G[..] |- s' : G0, G, GF *) in I.Dot (I.Exp (I.Root (I.BVar (g + k'-k), S')), s') (* G0, GA, G[..] |- g+k'-k. S', s' : G0, G, GF, V *) end val F' = raiseFor (k+1, Gorig, F, I.comp (w, I.shift), sc') in F.All (F.Prim (I.Dec (name, V')), F') *) val G = F.listToCtx (ctxSub (F.ctxToList Gorig, w)) val g = I.ctxLength G val s = sc (w, k) (* G0, {G}GF[..], G |- s : G0, G, GF *) val V' = I.EClo (V, s) (* G0, {G}GF[..], G |- V' : type *) val (nw, S) = weaken2 (G, I.targetFam V, 1) (* G0, {G}GF[..], G |- nw : G0, {G}GF[..], Gw Gw < G *) val iw = Whnf.invert nw (* G0, {G}GF[..], Gw |- iw : G0, {G}GF[..], G *) val Gw = Whnf.strengthen (iw, G) (* Generalize the invariant for Whnf.strengthen --cs *) val V'' = Whnf.normalize (V', iw) (* G0, {G}GF[..], Gw |- V'' = V'[iw] : type*) val V''' = Whnf.normalize (raiseType (Gw, V''), I.id) (* G0, {G}GF[..] |- V''' = {Gw} V'' : type*) val S''' = S I.Nil (* G0, {G}GF[..], G[..] |- S''' : {Gw} V''[..] > V''[..] *) (* G0, {G}GF[..], G |- s : G0, G, GF *) val sc' = fn (w', k') => let (* G0, GA |- w' : G0 *) val s' = sc (w', k') (* G0, GA, G[..] |- s' : G0, G, GF *) in I.Dot (I.Exp (I.Root (I.BVar (g+k'-k), S''')), s') (* G0, GA, G[..] |- (g+k'-k). S', s' : G0, G, GF, V *) end val F' = raiseFor (k+1, Gorig, F, I.comp (w, I.shift), sc') in F.All(F.Prim (I.Dec (name, V''')), F') end (* the other case of F.All (F.Block _, _) is not yet covered *) fun extend (K, nil) = K | extend (K, D :: L) = extend (I.Decl (K, BV (D, S.None)), L) (* makeFor (G, w, AF) = F' Invariant : If |- G ctx and G |- w : G' and G' |- AF approx for then G'; . |- F' = {EVARS} AF for *) fun makeFor (K, w, Head (G, (F, s), d)) = let val cf = collectGlobalSub (G, s, createEmptyB d, fn (_, K') => K') val k = I.ctxLength K val K' = cf (I.ctxLength G, K) val k' = I.ctxLength K' val (GK, BK) = abstractCtx K' val _ = if !Global.doubleCheck then TypeCheck.typeCheckCtx (GK) else () (* val _ = if !Global.doubleCheck then checkTags (GK, BK) else () *) val w' = I.comp (w, I.Shift (k'-k)) val FK = abstractFor (K', 0, (F, s)) val _ = if !Global.doubleCheck then FunTypeCheck.isFor (GK, FK) else () val (GK1, GK2) = split (GK, k'-k) in (GK1, allClo (GK2, FK)) end | makeFor (K, w, Block ((G, t, d, G2), AF)) = let val k = I.ctxLength K val collect = collectGlobalSub (G, t, createEmptyB d, fn (_, K') => K') val K' = collect (I.ctxLength G, K) (* BUG *) val k' = I.ctxLength K' val K'' = extend (K', G2) val w' = F.dot1n (F.listToCtx G2, I.comp (w, I.Shift (k'-k))) val (GK, F') = makeFor (K'', w', AF) val _ = if !Global.doubleCheck then FunTypeCheck.isFor (GK, F') else () val (GK1, GK2) = split (GK, List.length G2) val F'' = raiseFor (0, GK2, F', I.id, fn (w, _) => F.dot1n (GK2, w)) val _ = if !Global.doubleCheck then FunTypeCheck.isFor (GK1, F'') else () val (GK11, GK12) = split (GK1, k' - k) val F''' = allClo (GK12, F'') val _ = if !Global.doubleCheck then FunTypeCheck.isFor (GK11, F''') else () in (GK11, F''') end fun abstractApproxFor (AF as Head (G, _, _)) = let val (_, F) = makeFor (convert G, I.id, AF) in F end | abstractApproxFor (AF as Block ((G, _, _, _), _)) = let val (_, F) = makeFor (convert G, I.id, AF) in F end in val weaken = weaken val raiseType = raiseType val abstractSub = abstractSubAll val abstractSub' = abstractNew val abstractApproxFor = abstractApproxFor end end; (* functor MTPAbstract *)