module A201903.4-6-Properties-SmallStep-HS where
open import A201903.2-2-Semantics-SmallStep
open HS public
data RF? {n} : Pred₀ (Tm n) where
yes : ∀ {e} → RF e → RF? e
no : ∀ {e} → HNF e → RF? e
rf? : ∀ {n} (e : Tm n) → RF? e
rf? (var s x) = no (hnf var)
rf? (lam s e) with rf? e
... | yes (_ , r) = yes (_ , lam r)
... | no p = no (lam p)
rf? (app e₁ e₂) with rf? e₁
... | yes (_ , r₁) = yes (_ , app₁ r₁)
... | no (lam p₁) = yes (_ , applam p₁)
... | no (hnf p₁) = no (hnf (app p₁))
eval : ∀ {n i} (e : Tm n) → e ᶜᵒ⇓[ HNF ]⟨ i ⟩
eval e with rf? e
... | yes (_ , r) = r ◅ λ where .force → eval _
... | no p = ε p
hnf←nrf : ∀ {n} {e : Tm n} → NRF e → HNF e
hnf←nrf p with rf? _
... | yes (_ , r) = r ↯ p
... | no p′ = p′
nrf←naxnf : ∀ {n} {e : Tm n} → NAXNF e → NRF e
nrf←naxnf var = λ ()
nrf←naxnf (app p₁) = λ { (applam p₁′) → case p₁ of λ ()
; (app₁ r₁) → r₁ ↯ nrf←naxnf p₁ }
nrf←hnf : ∀ {n} {e : Tm n} → HNF e → NRF e
nrf←hnf (lam p) = λ { (lam r) → r ↯ nrf←hnf p }
nrf←hnf (hnf p) = nrf←naxnf p
rev-applam : ∀ {n s} {e₁ : Tm (suc n)} {e₂ : Tm n} {e′} →
(p₁ : HNF e₁) (r : app (lam s e₁) e₂ ⇒ e′) →
(Σ (e′ ≡ e₁ [ e₂ ]) λ { refl →
r ≡ applam p₁ })
rev-applam p₁ (applam p₁′) = refl , applam & uniq-hnf p₁′ p₁
rev-applam p₁ (app₁ (lam r₁)) = r₁ ↯ nrf←hnf p₁
rev-app₁ : ∀ {n s} {e₁ : Tm (suc n)} {e₂ : Tm n} {e′} →
(r : app (lam s e₁) e₂ ⇒ e′) →
(∃ λ p₁ →
Σ (e′ ≡ e₁ [ e₂ ]) λ { refl →
r ≡ applam p₁ }) ⊎
(Σ {_} {0ᴸ} (Tm (suc n)) λ e₁′ →
Σ (e₁ ⇒ e₁′) λ r₁ →
Σ (e′ ≡ app (lam s e₁′) e₂) λ { refl →
r ≡ app₁ (lam r₁) })
rev-app₁ (applam p₁) = inj₁ (p₁ , refl , refl)
rev-app₁ (app₁ (lam r₁)) = inj₂ (_ , r₁ , refl , refl)
uniq-⇒ : Unique _⇒_
uniq-⇒ {e = var _ _} () ()
uniq-⇒ {e = lam _ _} (lam r) (lam r′) = lam & uniq-⇒ r r′
uniq-⇒ {e = app (var _ _) _} (app₁ ()) r′
uniq-⇒ {e = app (lam _ _) _} (applam p₁) r′ with rev-applam p₁ r′
... | refl , refl = refl
uniq-⇒ {e = app (lam _ _) _} (app₁ (lam r₁)) r′ with rev-app₁ r′
... | inj₁ (p₁ , q₁ , q₂) = r₁ ↯ nrf←hnf p₁
... | inj₂ (_ , r₁′ , refl , refl) = app₁ & uniq-⇒ (lam r₁) (lam r₁′)
uniq-⇒ {e = app (app _ _) _} (app₁ r₁) (app₁ r₁′) = app₁ & uniq-⇒ r₁ r₁′
det-⇒ : Deterministic _⇒_
det-⇒ (applam p₁) (applam p₁′) = refl
det-⇒ (applam p₁) (app₁ (lam r₁′)) = r₁′ ↯ nrf←hnf p₁
det-⇒ (lam r) (lam r′) = lam & refl ⊗ det-⇒ r r′
det-⇒ (app₁ (lam r₁)) (applam p₁′) = r₁ ↯ nrf←hnf p₁′
det-⇒ (app₁ r₁) (app₁ r₁′) = app & det-⇒ r₁ r₁′ ⊗ refl
conf-⇒ : Confluent _⇒_
conf-⇒ = cor-conf-⇒ det-⇒
det-⇓-nrf : Deterministic _⇓[ NRF ]_
det-⇓-nrf = cor-det-⇓-nrf det-⇒
naxnf-⇒ : ∀ {n} {e : Tm n} {e′} → NAXNF e → e ⇒ e′ → NAXNF e′
naxnf-⇒ var ()
naxnf-⇒ (app ()) (applam p₁′)
naxnf-⇒ (app p₁) (app₁ r₁) = r₁ ↯ nrf←naxnf p₁
hnf-⇒ : ∀ {n} {e : Tm n} {e′} → HNF e → e ⇒ e′ → HNF e′
hnf-⇒ (lam p) (lam r) = r ↯ nrf←hnf p
hnf-⇒ (hnf p) r = hnf (naxnf-⇒ p r)
rev-¬hnf-⇒ : ∀ {n} {e : Tm n} {e′} → e ⇒ e′ → ¬ HNF e
rev-¬hnf-⇒ r = λ p → r ↯ nrf←hnf p