{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- |
-- A thin wrapper on top of "Debug.Trace", providing linear versions of
-- tracing functions.
--
-- It only contains minimal amount of documentation; you should consult
-- the original "Debug.Trace" module for more detailed information.
module Debug.Trace.Linear
  ( -- * Tracing
    trace
  , traceShow
  , traceId
  , traceStack
  , traceIO
  , traceM
  , traceShowM
    -- * Eventlog tracing
  , traceEvent
  , traceEventIO
    -- * Execution phase markers
  , traceMarker
  , traceMarkerIO
  ) where

import qualified Debug.Trace as NonLinear
import qualified Unsafe.Linear as Unsafe
import System.IO.Linear
import Data.Functor.Linear
import Data.Unrestricted.Linear
import Prelude (String, Show(..))
import Prelude.Linear.Internal

-- | The 'trace' function outputs the trace message given as its first
-- argument, before returning the second argument as its result.
trace :: String %1-> a %1-> a
trace :: forall a. String %1 -> a %1 -> a
trace = (String -> a -> a) %1 -> String %1 -> a %1 -> a
forall a b c (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %1 -> b %1 -> c
Unsafe.toLinear2 String -> a -> a
forall a. String -> a -> a
NonLinear.trace

-- | Like 'trace', but uses 'show' on the argument to convert it to
-- a 'String'.
traceShow :: Show a => a -> b %1-> b
traceShow :: forall a b. Show a => a -> b %1 -> b
traceShow a
a = (b -> b) %1 -> b %1 -> b
forall a b (p :: Multiplicity). (a %p -> b) %1 -> a %1 -> b
Unsafe.toLinear (a -> b -> b
forall a b. Show a => a -> b -> b
NonLinear.traceShow a
a)

-- | Like 'trace' but returns the message instead of a third value.
traceId :: String %1-> String
traceId :: String %1 -> String
traceId String
s = String %1 -> (String, String)
forall a. Dupable a => a %1 -> (a, a)
dup String
s (String, String) %1 -> ((String, String) %1 -> String) %1 -> String
forall a b. a %1 -> (a %1 -> b) %1 -> b
& \(String
s', String
s'') -> String %1 -> String %1 -> String
forall a. String %1 -> a %1 -> a
trace String
s' String
s''

-- | Like 'trace', but additionally prints a call stack if one is
-- available.
traceStack :: String %1-> a %1-> a
traceStack :: forall a. String %1 -> a %1 -> a
traceStack = (String -> a -> a) %1 -> String %1 -> a %1 -> a
forall a b c (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %1 -> b %1 -> c
Unsafe.toLinear2 String -> a -> a
forall a. String -> a -> a
NonLinear.traceStack

-- | The 'traceIO' function outputs the trace message from the IO monad.
-- This sequences the output with respect to other IO actions.
traceIO :: String %1-> IO ()
traceIO :: String %1 -> IO ()
traceIO String
s = IO () %1 -> IO ()
forall a. IO a %1 -> IO a
fromSystemIO ((String -> IO ()) %1 -> String %1 -> IO ()
forall a b (p :: Multiplicity). (a %p -> b) %1 -> a %1 -> b
Unsafe.toLinear String -> IO ()
NonLinear.traceIO String
s)

-- | Like 'trace' but returning unit in an arbitrary 'Applicative'
-- context. Allows for convenient use in do-notation.
traceM :: Applicative f => String %1-> f ()
traceM :: forall (f :: * -> *). Applicative f => String %1 -> f ()
traceM String
s = String %1 -> f () %1 -> f ()
forall a. String %1 -> a %1 -> a
trace String
s (f () %1 -> f ()) %1 -> f () %1 -> f ()
forall a b. (a %1 -> b) %1 -> a %1 -> b
$ () -> f ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

-- | Like 'traceM', but uses 'show' on the argument to convert it to a
-- 'String'.
traceShowM :: (Show a, Applicative f) => a -> f ()
traceShowM :: forall a (f :: * -> *). (Show a, Applicative f) => a -> f ()
traceShowM a
a = String %1 -> f ()
forall (f :: * -> *). Applicative f => String %1 -> f ()
traceM (a -> String
forall a. Show a => a -> String
show a
a)

-- | The 'traceEvent' function behaves like 'trace' with the difference
-- that the message is emitted to the eventlog, if eventlog profiling is
-- available and enabled at runtime.
traceEvent :: String %1-> a %1-> a
traceEvent :: forall a. String %1 -> a %1 -> a
traceEvent = (String -> a -> a) %1 -> String %1 -> a %1 -> a
forall a b c (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %1 -> b %1 -> c
Unsafe.toLinear2 String -> a -> a
forall a. String -> a -> a
NonLinear.traceEvent

-- | The 'traceEventIO' function emits a message to the eventlog, if
-- eventlog profiling is available and enabled at runtime.
traceEventIO :: String %1-> IO ()
traceEventIO :: String %1 -> IO ()
traceEventIO String
s = IO () %1 -> IO ()
forall a. IO a %1 -> IO a
fromSystemIO ((String -> IO ()) %1 -> String %1 -> IO ()
forall a b (p :: Multiplicity). (a %p -> b) %1 -> a %1 -> b
Unsafe.toLinear String -> IO ()
NonLinear.traceEventIO String
s)

-- | The 'traceMarker' function emits a marker to the eventlog, if eventlog
-- profiling is available and enabled at runtime. The @String@ is the name
-- of the marker. The name is just used in the profiling tools to help you
-- keep clear which marker is which.
traceMarker :: String %1-> a %1-> a
traceMarker :: forall a. String %1 -> a %1 -> a
traceMarker = (String -> a -> a) %1 -> String %1 -> a %1 -> a
forall a b c (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %1 -> b %1 -> c
Unsafe.toLinear2 String -> a -> a
forall a. String -> a -> a
NonLinear.traceMarker

-- | The 'traceMarkerIO' function emits a marker to the eventlog, if
-- eventlog profiling is available and enabled at runtime.
traceMarkerIO :: String %1-> IO ()
traceMarkerIO :: String %1 -> IO ()
traceMarkerIO String
s = IO () %1 -> IO ()
forall a. IO a %1 -> IO a
fromSystemIO ((String -> IO ()) %1 -> String %1 -> IO ()
forall a b (p :: Multiplicity). (a %p -> b) %1 -> a %1 -> b
Unsafe.toLinear String -> IO ()
NonLinear.traceMarkerIO String
s)