module Effectful.Zoo.Console.Dynamic.Run
  ( Console (..),
    runConsole,
    runConsoleBrackedToConsole,
    runConsoleAtomic,
  ) where

import Effectful
import Effectful.Exception
import Effectful.Concurrent.QSem
import Effectful.Dispatch.Dynamic
import Effectful.Zoo.Console.Dynamic.Effect
import Effectful.Zoo.Core
import Effectful.Zoo.Console.Static qualified as S
import HaskellWorks.Prelude

runConsole :: ()
  => HasCallStack
  => r <: IOE
  => UnliftStrategy
  -> (HasCallStack => i -> Eff r ())
  -> Eff (Console i : r) a
  -> Eff r a
runConsole :: forall (r :: [Effect]) i a.
(HasCallStack, r <: IOE) =>
UnliftStrategy
-> (HasCallStack => i -> Eff r ())
-> Eff (Console i : r) a
-> Eff r a
runConsole UnliftStrategy
s HasCallStack => i -> Eff r ()
run =
  (Eff (Console i : r) a -> Eff r a)
-> (forall {a} {localEs :: [Effect]}.
    (HasCallStack, Console i :> localEs) =>
    LocalEnv localEs (Console i : r)
    -> Console i (Eff localEs) a -> Eff (Console i : r) a)
-> Eff (Console i : r) a
-> Eff r a
forall (e :: Effect) (handlerEs :: [Effect]) a (es :: [Effect]) b.
(HasCallStack, DispatchOf e ~ 'Dynamic) =>
(Eff handlerEs a -> Eff es b)
-> EffectHandler e handlerEs -> Eff (e : es) a -> Eff es b
reinterpret (UnliftStrategy
-> (HasCallStack => i -> Eff r ())
-> Eff (Console i : r) a
-> Eff r a
forall (r :: [Effect]) i a.
(r <: IOE, HasCallStack) =>
UnliftStrategy
-> (HasCallStack => i -> Eff r ())
-> Eff (Console i : r) a
-> Eff r a
S.runConsole UnliftStrategy
s i -> Eff r ()
HasCallStack => i -> Eff r ()
run) ((forall {a} {localEs :: [Effect]}.
  (HasCallStack, Console i :> localEs) =>
  LocalEnv localEs (Console i : r)
  -> Console i (Eff localEs) a -> Eff (Console i : r) a)
 -> Eff (Console i : r) a -> Eff r a)
-> (forall {a} {localEs :: [Effect]}.
    (HasCallStack, Console i :> localEs) =>
    LocalEnv localEs (Console i : r)
    -> Console i (Eff localEs) a -> Eff (Console i : r) a)
-> Eff (Console i : r) a
-> Eff r a
forall a b. (a -> b) -> a -> b
$ \LocalEnv localEs (Console i : r)
env -> \case
    Print i
i -> i -> Eff (Console i : r) ()
forall (r :: [Effect]) i.
(HasCallStack, r <: Console i, r <: IOE) =>
i -> Eff r ()
S.print i
i
    Local i -> i
f Eff localEs a
m -> LocalEnv localEs (Console i : r)
-> ((forall {r}. Eff localEs r -> Eff (Console i : r) r)
    -> Eff (Console i : r) a)
-> Eff (Console i : r) a
forall (es :: [Effect]) (handlerEs :: [Effect])
       (localEs :: [Effect]) a.
(HasCallStack, SharedSuffix es handlerEs) =>
LocalEnv localEs handlerEs
-> ((forall r. Eff localEs r -> Eff es r) -> Eff es a) -> Eff es a
localSeqUnlift LocalEnv localEs (Console i : r)
env (((forall {r}. Eff localEs r -> Eff (Console i : r) r)
  -> Eff (Console i : r) a)
 -> Eff (Console i : r) a)
-> ((forall {r}. Eff localEs r -> Eff (Console i : r) r)
    -> Eff (Console i : r) a)
-> Eff (Console i : r) a
forall a b. (a -> b) -> a -> b
$ \forall {r}. Eff localEs r -> Eff (Console i : r) r
unlift -> (i -> i) -> Eff (Console i : r) a -> Eff (Console i : r) a
forall (r :: [Effect]) i a.
(HasCallStack, r <: Console i) =>
(i -> i) -> Eff r a -> Eff r a
S.local i -> i
f (Eff localEs a -> Eff (Console i : r) a
forall {r}. Eff localEs r -> Eff (Console i : r) r
unlift Eff localEs a
m)

runConsoleBrackedToConsole :: ()
  => HasCallStack
  => r <: Console i
  => Eff r b
  -> Eff r c
  -> Eff (Console i : r) a
  -> Eff r a
runConsoleBrackedToConsole :: forall (r :: [Effect]) i b c a.
(HasCallStack, r <: Console i) =>
Eff r b -> Eff r c -> Eff (Console i : r) a -> Eff r a
runConsoleBrackedToConsole Eff r b
before Eff r c
after =
  EffectHandler (Console i) r -> Eff (Console i : r) a -> Eff r a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic) =>
EffectHandler e es -> Eff (e : es) a -> Eff es a
interpret (EffectHandler (Console i) r -> Eff (Console i : r) a -> Eff r a)
-> EffectHandler (Console i) r -> Eff (Console i : r) a -> Eff r a
forall a b. (a -> b) -> a -> b
$ \LocalEnv localEs r
env -> \case
    Print i
i ->
      Eff r b -> Eff r c -> Eff r a -> Eff r a
forall (es :: [Effect]) a b c.
Eff es a -> Eff es b -> Eff es c -> Eff es c
bracket_ Eff r b
before Eff r c
after (Eff r a -> Eff r a) -> Eff r a -> Eff r a
forall a b. (a -> b) -> a -> b
$
        Console i (Eff r) a -> Eff r a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Console i (Eff r) a -> Eff r a) -> Console i (Eff r) a -> Eff r a
forall a b. (a -> b) -> a -> b
$ i -> Console i (Eff r) ()
forall a (b :: * -> *). a -> Console a b ()
Print i
i
    Local i -> i
f Eff localEs a
m ->
      Eff r b -> Eff r c -> Eff r a -> Eff r a
forall (es :: [Effect]) a b c.
Eff es a -> Eff es b -> Eff es c -> Eff es c
bracket_ Eff r b
before Eff r c
after (Eff r a -> Eff r a) -> Eff r a -> Eff r a
forall a b. (a -> b) -> a -> b
$
        LocalEnv localEs r
-> ((forall {r}. Eff localEs r -> Eff r r) -> Eff r a) -> Eff r a
forall (es :: [Effect]) (handlerEs :: [Effect])
       (localEs :: [Effect]) a.
(HasCallStack, SharedSuffix es handlerEs) =>
LocalEnv localEs handlerEs
-> ((forall r. Eff localEs r -> Eff es r) -> Eff es a) -> Eff es a
localSeqUnlift LocalEnv localEs r
env (((forall {r}. Eff localEs r -> Eff r r) -> Eff r a) -> Eff r a)
-> ((forall {r}. Eff localEs r -> Eff r r) -> Eff r a) -> Eff r a
forall a b. (a -> b) -> a -> b
$ \forall {r}. Eff localEs r -> Eff r r
unlift -> Console i (Eff r) a -> Eff r a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Console i (Eff r) a -> Eff r a) -> Console i (Eff r) a -> Eff r a
forall a b. (a -> b) -> a -> b
$ (i -> i) -> Eff r a -> Console i (Eff r) a
forall a (b :: * -> *) c. (a -> a) -> b c -> Console a b c
Local i -> i
f (Eff localEs a -> Eff r a
forall {r}. Eff localEs r -> Eff r r
unlift Eff localEs a
m)

runConsoleAtomic :: ()
  => HasCallStack
  => r <: Concurrent
  => r <: Console i
  => Eff (Console i : r) a
  -> Eff r a
runConsoleAtomic :: forall (r :: [Effect]) i a.
(HasCallStack, r <: Concurrent, r <: Console i) =>
Eff (Console i : r) a -> Eff r a
runConsoleAtomic Eff (Console i : r) a
f = do
  QSem
qsem <- Int -> Eff r QSem
forall (es :: [Effect]). (Concurrent :> es) => Int -> Eff es QSem
newQSem Int
1
  Eff r () -> Eff r () -> Eff (Console i : r) a -> Eff r a
forall (r :: [Effect]) i b c a.
(HasCallStack, r <: Console i) =>
Eff r b -> Eff r c -> Eff (Console i : r) a -> Eff r a
runConsoleBrackedToConsole (QSem -> Eff r ()
forall (es :: [Effect]). (Concurrent :> es) => QSem -> Eff es ()
waitQSem QSem
qsem) (QSem -> Eff r ()
forall (es :: [Effect]). (Concurrent :> es) => QSem -> Eff es ()
signalQSem QSem
qsem) Eff (Console i : r) a
f