{-# OPTIONS --without-K --safe #-}

module STLCSubst.Soundness where

open import Lib
open import STLCSubst.Statics
open import STLCSubst.Statics.Properties
open import STLCSubst.Semantics.Definitions

import Data.List.Properties as Lₚ
import Data.Nat.Properties as ℕₚ


weaken : Ctx  Wk
weaken Γ = repeat  (L.length Γ)

weaken⊢wk :  Δ  Δ ++ Γ ⊢w weaken Δ  Γ
weaken⊢wk []      = ⊢w-id
weaken⊢wk (T  Δ) = ⊢wk-∙ ⊢⇑ (weaken⊢wk Δ)

weaken-∙ :  Δ′ Δ  weaken Δ  weaken Δ′  weaken (Δ′ ++ Δ)
weaken-∙ [] Δ         = ≗.refl
weaken-∙ (T  Δ′) Δ x = cong suc (weaken-∙ Δ′ Δ x)

Pred : Set₁
Pred = Exp  D  Set

DPred : Set₁
DPred = Ctx  Pred

record TopPred Δ (ϕ : Wk) t a T : Set where
  field
    nf  : Nf
    ↘nf : Rf L.length Δ -  T a  nf
    ≈nf : Δ  t [ ϕ ]  Nf⇒Exp nf  T

record Top T Γ t a : Set where
  field
    t∶T  : Γ  t  T
    krip :  Δ  TopPred (Δ ++ Γ) (weaken Δ) t a T

record BotPred Δ (ϕ : Wk) t e T : Set where
  field
    neu : Ne
    ↘ne : Re L.length Δ - e  neu
    ≈ne : Δ  t [ ϕ ]  Ne⇒Exp neu  T

record Bot T Γ t e : Set where
  field
    t∶T  : Γ  t  T
    krip :  Δ  BotPred (Δ ++ Γ) (weaken Δ) t e T

record FunPred (B : DPred) Δ (ϕ : Wk) t f a s : Set where
  field
    fa   : D
    ↘fa  : f  a  fa
    $Bfa : B Δ ((t [ ϕ ]) $ s) fa

record ⟦_⊨[_]_⇒[_]_⟧ Γ S (A : DPred) T (B : DPred) t f : Set where
  field
    t∶S⟶T : Γ  t  S  T
    krip  :  Δ  A (Δ ++ Γ) s a  FunPred B (Δ ++ Γ) (weaken Δ) t f a s

[_]_⇒[_]_ : Typ  DPred  Typ  DPred  DPred
[ S ] A ⇒[ T ] B = ⟦_⊨[ S ] A ⇒[ T ] B 

⟦_⟧ : Typ  DPred
 N      = Top N
 S  T  = [ S ]  S  ⇒[ T ]  T 

⟦⟧⇒⊢ :  T   T  Γ t a  Γ  t  T
⟦⟧⇒⊢ N ⟦T⟧       = t∶T
  where open Top ⟦T⟧
⟦⟧⇒⊢ (S  T) ⟦T⟧ = t∶S⟶T
  where open ⟦_⊨[_]_⇒[_]_⟧ ⟦T⟧

Bot⇒TopN : Bot N Γ t e  Top N Γ t ( N e)
Bot⇒TopN bot = record
  { t∶T  = t∶T
  ; krip = λ σ 
    let open BotPred (krip σ) in
    record
    { nf  = ne neu
    ; ↘nf = Rne _ ↘ne
    ; ≈nf = ≈ne
    }
  }
  where open Bot bot

weaken-0-length :  Δ  weaken Δ 0  L.length Δ
weaken-0-length [] = refl
weaken-0-length (T  Δ) = cong suc (weaken-0-length Δ)

v⇒Bot-helper′ :  Δ (S : Typ) (Γ : Ctx)  v 0 [ weaken Δ ]  v (L.length (Δ ++ S  Γ)  L.length Γ  1)
v⇒Bot-helper′ Δ S Γ = begin
  v 0 [ weaken Δ ]
    ≡⟨ cong v (weaken-0-length Δ) 
  v (L.length Δ)
    ≡˘⟨ cong v (ℕₚ.m+n∸n≡m (L.length Δ) 1) 
  v ((L.length Δ) + 1  1)
    ≡˘⟨ cong  n  v ((L.length Δ) + n  1)) (ℕₚ.m+n∸n≡m 1 (L.length Γ)) 
  v ((L.length Δ) + (L.length (S  Γ)  L.length Γ)  1)
    ≡˘⟨ cong  n  v (n  1)) (ℕₚ.+-∸-assoc (L.length Δ) {suc (L.length Γ)} (ℕₚ.m≤n⇒m≤1+n ℕₚ.≤-refl)) 
  v ((L.length Δ + L.length (S  Γ))  L.length Γ  1)
    ≡˘⟨ cong  n  v (n  L.length Γ  1)) (Lₚ.length-++ Δ) 
  v (L.length (Δ ++ S  Γ)  L.length Γ  1) 
  where open ≡-Reasoning

v⇒Bot-helper :  Δ  Δ ++ S  Γ  v 0 [ weaken Δ ]  v (L.length (Δ ++ S  Γ)  L.length Γ  1)  S
v⇒Bot-helper {S} {Γ} Δ
  rewrite sym (v⇒Bot-helper′ Δ S Γ) = ≈-refl (⊢conv-subst (weaken⊢wk Δ) here)

v⇒Bot :  S Γ  Bot S (S  Γ) (v 0) (l (L.length Γ))
v⇒Bot S Γ = record
  { t∶T  = vlookup here
  ; krip = λ Δ  record
    { neu = v _
    ; ↘ne = Rl _ _
    ; ≈ne = v⇒Bot-helper Δ
    }
  }

mutual
  Bot⇒⟦⟧ :  T  Bot T Γ t e   T  Γ t ( T e)
  Bot⇒⟦⟧ N bot                   = Bot⇒TopN bot
  Bot⇒⟦⟧ {Γ} {t} {e} (S  T) bot = record
    { t∶S⟶T = t∶T
    ; krip  = λ Δ sSa  record
      { fa   = [ T ] _ $′  S _
      ; ↘fa  = $∙ S T _ _
      ; $Bfa = Bot⇒⟦⟧ T record
        { t∶T  = Λ-E (⊢wk-app t∶T (weaken⊢wk Δ)) (⟦⟧⇒⊢ S sSa)
        ; krip = λ Δ′ 
          let open BotPred (krip (Δ′ ++ Δ))
              module S = Top (⟦⟧⇒Top S sSa)
              open TopPred (S.krip Δ′) in
          record
          { neu = neu $ nf
          ; ↘ne = R$ _ (subst  l  Re L.length l - e  neu) (Lₚ.++-assoc Δ′ Δ Γ) ↘ne)
                       ↘nf
          ; ≈ne = $-cong (subst₂ (_⊢_≈ _  _)
                                 (Lₚ.++-assoc Δ′ Δ Γ)
                                 (trans (wk-transp t (≗.sym (weaken-∙ Δ′ Δ)))
                                        (sym (wk-app-comb t (weaken Δ) (weaken Δ′))))
                                 ≈ne)
                         ≈nf
          }
        }
      }
    }
    where open Bot bot

  ⟦⟧⇒Top :  T   T  Γ t a  Top T Γ t a
  ⟦⟧⇒Top N ⟦T⟧               = ⟦T⟧
  ⟦⟧⇒Top {Γ} {t} (S  T) ⟦T⟧ = record
    { t∶T  = t∶S⟶T
    ; krip = λ Δ 
      let vSl = Bot⇒⟦⟧ S (v⇒Bot S (Δ ++ Γ))
          open FunPred (krip (S  Δ) vSl)
          module T = Top (⟦⟧⇒Top T $Bfa)
          open TopPred (T.krip [])
      in
      record
      { nf  = Λ nf
      ; ↘nf =  _ ↘fa ↘nf
      ; ≈nf = ≈-trans (Λ-η (⊢wk-app t∶S⟶T (weaken⊢wk Δ)))
                      (Λ-cong (subst  x  _  x $ v 0  Nf⇒Exp nf  T)
                              (trans (wk-app-id (t [ weaken (S  Δ) ]))
                              (trans (wk-transp t (≗.sym (weaken-∙ (S  []) Δ)))
                                     (sym (wk-app-comb t (weaken Δ) (weaken (S  []))))))
                              ≈nf))
      }
    }
    where open ⟦_⊨[_]_⇒[_]_⟧ ⟦T⟧

⟦⟧-resp-trans :  T   T  Γ t a  Γ  t′  t  T   T  Γ t′ a
⟦⟧-resp-trans N       tTa t′≈ = record
  { t∶T  = ≈⇒⊢ t′≈
  ; krip = λ Δ 
    let open TopPred (krip Δ)
    in record
    { nf  = nf
    ; ↘nf = ↘nf
    ; ≈nf = ≈-trans (≈-resp-wk t′≈ (weaken⊢wk Δ))
                    ≈nf
    }
  }
  where open Top tTa
⟦⟧-resp-trans (S  T) tTa t′≈ = record
  { t∶S⟶T = ≈⇒⊢ t′≈
  ; krip  = λ Δ sSa 
    let open FunPred (krip Δ sSa)
    in record
    { fa   = fa
    ; ↘fa  = ↘fa
    ; $Bfa = ⟦⟧-resp-trans T $Bfa ($-cong (≈-resp-wk t′≈ (weaken⊢wk Δ)) (≈-refl (⟦⟧⇒⊢ S sSa)))
    }
  }
  where open ⟦_⊨[_]_⇒[_]_⟧ tTa


⟦⟧-weaken :  Δ T   T  Γ t a   T  (Δ ++ Γ) (t [ weaken Δ ]) a
⟦⟧-weaken {Γ} {t} [] T tTa
  rewrite wk-app-id t                      = tTa
⟦⟧-weaken {Γ} {t} {a} (S  Δ) N tTa        =
  let t∶T = ⟦⟧⇒⊢ N tTa
  in record
  { t∶T  = ⊢wk-app t∶T (weaken⊢wk (S L.∷ Δ))
  ; krip = λ Δ′ 
    let open TopPred (krip (Δ′ ++ S  []))
        assoc-eq  = Lₚ.++-assoc Δ′ (S  []) (Δ ++ Γ)
        assoc-eq′ = Lₚ.++-assoc Δ′ (S  []) Δ
    in record
      { nf  = nf
      ; ↘nf = subst  l  Rf L.length l -  N a  nf) assoc-eq ↘nf
      ; ≈nf = subst₂ (_⊢_≈ Nf⇒Exp nf  N)
                     assoc-eq
                     (trans (wk-app-comb t (weaken Δ) (weaken (Δ′ ++ S  [])))
                     (trans (wk-transp t (weaken-∙ (Δ′ ++ S  []) Δ))
                     (trans (cong  Γ  t [ weaken Γ ]) assoc-eq′)
                     (trans (sym (wk-transp t (weaken-∙ Δ′ (S  Δ))))
                            (sym (wk-app-comb t (weaken (S  Δ)) (weaken Δ′)))))))
                     ≈nf
      }
  }
  where open Top (⟦⟧-weaken Δ N tTa)
⟦⟧-weaken {Γ} {t} {a} (S  Δ) (T′  T) tTa =
  let t∶T = ⟦⟧⇒⊢ (T′  T) tTa
  in record
  { t∶S⟶T = ⊢wk-app t∶T (weaken⊢wk (S  Δ))
  ; krip  = λ Δ′ sT′b 
    let assoc-eq  = Lₚ.++-assoc Δ′ (S  []) (Δ ++ Γ)
        assoc-eq′ = Lₚ.++-assoc Δ′ (S  []) Δ
        open FunPred (krip (Δ′ ++ S  []) (subst  l   T′  l _ _) (sym assoc-eq) sT′b))
    in record
      { fa   = fa
      ; ↘fa  = ↘fa
      ; $Bfa = subst₂  a b   T  a b fa)
                      assoc-eq
                      (cong (_$ _)
                            (trans (wk-app-comb t (weaken Δ) (weaken (Δ′ ++ S  [])))
                            (trans (wk-transp t (weaken-∙ (Δ′ ++ S  []) Δ))
                            (trans (cong  Γ  t [ weaken Γ ]) assoc-eq′)
                            (trans (sym (wk-transp t (weaken-∙ Δ′ (S  Δ))))
                                   (sym (wk-app-comb t (weaken (S  Δ)) (weaken Δ′))))))))
                      $Bfa
      }
  }
  where open ⟦_⊨[_]_⇒[_]_⟧ (⟦⟧-weaken Δ (T′  T) tTa)

infix 4 _∼_∈⟦_⟧_ _⊨_∶_
record _∼_∈⟦_⟧_ σ (ρ : Env) Γ Δ : Set where
  field
    ⊢σ   : Δ ⊢s σ  Γ
    lkup :  {x T}  x  T  Γ   T  Δ (v x [ σ ]) (ρ x)

record Intp Δ (σ : Subst) ρ t T : Set where
  field
    ⟦t⟧  : D
    ↘⟦t⟧ :  t  ρ  ⟦t⟧
    tT   :  T  Δ (t [ σ ]) ⟦t⟧

_⊨_∶_ : Ctx  Exp  Typ  Set
Γ  t  T =  {σ ρ Δ}  σ  ρ ∈⟦ Γ  Δ  Intp Δ σ ρ t T

∼-ext :  Δ′  σ  ρ ∈⟦ Γ  Δ   T  (Δ′ ++ Δ) t a  ((σ [ weaken Δ′ ])  t)  ρ  a ∈⟦ T  Γ  Δ′ ++ Δ
∼-ext Δ′ σ∼ρ tTa = record
  { ⊢σ   = ⊢ext (⊢wk-subst (_∼_∈⟦_⟧_.⊢σ σ∼ρ) (weaken⊢wk Δ′)) (⟦⟧⇒⊢ _ tTa)
  ; lkup = helper Δ′ σ∼ρ tTa
  }
  where helper :  {x} Δ′  σ  ρ ∈⟦ Γ  Δ   T  (Δ′ ++ Δ) t a  x  S  T  Γ   S  (Δ′ ++ Δ) (v x [ (σ [ weaken Δ′ ])  t ]) ((ρ  a) x)
        helper {S = S} Δ′ σ∼ρ tTa here                = tTa
        helper {T = T} {S = S} Δ′ σ∼ρ tTa (there S∈Γ) = ⟦⟧-weaken Δ′ S (lkup S∈Γ)
          where open _∼_∈⟦_⟧_ σ∼ρ

id-Init :  Γ  id  InitialEnv Γ ∈⟦ Γ  Γ
id-Init []      = record
  { ⊢σ   = ⊢id
  ; lkup = λ { () }
  }
id-Init (T  Γ) = record
  { ⊢σ   = ⊢id
  ; lkup = helper
  }
  where open _∼_∈⟦_⟧_ (id-Init Γ)
        helper :  {x}  x  S  T  Γ   S  (T  Γ) (v x [ v ]) (InitialEnv (T  Γ) x)
        helper here            = Bot⇒⟦⟧ T (v⇒Bot T Γ)
        helper {S} (there S∈Γ) = ⟦⟧-weaken (T  []) S (lkup S∈Γ)

⊨⇒⊢ : Γ  t  T 
      -------------
      Γ  t  T
⊨⇒⊢ {Γ} {t} {T} t∶T = helper (⟦⟧⇒⊢ T tT)
  where open Intp (t∶T (id-Init _))
        helper : Γ  t [ v ]  T  Γ  t  T
        helper ⊢t
          rewrite subst-app-id t = ⊢t

vlookup′ :  {x} 
           x  T  Γ 
           -----------------
           Γ  v x  T
vlookup′ T∈Γ σ∼ρ = record
  { ⟦t⟧  = _
  ; ↘⟦t⟧ = ⟦v⟧ _
  ; tT   = lkup T∈Γ
  }
  where open _∼_∈⟦_⟧_ σ∼ρ

ze-I′ : Γ  ze  N
ze-I′ σ∼ρ = record
  { ⟦t⟧  = ze
  ; ↘⟦t⟧ = ⟦ze⟧
  ; tT   = record
    { t∶T = ze-I
    ; krip = λ Δ  record
      { nf  = ze
      ; ↘nf = Rze (L.length (Δ ++ _))
      ; ≈nf = ze-≈
      }
    }
  }
  where open _∼_∈⟦_⟧_ σ∼ρ

su-I′ : Γ  t  N 
        ---------------
        Γ  su t  N
su-I′ t σ∼ρ = record
  { ⟦t⟧  = su ⟦t⟧
  ; ↘⟦t⟧ = ⟦su⟧ ↘⟦t⟧
  ; tT   =
    record
    { t∶T  = su-I t∶T
    ; krip = λ Δ 
      let open TopPred (krip Δ)
      in record
      { nf  = su nf
      ; ↘nf = Rsu _ ↘nf
      ; ≈nf = su-cong ≈nf
      }
    }
  }
  where open _∼_∈⟦_⟧_ σ∼ρ
        open Intp (t σ∼ρ)
        open Top tT

Λ-I′ : S  Γ  t  T 
       ------------------
       Γ  Λ t  S  T
Λ-I′ {S} {_} {t} {T} ⊨t {σ} {_} {Δ′} σ∼ρ =
  let t∶T = ⊨⇒⊢ ⊨t
  in record
  { ⟦t⟧  = Λ _ _
  ; ↘⟦t⟧ = ⟦Λ⟧ _
  ; tT   = record
    { t∶S⟶T = ⊢subst-app (Λ-I t∶T) ⊢σ
    ; krip  = λ {s} Δ sSa 
      let open Intp (⊨t (∼-ext _ σ∼ρ sSa))
          s∶S = ⟦⟧⇒⊢ S sSa
          s≈s = ≈-refl s∶S
      in record
      { fa   = ⟦t⟧
      ; ↘fa  = Λ∙ ↘⟦t⟧
      ; $Bfa = ⟦⟧-resp-trans T tT
                             (subst₂  x y  Δ ++ Δ′  x $ s  y  T)
                                    (sym (wk-app-subst (Λ t) σ (weaken Δ)))
                                    (subst-q-ext₁ t s (σ [ weaken Δ ]))
                                    (Λ-β (⊢subst-app t∶T (⊢subst-q S (⊢wk-subst ⊢σ (weaken⊢wk Δ)))) s∶S))
      }
    }
  }
  where open _∼_∈⟦_⟧_ σ∼ρ

TopPred-su : Γ  t  N 
             TopPred (Δ ++ Γ) (weaken Δ) (su t) (su a) N 
             TopPred (Δ ++ Γ) (weaken Δ) t a N
TopPred-su {_} {t} {Δ} ⊢t record { nf = su a ; ↘nf = (Rsu ._ ↘nf) ; ≈nf = ≈nf } = record
  { nf  = a
  ; ↘nf = ↘nf
  ; ≈nf = inv-su-≈ ≈nf
  }

N-E-helper :  T 
             σ  ρ ∈⟦ Γ  Δ 
             (s′ : Intp Δ σ ρ s T) 
             Γ  s  T 
             T  N  Γ  r  T 
             Δ  Nf⇒Exp w  N 
             (∀ Δ′  TopPred (Δ′ ++ Δ) (weaken Δ′) (Nf⇒Exp w) b N) 
             Rf L.length Δ -  N b  w 
              λ a  rec T , Intp.⟦t⟧ s′ , r , ρ , b  a ×  T  Δ (rec T (s [ σ ]) (r [ q (q σ) ]) (Nf⇒Exp w)) a
N-E-helper {σ} {_} {_} {_} {s} {r} T σ∼ρ s′ ⊢s r′ ⊢w k (Rze _)
  = s.⟦t⟧
  , rze
  , ⟦⟧-resp-trans T
                  s.tT
                  (rec-β-ze (⊢subst-app ⊢s ⊢σ) (⊢subst-app ⊢r (⊢subst-q T (⊢subst-q N ⊢σ))))
  where module s = Intp s′
        open _∼_∈⟦_⟧_ σ∼ρ
        ⊢r = ⊨⇒⊢ r′
N-E-helper {σ} {_} {_} {Δ} {s} {r} {su w} T σ∼ρ s′ ⊢s r′ (su-I ⊢w) k (Rsu {n} _ ↘w)
  with N-E-helper T σ∼ρ s′ ⊢s r′ ⊢w  Δ′  TopPred-su ⊢w (k Δ′)) ↘w
...  | a , ↘a , Ta
  = r′.⟦t⟧
  , rsu ↘a r′.↘⟦t⟧
  , ⟦⟧-resp-trans T
                  r′.tT
                  (subst (Δ  rec T _ _ _ ≈_∶ T)
                         (begin
                           r [ q (q σ) ] [ id  Nf⇒Exp w  rec T (s [ σ ]) (r [ q (q σ) ]) (Nf⇒Exp w) ]
                             ≡⟨ subst-q-ext₂ r (Nf⇒Exp w) (rec T (s [ σ ]) (r [ q (q σ) ]) (Nf⇒Exp w)) σ 
                           r [ σ  Nf⇒Exp w  rec T (s [ σ ]) (r [ q (q σ) ]) (Nf⇒Exp w) ]
                             ≡˘⟨ subst-transp r (subst-ext-cong (subst-ext-cong (subst-wk-id σ) refl) refl) 
                           r [ σ [ id ]  Nf⇒Exp w  rec T (s [ σ ]) (r [ q (q σ) ]) (Nf⇒Exp w) ]
                             ≡˘⟨ subst-transp r (subst-ext-cong (subst-wk-id (σ [ id ]  Nf⇒Exp w)) refl) 
                           r [ (σ [ id ]  Nf⇒Exp w) [ id ]  rec T (s [ σ ]) (r [ q (q σ) ]) (Nf⇒Exp w) ]
                             )
                         (rec-β-su (⊢subst-app ⊢s ⊢σ) (⊢subst-app ⊢r (⊢subst-q T (⊢subst-q N ⊢σ))) ⊢w))
  where module s = Intp s′
        σw∼ρb   = ∼-ext {T = N} [] σ∼ρ record { t∶T = ⊢w ; krip = λ Δ′  TopPred-su ⊢w (k Δ′) }
        σwr∼ρba = ∼-ext {T = T} [] σw∼ρb Ta
        module r′ = Intp (r′ σwr∼ρba)
        ⊢r = ⊨⇒⊢ r′
        open _∼_∈⟦_⟧_ σ∼ρ
        open ≡-Reasoning
N-E-helper {σ} {_} {_} {Δ} {s} {r} T σ∼ρ s′ ⊢s r′ ⊢w k (Rne {e} {u} _ ↘e)
  = rec′ T T ( T s.⟦t⟧) r _ e
  , rec
  , Bot⇒⟦⟧ T record
  { t∶T  = N-E (⊢subst-app ⊢s ⊢σ) (⊢subst-app ⊢r (⊢subst-q T (⊢subst-q N ⊢σ))) ⊢w
  ; krip = λ Δ′ 
    let σ∼ρN  = ∼-ext {T = N} (N  Δ′) σ∼ρ (Bot⇒⟦⟧ N (v⇒Bot N (Δ′ ++ Δ)))
        σ∼ρNT = ∼-ext {T = T} (T  []) σ∼ρN (Bot⇒⟦⟧ T (v⇒Bot T (N  Δ′ ++ Δ))) -- (Bot⇒⟦⟧ T {!(v⇒Bot T (N ∷ Δ′ ++ Δ))!})
        module r′ = Intp (r′ σ∼ρNT)
        module r′Top = Top (⟦⟧⇒Top T r′.tT)
        neu , ↘ne , ≈ne = helper Δ′ (k Δ′)
        open ≡-Reasoning
    in record
    { neu = rec T (TopPred.nf (s.krip Δ′)) (TopPred.nf (r′Top.krip L.[])) neu
    ; ↘ne = Rr _ (s.k.↘nf Δ′) r′.↘⟦t⟧ (TopPred.↘nf (r′Top.krip [])) ↘ne
    ; ≈ne = rec-cong (s.k.≈nf Δ′)
                     (subst (_ ⊢_≈ Nf⇒Exp (TopPred.nf (r′Top.krip []))  T)
                            (begin
                              r [ (σ [ weaken (N  Δ′) ]  v 0) [  ]  v 0 ] [ weaken [] ]
                                ≡⟨ wk-app-id (r [ (σ [ weaken (N  Δ′) ]  v 0) [  ]  v 0 ]) 
                              r [ (σ [ weaken (N  Δ′) ]  v 0) [  ]  v 0 ]
                                ≡˘⟨ subst-transp r (subst-q-equiv (σ [ weaken (N  Δ′) ]  v 0)) 
                              r [ q (σ [ weaken (N  Δ′) ]  v 0) ]
                                ≡˘⟨ subst-transp r (subst-q-cong (subst-ext-cong  x  wk-transp (σ x) (weaken-∙ (N  []) Δ′)) refl)) 
                              r [ q (σ [ weaken Δ′   ]  v 0) ]
                                ≡˘⟨ subst-transp r (subst-q-cong (subst-ext-cong  x  wk-app-comb (σ x) (weaken Δ′) ) refl)) 
                              r [ q (σ [ weaken Δ′ ] [  ]  v 0) ]
                                ≡˘⟨ subst-transp r (subst-q-cong (subst-q-equiv (σ [ weaken Δ′ ]))) 
                              r [ q (q (σ [ weaken Δ′ ])) ]
                                ≡˘⟨ subst-transp r (wk-subst-q₂ σ (weaken Δ′)) 
                              r [ q (q σ) [ q (q (weaken Δ′)) ] ]
                                ≡˘⟨ wk-app-subst r (q (q σ)) (q (q (weaken Δ′))) 
                              r [ q (q σ) ] [ q (q (weaken Δ′)) ]
                                )
                            (TopPred.≈nf (r′Top.krip [])))
                     ≈ne
    }
  }
  where module s where
          open Intp s′ public
          open Top (⟦⟧⇒Top T tT) public
          module k Δ = TopPred (krip Δ)
        ⊢r = ⊨⇒⊢ r′
        helper :  {T} Δ′  TopPred (Δ′ ++ Δ) (weaken Δ′) (Ne⇒Exp u) ( T e) N 
                  λ neu  Re L.length (Δ′ ++ Δ) - e  neu × Δ′ ++ Δ  Ne⇒Exp u [ weaken Δ′ ]  Ne⇒Exp neu  N
        helper Δ′ record { nf = .(ne _) ; ↘nf = (Rne ._ ↘ne) ; ≈nf = ≈nf } = _ , ↘ne , ≈nf
        open _∼_∈⟦_⟧_ σ∼ρ

N-E′ : Γ  s  T 
       T  N  Γ  r  T 
       Γ  t  N 
       ----------------------
       Γ  rec T s r t  T
N-E′ {_} {s} {T} {r} {t} ⊨s ⊨r ⊨t {σ} {_} {Δ} σ∼ρ =
  let a , ↘a , nfTa = N-E-helper T σ∼ρ (⊨s σ∼ρ) (⊨⇒⊢ ⊨s) ⊨r (≈⇒⊢′ ≈nf) helper ↘nf
  in record
  { ⟦t⟧  = a
  ; ↘⟦t⟧ = ⟦rec⟧ s.↘⟦t⟧ t.↘⟦t⟧ ↘a
  ; tT   = ⟦⟧-resp-trans T
                         nfTa
                         (rec-cong (≈-refl ((⊢subst-app ⊢s ⊢σ)))
                                   (≈-refl ((⊢subst-app ⊢r (⊢subst-q T (⊢subst-q N ⊢σ)))))
                                   (subst (_ ⊢_≈ _  _) (wk-app-id (t [ σ ])) ≈nf))
  }
  where module s = Intp (⊨s σ∼ρ)
        module t = Intp (⊨t σ∼ρ)
        open Top t.tT
        open _∼_∈⟦_⟧_ σ∼ρ
        ⊢s = ⊨⇒⊢ ⊨s
        ⊢r = ⊨⇒⊢ ⊨r
        ⊢t = ⊨⇒⊢ ⊨t

        helper :  Δ′  TopPred (Δ′ ++ Δ) (weaken Δ′) (Nf⇒Exp (TopPred.nf (krip []))) t.⟦t⟧ N
        helper Δ′ = record
          { nf = nf
          ; ↘nf = ↘nf
          ; ≈nf = begin
            Nf⇒Exp k.nf [ weaken Δ′ ]   ≈˘⟨ ≈-resp-wk (subst (_ ⊢_≈ _  _) (wk-app-id (t [ σ ])) k.≈nf) (weaken⊢wk Δ′) 
            t [ σ ] [ weaken Δ′ ]       ≈⟨ ≈nf 
            Nf⇒Exp nf                   
          }
          where module k = TopPred (krip [])
                open TopPred (krip Δ′)
                open TR

        open TopPred (krip [])

Λ-E′ : Γ  r  S  T 
       Γ  s  S 
       -----------------
       Γ  r $ s  T
Λ-E′ {_} {r} {_} {T} {s} ⊨r ⊨s {σ} σ∼ρ = record
  { ⟦t⟧  = fa
  ; ↘⟦t⟧ = ⟦$⟧ r.↘⟦t⟧ s.↘⟦t⟧ ↘fa
  ; tT   = subst  x   T  _ (x $ _) _) (wk-app-id (r [ σ ])) $Bfa
  }
  where open _∼_∈⟦_⟧_ σ∼ρ
        module r = Intp (⊨r σ∼ρ)
        module s = Intp (⊨s σ∼ρ)
        open ⟦_⊨[_]_⇒[_]_⟧ r.tT
        open FunPred (krip [] s.tT)



fundamental : Γ  t  T  Γ  t  T
fundamental (vlookup T∈Γ) = vlookup′ T∈Γ
fundamental ze-I          = ze-I′
fundamental (su-I t)      = su-I′ (fundamental t)
fundamental (N-E s r t)   = N-E′ (fundamental s) (fundamental r) (fundamental t)
fundamental (Λ-I t)       = Λ-I′ (fundamental t)
fundamental (Λ-E r s)     = Λ-E′ (fundamental r) (fundamental s)

record Soundness Γ ρ t T : Set where
  field
    nf  : Nf
    nbe : Nbe (L.length Γ) ρ t T nf
    ≈nf : Γ  t  Nf⇒Exp nf  T

soundness : Γ  t  T  Soundness Γ (InitialEnv Γ) t T
soundness {Γ} {t} {T} ⊢t = record
  { nf  = nf
  ; nbe = record
    { ⟦t⟧  = ⟦t⟧
    ; ↘⟦t⟧ = ↘⟦t⟧
    ; ↓⟦t⟧ = ↘nf
    }
  ; ≈nf = subst (_ ⊢_≈ Nf⇒Exp nf  _) (trans (wk-app-id (t [ v ])) (subst-app-id t)) ≈nf
  }
  where open Intp (fundamental ⊢t (id-Init Γ))
        open Top (⟦⟧⇒Top T tT)
        open TopPred (krip [])

nbe-comp : Γ  t  T   λ w  Nbe (L.length Γ) (InitialEnv Γ) t T w
nbe-comp t = nf , nbe
  where open Soundness (soundness t)