{-# OPTIONS --safe #-}
module Pat.Term where
open import Data.Nat using (ℕ; suc; zero; _≥‴_; ≤‴-refl; ≤‴-step)
open import Function using (id; _∘_)
open import Pat.Context
data Term : (n : ℕ) → Context n → Type n → Set
infix 4 Term
syntax Term n Γ A = Γ ⊢ A ^ n
infix 4 _⊩_
infix 4 _⊩[_⊢_^_]
infix 4 _∣_⊩_↝_
infix 4 _∣_⊩[_⊢_^_]↝_
infixl 5 _,_
infixl 5 _++ˢ_
data _⊩[_⊢_^_] Γ′ {m} (Δ : Context m) (A : Type m) (m≥n : m ≥‴ n) : Set where
term
: (e : Γ′ ↾≥ m≥n ++ Δ ⊢ A ^ m)
→ Γ′ ⊩[ Δ ⊢ A ^ m≥n ]
var
: (x : Γ′ ∋[ Δ ⊢ A ^ m≥n ])
→ Γ′ ⊩[ Δ ⊢ A ^ m≥n ]
data _⊩_ (Γ′ : Context n) : Context n → Set where
∅ : Γ′ ⊩ ∅
_,_ : (σ : Γ′ ⊩ Γ) → (item : Γ′ ⊩[ Δ ⊢ A ^ m≥n ]) → Γ′ ⊩ Γ ,[ Δ ⊢ A ^ m≥n ]
_++ˢ_ : Γ′ ⊩ Γ₁ → Γ′ ⊩ Γ₂ → Γ′ ⊩ Γ₁ ++ Γ₂
lookup : Γ′ ⊩ Γ → Γ ∋[ Δ ⊢ A ^ m≥n ] → Γ′ ⊩[ Δ ⊢ A ^ m≥n ]
lookup (σ , e) Z = e
lookup (σ , e) (S x) = lookup σ x
lookup (σ₁ ++ˢ σ₂) (L x) = lookup σ₁ x
lookup (σ₁ ++ˢ σ₂) (R x) = lookup σ₂ x
lookup⁻¹ : (f : ∀ {m} {Δ} {A} {m≥n : m ≥‴ _} → Γ ∋[ Δ ⊢ A ^ m≥n ] → Γ′ ⊩[ Δ ⊢ A ^ m≥n ]) → Γ′ ⊩ Γ
lookup⁻¹ {Γ = ∅} f = ∅
lookup⁻¹ {Γ = Γ ,[ _ ⊢ _ ^ _ ]} f = lookup⁻¹ (f ∘ S) , f Z
lookup⁻¹ {Γ = Γ₁ ++ Γ₂} f = lookup⁻¹ (f ∘ L) ++ˢ lookup⁻¹ (f ∘ R)
infixl 5 _++ˢ♭_
_++ˢ♭_ : Γ′ ⊩ Γ → Γ′ ⊩ Δ → Γ′ ⊩ Γ ++♭ Δ
σ₁ ++ˢ♭ ∅ = σ₁
σ₁ ++ˢ♭ (σ₂ , item) = σ₁ ++ˢ♭ σ₂ , item
σ₁ ++ˢ♭ (σ₂ ++ˢ σ₃) = σ₁ ++ˢ♭ σ₂ ++ˢ♭ σ₃
Subst : Context n → Context n → Set
Subst Γ Γ′ = Γ′ ⊩ Γ
variable
Π Π′ Π₁ Π₂ Π₃ : Context n
infix 4 Pattern
syntax Pattern n Γ Δ A Π = Γ ∣ Δ ⊢ A ^ n ↝ Π
data Pattern : (n : ℕ) → Context n → Context n → Type n → Context n → Set
data _∣_⊩[_⊢_^_]↝_ (Γ′ Δ : Context n) {m} (Δ′ : Context m) (A : Type m) (m≥n : m ≥‴ n) : (Π : Context m) → Set where
term
: (p : Γ′ ↾≥ m≥n ∣ Δ ↾≥ m≥n ++ Δ′ ⊢ A ^ m ↝ Π)
→ Γ′ ∣ Δ ⊩[ Δ′ ⊢ A ^ m≥n ]↝ Π
var
: (x : Γ′ ++ Δ ∋[ Δ′ ⊢ A ^ m≥n ])
→ Γ′ ∣ Δ ⊩[ Δ′ ⊢ A ^ m≥n ]↝ ∅
data _∣_⊩_↝_ (Γ′ : Context n) (Δ : Context n) : Context n → (Π : Context n) → Set where
∅ : Γ′ ∣ Δ ⊩ ∅ ↝ ∅
_,_
: (π : Γ′ ∣ Δ ⊩ Γ ↝ Π₁)
→ (item : Γ′ ∣ Δ ⊩[ Δ′ ⊢ A ^ m≥n ]↝ Π₂)
→ Γ′ ∣ Δ ⊩ Γ ,[ Δ′ ⊢ A ^ m≥n ] ↝ Π₁ ++♭ inject≥ m≥n Π₂
_++ˢᵖ_
: (π₁ : Γ′ ∣ Δ ⊩ Γ ↝ Π₁)
→ (π₂ : Γ′ ∣ Δ ⊩ Δ′ ↝ Π₂)
→ Γ′ ∣ Δ ⊩ Γ ++ Δ′ ↝ Π₁ ++♭ Π₂
data Pattern where
`pat
: Γ ∣ Δ ⊢ A ^ n ↝ ∅ ,[ Δ ⊢ A ^ ≤‴-refl ]
`_`with₁_
: (x : Γ ∋[ Δ′ ⊢ A ^ ≤‴-refl ])
→ (σ : Γ ++ Δ ⊩ Δ′)
→ Γ ∣ Δ ⊢ A ^ n ↝ ∅
`_`with₂_
: (x : Δ ∋[ Δ′ ⊢ A ^ ≤‴-refl ])
→ (π : Γ ∣ Δ ⊩ Δ′ ↝ Π)
→ Γ ∣ Δ ⊢ A ^ n ↝ Π
`true
: Γ ∣ Δ ⊢ `Bool ^ n ↝ ∅
`false
: Γ ∣ Δ ⊢ `Bool ^ n ↝ ∅
`if_`then_`else_
: (p₁ : Γ ∣ Δ ⊢ `Bool ^ n ↝ Π₁)
→ (p₂ : Γ ∣ Δ ⊢ A ^ n ↝ Π₂)
→ (p₃ : Γ ∣ Δ ⊢ A ^ n ↝ Π₃)
→ Γ ∣ Δ ⊢ A ^ n ↝ Π₁ ++♭ Π₂ ++♭ Π₃
`λ⟨_⟩_
: ∀ Δ′
→ (p : Γ ∣ Δ ,[ inject₁ Δ′ ⊢ A ^ ≤‴-refl ] ⊢ B ^ n ↝ Π)
→ Γ ∣ Δ ⊢ [ Δ′ ⊢ A ]⇒ B ^ n ↝ Π
_·_
: (p₁ : Γ ∣ Δ ⊢ [ Δ′ ⊢ A ]⇒ B ^ n ↝ Π₁)
→ (p₂ : Γ ∣ Δ ++ inject₁ Δ′ ⊢ A ^ n ↝ Π₂)
→ Γ ∣ Δ ⊢ B ^ n ↝ Π₁ ++♭ Π₂
⟨_⟩
: (p : Γ ↾ ∣ Δ ↾ ⊢ A ^ suc n ↝ Π)
→ Γ ∣ Δ ⊢ ◯ A ^ n ↝ inject₁ Π
`let⟨_⟩
: ∀ Δ′
→ (p₁ : Γ ∣ Δ ++ inject₁ Δ′ ⊢ ◯ A ^ n ↝ Π₁)
→ (p₂ : Γ ∣ Δ ,[ Δ′ ⊢ A ^ ≤‴-step ≤‴-refl ] ⊢ B ^ n ↝ Π₂)
→ Γ ∣ Δ ⊢ B ^ n ↝ Π₁ ++♭ Π₂
`wrap : ∀ Δ′
→ (e : Γ ∣ Δ ++ inject₁ Δ′ ⊢ A ^ n ↝ Π)
→ Γ ∣ Δ ⊢ Δ′ ▷ A ^ n ↝ Π
`letwrap : ∀ Δ′
→ (e₁ : Γ ∣ Δ ⊢ Δ′ ▷ A ^ n ↝ Π₁)
→ (e₂ : Γ ∣ Δ ,[ inject₁ Δ′ ⊢ A ^ ≤‴-refl ] ⊢ B ^ n ↝ Π₂)
→ Γ ∣ Δ ⊢ B ^ n ↝ Π₁ ++♭ Π₂
`iflet⟨_⟩
: ∀ Δ′
→ (p : Γ ↾ ++ (Δ ↾) ∣ Δ′ ⊢ A ^ suc n ↝ Π)
→ (p₁ : Γ ∣ Δ ++ inject₁ Δ′ ⊢ ◯ A ^ n ↝ Π₁)
→ (p₂ : Γ ∣ Δ ++ inject₁ Π ⊢ B ^ n ↝ Π₂)
→ (p₃ : Γ ∣ Δ ⊢ B ^ n ↝ Π₃)
→ Γ ∣ Δ ⊢ B ^ n ↝ Π₁ ++♭ Π₂ ++♭ Π₃
`rewrite
: (p₁ : Γ ∣ Δ ⊢ ◯ A ^ n ↝ Π₁)
→ (p : Γ ↾ ++ (Δ ↾) ∣ ∅ ⊢ B ^ suc n ↝ Π)
→ (p₂ : Γ ∣ Δ ++ inject₁ Π ⊢ ◯ B ^ n ↝ Π₂)
→ Γ ∣ Δ ⊢ ◯ A ^ n ↝ Π₁ ++♭ Π₂
infix 5 `λ⟨_⟩_
infixl 7 _·_
infixr 7 `if_`then_`else_
infix 9 `_`with_
data Term where
`_`with_
: (x : Γ ∋[ Δ ⊢ A ^ ≤‴-refl ])
→ (σ : Γ ⊩ Δ)
→ Γ ⊢ A ^ n
`true
: Γ ⊢ `Bool ^ n
`false
: Γ ⊢ `Bool ^ n
`if_`then_`else_
: (e₁ : Γ ⊢ `Bool ^ n)
→ (e₂ : Γ ⊢ A ^ n)
→ (e₃ : Γ ⊢ A ^ n)
→ Γ ⊢ A ^ n
`λ⟨_⟩_
: ∀ Δ
→ (e : Γ ,[ inject₁ Δ ⊢ A ^ ≤‴-refl ] ⊢ B ^ n)
→ Γ ⊢ [ Δ ⊢ A ]⇒ B ^ n
_·_
: (e₁ : Γ ⊢ [ Δ ⊢ A ]⇒ B ^ n)
→ (e₂ : Γ ++ inject₁ Δ ⊢ A ^ n)
→ Γ ⊢ B ^ n
⟨_⟩
: (e : Γ ↾ ⊢ A ^ suc n)
→ Γ ⊢ ◯ A ^ n
`let⟨_⟩ : ∀ Δ
→ (e₁ : Γ ++ inject₁ Δ ⊢ ◯ A ^ n)
→ (e₂ : Γ ,[ Δ ⊢ A ^ ≤‴-step ≤‴-refl ] ⊢ B ^ n)
→ Γ ⊢ B ^ n
`wrap : ∀ Δ
→ (e : Γ ++ inject₁ Δ ⊢ A ^ n)
→ Γ ⊢ Δ ▷ A ^ n
`letwrap : ∀ Δ
→ (e₁ : Γ ⊢ Δ ▷ A ^ n)
→ (e₂ : Γ ,[ inject₁ Δ ⊢ A ^ ≤‴-refl ] ⊢ B ^ n)
→ Γ ⊢ B ^ n
`iflet⟨_⟩ : ∀ Δ
→ (p : Γ ↾ ∣ Δ ⊢ A ^ suc n ↝ Π)
→ (e₁ : Γ ++ inject₁ Δ ⊢ ◯ A ^ n)
→ (e₂ : Γ ++ inject₁ Π ⊢ B ^ n)
→ (e₃ : Γ ⊢ B ^ n)
→ Γ ⊢ B ^ n
`rewrite
: (e₁ : Γ ⊢ ◯ A ^ n)
→ (p : Γ ↾ ∣ ∅ ⊢ B ^ suc n ↝ Π)
→ (e₂ : Γ ++ inject₁ Π ⊢ ◯ B ^ n)
→ Γ ⊢ ◯ A ^ n
rename : Rename Γ Γ′ → Γ ⊢ A ^ n → Γ′ ⊢ A ^ n
renameSubst : Rename Γ Γ′ → Γ ⊩ Δ → Γ′ ⊩ Δ
renameSubstItem : Rename Γ Γ′ → Γ ⊩[ Δ ⊢ A ^ m≥n ] → Γ′ ⊩[ Δ ⊢ A ^ m≥n ]
renamePattern : Rename Γ Γ′ → Γ ∣ Δ ⊢ A ^ n ↝ Π → Γ′ ∣ Δ ⊢ A ^ n ↝ Π
renameSubstPattern : Rename Γ Γ′ → Γ ∣ Δ ⊩ Δ′ ↝ Π → Γ′ ∣ Δ ⊩ Δ′ ↝ Π
renameSubstPatternItem : Rename Γ Γ′ → Γ ∣ Δ ⊩[ Δ′ ⊢ A ^ m≥n ]↝ Π → Γ′ ∣ Δ ⊩[ Δ′ ⊢ A ^ m≥n ]↝ Π
rename ρ (` x `with σ) = ` ρ x `with renameSubst ρ σ
rename ρ `true = `true
rename ρ `false = `false
rename ρ (`if e₁ `then e₂ `else e₃) = `if rename ρ e₁ `then rename ρ e₂ `else rename ρ e₃
rename ρ (`λ⟨ Δ ⟩ e) = `λ⟨ Δ ⟩ (rename (ext ρ) e)
rename ρ (e₁ · e₂) = rename ρ e₁ · rename (ext++ _ ρ) e₂
rename ρ ⟨ e ⟩ = ⟨ rename (ext↾ ρ) e ⟩
rename ρ (`let⟨ Δ ⟩ e₁ e₂) = `let⟨ Δ ⟩ (rename (ext++ (inject₁ Δ) ρ) e₁) (rename (ext ρ) e₂)
rename ρ (`iflet⟨ Δ ⟩ p e₁ e₂ e₃) = `iflet⟨ Δ ⟩ (renamePattern (ext↾ ρ) p) (rename (ext++ (inject₁ Δ) ρ) e₁) (rename (ext++ (inject₁ _) ρ) e₂) (rename ρ e₃)
rename ρ (`wrap Δ e) = `wrap Δ (rename (ext++ (inject₁ Δ) ρ) e)
rename ρ (`letwrap Δ e₁ e₂) = `letwrap Δ (rename ρ e₁) (rename (ext ρ) e₂)
rename ρ (`rewrite e₁ p e₂) = `rewrite (rename ρ e₁) (renamePattern (ext↾ ρ) p) (rename (ext++ _ ρ) e₂)
renameSubst ρ ∅ = ∅
renameSubst ρ (σ , item) = renameSubst ρ σ , renameSubstItem ρ item
renameSubst ρ (σ₁ ++ˢ σ₂) = renameSubst ρ σ₁ ++ˢ renameSubst ρ σ₂
renameSubstItem {Δ = Δ} {m≥n = m≥n} ρ (term e) = term (rename (ext++ Δ (ext↾≥ m≥n ρ)) e)
renameSubstItem ρ (var x) = var (ρ x)
renamePattern ρ `pat = `pat
renamePattern ρ (` x `with₁ σ) = ` ρ x `with₁ renameSubst (ext++ _ ρ) σ
renamePattern ρ (` x `with₂ π) = ` x `with₂ renameSubstPattern ρ π
renamePattern ρ `true = `true
renamePattern ρ `false = `false
renamePattern ρ (`if p₁ `then p₂ `else p₃)
= `if (renamePattern ρ p₁) `then (renamePattern ρ p₂) `else (renamePattern ρ p₃)
renamePattern ρ (`λ⟨ Δ′ ⟩ p) = `λ⟨ Δ′ ⟩ renamePattern ρ p
renamePattern ρ (p₁ · p₂) = renamePattern ρ p₁ · renamePattern ρ p₂
renamePattern ρ (⟨ p ⟩) = ⟨ renamePattern (ext↾ ρ) p ⟩
renamePattern ρ (`let⟨ Δ ⟩ p₁ p₂) = `let⟨ Δ ⟩ (renamePattern ρ p₁) (renamePattern ρ p₂)
renamePattern ρ (`iflet⟨ Δ′ ⟩ p e₁ e₂ e₃) = `iflet⟨ Δ′ ⟩ (renamePattern (ext++ _ (ext↾ ρ)) p) (renamePattern ρ e₁) (renamePattern ρ e₂) (renamePattern ρ e₃)
renamePattern ρ (`wrap Δ p) = `wrap Δ (renamePattern ρ p)
renamePattern ρ (`letwrap Δ p₁ p₂) = `letwrap Δ (renamePattern ρ p₁) (renamePattern ρ p₂)
renamePattern ρ (`rewrite e₁ p e₂) = `rewrite (renamePattern ρ e₁) (renamePattern (ext++ _ (ext↾ ρ)) p) (renamePattern ρ e₂)
renameSubstPattern ρ ∅ = ∅
renameSubstPattern ρ (π , item) = renameSubstPattern ρ π , renameSubstPatternItem ρ item
renameSubstPattern ρ (π₁ ++ˢᵖ π₂) = renameSubstPattern ρ π₁ ++ˢᵖ renameSubstPattern ρ π₂
renameSubstPatternItem {m≥n = m≥n} ρ (term p) = term (renamePattern (ext↾≥ m≥n ρ) p)
renameSubstPatternItem ρ (var x) = var ((ext++ _ ρ) x)
renameSubstʳ : Rename Δ′ Δ → Γ ⊩ Δ → Γ ⊩ Δ′
renameSubstʳ ρ σ = lookup⁻¹ (lookup σ ∘ ρ)
lift : Rename Γ Γ′ → Subst Γ Γ′
lift ρ = lookup⁻¹ (var ∘ ρ)
exts : Subst Γ Γ′ → Subst (Γ ,[ Δ ⊢ A ^ m≥n ]) (Γ′ ,[ Δ ⊢ A ^ m≥n ])
exts {Δ = Δ} {m≥n = m≥n} σ = renameSubst S σ , var Z
exts++ : ∀ Δ → Subst Γ Γ′ → Subst (Γ ++ Δ) (Γ′ ++ Δ)
exts++ Δ σ = renameSubst L σ ++ˢ lift R
⊩[]-↾⁻ : Γ ↾ ⊩[ Δ ⊢ A ^ m≥n ] → Γ ⊩[ Δ ⊢ A ^ ≤‴-step m≥n ]
⊩[]-↾⁻ (term e) = term e
⊩[]-↾⁻ (var x) = var (∋-↾⁻ x)
⊩[]-↾⁺ : Γ ⊩[ Δ ⊢ A ^ ≤‴-step m≥n ] → Γ ↾ ⊩[ Δ ⊢ A ^ m≥n ]
⊩[]-↾⁺ (term e) = term e
⊩[]-↾⁺ (var x) = var (∋-↾⁺ x)
exts↾ : Subst Γ Γ′ → Subst (Γ ↾) (Γ′ ↾)
exts↾ ∅ = ∅
exts↾ (_,_ {m≥n = ≤‴-refl} σ item) = exts↾ σ
exts↾ (_,_ {m≥n = ≤‴-step m≥n} σ item) = exts↾ σ , ⊩[]-↾⁺ item
exts↾ (σ₁ ++ˢ σ₂) = exts↾ σ₁ ++ˢ exts↾ σ₂
exts↾≥ : (m≥n : m ≥‴ n) → Subst Γ Γ′ → Subst (Γ ↾≥ m≥n) (Γ′ ↾≥ m≥n)
exts↾≥ ≤‴-refl σ = σ
exts↾≥ (≤‴-step sm≥n) σ = exts↾≥ sm≥n (exts↾ σ)
⊩-↾⁻ : Γ ↾ ⊩ Δ → Γ ⊩ inject₁ Δ
⊩-↾⁻ ∅ = ∅
⊩-↾⁻ (σ , item) = ⊩-↾⁻ σ , ⊩[]-↾⁻ item
⊩-↾⁻ (σ₁ ++ˢ σ₂) = ⊩-↾⁻ σ₁ ++ˢ ⊩-↾⁻ σ₂
⊩-↾⁺ : Γ ⊩ inject₁ Δ → Γ ↾ ⊩ Δ
⊩-↾⁺ {Δ = ∅} ∅ = ∅
⊩-↾⁺ {Δ = Δ ,[ _ ^ _ ]} (σ , item) = ⊩-↾⁺ σ , ⊩[]-↾⁺ item
⊩-↾⁺ {Δ = Δ₁ ++ Δ₂} (σ₁ ++ˢ σ₂) = ⊩-↾⁺ σ₁ ++ˢ ⊩-↾⁺ σ₂
⊩-↾≥⁻ : ∀ m≥n → Γ ↾≥ m≥n ⊩ Δ → Γ ⊩ inject≥ m≥n Δ
⊩-↾≥⁻ ≤‴-refl σ = σ
⊩-↾≥⁻ (≤‴-step m≥n) σ = ⊩-↾⁻ (⊩-↾≥⁻ m≥n σ)
⊩-↾≥⁺ : ∀ m≥n → Γ ⊩ inject≥ m≥n Δ → Γ ↾≥ m≥n ⊩ Δ
⊩-↾≥⁺ ≤‴-refl σ = σ
⊩-↾≥⁺ (≤‴-step m≥n) σ = ⊩-↾≥⁺ m≥n (⊩-↾⁺ σ)
⊩[]-inject₁⁻ : inject₁ Γ ⊩[ Δ′ ⊢ A ^ ≤‴-step m≥n ] → Γ ⊩[ Δ′ ⊢ A ^ m≥n ]
⊩[]-inject₁⁻ {Δ′ = Δ′} {m≥n = m≥n} (term e) = term (rename (ext++ Δ′ (ext↾≥ m≥n (∋-inject₁⁻ ∘ ∋-↾⁻))) e)
⊩[]-inject₁⁻ (var x) = var (∋-inject₁⁻ x)
⊩[]-inject₁⁺ : Γ ⊩[ Δ′ ⊢ A ^ m≥n ] → inject₁ Γ ⊩[ Δ′ ⊢ A ^ ≤‴-step m≥n ]
⊩[]-inject₁⁺ {Δ′ = Δ′} {m≥n = m≥n} (term e) = term (rename (ext++ Δ′ (ext↾≥ m≥n (∋-↾⁺ ∘ ∋-inject₁⁺))) e)
⊩[]-inject₁⁺ (var x) = var (∋-inject₁⁺ x)
⊩-inject₁⁻ : inject₁ Γ′ ⊩ inject₁ Γ → Γ′ ⊩ Γ
⊩-inject₁⁻ {Γ = ∅} ∅ = ∅
⊩-inject₁⁻ {Γ = Γ ,[ Δ ⊢ A ^ m≥n ]} (σ , item) = ⊩-inject₁⁻ σ , ⊩[]-inject₁⁻ item
⊩-inject₁⁻ {Γ = Γ ++ Δ} (σ₁ ++ˢ σ₂) = ⊩-inject₁⁻ σ₁ ++ˢ ⊩-inject₁⁻ σ₂
⊩-inject₁⁺ : Γ′ ⊩ Γ → inject₁ Γ′ ⊩ inject₁ Γ
⊩-inject₁⁺ {Γ = ∅} ∅ = ∅
⊩-inject₁⁺ {Γ = Γ ,[ Δ ⊢ A ^ m≥n ]} (σ , item) = ⊩-inject₁⁺ σ , ⊩[]-inject₁⁺ item
⊩-inject₁⁺ {Γ = Γ ++ Δ} (σ₁ ++ˢ σ₂) = ⊩-inject₁⁺ σ₁ ++ˢ ⊩-inject₁⁺ σ₂