{-# LANGUAGE CPP #-}
module Auxiliary where
import Network
import Control.Concurrent (forkIO, ThreadId)
import System.Environment (withArgs)
import GhcMonad(Ghc(..))
import IdeSession.RPC.API
import IdeSession.RPC.Server
import IdeSession.Util
import IdeSession.Util.PortableProcess
#ifdef VERSION_unix
import System.Posix.Process (forkProcess)
#else
forkProcess :: IO () -> IO Pid
forkProcess = error "unsupported on non-Unix"
#endif
-- | Generalization of captureOutput
captureGhcOutput :: Ghc a -> Ghc (String, a)
captureGhcOutput = unsafeLiftIO captureOutput
-- | Lift operations on `IO` to the `Ghc` monad. This is unsafe as it makes
-- operations possible in the `Ghc` monad that weren't possible before
-- (for instance, @unsafeLiftIO forkIO@ is probably a bad idea!).
unsafeLiftIO :: (IO a -> IO b) -> Ghc a -> Ghc b
unsafeLiftIO f (Ghc ghc) = Ghc $ \session -> f (ghc session)
-- | Generalization of 'unsafeLiftIO'
_unsafeLiftIO1 :: ((c -> IO a) -> IO b) -> (c -> Ghc a) -> Ghc b
_unsafeLiftIO1 f g = Ghc $ \session ->
f $ \c -> case g c of Ghc ghc -> ghc session
-- | Generalization of 'unsafeLiftIO'
--
-- TODO: Is there a more obvious way to define this progression?
unsafeLiftIO2 :: ((c -> d -> IO a) -> IO b) -> (c -> d -> Ghc a) -> Ghc b
unsafeLiftIO2 f g = Ghc $ \session ->
f $ \c d -> case g c d of Ghc ghc -> ghc session
-- | Lift `withArgs` to the `Ghc` monad. Relies on `unsafeLiftIO`.
ghcWithArgs :: [String] -> Ghc a -> Ghc a
ghcWithArgs = unsafeLiftIO . withArgs
-- | Fork within the `Ghc` monad. Use with caution.
_forkGhc :: Ghc () -> Ghc ThreadId
_forkGhc = unsafeLiftIO forkIO
-- | forkProcess within the `Ghc` monad. Use with extreme caution.
forkGhcProcess :: Ghc () -> Ghc Pid
forkGhcProcess = unsafeLiftIO forkProcess
-- | Lifted version of concurrentConversation
ghcConcurrentConversation :: (FilePath -> RpcConversation -> Ghc ())
-> Socket
-> Socket
-> FilePath
-> Ghc ()
ghcConcurrentConversation f requestR responseW errorLog =
unsafeLiftIO2 (concurrentConversation requestR responseW errorLog) f