content: {-# 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
  