{-# options_haddock prune #-}

-- |Description: Process Interpreters, Internal
module Polysemy.Process.Interpreter.Process where

import Control.Concurrent.STM.TBMQueue (TBMQueue)
import Data.ByteString (hGetSome, hPut)
import Polysemy.Conc.Async (withAsync_)
import qualified Polysemy.Conc.Data.QueueResult as QueueResult
import qualified Polysemy.Conc.Effect.Queue as Queue
import Polysemy.Conc.Effect.Queue (Queue)
import Polysemy.Conc.Effect.Race (Race)
import qualified Polysemy.Conc.Effect.Sync as Sync
import Polysemy.Conc.Effect.Sync (Sync)
import Polysemy.Conc.Interpreter.Queue.TBM (interpretQueueTBMWith, withTBMQueue)
import Polysemy.Conc.Interpreter.Sync (interpretSync)
import qualified Polysemy.Conc.Race as Conc (timeout_)
import Polysemy.Input (Input (Input))
import Polysemy.Opaque (Opaque)
import Polysemy.Output (Output (Output))
import Polysemy.Resume (
  Stop,
  interpretResumable,
  interpretScopedResumableWith_,
  mapStop,
  restop,
  resumeHoist,
  resumeOr,
  resume_,
  stop,
  stopNote,
  type (!!),
  )
import Prelude hiding (fromException)
import System.IO (BufferMode (NoBuffering), Handle, hSetBuffering, stdin, stdout)

import qualified Polysemy.Process.Data.ProcessError as ProcessError
import Polysemy.Process.Data.ProcessError (ProcessError (Exit, Unknown))
import Polysemy.Process.Data.ProcessKill (ProcessKill (KillAfter, KillImmediately, KillNever))
import Polysemy.Process.Data.ProcessOptions (ProcessOptions (ProcessOptions))
import qualified Polysemy.Process.Data.SystemProcessError as SystemProcessError
import Polysemy.Process.Data.SystemProcessError (SystemProcessError, SystemProcessScopeError)
import qualified Polysemy.Process.Effect.Process as Process
import Polysemy.Process.Effect.Process (Process)
import qualified Polysemy.Process.Effect.ProcessInput as ProcessInput
import Polysemy.Process.Effect.ProcessInput (ProcessInput)
import qualified Polysemy.Process.Effect.ProcessOutput as ProcessOutput
import Polysemy.Process.Effect.ProcessOutput (OutputPipe (Stderr, Stdout), ProcessOutput)
import qualified Polysemy.Process.Effect.SystemProcess as SystemProcess
import Polysemy.Process.Effect.SystemProcess (SystemProcess, withSystemProcess, withSystemProcess_)
import Polysemy.Process.Interpreter.ProcessIO (ProcessIO)
import Polysemy.Process.Interpreter.SystemProcess (
  SysProcConf,
  interpretSystemProcessNative,
  interpretSystemProcessNative_,
  )

newtype In a =
  In { forall a. In a -> a
unIn :: a }
  deriving stock (In a -> In a -> Bool
(In a -> In a -> Bool) -> (In a -> In a -> Bool) -> Eq (In a)
forall a. Eq a => In a -> In a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => In a -> In a -> Bool
== :: In a -> In a -> Bool
$c/= :: forall a. Eq a => In a -> In a -> Bool
/= :: In a -> In a -> Bool
Eq, Int -> In a -> ShowS
[In a] -> ShowS
In a -> String
(Int -> In a -> ShowS)
-> (In a -> String) -> ([In a] -> ShowS) -> Show (In a)
forall a. Show a => Int -> In a -> ShowS
forall a. Show a => [In a] -> ShowS
forall a. Show a => In a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> In a -> ShowS
showsPrec :: Int -> In a -> ShowS
$cshow :: forall a. Show a => In a -> String
show :: In a -> String
$cshowList :: forall a. Show a => [In a] -> ShowS
showList :: [In a] -> ShowS
Show)

newtype Out a =
  Out { forall a. Out a -> a
unOut :: a }
  deriving stock (Out a -> Out a -> Bool
(Out a -> Out a -> Bool) -> (Out a -> Out a -> Bool) -> Eq (Out a)
forall a. Eq a => Out a -> Out a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Out a -> Out a -> Bool
== :: Out a -> Out a -> Bool
$c/= :: forall a. Eq a => Out a -> Out a -> Bool
/= :: Out a -> Out a -> Bool
Eq, Int -> Out a -> ShowS
[Out a] -> ShowS
Out a -> String
(Int -> Out a -> ShowS)
-> (Out a -> String) -> ([Out a] -> ShowS) -> Show (Out a)
forall a. Show a => Int -> Out a -> ShowS
forall a. Show a => [Out a] -> ShowS
forall a. Show a => Out a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Out a -> ShowS
showsPrec :: Int -> Out a -> ShowS
$cshow :: forall a. Show a => Out a -> String
show :: Out a -> String
$cshowList :: forall a. Show a => [Out a] -> ShowS
showList :: [Out a] -> ShowS
Show)

newtype Err a =
  Err { forall a. Err a -> a
unErr :: a }
  deriving stock (Err a -> Err a -> Bool
(Err a -> Err a -> Bool) -> (Err a -> Err a -> Bool) -> Eq (Err a)
forall a. Eq a => Err a -> Err a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Err a -> Err a -> Bool
== :: Err a -> Err a -> Bool
$c/= :: forall a. Eq a => Err a -> Err a -> Bool
/= :: Err a -> Err a -> Bool
Eq, Int -> Err a -> ShowS
[Err a] -> ShowS
Err a -> String
(Int -> Err a -> ShowS)
-> (Err a -> String) -> ([Err a] -> ShowS) -> Show (Err a)
forall a. Show a => Int -> Err a -> ShowS
forall a. Show a => [Err a] -> ShowS
forall a. Show a => Err a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Err a -> ShowS
showsPrec :: Int -> Err a -> ShowS
$cshow :: forall a. Show a => Err a -> String
show :: Err a -> String
$cshowList :: forall a. Show a => [Err a] -> ShowS
showList :: [Err a] -> ShowS
Show)

data ProcessQueues i o =
  ProcessQueues {
    forall i o. ProcessQueues i o -> TBMQueue (In i)
pqIn :: TBMQueue (In i),
    forall i o. ProcessQueues i o -> TBMQueue (Out o)
pqOut :: TBMQueue (Out o)
  }

terminated ::
  Members [SystemProcess !! SystemProcessError, Stop ProcessError] r =>
  Text ->
  Sem r a
terminated :: forall (r :: EffectRow) a.
Members
  '[SystemProcess !! SystemProcessError, Stop ProcessError] r =>
Text -> Sem r a
terminated Text
site =
  ProcessError -> Sem r a
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop (ProcessError -> Sem r a)
-> (ExitCode -> ProcessError) -> ExitCode -> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExitCode -> ProcessError
Exit (ExitCode -> Sem r a) -> Sem r ExitCode -> Sem r a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall err (eff :: (* -> *) -> * -> *) err' (r :: EffectRow) a.
Members '[Resumable err eff, Stop err'] r =>
(err -> err') -> Sem (eff : r) a -> Sem r a
resumeHoist @_ @SystemProcess SystemProcessError -> ProcessError
fatal Sem (SystemProcess : r) ExitCode
forall (r :: EffectRow). Member SystemProcess r => Sem r ExitCode
SystemProcess.wait
  where
    fatal :: SystemProcessError -> ProcessError
fatal = \case
      SystemProcessError.Terminated Text
reason ->
        Text -> ProcessError
Unknown (Text
site Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": wait failed (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
reason Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
      SystemProcessError
SystemProcessError.NoPipes ->
        Text -> ProcessError
Unknown (Text
site Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": no pipes")

interpretQueues ::
  Members [Resource, Race, Embed IO] r =>
  ProcessQueues i o ->
  InterpretersFor [Queue (In i), Queue (Out o)] r
interpretQueues :: forall (r :: EffectRow) i o.
Members '[Resource, Race, Embed IO] r =>
ProcessQueues i o
-> InterpretersFor '[Queue (In i), Queue (Out o)] r
interpretQueues (ProcessQueues TBMQueue (In i)
inQ TBMQueue (Out o)
outQ) =
  TBMQueue (Out o) -> InterpreterFor (Queue (Out o)) r
forall d (r :: EffectRow).
Members '[Race, Embed IO] r =>
TBMQueue d -> InterpreterFor (Queue d) r
interpretQueueTBMWith TBMQueue (Out o)
outQ (Sem (Queue (Out o) : r) a -> Sem r a)
-> (Sem (Queue (In i) : Queue (Out o) : r) a
    -> Sem (Queue (Out o) : r) a)
-> Sem (Queue (In i) : Queue (Out o) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  TBMQueue (In i)
-> InterpreterFor (Queue (In i)) (Queue (Out o) : r)
forall d (r :: EffectRow).
Members '[Race, Embed IO] r =>
TBMQueue d -> InterpreterFor (Queue d) r
interpretQueueTBMWith TBMQueue (In i)
inQ

handleProcessWithQueues ::
   i o m r a .
  Members [Queue (In i), Queue (Out o), Stop ProcessError] r =>
  ( x . Text -> Sem r x) ->
  Process i o m a ->
  Sem r a
handleProcessWithQueues :: forall i o (m :: * -> *) (r :: EffectRow) a.
Members '[Queue (In i), Queue (Out o), Stop ProcessError] r =>
(forall x. Text -> Sem r x) -> Process i o m a -> Sem r a
handleProcessWithQueues forall x. Text -> Sem r x
onError = \case
  Process i o m a
Process.Recv ->
    Sem r (QueueResult (Out a))
forall d (r :: EffectRow).
Member (Queue d) r =>
Sem r (QueueResult d)
Queue.read Sem r (QueueResult (Out a))
-> (QueueResult (Out a) -> Sem r a) -> Sem r a
forall a b. Sem r a -> (a -> Sem r b) -> Sem r b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      QueueResult (Out a)
QueueResult.Closed ->
        Text -> Sem r a
forall x. Text -> Sem r x
onError Text
"recv: closed"
      QueueResult (Out a)
QueueResult.NotAvailable ->
        Text -> Sem r a
forall x. Text -> Sem r x
onError Text
"recv: impossible: empty"
      QueueResult.Success (Out a
msg) ->
        a -> Sem r a
forall a. a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
msg
  Process.Send i
msg -> do
    Sem r Bool -> Sem r () -> Sem r ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM (forall d (r :: EffectRow). Member (Queue d) r => Sem r Bool
Queue.closed @(In i)) (Text -> Sem r ()
forall x. Text -> Sem r x
onError Text
"send: closed")
    In i -> Sem r ()
forall d (r :: EffectRow). Member (Queue d) r => d -> Sem r ()
Queue.write (i -> In i
forall a. a -> In a
In i
msg)

withSTMResources ::
   i o r a .
  Members [Resource, Embed IO] r =>
  Int ->
  (ProcessQueues i o -> Sem r a) ->
  Sem r a
withSTMResources :: forall i o (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
Int -> (ProcessQueues i o -> Sem r a) -> Sem r a
withSTMResources Int
qSize ProcessQueues i o -> Sem r a
action = do
  Int -> (TBMQueue (In i) -> Sem r a) -> Sem r a
forall d (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
Int -> (TBMQueue d -> Sem r a) -> Sem r a
withTBMQueue Int
qSize \ TBMQueue (In i)
inQ ->
    Int -> (TBMQueue (Out o) -> Sem r a) -> Sem r a
forall d (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
Int -> (TBMQueue d -> Sem r a) -> Sem r a
withTBMQueue Int
qSize \ TBMQueue (Out o)
outQ ->
      ProcessQueues i o -> Sem r a
action (TBMQueue (In i) -> TBMQueue (Out o) -> ProcessQueues i o
forall i o.
TBMQueue (In i) -> TBMQueue (Out o) -> ProcessQueues i o
ProcessQueues TBMQueue (In i)
inQ TBMQueue (Out o)
outQ)

withQueues ::
   i o r .
  Members [Race, Resource, Embed IO] r =>
  Int ->
  InterpretersFor [Queue (In i), Queue (Out o)] r
withQueues :: forall i o (r :: EffectRow).
Members '[Race, Resource, Embed IO] r =>
Int -> InterpretersFor '[Queue (In i), Queue (Out o)] r
withQueues Int
qSize Sem (Append '[Queue (In i), Queue (Out o)] r) a
action =
  Int -> (ProcessQueues i o -> Sem r a) -> Sem r a
forall i o (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
Int -> (ProcessQueues i o -> Sem r a) -> Sem r a
withSTMResources Int
qSize \ ProcessQueues i o
qs -> ProcessQueues i o
-> InterpretersFor '[Queue (In i), Queue (Out o)] r
forall (r :: EffectRow) i o.
Members '[Resource, Race, Embed IO] r =>
ProcessQueues i o
-> InterpretersFor '[Queue (In i), Queue (Out o)] r
interpretQueues ProcessQueues i o
qs Sem (Append '[Queue (In i), Queue (Out o)] r) a
action

-- |Call a chunk reading action repeatedly, pass the bytes to 'ProcessOutput' and enqueue its results.
-- As soon as an empty chunk is encountered, the queue is closed if the gating action returns 'False'.
-- The conditional closing is for the purpose of keeping the queue alive until the last producer has written all
-- received chunks – this is important when both stdout and stderr are written to the same queue.
-- When a process writes to stdout and terminates, the stderr reader will immediately receive an empty chunk and close
-- the queue while the stdout reader calls 'ProcessOutput', after which 'Queue.write' will fail and the consumer won't
-- receive the output.
outputQueue ::
   p chunk err eff r .
  Members [eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO] r =>
  Bool ->
  Sem r Bool ->
  Sem (eff : r) ByteString ->
  Sem r ()
outputQueue :: forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: EffectRow).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem r Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue Bool
discardWhenFull Sem r Bool
dontClose Sem (eff : r) ByteString
readChunk = do
  ByteString -> Sem r ()
spin ByteString
""
  where
    spin :: ByteString -> Sem r ()
spin ByteString
buffer =
      forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a b.
Member (Resumable err eff) r =>
Sem (eff : r) a -> (a -> Sem r b) -> (err -> Sem r b) -> Sem r b
resumeOr @err Sem (eff : r) ByteString
readChunk (ByteString -> ByteString -> Sem r ()
write ByteString
buffer) (Sem r () -> err -> Sem r ()
forall a b. a -> b -> a
const Sem r ()
close)
    write :: ByteString -> ByteString -> Sem r ()
write ByteString
buffer ByteString
msg = do
      ([chunk]
chunks, ByteString
newBuffer) <- forall (p :: OutputPipe) a (r :: EffectRow).
Member (ProcessOutput p a) r =>
ByteString -> ByteString -> Sem r ([a], ByteString)
ProcessOutput.chunk @p @chunk ByteString
buffer ByteString
msg
      [chunk] -> (chunk -> Sem r ()) -> Sem r ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [chunk]
chunks \ (chunk -> Out chunk
forall a. a -> Out a
Out -> Out chunk
c) ->
        if Bool
discardWhenFull then Sem r (QueueResult ()) -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Out chunk -> Sem r (QueueResult ())
forall d (r :: EffectRow).
Member (Queue d) r =>
d -> Sem r (QueueResult ())
Queue.tryWrite Out chunk
c) else Out chunk -> Sem r ()
forall d (r :: EffectRow). Member (Queue d) r => d -> Sem r ()
Queue.write Out chunk
c
      ByteString -> Sem r ()
spin ByteString
newBuffer
    close :: Sem r ()
close =
      Sem r Bool -> Sem r () -> Sem r ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM Sem r Bool
dontClose (forall d (r :: EffectRow). Member (Queue d) r => Sem r ()
Queue.close @(Out chunk))

inputQueue ::
   i err eff r .
  Members [eff !! err, ProcessInput i, Queue (In i), Embed IO] r =>
  (ByteString -> Sem (eff : r) ()) ->
  Sem r ()
inputQueue :: forall i err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[eff !! err, ProcessInput i, Queue (In i), Embed IO] r =>
(ByteString -> Sem (eff : r) ()) -> Sem r ()
inputQueue ByteString -> Sem (eff : r) ()
writeChunk =
  Sem r ()
spin
  where
    spin :: Sem r ()
spin =
      forall d (r :: EffectRow).
Member (Queue d) r =>
Sem r (QueueResult d)
Queue.read @(In i) Sem r (QueueResult (In i))
-> (QueueResult (In i) -> Sem r ()) -> Sem r ()
forall a b. Sem r a -> (a -> Sem r b) -> Sem r b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        QueueResult.Success (In i
msg) -> do
          ByteString
bytes <- i -> Sem r ByteString
forall a (r :: EffectRow).
Member (ProcessInput a) r =>
a -> Sem r ByteString
ProcessInput.encode i
msg
          forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a b.
Member (Resumable err eff) r =>
Sem (eff : r) a -> (a -> Sem r b) -> (err -> Sem r b) -> Sem r b
resumeOr @err (ByteString -> Sem (eff : r) ()
writeChunk ByteString
bytes) (Sem r () -> () -> Sem r ()
forall a b. a -> b -> a
const Sem r ()
spin) (Sem r () -> err -> Sem r ()
forall a b. a -> b -> a
const (forall d (r :: EffectRow). Member (Queue d) r => Sem r ()
Queue.close @(In i)))
        QueueResult (In i)
_ ->
          Sem r ()
forall (f :: * -> *). Applicative f => f ()
unit

handleKill ::
  Members [SystemProcess, Race] r =>
  ProcessKill ->
  Sem r ()
handleKill :: forall (r :: EffectRow).
Members '[SystemProcess, Race] r =>
ProcessKill -> Sem r ()
handleKill = \case
  KillAfter NanoSeconds
interval ->
    Sem r () -> NanoSeconds -> Sem r () -> Sem r ()
forall u (r :: EffectRow) a.
(TimeUnit u, Member Race r) =>
Sem r a -> u -> Sem r a -> Sem r a
Conc.timeout_ Sem r ()
forall (r :: EffectRow). Member SystemProcess r => Sem r ()
SystemProcess.term NanoSeconds
interval (Sem r ExitCode -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Sem r ExitCode
forall (r :: EffectRow). Member SystemProcess r => Sem r ExitCode
SystemProcess.wait)
  ProcessKill
KillImmediately ->
    Sem r ()
forall (r :: EffectRow). Member SystemProcess r => Sem r ()
SystemProcess.term
  ProcessKill
KillNever ->
    Sem r ExitCode -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Sem r ExitCode
forall (r :: EffectRow). Member SystemProcess r => Sem r ExitCode
SystemProcess.wait

withKill ::
   err r a .
  Members [SystemProcess !! err, Resource, Race] r =>
  ProcessKill ->
  Sem r a ->
  Sem r a
withKill :: forall err (r :: EffectRow) a.
Members '[SystemProcess !! err, Resource, Race] r =>
ProcessKill -> Sem r a -> Sem r a
withKill ProcessKill
kill Sem r a
ma =
  Sem r a -> Sem r () -> Sem r a
forall (r :: EffectRow) a b.
Member Resource r =>
Sem r a -> Sem r b -> Sem r a
finally Sem r a
ma (Sem r () -> Sem r a) -> Sem r () -> Sem r a
forall a b. (a -> b) -> a -> b
$ forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Member (Resumable err eff) r =>
Sem (eff : r) () -> Sem r ()
resume_ @err @SystemProcess do
    Sem (SystemProcess : r) Pid -> Sem (SystemProcess : r) ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Sem (SystemProcess : r) Pid
forall (r :: EffectRow). Member SystemProcess r => Sem r Pid
SystemProcess.pid
    ProcessKill -> Sem (SystemProcess : r) ()
forall (r :: EffectRow).
Members '[SystemProcess, Race] r =>
ProcessKill -> Sem r ()
handleKill ProcessKill
kill

type ScopeEffects i o err =
  [Queue (In i), Queue (Out o), Sync (), SystemProcess !! err]

queues ::
   err i o r .
  Member (SystemProcess !! err) r =>
  Members [ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpretersFor [Queue (In i), Queue (Out o), Sync ()] r
queues :: forall err i o (r :: EffectRow).
(Member (SystemProcess !! err) r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions
-> InterpretersFor '[Queue (In i), Queue (Out o), Sync ()] r
queues (ProcessOptions Bool
discard Int
qSize ProcessKill
kill) =
  Sem (Sync () : r) a -> Sem r a
InterpreterFor (Sync ()) r
forall d (r :: EffectRow).
Members '[Race, Embed IO] r =>
InterpreterFor (Sync d) r
interpretSync (Sem (Sync () : r) a -> Sem r a)
-> (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
    -> Sem (Sync () : r) a)
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Int -> InterpretersFor '[Queue (In i), Queue (Out o)] (Sync () : r)
forall i o (r :: EffectRow).
Members '[Race, Resource, Embed IO] r =>
Int -> InterpretersFor '[Queue (In i), Queue (Out o)] r
withQueues Int
qSize (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
 -> Sem (Sync () : r) a)
-> (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
    -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a)
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem (Sync () : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : Sync () : r) ()
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
forall (r :: EffectRow) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: EffectRow).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem r Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue @'Stderr @o @err @SystemProcess Bool
discard (() -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) Bool
forall d (r :: EffectRow). Member (Sync d) r => d -> Sem r Bool
Sync.putTry ()) Sem
  (SystemProcess : Queue (In i) : Queue (Out o) : Sync () : r)
  ByteString
forall (r :: EffectRow). Member SystemProcess r => Sem r ByteString
SystemProcess.readStderr) (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
 -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a)
-> (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
    -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a)
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : Sync () : r) ()
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
forall (r :: EffectRow) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: EffectRow).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem r Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue @'Stdout @o @err @SystemProcess Bool
discard (() -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) Bool
forall d (r :: EffectRow). Member (Sync d) r => d -> Sem r Bool
Sync.putTry ()) Sem
  (SystemProcess : Queue (In i) : Queue (Out o) : Sync () : r)
  ByteString
forall (r :: EffectRow). Member SystemProcess r => Sem r ByteString
SystemProcess.readStdout) (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
 -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a)
-> (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
    -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a)
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : Sync () : r) ()
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
forall (r :: EffectRow) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall i err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[eff !! err, ProcessInput i, Queue (In i), Embed IO] r =>
(ByteString -> Sem (eff : r) ()) -> Sem r ()
inputQueue @i @err @SystemProcess ByteString
-> Sem
     (SystemProcess : Queue (In i) : Queue (Out o) : Sync () : r) ()
forall (r :: EffectRow).
Member SystemProcess r =>
ByteString -> Sem r ()
SystemProcess.writeStdin) (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
 -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a)
-> (Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
    -> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a)
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
-> Sem (Queue (In i) : Queue (Out o) : Sync () : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall err (r :: EffectRow) a.
Members '[SystemProcess !! err, Resource, Race] r =>
ProcessKill -> Sem r a -> Sem r a
withKill @err ProcessKill
kill

scope ::
   serr err i o r .
  Members [Scoped_ (SystemProcess !! err) !! serr, Stop serr] r =>
  Members [ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpretersFor (ScopeEffects i o err) r
scope :: forall serr err i o (r :: EffectRow).
(Members '[Scoped_ (SystemProcess !! err) !! serr, Stop serr] r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions -> InterpretersFor (ScopeEffects i o err) r
scope ProcessOptions
options =
  forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop @serr @(Scoped_ (SystemProcess !! err)) (Sem (Scoped_ (SystemProcess !! err) : r) a -> Sem r a)
-> (Sem
      (Queue (In i)
         : Queue (Out o) : Sync () : (SystemProcess !! err) : r)
      a
    -> Sem (Scoped_ (SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! err) : r)
     a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((SystemProcess !! err) : Scoped_ (SystemProcess !! err) : r) a
-> Sem (Scoped_ (SystemProcess !! err) : r) a
InterpreterFor
  (SystemProcess !! err) (Scoped_ (SystemProcess !! err) : r)
forall err (r :: EffectRow).
Member (Scoped_ (SystemProcess !! err)) r =>
InterpreterFor (SystemProcess !! err) r
withSystemProcess_ (Sem
   ((SystemProcess !! err) : Scoped_ (SystemProcess !! err) : r) a
 -> Sem (Scoped_ (SystemProcess !! err) : r) a)
-> (Sem
      (Queue (In i)
         : Queue (Out o) : Sync () : (SystemProcess !! err) : r)
      a
    -> Sem
         ((SystemProcess !! err) : Scoped_ (SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! err) : r)
     a
-> Sem (Scoped_ (SystemProcess !! err) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((SystemProcess !! err) : r) a
-> Sem
     ((SystemProcess !! err) : Scoped_ (SystemProcess !! err) : r) a
forall (e2 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder (Sem ((SystemProcess !! err) : r) a
 -> Sem
      ((SystemProcess !! err) : Scoped_ (SystemProcess !! err) : r) a)
-> (Sem
      (Queue (In i)
         : Queue (Out o) : Sync () : (SystemProcess !! err) : r)
      a
    -> Sem ((SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! err) : r)
     a
-> Sem
     ((SystemProcess !! err) : Scoped_ (SystemProcess !! err) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall err i o (r :: EffectRow).
(Member (SystemProcess !! err) r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions
-> InterpretersFor '[Queue (In i), Queue (Out o), Sync ()] r
queues @err ProcessOptions
options

pscope ::
   serr i o param proc err r .
  Members [Scoped proc (SystemProcess !! err) !! serr, Stop serr] r =>
  Members [ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  (param -> Sem r proc) ->
  param ->
  InterpretersFor (ScopeEffects i o err) r
pscope :: forall serr i o param proc err (r :: EffectRow).
(Members
   '[Scoped proc (SystemProcess !! err) !! serr, Stop serr] r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions
-> (param -> Sem r proc)
-> param
-> InterpretersFor (ScopeEffects i o err) r
pscope ProcessOptions
options param -> Sem r proc
consResource param
param Sem (Append (ScopeEffects i o err) r) a
sem =
  param -> Sem r proc
consResource param
param Sem r proc -> (proc -> Sem r a) -> Sem r a
forall a b. Sem r a -> (a -> Sem r b) -> Sem r b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ proc
proc ->
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop @serr @(Scoped proc (SystemProcess !! err)) (Sem (Scoped proc (SystemProcess !! err) : r) a -> Sem r a)
-> Sem (Scoped proc (SystemProcess !! err) : r) a -> Sem r a
forall a b. (a -> b) -> a -> b
$
    forall param err (r :: EffectRow).
Member (Scoped param (SystemProcess !! err)) r =>
param -> InterpreterFor (SystemProcess !! err) r
withSystemProcess @proc proc
proc (Sem
   ((SystemProcess !! err) : Scoped proc (SystemProcess !! err) : r) a
 -> Sem (Scoped proc (SystemProcess !! err) : r) a)
-> Sem
     ((SystemProcess !! err) : Scoped proc (SystemProcess !! err) : r) a
-> Sem (Scoped proc (SystemProcess !! err) : r) a
forall a b. (a -> b) -> a -> b
$
    Sem ((SystemProcess !! err) : r) a
-> Sem
     ((SystemProcess !! err) : Scoped proc (SystemProcess !! err) : r) a
forall (e2 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder (Sem ((SystemProcess !! err) : r) a
 -> Sem
      ((SystemProcess !! err) : Scoped proc (SystemProcess !! err) : r)
      a)
-> Sem ((SystemProcess !! err) : r) a
-> Sem
     ((SystemProcess !! err) : Scoped proc (SystemProcess !! err) : r) a
forall a b. (a -> b) -> a -> b
$
    forall err i o (r :: EffectRow).
(Member (SystemProcess !! err) r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions
-> InterpretersFor '[Queue (In i), Queue (Out o), Sync ()] r
queues @err ProcessOptions
options Sem (Append (ScopeEffects i o err) r) a
Sem
  (Append
     '[Queue (In i), Queue (Out o), Sync ()]
     ((SystemProcess !! err) : r))
  a
sem

-- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,
-- deferring decoding of stdout and stderr to the interpreters of two 'ProcessOutput' effects.
-- This variant:
-- - Models a daemon process that is not expected to terminate, causing 'Stop' to be sent to the scope callsite instead
--   of individual 'Process' actions.
-- - Is for parameterized scopes, meaning that a value of arbitrary type may be passed to
--   'Polysemy.Process.withProcessOneshotParam' which is then passed to the supplied function to produce a 'SysProcConf'
--   for the native process.
interpretProcess ::
   param proc i o r .
  Members (ProcessIO i o) r =>
  Member (Scoped proc (SystemProcess !! SystemProcessError) !! SystemProcessScopeError) r =>
  Members [Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  (param -> Sem (Stop ProcessError : r) proc) ->
  InterpreterFor (Scoped param (Process i o) !! ProcessError) r
interpretProcess :: forall param proc i o (r :: EffectRow).
(Members (ProcessIO i o) r,
 Member
   (Scoped proc (SystemProcess !! SystemProcessError)
    !! SystemProcessScopeError)
   r,
 Members '[Resource, Race, Async, Embed IO] r) =>
ProcessOptions
-> (param -> Sem (Stop ProcessError : r) proc)
-> InterpreterFor (Scoped param (Process i o) !! ProcessError) r
interpretProcess ProcessOptions
options param -> Sem (Stop ProcessError : r) proc
proc =
  forall (extra :: EffectRow) param (effect :: (* -> *) -> * -> *)
       err (r :: EffectRow).
KnownList extra =>
(forall (q :: (* -> *) -> * -> *) x.
 param
 -> Sem (extra ++ (Stop err : Opaque q : r)) x
 -> Sem (Stop err : Opaque q : r) x)
-> (forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
    effect (Sem r0) x -> Sem (extra ++ (Stop err : Opaque q : r)) x)
-> InterpreterFor (Scoped param effect !! err) r
interpretScopedResumableWith_ @(ScopeEffects i o SystemProcessError) param
-> Sem
     (ScopeEffects i o SystemProcessError
      ++ (Stop ProcessError : Opaque q : r))
     x
-> Sem (Stop ProcessError : Opaque q : r) x
forall (q :: (* -> *) -> * -> *) x.
param
-> Sem
     (ScopeEffects i o SystemProcessError
      ++ (Stop ProcessError : Opaque q : r))
     x
-> Sem (Stop ProcessError : Opaque q : r) x
acq ((forall x.
 Text
 -> Sem
      (Queue (In i)
         : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
         : Stop ProcessError : Opaque q : r)
      x)
-> Process i o (Sem r0) x
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
        : Stop ProcessError : Opaque q : r)
     x
forall i o (m :: * -> *) (r :: EffectRow) a.
Members '[Queue (In i), Queue (Out o), Stop ProcessError] r =>
(forall x. Text -> Sem r x) -> Process i o m a -> Sem r a
handleProcessWithQueues Text
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
        : Stop ProcessError : Opaque q : r)
     x
forall (r :: EffectRow) a.
Members
  '[SystemProcess !! SystemProcessError, Stop ProcessError] r =>
Text -> Sem r a
forall x.
Text
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
        : Stop ProcessError : Opaque q : r)
     x
terminated)
  where
    acq ::
       e a .
      param ->
      Sem (ScopeEffects i o SystemProcessError ++ Stop ProcessError : Opaque e : r) a ->
      Sem (Stop ProcessError : Opaque e : r) a
    acq :: forall (q :: (* -> *) -> * -> *) x.
param
-> Sem
     (ScopeEffects i o SystemProcessError
      ++ (Stop ProcessError : Opaque q : r))
     x
-> Sem (Stop ProcessError : Opaque q : r) x
acq param
p Sem
  (Append
     (ScopeEffects i o SystemProcessError)
     (Stop ProcessError : Opaque e : r))
  a
sem =
      (SystemProcessScopeError -> ProcessError)
-> Sem
     (Stop SystemProcessScopeError : Stop ProcessError : Opaque e : r) a
-> Sem (Stop ProcessError : Opaque e : r) a
forall err e' (r :: EffectRow) a.
Member (Stop e') r =>
(err -> e') -> Sem (Stop err : r) a -> Sem r a
mapStop SystemProcessScopeError -> ProcessError
ProcessError.StartFailed do
        forall serr i o param proc err (r :: EffectRow).
(Members
   '[Scoped proc (SystemProcess !! err) !! serr, Stop serr] r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions
-> (param -> Sem r proc)
-> param
-> InterpretersFor (ScopeEffects i o err) r
pscope @SystemProcessScopeError ProcessOptions
options (Sem (Stop ProcessError : Opaque e : r) proc
-> Sem
     (Stop SystemProcessScopeError : Stop ProcessError : Opaque e : r)
     proc
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
Sem r a -> Sem (e : r) a
raise (Sem (Stop ProcessError : Opaque e : r) proc
 -> Sem
      (Stop SystemProcessScopeError : Stop ProcessError : Opaque e : r)
      proc)
-> (param -> Sem (Stop ProcessError : Opaque e : r) proc)
-> param
-> Sem
     (Stop SystemProcessScopeError : Stop ProcessError : Opaque e : r)
     proc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem (Stop ProcessError : r) proc
-> Sem (Stop ProcessError : Opaque e : r) proc
forall (e2 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder (Sem (Stop ProcessError : r) proc
 -> Sem (Stop ProcessError : Opaque e : r) proc)
-> (param -> Sem (Stop ProcessError : r) proc)
-> param
-> Sem (Stop ProcessError : Opaque e : r) proc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. param -> Sem (Stop ProcessError : r) proc
proc) param
p (forall (index :: Nat) (inserted :: EffectRow) (head :: EffectRow)
       (oldTail :: EffectRow) (tail :: EffectRow) (old :: EffectRow)
       (full :: EffectRow) a.
(ListOfLength index head, WhenStuck index InsertAtUnprovidedIndex,
 old ~ Append head oldTail, tail ~ Append inserted oldTail,
 full ~ Append head tail,
 InsertAtIndex index head tail oldTail full inserted) =>
Sem old a -> Sem full a
insertAt @4 Sem
  (Append
     (ScopeEffects i o SystemProcessError)
     (Stop ProcessError : Opaque e : r))
  a
sem)

-- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,
-- deferring decoding of stdout and stderr to the interpreters of two 'ProcessOutput' effects.
-- This variant:
-- - Models a daemon process that is not expected to terminate, causing 'Stop' to be sent to the scope callsite instead
--   of individual 'Process' actions.
-- - Defers process config to 'SystemProcess'.
interpretProcess_ ::
   i o r .
  Member (Scoped_ (SystemProcess !! SystemProcessError) !! SystemProcessScopeError) r =>
  Members [ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, ProcessInput i, Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpreterFor (Scoped_ (Process i o) !! ProcessError) r
interpretProcess_ :: forall i o (r :: EffectRow).
(Member
   (Scoped_ (SystemProcess !! SystemProcessError)
    !! SystemProcessScopeError)
   r,
 Members
   '[ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, ProcessInput i,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions
-> InterpreterFor (Scoped_ (Process i o) !! ProcessError) r
interpretProcess_ ProcessOptions
options =
  forall (extra :: EffectRow) param (effect :: (* -> *) -> * -> *)
       err (r :: EffectRow).
KnownList extra =>
(forall (q :: (* -> *) -> * -> *) x.
 param
 -> Sem (extra ++ (Stop err : Opaque q : r)) x
 -> Sem (Stop err : Opaque q : r) x)
-> (forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
    effect (Sem r0) x -> Sem (extra ++ (Stop err : Opaque q : r)) x)
-> InterpreterFor (Scoped param effect !! err) r
interpretScopedResumableWith_ @(ScopeEffects i o SystemProcessError) ()
-> Sem
     (ScopeEffects i o SystemProcessError
      ++ (Stop ProcessError : Opaque q : r))
     x
-> Sem (Stop ProcessError : Opaque q : r) x
forall (q :: (* -> *) -> * -> *) x.
()
-> Sem
     (ScopeEffects i o SystemProcessError
      ++ (Stop ProcessError : Opaque q : r))
     x
-> Sem (Stop ProcessError : Opaque q : r) x
acq ((forall x.
 Text
 -> Sem
      (Queue (In i)
         : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
         : Stop ProcessError : Opaque q : r)
      x)
-> Process i o (Sem r0) x
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
        : Stop ProcessError : Opaque q : r)
     x
forall i o (m :: * -> *) (r :: EffectRow) a.
Members '[Queue (In i), Queue (Out o), Stop ProcessError] r =>
(forall x. Text -> Sem r x) -> Process i o m a -> Sem r a
handleProcessWithQueues Text
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
        : Stop ProcessError : Opaque q : r)
     x
forall (r :: EffectRow) a.
Members
  '[SystemProcess !! SystemProcessError, Stop ProcessError] r =>
Text -> Sem r a
forall x.
Text
-> Sem
     (Queue (In i)
        : Queue (Out o) : Sync () : (SystemProcess !! SystemProcessError)
        : Stop ProcessError : Opaque q : r)
     x
terminated)
  where
    acq ::
      () ->
      Sem (ScopeEffects i o SystemProcessError ++ Stop ProcessError : Opaque e : r) a ->
      Sem (Stop ProcessError : Opaque e : r) a
    acq :: forall (q :: (* -> *) -> * -> *) x.
()
-> Sem
     (ScopeEffects i o SystemProcessError
      ++ (Stop ProcessError : Opaque q : r))
     x
-> Sem (Stop ProcessError : Opaque q : r) x
acq () Sem
  (Append
     (ScopeEffects i o SystemProcessError)
     (Stop ProcessError : Opaque e : r))
  a
sem =
      (SystemProcessScopeError -> ProcessError)
-> Sem
     (Stop SystemProcessScopeError : Stop ProcessError : Opaque e : r) a
-> Sem (Stop ProcessError : Opaque e : r) a
forall err e' (r :: EffectRow) a.
Member (Stop e') r =>
(err -> e') -> Sem (Stop err : r) a -> Sem r a
mapStop SystemProcessScopeError -> ProcessError
ProcessError.StartFailed do
        forall serr err i o (r :: EffectRow).
(Members '[Scoped_ (SystemProcess !! err) !! serr, Stop serr] r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions -> InterpretersFor (ScopeEffects i o err) r
scope @SystemProcessScopeError ProcessOptions
options (forall (index :: Nat) (inserted :: EffectRow) (head :: EffectRow)
       (oldTail :: EffectRow) (tail :: EffectRow) (old :: EffectRow)
       (full :: EffectRow) a.
(ListOfLength index head, WhenStuck index InsertAtUnprovidedIndex,
 old ~ Append head oldTail, tail ~ Append inserted oldTail,
 full ~ Append head tail,
 InsertAtIndex index head tail oldTail full inserted) =>
Sem old a -> Sem full a
insertAt @4 Sem
  (Append
     (ScopeEffects i o SystemProcessError)
     (Stop ProcessError : Opaque e : r))
  a
sem)

-- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess'.
-- This variant:
-- - Models a daemon process that is not expected to terminate, causing 'Stop' to be sent to the scope callsite instead
--   of individual 'Process' actions.
-- - Is for parameterized scopes, meaning that a value of arbitrary type may be passed to
--   'Polysemy.Process.withProcessOneshotParam' which is then passed to the supplied function to produce a 'SysProcConf'
--   for the native process.
interpretProcessNative ::
   param i o r .
  Members (ProcessIO i o) r =>
  Members [Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  (param -> Sem r (Either Text SysProcConf)) ->
  InterpreterFor (Scoped param (Process i o) !! ProcessError) r
interpretProcessNative :: forall param i o (r :: EffectRow).
(Members (ProcessIO i o) r,
 Members '[Resource, Race, Async, Embed IO] r) =>
ProcessOptions
-> (param -> Sem r (Either Text SysProcConf))
-> InterpreterFor (Scoped param (Process i o) !! ProcessError) r
interpretProcessNative ProcessOptions
options param -> Sem r (Either Text SysProcConf)
proc =
  (Either Text SysProcConf -> Sem r (Either Text SysProcConf))
-> InterpreterFor
     (Scoped
        (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
forall param (r :: EffectRow).
Members '[Resource, Embed IO] r =>
(param -> Sem r (Either Text SysProcConf))
-> InterpreterFor
     (Scoped param (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
interpretSystemProcessNative Either Text SysProcConf -> Sem r (Either Text SysProcConf)
forall a. a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Sem
   ((Scoped
       (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
     !! SystemProcessScopeError)
      : r)
   a
 -> Sem r a)
-> (Sem ((Scoped param (Process i o) !! ProcessError) : r) a
    -> Sem
         ((Scoped
             (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
           !! SystemProcessScopeError)
            : r)
         a)
-> Sem ((Scoped param (Process i o) !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  ProcessOptions
-> (param
    -> Sem
         (Stop ProcessError
            : (Scoped
                 (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
               !! SystemProcessScopeError)
            : r)
         (Either Text SysProcConf))
-> InterpreterFor
     (Scoped param (Process i o) !! ProcessError)
     ((Scoped
         (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
       !! SystemProcessScopeError)
        : r)
forall param proc i o (r :: EffectRow).
(Members (ProcessIO i o) r,
 Member
   (Scoped proc (SystemProcess !! SystemProcessError)
    !! SystemProcessScopeError)
   r,
 Members '[Resource, Race, Async, Embed IO] r) =>
ProcessOptions
-> (param -> Sem (Stop ProcessError : r) proc)
-> InterpreterFor (Scoped param (Process i o) !! ProcessError) r
interpretProcess ProcessOptions
options (forall (index :: Nat) (inserted :: EffectRow) (head :: EffectRow)
       (oldTail :: EffectRow) (tail :: EffectRow) (old :: EffectRow)
       (full :: EffectRow) a.
(ListOfLength index head, WhenStuck index InsertAtUnprovidedIndex,
 old ~ Append head oldTail, tail ~ Append inserted oldTail,
 full ~ Append head tail,
 InsertAtIndex index head tail oldTail full inserted) =>
Sem old a -> Sem full a
insertAt @0 (Sem r (Either Text SysProcConf)
 -> Sem
      (Stop ProcessError
         : (Scoped
              (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
            !! SystemProcessScopeError)
         : r)
      (Either Text SysProcConf))
-> (param -> Sem r (Either Text SysProcConf))
-> param
-> Sem
     (Stop ProcessError
        : (Scoped
             (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
           !! SystemProcessScopeError)
        : r)
     (Either Text SysProcConf)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. param -> Sem r (Either Text SysProcConf)
proc) (Sem
   ((Scoped param (Process i o) !! ProcessError)
      : (Scoped
           (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
         !! SystemProcessScopeError)
      : r)
   a
 -> Sem
      ((Scoped
          (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
        !! SystemProcessScopeError)
         : r)
      a)
-> (Sem ((Scoped param (Process i o) !! ProcessError) : r) a
    -> Sem
         ((Scoped param (Process i o) !! ProcessError)
            : (Scoped
                 (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
               !! SystemProcessScopeError)
            : r)
         a)
-> Sem ((Scoped param (Process i o) !! ProcessError) : r) a
-> Sem
     ((Scoped
         (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
       !! SystemProcessScopeError)
        : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((Scoped param (Process i o) !! ProcessError) : r) a
-> Sem
     ((Scoped param (Process i o) !! ProcessError)
        : (Scoped
             (Either Text SysProcConf) (SystemProcess !! SystemProcessError)
           !! SystemProcessScopeError)
        : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder

-- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess'.
-- This variant:
-- - Models a daemon process that is not expected to terminate, causing 'Stop' to be sent to the scope callsite instead
--   of individual 'Process' actions.
-- - Defers process config to 'SystemProcess'.
interpretProcessNative_ ::
   i o r .
  Members (ProcessIO i o) r =>
  Members [Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  SysProcConf ->
  InterpreterFor (Scoped_ (Process i o) !! ProcessError) r
interpretProcessNative_ :: forall i o (r :: EffectRow).
(Members (ProcessIO i o) r,
 Members '[Resource, Race, Async, Embed IO] r) =>
ProcessOptions
-> SysProcConf
-> InterpreterFor (Scoped_ (Process i o) !! ProcessError) r
interpretProcessNative_ ProcessOptions
options SysProcConf
conf =
  SysProcConf
-> InterpreterFor
     (Scoped_ (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
forall (r :: EffectRow).
Members '[Resource, Embed IO] r =>
SysProcConf
-> InterpreterFor
     (Scoped_ (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
interpretSystemProcessNative_ SysProcConf
conf (Sem
   ((Scoped_ (SystemProcess !! SystemProcessError)
     !! SystemProcessScopeError)
      : r)
   a
 -> Sem r a)
-> (Sem ((Scoped_ (Process i o) !! ProcessError) : r) a
    -> Sem
         ((Scoped_ (SystemProcess !! SystemProcessError)
           !! SystemProcessScopeError)
            : r)
         a)
-> Sem ((Scoped_ (Process i o) !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  ProcessOptions
-> InterpreterFor
     (Scoped_ (Process i o) !! ProcessError)
     ((Scoped_ (SystemProcess !! SystemProcessError)
       !! SystemProcessScopeError)
        : r)
forall i o (r :: EffectRow).
(Member
   (Scoped_ (SystemProcess !! SystemProcessError)
    !! SystemProcessScopeError)
   r,
 Members
   '[ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, ProcessInput i,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions
-> InterpreterFor (Scoped_ (Process i o) !! ProcessError) r
interpretProcess_ ProcessOptions
options (Sem
   ((Scoped_ (Process i o) !! ProcessError)
      : (Scoped_ (SystemProcess !! SystemProcessError)
         !! SystemProcessScopeError)
      : r)
   a
 -> Sem
      ((Scoped_ (SystemProcess !! SystemProcessError)
        !! SystemProcessScopeError)
         : r)
      a)
-> (Sem ((Scoped_ (Process i o) !! ProcessError) : r) a
    -> Sem
         ((Scoped_ (Process i o) !! ProcessError)
            : (Scoped_ (SystemProcess !! SystemProcessError)
               !! SystemProcessScopeError)
            : r)
         a)
-> Sem ((Scoped_ (Process i o) !! ProcessError) : r) a
-> Sem
     ((Scoped_ (SystemProcess !! SystemProcessError)
       !! SystemProcessScopeError)
        : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((Scoped_ (Process i o) !! ProcessError) : r) a
-> Sem
     ((Scoped_ (Process i o) !! ProcessError)
        : (Scoped_ (SystemProcess !! SystemProcessError)
           !! SystemProcessScopeError)
        : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder

-- |Reinterpret 'Input' and 'Output' as 'Process'.
interpretInputOutputProcess ::
   i o r .
  Member (Process i o) r =>
  InterpretersFor [Input o, Output i] r
interpretInputOutputProcess :: forall i o (r :: EffectRow).
Member (Process i o) r =>
InterpretersFor '[Input o, Output i] r
interpretInputOutputProcess =
  (i -> Sem r ()) -> Sem (Output i : r) a -> Sem r a
forall o (r :: EffectRow) a.
(o -> Sem r ()) -> Sem (Output o : r) a -> Sem r a
runOutputSem (forall i o (r :: EffectRow).
Member (Process i o) r =>
i -> Sem r ()
Process.send @i @o) (Sem (Output i : r) a -> Sem r a)
-> (Sem (Input o : Output i : r) a -> Sem (Output i : r) a)
-> Sem (Input o : Output i : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Output i : r) o
-> Sem (Input o : Output i : r) a -> Sem (Output i : r) a
forall i (r :: EffectRow) a.
Sem r i -> Sem (Input i : r) a -> Sem r a
runInputSem (forall i o (r :: EffectRow). Member (Process i o) r => Sem r o
Process.recv @i @o)

-- |Interpret 'Input ByteString' by polling a 'Handle' and stopping with 'ProcessError' when it fails.
interpretInputHandleBuffered ::
  Member (Embed IO) r =>
  Handle ->
  InterpreterFor (Input ByteString !! ProcessError) r
interpretInputHandleBuffered :: forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Input ByteString !! ProcessError) r
interpretInputHandleBuffered Handle
handle =
  (forall x (r0 :: EffectRow).
 Input ByteString (Sem r0) x -> Sem (Stop ProcessError : r) x)
-> InterpreterFor (Input ByteString !! ProcessError) r
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
FirstOrder eff "interpretResumable" =>
(forall x (r0 :: EffectRow).
 eff (Sem r0) x -> Sem (Stop err : r) x)
-> InterpreterFor (Resumable err eff) r
interpretResumable \case
    Input ByteString (Sem r0) x
Input ->
      ProcessError -> Maybe x -> Sem (Stop ProcessError : r) x
forall err (r :: EffectRow) a.
Member (Stop err) r =>
err -> Maybe a -> Sem r a
stopNote (Text -> ProcessError
Unknown Text
"handle closed") (Maybe x -> Sem (Stop ProcessError : r) x)
-> Sem (Stop ProcessError : r) (Maybe x)
-> Sem (Stop ProcessError : r) x
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO x -> Sem (Stop ProcessError : r) (Maybe x)
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Maybe a)
tryMaybe (Handle -> Int -> IO ByteString
hGetSome Handle
handle Int
4096)

-- |Interpret 'Input ByteString' by polling a 'Handle' and stopping with 'ProcessError' when it fails.
-- This variant deactivates buffering for the 'Handle'.
interpretInputHandle ::
  Member (Embed IO) r =>
  Handle ->
  InterpreterFor (Input ByteString !! ProcessError) r
interpretInputHandle :: forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Input ByteString !! ProcessError) r
interpretInputHandle Handle
handle Sem ((Input ByteString !! ProcessError) : r) a
sem = do
  IO () -> Sem r ()
forall (r :: EffectRow). Member (Embed IO) r => IO () -> Sem r ()
tryAny_ (Handle -> BufferMode -> IO ()
hSetBuffering Handle
handle BufferMode
NoBuffering)
  Handle -> InterpreterFor (Input ByteString !! ProcessError) r
forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Input ByteString !! ProcessError) r
interpretInputHandleBuffered Handle
handle Sem ((Input ByteString !! ProcessError) : r) a
sem

-- |Interpret 'Output ByteString' by writing to a 'Handle' and stopping with 'ProcessError' when it fails.
interpretOutputHandleBuffered ::
  Member (Embed IO) r =>
  Handle ->
  InterpreterFor (Output ByteString !! ProcessError) r
interpretOutputHandleBuffered :: forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Output ByteString !! ProcessError) r
interpretOutputHandleBuffered Handle
handle =
  (forall x (r0 :: EffectRow).
 Output ByteString (Sem r0) x -> Sem (Stop ProcessError : r) x)
-> InterpreterFor (Output ByteString !! ProcessError) r
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
FirstOrder eff "interpretResumable" =>
(forall x (r0 :: EffectRow).
 eff (Sem r0) x -> Sem (Stop err : r) x)
-> InterpreterFor (Resumable err eff) r
interpretResumable \case
    Output ByteString
o ->
      ProcessError -> Maybe x -> Sem (Stop ProcessError : r) x
forall err (r :: EffectRow) a.
Member (Stop err) r =>
err -> Maybe a -> Sem r a
stopNote (Text -> ProcessError
Unknown Text
"handle closed") (Maybe x -> Sem (Stop ProcessError : r) x)
-> Sem (Stop ProcessError : r) (Maybe x)
-> Sem (Stop ProcessError : r) x
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO x -> Sem (Stop ProcessError : r) (Maybe x)
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Maybe a)
tryMaybe (Handle -> ByteString -> IO ()
hPut Handle
handle ByteString
o)

-- |Interpret 'Output ByteString' by writing to a 'Handle' and stopping with 'ProcessError' when it fails.
-- This variant deactivates buffering for the 'Handle'.
interpretOutputHandle ::
  Member (Embed IO) r =>
  Handle ->
  InterpreterFor (Output ByteString !! ProcessError) r
interpretOutputHandle :: forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Output ByteString !! ProcessError) r
interpretOutputHandle Handle
handle Sem ((Output ByteString !! ProcessError) : r) a
sem = do
  IO () -> Sem r ()
forall (r :: EffectRow). Member (Embed IO) r => IO () -> Sem r ()
tryAny_ (Handle -> BufferMode -> IO ()
hSetBuffering Handle
handle BufferMode
NoBuffering)
  Handle -> InterpreterFor (Output ByteString !! ProcessError) r
forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Output ByteString !! ProcessError) r
interpretOutputHandleBuffered Handle
handle Sem ((Output ByteString !! ProcessError) : r) a
sem

-- |Interpret 'Process' in terms of 'Input' and 'Output'.
-- Since the @i@ and @o@ parameters correspond to the abstraction of stdio fds of an external system process, @i@ is
-- written by 'Output' and @o@ is read from 'Input'.
-- This is useful to abstract the current process's stdio as an external process, with input and output swapped.
interpretProcessIO ::
   i o ie oe r .
  Members [Input ByteString !! ie, Output ByteString !! oe] r =>
  Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpreterFor (Process i o !! ProcessError) r
interpretProcessIO :: forall i o ie oe (r :: EffectRow).
(Members '[Input ByteString !! ie, Output ByteString !! oe] r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async,
     Embed IO]
   r) =>
ProcessOptions -> InterpreterFor (Process i o !! ProcessError) r
interpretProcessIO (ProcessOptions Bool
discard Int
qSize ProcessKill
_) =
  forall i o (r :: EffectRow).
Members '[Race, Resource, Embed IO] r =>
Int -> InterpretersFor '[Queue (In i), Queue (Out o)] r
withQueues @i @o Int
qSize (Sem (Queue (In i) : Queue (Out o) : r) a -> Sem r a)
-> (Sem ((Process i o !! ProcessError) : r) a
    -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> Sem ((Process i o !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : r) ()
-> Sem (Queue (In i) : Queue (Out o) : r) a
-> Sem (Queue (In i) : Queue (Out o) : r) a
forall (r :: EffectRow) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: EffectRow).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem r Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue @'Stdout @o @ie @(Input ByteString) Bool
discard (Bool -> Sem (Queue (In i) : Queue (Out o) : r) Bool
forall a. a -> Sem (Queue (In i) : Queue (Out o) : r) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False) Sem
  (Input ByteString : Queue (In i) : Queue (Out o) : r) ByteString
forall i (r :: EffectRow). Member (Input i) r => Sem r i
input) (Sem (Queue (In i) : Queue (Out o) : r) a
 -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> (Sem ((Process i o !! ProcessError) : r) a
    -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> Sem ((Process i o !! ProcessError) : r) a
-> Sem (Queue (In i) : Queue (Out o) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : r) ()
-> Sem (Queue (In i) : Queue (Out o) : r) a
-> Sem (Queue (In i) : Queue (Out o) : r) a
forall (r :: EffectRow) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall i err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[eff !! err, ProcessInput i, Queue (In i), Embed IO] r =>
(ByteString -> Sem (eff : r) ()) -> Sem r ()
inputQueue @i @oe @(Output ByteString) ByteString
-> Sem (Output ByteString : Queue (In i) : Queue (Out o) : r) ()
forall o (r :: EffectRow). Member (Output o) r => o -> Sem r ()
output) (Sem (Queue (In i) : Queue (Out o) : r) a
 -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> (Sem ((Process i o !! ProcessError) : r) a
    -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> Sem ((Process i o !! ProcessError) : r) a
-> Sem (Queue (In i) : Queue (Out o) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  (forall x (r0 :: EffectRow).
 Process i o (Sem r0) x
 -> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x)
-> InterpreterFor
     (Process i o !! ProcessError) (Queue (In i) : Queue (Out o) : r)
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
FirstOrder eff "interpretResumable" =>
(forall x (r0 :: EffectRow).
 eff (Sem r0) x -> Sem (Stop err : r) x)
-> InterpreterFor (Resumable err eff) r
interpretResumable ((forall x.
 Text
 -> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x)
-> Process i o (Sem r0) x
-> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x
forall i o (m :: * -> *) (r :: EffectRow) a.
Members '[Queue (In i), Queue (Out o), Stop ProcessError] r =>
(forall x. Text -> Sem r x) -> Process i o m a -> Sem r a
handleProcessWithQueues (ProcessError
-> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop (ProcessError
 -> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x)
-> (Text -> ProcessError)
-> Text
-> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ProcessError
Unknown)) (Sem
   ((Process i o !! ProcessError) : Queue (In i) : Queue (Out o) : r)
   a
 -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> (Sem ((Process i o !! ProcessError) : r) a
    -> Sem
         ((Process i o !! ProcessError) : Queue (In i) : Queue (Out o) : r)
         a)
-> Sem ((Process i o !! ProcessError) : r) a
-> Sem (Queue (In i) : Queue (Out o) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((Process i o !! ProcessError) : r) a
-> Sem
     ((Process i o !! ProcessError) : Queue (In i) : Queue (Out o) : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e3 :: (* -> *) -> * -> *)
       (e1 :: (* -> *) -> * -> *) (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : e3 : r) a
raiseUnder2

-- |Interpret 'Process' in terms of two 'Handle's.
-- This is useful to abstract the current process's stdio as an external process, with input and output swapped.
-- The first 'Handle' argument corresponds to the @o@ parameter, the second one to @i@, despite the first one usually
-- being the current process's stdin.
-- This is due to 'Process' abstracting an external process to whose stdin would be /written/, while the current one's
-- is /read/.
interpretProcessHandles ::
   i o r .
  Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  Handle ->
  Handle ->
  InterpreterFor (Process i o !! ProcessError) r
interpretProcessHandles :: forall i o (r :: EffectRow).
Members
  '[ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async,
    Embed IO]
  r =>
ProcessOptions
-> Handle
-> Handle
-> InterpreterFor (Process i o !! ProcessError) r
interpretProcessHandles ProcessOptions
options Handle
hIn Handle
hOut =
  Handle -> InterpreterFor (Output ByteString !! ProcessError) r
forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Output ByteString !! ProcessError) r
interpretOutputHandle Handle
hOut (Sem ((Output ByteString !! ProcessError) : r) a -> Sem r a)
-> (Sem ((Process i o !! ProcessError) : r) a
    -> Sem ((Output ByteString !! ProcessError) : r) a)
-> Sem ((Process i o !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Handle
-> InterpreterFor
     (Input ByteString !! ProcessError)
     ((Output ByteString !! ProcessError) : r)
forall (r :: EffectRow).
Member (Embed IO) r =>
Handle -> InterpreterFor (Input ByteString !! ProcessError) r
interpretInputHandle Handle
hIn (Sem
   ((Input ByteString !! ProcessError)
      : (Output ByteString !! ProcessError) : r)
   a
 -> Sem ((Output ByteString !! ProcessError) : r) a)
-> (Sem ((Process i o !! ProcessError) : r) a
    -> Sem
         ((Input ByteString !! ProcessError)
            : (Output ByteString !! ProcessError) : r)
         a)
-> Sem ((Process i o !! ProcessError) : r) a
-> Sem ((Output ByteString !! ProcessError) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall i o ie oe (r :: EffectRow).
(Members '[Input ByteString !! ie, Output ByteString !! oe] r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async,
     Embed IO]
   r) =>
ProcessOptions -> InterpreterFor (Process i o !! ProcessError) r
interpretProcessIO @i @o @ProcessError @ProcessError ProcessOptions
options (Sem
   ((Process i o !! ProcessError)
      : (Input ByteString !! ProcessError)
      : (Output ByteString !! ProcessError) : r)
   a
 -> Sem
      ((Input ByteString !! ProcessError)
         : (Output ByteString !! ProcessError) : r)
      a)
-> (Sem ((Process i o !! ProcessError) : r) a
    -> Sem
         ((Process i o !! ProcessError)
            : (Input ByteString !! ProcessError)
            : (Output ByteString !! ProcessError) : r)
         a)
-> Sem ((Process i o !! ProcessError) : r) a
-> Sem
     ((Input ByteString !! ProcessError)
        : (Output ByteString !! ProcessError) : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((Process i o !! ProcessError) : r) a
-> Sem
     ((Process i o !! ProcessError)
        : (Input ByteString !! ProcessError)
        : (Output ByteString !! ProcessError) : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e3 :: (* -> *) -> * -> *)
       (e1 :: (* -> *) -> * -> *) (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : e3 : r) a
raiseUnder2

-- |Interpret 'Process' using the current process's stdin and stdout.
-- This mirrors the usual abstraction of an external process, to whose stdin would be /written/, while the current one's
-- is /read/.
interpretProcessCurrent ::
  Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpreterFor (Process i o !! ProcessError) r
interpretProcessCurrent :: forall i o (r :: EffectRow).
Members
  '[ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async,
    Embed IO]
  r =>
ProcessOptions -> InterpreterFor (Process i o !! ProcessError) r
interpretProcessCurrent ProcessOptions
options =
  ProcessOptions
-> Handle
-> Handle
-> InterpreterFor (Process i o !! ProcessError) r
forall i o (r :: EffectRow).
Members
  '[ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async,
    Embed IO]
  r =>
ProcessOptions
-> Handle
-> Handle
-> InterpreterFor (Process i o !! ProcessError) r
interpretProcessHandles ProcessOptions
options Handle
stdin Handle
stdout