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

-- | 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 :: forall a. 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 a. 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 :: forall a. HasCallStack => Text -> a
error Text
s = SomeException -> a
forall a b. a -> b
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 :: forall a b. Show a => 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 :: forall a. Show a => 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 :: forall a. (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 :: forall s a. Show s => (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 :: forall a (m :: * -> *). (Show a, Monad m) => 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 :: forall (m :: * -> *). Monad m => 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
$c== :: Undefined -> Undefined -> Bool
== :: Undefined -> Undefined -> Bool
$c/= :: Undefined -> Undefined -> Bool
/= :: 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
$ccompare :: Undefined -> Undefined -> Ordering
compare :: Undefined -> Undefined -> Ordering
$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
>= :: Undefined -> Undefined -> Bool
$cmax :: Undefined -> Undefined -> Undefined
max :: Undefined -> Undefined -> Undefined
$cmin :: Undefined -> Undefined -> Undefined
min :: Undefined -> Undefined -> 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
$cshowsPrec :: Int -> Undefined -> ShowS
showsPrec :: Int -> Undefined -> ShowS
$cshow :: Undefined -> String
show :: Undefined -> String
$cshowList :: [Undefined] -> ShowS
showList :: [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
$creadsPrec :: Int -> ReadS Undefined
readsPrec :: Int -> ReadS Undefined
$creadList :: ReadS [Undefined]
readList :: ReadS [Undefined]
$creadPrec :: ReadPrec Undefined
readPrec :: ReadPrec Undefined
$creadListPrec :: ReadPrec [Undefined]
readListPrec :: ReadPrec [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
$csucc :: Undefined -> Undefined
succ :: Undefined -> Undefined
$cpred :: Undefined -> Undefined
pred :: Undefined -> Undefined
$ctoEnum :: Int -> Undefined
toEnum :: Int -> Undefined
$cfromEnum :: Undefined -> Int
fromEnum :: Undefined -> Int
$cenumFrom :: Undefined -> [Undefined]
enumFrom :: Undefined -> [Undefined]
$cenumFromThen :: Undefined -> Undefined -> [Undefined]
enumFromThen :: Undefined -> Undefined -> [Undefined]
$cenumFromTo :: Undefined -> Undefined -> [Undefined]
enumFromTo :: Undefined -> Undefined -> [Undefined]
$cenumFromThenTo :: Undefined -> Undefined -> Undefined -> [Undefined]
enumFromThenTo :: Undefined -> Undefined -> Undefined -> [Undefined]
P.Enum, Undefined
Undefined -> Undefined -> Bounded Undefined
forall a. a -> a -> Bounded a
$cminBound :: Undefined
minBound :: Undefined
$cmaxBound :: Undefined
maxBound :: Undefined
P.Bounded, Typeable Undefined
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 -> Constr
Undefined -> DataType
(forall b. Data b => b -> b) -> Undefined -> 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)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Undefined -> c Undefined
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Undefined -> c Undefined
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Undefined
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Undefined
$ctoConstr :: Undefined -> Constr
toConstr :: Undefined -> Constr
$cdataTypeOf :: Undefined -> DataType
dataTypeOf :: Undefined -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Undefined)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Undefined)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Undefined)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Undefined)
$cgmapT :: (forall b. Data b => b -> b) -> Undefined -> Undefined
gmapT :: (forall b. Data b => b -> b) -> Undefined -> Undefined
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
gmapQl :: forall r r'.
(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
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Undefined -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Undefined -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Undefined -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Undefined -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Undefined -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Undefined -> m Undefined
gmapM :: forall (m :: * -> *).
Monad m =>
(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
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(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
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Undefined -> m 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
$cfrom :: forall x. Undefined -> Rep Undefined x
from :: forall x. Undefined -> Rep Undefined x
$cto :: forall x. Rep Undefined x -> Undefined
to :: forall x. Rep Undefined x -> Undefined
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 :: forall a. HasCallStack => a
undefined = a
forall a. HasCallStack => a
P.undefined