module A201802.LR3 where
open import A201801.Prelude
open import A201801.Category
open import A201801.Fin
open import A201801.FinLemmas
open import A201801.Vec
open import A201801.VecLemmas
open import A201801.AllVec
open import A201802.LR0
open import A201802.LR0Lemmas
open import A201802.LR1
open import A201802.LR2
postulate
oops : ∀ {ℓ} {X : Set ℓ} → X
mutual
SN : Term 0 → Type → Set
SN M A = ∙ ⊢ M ⦂ A × M ⇓ × SN! M A
SN! : Term 0 → Type → Set
SN! M 𝔹 = ⊤
SN! M (A ∨ B) = oops
SN! M 𝟘 = ⊥
SN! M 𝟙 = ⊤
SN! M (A ∧ B) = SN (FST M) A × SN (SND M) B
SN! M (A ⊃ B) = ∀ {N} → SN N A → SN (APP M N) B
derp : ∀ {A M} → SN M A
→ ∙ ⊢ M ⦂ A
derp (𝒟 , M⇓ , s!) = 𝒟
SNs : ∀ {g} → (τ : Terms 0 g) → Types g → Set
SNs τ Γ = All (\ { (M , A) → SN M A }) (zip τ Γ)
derps : ∀ {g} → {τ : Terms 0 g} {Γ : Types g}
→ SNs τ Γ
→ ∙ ⊢ τ ⦂ Γ all
derps σ = maps derp σ
mutual
snpr↦ : ∀ {A M M′} → M ↦ M′ → ∙ ⊢ M ⦂ A → SN M′ A
→ SN M A
snpr↦ M↦M′ 𝒟 (𝒟′ , M′⇓ , s!′) = 𝒟 , hpr↦ M↦M′ M′⇓ , sn!pr↦ M↦M′ 𝒟 s!′
sn!pr↦ : ∀ {A M M′} → M ↦ M′ → ∙ ⊢ M ⦂ A → SN! M′ A
→ SN! M A
sn!pr↦ {𝔹} M↦M′ 𝒟 ∙ = ∙
sn!pr↦ {A ∨ B} M↦M′ 𝒟 x = oops
sn!pr↦ {𝟘} M↦M′ 𝒟 ()
sn!pr↦ {𝟙} M↦M′ 𝒟 ∙ = ∙
sn!pr↦ {A ∧ B} M↦M′ 𝒟 (s₁ , s₂) = snpr↦ (cong-fst M↦M′) (fst 𝒟) s₁ , snpr↦ (cong-snd M↦M′) (snd 𝒟) s₂
sn!pr↦ {A ⊃ B} M↦M′ 𝒟 f s = snpr↦ (cong-app₁ M↦M′) (app 𝒟 (derp s)) (f s)
snpr⤅ : ∀ {A M M′} → M ⤅ M′ → ∙ ⊢ M ⦂ A → SN M′ A
→ SN M A
snpr⤅ done 𝒟 s = s
snpr⤅ (step M↦M″ M″⤅M′) 𝒟 s = snpr↦ M↦M″ 𝒟 (snpr⤅ M″⤅M′ (tp↦ M↦M″ 𝒟) s)
snpr⇓ : ∀ {A M M′} → M ⇓ M′ → ∙ ⊢ M ⦂ A → SN M′ A
→ SN M A
snpr⇓ (M⤅M′ , VM′) 𝒟 s = snpr⤅ M⤅M′ 𝒟 s
mutual
snp↦ : ∀ {A M M′} → M ↦ M′ → ∙ ⊢ M ⦂ A → SN M A
→ SN M′ A
snp↦ M↦M′ 𝒟 (_ , M⇓ , s!) = tp↦ M↦M′ 𝒟 , hp↦ M↦M′ M⇓ , sn!p↦ M↦M′ 𝒟 s!
sn!p↦ : ∀ {A M M′} → M ↦ M′ → ∙ ⊢ M ⦂ A → SN! M A
→ SN! M′ A
sn!p↦ {𝔹} M↦M′ 𝒟 ∙ = ∙
sn!p↦ {A ∨ B} M↦M′ 𝒟 x = oops
sn!p↦ {𝟘} M↦M′ 𝒟 ()
sn!p↦ {𝟙} M↦M′ 𝒟 ∙ = ∙
sn!p↦ {A ∧ B} M↦M′ 𝒟 (s₁ , s₂) = snp↦ (cong-fst M↦M′) (fst 𝒟) s₁ , snp↦ (cong-snd M↦M′) (snd 𝒟) s₂
sn!p↦ {A ⊃ B} M↦M′ 𝒟 f s = snp↦ (cong-app₁ M↦M′) (app 𝒟 (derp s)) (f s)
snp⤅ : ∀ {A M M′} → M ⤅ M′ → ∙ ⊢ M ⦂ A → SN M A
→ SN M′ A
snp⤅ done 𝒟 s = s
snp⤅ (step M↦M″ M″⤅M′) 𝒟 s = snp⤅ M″⤅M′ (tp↦ M↦M″ 𝒟) (snp↦ M↦M″ 𝒟 s)
snp⇓ : ∀ {A M M′} → M ⇓ M′ → ∙ ⊢ M ⦂ A → SN M A
→ SN M′ A
snp⇓ (M⤅M′ , VM′) 𝒟 s = snp⤅ M⤅M′ 𝒟 s
sn-pair : ∀ {A B M N} → SN M A → SN N B
→ SN (PAIR M N) (A ∧ B)
sn-pair s₁@(𝒟 , M⇓@(M′ , M⇓M′@(M⤅M′ , VM′)) , s!₁) s₂@(ℰ , N⇓@(N′ , N⇓N′@(N⤅N′ , VN′)) , s!₂)
= pair 𝒟 ℰ ,
halt-pair M⇓ N⇓ ,
snpr⇓ (big-red-fst-pair {{VM′}} {{VN′}} (congs-pair {{VM′}} {{VN′}} M⤅M′ N⤅N′)) (fst (pair 𝒟 ℰ)) (snp⤅ M⤅M′ 𝒟 s₁) ,
snpr⇓ (big-red-snd-pair {{VM′}} {{VN′}} ((congs-pair {{VM′}} {{VN′}} M⤅M′ N⤅N′))) (snd (pair 𝒟 ℰ)) (snp⤅ N⤅N′ ℰ s₂)
mutual
sn-fst : ∀ {A B M} → SN M (A ∧ B)
→ SN (FST M) A
sn-fst (𝒟 , M⇓ , s!) = fst 𝒟 , halt-fst 𝒟 M⇓ , sn!-fst s!
sn!-fst : ∀ {A B M} → SN! M (A ∧ B)
→ SN! (FST M) A
sn!-fst {𝔹} _ = ∙
sn!-fst {A₁ ∨ A₂} x = oops
sn!-fst {𝟘} ()
sn!-fst {𝟙} _ = ∙
sn!-fst {A₁ ∧ A₂} ((ℰ , FST⇓ , s) , _) = s
sn!-fst {A₁ ⊃ A₂} ((ℰ , FST⇓ , f) , _) s = f s
mutual
sn-snd : ∀ {A B M} → SN M (A ∧ B)
→ SN (SND M) B
sn-snd (𝒟 , M⇓ , s!) = snd 𝒟 , halt-snd 𝒟 M⇓ , sn!-snd s!
sn!-snd : ∀ {B A M} → SN! M (A ∧ B)
→ SN! (SND M) B
sn!-snd {𝔹} _ = ∙
sn!-snd {B₁ ∨ B₂} x = oops
sn!-snd {𝟘} ()
sn!-snd {𝟙} _ = ∙
sn!-snd {B₁ ∧ B₂} (_ , (ℰ , SND⇓ , s)) = s
sn!-snd {B₁ ⊃ B₂} (_ , (ℰ , SND⇓ , f)) s = f s
mutual
sn-abort : ∀ {C M} → SN M 𝟘
→ SN (ABORT M) C
sn-abort {C} (𝒟 , M⇓ , s!) = abort 𝒟 , halt-abort 𝒟 M⇓ , sn!-abort {C} s!
sn!-abort : ∀ {C M} → SN! M 𝟘
→ SN! (ABORT M) C
sn!-abort {𝔹} ()
sn!-abort {A ∨ B} x = oops
sn!-abort {𝟘} ()
sn!-abort {𝟙} ()
sn!-abort {A ∧ B} ()
sn!-abort {A ⊃ B} () _
sn-left : ∀ {A B M} → SN M A
→ SN (LEFT M) (A ∨ B)
sn-left s@(𝒟 , M⇓@(M′ , M⇓M′@(M⤅M′ , VM′)) , s!) = left 𝒟 , halt-left M⇓ , oops
sn-right : ∀ {A B M} → SN M B
→ SN (RIGHT M) (A ∨ B)
sn-right s@(𝒟 , M⇓@(M′ , M⇓M′@(M⤅M′ , VM′)) , s!) = right 𝒟 , halt-right M⇓ , oops
mutual
sn-if : ∀ {C M N O} → SN M 𝔹 → SN N C → SN O C
→ SN (IF M N O) C
sn-if (𝒟 , M⇓@(M′ , M⤅M′ , VM′) , ∙) _ _ with tp⤅ M⤅M′ 𝒟
sn-if (𝒟 , M⇓@(LAM _ , _ , val-lam) , ∙) _ _ | ()
sn-if (𝒟 , M⇓@(PAIR _ _ , _ , val-pair) , ∙) _ _ | ()
sn-if (𝒟 , M⇓@(UNIT , _ , val-unit) , ∙) _ _ | ()
sn-if (𝒟 , M⇓@(LEFT _ , _ , val-left) , ∙) _ _ | ()
sn-if (𝒟 , M⇓@(RIGHT _ , _ , val-right) , ∙) _ _ | ()
sn-if (𝒟 , M⇓@(TRUE , M⤅TRUE , val-true) , ∙) (ℰ , N⇓ , s!₁) (ℱ , O⇓ , s!₂) | true = if 𝒟 ℰ ℱ , halt-if 𝒟 M⇓ N⇓ O⇓ , sn!-if-true M⤅TRUE 𝒟 ℰ ℱ s!₁
sn-if (𝒟 , M⇓@(FALSE , M⤅FALSE , val-false) , ∙) (ℰ , N⇓ , s!₁) (ℱ , O⇓ , s!₂) | false = if 𝒟 ℰ ℱ , halt-if 𝒟 M⇓ N⇓ O⇓ , sn!-if-false M⤅FALSE 𝒟 ℰ ℱ s!₂
sn!-if-true : ∀ {C M N O} → M ⤅ TRUE → ∙ ⊢ M ⦂ 𝔹 → ∙ ⊢ N ⦂ C → ∙ ⊢ O ⦂ C → SN! N C
→ SN! (IF M N O) C
sn!-if-true {𝔹} M⤅TRUE 𝒟 ℰ ℱ ∙ = ∙
sn!-if-true {A ∨ B} M⤅TRUE 𝒟 ℰ ℱ x = oops
sn!-if-true {𝟘} M⤅TRUE 𝒟 ℰ ℱ ()
sn!-if-true {𝟙} M⤅TRUE 𝒟 ℰ ℱ ∙ = ∙
sn!-if-true {A ∧ B} M⤅TRUE 𝒟 ℰ ℱ (s₁ , s₂) = snpr⤅ (congs-fst (reds-if-true M⤅TRUE done)) (fst (if 𝒟 ℰ ℱ)) s₁ ,
snpr⤅ (congs-snd (reds-if-true M⤅TRUE done)) (snd (if 𝒟 ℰ ℱ)) s₂
sn!-if-true {A ⊃ B} M⤅TRUE 𝒟 ℰ ℱ f s = snpr⤅ (congs-app₁ (reds-if-true M⤅TRUE done)) (app (if 𝒟 ℰ ℱ) (derp s)) (f s)
sn!-if-false : ∀ {C M N O} → M ⤅ FALSE → ∙ ⊢ M ⦂ 𝔹 → ∙ ⊢ N ⦂ C → ∙ ⊢ O ⦂ C → SN! O C
→ SN! (IF M N O) C
sn!-if-false {𝔹} M⤅FALSE 𝒟 ℰ ℱ ∙ = ∙
sn!-if-false {A ∨ B} M⤅FALSE 𝒟 ℰ ℱ x = oops
sn!-if-false {𝟘} M⤅FALSE 𝒟 ℰ ℱ ()
sn!-if-false {𝟙} M⤅FALSE 𝒟 ℰ ℱ ∙ = ∙
sn!-if-false {A ∧ B} M⤅FALSE 𝒟 ℰ ℱ (s₁ , s₂) = snpr⤅ (congs-fst (reds-if-false M⤅FALSE done)) (fst (if 𝒟 ℰ ℱ)) s₁ ,
snpr⤅ (congs-snd (reds-if-false M⤅FALSE done)) (snd (if 𝒟 ℰ ℱ)) s₂
sn!-if-false {A ⊃ B} M⤅FALSE 𝒟 ℰ ℱ f s = snpr⤅ (congs-app₁ (reds-if-false M⤅FALSE done)) (app (if 𝒟 ℰ ℱ) (derp s)) (f s)
gen-red-app-lam : ∀ {g M N} → {τ : Terms 0 g} → {{_ : Val N}}
→ APP (LAM (SUB (LIFTS τ) M)) N ↦ SUB (τ , N) M
gen-red-app-lam {M = M} {N} {τ} rewrite simp-CUT-SUB N τ M ⁻¹ = red app-lam
gen-big-red-app-lam : ∀ {g M M′ N} → {τ : Terms 0 g} → {{_ : Vals τ}} {{_ : Val N}}
→ SUB (τ , N) M ⇓ M′
→ APP (LAM (SUB (LIFTS τ) M)) N ⇓ M′
gen-big-red-app-lam {M = M} (SUB⤅M′ , VM′) = step (gen-red-app-lam {M = M}) SUB⤅M′ , VM′
gen-halt-app-lam : ∀ {g M N} → {τ : Terms 0 g} → {{_ : Vals τ}} {{_ : Val N}}
→ SUB (τ , N) M ⇓
→ APP (LAM (SUB (LIFTS τ) M)) N ⇓
gen-halt-app-lam {M = M} (M′ , SUB⇓M′) = M′ , gen-big-red-app-lam {M = M} SUB⇓M′
mutual
gen-sn-app-lam : ∀ {B g M N A} → {τ : Terms 0 g} → {{_ : Vals τ}} {{_ : Val N}}
→ ∙ ⊢ SUB τ (LAM M) ⦂ A ⊃ B → ∙ ⊢ N ⦂ A → SN (SUB (τ , N) M) B
→ SN (APP (LAM (SUB (LIFTS τ) M)) N) B
gen-sn-app-lam {M = M} 𝒟 ℰ (𝒟′ , SUB⇓ , s!) = app 𝒟 ℰ , gen-halt-app-lam {M = M} SUB⇓ , gen-sn!-app-lam {M = M} 𝒟 ℰ s!
gen-sn!-app-lam : ∀ {B g M N A} → {τ : Terms 0 g} → {{_ : Vals τ}} {{_ : Val N}}
→ ∙ ⊢ SUB τ (LAM M) ⦂ A ⊃ B → ∙ ⊢ N ⦂ A → SN! (SUB (τ , N) M) B
→ SN! (APP (LAM (SUB (LIFTS τ) M)) N) B
gen-sn!-app-lam {𝔹} {M = M} 𝒟 ℰ ∙ = ∙
gen-sn!-app-lam {B₁ ∨ B₂} {M = M} 𝒟 ℰ x = oops
gen-sn!-app-lam {𝟘} {M = M} 𝒟 ℰ ()
gen-sn!-app-lam {𝟙} {M = M} 𝒟 ℰ ∙ = ∙
gen-sn!-app-lam {B₁ ∧ B₂} {M = M} 𝒟 ℰ (s₁ , s₂) = snpr↦ (cong-fst (gen-red-app-lam {M = M})) (fst (app 𝒟 ℰ)) s₁ ,
snpr↦ (cong-snd (gen-red-app-lam {M = M})) (snd (app 𝒟 ℰ)) s₂
gen-sn!-app-lam {B₁ ⊃ B₂} {M = M} 𝒟 ℰ f s = snpr↦ (cong-app₁ (gen-red-app-lam {M = M})) (app (app 𝒟 ℰ) (derp s)) (f s)
mutual
gen-sn : ∀ {g M A} → {τ : Terms 0 g} {Γ : Types g} → {{_ : Vals τ}}
→ SNs τ Γ → Γ ⊢ M ⦂ A
→ SN (SUB τ M) A
gen-sn σ (var i) = get σ (zip∋₂ i)
gen-sn σ (lam 𝒟) = let 𝒟′ = sub (derps σ) (lam 𝒟) in
𝒟′ , (LAM _ , done , val-lam) , gen-sn-lam σ 𝒟 𝒟′
gen-sn σ (app 𝒟 ℰ) with gen-sn σ 𝒟
gen-sn σ (app 𝒟 ℰ) | 𝒟′ , M′⇓ , f = f (gen-sn σ ℰ)
gen-sn σ (pair 𝒟 ℰ) = sn-pair (gen-sn σ 𝒟) (gen-sn σ ℰ)
gen-sn σ (fst 𝒟) = sn-fst (gen-sn σ 𝒟)
gen-sn σ (snd 𝒟) = sn-snd (gen-sn σ 𝒟)
gen-sn σ unit = unit , (UNIT , done , val-unit) , ∙
gen-sn σ (abort 𝒟) = sn-abort (gen-sn σ 𝒟)
gen-sn σ (left 𝒟) = sn-left (gen-sn σ 𝒟)
gen-sn σ (right 𝒟) = sn-right (gen-sn σ 𝒟)
gen-sn σ (case 𝒟 ℰ ℱ) = oops
gen-sn σ true = true , (TRUE , done , val-true) , ∙
gen-sn σ false = false , (FALSE , done , val-false) , ∙
gen-sn σ (if 𝒟 ℰ ℱ) = sn-if (gen-sn σ 𝒟) (gen-sn σ ℰ) (gen-sn σ ℱ)
gen-sn-lam : ∀ {g M N A B} → {τ : Terms 0 g} {Γ : Types g} → {{_ : Vals τ}}
→ SNs τ Γ → Γ , A ⊢ M ⦂ B → ∙ ⊢ LAM (SUB (LIFTS τ) M) ⦂ A ⊃ B → SN N A
→ SN (APP (LAM (SUB (LIFTS τ) M)) N) B
gen-sn-lam {M = M} {{Vτ}} σ 𝒟 𝒟′ s@(ℰ , (N′ , N⇓N′@(N⤅N′ , VN′)) , s!)
= let s′ = snp⇓ N⇓N′ ℰ s in
snpr⤅ (congs-app₂ N⤅N′) (app 𝒟′ ℰ) (gen-sn-app-lam {M = M} {{Vτ}} {{VN′}} 𝒟′ (derp s′) (gen-sn {{Vτ , VN′}} (σ , s′) 𝒟))
sn : ∀ {A M} → ∙ ⊢ M ⦂ A
→ SN M A
sn {A} {M} 𝒟 = subst (\ M′ → SN M′ A) (id-SUB M) (gen-sn ∙ 𝒟)
herp : ∀ {A M} → SN M A
→ M ⇓
herp (𝒟 , M⇓ , s!) = M⇓
halt : ∀ {A M} → ∙ ⊢ M ⦂ A
→ M ⇓
halt {A} 𝒟 = herp {A} (sn 𝒟)