{-# options_haddock prune #-}

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

import Data.ByteString (hGetSome, hPut)
import Polysemy.Resume (Stop, interpretResumable, interpretScopedR, stop, stopNote, stopTryIOError, type (!!))
import Polysemy.Scoped (Scoped, Scoped_, runScopedNew)
import Prelude hiding (fromException)
import System.IO (BufferMode (NoBuffering), Handle, hSetBuffering)
import qualified System.Posix as Signal
import System.Process (Pid, getPid)
import System.Process.Typed (
  Process,
  ProcessConfig,
  createPipe,
  getStderr,
  getStdin,
  getStdout,
  setStderr,
  setStdin,
  setStdout,
  startProcess,
  stopProcess,
  unsafeProcessHandle,
  waitExitCode,
  )

import qualified Polysemy.Process.Data.SystemProcessError as SystemProcessError
import Polysemy.Process.Data.SystemProcessError (SystemProcessError, SystemProcessScopeError (StartFailed))
import qualified Polysemy.Process.Effect.SystemProcess as SystemProcess
import Polysemy.Process.Effect.SystemProcess (SystemProcess)

-- |Convenience alias for a vanilla 'ProcessConfig', which will usually be transformed by interpreters to use 'Handle's.
type SysProcConf =
  ProcessConfig () () ()

-- |Convenience alias for the 'Process' type used by native interpreters.
type PipesProcess =
  Process Handle Handle Handle

processWithPipes :: SysProcConf -> ProcessConfig Handle Handle Handle
processWithPipes :: SysProcConf -> ProcessConfig Handle Handle Handle
processWithPipes =
  StreamSpec 'STInput Handle
-> ProcessConfig () Handle Handle
-> ProcessConfig Handle Handle Handle
forall stdin stdin0 stdout stderr.
StreamSpec 'STInput stdin
-> ProcessConfig stdin0 stdout stderr
-> ProcessConfig stdin stdout stderr
setStdin StreamSpec 'STInput Handle
forall (anyStreamType :: StreamType).
StreamSpec anyStreamType Handle
createPipe (ProcessConfig () Handle Handle
 -> ProcessConfig Handle Handle Handle)
-> (SysProcConf -> ProcessConfig () Handle Handle)
-> SysProcConf
-> ProcessConfig Handle Handle Handle
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  StreamSpec 'STOutput Handle
-> ProcessConfig () () Handle -> ProcessConfig () Handle Handle
forall stdout stdin stdout0 stderr.
StreamSpec 'STOutput stdout
-> ProcessConfig stdin stdout0 stderr
-> ProcessConfig stdin stdout stderr
setStdout StreamSpec 'STOutput Handle
forall (anyStreamType :: StreamType).
StreamSpec anyStreamType Handle
createPipe (ProcessConfig () () Handle -> ProcessConfig () Handle Handle)
-> (SysProcConf -> ProcessConfig () () Handle)
-> SysProcConf
-> ProcessConfig () Handle Handle
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  StreamSpec 'STOutput Handle
-> SysProcConf -> ProcessConfig () () Handle
forall stderr stdin stdout stderr0.
StreamSpec 'STOutput stderr
-> ProcessConfig stdin stdout stderr0
-> ProcessConfig stdin stdout stderr
setStderr StreamSpec 'STOutput Handle
forall (anyStreamType :: StreamType).
StreamSpec anyStreamType Handle
createPipe

start ::
  Members [Stop SystemProcessScopeError, Embed IO] r =>
  SysProcConf ->
  Sem r PipesProcess
start :: forall (r :: EffectRow).
Members '[Stop SystemProcessScopeError, Embed IO] r =>
SysProcConf -> Sem r PipesProcess
start =
  (Text -> SystemProcessScopeError)
-> IO PipesProcess -> Sem r PipesProcess
forall err (r :: EffectRow) a.
Members '[Stop err, Embed IO] r =>
(Text -> err) -> IO a -> Sem r a
stopTryIOError Text -> SystemProcessScopeError
SystemProcessError.StartFailed (IO PipesProcess -> Sem r PipesProcess)
-> (SysProcConf -> IO PipesProcess)
-> SysProcConf
-> Sem r PipesProcess
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  ProcessConfig Handle Handle Handle -> IO PipesProcess
forall (m :: * -> *) stdin stdout stderr.
MonadIO m =>
ProcessConfig stdin stdout stderr
-> m (Process stdin stdout stderr)
startProcess (ProcessConfig Handle Handle Handle -> IO PipesProcess)
-> (SysProcConf -> ProcessConfig Handle Handle Handle)
-> SysProcConf
-> IO PipesProcess
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  SysProcConf -> ProcessConfig Handle Handle Handle
processWithPipes

withProcess ::
  Members [Resource, Stop SystemProcessScopeError, Embed IO] r =>
  SysProcConf ->
  (PipesProcess -> Sem r a) ->
  Sem r a
withProcess :: forall (r :: EffectRow) a.
Members '[Resource, Stop SystemProcessScopeError, Embed IO] r =>
SysProcConf -> (PipesProcess -> Sem r a) -> Sem r a
withProcess SysProcConf
config PipesProcess -> Sem r a
use =
  Sem r PipesProcess
-> (PipesProcess -> Sem r (Either Text ()))
-> (PipesProcess -> Sem r a)
-> Sem r a
forall (r :: EffectRow) a c b.
Member Resource r =>
Sem r a -> (a -> Sem r c) -> (a -> Sem r b) -> Sem r b
bracket (SysProcConf -> Sem r PipesProcess
forall (r :: EffectRow).
Members '[Stop SystemProcessScopeError, Embed IO] r =>
SysProcConf -> Sem r PipesProcess
start SysProcConf
config) (IO () -> Sem r (Either Text ())
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either Text a)
tryIOError (IO () -> Sem r (Either Text ()))
-> (PipesProcess -> IO ())
-> PipesProcess
-> Sem r (Either Text ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PipesProcess -> IO ()
forall (m :: * -> *) stdin stdout stderr.
MonadIO m =>
Process stdin stdout stderr -> m ()
stopProcess) \ PipesProcess
p -> do
    Handle -> Sem r ()
forall {r :: EffectRow}. Member (Embed IO) r => Handle -> Sem r ()
unbuffer (PipesProcess -> Handle
forall stdin stdout stderr. Process stdin stdout stderr -> stdin
getStdin PipesProcess
p)
    Handle -> Sem r ()
forall {r :: EffectRow}. Member (Embed IO) r => Handle -> Sem r ()
unbuffer (PipesProcess -> Handle
forall stdin stdout stderr. Process stdin stdout stderr -> stdout
getStdout PipesProcess
p)
    Handle -> Sem r ()
forall {r :: EffectRow}. Member (Embed IO) r => Handle -> Sem r ()
unbuffer (PipesProcess -> Handle
forall stdin stdout stderr. Process stdin stdout stderr -> stderr
getStderr PipesProcess
p)
    PipesProcess -> Sem r a
use PipesProcess
p
  where
    unbuffer :: Handle -> Sem r ()
unbuffer Handle
h =
      Sem r (Maybe ()) -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Sem r (Maybe ()) -> Sem r ()) -> Sem r (Maybe ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ IO () -> Sem r (Maybe ())
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Maybe a)
tryMaybe (Handle -> BufferMode -> IO ()
hSetBuffering Handle
h BufferMode
NoBuffering)

withProcessOpaque ::
  Members [Resource, Embed IO] r =>
  ProcessConfig i o e ->
  (Process i o e -> Sem r a) ->
  Sem r a
withProcessOpaque :: forall (r :: EffectRow) i o e a.
Members '[Resource, Embed IO] r =>
ProcessConfig i o e -> (Process i o e -> Sem r a) -> Sem r a
withProcessOpaque ProcessConfig i o e
config =
  Sem r (Process i o e)
-> (Process i o e -> Sem r (Either Text ()))
-> (Process i o e -> Sem r a)
-> Sem r a
forall (r :: EffectRow) a c b.
Member Resource r =>
Sem r a -> (a -> Sem r c) -> (a -> Sem r b) -> Sem r b
bracket (ProcessConfig i o e -> Sem r (Process i o e)
forall (m :: * -> *) stdin stdout stderr.
MonadIO m =>
ProcessConfig stdin stdout stderr
-> m (Process stdin stdout stderr)
startProcess ProcessConfig i o e
config) (IO () -> Sem r (Either Text ())
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either Text a)
tryIOError (IO () -> Sem r (Either Text ()))
-> (Process i o e -> IO ())
-> Process i o e
-> Sem r (Either Text ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Process i o e -> IO ()
forall (m :: * -> *) stdin stdout stderr.
MonadIO m =>
Process stdin stdout stderr -> m ()
stopProcess)

terminate ::
  Member (Stop SystemProcessError) r =>
  Text ->
  Maybe a ->
  Sem r a
terminate :: forall (r :: EffectRow) a.
Member (Stop SystemProcessError) r =>
Text -> Maybe a -> Sem r a
terminate Text
msg =
  SystemProcessError -> Maybe a -> Sem r a
forall err (r :: EffectRow) a.
Member (Stop err) r =>
err -> Maybe a -> Sem r a
stopNote (Text -> SystemProcessError
SystemProcessError.Terminated Text
msg)

tryStop ::
  Members [Stop SystemProcessError, Embed IO] r =>
  Text ->
  IO a ->
  Sem r a
tryStop :: forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
msg =
  Text -> Maybe a -> Sem r a
forall (r :: EffectRow) a.
Member (Stop SystemProcessError) r =>
Text -> Maybe a -> Sem r a
terminate Text
msg (Maybe a -> Sem r a)
-> (IO a -> Sem r (Maybe a)) -> IO a -> Sem r a
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< IO a -> Sem r (Maybe a)
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Maybe a)
tryMaybe

processId ::
  Members [Stop SystemProcessError, Embed IO] r =>
  Process i o e ->
  Sem r Pid
processId :: forall (r :: EffectRow) i o e.
Members '[Stop SystemProcessError, Embed IO] r =>
Process i o e -> Sem r Pid
processId Process i o e
process =
  Text -> Maybe Pid -> Sem r Pid
forall (r :: EffectRow) a.
Member (Stop SystemProcessError) r =>
Text -> Maybe a -> Sem r a
terminate Text
"getPid returned Nothing" (Maybe Pid -> Sem r Pid) -> Sem r (Maybe Pid) -> Sem r Pid
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Maybe Pid) -> Sem r (Maybe Pid)
forall (m :: * -> *) (r :: EffectRow) a.
Member (Embed m) r =>
m a -> Sem r a
embed (ProcessHandle -> IO (Maybe Pid)
getPid (Process i o e -> ProcessHandle
forall stdin stdout stderr.
Process stdin stdout stderr -> ProcessHandle
unsafeProcessHandle Process i o e
process))

checkEof ::
  Member (Stop SystemProcessError) r =>
  ByteString ->
  Sem r ByteString
checkEof :: forall (r :: EffectRow).
Member (Stop SystemProcessError) r =>
ByteString -> Sem r ByteString
checkEof = \case
  ByteString
"" ->
    SystemProcessError -> Sem r ByteString
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop (Text -> SystemProcessError
SystemProcessError.Terminated Text
"Process terminated, empty ByteString read from handle")
  ByteString
b ->
    ByteString -> Sem r ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString
b

-- |Handle 'SystemProcess' with a concrete 'System.Process' with connected pipes.
handleSystemProcessWithProcess ::
   r r0 a .
  Members [Stop SystemProcessError, Embed IO] r =>
  Process Handle Handle Handle ->
  SystemProcess (Sem r0) a ->
  Sem r a
handleSystemProcessWithProcess :: forall (r :: EffectRow) (r0 :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
PipesProcess -> SystemProcess (Sem r0) a -> Sem r a
handleSystemProcessWithProcess PipesProcess
process = \case
  SystemProcess (Sem r0) a
SystemProcess.Pid ->
    Pid -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Pid -> a) -> Sem r Pid -> Sem r a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PipesProcess -> Sem r Pid
forall (r :: EffectRow) i o e.
Members '[Stop SystemProcessError, Embed IO] r =>
Process i o e -> Sem r Pid
processId PipesProcess
process
  SystemProcess.Signal Signal
sig -> do
    Pid
pid <- PipesProcess -> Sem r Pid
forall (r :: EffectRow) i o e.
Members '[Stop SystemProcessError, Embed IO] r =>
Process i o e -> Sem r Pid
processId PipesProcess
process
    Text -> IO () -> Sem r ()
forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
"signal failed" (Signal -> Pid -> IO ()
Signal.signalProcess Signal
sig Pid
pid)
  SystemProcess (Sem r0) a
SystemProcess.ReadStdout ->
    ByteString -> Sem r ByteString
forall (r :: EffectRow).
Member (Stop SystemProcessError) r =>
ByteString -> Sem r ByteString
checkEof (ByteString -> Sem r ByteString)
-> Sem r ByteString -> Sem r ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Text -> IO ByteString -> Sem r ByteString
forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
"stdout failed" (Handle -> Int -> IO ByteString
hGetSome (PipesProcess -> Handle
forall stdin stdout stderr. Process stdin stdout stderr -> stdout
getStdout PipesProcess
process) Int
4096)
  SystemProcess (Sem r0) a
SystemProcess.ReadStderr ->
    ByteString -> Sem r ByteString
forall (r :: EffectRow).
Member (Stop SystemProcessError) r =>
ByteString -> Sem r ByteString
checkEof (ByteString -> Sem r ByteString)
-> Sem r ByteString -> Sem r ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Text -> IO ByteString -> Sem r ByteString
forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
"stderr failed" (Handle -> Int -> IO ByteString
hGetSome (PipesProcess -> Handle
forall stdin stdout stderr. Process stdin stdout stderr -> stderr
getStderr PipesProcess
process) Int
4096)
  SystemProcess.WriteStdin ByteString
msg ->
    Text -> IO () -> Sem r ()
forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
"stdin failed" (Handle -> ByteString -> IO ()
hPut (PipesProcess -> Handle
forall stdin stdout stderr. Process stdin stdout stderr -> stdin
getStdin PipesProcess
process) ByteString
msg)
  SystemProcess (Sem r0) a
SystemProcess.Wait ->
    Text -> IO ExitCode -> Sem r ExitCode
forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
"wait failed" (PipesProcess -> IO ExitCode
forall (m :: * -> *) stdin stdout stderr.
MonadIO m =>
Process stdin stdout stderr -> m ExitCode
waitExitCode PipesProcess
process)

-- |Interpret 'SystemProcess' with a concrete 'System.Process' with connected pipes.
interpretSystemProcessWithProcess ::
   r .
  Member (Embed IO) r =>
  Process Handle Handle Handle ->
  InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessWithProcess :: forall (r :: EffectRow).
Member (Embed IO) r =>
PipesProcess
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessWithProcess PipesProcess
process =
  (forall x (r0 :: EffectRow).
 SystemProcess (Sem r0) x -> Sem (Stop SystemProcessError : r) x)
-> InterpreterFor (SystemProcess !! SystemProcessError) 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 (PipesProcess
-> SystemProcess (Sem r0) x -> Sem (Stop SystemProcessError : r) x
forall (r :: EffectRow) (r0 :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
PipesProcess -> SystemProcess (Sem r0) a -> Sem r a
handleSystemProcessWithProcess PipesProcess
process)

-- |Interpret 'SystemProcess' as a single global 'System.Process' that's started immediately.
interpretSystemProcessNativeSingle ::
   r .
  Members [Stop SystemProcessScopeError, Resource, Embed IO] r =>
  SysProcConf ->
  InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessNativeSingle :: forall (r :: EffectRow).
Members '[Stop SystemProcessScopeError, Resource, Embed IO] r =>
SysProcConf
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessNativeSingle SysProcConf
config Sem ((SystemProcess !! SystemProcessError) : r) a
sem =
  SysProcConf -> (PipesProcess -> Sem r a) -> Sem r a
forall (r :: EffectRow) a.
Members '[Resource, Stop SystemProcessScopeError, Embed IO] r =>
SysProcConf -> (PipesProcess -> Sem r a) -> Sem r a
withProcess SysProcConf
config \ PipesProcess
process ->
    PipesProcess
-> InterpreterFor (SystemProcess !! SystemProcessError) r
forall (r :: EffectRow).
Member (Embed IO) r =>
PipesProcess
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessWithProcess PipesProcess
process Sem ((SystemProcess !! SystemProcessError) : r) a
sem

withProcConf ::
  Members [Stop SystemProcessScopeError, Resource, Embed IO] r =>
  (PipesProcess -> Sem r a) ->
  Either Text SysProcConf ->
  Sem r a
withProcConf :: forall (r :: EffectRow) a.
Members '[Stop SystemProcessScopeError, Resource, Embed IO] r =>
(PipesProcess -> Sem r a) -> Either Text SysProcConf -> Sem r a
withProcConf PipesProcess -> Sem r a
use = \case
  Right SysProcConf
conf ->
    SysProcConf -> (PipesProcess -> Sem r a) -> Sem r a
forall (r :: EffectRow) a.
Members '[Resource, Stop SystemProcessScopeError, Embed IO] r =>
SysProcConf -> (PipesProcess -> Sem r a) -> Sem r a
withProcess SysProcConf
conf PipesProcess -> Sem r a
use
  Left Text
err ->
    SystemProcessScopeError -> Sem r a
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop (Text -> SystemProcessScopeError
StartFailed Text
err)
{-# inline withProcConf #-}

-- |Interpret 'SystemProcess' as a scoped 'System.Process' that's started wherever 'Polysemy.Process.withSystemProcess'
-- is called and terminated when the wrapped action finishes.
-- This variant is for parameterized scopes, allowing the consumer to supply a value of type @param@ to create the
-- process config.
interpretSystemProcessNative ::
   param r .
  Members [Resource, Embed IO] r =>
  (param -> Sem r (Either Text SysProcConf)) ->
  InterpreterFor (Scoped param (SystemProcess !! SystemProcessError) !! SystemProcessScopeError) r
interpretSystemProcessNative :: forall param (r :: EffectRow).
Members '[Resource, Embed IO] r =>
(param -> Sem r (Either Text SysProcConf))
-> InterpreterFor
     (Scoped param (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
interpretSystemProcessNative param -> Sem r (Either Text SysProcConf)
config =
  (forall (q :: (* -> *) -> * -> *) x.
 param
 -> (PipesProcess
     -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
 -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
-> (forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
    PipesProcess
    -> SystemProcess (Sem r0) x
    -> Sem
         (Stop SystemProcessError
            : Stop SystemProcessScopeError : Opaque q : r)
         x)
-> InterpreterFor
     (Scoped param (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
forall param resource (effect :: (* -> *) -> * -> *) eo ei
       (r :: EffectRow).
(forall (q :: (* -> *) -> * -> *) x.
 param
 -> (resource -> Sem (Stop eo : Opaque q : r) x)
 -> Sem (Stop eo : Opaque q : r) x)
-> (forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
    resource
    -> effect (Sem r0) x -> Sem (Stop ei : Stop eo : Opaque q : r) x)
-> InterpreterFor (Scoped param (effect !! ei) !! eo) r
interpretScopedR (\ param
p PipesProcess -> Sem (Stop SystemProcessScopeError : Opaque q : r) x
u -> Sem (Opaque q : r) (Either Text SysProcConf)
-> Sem
     (Stop SystemProcessScopeError : Opaque q : r)
     (Either Text SysProcConf)
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
Sem r a -> Sem (e : r) a
raise (Sem r (Either Text SysProcConf)
-> Sem (Opaque q : r) (Either Text SysProcConf)
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
Sem r a -> Sem (e : r) a
raise (param -> Sem r (Either Text SysProcConf)
config param
p)) Sem
  (Stop SystemProcessScopeError : Opaque q : r)
  (Either Text SysProcConf)
-> (Either Text SysProcConf
    -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
-> Sem (Stop SystemProcessScopeError : Opaque q : r) x
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (PipesProcess
 -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
-> Either Text SysProcConf
-> Sem (Stop SystemProcessScopeError : Opaque q : r) x
forall (r :: EffectRow) a.
Members '[Stop SystemProcessScopeError, Resource, Embed IO] r =>
(PipesProcess -> Sem r a) -> Either Text SysProcConf -> Sem r a
withProcConf PipesProcess -> Sem (Stop SystemProcessScopeError : Opaque q : r) x
u) forall (r :: EffectRow) (r0 :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
PipesProcess -> SystemProcess (Sem r0) a -> Sem r a
forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
PipesProcess
-> SystemProcess (Sem r0) x
-> Sem
     (Stop SystemProcessError
        : Stop SystemProcessScopeError : Opaque q : r)
     x
handleSystemProcessWithProcess

-- |Interpret 'SystemProcess' as a scoped 'System.Process' that's started wherever 'Polysemy.Process.withSystemProcess'
-- is called and terminated when the wrapped action finishes.
-- This variant takes a static 'SysProcConf'.
interpretSystemProcessNative_ ::
   r .
  Members [Resource, Embed IO] r =>
  SysProcConf ->
  InterpreterFor (Scoped_ (SystemProcess !! SystemProcessError) !! SystemProcessScopeError) r
interpretSystemProcessNative_ :: forall (r :: EffectRow).
Members '[Resource, Embed IO] r =>
SysProcConf
-> InterpreterFor
     (Scoped_ (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
interpretSystemProcessNative_ SysProcConf
config =
  (forall (q :: (* -> *) -> * -> *) x.
 ()
 -> (PipesProcess
     -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
 -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
-> (forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
    PipesProcess
    -> SystemProcess (Sem r0) x
    -> Sem
         (Stop SystemProcessError
            : Stop SystemProcessScopeError : Opaque q : r)
         x)
-> InterpreterFor
     (Scoped_ (SystemProcess !! SystemProcessError)
      !! SystemProcessScopeError)
     r
forall param resource (effect :: (* -> *) -> * -> *) eo ei
       (r :: EffectRow).
(forall (q :: (* -> *) -> * -> *) x.
 param
 -> (resource -> Sem (Stop eo : Opaque q : r) x)
 -> Sem (Stop eo : Opaque q : r) x)
-> (forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
    resource
    -> effect (Sem r0) x -> Sem (Stop ei : Stop eo : Opaque q : r) x)
-> InterpreterFor (Scoped param (effect !! ei) !! eo) r
interpretScopedR (((PipesProcess
  -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
 -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
-> ()
-> (PipesProcess
    -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
-> Sem (Stop SystemProcessScopeError : Opaque q : r) x
forall a b. a -> b -> a
const (SysProcConf
-> (PipesProcess
    -> Sem (Stop SystemProcessScopeError : Opaque q : r) x)
-> Sem (Stop SystemProcessScopeError : Opaque q : r) x
forall (r :: EffectRow) a.
Members '[Resource, Stop SystemProcessScopeError, Embed IO] r =>
SysProcConf -> (PipesProcess -> Sem r a) -> Sem r a
withProcess SysProcConf
config)) forall (r :: EffectRow) (r0 :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
PipesProcess -> SystemProcess (Sem r0) a -> Sem r a
forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x.
PipesProcess
-> SystemProcess (Sem r0) x
-> Sem
     (Stop SystemProcessError
        : Stop SystemProcessScopeError : Opaque q : r)
     x
handleSystemProcessWithProcess

-- |Interpret 'SystemProcess' with a concrete 'System.Process' with no connection to stdio.
interpretSystemProcessWithProcessOpaque ::
   i o e r .
  Member (Embed IO) r =>
  Process i o e ->
  InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessWithProcessOpaque :: forall i o e (r :: EffectRow).
Member (Embed IO) r =>
Process i o e
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessWithProcessOpaque Process i o e
process =
  (forall x (r0 :: EffectRow).
 SystemProcess (Sem r0) x -> Sem (Stop SystemProcessError : r) x)
-> InterpreterFor (SystemProcess !! SystemProcessError) 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
    SystemProcess (Sem r0) x
SystemProcess.Pid ->
      Pid -> x
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Pid -> x)
-> Sem (Stop SystemProcessError : r) Pid
-> Sem (Stop SystemProcessError : r) x
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Process i o e -> Sem (Stop SystemProcessError : r) Pid
forall (r :: EffectRow) i o e.
Members '[Stop SystemProcessError, Embed IO] r =>
Process i o e -> Sem r Pid
processId Process i o e
process
    SystemProcess.Signal Signal
sig -> do
      Pid
pid <- Process i o e -> Sem (Stop SystemProcessError : r) Pid
forall (r :: EffectRow) i o e.
Members '[Stop SystemProcessError, Embed IO] r =>
Process i o e -> Sem r Pid
processId Process i o e
process
      Text -> IO () -> Sem (Stop SystemProcessError : r) ()
forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
"signal failed" (Signal -> Pid -> IO ()
Signal.signalProcess Signal
sig Pid
pid)
    SystemProcess (Sem r0) x
SystemProcess.ReadStdout ->
      SystemProcessError -> Sem (Stop SystemProcessError : r) x
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop SystemProcessError
SystemProcessError.NoPipes
    SystemProcess (Sem r0) x
SystemProcess.ReadStderr ->
      SystemProcessError -> Sem (Stop SystemProcessError : r) x
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop SystemProcessError
SystemProcessError.NoPipes
    SystemProcess.WriteStdin ByteString
_ ->
      SystemProcessError -> Sem (Stop SystemProcessError : r) x
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop SystemProcessError
SystemProcessError.NoPipes
    SystemProcess (Sem r0) x
SystemProcess.Wait ->
      Text -> IO ExitCode -> Sem (Stop SystemProcessError : r) ExitCode
forall (r :: EffectRow) a.
Members '[Stop SystemProcessError, Embed IO] r =>
Text -> IO a -> Sem r a
tryStop Text
"wait failed" (Process i o e -> IO ExitCode
forall (m :: * -> *) stdin stdout stderr.
MonadIO m =>
Process stdin stdout stderr -> m ExitCode
waitExitCode Process i o e
process)

-- |Interpret 'SystemProcess' as a single global 'System.Process' that's started immediately.
interpretSystemProcessNativeOpaqueSingle ::
   i o e r .
  Members [Resource, Embed IO] r =>
  ProcessConfig i o e ->
  InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessNativeOpaqueSingle :: forall i o e (r :: EffectRow).
Members '[Resource, Embed IO] r =>
ProcessConfig i o e
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessNativeOpaqueSingle ProcessConfig i o e
config Sem ((SystemProcess !! SystemProcessError) : r) a
sem =
  ProcessConfig i o e -> (Process i o e -> Sem r a) -> Sem r a
forall (r :: EffectRow) i o e a.
Members '[Resource, Embed IO] r =>
ProcessConfig i o e -> (Process i o e -> Sem r a) -> Sem r a
withProcessOpaque ProcessConfig i o e
config \ Process i o e
process ->
    Process i o e
-> InterpreterFor (SystemProcess !! SystemProcessError) r
forall i o e (r :: EffectRow).
Member (Embed IO) r =>
Process i o e
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessWithProcessOpaque Process i o e
process Sem ((SystemProcess !! SystemProcessError) : r) a
sem

-- |Interpret 'SystemProcess' as a scoped 'System.Process' that's started wherever 'Polysemy.Process.withSystemProcess'
-- is called and terminated when the wrapped action finishes.
interpretSystemProcessNativeOpaque ::
   i o e r .
  Members [Resource, Embed IO] r =>
  ProcessConfig i o e ->
  InterpreterFor (Scoped_ (SystemProcess !! SystemProcessError)) r
interpretSystemProcessNativeOpaque :: forall i o e (r :: EffectRow).
Members '[Resource, Embed IO] r =>
ProcessConfig i o e
-> InterpreterFor (Scoped_ (SystemProcess !! SystemProcessError)) r
interpretSystemProcessNativeOpaque ProcessConfig i o e
config =
  (forall (q :: (* -> *) -> * -> *).
 ()
 -> InterpreterFor
      (SystemProcess !! SystemProcessError) (Opaque q : r))
-> InterpreterFor (Scoped_ (SystemProcess !! SystemProcessError)) r
forall param (effect :: (* -> *) -> * -> *) (r :: EffectRow).
(forall (q :: (* -> *) -> * -> *).
 param -> InterpreterFor effect (Opaque q : r))
-> InterpreterFor (Scoped param effect) r
runScopedNew \ () -> ProcessConfig i o e
-> InterpreterFor
     (SystemProcess !! SystemProcessError) (Opaque q : r)
forall i o e (r :: EffectRow).
Members '[Resource, Embed IO] r =>
ProcessConfig i o e
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessNativeOpaqueSingle ProcessConfig i o e
config