module A201903.5-6-Equivalence-HS where
open import A201903.1-2-Syntax-Predicates
import A201903.2-1-Semantics-BigStep as BS
import A201903.2-2-Semantics-SmallStep as SS
import A201903.3-6-Properties-BigStep-HS as BS-HS
import A201903.4-6-Properties-SmallStep-HS as SS-HS
module Lem-5-6-1 where
open SS-HS
open BS-HS
rev-lam* : ∀ {n i s} {e : Tm (suc n)} {e′} → lam s e ⇒*⟨ i ⟩ lam s e′ → e ⇒*⟨ i ⟩ e′
rev-lam* ε = ε
rev-lam* (lam r ◅ rs) = r ◅ rev-lam* rs
¬lam⇒*var : ∀ {n s} {e : Tm (suc n)} {s′ x} → ¬ (lam s e ⇒* var s′ x)
¬lam⇒*var = λ { (lam r ◅ rs) → rs ↯ ¬lam⇒*var }
¬lam-s⇒*lam-s′ : ∀ {n s} {e : Tm (suc n)} {s′ e′} → s ≢ s′ → ¬ (lam s e ⇒* lam s′ e′)
¬lam-s⇒*lam-s′ s≢s′ = λ { ε → refl ↯ s≢s′
; (lam r ◅ rs) → rs ↯ ¬lam-s⇒*lam-s′ s≢s′ }
¬lam⇒*app : ∀ {n s} {e : Tm (suc n)} {e₁ e₂} → ¬ (lam s e ⇒* app e₁ e₂)
¬lam⇒*app = λ { (lam r ◅ rs) → rs ↯ ¬lam⇒*app }
rev-app₁* : ∀ {n i} {e₁ e₂ : Tm n} {e′} →
app e₁ e₂ ⇒*⟨ i ⟩ e′ → HNF e′ →
(∃² λ s e₁′ →
e₁ ⇒*⟨ i ⟩ lam s e₁′ × HNF e₁′ × e₁′ [ e₂ ] ⇒*⟨ i ⟩ e′) ⊎
(∃ λ e₁′ →
e₁ ⇒*⟨ i ⟩ e₁′ × NAXNF e₁′ × app e₁′ e₂ ≡ e′)
rev-app₁* ε (hnf (app p₁)) = inj₂ (_ , ε , p₁ , refl)
rev-app₁* (applam p₁ ◅ rs) p′ = inj₁ (_ , ε , p₁ , rs)
rev-app₁* (app₁ r₁ ◅ rs) p′ with rev-app₁* rs p′
... | inj₁ (_ , rs₁ , p₁′ , rs′) = inj₁ (_ , r₁ ◅ rs₁ , p₁′ , rs′)
... | inj₂ (_ , rs₁ , p₁′ , refl) = inj₂ (_ , r₁ ◅ rs₁ , p₁′ , refl)
mutual
bs←ss : ∀ {n i} {e : Tm n} {e′} → e ⇒*⟨ i ⟩ e′ → HNF e′ → e ⟱ e′
bs←ss ε p′ = refl-⟱ p′
bs←ss (r ◅ rs) p′ = bs←ss′ r rs p′
bs←ss′ : ∀ {n i} {e : Tm n} {e′ e″} → e ⇒ e′ → e′ ⇒*⟨ i ⟩ e″ → HNF e″ → e ⟱ e″
bs←ss′ (applam p₁) rs p″ = applam (refl-⟱ (lam p₁)) (bs←ss rs p″)
bs←ss′ (lam {s = s} r) rs (lam {s = s′} p″) with s ≟ s′
... | no s≢s′ = rs ↯ ¬lam-s⇒*lam-s′ s≢s′
... | yes refl = lam (bs←ss′ r (rev-lam* rs) p″)
bs←ss′ (lam r) rs (hnf var) = rs ↯ ¬lam⇒*var
bs←ss′ (lam r) rs (hnf (app _)) = rs ↯ ¬lam⇒*app
bs←ss′ (app₁ r₁) rs p″ with rev-app₁* rs p″
... | inj₁ (_ , rs₁ , p₁′ , rs′) = applam (bs←ss′ r₁ rs₁ (lam p₁′)) (bs←ss rs′ p″)
... | inj₂ (_ , rs₁ , p₁′ , refl) = app (bs←ss′ r₁ rs₁ (hnf p₁′)) (na←naxnf p₁′)
module Lem-5-6-2 where
open SS-HS
open BS-HS
applam* : ∀ {n s} {e₁ : Tm (suc n)} {e₂ : Tm n} → HNF e₁ → app (lam s e₁) e₂ ⇒* e₁ [ e₂ ]
applam* p₁ = applam p₁ ◅ ε
lam* : ∀ {n s} {e : Tm (suc n)} {e′} → e ⇒* e′ → lam s e ⇒* lam s e′
lam* = map* lam
app₁* : ∀ {n} {e₁ e₂ : Tm n} {e₁′} → e₁ ⇒* e₁′ → app e₁ e₂ ⇒* app e₁′ e₂
app₁* = map* app₁
bs-applam : ∀ {n s} {e₁ e₂ : Tm n} {e₁′ e′} →
e₁ ⇒* lam s e₁′ → HNF (lam s e₁′) → e₁′ [ e₂ ] ⇒* e′ →
app e₁ e₂ ⇒* e′
bs-applam rs₁ (lam p₁′) rs = app₁* rs₁ ◅◅ applam* p₁′ ◅◅ rs
bs-applam rs₁ (hnf ()) rs
bs-lam : ∀ {n s} {e : Tm (suc n)} {e′} → e ⇒* e′ → lam s e ⇒* lam s e′
bs-lam = lam*
bs-app : ∀ {n} {e₁ e₂ : Tm n} {e₁′} → e₁ ⇒* e₁′ → app e₁ e₂ ⇒* app e₁′ e₂
bs-app = app₁*
ss←bs : ∀ {n} {e : Tm n} {e′} → e ⟱ e′ → e ⇒* e′
ss←bs (applam r₁ r) = bs-applam (ss←bs r₁) (hnf-⟱ r₁) (ss←bs r)
ss←bs var = ε
ss←bs (lam r) = bs-lam (ss←bs r)
ss←bs (app r₁ p₁′) = bs-app (ss←bs r₁)
module Thm-5-6-3 where
ss↔bs : ∀ {n} {e : Tm n} {e′} → (e SS.HS.⇒* e′ × HNF e′) ↔ e BS.HS.⟱ e′
ss↔bs = uncurry Lem-5-6-1.bs←ss , λ r → Lem-5-6-2.ss←bs r , BS-HS.hnf-⟱ r