{-# OPTIONS --safe #-}
module Splice.Translate where
open import Data.Nat.Base using (ℕ; zero; suc; _≥‴_; ≤‴-refl; ≤‴-step)
open import Relation.Binary.PropositionalEquality.Core using (_≡_; refl; cong; subst)
import Splice.Context as S
import Splice.Term as S
import CtxTyp.Context as C
import CtxTyp.Term as C
variable
n m n′ m′ n″ m″ : ℕ
m≥n m′≥n : m ≥‴ n
◯^ : m ≥‴ n → S.Type m → S.Type n
◯^ ≤‴-refl A = A
◯^ (≤‴-step m≥n) A = S.◯ (◯^ m≥n A)
infixr 7 _^_⇛_ _⇛₀_ _⇛₁_
_^_⇛_ : C.Context m → m ≥‴ n → S.Type n → S.Type n
⟦_⟧ᵗ : C.Type n → S.Type n
_⇛₀_ : C.Context n → S.Type n → S.Type n
Δ ⇛₀ A = Δ ^ ≤‴-refl ⇛ A
_⇛₁_ : C.Context (suc n) → S.Type n → S.Type n
Δ ⇛₁ A = _^_⇛_ Δ (≤‴-step ≤‴-refl) A
C.∅ ^ m≥n ⇛ A = A
(Γ C.,[ Δ C.⊢ A′ ^ m′≥m ]) ^ m≥n ⇛ A = _^_⇛_ Γ m≥n (◯^ m≥n (◯^ m′≥m (Δ ⇛₀ ⟦ A′ ⟧ᵗ)) S.⇒ A)
⟦ C.[ Δ ⊢ A ]⇒ B ⟧ᵗ = (Δ ⇛₁ ⟦ A ⟧ᵗ) S.⇒ ⟦ B ⟧ᵗ
⟦ Δ C.▷ A ⟧ᵗ = (Δ ⇛₁ ⟦ A ⟧ᵗ)
⟦ C.`Bool ⟧ᵗ = S.`Bool
⟦ C.◯ A ⟧ᵗ = S.◯ ⟦ A ⟧ᵗ
⟦_⟧ᶜ : C.Context n → S.Context
⟦ C.∅ ⟧ᶜ = S.∅
⟦ Γ C.,[ Δ C.⊢ A ^ m≥n ] ⟧ᶜ = ⟦ Γ ⟧ᶜ S., (Δ ⇛₀ ⟦ A ⟧ᵗ)
⟦_⟧ˣ : ∀ {Γ} {Δ} {A} {m≥n : m ≥‴ n} → Γ C.∋[ Δ C.⊢ A ^ m≥n ] → ⟦ Γ ⟧ᶜ S.∋ (_^_⇛_ Δ ≤‴-refl ⟦ A ⟧ᵗ) ^ _
⟦ C.Z ⟧ˣ = S.Z
⟦ C.S x ⟧ˣ = S.S ⟦ x ⟧ˣ
inject₁-⇛₀ : ∀ Δ {A : S.Type n} → C.inject₁ Δ ⇛₀ A ≡ Δ ⇛₁ A
inject₁-⇛₀ C.∅ = refl
inject₁-⇛₀ (Δ C.,[ Δ′ C.⊢ A′ ^ m≥n ]) = inject₁-⇛₀ Δ
⟨_⟩^_ : ∀ {Γ} {A} → S.Term m Γ A → (m≥n : m ≥‴ n) → S.Term n Γ (◯^ m≥n A)
⟨ e ⟩^ ≤‴-refl = e
⟨ e ⟩^ ≤‴-step m≥n = S.⟨ ⟨ e ⟩^ m≥n ⟩
$^ : ∀ {Γ} {A} → (m≥n : m ≥‴ n) → S.Term n Γ (◯^ m≥n A) → S.Term m Γ A
$^ ≤‴-refl e = e
$^ (≤‴-step m≥n) e = $^ m≥n (S.$ e)
`λλ : ∀ {Γ} Δ {A} → S.Term n ⟦ Γ C.++ Δ ⟧ᶜ A → S.Term n ⟦ Γ ⟧ᶜ (Δ ⇛₀ A)
`λλ C.∅ e = e
`λλ (Δ C.,[ Δ₁ C.⊢ A ^ m≥n ]) e = `λλ Δ (S.`λ S.subst (λ { S.Z → $^ m≥n (S.` S.Z); (S.S x) → S.` S.S x }) e)
`λλ₁ : ∀ {Γ} Δ {A} → S.Term (suc n) ⟦ Γ C.++ C.inject₁ Δ ⟧ᶜ A → S.Term (suc n) ⟦ Γ ⟧ᶜ (Δ ⇛₀ A)
`λλ₁ C.∅ e = e
`λλ₁ (Δ C.,[ Δ₁ C.⊢ A ^ m≥n ]) e = `λλ₁ Δ (S.`λ S.subst (λ { S.Z → $^ m≥n (S.` S.Z); (S.S x) → S.` S.S x }) e)
`λλ◯ : ∀ {Γ} Δ {A} → S.Term n ⟦ Γ C.++ C.inject₁ Δ ⟧ᶜ A → S.Term n ⟦ Γ ⟧ᶜ (Δ ⇛₁ A)
`λλ◯ C.∅ e = e
`λλ◯ (Δ C.,[ Δ₁ C.⊢ A ^ m≥n ]) e = `λλ◯ Δ (S.`λ S.subst (λ { S.Z → $^ m≥n (S.$ (S.` S.Z)); (S.S x) → S.` S.S x }) e)
wk↾ : ∀ {Γ : C.Context n} → S.Rename ⟦ Γ C.↾ ⟧ᶜ ⟦ Γ ⟧ᶜ
wk↾ {Γ = Γ C.,[ Δ C.⊢ A ^ ≤‴-refl ]} x = S.S (wk↾ x)
wk↾ {Γ = Γ C.,[ Δ C.⊢ A ^ ≤‴-step m≥n ]} S.Z = S.Z
wk↾ {Γ = Γ C.,[ Δ C.⊢ A ^ ≤‴-step m≥n ]} (S.S x) = S.S (wk↾ x)
wk↾≥ : ∀ {Γ : C.Context n} → (m≥n : m ≥‴ n) → S.Rename ⟦ Γ C.↾≥ m≥n ⟧ᶜ ⟦ Γ ⟧ᶜ
wk↾≥ ≤‴-refl x = x
wk↾≥ (≤‴-step m≥n) x = wk↾ (wk↾≥ m≥n x)
applyTerm : ∀ {Γ} {Δ} {A} → S.Term n ⟦ Γ ⟧ᶜ (Δ ⇛₀ A) → Γ C.⊩ Δ → S.Term n ⟦ Γ ⟧ᶜ A
⟦_⟧ᵉ : ∀ {Γ} {A} → C.Term n Γ A → S.Term n (⟦ Γ ⟧ᶜ) (⟦ A ⟧ᵗ)
applyTerm e C.∅ = e
applyTerm e (C._,_ {Δ = Δ} {m≥n = m≥n} σ (C.term e′)) = applyTerm e σ S.· ⟨ S.rename (wk↾≥ m≥n) (`λλ Δ ⟦ e′ ⟧ᵉ) ⟩^ m≥n
applyTerm e (C._,_ {m≥n = m≥n} σ (C.var y)) = applyTerm e σ S.· (⟨ S.` ⟦ y ⟧ˣ ⟩^ m≥n)
⟦ C.` x `with σ ⟧ᵉ = applyTerm (S.` ⟦ x ⟧ˣ) σ
⟦ C.`true ⟧ᵉ = S.`true
⟦ C.`false ⟧ᵉ = S.`false
⟦ C.`if e₁ `then e₂ `else e₃ ⟧ᵉ = S.`if ⟦ e₁ ⟧ᵉ `then ⟦ e₂ ⟧ᵉ `else ⟦ e₃ ⟧ᵉ
⟦ C.`λ⟨ Δ ⟩ e ⟧ᵉ = S.`λ subst (λ d → (S.Term _ (_ S., d) _)) (inject₁-⇛₀ Δ) ⟦ e ⟧ᵉ
⟦ e₁ C.· e₂ ⟧ᵉ = ⟦ e₁ ⟧ᵉ S.· `λλ◯ _ ⟦ e₂ ⟧ᵉ
⟦ C.⟨ e ⟩ ⟧ᵉ = S.⟨ S.rename wk↾ ⟦ e ⟧ᵉ ⟩
⟦ C.`let⟨ Δ ⟩ e₁ e₂ ⟧ᵉ =
S.`let S.⟨ `λλ₁ Δ (S.$ ⟦ e₁ ⟧ᵉ) ⟩ `in
S.subst (λ {S.Z → S.$ (S.` S.Z); (S.S x) → S.` S.S x }) ⟦ e₂ ⟧ᵉ
⟦ C.`wrap Δ e ⟧ᵉ = `λλ◯ Δ ⟦ e ⟧ᵉ
⟦ C.`letwrap Δ e₁ e₂ ⟧ᵉ = S.`let ⟦ e₁ ⟧ᵉ `in subst (λ ΔA → (S.Term _ (_ S., ΔA) _)) (inject₁-⇛₀ Δ) ⟦ e₂ ⟧ᵉ