{-# OPTIONS --cubical --safe --postfix-projections #-}
module Data.Dyck.Prog where
open import Prelude
open import Data.Nat using (_+_)
private variable n : ℕ
data Expr : Type where
[_] : ℕ → Expr
_⊕_ : Expr → Expr → Expr
⟨_⟩_↝_ : (ℕ → Type) → ℕ → ℕ → Type
⟨ C ⟩ n ↝ m = ∀ {i} → C (n + i) → C (m + i)
data Code : ℕ → Type where
HALT : Code 1
PUSH : ℕ → ⟨ Code ⟩ 1 ↝ 0
ADD : ⟨ Code ⟩ 1 ↝ 2
Stack : Type → ℕ → Type
Stack A zero = ⊤
Stack A (suc n) = Stack A n × A
infixl 5 _∷_
pattern _∷_ xs x = xs , x
foldl : (P : ℕ → Type) → (A → ⟨ P ⟩ 1 ↝ 0) → Stack A n → P n → P zero
foldl {n = zero} P f tt = id
foldl {n = suc n} P f (xs ∷ x) = foldl P f xs ∘ f x
private variable st : Stack Expr n
code→expr⊙ : Code n → Stack Expr n → Expr
code→expr⊙ HALT (tt ∷ e) = e
code→expr⊙ (PUSH v is) st = code→expr⊙ is (st ∷ [ v ])
code→expr⊙ (ADD is) (st ∷ xs ∷ ys) = code→expr⊙ is (st ∷ xs ⊕ ys)
code→expr : Code 0 → Expr
code→expr ds = code→expr⊙ ds tt
expr→code⊙ : Expr → ⟨ Code ⟩ 1 ↝ 0
expr→code⊙ [ x ] = PUSH x
expr→code⊙ (xs ⊕ ys) = expr→code⊙ xs ∘ expr→code⊙ ys ∘ ADD
expr→code : Expr → Code 0
expr→code xs = expr→code⊙ xs HALT
expr→code→expr⊙ : {is : Code (1 + n)} (e : Expr) →
code→expr⊙ (expr→code⊙ e is) st ≡ code→expr⊙ is (st ∷ e)
expr→code→expr⊙ [ x ] = refl
expr→code→expr⊙ (xs ⊕ ys) = expr→code→expr⊙ xs ; expr→code→expr⊙ ys
code→expr→code⊙ : (is : Code n) →
expr→code (code→expr⊙ is st) ≡ foldl Code expr→code⊙ st is
code→expr→code⊙ HALT = refl
code→expr→code⊙ (PUSH i is) = code→expr→code⊙ is
code→expr→code⊙ (ADD is) = code→expr→code⊙ is
prog-iso : Code 0 ⇔ Expr
prog-iso .fun = code→expr
prog-iso .inv = expr→code
prog-iso .rightInv = expr→code→expr⊙
prog-iso .leftInv = code→expr→code⊙