module A202401.STLC-Base-EWNF-CBV where
open import A202401.STLC-Base-RenSub public
import A202401.STLC-Base-EWNF as F
open F using (⌜λ⌝- ; nnf ; var- ; _⌜$⌝_ ; ∙ ; _,_)
open import A202401.Kit3 public
data Expandable {Γ} : ∀ {A} → Γ ⊢ A → Set where
var- : ∀ {A B} {i : Γ ∋ A ⌜⊃⌝ B} → Expandable (var i)
_⌜$⌝_ : ∀ {A B C} {t₁ : Γ ⊢ A ⌜⊃⌝ B ⌜⊃⌝ C} {t₂ : Γ ⊢ A} (p₁ : F.NNF t₁) (p₂ : F.NF t₂) →
Expandable (t₁ ⌜$⌝ t₂)
uniExpandable : ∀ {Γ A} {t : Γ ⊢ A} (x x′ : Expandable t) → x ≡ x′
uniExpandable var- var- = refl
uniExpandable (p₁ ⌜$⌝ p₂) (p₁′ ⌜$⌝ p₂′) = _⌜$⌝_ & F.uniNNF p₁ p₁′ ⊗ F.uniNF p₂ p₂′
data Expandable* {Γ} : ∀ {Δ} → Γ ⊢§ Δ → Set where
∙ : Expandable* ∙
_,_ : ∀ {Δ A} {τ : Γ ⊢§ Δ} {t : Γ ⊢ A} (ξ : Expandable* τ) (x : Expandable t) → Expandable* (τ , t)
FNNF→Expandable : ∀ {Γ A B} {t : Γ ⊢ A ⌜⊃⌝ B} → F.NNF t → Expandable t
FNNF→Expandable var- = var-
FNNF→Expandable (p₁ ⌜$⌝ p₂) = p₁ ⌜$⌝ p₂
Expandable→FNNF : ∀ {Γ A B} {t : Γ ⊢ A ⌜⊃⌝ B} → Expandable t → F.NNF t
Expandable→FNNF var- = var-
Expandable→FNNF (p₁ ⌜$⌝ p₂) = p₁ ⌜$⌝ p₂
Expandable→¬FNF : ∀ {Γ A} {t : Γ ⊢ A} → Expandable t → ¬ F.NF t
Expandable→¬FNF var- ()
Expandable→¬FNF (p₁ ⌜$⌝ p₂) ()
uni¬Expandable : ∀ {Γ A} {t : Γ ⊢ A} (¬x ¬x′ : ¬ Expandable t) → ¬x ≡ ¬x′
uni¬Expandable = uni¬
data _ExpandsTo_ {Γ} : ∀ {A} (t t′ : Γ ⊢ A) → Set where
ηexp⊃ : ∀ {A B} {t t′ : Γ ⊢ A ⌜⊃⌝ B} (eq : t′ ≡ ⌜λ⌝ (wk t ⌜$⌝ var zero)) (x : Expandable t) →
t ExpandsTo t′
Expanded : ∀ {Γ A} (t′ : Γ ⊢ A) → Set
Expanded t′ = Σ _ λ t → t ExpandsTo t′
uni¬Expanded : ∀ {Γ A} {t : Γ ⊢ A} (¬x ¬x′ : ¬ Expanded t) → ¬x ≡ ¬x′
uni¬Expanded = uni¬
INF : ∀ {Γ A} → Γ ⊢ A → Set
INF t = F.NF t × ¬ Expanded t
INF→FNF : ∀ {Γ A} {t : Γ ⊢ A} → INF t → F.NF t
INF→FNF (p , _) = p
uniINF : ∀ {Γ A} {t : Γ ⊢ A} (p p′ : INF t) → p ≡ p′
uniINF (p , ¬x) (p′ , ¬x′) = _,_ & F.uniNF p p′ ⊗ uni¬Expanded ¬x ¬x′
mutual
infix 4 _⇒F_
data _⇒F_ {Γ} : ∀ {A} → Γ ⊢ A → Γ ⊢ A → Set where
Ired : ∀ {A} {t t′ : Γ ⊢ A} (¬x : ¬ Expandable t) (r : t ⇒I t′) → t ⇒F t′
ηexp⊃ : ∀ {A B} {t : Γ ⊢ A ⌜⊃⌝ B} {t′} (eq : t′ ≡ wk t) (x : Expandable t) →
t ⇒F ⌜λ⌝ (t′ ⌜$⌝ var zero)
infix 4 _⇒I_
data _⇒I_ {Γ} : ∀ {A} → Γ ⊢ A → Γ ⊢ A → Set where
cong$₁ : ∀ {A B} {t₁ t₁′ : Γ ⊢ A ⌜⊃⌝ B} {t₂ : Γ ⊢ A} (r₁ : t₁ ⇒I t₁′) →
t₁ ⌜$⌝ t₂ ⇒I t₁′ ⌜$⌝ t₂
Fcong$₂ : ∀ {A B} {t₁ : Γ ⊢ A ⌜⊃⌝ B} {t₂ t₂′ : Γ ⊢ A} (p₁ : F.NF t₁) (r₂ : t₂ ⇒F t₂′) →
t₁ ⌜$⌝ t₂ ⇒I t₁ ⌜$⌝ t₂′
Xcong$₂ : ∀ {A B} {t₁ : Γ ⊢ A ⌜⊃⌝ B} {t₂ t₂′ : Γ ⊢ A} (x₁ : Expandable t₁) (r₂ : t₂ ⇒F t₂′) →
t₁ ⌜$⌝ t₂ ⇒I t₁ ⌜$⌝ t₂′
βred⊃ : ∀ {A B} {t₁ : Γ , A ⊢ B} {t₂ : Γ ⊢ A} {t′} (eq : t′ ≡ t₁ [ t₂ ]) (p₂ : F.NF t₂) →
⌜λ⌝ t₁ ⌜$⌝ t₂ ⇒I t′
module RK1F = RedKit1 (kit tmkit _⇒F_)
module RK1I = RedKit1 (kit tmkit _⇒I_)
mutual
FNF→¬FR : ∀ {Γ A} {t : Γ ⊢ A} → F.NF t → RK1F.¬R t
FNF→¬FR ⌜λ⌝- (ηexp⊃ refl ())
FNF→¬FR (nnf p) r = r ↯ FNNF→¬FR p
FNNF→¬FR : ∀ {Γ} {t : Γ ⊢ ⌜◦⌝} → F.NNF t → RK1F.¬R t
FNNF→¬FR p (Ired ¬x r) = r ↯ FNNF→¬IR p
FNF→¬IR : ∀ {Γ A} {t : Γ ⊢ A} → F.NF t → RK1I.¬R t
FNF→¬IR (nnf p) r = r ↯ FNNF→¬IR p
FNNF→¬IR : ∀ {Γ A} {t : Γ ⊢ A} → F.NNF t → RK1I.¬R t
FNNF→¬IR (p₁ ⌜$⌝ p₂) (cong$₁ r₁) = r₁ ↯ FNNF→¬IR p₁
FNNF→¬IR (p₁ ⌜$⌝ p₂) (Fcong$₂ p₁′ r₂) = r₂ ↯ FNF→¬FR p₂
FNNF→¬IR (p₁ ⌜$⌝ p₂) (Xcong$₂ x₁ r₂) = r₂ ↯ FNF→¬FR p₂
INF→¬IR : ∀ {Γ A} {t : Γ ⊢ A} → INF t → RK1I.¬R t
INF→¬IR = FNF→¬IR ∘ INF→FNF
module RK2F = RedKit2 (kit RK1F.redkit1 F.uniNF FNF→¬FR)
module RK2I = RedKit2 (kit RK1I.redkit1 uniINF INF→¬IR)
Expandable→¬IR : ∀ {Γ A B} {t : Γ ⊢ A ⌜⊃⌝ B} → Expandable t → RK1I.¬R t
Expandable→¬IR = FNNF→¬IR ∘ Expandable→FNNF
mutual
det⇒F : ∀ {Γ A} {t t′ t″ : Γ ⊢ A} → t ⇒F t′ → t ⇒F t″ → t′ ≡ t″
det⇒F (Ired ¬x r) (Ired ¬x′ r′) = det⇒I r r′
det⇒F (Ired ¬x r) (ηexp⊃ refl x′) = x′ ↯ ¬x
det⇒F (ηexp⊃ refl x) (Ired ¬x′ r′) = x ↯ ¬x′
det⇒F (ηexp⊃ refl x) (ηexp⊃ refl x′) = refl
det⇒I : ∀ {Γ A} {t t′ t″ : Γ ⊢ A} → t ⇒I t′ → t ⇒I t″ → t′ ≡ t″
det⇒I (cong$₁ r₁) (cong$₁ r₁′) = (_⌜$⌝ _) & det⇒I r₁ r₁′
det⇒I (cong$₁ r₁) (Fcong$₂ p₁′ r₂′) = r₁ ↯ FNF→¬IR p₁′
det⇒I (cong$₁ r₁) (Xcong$₂ x₁′ r₂′) = r₁ ↯ Expandable→¬IR x₁′
det⇒I (Fcong$₂ p₁ r₂) (cong$₁ r₁′) = r₁′ ↯ FNF→¬IR p₁
det⇒I (Fcong$₂ p₁ r₂) (Fcong$₂ p₁′ r₂′) = (_ ⌜$⌝_) & det⇒F r₂ r₂′
det⇒I (Fcong$₂ p₁ r₂) (Xcong$₂ x₁′ r₂′) = p₁ ↯ Expandable→¬FNF x₁′
det⇒I (Fcong$₂ p₁ r₂) (βred⊃ refl p₂′) = r₂ ↯ FNF→¬FR p₂′
det⇒I (Xcong$₂ x₁ r₂) (cong$₁ r₁′) = r₁′ ↯ Expandable→¬IR x₁
det⇒I (Xcong$₂ x₁ r₂) (Fcong$₂ p₁′ r₂′) = p₁′ ↯ Expandable→¬FNF x₁
det⇒I (Xcong$₂ x₁ r₂) (Xcong$₂ x₁′ r₂′) = (_ ⌜$⌝_) & det⇒F r₂ r₂′
det⇒I (βred⊃ refl p₂) (Fcong$₂ p₁′ r₂′) = r₂′ ↯ FNF→¬FR p₂
det⇒I (βred⊃ refl p₂) (βred⊃ refl p₂′) = refl
mutual
uni⇒F : ∀ {Γ A} {t t′ : Γ ⊢ A} (r r′ : t ⇒F t′) → r ≡ r′
uni⇒F (Ired ¬x r) (Ired ¬x′ r′) = Ired & uni¬Expandable ¬x ¬x′ ⊗ uni⇒I r r′
uni⇒F (Ired ¬x r) (ηexp⊃ eq′ x′) = x′ ↯ ¬x
uni⇒F (ηexp⊃ eq x) (Ired ¬x′ r′) = x ↯ ¬x′
uni⇒F (ηexp⊃ refl x) (ηexp⊃ refl x′) = ηexp⊃ refl & uniExpandable x x′
uni⇒I : ∀ {Γ A} {t t′ : Γ ⊢ A} (r r′ : t ⇒I t′) → r ≡ r′
uni⇒I (cong$₁ r₁) (cong$₁ r₁′) = cong$₁ & uni⇒I r₁ r₁′
uni⇒I (cong$₁ r₁) (Fcong$₂ p₁′ r₂′) = r₁ ↯ FNF→¬IR p₁′
uni⇒I (cong$₁ r₁) (Xcong$₂ x₁′ r₂′) = r₁ ↯ Expandable→¬IR x₁′
uni⇒I (Fcong$₂ p₁ r₂) (cong$₁ r₁′) = r₁′ ↯ FNF→¬IR p₁
uni⇒I (Fcong$₂ p₁ r₂) (Fcong$₂ p₁′ r₂′) = Fcong$₂ & F.uniNF p₁ p₁′ ⊗ uni⇒F r₂ r₂′
uni⇒I (Fcong$₂ p₁ r₂) (Xcong$₂ x₁′ r₂′) = p₁ ↯ Expandable→¬FNF x₁′
uni⇒I (Fcong$₂ p₁ r₂) (βred⊃ eq′ p₂′) = r₂ ↯ FNF→¬FR p₂′
uni⇒I (Xcong$₂ x₁ r₂) (cong$₁ r₁′) = r₁′ ↯ Expandable→¬IR x₁
uni⇒I (Xcong$₂ x₁ r₂) (Fcong$₂ p₁′ r₂′) = p₁′ ↯ Expandable→¬FNF x₁
uni⇒I (Xcong$₂ x₁ r₂) (Xcong$₂ x₁′ r₂′) = Xcong$₂ & uniExpandable x₁ x₁′ ⊗ uni⇒F r₂ r₂′
uni⇒I (βred⊃ eq p₂) (Fcong$₂ p₁′ r₂′) = r₂′ ↯ FNF→¬FR p₂
uni⇒I (βred⊃ refl p₂) (βred⊃ refl p₂′) = βred⊃ refl & F.uniNF p₂ p₂′
module DKF = DetKit (kit RK2F.redkit2 det⇒F uni⇒F)
module DKI = DetKit (kit RK2I.redkit2 det⇒I uni⇒I)
prog⇒F : ∀ {A Γ} (t : Γ ⊢ A) → RK2F.Prog t
prog⇒F {⌜◦⌝} (var i) = RK2F.done (nnf var-)
prog⇒F {⌜◦⌝} (t₁ ⌜$⌝ t₂) with prog⇒F t₁ | prog⇒F t₂
... | RK2F.step (Ired ¬x₁ r₁) | _ = RK2F.step (Ired (λ ()) (cong$₁ r₁))
... | RK2F.step (ηexp⊃ eq x₁) | RK2F.step r₂ = RK2F.step (Ired (λ ()) (Xcong$₂ x₁ r₂))
... | RK2F.step (ηexp⊃ eq x₁) | RK2F.done p₂ = RK2F.done (nnf (Expandable→FNNF x₁ ⌜$⌝ p₂))
... | RK2F.done p₁ | RK2F.step r₂ = RK2F.step (Ired (λ ()) (Fcong$₂ p₁ r₂))
... | RK2F.done ⌜λ⌝- | RK2F.done p₂ = RK2F.step (Ired (λ ()) (βred⊃ refl p₂))
prog⇒F {A ⌜⊃⌝ B} (var i) = RK2F.step (ηexp⊃ refl var-)
prog⇒F {A ⌜⊃⌝ B} (⌜λ⌝ t) = RK2F.done ⌜λ⌝-
prog⇒F {A ⌜⊃⌝ B} (t₁ ⌜$⌝ t₂) with prog⇒F t₁ | prog⇒F t₂
... | RK2F.step (Ired ¬x₁ r₁) | _ = RK2F.step (Ired (λ { (p₁ ⌜$⌝ p₂) →
FNNF→Expandable p₁ ↯ ¬x₁ }) (cong$₁ r₁))
... | RK2F.step (ηexp⊃ eq x₁) | RK2F.step r₂ = RK2F.step (Ired (λ { (p₁ ⌜$⌝ p₂) →
r₂ ↯ FNF→¬FR p₂ }) (Xcong$₂ x₁ r₂))
... | RK2F.step (ηexp⊃ eq x₁) | RK2F.done p₂ = RK2F.step (ηexp⊃ refl (Expandable→FNNF x₁ ⌜$⌝ p₂))
... | RK2F.done ⌜λ⌝- | RK2F.step r₂ = RK2F.step (Ired (λ { (() ⌜$⌝ p₂′) }) (Fcong$₂ ⌜λ⌝- r₂))
... | RK2F.done ⌜λ⌝- | RK2F.done p₂ = RK2F.step (Ired (λ { (() ⌜$⌝ p₂′) }) (βred⊃ refl p₂))
module PKF = ProgKit (kit RK2F.redkit2 prog⇒F)
renExpandable : ∀ {Γ Γ′ A} {t : Γ ⊢ A} (ϱ : Γ ⊑ Γ′) → Expandable t → Expandable (ren ϱ t)
renExpandable ϱ var- = var-
renExpandable ϱ (p₁ ⌜$⌝ p₂) = F.renNNF ϱ p₁ ⌜$⌝ F.renNF ϱ p₂
ren¬Expandable : ∀ {Γ Γ′ A} {t : Γ ⊢ A} (ϱ : Γ ⊑ Γ′) → ¬ Expandable t → ¬ Expandable (ren ϱ t)
ren¬Expandable {t = var i} ϱ ¬x var- = var- ↯ ¬x
ren¬Expandable {t = t₁ ⌜$⌝ t₂} ϱ ¬x (p₁ ⌜$⌝ p₂) = (F.nerNNF ϱ p₁ ⌜$⌝ F.nerNF ϱ p₂) ↯ ¬x
mutual
ren⇒F : ∀ {Γ Γ′ A} {t t′ : Γ ⊢ A} (ϱ : Γ ⊑ Γ′) → t ⇒F t′ → ren ϱ t ⇒F ren ϱ t′
ren⇒F ϱ (Ired ¬x r) = Ired (ren¬Expandable ϱ ¬x) (ren⇒I ϱ r)
ren⇒F ϱ (ηexp⊃ refl x) = ηexp⊃ (eqwkren ϱ _) (renExpandable ϱ x)
ren⇒I : ∀ {Γ Γ′ A} {t t′ : Γ ⊢ A} (ϱ : Γ ⊑ Γ′) → t ⇒I t′ → ren ϱ t ⇒I ren ϱ t′
ren⇒I ϱ (cong$₁ r₁) = cong$₁ (ren⇒I ϱ r₁)
ren⇒I ϱ (Fcong$₂ p₁ r₂) = Fcong$₂ (F.renNF ϱ p₁) (ren⇒F ϱ r₂)
ren⇒I ϱ (Xcong$₂ x₁ r₂) = Xcong$₂ (renExpandable ϱ x₁) (ren⇒F ϱ r₂)
ren⇒I ϱ (βred⊃ {t₁ = t₁} refl p₂) = βred⊃ (rencut ϱ t₁ _ ⁻¹) (F.renNF ϱ p₂)
sub∋Expandable : ∀ {Γ Ξ A} {σ : Ξ ⊢§ Γ} {i : Γ ∋ A} → Expandable* σ → Expandable (sub∋ σ i)
sub∋Expandable {i = zero} (ξ , x) = x
sub∋Expandable {i = wk∋ i} (ξ , x) = sub∋Expandable ξ
subExpandable : ∀ {Γ Ξ A} {σ : Ξ ⊢§ Γ} {t : Γ ⊢ A} → F.NNF§ σ → Expandable* σ → Expandable t →
Expandable (sub σ t)
subExpandable ψ ξ var- = sub∋Expandable ξ
subExpandable ψ ξ (p₁ ⌜$⌝ p₂) = F.subNNF ψ p₁ ⌜$⌝ F.subNF ψ p₂
sub¬Expandable : ∀ {A Γ Ξ} {σ : Ξ ⊢§ Γ} {t : Γ ⊢ A} → F.NNF§ σ → ¬ Expandable t →
¬ Expandable (sub σ t)
sub¬Expandable {A ⌜⊃⌝ B} {t = var i} ψ ¬x x = var- ↯ ¬x
sub¬Expandable {A ⌜⊃⌝ B} {t = t₁ ⌜$⌝ t₂} ψ ¬x (p₁ ⌜$⌝ p₂) = (F.busNNF ψ p₁ ⌜$⌝ F.busNF ψ p₂) ↯ ¬x
mutual
sub⇒I : ∀ {Γ Ξ A} {σ : Ξ ⊢§ Γ} {t t′ : Γ ⊢ A} → F.NNF§ σ → Expandable* σ → t ⇒I t′ →
sub σ t ⇒I sub σ t′
sub⇒I ψ ξ (cong$₁ r₁) = cong$₁ (sub⇒I ψ ξ r₁)
sub⇒I ψ ξ (Fcong$₂ p₁ r₂) = Fcong$₂ (F.subNF ψ p₁) (sub⇒F ψ ξ r₂)
sub⇒I ψ ξ (Xcong$₂ x₁ r₂) = Xcong$₂ (subExpandable ψ ξ x₁) (sub⇒F ψ ξ r₂)
sub⇒I ψ ξ (βred⊃ {t₁ = t₁} refl p₂) = βred⊃ (subcut _ t₁ _ ⁻¹) (F.subNF ψ p₂)
sub⇒F : ∀ {Γ Ξ A} {σ : Ξ ⊢§ Γ} {t t′ : Γ ⊢ A} → F.NNF§ σ → Expandable* σ → t ⇒F t′ →
sub σ t ⇒F sub σ t′
sub⇒F ψ ξ (Ired ¬x r) = Ired (sub¬Expandable ψ ¬x) (sub⇒I ψ ξ r)
sub⇒F ψ ξ (ηexp⊃ {t = t} refl x) = ηexp⊃ (eqwksub _ t) (subExpandable ψ ξ x)
Expandable? : ∀ {A Γ} (t : Γ ⊢ A) → Dec (Expandable t)
Expandable? {⌜◦⌝} t = no λ ()
Expandable? {A ⌜⊃⌝ B} (var i) = yes var-
Expandable? {A ⌜⊃⌝ B} (⌜λ⌝ t) = no λ ()
Expandable? {A ⌜⊃⌝ B} (t₁ ⌜$⌝ t₂) with F.NNF? t₁ | F.NF? t₂
... | no ¬p₁ | _ = no λ { (p₁ ⌜$⌝ p₂) → p₁ ↯ ¬p₁ }
... | yes p₁ | no ¬p₂ = no λ { (p₁ ⌜$⌝ p₂) → p₂ ↯ ¬p₂ }
... | yes p₁ | yes p₂ = yes (p₁ ⌜$⌝ p₂)
FR→IR⊎ExpandsTo : ∀ {Γ A} {t t′ : Γ ⊢ A} → t ⇒F t′ → t ⇒I t′ ⊎ t ExpandsTo t′
FR→IR⊎ExpandsTo (Ired ¬x (cong$₁ r₁)) = left (cong$₁ r₁)
FR→IR⊎ExpandsTo (Ired ¬x (Fcong$₂ p₁ r₂)) = left (Fcong$₂ p₁ r₂)
FR→IR⊎ExpandsTo (Ired ¬x (Xcong$₂ x₁ r₂)) = left (Xcong$₂ x₁ r₂)
FR→IR⊎ExpandsTo (Ired ¬x (βred⊃ eq p₂)) = left (βred⊃ eq p₂)
FR→IR⊎ExpandsTo (ηexp⊃ refl x) = right (ηexp⊃ refl x)
IR⊎ExpandsTo→FR : ∀ {A Γ} {t t′ : Γ ⊢ A} → t ⇒I t′ ⊎ t ExpandsTo t′ → t ⇒F t′
IR⊎ExpandsTo→FR {⌜◦⌝} {t = t} (left r) = Ired (λ ()) r
IR⊎ExpandsTo→FR {A ⌜⊃⌝ B} {t = t} (left r) with Expandable? t
... | yes x = r ↯ Expandable→¬IR x
... | no ¬x = Ired ¬x r
IR⊎ExpandsTo→FR (right (ηexp⊃ refl x)) = ηexp⊃ refl x