{-# LANGUAGE Unsafe #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE UnboxedTuples #-}
module Debug.Trace (
trace,
traceId,
traceShow,
traceShowId,
traceWith,
traceShowWith,
traceStack,
traceIO,
traceM,
traceShowM,
putTraceMsg,
traceEvent,
traceEventWith,
traceEventIO,
flushEventLog,
traceMarker,
traceMarkerIO,
) where
import System.IO.Unsafe
import Foreign.C.String
import GHC.Base
import qualified GHC.Foreign
import GHC.IO.Encoding
import GHC.Ptr
import GHC.Show
import GHC.Stack
import Data.List (null, partition)
traceIO :: String -> IO ()
traceIO :: String -> IO ()
traceIO String
msg =
String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCString String
"%s\n" ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
cfmt -> do
let (String
nulls, String
msg') = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'\0') String
msg
String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCString String
msg' ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
cmsg ->
CString -> CString -> IO ()
debugBelch CString
cfmt CString
cmsg
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
nulls)) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCString String
"WARNING: previous trace message had null bytes" ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
cmsg ->
CString -> CString -> IO ()
debugBelch CString
cfmt CString
cmsg
foreign import ccall unsafe "HsBase.h debugBelch2"
debugBelch :: CString -> CString -> IO ()
putTraceMsg :: String -> IO ()
putTraceMsg :: String -> IO ()
putTraceMsg = String -> IO ()
traceIO
{-# DEPRECATED putTraceMsg "Use 'Debug.Trace.traceIO'" #-}
{-# NOINLINE trace #-}
trace :: String -> a -> a
trace :: forall a. String -> a -> a
trace String
string a
expr = IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
traceIO String
string
a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
expr
traceId :: String -> String
traceId :: String -> String
traceId String
a = String -> String -> String
forall a. String -> a -> a
trace String
a String
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. String -> a -> a
trace (a -> String
forall a. Show a => a -> String
show a
a) a
a
traceWith :: (a -> String) -> a -> a
traceWith :: forall a. (a -> String) -> a -> a
traceWith a -> String
f a
a = String -> a -> a
forall a. String -> a -> a
trace (a -> String
f a
a) a
a
traceShowWith :: Show b => (a -> b) -> a -> a
traceShowWith :: forall b a. Show b => (a -> b) -> a -> a
traceShowWith a -> b
f = (a -> String) -> a -> a
forall a. (a -> String) -> a -> a
traceWith (b -> String
forall a. Show a => a -> String
show (b -> String) -> (a -> b) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f)
traceM :: Applicative f => String -> f ()
traceM :: forall (f :: * -> *). Applicative f => String -> f ()
traceM String
string = String -> f () -> f ()
forall a. String -> a -> a
trace String
string (f () -> f ()) -> f () -> f ()
forall a b. (a -> b) -> a -> b
$ () -> f ()
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
traceShowM :: (Show a, Applicative f) => a -> f ()
traceShowM :: forall a (f :: * -> *). (Show a, Applicative f) => a -> f ()
traceShowM = String -> f ()
forall (f :: * -> *). Applicative f => String -> f ()
traceM (String -> f ()) -> (a -> String) -> a -> f ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
traceStack :: String -> a -> a
traceStack :: forall a. String -> a -> a
traceStack String
str a
expr = IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
traceIO String
str
[String]
stack <- IO [String]
currentCallStack
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not ([String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
stack)) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
traceIO ([String] -> String
renderStack [String]
stack)
a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
expr
{-# NOINLINE traceEvent #-}
traceEvent :: String -> a -> a
traceEvent :: forall a. String -> a -> a
traceEvent String
msg a
expr = IO a -> a
forall a. IO a -> a
unsafeDupablePerformIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
traceEventIO String
msg
a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
expr
traceEventIO :: String -> IO ()
traceEventIO :: String -> IO ()
traceEventIO String
msg =
TextEncoding -> String -> (CString -> IO ()) -> IO ()
forall a. TextEncoding -> String -> (CString -> IO a) -> IO a
GHC.Foreign.withCString TextEncoding
utf8 String
msg ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Ptr Addr#
p) -> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s ->
case Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
traceEvent# Addr#
p State# RealWorld
s of State# RealWorld
s' -> (# State# RealWorld
s', () #)
traceEventWith :: (a -> String) -> a -> a
traceEventWith :: forall a. (a -> String) -> a -> a
traceEventWith a -> String
f a
a = String -> a -> a
forall a. String -> a -> a
traceEvent (a -> String
f a
a) a
a
{-# NOINLINE traceMarker #-}
traceMarker :: String -> a -> a
traceMarker :: forall a. String -> a -> a
traceMarker String
msg a
expr = IO a -> a
forall a. IO a -> a
unsafeDupablePerformIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
traceMarkerIO String
msg
a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
expr
traceMarkerIO :: String -> IO ()
traceMarkerIO :: String -> IO ()
traceMarkerIO String
msg =
TextEncoding -> String -> (CString -> IO ()) -> IO ()
forall a. TextEncoding -> String -> (CString -> IO a) -> IO a
GHC.Foreign.withCString TextEncoding
utf8 String
msg ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Ptr Addr#
p) -> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s ->
case Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
traceMarker# Addr#
p State# RealWorld
s of State# RealWorld
s' -> (# State# RealWorld
s', () #)
flushEventLog :: IO ()
flushEventLog :: IO ()
flushEventLog = Ptr () -> IO ()
c_flushEventLog Ptr ()
forall a. Ptr a
nullPtr
foreign import ccall "flushEventLog" c_flushEventLog :: Ptr () -> IO ()