module Staged.Expression.Lambda where
open import Data.Sum
open import Data.Nat
open import Data.Empty
open import Data.Unit
open import Data.Bool
open import Data.Product
open import Container
open import Staged.Denote
open import Staged.Effects.Lambda
open import Staged.Value.Core
module _ where
LamExpr : Con
Con.S LamExpr = (Name ⊎ Name) ⊎ ⊤ ⊎ Name
Con.P LamExpr (inj₁ (inj₁ x )) = ⊥
Con.P LamExpr (inj₁ (inj₂ y )) = ⊤
Con.P LamExpr (inj₂ (inj₁ tt)) = Bool
Con.P LamExpr (inj₂ (inj₂ y )) = Bool
module _ {V : Set} where
⟦lambda⟧ : ⦃ LamSig V ⊏ ζ ⦄
→ ⦃ Closure V ⊂ V ⦄
→ LamExpr ⟨ ζ ⟩⇒ V
denote ⟦lambda⟧ (inj₁ (inj₁ x) , p) = fetch x
denote ⟦lambda⟧ (inj₁ (inj₂ y) , p) = abs y (p tt)
denote ⟦lambda⟧ (inj₂ (inj₁ tt) , p) = do
v₁ ← p false
v₂ ← p true
app v₁ v₂
denote ⟦lambda⟧ (inj₂ (inj₂ y) , p) = do
v ← p false
letbind y v (p true)
module _ where
var' : ⦃ LamExpr ≺ C ⦄ → Name → μ C
var' x = inject ((inj₁ (inj₁ x)) , λ())
abs' : ⦃ LamExpr ≺ C ⦄ → Name → μ C → μ C
abs' x e = inject ((inj₁ (inj₂ x)) , λ _ → e)
app' : ⦃ LamExpr ≺ C ⦄ → μ C → μ C → μ C
app' e₁ e₂ = inject ((inj₂ (inj₁ tt)) , λ { false → e₁ ; true → e₂ })
let' : ⦃ LamExpr ≺ C ⦄ → Name → μ C → μ C → μ C
let' x e₁ e₂ = inject ((inj₂ (inj₂ x)) , λ { false → e₁ ; true → e₂ })