module Debug.NonInterleavedIO (
putStr
, putStrLn
, print
, trace
, traceShow
, traceShowId
, traceM
, traceShowM
) where
import Prelude hiding (putStr, putStrLn, print)
import Control.Concurrent
import Control.Exception
import Control.Monad.IO.Class
import System.Environment
import System.IO qualified as IO
import System.IO.Temp (getCanonicalTemporaryDirectory)
import System.IO.Unsafe
putStr :: MonadIO m => String -> m ()
putStr :: forall (m :: * -> *). MonadIO m => String -> m ()
putStr String
str = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ MVar Handle -> (Handle -> IO ()) -> IO ()
forall a b. MVar a -> (a -> IO b) -> IO b
withMVar MVar Handle
globalHandle ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Handle
h -> do
Handle -> String -> IO ()
IO.hPutStr Handle
h String
str
Handle -> IO ()
IO.hFlush Handle
h
putStrLn :: MonadIO m => String -> m ()
putStrLn :: forall (m :: * -> *). MonadIO m => String -> m ()
putStrLn = String -> m ()
forall (m :: * -> *). MonadIO m => String -> m ()
putStr (String -> m ()) -> (String -> String) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n")
print :: MonadIO m => Show a => a -> m ()
print :: forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
print = String -> m ()
forall (m :: * -> *). MonadIO m => String -> m ()
putStrLn (String -> m ()) -> (a -> String) -> a -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
trace :: String -> a -> a
trace :: forall a. String -> a -> a
trace String
str a
a = IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ String -> IO ()
forall (m :: * -> *). MonadIO m => String -> m ()
putStrLn String
str IO () -> IO a -> IO a
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
traceShow :: Show a => a -> b -> b
traceShow :: forall a b. Show a => a -> b -> b
traceShow = String -> b -> b
forall a. String -> a -> a
trace (String -> b -> b) -> (a -> String) -> a -> b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
traceShowId :: Show a => a -> a
traceShowId :: forall a. Show a => a -> a
traceShowId a
a = String -> a -> a
forall a b. Show a => a -> b -> b
traceShow (a -> String
forall a. Show a => a -> String
show a
a) a
a
traceM :: Applicative m => String -> m ()
traceM :: forall (m :: * -> *). Applicative m => String -> m ()
traceM String
str = String -> m () -> m ()
forall a. String -> a -> a
trace String
str (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
traceShowM :: (Applicative m, Show a) => a -> m ()
traceShowM :: forall (m :: * -> *) a. (Applicative m, Show a) => a -> m ()
traceShowM = String -> m ()
forall (m :: * -> *). Applicative m => String -> m ()
traceM (String -> m ()) -> (a -> String) -> a -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
globalHandle :: MVar IO.Handle
{-# NOINLINE globalHandle #-}
globalHandle :: MVar Handle
globalHandle = IO (MVar Handle) -> MVar Handle
forall a. IO a -> a
unsafePerformIO (IO (MVar Handle) -> MVar Handle)
-> IO (MVar Handle) -> MVar Handle
forall a b. (a -> b) -> a -> b
$ IO (MVar Handle) -> IO (MVar Handle)
forall a. IO a -> IO a
uninterruptibleMask_ (IO (MVar Handle) -> IO (MVar Handle))
-> IO (MVar Handle) -> IO (MVar Handle)
forall a b. (a -> b) -> a -> b
$ do
mOutput <- String -> IO (Maybe String)
lookupEnv String
"NIIO_OUTPUT"
(fp, h) <- case mOutput of
Maybe String
Nothing -> do
tmpDir <- IO String
getCanonicalTemporaryDirectory
IO.openTempFile tmpDir "niio"
Just String
fp -> do
(String
fp,) (Handle -> (String, Handle)) -> IO Handle -> IO (String, Handle)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IOMode -> IO Handle
IO.openFile String
fp IOMode
IO.WriteMode
IO.hPutStrLn IO.stderr $ "niio output to " ++ fp
IO.hFlush IO.stderr
newMVar h