module ApplicationBased where
open import Derivation
open import Data.Nat
open import Data.Vec
open import Data.Product
open import Function
open import Relation.Binary.PropositionalEquality
open ≡-Reasoning
data Expr : Set where
val : ℕ → Expr
_⊖_ : Expr → Expr → Expr
⟦_⟧ : Expr → ℕ
⟦ val n ⟧ = n
⟦ m ⊖ n ⟧ = ⟦ m ⟧ ∸ ⟦ n ⟧
Stack : Set → ℕ → Set
Stack = Vec
_^_ : Set → ℕ → Set
A ^ zero = A
A ^ suc n = A → A ^ n
_<$_$>_ : ∀ {A} → A → (n : ℕ) → A ^ (1 + n) → A ^ n
x <$ zero $> f = f x
x <$ suc n $> f = λ y → x <$ n $> f y
app : ∀ {A} m {n} → A ^ m → Stack A (m + n) → Stack A (1 + n)
app zero f xs = f ∷ xs
app (suc m) f (x ∷ xs) = app m (x <$ m $> f) xs
module Step₁ where
return : ℕ → ℕ ^ 0
return n = n
sub : ℕ ^ 2
sub m n = m ∸ n
private
mutual
⟦_⟧' : Expr → ℕ ^ 0
⟦ e ⟧' = witness (eval e)
eval : (e : Expr) → EqualTo ⟦ e ⟧
eval (val n) = ▷ begin return n ∎
eval (e₁ ⊖ e₂) = ▷ begin
⟦ e₁ ⟧ ∸ ⟦ e₂ ⟧
≡⟨ cong₂ _∸_ (proof (eval e₁)) (proof (eval e₂)) ⟩
⟦ e₁ ⟧' ∸ ⟦ e₂ ⟧'
≡⟨ refl ⟩
⟦ e₁ ⟧' <$ 0 $> (⟦ e₂ ⟧' <$ 1 $> sub)
∎
module Step₂ where
data Cmd : (n : ℕ) → ℕ ^ n → Set where
return : (n : ℕ) → Cmd 0 (Step₁.return n)
sub : Cmd 2 Step₁.sub
data Tree : (n : ℕ) → ℕ ^ n → Set where
cmd : ∀ {n f} → Cmd n f → Tree n f
_$$_ : ∀ {n x f} →
Tree 0 x → Tree (1 + n) f → Tree n (x <$ n $> f)
comp : (e : Expr) → Tree 0 ⟦ e ⟧
comp (val n) = cmd (return n)
comp (e₁ ⊖ e₂) = comp e₁ $$ (comp e₂ $$ cmd sub)
module Step₃ where
open Step₂ hiding (comp)
open Step₂ hiding (comp) renaming (return to push)
Sem : ℕ → ℕ → Set
Sem i f = Stack ℕ i → Stack ℕ f
data Code : (i f : ℕ) → Sem i f → Set where
ε : ∀ {i} → Code i i id
_◅_ : ∀ {n g i f s} →
Step₂.Cmd n g → Code (1 + i) f s →
Code (n + i) f (s ∘ app n g)
exec : ∀ {m n sem} → Code m n sem → Sem m n
exec {sem = sem} _ = sem
module Details where
exec' : ∀ {m n sem} → Code m n sem → Sem m n
exec' ε s = s
exec' (push x ◅ cs) s = exec' cs (x ∷ s)
exec' (sub ◅ cs) (n ∷ m ∷ s) = exec' cs (m ∸ n ∷ s)
execOK : ∀ {m n sem} (cs : Code m n sem) (s : Stack ℕ m) →
exec cs s ≡ exec' cs s
execOK ε s = refl
execOK (push x ◅ cs) s = execOK cs (x ∷ s)
execOK (sub ◅ cs) (n ∷ m ∷ s) = execOK cs (m ∸ n ∷ s)
comp : ∀ {m n f sem} →
Tree m f → Code (1 + n) 1 sem →
Code (m + n) 1 (sem ∘ app m f)
comp (cmd c) cs = c ◅ cs
comp (t₁ $$ t₂) cs = comp t₁ (comp t₂ cs)
module Step₄ where
Code : Set
Code = ∃ (Step₃.Code 0 1)
comp : Expr → Code
comp e = (_ , Step₃.comp (Step₂.comp e) Step₃.ε)
exec : Code → ℕ
exec cs = head (Step₃.exec (proj₂ cs) [])
correct : (e : Expr) → ⟦ e ⟧ ≡ exec (comp e)
correct e = refl