{-# OPTIONS --overlapping-instances --instance-search-depth=10 #-}

module Example.Hefty.Output+Concur where

open import Level renaming (zero to ℓ0) using ()
open import Data.Unit
open import Data.Product
open import Data.Nat
open import Data.String
open import Data.Universe renaming (Universe to Univ)
private Universe = Univ ℓ0 ℓ0
open Univ  ...  renaming (U to Ty; El to ⟦_⟧)
open import Relation.Binary.PropositionalEquality

open import Free  hiding (_>>=_; _>>_)
open import Free.Output
open import Free.SubJump
open import Free.Nil

open import Hefty hiding (_>>=_; _>>_)
open import Hefty.Lift
open import Hefty.Concur
open import Hefty.Nil


{-
A simple universe of types
-}

data Type : Set where
  unit : Type
  num : Type

instance
  ConcurUniverse : Universe
  Ty  ConcurUniverse  = Type
  ⟦_⟧  ConcurUniverse  unit = 
  ⟦_⟧  ConcurUniverse  num = 


{-
Automatic elaboration
-}

concur-elab : Elab (Lift Output  Concur  Lift Nil)
                   (  CC  t   t   Free (Output  Nil) )
                    Output
                    Nil )
concur-elab = auto-elab


{-
Tests
-}

ex-01234 : Hefty (Lift Output  Concur  Lift Nil) 
ex-01234 = ‵spawn (do  out "0";  out "1";  out "2"; pure 0)
                  (do  out "3";  out "4"; pure 0)
           where open import Hefty using (_>>_)

test-ex-01234 :  un (  (  given hOut
                          handle (  (  given hCC
                                       handle (elab concur-elab ex-01234)
                                    ) tt ) ) tt )  (0 , "03142")
test-ex-01234 = refl


ex-01234567 : Hefty (Lift Output  Concur  Lift Nil) 
ex-01234567 = ‵spawn  ex-01234
                      (‵atomic (do  out "5";  out "6";  out "7"; pure 0))
              where open import Hefty using (_>>_)

test-ex-01234567 :  un (  (  given hOut
                             handle (  (  given hCC
                                          handle (elab concur-elab ex-01234567)
                                       ) tt ) ) tt )  (0 , "05673142")
test-ex-01234567 = refl


{-
Alternative ordering of effects
-}

concur-elab′ : Elab (Lift Output  Concur  Lift Nil)
                   (  Output
                    CC  t   t   Free Nil ( × String))
                    Nil )
concur-elab′ = auto-elab

test-ex′ : un (  (  given hCC
                    handle (  (  given hOut
                                 handle (elab concur-elab′ ex-01234) )
                              tt ) ) tt )  (0 , "03142")
test-ex′ = refl

ex-atomic-01234 : Hefty (Lift Output  Concur  Lift Nil) 
ex-atomic-01234 = ‵spawn (‵atomic (do  out "0";  out "1";  out "2"; pure 0)) (do  out "3";  out "4"; pure 0)
  where open import Hefty using (_>>_)

test-atomic-ex : un ((given hCC handle ((given hOut handle (elab concur-elab′ ex-atomic-01234)) tt)) tt)  (0 , "34")
test-atomic-ex = refl