{-# LANGUAGE CPP                #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric      #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE ImplicitParams     #-}
{-# LANGUAGE KindSignatures     #-}
{-# LANGUAGE MagicHash          #-}
{-# LANGUAGE PolyKinds          #-}
{-# LANGUAGE RankNTypes         #-}
{-# LANGUAGE Trustworthy        #-}
{-# LANGUAGE TypeInType         #-}

-- | Functions for debugging. If you left these functions in your code
-- then warning is generated to remind you about left usages. Also, some
-- functions (and data types) are convenient for prototyping.

module Universum.Debug
       ( Undefined (..)
       , error
       , trace
       , traceM
       , traceId
       , traceIdWith
       , traceShow
       , traceShowId
       , traceShowIdWith
       , traceShowM
       , undefined
       ) where

import Control.Monad (Monad, return)
import Data.Data (Data)
import Data.Text (Text, pack, unpack)
import GHC.Generics (Generic)
import System.IO.Unsafe (unsafePerformIO)

import GHC.Exception (errorCallWithCallStackException)
import GHC.Exts (RuntimeRep, TYPE, raise#)

import Universum.Applicative (pass)
import Universum.Base (HasCallStack, callStack)
import Universum.Print (putStrLn)

import qualified Prelude as P

-- | Version of 'Debug.Trace.trace' that leaves a warning and takes 'Text'.
{-# WARNING trace "'trace' remains in code" #-}
trace :: Text -> a -> a
trace :: Text -> a -> a
trace Text
string a
expr = IO a -> a
forall a. IO a -> a
unsafePerformIO (do
    Text -> IO ()
forall a (m :: * -> *). (Print a, MonadIO m) => a -> m ()
putStrLn Text
string
    a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
expr)

-- | 'P.error' that takes 'Text' as an argument.
error :: forall (r :: RuntimeRep) . forall (a :: TYPE r) . HasCallStack
      => Text -> a
error :: Text -> a
error Text
s = SomeException -> a
forall b a. b -> a
raise# (String -> CallStack -> SomeException
errorCallWithCallStackException (Text -> String
unpack Text
s) CallStack
HasCallStack => CallStack
callStack)

-- | Version of 'Debug.Trace.traceShow' that leaves a warning.
{-# WARNING traceShow "'traceShow' remains in code" #-}
traceShow :: P.Show a => a -> b -> b
traceShow :: a -> b -> b
traceShow a
a b
b = Text -> b -> b
forall a. Text -> a -> a
trace (String -> Text
pack (a -> String
forall a. Show a => a -> String
P.show a
a)) b
b

-- | Version of 'Debug.Trace.traceShowId' that leaves a warning.
{-# WARNING traceShowId "'traceShowId' remains in code" #-}
traceShowId :: P.Show a => a -> a
traceShowId :: a -> a
traceShowId a
a = Text -> a -> a
forall a. Text -> a -> a
trace (String -> Text
pack (a -> String
forall a. Show a => a -> String
P.show a
a)) a
a

{- | Version of 'Debug.Trace.traceId' that leaves a warning.
Useful to tag printed data, for instance:

@
traceIdWith (\x -> "My data: " <> show x) (veryLargeExpression)
@

This is especially useful with custom formatters:

@
traceIdWith (\x -> "My data: " <> pretty x) (veryLargeExpression)
@
-}
{-# WARNING traceIdWith "'traceIdWith' remains in code" #-}
traceIdWith :: (a -> Text) -> a -> a
traceIdWith :: (a -> Text) -> a -> a
traceIdWith a -> Text
f a
a = Text -> a -> a
forall a. Text -> a -> a
trace (a -> Text
f a
a) a
a

-- | Version of 'Debug.Trace.traceShowId' that leaves a warning.
-- Useful to tag printed data, for instance:
--
-- @
-- traceShowIdWith ("My data: ", ) (veryLargeExpression)
-- @
{-# WARNING traceShowIdWith "'traceShowIdWith' remains in code" #-}
traceShowIdWith :: P.Show s => (a -> s) -> a -> a
traceShowIdWith :: (a -> s) -> a -> a
traceShowIdWith a -> s
f a
a = Text -> a -> a
forall a. Text -> a -> a
trace (String -> Text
pack (s -> String
forall a. Show a => a -> String
P.show (a -> s
f a
a))) a
a

-- | Version of 'Debug.Trace.traceShowM' that leaves a warning.
{-# WARNING traceShowM "'traceShowM' remains in code" #-}
traceShowM :: (P.Show a, Monad m) => a -> m ()
traceShowM :: a -> m ()
traceShowM a
a = Text -> m () -> m ()
forall a. Text -> a -> a
trace (String -> Text
pack (a -> String
forall a. Show a => a -> String
P.show a
a)) m ()
forall (f :: * -> *). Applicative f => f ()
pass

-- | Version of 'Debug.Trace.traceM' that leaves a warning and takes 'Text'.
{-# WARNING traceM "'traceM' remains in code" #-}
traceM :: (Monad m) => Text -> m ()
traceM :: Text -> m ()
traceM Text
s = Text -> m () -> m ()
forall a. Text -> a -> a
trace Text
s m ()
forall (f :: * -> *). Applicative f => f ()
pass

-- | Version of 'Debug.Trace.traceId' that leaves a warning.
{-# WARNING traceId "'traceId' remains in code" #-}
traceId :: Text -> Text
traceId :: Text -> Text
traceId Text
s = Text -> Text -> Text
forall a. Text -> a -> a
trace Text
s Text
s

-- | Similar to 'undefined' but data type.
{-# WARNING Undefined "'Undefined' type remains in code" #-}
data Undefined = Undefined
    deriving stock (Undefined -> Undefined -> Bool
(Undefined -> Undefined -> Bool)
-> (Undefined -> Undefined -> Bool) -> Eq Undefined
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Undefined -> Undefined -> Bool
$c/= :: Undefined -> Undefined -> Bool
== :: Undefined -> Undefined -> Bool
$c== :: Undefined -> Undefined -> Bool
P.Eq, Eq Undefined
Eq Undefined
-> (Undefined -> Undefined -> Ordering)
-> (Undefined -> Undefined -> Bool)
-> (Undefined -> Undefined -> Bool)
-> (Undefined -> Undefined -> Bool)
-> (Undefined -> Undefined -> Bool)
-> (Undefined -> Undefined -> Undefined)
-> (Undefined -> Undefined -> Undefined)
-> Ord Undefined
Undefined -> Undefined -> Bool
Undefined -> Undefined -> Ordering
Undefined -> Undefined -> Undefined
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Undefined -> Undefined -> Undefined
$cmin :: Undefined -> Undefined -> Undefined
max :: Undefined -> Undefined -> Undefined
$cmax :: Undefined -> Undefined -> Undefined
>= :: Undefined -> Undefined -> Bool
$c>= :: Undefined -> Undefined -> Bool
> :: Undefined -> Undefined -> Bool
$c> :: Undefined -> Undefined -> Bool
<= :: Undefined -> Undefined -> Bool
$c<= :: Undefined -> Undefined -> Bool
< :: Undefined -> Undefined -> Bool
$c< :: Undefined -> Undefined -> Bool
compare :: Undefined -> Undefined -> Ordering
$ccompare :: Undefined -> Undefined -> Ordering
$cp1Ord :: Eq Undefined
P.Ord, Int -> Undefined -> ShowS
[Undefined] -> ShowS
Undefined -> String
(Int -> Undefined -> ShowS)
-> (Undefined -> String)
-> ([Undefined] -> ShowS)
-> Show Undefined
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Undefined] -> ShowS
$cshowList :: [Undefined] -> ShowS
show :: Undefined -> String
$cshow :: Undefined -> String
showsPrec :: Int -> Undefined -> ShowS
$cshowsPrec :: Int -> Undefined -> ShowS
P.Show, ReadPrec [Undefined]
ReadPrec Undefined
Int -> ReadS Undefined
ReadS [Undefined]
(Int -> ReadS Undefined)
-> ReadS [Undefined]
-> ReadPrec Undefined
-> ReadPrec [Undefined]
-> Read Undefined
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Undefined]
$creadListPrec :: ReadPrec [Undefined]
readPrec :: ReadPrec Undefined
$creadPrec :: ReadPrec Undefined
readList :: ReadS [Undefined]
$creadList :: ReadS [Undefined]
readsPrec :: Int -> ReadS Undefined
$creadsPrec :: Int -> ReadS Undefined
P.Read, Int -> Undefined
Undefined -> Int
Undefined -> [Undefined]
Undefined -> Undefined
Undefined -> Undefined -> [Undefined]
Undefined -> Undefined -> Undefined -> [Undefined]
(Undefined -> Undefined)
-> (Undefined -> Undefined)
-> (Int -> Undefined)
-> (Undefined -> Int)
-> (Undefined -> [Undefined])
-> (Undefined -> Undefined -> [Undefined])
-> (Undefined -> Undefined -> [Undefined])
-> (Undefined -> Undefined -> Undefined -> [Undefined])
-> Enum Undefined
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Undefined -> Undefined -> Undefined -> [Undefined]
$cenumFromThenTo :: Undefined -> Undefined -> Undefined -> [Undefined]
enumFromTo :: Undefined -> Undefined -> [Undefined]
$cenumFromTo :: Undefined -> Undefined -> [Undefined]
enumFromThen :: Undefined -> Undefined -> [Undefined]
$cenumFromThen :: Undefined -> Undefined -> [Undefined]
enumFrom :: Undefined -> [Undefined]
$cenumFrom :: Undefined -> [Undefined]
fromEnum :: Undefined -> Int
$cfromEnum :: Undefined -> Int
toEnum :: Int -> Undefined
$ctoEnum :: Int -> Undefined
pred :: Undefined -> Undefined
$cpred :: Undefined -> Undefined
succ :: Undefined -> Undefined
$csucc :: Undefined -> Undefined
P.Enum, Undefined
Undefined -> Undefined -> Bounded Undefined
forall a. a -> a -> Bounded a
maxBound :: Undefined
$cmaxBound :: Undefined
minBound :: Undefined
$cminBound :: Undefined
P.Bounded, Typeable Undefined
DataType
Constr
Typeable Undefined
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Undefined -> c Undefined)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Undefined)
-> (Undefined -> Constr)
-> (Undefined -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Undefined))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Undefined))
-> ((forall b. Data b => b -> b) -> Undefined -> Undefined)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Undefined -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Undefined -> r)
-> (forall u. (forall d. Data d => d -> u) -> Undefined -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> Undefined -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Undefined -> m Undefined)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Undefined -> m Undefined)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Undefined -> m Undefined)
-> Data Undefined
Undefined -> DataType
Undefined -> Constr
(forall b. Data b => b -> b) -> Undefined -> Undefined
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Undefined -> c Undefined
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Undefined
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Undefined -> u
forall u. (forall d. Data d => d -> u) -> Undefined -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Undefined -> m Undefined
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Undefined -> m Undefined
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Undefined
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Undefined -> c Undefined
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Undefined)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Undefined)
$cUndefined :: Constr
$tUndefined :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Undefined -> m Undefined
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Undefined -> m Undefined
gmapMp :: (forall d. Data d => d -> m d) -> Undefined -> m Undefined
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Undefined -> m Undefined
gmapM :: (forall d. Data d => d -> m d) -> Undefined -> m Undefined
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Undefined -> m Undefined
gmapQi :: Int -> (forall d. Data d => d -> u) -> Undefined -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Undefined -> u
gmapQ :: (forall d. Data d => d -> u) -> Undefined -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Undefined -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
gmapT :: (forall b. Data b => b -> b) -> Undefined -> Undefined
$cgmapT :: (forall b. Data b => b -> b) -> Undefined -> Undefined
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Undefined)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Undefined)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Undefined)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Undefined)
dataTypeOf :: Undefined -> DataType
$cdataTypeOf :: Undefined -> DataType
toConstr :: Undefined -> Constr
$ctoConstr :: Undefined -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Undefined
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Undefined
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Undefined -> c Undefined
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Undefined -> c Undefined
$cp1Data :: Typeable Undefined
Data, (forall x. Undefined -> Rep Undefined x)
-> (forall x. Rep Undefined x -> Undefined) -> Generic Undefined
forall x. Rep Undefined x -> Undefined
forall x. Undefined -> Rep Undefined x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Undefined x -> Undefined
$cfrom :: forall x. Undefined -> Rep Undefined x
Generic)

-- | 'P.undefined' that leaves a warning in code on every usage.
{-# WARNING undefined "'undefined' function remains in code (or use 'error')" #-}
undefined :: forall (r :: RuntimeRep) . forall (a :: TYPE r) . HasCallStack => a
undefined :: a
undefined = a
forall a. HasCallStack => a
P.undefined