module stlc.catComb.compile where
open import Data.List
open import stlc.term
open import stlc.value
open import stlc.catComb public
open import stlc.inst
open import context
open import stlc.monad
open import stlc.monad.impl
⟦_⟧ : ∀ {Γ A} → Γ ⊢ A → CatComb (ctxToType Γ) A
⟦ ⟨⟩ ⟧ = !
⟦ `nat n ⟧ = nat n
⟦ ` Z ⟧ = p₂
⟦ ` (S x) ⟧ = ⟦ ` x ⟧ ∘ p₁
⟦ ƛ M ⟧ = cur ⟦ M ⟧
⟦ M · N ⟧ = app ∘ ⟨ ⟦ M ⟧ , ⟦ N ⟧ ⟩
⟦ fst M ⟧ = p₁ ∘ ⟦ M ⟧
⟦ snd M ⟧ = p₂ ∘ ⟦ M ⟧
⟦ M , N ⟧ = ⟨ ⟦ M ⟧ , ⟦ N ⟧ ⟩
⟦ inl M ⟧ = i1 ∘ ⟦ M ⟧
⟦ inr M ⟧ = i2 ∘ ⟦ M ⟧
⟦ case M inl M₁ inr M₂ ⟧ = [_,_] ⟦ M₁ ⟧ ⟦ M₂ ⟧ ∘ ⟨ id , ⟦ M ⟧ ⟩
⟦ [] ⟧ = nil ∘ !
⟦ h ⦂ t ⟧ = cons ∘ ⟨ ⟦ h ⟧ , ⟦ t ⟧ ⟩
⟦ it x r l ⟧ = it ⟦ x ⟧ ⟦ r ⟧ ∘ ⟨ id , ⟦ l ⟧ ⟩
⟦ `let_`in_ {s = s} x x₁ ⟧ = bind {s = s} ∘ ⟨ ⟦ x ⟧ , cur ⟦ x₁ ⟧ ⟩
⟦ return {m = m} x ⟧ = ret {m = m} ∘ ⟦ x ⟧
useMonadImpl : ∀ {A B} → CatComb A B → CatComb A B
useMonadImpl ! = !
useMonadImpl (nat x) = nat x
useMonadImpl id = id
useMonadImpl (x ∘ x₁) = useMonadImpl x ∘ useMonadImpl x₁
useMonadImpl ⟨ x , x₁ ⟩ = ⟨ useMonadImpl x , useMonadImpl x₁ ⟩
useMonadImpl p₁ = p₁
useMonadImpl p₂ = p₂
useMonadImpl (cur x) = cur (useMonadImpl x)
useMonadImpl app = app
useMonadImpl [ x , x₁ ] = [_,_] (useMonadImpl x) (useMonadImpl x₁)
useMonadImpl i1 = i1
useMonadImpl i2 = i2
useMonadImpl nil = nil
useMonadImpl cons = cons
useMonadImpl (it x x₁) = it (useMonadImpl x) (useMonadImpl x₁)
useMonadImpl (ret {m = m}) = getReturnImpl m
useMonadImpl (bind {s = s}) = getBindImpl s
code : ∀ {A B} → CatComb A B → List Inst
code ! = [ UNIT ]
code (nat n) = [ NAT n ]
code id = [ SKIP ]
code (g ∘ f) = code f ++ code g
code ⟨ f , g ⟩ = PUSH ∷ code f ++ [ SWAP ] ++ code g ++ [ PAIR ]
code p₁ = [ FST ]
code p₂ = [ SND ]
code (cur f) = [ CUR (code f) ]
code app = [ APP ]
code [ f , g ] = [ CASE (code f) (code g) ]
code i1 = [ INL ]
code i2 = [ INR ]
code nil = [ NIL ]
code cons = [ C ]
code (it x r) = [ IT (code x) (code r) ]
code (ret {m = m}) = getReturnInst m
code (bind {s = s}) = getBindInst s
compile : ∀ {Γ A} → Γ ⊢ A → List Inst
compile M = code (useMonadImpl ⟦ M ⟧)
catCombValueToMachineValue : ∀ {A} → CatCombValue A → MachineValue
catCombValueToMachineValue (`nat n) = `nat n
catCombValueToMachineValue ⟨⟩ = ⟨⟩
catCombValueToMachineValue (s₁ , s₂) = catCombValueToMachineValue s₁ , catCombValueToMachineValue s₂
catCombValueToMachineValue (cur f s) = cur (code f) (catCombValueToMachineValue s)
catCombValueToMachineValue (L x) = L catCombValueToMachineValue x
catCombValueToMachineValue (R x) = R catCombValueToMachineValue x
catCombValueToMachineValue [] = []
catCombValueToMachineValue (h ⦂ t) = catCombValueToMachineValue h ⦂ catCombValueToMachineValue t
ctxToMachineValue : ∀ {Γ} → ValueOfContext Γ → MachineValue
ctxToMachineValue empty = ⟨⟩
ctxToMachineValue (cons x x₁) with ctxToMachineValue x | catCombValueToMachineValue x₁
... | z | w = z , w