{-# OPTIONS --safe --sized-types #-}
module Generic.Semantics.Elaboration.State where
open import Data.Product
open import Data.List.Base as L hiding (lookup)
open import Relation.Binary.PropositionalEquality
open import Function.Base
open import Data.Var as V
open import Data.Var.Varlike
open import Data.Environment as E
open import Generic.Syntax
open import Generic.Syntax.STLC+State
open import Generic.Syntax.STLC+Product
open import Generic.Semantics
open import Generic.Semantics.Syntactic
M⟦_⟧ : MType → PType
M⟦ α ⟧ = α
M⟦ 𝟙 ⟧ = 𝟙
M⟦ σ `→ τ ⟧ = M⟦ σ ⟧ `→ M⟦ τ ⟧
M⟦ M σ ⟧ = α `→ (α ⊗ M⟦ σ ⟧)
`→-inj : {σ τ σ₁ τ₁ : PType} → (PType ∋ σ `→ τ) ≡ σ₁ `→ τ₁ → σ ≡ σ₁ × τ ≡ τ₁
`→-inj refl = refl , refl
⊗-inj : {σ τ σ₁ τ₁ : PType} → (PType ∋ σ ⊗ τ) ≡ σ₁ ⊗ τ₁ → σ ≡ σ₁ × τ ≡ τ₁
⊗-inj refl = refl , refl
M⟦⟧-inj : Injective M⟦_⟧
M⟦⟧-inj = record { inj = go _ _ } where
go : (σ τ : MType) → M⟦ σ ⟧ ≡ M⟦ τ ⟧ → σ ≡ τ
go α α eq = refl
go α 𝟙 ()
go α (τ `→ τ₁) ()
go α (M τ) ()
go 𝟙 α ()
go 𝟙 𝟙 eq = refl
go 𝟙 (τ `→ τ₁) ()
go 𝟙 (M τ) ()
go (σ `→ σ₁) α ()
go (σ `→ σ₁) 𝟙 ()
go (σ `→ σ₁) (τ `→ τ₁) eq =
cong₂ _`→_ (go σ τ (proj₁ (`→-inj eq))) (go σ₁ τ₁ (proj₂ (`→-inj eq)))
go (σ `→ α) (M τ) ()
go (σ `→ 𝟙) (M τ) ()
go (σ `→ (σ₁ `→ σ₂)) (M τ) ()
go (σ `→ M σ₁) (M τ) ()
go (M σ) α ()
go (M σ) 𝟙 ()
go (M σ) (τ `→ α) ()
go (M σ) (τ `→ 𝟙) ()
go (M σ) (τ `→ (τ₁ `→ τ₂)) ()
go (M σ) (τ `→ M τ₁) ()
go (M σ) (M τ) eq = cong M (go σ τ (proj₂ (⊗-inj (proj₂ (`→-inj eq)))))
MVAR : MType ─Scoped
MVAR σ Γ = Var M⟦ σ ⟧ (L.map M⟦_⟧ Γ)
vl^MVAR : VarLike MVAR
new vl^MVAR = z
th^𝓥 vl^MVAR {σ} v ρ = M⟦_⟧ V.<$> (lookup ρ {σ} (M⟦⟧-inj <$>⁻¹ v))
MTM : MType ─Scoped
MTM σ Γ = Tm STLCPr _ M⟦ σ ⟧ (L.map M⟦_⟧ Γ)
UnState : Semantics STLCSt MVAR MTM
Semantics.th^𝓥 UnState {σ} = th^𝓥 vl^MVAR {σ}
Semantics.var UnState = `var
Semantics.alg UnState = let open Generic.Syntax.STLC+Product.PATTERNS in λ where
(App σ τ , f , t , refl) → APP f t
(Lam σ τ , b , refl) → LAM (reify {𝓒 = MTM} vl^MVAR (σ ∷ []) τ b)
(One , refl) → ONE
(Get , refl) → LAM (PRD (`var z) (`var z))
(Put , t , refl) → LAM (PRD (`var z) ONE)
(Ret σ , t , refl) → LAM (PRD (`var z) (ren weaken t))
(Bnd σ τ , m , f , refl) → let f′ = ren weaken f ; m′ = ren weaken m in
LAM (APP (CUR f′) (SWP (APP m′ (`var z))))