{-# 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 qualified Polysemy.Conc as Conc
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 Polysemy.Conc.Effect.Scoped (Scoped)
import Polysemy.Conc.Interpreter.Queue.TBM (interpretQueueTBMWith, withTBMQueue)
import Polysemy.Conc.Interpreter.Scoped (interpretScopedResumableWith_)
import Polysemy.Input (Input (Input))
import Polysemy.Output (Output (Output))
import Polysemy.Resume (Stop, interpretResumable, resumeOr, resume_, stop, stopNote, type (!!))
import Prelude hiding (fromException)
import System.IO (BufferMode (NoBuffering), Handle, hSetBuffering, stdin, stdout)

import Polysemy.Process.Data.ProcessError (ProcessError (Terminated))
import Polysemy.Process.Data.ProcessKill (ProcessKill (KillAfter, KillImmediately, KillNever))
import Polysemy.Process.Data.ProcessOptions (ProcessOptions (ProcessOptions))
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)
import Polysemy.Process.Interpreter.ProcessInput (interpretProcessInputId, interpretProcessInputText)
import Polysemy.Process.Interpreter.ProcessOutput (
  interpretProcessOutputId,
  interpretProcessOutputIgnore,
  interpretProcessOutputLines,
  interpretProcessOutputText,
  interpretProcessOutputTextLines,
  )

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
/= :: In a -> In a -> Bool
$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
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
showList :: [In a] -> ShowS
$cshowList :: forall a. Show a => [In a] -> ShowS
show :: In a -> String
$cshow :: forall a. Show a => In a -> String
showsPrec :: Int -> In a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> 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
/= :: Out a -> Out a -> Bool
$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
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
showList :: [Out a] -> ShowS
$cshowList :: forall a. Show a => [Out a] -> ShowS
show :: Out a -> String
$cshow :: forall a. Show a => Out a -> String
showsPrec :: Int -> Out a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> 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
/= :: Err a -> Err a -> Bool
$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
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
showList :: [Err a] -> ShowS
$cshowList :: forall a. Show a => [Err a] -> ShowS
show :: Err a -> String
$cshow :: forall a. Show a => Err a -> String
showsPrec :: Int -> Err a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> 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)
  }

interpretQueues ::
  Members [Resource, Race, Embed IO] r =>
  ProcessQueues i o ->
  InterpretersFor [Queue (In i), Queue (Out o)] r
interpretQueues :: forall (r :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
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 =>
  Process i o m a ->
  Sem r a
handleProcessWithQueues :: forall i o (m :: * -> *) (r :: [(* -> *) -> * -> *]) a.
Members '[Queue (In i), Queue (Out o), Stop ProcessError] r =>
Process i o m a -> Sem r a
handleProcessWithQueues = \case
  Process i o m a
Process.Recv ->
    Sem r (QueueResult (Out a))
forall d (r :: [(* -> *) -> * -> *]).
MemberWithError (Queue d) r =>
Sem r (QueueResult d)
Queue.read Sem r (QueueResult (Out a))
-> (QueueResult (Out a) -> Sem r a) -> Sem r a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      QueueResult (Out a)
QueueResult.Closed ->
        ProcessError -> Sem r a
forall e (r :: [(* -> *) -> * -> *]) a.
MemberWithError (Stop e) r =>
e -> Sem r a
stop (Text -> ProcessError
Terminated Text
"closed")
      QueueResult (Out a)
QueueResult.NotAvailable ->
        ProcessError -> Sem r a
forall e (r :: [(* -> *) -> * -> *]) a.
MemberWithError (Stop e) r =>
e -> Sem r a
stop (Text -> ProcessError
Terminated Text
"impossible: empty")
      QueueResult.Success (Out a
msg) ->
        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 :: [(* -> *) -> * -> *]).
MemberWithError (Queue d) r =>
Sem r Bool
Queue.closed @(In i)) (ProcessError -> Sem r ()
forall e (r :: [(* -> *) -> * -> *]) a.
MemberWithError (Stop e) r =>
e -> Sem r a
stop (Text -> ProcessError
Terminated Text
"closed"))
    In i -> Sem r ()
forall d (r :: [(* -> *) -> * -> *]).
MemberWithError (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 :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]) 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

outputQueue ::
   p chunk err eff r .
  Members [eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO] r =>
  Bool ->
  Sem (eff : r) ByteString ->
  Sem r ()
outputQueue :: forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue Bool
discardWhenFull Sem (eff : r) ByteString
readChunk = do
  ByteString -> Sem r ()
spin ByteString
""
  where
    spin :: ByteString -> Sem r ()
spin ByteString
buffer =
      forall err (eff :: (* -> *) -> * -> *) (r :: [(* -> *) -> * -> *])
       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 (forall d (r :: [(* -> *) -> * -> *]).
MemberWithError (Queue d) r =>
Sem r ()
Queue.close @(Out chunk)))
    write :: ByteString -> ByteString -> Sem r ()
write ByteString
buffer ByteString
msg = do
      ([chunk]
chunks, ByteString
newBuffer) <- forall (p :: OutputPipe) a (r :: [(* -> *) -> * -> *]).
MemberWithError (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 :: [(* -> *) -> * -> *]).
MemberWithError (Queue d) r =>
d -> Sem r (QueueResult ())
Queue.tryWrite Out chunk
c) else Out chunk -> Sem r ()
forall d (r :: [(* -> *) -> * -> *]).
MemberWithError (Queue d) r =>
d -> Sem r ()
Queue.write Out chunk
c
      ByteString -> Sem r ()
spin ByteString
newBuffer

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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
MemberWithError (Queue d) r =>
Sem r (QueueResult d)
Queue.read @(In i) Sem r (QueueResult (In i))
-> (QueueResult (In i) -> Sem r ()) -> Sem r ()
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 :: [(* -> *) -> * -> *]).
MemberWithError (ProcessInput a) r =>
a -> Sem r ByteString
ProcessInput.encode i
msg
          forall err (eff :: (* -> *) -> * -> *) (r :: [(* -> *) -> * -> *])
       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 :: [(* -> *) -> * -> *]).
MemberWithError (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 :: [(* -> *) -> * -> *]).
Members '[SystemProcess, Race] r =>
ProcessKill -> Sem r ()
handleKill = \case
  KillAfter NanoSeconds
interval ->
    Sem r () -> NanoSeconds -> Sem r () -> Sem r ()
forall u (r :: [(* -> *) -> * -> *]) a.
(TimeUnit u, Member Race r) =>
Sem r a -> u -> Sem r a -> Sem r a
Conc.timeout_ Sem r ()
forall (r :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
MemberWithError SystemProcess r =>
Sem r ExitCode
SystemProcess.wait)
  ProcessKill
KillImmediately ->
    Sem r ()
forall (r :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
MemberWithError 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 :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
MemberWithError SystemProcess r =>
Sem r Pid
SystemProcess.pid
    ProcessKill -> Sem (SystemProcess : r) ()
forall (r :: [(* -> *) -> * -> *]).
Members '[SystemProcess, Race] r =>
ProcessKill -> Sem r ()
handleKill ProcessKill
kill

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

scope ::
   i o resource err r .
  Member (Scoped resource (SystemProcess !! err)) 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 i o resource err (r :: [(* -> *) -> * -> *]).
(Member (Scoped resource (SystemProcess !! err)) 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 Bool
discard Int
qSize ProcessKill
kill) =
  forall resource err (r :: [(* -> *) -> * -> *]).
Member (Scoped resource (SystemProcess !! err)) r =>
InterpreterFor (SystemProcess !! err) r
withSystemProcess @resource (Sem ((SystemProcess !! err) : r) a -> Sem r a)
-> (Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
    -> Sem ((SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Int
-> InterpretersFor
     '[Queue (In i), Queue (Out o)] ((SystemProcess !! err) : r)
forall i o (r :: [(* -> *) -> * -> *]).
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) : (SystemProcess !! err) : r) a
 -> Sem ((SystemProcess !! err) : r) a)
-> (Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
    -> Sem
         (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem ((SystemProcess !! err) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) ()
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
forall (r :: [(* -> *) -> * -> *]) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue @'Stderr @o @err @SystemProcess Bool
discard Sem
  (SystemProcess
     : Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r)
  ByteString
forall (r :: [(* -> *) -> * -> *]).
MemberWithError SystemProcess r =>
Sem r ByteString
SystemProcess.readStderr) (Sem (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
 -> Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a)
-> (Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
    -> Sem
         (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) ()
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
forall (r :: [(* -> *) -> * -> *]) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue @'Stdout @o @err @SystemProcess Bool
discard Sem
  (SystemProcess
     : Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r)
  ByteString
forall (r :: [(* -> *) -> * -> *]).
MemberWithError SystemProcess r =>
Sem r ByteString
SystemProcess.readStdout) (Sem (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
 -> Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a)
-> (Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
    -> Sem
         (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) ()
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
forall (r :: [(* -> *) -> * -> *]) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall i err (eff :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]).
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) : (SystemProcess !! err) : r)
     ()
forall (r :: [(* -> *) -> * -> *]).
MemberWithError SystemProcess r =>
ByteString -> Sem r ()
SystemProcess.writeStdin) (Sem (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
 -> Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a)
-> (Sem
      (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
    -> Sem
         (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a)
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
-> Sem
     (Queue (In i) : Queue (Out o) : (SystemProcess !! err) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall err (r :: [(* -> *) -> * -> *]) a.
Members '[SystemProcess !! err, Resource, Race] r =>
ProcessKill -> Sem r a -> Sem r a
withKill @err ProcessKill
kill

-- |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.
interpretProcess ::
   resource err i o r .
  Member (Scoped resource (SystemProcess !! err)) 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 resource err i o (r :: [(* -> *) -> * -> *]).
(Member (Scoped resource (SystemProcess !! err)) 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 :: [(* -> *) -> * -> *])
       (effect :: (* -> *) -> * -> *) err (r :: [(* -> *) -> * -> *])
       (r1 :: [(* -> *) -> * -> *]).
(r1 ~ ((extra ++ '[Stop err]) ++ r),
 InsertAtIndex
   1
   '[Scoped () effect !! err]
   r1
   r
   ((Scoped () effect !! err) : r1)
   (extra ++ '[Stop err])) =>
(forall x. Sem r1 x -> Sem (Stop err : r) x)
-> (forall (r0 :: [(* -> *) -> * -> *]) x.
    effect (Sem r0) x -> Sem r1 x)
-> InterpreterFor (Scoped () effect !! err) r
interpretScopedResumableWith_ @(ScopeEffects i o err) (forall i o resource err (r :: [(* -> *) -> * -> *]).
(Member (Scoped resource (SystemProcess !! err)) r,
 Members
   '[ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o,
     Resource, Race, Async, Embed IO]
   r) =>
ProcessOptions -> InterpretersFor (ScopeEffects i o err) r
scope @i @o @resource ProcessOptions
options) forall (r0 :: [(* -> *) -> * -> *]) x.
Process i o (Sem r0) x
-> Sem
     (Queue (In i)
        : Queue (Out o) : (SystemProcess !! err) : Stop ProcessError : r)
     x
forall i o (m :: * -> *) (r :: [(* -> *) -> * -> *]) a.
Members '[Queue (In i), Queue (Out o), Stop ProcessError] r =>
Process i o m a -> Sem r a
handleProcessWithQueues

-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's,
-- producing 'ByteString's.
-- Silently discards stderr.
interpretProcessByteString ::
   resource err r .
  Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
interpretProcessByteString :: forall resource err (r :: [(* -> *) -> * -> *]).
Members
  '[Scoped resource (SystemProcess !! err), Resource, Race, Async,
    Embed IO]
  r =>
ProcessOptions
-> InterpreterFor
     (Scoped () (Process ByteString ByteString) !! ProcessError) r
interpretProcessByteString ProcessOptions
options =
  forall (p :: OutputPipe) a (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p a) r
interpretProcessOutputIgnore @'Stderr @ByteString (Sem (ProcessOutput 'Stderr ByteString : r) a -> Sem r a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem (ProcessOutput 'Stderr ByteString : r) a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall (p :: OutputPipe) (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p ByteString) r
interpretProcessOutputId @'Stdout (Sem
   (ProcessOutput 'Stdout ByteString
      : ProcessOutput 'Stderr ByteString : r)
   a
 -> Sem (ProcessOutput 'Stderr ByteString : r) a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem
         (ProcessOutput 'Stdout ByteString
            : ProcessOutput 'Stderr ByteString : r)
         a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem (ProcessOutput 'Stderr ByteString : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem
  (ProcessInput ByteString
     : ProcessOutput 'Stdout ByteString
     : ProcessOutput 'Stderr ByteString : r)
  a
-> Sem
     (ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessInput ByteString) r
interpretProcessInputId (Sem
   (ProcessInput ByteString
      : ProcessOutput 'Stdout ByteString
      : ProcessOutput 'Stderr ByteString : r)
   a
 -> Sem
      (ProcessOutput 'Stdout ByteString
         : ProcessOutput 'Stderr ByteString : r)
      a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem
         (ProcessInput ByteString
            : ProcessOutput 'Stdout ByteString
            : ProcessOutput 'Stderr ByteString : r)
         a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem
     (ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall resource err i o (r :: [(* -> *) -> * -> *]).
(Member (Scoped resource (SystemProcess !! err)) 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 @resource @err ProcessOptions
options (Sem
   ((Scoped () (Process ByteString ByteString) !! ProcessError)
      : ProcessInput ByteString : ProcessOutput 'Stdout ByteString
      : ProcessOutput 'Stderr ByteString : r)
   a
 -> Sem
      (ProcessInput ByteString
         : ProcessOutput 'Stdout ByteString
         : ProcessOutput 'Stderr ByteString : r)
      a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem
         ((Scoped () (Process ByteString ByteString) !! ProcessError)
            : ProcessInput ByteString : ProcessOutput 'Stdout ByteString
            : ProcessOutput 'Stderr ByteString : r)
         a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem
     (ProcessInput ByteString
        : ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem
  ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError)
        : ProcessInput ByteString : ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e3 :: (* -> *) -> * -> *)
       (e4 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]) a.
Sem (e1 : r) a -> Sem (e1 : e2 : e3 : e4 : r) a
raiseUnder3

-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's,
-- producing chunks of lines of 'ByteString's.
-- Silently discards stderr.
interpretProcessByteStringLines ::
   resource err r .
  Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
interpretProcessByteStringLines :: forall resource err (r :: [(* -> *) -> * -> *]).
Members
  '[Scoped resource (SystemProcess !! err), Resource, Race, Async,
    Embed IO]
  r =>
ProcessOptions
-> InterpreterFor
     (Scoped () (Process ByteString ByteString) !! ProcessError) r
interpretProcessByteStringLines ProcessOptions
options =
  forall (p :: OutputPipe) a (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p a) r
interpretProcessOutputIgnore @'Stderr @ByteString (Sem (ProcessOutput 'Stderr ByteString : r) a -> Sem r a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem (ProcessOutput 'Stderr ByteString : r) a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall (p :: OutputPipe) (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p ByteString) r
interpretProcessOutputLines @'Stdout (Sem
   (ProcessOutput 'Stdout ByteString
      : ProcessOutput 'Stderr ByteString : r)
   a
 -> Sem (ProcessOutput 'Stderr ByteString : r) a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem
         (ProcessOutput 'Stdout ByteString
            : ProcessOutput 'Stderr ByteString : r)
         a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem (ProcessOutput 'Stderr ByteString : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem
  (ProcessInput ByteString
     : ProcessOutput 'Stdout ByteString
     : ProcessOutput 'Stderr ByteString : r)
  a
-> Sem
     (ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessInput ByteString) r
interpretProcessInputId (Sem
   (ProcessInput ByteString
      : ProcessOutput 'Stdout ByteString
      : ProcessOutput 'Stderr ByteString : r)
   a
 -> Sem
      (ProcessOutput 'Stdout ByteString
         : ProcessOutput 'Stderr ByteString : r)
      a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem
         (ProcessInput ByteString
            : ProcessOutput 'Stdout ByteString
            : ProcessOutput 'Stderr ByteString : r)
         a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem
     (ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall resource err i o (r :: [(* -> *) -> * -> *]).
(Member (Scoped resource (SystemProcess !! err)) 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 @resource @err ProcessOptions
options (Sem
   ((Scoped () (Process ByteString ByteString) !! ProcessError)
      : ProcessInput ByteString : ProcessOutput 'Stdout ByteString
      : ProcessOutput 'Stderr ByteString : r)
   a
 -> Sem
      (ProcessInput ByteString
         : ProcessOutput 'Stdout ByteString
         : ProcessOutput 'Stderr ByteString : r)
      a)
-> (Sem
      ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
    -> Sem
         ((Scoped () (Process ByteString ByteString) !! ProcessError)
            : ProcessInput ByteString : ProcessOutput 'Stdout ByteString
            : ProcessOutput 'Stderr ByteString : r)
         a)
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem
     (ProcessInput ByteString
        : ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem
  ((Scoped () (Process ByteString ByteString) !! ProcessError) : r) a
-> Sem
     ((Scoped () (Process ByteString ByteString) !! ProcessError)
        : ProcessInput ByteString : ProcessOutput 'Stdout ByteString
        : ProcessOutput 'Stderr ByteString : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e3 :: (* -> *) -> * -> *)
       (e4 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]) a.
Sem (e1 : r) a -> Sem (e1 : e2 : e3 : e4 : r) a
raiseUnder3

-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's,
-- producing 'Text's.
-- Silently discards stderr.
interpretProcessText ::
   resource err r .
  Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
interpretProcessText :: forall resource err (r :: [(* -> *) -> * -> *]).
Members
  '[Scoped resource (SystemProcess !! err), Resource, Race, Async,
    Embed IO]
  r =>
ProcessOptions
-> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
interpretProcessText ProcessOptions
options =
  forall (p :: OutputPipe) a (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p a) r
interpretProcessOutputIgnore @'Stderr @Text (Sem (ProcessOutput 'Stderr Text : r) a -> Sem r a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem (ProcessOutput 'Stderr Text : r) a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall (p :: OutputPipe) (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p Text) r
interpretProcessOutputText @'Stdout (Sem
   (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a
 -> Sem (ProcessOutput 'Stderr Text : r) a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem
         (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem (ProcessOutput 'Stderr Text : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem
  (ProcessInput Text
     : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
  a
-> Sem
     (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a
forall (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessInput Text) r
interpretProcessInputText (Sem
   (ProcessInput Text
      : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
   a
 -> Sem
      (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem
         (ProcessInput Text
            : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
         a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem
     (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall resource err i o (r :: [(* -> *) -> * -> *]).
(Member (Scoped resource (SystemProcess !! err)) 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 @resource @err ProcessOptions
options (Sem
   ((Scoped () (Process Text Text) !! ProcessError)
      : ProcessInput Text : ProcessOutput 'Stdout Text
      : ProcessOutput 'Stderr Text : r)
   a
 -> Sem
      (ProcessInput Text
         : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
      a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem
         ((Scoped () (Process Text Text) !! ProcessError)
            : ProcessInput Text : ProcessOutput 'Stdout Text
            : ProcessOutput 'Stderr Text : r)
         a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem
     (ProcessInput Text
        : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem
     ((Scoped () (Process Text Text) !! ProcessError)
        : ProcessInput Text : ProcessOutput 'Stdout Text
        : ProcessOutput 'Stderr Text : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e3 :: (* -> *) -> * -> *)
       (e4 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]) a.
Sem (e1 : r) a -> Sem (e1 : e2 : e3 : e4 : r) a
raiseUnder3

-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's,
-- producing chunks of lines of 'Text's.
-- Silently discards stderr.
interpretProcessTextLines ::
   resource err r .
  Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>
  ProcessOptions ->
  InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
interpretProcessTextLines :: forall resource err (r :: [(* -> *) -> * -> *]).
Members
  '[Scoped resource (SystemProcess !! err), Resource, Race, Async,
    Embed IO]
  r =>
ProcessOptions
-> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
interpretProcessTextLines ProcessOptions
options =
  forall (p :: OutputPipe) a (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p a) r
interpretProcessOutputIgnore @'Stderr @Text (Sem (ProcessOutput 'Stderr Text : r) a -> Sem r a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem (ProcessOutput 'Stderr Text : r) a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall (p :: OutputPipe) (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessOutput p Text) r
interpretProcessOutputTextLines @'Stdout (Sem
   (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a
 -> Sem (ProcessOutput 'Stderr Text : r) a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem
         (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem (ProcessOutput 'Stderr Text : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem
  (ProcessInput Text
     : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
  a
-> Sem
     (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a
forall (r :: [(* -> *) -> * -> *]).
InterpreterFor (ProcessInput Text) r
interpretProcessInputText (Sem
   (ProcessInput Text
      : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
   a
 -> Sem
      (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem
         (ProcessInput Text
            : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
         a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem
     (ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall resource err i o (r :: [(* -> *) -> * -> *]).
(Member (Scoped resource (SystemProcess !! err)) 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 @resource @err ProcessOptions
options (Sem
   ((Scoped () (Process Text Text) !! ProcessError)
      : ProcessInput Text : ProcessOutput 'Stdout Text
      : ProcessOutput 'Stderr Text : r)
   a
 -> Sem
      (ProcessInput Text
         : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
      a)
-> (Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
    -> Sem
         ((Scoped () (Process Text Text) !! ProcessError)
            : ProcessInput Text : ProcessOutput 'Stdout Text
            : ProcessOutput 'Stderr Text : r)
         a)
-> Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem
     (ProcessInput Text
        : ProcessOutput 'Stdout Text : ProcessOutput 'Stderr Text : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem ((Scoped () (Process Text Text) !! ProcessError) : r) a
-> Sem
     ((Scoped () (Process Text Text) !! ProcessError)
        : ProcessInput Text : ProcessOutput 'Stdout Text
        : ProcessOutput 'Stderr Text : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e3 :: (* -> *) -> * -> *)
       (e4 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]) a.
Sem (e1 : r) a -> Sem (e1 : e2 : e3 : e4 : r) a
raiseUnder3

-- |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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]) a.
(o -> Sem r ()) -> Sem (Output o : r) a -> Sem r a
runOutputSem (forall i o (r :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]) a.
Sem r i -> Sem (Input i : r) a -> Sem r a
runInputSem (forall i o (r :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
Member (Embed IO) r =>
Handle -> InterpreterFor (Input ByteString !! ProcessError) r
interpretInputHandleBuffered Handle
handle =
  (forall x (r0 :: [(* -> *) -> * -> *]).
 Input ByteString (Sem r0) x -> Sem (Stop ProcessError : r) x)
-> InterpreterFor (Input ByteString !! ProcessError) r
forall err (eff :: (* -> *) -> * -> *) (r :: [(* -> *) -> * -> *]).
FirstOrder eff "interpretResumable" =>
(forall x (r0 :: [(* -> *) -> * -> *]).
 eff (Sem r0) x -> Sem (Stop err : r) x)
-> InterpreterFor (Resumable err eff) r
interpretResumable \case
    Input ByteString (Sem r0) x
Input ->
      ProcessError
-> Maybe ByteString -> Sem (Stop ProcessError : r) ByteString
forall err (r :: [(* -> *) -> * -> *]) a.
Member (Stop err) r =>
err -> Maybe a -> Sem r a
stopNote (Text -> ProcessError
Terminated Text
"handle closed") (Maybe ByteString -> Sem (Stop ProcessError : r) ByteString)
-> Sem (Stop ProcessError : r) (Maybe ByteString)
-> Sem (Stop ProcessError : r) ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO ByteString -> Sem (Stop ProcessError : r) (Maybe ByteString)
forall (r :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
Member (Embed IO) r =>
IO () -> Sem r ()
tryAny_ (Handle -> BufferMode -> IO ()
hSetBuffering Handle
handle BufferMode
NoBuffering)
  Handle -> InterpreterFor (Input ByteString !! ProcessError) r
forall (r :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
Member (Embed IO) r =>
Handle -> InterpreterFor (Output ByteString !! ProcessError) r
interpretOutputHandleBuffered Handle
handle =
  (forall x (r0 :: [(* -> *) -> * -> *]).
 Output ByteString (Sem r0) x -> Sem (Stop ProcessError : r) x)
-> InterpreterFor (Output ByteString !! ProcessError) r
forall err (eff :: (* -> *) -> * -> *) (r :: [(* -> *) -> * -> *]).
FirstOrder eff "interpretResumable" =>
(forall x (r0 :: [(* -> *) -> * -> *]).
 eff (Sem r0) x -> Sem (Stop err : r) x)
-> InterpreterFor (Resumable err eff) r
interpretResumable \case
    Output ByteString
o ->
      ProcessError -> Maybe () -> Sem (Stop ProcessError : r) ()
forall err (r :: [(* -> *) -> * -> *]) a.
Member (Stop err) r =>
err -> Maybe a -> Sem r a
stopNote (Text -> ProcessError
Terminated Text
"handle closed") (Maybe () -> Sem (Stop ProcessError : r) ())
-> Sem (Stop ProcessError : r) (Maybe ())
-> Sem (Stop ProcessError : r) ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO () -> Sem (Stop ProcessError : r) (Maybe ())
forall (r :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
Member (Embed IO) r =>
IO () -> Sem r ()
tryAny_ (Handle -> BufferMode -> IO ()
hSetBuffering Handle
handle BufferMode
NoBuffering)
  Handle -> InterpreterFor (Output ByteString !! ProcessError) r
forall (r :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
(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 :: [(* -> *) -> * -> *]).
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 (Resumable ProcessError (Process i o) : r) a
    -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> Sem (Resumable ProcessError (Process i o) : 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 :: [(* -> *) -> * -> *]) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall (p :: OutputPipe) chunk err (eff :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]).
Members
  '[eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO]
  r =>
Bool -> Sem (eff : r) ByteString -> Sem r ()
outputQueue @'Stdout @o @ie @(Input ByteString) Bool
discard Sem
  (Input ByteString : Queue (In i) : Queue (Out o) : r) ByteString
forall i (r :: [(* -> *) -> * -> *]).
MemberWithError (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 (Resumable ProcessError (Process i o) : r) a
    -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> Sem (Resumable ProcessError (Process i o) : 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 :: [(* -> *) -> * -> *]) b a.
Members '[Resource, Race, Async] r =>
Sem r b -> Sem r a -> Sem r a
withAsync_ (forall i err (eff :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
MemberWithError (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 (Resumable ProcessError (Process i o) : r) a
    -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> Sem (Resumable ProcessError (Process i o) : r) a
-> Sem (Queue (In i) : Queue (Out o) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  (forall x (r0 :: [(* -> *) -> * -> *]).
 Process i o (Sem r0) x
 -> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x)
-> InterpreterFor
     (Resumable ProcessError (Process i o))
     (Queue (In i) : Queue (Out o) : r)
forall err (eff :: (* -> *) -> * -> *) (r :: [(* -> *) -> * -> *]).
FirstOrder eff "interpretResumable" =>
(forall x (r0 :: [(* -> *) -> * -> *]).
 eff (Sem r0) x -> Sem (Stop err : r) x)
-> InterpreterFor (Resumable err eff) r
interpretResumable forall x (r0 :: [(* -> *) -> * -> *]).
Process i o (Sem r0) x
-> Sem (Stop ProcessError : Queue (In i) : Queue (Out o) : r) x
forall i o (m :: * -> *) (r :: [(* -> *) -> * -> *]) a.
Members '[Queue (In i), Queue (Out o), Stop ProcessError] r =>
Process i o m a -> Sem r a
handleProcessWithQueues (Sem
   (Resumable ProcessError (Process i o)
      : Queue (In i) : Queue (Out o) : r)
   a
 -> Sem (Queue (In i) : Queue (Out o) : r) a)
-> (Sem (Resumable ProcessError (Process i o) : r) a
    -> Sem
         (Resumable ProcessError (Process i o)
            : Queue (In i) : Queue (Out o) : r)
         a)
-> Sem (Resumable ProcessError (Process i o) : r) a
-> Sem (Queue (In i) : Queue (Out o) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (Resumable ProcessError (Process i o) : r) a
-> Sem
     (Resumable ProcessError (Process i o)
        : Queue (In i) : Queue (Out o) : r)
     a
forall (e2 :: (* -> *) -> * -> *) (e3 :: (* -> *) -> * -> *)
       (e1 :: (* -> *) -> * -> *) (r :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
(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 :: [(* -> *) -> * -> *]) 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 :: [(* -> *) -> * -> *]).
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 :: [(* -> *) -> * -> *]).
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