{-# OPTIONS --injective-type-constructors #-}
module Algorithmic.Erasure where
open import Agda.Primitive using (lzero) open import Data.Nat using (ℕ) open import Function using (_∘_;id) open import Data.Nat using (_+_) open import Data.Nat.Properties using (+-cancelˡ-≡) open import Data.Fin using (Fin;zero;suc;toℕ) open import Data.List.Properties using (map-compose;map-id) open import Data.Vec using (Vec;lookup) open import Data.Product using () renaming (_,_ to _,,_) open import Relation.Binary.PropositionalEquality using (_≡_;refl;cong;subst;trans;sym;cong₂;cong-app) open import Data.Empty using (⊥) open import Data.Unit using (tt) open import Algorithmic as A open import Untyped using (_⊢) open _⊢ open import Type.BetaNormal using (_⊢Nf⋆_;_⊢Ne⋆_;ren-embNf;embNf) open _⊢Nf⋆_ open _⊢Ne⋆_ open import Type.BetaNBE using (nf;reflect;eval-VecList;lookup-eval-VecList ) open import Type.BetaNBE.Completeness using (completeness) open import Utils using (Kind;*;Maybe;nothing;just;fromList;map-cong) open import Utils.List using (List;IList;[];_∷_;map) open import RawU using (TmCon;tmCon;TyTag) open import Builtin.Signature using (_⊢♯) open _⊢♯ open import Builtin.Constant.Type open import Type using (Ctx⋆;∅;_,⋆_;_⊢⋆_;_∋⋆_;S;Z) open _⊢⋆_ open import Type.BetaNBE.RenamingSubstitution using (ren-nf;subNf-lemma') open import Type.BetaNBE.Stability using (stability) open import Builtin using (Builtin) open import Type.RenamingSubstitution as T import Declarative as D import Declarative.Erasure as D open import Algorithmic.Completeness using (nfCtx;nfTyVar;nfType;lemΠ;lem[];stability-μ;btype-lem;nfType-ConstrArgs;nfType-Cases;lemma-mkCaseType) open import Algorithmic.Soundness using (embCtx;embVar;emb;emb-ConstrArgs;lema-mkCaseType)
len⋆ : Ctx⋆ → Set
len⋆ ∅ = ⊥
len⋆ (Γ ,⋆ K) = Maybe (len⋆ Γ)
len : ∀{Φ} → Ctx Φ → Set
len ∅ = ⊥
len (Γ ,⋆ K) = len Γ
len (Γ , A) = Maybe (len Γ)
eraseVar : ∀{Φ Γ}{A : Φ ⊢Nf⋆ *} → Γ ∋ A → len Γ
eraseVar Z = nothing
eraseVar (S α) = just (eraseVar α)
eraseVar (T α) = eraseVar α
eraseTC : (A : ∅ ⊢Nf⋆ Kind.♯) → ⟦ A ⟧ → TmCon
eraseTC A t = tmCon (A.ty2sty A) (subst ⟦_⟧ (ty≅sty₁ A) t)
erase : ∀{Φ Γ}{A : Φ ⊢Nf⋆ *} → Γ ⊢ A → len Γ ⊢
erase-ConstrArgs : ∀ {Φ} {Γ : Ctx Φ}
{Ts : List (Φ ⊢Nf⋆ *)}
(cs : ConstrArgs Γ Ts)
→ List (len Γ ⊢)
erase-ConstrArgs [] = []
erase-ConstrArgs (c ∷ cs) = (erase c) ∷ (erase-ConstrArgs cs)
erase-Cases : ∀ {Φ} {Γ : Ctx Φ} {A : Φ ⊢Nf⋆ *} {n}
{Tss : Vec (List (Φ ⊢Nf⋆ *)) n}
(cs : Cases Γ A Tss) →
List (len Γ ⊢)
erase-Cases [] = []
erase-Cases (c ∷ cs) = (erase c) ∷ (erase-Cases cs)
erase (` α) = ` (eraseVar α)
erase (ƛ t) = ƛ (erase t)
erase (t · u) = erase t · erase u
erase (Λ t) = delay (erase t)
erase (t ·⋆ A / refl) = force (erase t)
erase (wrap A B t) = erase t
erase (unwrap t refl) = erase t
erase (con {A = A} t p) = con (eraseTC A t)
erase (builtin b / refl) = builtin b
erase (error A) = error
erase (constr e Tss p cs) = constr (toℕ e) (erase-ConstrArgs cs)
erase (case t cases) = case (erase t) (erase-Cases cases)
Porting this from declarative required basically deleting one line but I don’t think I can fully exploit this by parameterizing the module as I need to pattern match on the term constructors
lenLemma : ∀ {Φ}(Γ : D.Ctx Φ) → len (nfCtx Γ) ≡ D.len Γ
lenLemma D.∅ = refl
lenLemma (Γ D.,⋆ J) = lenLemma Γ
lenLemma (Γ D., A) = cong Maybe (lenLemma Γ)
lenLemma⋆ : ∀ Φ → D.len⋆ Φ ≡ len⋆ Φ
lenLemma⋆ ∅ = refl
lenLemma⋆ (Φ ,⋆ K) = cong Maybe (lenLemma⋆ Φ)
-- these lemmas for each clause of eraseVar and erase below could be
-- avoided by using with but it would involve doing with on a long
-- string of arguments, both contexts, equality proof above, and
-- before and after versions of all arguments and all recursive calls
-- these lemmas (as stated and proved) require injectivity of type
-- constructors
lemzero : ∀{X X'}(p : Maybe {lzero} X ≡ Maybe X') → nothing ≡ subst id p nothing
lemzero refl = refl
lemsuc : ∀{X X'}(p : Maybe {lzero} X ≡ Maybe X')(q : X ≡ X')(x : X) →
just (subst id q x) ≡ subst id p (just x)
lemsuc refl refl x = refl
lem≡Ctx : ∀{Φ}{Γ Γ' : Ctx Φ} → Γ ≡ Γ' → len Γ ≡ len Γ'
lem≡Ctx refl = refl
lem-conv∋ : ∀{Φ Γ Γ'}{A A' : Φ ⊢Nf⋆ *}(p : Γ ≡ Γ')(q : A ≡ A')(x : Γ A.∋ A)
→ subst id (lem≡Ctx p) (eraseVar x) ≡ eraseVar (conv∋ p q x)
lem-conv∋ refl refl x = refl
sameVar : ∀{Φ Γ}{A : Φ ⊢⋆ *}(x : Γ D.∋ A)
→ D.eraseVar x ≡ subst id (lenLemma Γ) (eraseVar (nfTyVar x))
sameVar {Γ = Γ D., _} D.Z = lemzero (cong Maybe (lenLemma Γ))
sameVar {Γ = Γ D., _} (D.S x) = trans
(cong just (sameVar x))
(lemsuc (cong Maybe (lenLemma Γ)) (lenLemma Γ) (eraseVar (nfTyVar x)))
sameVar {Γ = Γ D.,⋆ _} (D.T {A = A} x) = trans
(sameVar x)
(cong (subst id (lenLemma Γ)) (lem-conv∋ refl (ren-nf S A) (T (nfTyVar x))))
lemVar : ∀{X X'}(p : X ≡ X')(x : X) → ` (subst id p x) ≡ subst _⊢ p (` x)
lemVar refl x = refl
lemƛ : ∀{X X'}(p : X ≡ X')(q : Maybe X ≡ Maybe X')(t : Maybe X ⊢)
→ ƛ (subst _⊢ q t) ≡ subst _⊢ p (ƛ t)
lemƛ refl refl t = refl
lem· : ∀{X X'}(p : X ≡ X')(t u : X ⊢) → subst _⊢ p t · subst _⊢ p u ≡ subst _⊢ p (t · u)
lem· refl t u = refl
lem-delay : ∀{X X'}(p : X ≡ X')(t : X ⊢) → delay (subst _⊢ p t) ≡ subst _⊢ p (delay t)
lem-delay refl t = refl
lem-force : ∀{X X'}(p : X ≡ X')(t : X ⊢) → force (subst _⊢ p t) ≡ subst _⊢ p (force t)
lem-force refl t = refl
lemcon' : ∀{X X'}(p : X ≡ X')(tcn : TmCon) → con tcn ≡ subst _⊢ p (con tcn)
lemcon' refl tcn = refl
lemerror : ∀{X X'}(p : X ≡ X') → error ≡ subst _⊢ p error
lemerror refl = refl
lembuiltin : ∀{X X'}(b : Builtin)(p : X ≡ X') → builtin b ≡ subst _⊢ p (builtin b)
lembuiltin b refl = refl
lemConstr : ∀ {X X'}(e : ℕ) (xs : List (X ⊢))(p : X ≡ X')
→ subst _⊢ p (constr e xs) ≡ constr e (map (subst _⊢ p) xs)
lemConstr e [] refl = refl
lemConstr e (x ∷ xs) refl = cong (constr e) (cong (x ∷_) (sym (map-id xs)))
lemCase : ∀ {X X'}(t : X ⊢) (cs : List (X ⊢))(p : X ≡ X')
→ subst _⊢ p (case t cs) ≡ case (subst _⊢ p t) (map (subst _⊢ p) cs)
lemCase t cs refl = cong (case t) (sym (map-id cs))
lem-erase : ∀{Φ Γ Γ'}{A A' : Φ ⊢Nf⋆ *}(p : Γ ≡ Γ')(q : A ≡ A')(t : Γ A.⊢ A)
→ subst _⊢ (lem≡Ctx p) (erase t) ≡ erase (conv⊢ p q t)
lem-erase refl refl t = refl
lem-subst : ∀{n}(t : n ⊢)(p : n ≡ n) → subst _⊢ p t ≡ t
lem-subst t refl = refl
lem-erase' : ∀{Φ Γ}{A A' : Φ ⊢Nf⋆ *}(q : A ≡ A')(t : Γ A.⊢ A)
→ erase t ≡ erase (conv⊢ refl q t)
lem-erase' {Γ = Γ} p t = trans
(sym (lem-subst (erase t) (lem≡Ctx {Γ = Γ} refl)))
(lem-erase refl p t)
lem-erase'' : ∀{Φ Γ}{A A' : Φ ⊢Nf⋆ *}(q : A ≡ A')(t : Γ A.⊢ A)
→ erase t ≡ erase (subst (Γ A.⊢_) q t)
lem-erase'' refl t = refl
same : ∀{Φ Γ}{A : Φ ⊢⋆ *}(t : Γ D.⊢ A)
→ D.erase t ≡ subst _⊢ (lenLemma Γ) (erase (nfType t))
+cancel : ∀{m m' n n'} → m + n ≡ m' + n' → m ≡ m' → n ≡ n'
+cancel p refl = +-cancelˡ-≡ _ _ _ p
same-ConstrArgs : ∀{Φ}{Γ : D.Ctx Φ}{Ts : List (Φ ⊢⋆ *)}
(xs : D.ConstrArgs Γ Ts)
→ D.erase-ConstrArgs xs ≡ map (subst _⊢ (lenLemma Γ)) (erase-ConstrArgs (nfType-ConstrArgs xs))
same-ConstrArgs {Γ = Γ} [] = refl
same-ConstrArgs {Γ = Γ} (x ∷ xs) = cong₂ _∷_ (same x) (same-ConstrArgs xs)
same-mkCaseType : ∀ {Φ} {Γ : Ctx Φ} {A B : Φ ⊢Nf⋆ *}
(c : Γ ⊢ A)
(eq : A ≡ B)
→ erase {Φ} {Γ} { A } c ≡ erase {Φ} {Γ} { B } (subst (Γ ⊢_) eq c)
same-mkCaseType c refl = refl
same-Cases : ∀ {Φ} {Γ : D.Ctx Φ} {A : Φ ⊢⋆ *} {n}
{Tss : Vec (List (Φ ⊢⋆ *)) n}
(cases : D.Cases Γ A Tss) →
D.erase-Cases cases ≡
map (subst _⊢ (lenLemma Γ)) (erase-Cases (nfType-Cases cases))
same-Cases D.[] = refl
same-Cases {Γ = Γ}(D._∷_ {Ts = As} c cs) = cong₂ _∷_ (trans (same c)
(cong (subst _⊢ (lenLemma Γ)) (same-mkCaseType (nfType c) (lemma-mkCaseType As))))
(same-Cases cs)
same {Γ = Γ}(D.` x) =
trans (cong ` (sameVar x)) (lemVar (lenLemma Γ) (eraseVar (nfTyVar x)))
same {Γ = Γ} (D.ƛ t) = trans
(cong ƛ (same t))
(lemƛ (lenLemma Γ) (cong Maybe (lenLemma Γ)) (erase (nfType t)))
same {Γ = Γ} (t D.· u) = trans
(cong₂ _·_ (same t) (same u))
(lem· (lenLemma Γ) (erase (nfType t)) (erase (nfType u)))
same {Γ = Γ} (D.Λ {B = B} t) = trans
(trans (cong delay (same t))
(lem-delay (lenLemma Γ) (erase (nfType t))))
(cong (subst _⊢ (lenLemma Γ) ∘ delay)
(lem-erase' (subNf-lemma' B) (nfType t)))
same {Γ = Γ} (D._·⋆_ {B = B} t A) = trans
(trans (cong force (same t))
(lem-force (lenLemma Γ) (erase (nfType t))))
(cong (subst _⊢ (lenLemma Γ))
(trans (cong force (lem-erase' (lemΠ B) (nfType t)))
(lem-erase' (lem[] A B) (conv⊢ refl (lemΠ B) (nfType t) ·⋆ nf A / refl))))
same {Γ = Γ} (D.wrap A B t) = trans
(same t)
(cong (subst _⊢ (lenLemma Γ)) (lem-erase' (stability-μ A B) (nfType t)))
same {Γ = Γ} (D.unwrap {A = A}{B = B} t) = trans
(same t)
(cong
(subst _⊢ (lenLemma Γ))
(lem-erase' (sym (stability-μ A B)) (unwrap (nfType t) refl)))
same {Γ = Γ} (D.conv p t) = trans
(same t)
(cong (subst _⊢ (lenLemma Γ)) (lem-erase' (completeness p) (nfType t)))
same {Γ = Γ} (D.con {A = A} tcn p) = lemcon' (lenLemma Γ) (eraseTC (nf A) tcn)
same {Γ = Γ} (D.builtin b) = trans
(lembuiltin b (lenLemma Γ)) (cong (subst _⊢ (lenLemma Γ))
(lem-erase refl (btype-lem b) (builtin b / refl)))
same {Γ = Γ} (D.error A) = lemerror (lenLemma Γ)
same {Γ = Γ} (D.constr e Tss refl xs) rewrite lemConstr (toℕ e) (erase-ConstrArgs (nfType-ConstrArgs xs)) (lenLemma Γ)
= cong (constr (toℕ e)) (same-ConstrArgs xs)
same {Γ = Γ} (D.case t cases) rewrite lemCase (erase (nfType t)) (erase-Cases (Algorithmic.Completeness.nfType-Cases cases)) (lenLemma Γ)
= cong₂ case (same t) (same-Cases cases)
same'Len : ∀ {Φ}(Γ : A.Ctx Φ) → D.len (embCtx Γ) ≡ len Γ
same'Len ∅ = refl
same'Len (Γ ,⋆ J) = same'Len Γ
same'Len (Γ , A) = cong Maybe (same'Len Γ)
lem-Dconv∋ : ∀{Φ Γ Γ'}{A A' : Φ ⊢⋆ *}(p : Γ ≡ Γ')(q : A ≡ A')(x : Γ D.∋ A)
→ subst id (cong D.len p) (D.eraseVar x) ≡ D.eraseVar (D.conv∋ p q x)
lem-Dconv∋ refl refl x = refl
same'Var : ∀{Φ Γ}{A : Φ ⊢Nf⋆ *}(x : Γ A.∋ A)
→ eraseVar x ≡ subst id (same'Len Γ) (D.eraseVar (embVar x))
same'Var {Γ = Γ , _} Z = lemzero (cong Maybe (same'Len Γ))
same'Var {Γ = Γ , _} (S x) = trans
(cong just (same'Var x))
(lemsuc (cong Maybe (same'Len Γ)) (same'Len Γ) (D.eraseVar (embVar x)))
same'Var {Γ = Γ ,⋆ _} (T {A = A} x) = trans
(same'Var x)
(cong (subst id (same'Len Γ)) (lem-Dconv∋ refl (sym (ren-embNf S A))
(D.T (embVar x))))
same'TC : ∀ {Φ} {Γ : Ctx Φ} A (tcn : ⟦ A ⟧) →
eraseTC A tcn ≡ D.eraseTC (embNf A) (subst ⟦_⟧ (sym (stability A)) tcn)
same'TC A tcn rewrite stability A = refl
same' : ∀{Φ Γ}{A : Φ ⊢Nf⋆ *}(x : Γ A.⊢ A)
→ erase x ≡ subst _⊢ (same'Len Γ) (D.erase (emb x))
same'ConstrArgs : ∀ {Φ} {Γ : Ctx Φ}
{Ts : List (Φ ⊢Nf⋆ *)}
(xs : ConstrArgs Γ Ts)
→ erase-ConstrArgs xs ≡ map (subst _⊢ (same'Len Γ))
(D.erase-ConstrArgs (emb-ConstrArgs xs))
same'ConstrArgs [] = refl
same'ConstrArgs (x ∷ xs) = cong₂ _∷_ (same' x) (same'ConstrArgs xs)
same-subst : ∀ {Φ} {Γ : D.Ctx Φ} {A B : Φ ⊢⋆ *}
(c : Γ D.⊢ A)
(eq : A ≡ B)
→ D.erase c ≡ D.erase (subst (D._⊢_ Γ) eq c)
same-subst c refl = refl
same'Case : ∀ {Φ} {Γ : Ctx Φ} {A : Φ ⊢Nf⋆ *} {n}
{Tss : Vec (List (Φ ⊢Nf⋆ *)) n}
(cases : Cases Γ A Tss)
→ erase-Cases cases ≡ map (subst _⊢ (same'Len Γ))
(D.erase-Cases (Algorithmic.Soundness.emb-Cases cases))
same'Case [] = refl
same'Case {Γ = Γ} (_∷_ {Ts = As} c cases) =
cong₂ _∷_ (trans (same' c)
(cong (subst _⊢ (same'Len Γ)) (same-subst (emb c) (lema-mkCaseType As))))
(same'Case cases)
same' {Γ = Γ} (` x) =
trans (cong ` (same'Var x)) (lemVar (same'Len Γ) (D.eraseVar (embVar x)))
same' {Γ = Γ} (ƛ t) = trans
(cong ƛ (same' t))
(lemƛ (same'Len Γ) (cong Maybe (same'Len Γ)) (D.erase (emb t)))
same' {Γ = Γ} (t · u) = trans
(cong₂ _·_ (same' t) (same' u))
(lem· (same'Len Γ) (D.erase (emb t)) (D.erase (emb u)))
same' {Γ = Γ} (Λ t) = trans
(cong delay (same' t))
(lem-delay (same'Len Γ) (D.erase (emb t)))
same' {Γ = Γ} (t ·⋆ A / refl) = trans
(cong force (same' t))
(lem-force (same'Len Γ) (D.erase (emb t)))
same' (wrap A B t) = same' t
same' (unwrap t refl) = same' t
same' {Γ = Γ} (con {A = A} tcn refl) = trans (cong con (same'TC {Γ = Γ} A tcn))
(lemcon' (same'Len Γ) (D.eraseTC (embNf A) (subst ⟦_⟧ (sym (stability A)) tcn)))
same' {Γ = Γ} (builtin b / refl) = lembuiltin b (same'Len Γ)
same' {Γ = Γ} (error A) = lemerror (same'Len Γ)
same' {Γ = Γ} (constr e Tss {ts} refl xs) rewrite lemConstr (toℕ e) (D.erase-ConstrArgs (Algorithmic.Soundness.emb-ConstrArgs xs)) (same'Len Γ)
= cong (constr (toℕ e)) (same'ConstrArgs xs)
same' {Γ = Γ}(case t cases) rewrite lemCase (D.erase (emb t)) (D.erase-Cases (Algorithmic.Soundness.emb-Cases cases)) (same'Len Γ)
= cong₂ case (same' t) (same'Case cases)