open import Relation.Binary.PropositionalEquality
module Wand
(ext : forall {a b : Set} {f g : a -> b} ->
(forall x -> f x ≡ g x) -> f ≡ g)
(Id : Set)
where
import MultiComposition as MC
open MC ext
open TypeList using (_⟶_)
open import Data.Nat
open import Derivation
open ≡-Reasoning
open import Function hiding (id)
open import Data.Vec
module Language where
data Exp : Set where
id : Id -> Exp
[_+_] : Exp -> Exp -> Exp
V : Set
V = ℕ
S : Set
S = Id -> V
C : Set
C = S -> V
K : Set
K = V -> C
E : Exp -> K -> C
E (id I) = \κ σ -> κ (σ I) σ
E [ e₁ + e₂ ] = \κ -> E e₁ (\v₁ -> E e₂ (\v₂ -> κ (v₁ + v₂)))
P : Exp -> C
P e = E e (\v σ -> v)
module Step₁ where
open Language
mutual
fetch : Id -> K -> C
fetch I = \κ σ -> κ (σ I) σ
add : K -> V -> V -> C
add = \κ v₁ v₂ -> κ (v₁ + v₂)
E' : Exp -> K -> C
E' e = witness (E'P e)
E'P : (e : Exp) -> EqualTo (E e)
E'P (id I) = ▷ begin
(\κ σ -> κ (σ I) σ)
≡⟨ refl ⟩
fetch I
∎
E'P [ e₁ + e₂ ] = ▷ begin
(\κ σ -> E e₁ (\v₁ -> E e₂ (\v₂ -> κ (v₁ + v₂))) σ)
≡⟨ refl ⟩
(\κ -> E e₁ (\v₁ -> E e₂ (\v₂ -> κ (v₁ + v₂))))
≡⟨ refl ⟩
E e₁ ⟪ K ▻ ε ⟫ (\κ v₁ -> E e₂ (\v₂ -> κ (v₁ + v₂)))
≡⟨ refl ⟩
E e₁ ⟪ K ▻ ε ⟫ (E e₂ ⟪ K ▻ V ▻ ε ⟫ (\κ v₁ v₂ -> κ (v₁ + v₂)))
≡⟨ proof (E'P e₁) ⟪ K ▻ ε ⟫-cong
(proof (E'P e₂) ⟪ K ▻ V ▻ ε ⟫-cong refl) ⟩
E' e₁ ⟪ K ▻ ε ⟫ (E' e₂ ⟪ K ▻ V ▻ ε ⟫ (\κ v₁ v₂ -> κ (v₁ + v₂)))
≡⟨ refl ⟩
E' e₁ ⟪ K ▻ ε ⟫ (E' e₂ ⟪ K ▻ V ▻ ε ⟫ add)
∎
mutual
halt : K
halt = \v σ -> v
P' : Exp -> C
P' e = witness (P'P e)
P'P : (e : Exp) -> EqualTo (P e)
P'P e = ▷ begin
E e (\v σ -> v)
≡⟨ refl ⟩
E e ⟪ ε ⟫ (\v σ -> v)
≡⟨ proof (E'P e) ⟪ ε ⟫-cong refl ⟩
E' e ⟪ ε ⟫ halt
∎
module Step₂ where
open Language
data Exp' : Set -> Set1 where
B : forall {a b} ts ->
Exp' (a -> b) -> Exp' (ts ⟶ a) -> Exp' (ts ⟶ b)
add : Exp' (K -> V -> V -> C)
fetch : Id -> Exp' (K -> C)
halt : Exp' K
⟦_⟧ : forall {t} -> Exp' t -> t
⟦ B ts e₁ e₂ ⟧ = ⟦ e₁ ⟧ ⟪ ts ⟫ ⟦ e₂ ⟧
⟦ add ⟧ = Step₁.add
⟦ fetch I ⟧ = Step₁.fetch I
⟦ halt ⟧ = Step₁.halt
comp : Exp -> Exp' (K -> C)
comp (id I) = fetch I
comp [ e₁ + e₂ ] =
B (K ▻ ε) (comp e₁) (B (K ▻ V ▻ ε) (comp e₂) add)
correct : forall e -> Step₁.E' e ≡ ⟦ comp e ⟧
correct (id I) = refl
correct [ e₁ + e₂ ] =
ext (\κ -> cong₂ _$_
(correct e₁)
(ext \v₁ -> cong (\e -> e (Step₁.add κ v₁))
(correct e₂)))
module DerivedCompiler where
data Σ₁ (a : Set1) (b : a -> Set) : Set1 where
_,_ : (x : a) -> b x -> Σ₁ a b
witness₁ : forall {a b} -> Σ₁ a b -> a
witness₁ (x , y) = x
proof₁ : forall {a b} -> (p : Σ₁ a b) -> b (witness₁ p)
proof₁ (x , y) = y
mutual
comp' : Exp -> Exp' (K -> C)
comp' e = witness₁ (comp'P e)
comp'P : (e : Exp) -> Σ₁ _ \e' -> Step₁.E' e ≡ ⟦ e' ⟧
comp'P (id I) =
( fetch I
, (begin
Step₁.fetch I
≡⟨ refl ⟩
⟦ fetch I ⟧
∎)
)
comp'P [ e₁ + e₂ ] =
( B (K ▻ ε) (comp' e₁) (B (K ▻ V ▻ ε) (comp' e₂) add)
,
(begin
Step₁.E' e₁ ⟪ K ▻ ε ⟫ (Step₁.E' e₂ ⟪ K ▻ V ▻ ε ⟫ Step₁.add)
≡⟨ ext (\κ -> cong₂ _$_
(proof₁ (comp'P e₁))
(ext \v₁ -> cong (\e -> e (Step₁.add κ v₁))
(proof₁ (comp'P e₂)))) ⟩
⟦ B (K ▻ ε) (comp' e₁) (B (K ▻ V ▻ ε) (comp' e₂) add) ⟧
∎)
)
correct' : forall e -> E e ≡ ⟦ comp e ⟧
correct' e = begin
E e
≡⟨ proof (Step₁.E'P e) ⟩
Step₁.E' e
≡⟨ correct e ⟩
⟦ comp e ⟧
∎
module Step₂′ where
open Language
data Exp' : {t : Set} -> t -> Set1 where
B : forall {a b} ts {f : a -> b} {g : ts ⟶ a} ->
Exp' f -> Exp' g -> Exp' (f ⟪ ts ⟫ g)
add : Exp' Step₁.add
fetch : (I : Id) -> Exp' (Step₁.fetch I)
halt : Exp' Step₁.halt
⟦_⟧ : forall {t} {f : t} -> Exp' f -> t
⟦_⟧ {f = f} _ = f
comp : (e : Exp) -> Exp' (Step₁.E' e)
comp (id I) = fetch I
comp [ e₁ + e₂ ] =
B (K ▻ ε) (comp e₁) (B (K ▻ V ▻ ε) (comp e₂) add)
correct : forall e -> E e ≡ ⟦ comp e ⟧
correct e = begin
E e
≡⟨ proof (Step₁.E'P e) ⟩
Step₁.E' e
≡⟨ refl ⟩
⟦ comp e ⟧
∎
module Examples (X Y Z : Id) where
open Language
open Step₂′
fig2b : Exp' {C} _
fig2b = B ε l halt
where
llr : Exp' {K -> V -> C} _
llr = B (K ▻ V ▻ ε) (fetch Y) add
ll : Exp' {K -> C} _
ll = B (K ▻ ε) (fetch X) llr
lr : Exp' {K -> V -> C} _
lr = B (K ▻ V ▻ ε) (fetch Z) add
l : Exp' {K -> C} _
l = B (K ▻ ε) ll lr
fig2c : Exp' {C} _
fig2c = B ε (fetch X) step₂
where
step₆ : Exp' {V -> C} _
step₆ = halt
step₅ : Exp' {V -> V -> C} _
step₅ = B ε add step₆
step₄ : Exp' {V -> C} _
step₄ = B (V ▻ ε) (fetch Z) step₅
step₃ : Exp' {V -> V -> C} _
step₃ = B ε add step₄
step₂ : Exp' {V -> C} _
step₂ = B (V ▻ ε) (fetch Y) step₃
module Step₂″ where
open Language
data Exp' : (n : ℕ) -> (K -> V ^ n ⟶ C) -> Set where
B : forall {n f g} ->
Exp' 0 f -> Exp' (suc n) g -> Exp' n (B′ n f g)
add : Exp' 2 Step₁.add
fetch : (I : Id) -> Exp' 0 (Step₁.fetch I)
data ToplevelExp : C -> Set where
Bhalt : forall {f} -> Exp' 0 f -> ToplevelExp (f Step₁.halt)
comp' : (e : Exp) -> Exp' 0 (Step₁.E' e)
comp' (id I) = fetch I
comp' [ e₁ + e₂ ] = B (comp' e₁) (B (comp' e₂) add)
comp : (e : Exp) -> ToplevelExp (Step₁.P' e)
comp e = Bhalt (comp' e)
⟦_⟧ : forall {f} -> ToplevelExp f -> C
⟦_⟧ {f = f} _ = f
correct : forall e -> P e ≡ ⟦ comp e ⟧
correct e = begin
P e
≡⟨ proof (Step₁.P'P e) ⟩
Step₁.P' e
≡⟨ refl ⟩
⟦ comp e ⟧
∎
module Step₃ where
open Language
data Command : (n : ℕ) -> (K -> V ^ n ⟶ C) -> Set where
add : Command 2 Step₁.add
fetch : (I : Id) -> Command 0 (Step₁.fetch I)
mutual
Cont : (m : ℕ) -> (K -> V ^ m ⟶ C) -> Set
Cont m f = forall {n g} ->
LinearExp (suc n) g -> LinearExp (m + n) (B″ m n f g)
data LinearExp : (n : ℕ) -> V ^ n ⟶ C -> Set where
_○_ : forall {m f} -> Command m f -> Cont m f
halt : LinearExp 1 Step₁.halt
rot : forall {m f} -> Step₂″.Exp' m f -> Cont m f
rot Step₂″.add = \k -> add ○ k
rot (Step₂″.fetch I) = \k -> fetch I ○ k
rot (Step₂″.B {m} {f} {g} e₁ e₂) {n} {h} = \k -> cast₁ (rot e₁ (rot e₂ k))
where
cast₁ = subst (LinearExp (m + n)) (rot-lemma m n f g h)
toplevelRot : forall {f} -> Step₂″.ToplevelExp f -> LinearExp 0 f
toplevelRot (Step₂″.Bhalt e) = rot e halt
module Step₄ where
open Language
open Step₃
Stack : ℕ -> Set
Stack = Vec V
⟦_⟧' : forall {a n} -> V ^ n ⟶ a -> Stack n -> a
⟦ f ⟧' [] = f
⟦ f ⟧' (x ∷ s) = ⟦ f x ⟧' s
⟦_⟧ : forall {a n} -> V ^ n ⟶ a -> Stack n -> a
⟦ f ⟧ s = ⟦ f ⟧' (reverse s)
postulate
lemma₁ : forall {n} g x y (s : Stack n) σ ->
⟦ B″ 2 n Step₁.add g ⟧ (x ∷ y ∷ s) σ ≡ ⟦ g ⟧ (y + x ∷ s) σ
lemma₂ : forall {n} g I (s : Stack n) σ ->
⟦ B″ 0 n (Step₁.fetch I) g ⟧ s σ ≡ ⟦ g ⟧ (σ I ∷ s) σ
mutual
exec : forall {n f} -> LinearExp n f -> Stack n -> C
exec e s σ = witness (execP e s σ)
execP : forall {n f} (e : LinearExp n f) (s : Stack n) (σ : S) ->
EqualTo (⟦ f ⟧ s σ)
execP (_○_ add {n} {g} c) (x ∷ y ∷ s) σ = ▷ begin
⟦ B″ 2 n Step₁.add g ⟧ (x ∷ y ∷ s) σ
≡⟨ lemma₁ g x y s σ ⟩
⟦ g ⟧ (y + x ∷ s) σ
≡⟨ proof (execP c (y + x ∷ s) σ) ⟩
exec c (y + x ∷ s) σ
∎
execP (_○_ (fetch I) {n} {g} c) s σ = ▷ begin
⟦ B″ 0 n (Step₁.fetch I) g ⟧ s σ
≡⟨ lemma₂ g I s σ ⟩
⟦ g ⟧ (σ I ∷ s) σ
≡⟨ proof (execP c (σ I ∷ s) σ) ⟩
exec c (σ I ∷ s) σ
∎
execP halt (x ∷ []) σ = ▷ begin x ∎
module Step₅ where
open Language
open Step₃ using () renaming (LinearExp to Code)
open Step₄ using (exec)
comp : (e : Exp) -> Code 0 (Step₁.P' e)
comp e = Step₃.toplevelRot (Step₂″.comp e)
correct : forall e σ -> P e σ ≡ exec (comp e) [] σ
correct e σ = begin
P e σ
≡⟨ cong (\f -> f σ) (proof (Step₁.P'P e)) ⟩
Step₁.P' e σ
≡⟨ proof (Step₄.execP (comp e) [] σ) ⟩
exec (comp e) [] σ
∎