{-# 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 Data.Functor.Linear
import Data.Unrestricted.Linear
import qualified Debug.Trace as NonLinear
import Prelude.Linear.Internal
import System.IO.Linear
import qualified Unsafe.Linear as Unsafe
import Prelude (Show (..), String)

-- | 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 = forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 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 = forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear (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 = forall a. Dupable a => a %1 -> (a, a)
dup String
s forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
& \(String
s', String
s'') -> 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 = forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 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 = forall a. IO a %1 -> IO a
fromSystemIO (forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> 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 = forall a. String %1 -> a %1 -> a
trace String
s forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ 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 = forall (f :: * -> *). Applicative f => String %1 -> f ()
traceM (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 = forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 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 = forall a. IO a %1 -> IO a
fromSystemIO (forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> 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 = forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 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 = forall a. IO a %1 -> IO a
fromSystemIO (forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear String -> IO ()
NonLinear.traceMarkerIO String
s)