module Scoped.LetBind where

open import Function
open import Level

open import Data.Nat
open import Data.Product
open import Data.List
open import Data.Unit
open import Data.Sum
open import Data.Maybe using (Maybe ; just ; nothing ; maybe)

open import Container
open import Scoped.Prog

module _ where

  open Con

  Name = 

  Env : Set  Set
  Env V = List (Name × V)

  data FetchOp (V : Set) : Set where
     `fetch : Name  FetchOp V

  FetchSig : Set  Con
  S (FetchSig V) = FetchOp V
  P (FetchSig V) (`fetch x) = V

  data LetScope (V : Set) : Set where
     `letbind : Name  V  LetScope V

  LetSig : Set  Con
  S (LetSig V) = LetScope V
  P (LetSig V) (`letbind n v) = 


module _ {V : Set} where 

  postulate
    lookupₐ :  {X : Set}  List (Name × X)  Name  Maybe X

  hLet :  Env V  Prog (FetchSig V  σ) (LetSig V  γ) A 
          Prog σ γ (Maybe A)
  hLet _ (var x) = var (just x)
  hLet E (op (inj₁ (`fetch x)) k) =
     maybe  (hLet E  k) (var nothing)
               (lookupₐ E x)
  hLet E (op (inj₂ c) k) = op c (hLet E  k) 
  hLet E (scope (inj₁ (`letbind n v)) sc k) =
     hLet ((n , v)  E) (sc tt) >>=
       maybe (hLet E  k) (var nothing)
  hLet E (scope (inj₂ g) sc k) =
     scope g  (hLet E  sc) (maybe (hLet E  k) (var nothing))