#if __GLASGOW_HASKELL__ >= 706
#endif
#if __GLASGOW_HASKELL__ >= 800
#endif
module TextShow.Generic (
genericShowt
, genericShowtl
, genericShowtPrec
, genericShowtlPrec
, genericShowtList
, genericShowtlList
, genericShowb
, genericShowbPrec
, genericShowbList
, genericPrintT
, genericPrintTL
, genericHPrintT
, genericHPrintTL
, genericLiftShowbPrec
, genericShowbPrec1
, GTextShowB(..)
, GTextShowConB(..)
, ShowFunsB(..)
, GTextShowT(..)
, GTextShowConT(..)
, ShowFunsT(..)
, GTextShowTL(..)
, GTextShowConTL(..)
, ShowFunsTL(..)
, IsNullary(..)
, ConType(..)
, Zero
, One
) where
import Data.Data (Data, Typeable)
import Data.Functor.Contravariant (Contravariant(..))
import Data.Monoid.Compat ((<>))
import qualified Data.Text as TS (Text, pack, singleton)
import qualified Data.Text.IO as TS (putStrLn, hPutStrLn)
import qualified Data.Text.Lazy as TL (Text, pack, singleton)
import qualified Data.Text.Lazy.IO as TL (putStrLn, hPutStrLn)
import qualified Data.Text.Lazy.Builder as TB (fromString, singleton)
import Data.Text.Lazy.Builder (Builder)
import Generics.Deriving.Base
import GHC.Exts (Char(C#), Double(D#), Float(F#), Int(I#), Word(W#))
import GHC.Show (appPrec, appPrec1)
import Language.Haskell.TH.Lift
import Prelude ()
import Prelude.Compat
import System.IO (Handle)
import TextShow.Classes (TextShow(..), TextShow1(..),
showbListWith, showbParen, showbSpace,
showtListWith, showtParen, showtSpace,
showtlListWith, showtlParen, showtlSpace,
liftShowtPrec, liftShowtlPrec)
import TextShow.Instances ()
import TextShow.TH.Internal (deriveTextShow)
import TextShow.Utils (isInfixDataCon, isSymVar, isTupleString)
genericShowt :: (Generic a, GTextShowT Zero (Rep a)) => a -> TS.Text
genericShowt = genericShowtPrec 0
genericShowtl :: (Generic a, GTextShowTL Zero (Rep a)) => a -> TL.Text
genericShowtl = genericShowtlPrec 0
genericShowtPrec :: (Generic a, GTextShowT Zero (Rep a)) => Int -> a -> TS.Text
genericShowtPrec p = gShowtPrec NoShowFunsT p . from
genericShowtlPrec :: (Generic a, GTextShowTL Zero (Rep a)) => Int -> a -> TL.Text
genericShowtlPrec p = gShowtlPrec NoShowFunsTL p . from
genericShowtList :: (Generic a, GTextShowT Zero (Rep a)) => [a] -> TS.Text
genericShowtList = showtListWith genericShowt
genericShowtlList :: (Generic a, GTextShowTL Zero (Rep a)) => [a] -> TL.Text
genericShowtlList = showtlListWith genericShowtl
genericShowb :: (Generic a, GTextShowB Zero (Rep a)) => a -> Builder
genericShowb = genericShowbPrec 0
genericShowbPrec :: (Generic a, GTextShowB Zero (Rep a)) => Int -> a -> Builder
genericShowbPrec p = gShowbPrec NoShowFunsB p . from
genericShowbList :: (Generic a, GTextShowB Zero (Rep a)) => [a] -> Builder
genericShowbList = showbListWith genericShowb
genericPrintT :: (Generic a, GTextShowT Zero (Rep a)) => a -> IO ()
genericPrintT = TS.putStrLn . genericShowt
genericPrintTL :: (Generic a, GTextShowTL Zero (Rep a)) => a -> IO ()
genericPrintTL = TL.putStrLn . genericShowtl
genericHPrintT :: (Generic a, GTextShowT Zero (Rep a)) => Handle -> a -> IO ()
genericHPrintT h = TS.hPutStrLn h . genericShowt
genericHPrintTL :: (Generic a, GTextShowTL Zero (Rep a)) => Handle -> a -> IO ()
genericHPrintTL h = TL.hPutStrLn h . genericShowtl
genericLiftShowbPrec :: (Generic1 f, GTextShowB One (Rep1 f))
=> (Int -> a -> Builder) -> ([a] -> Builder)
-> Int -> f a -> Builder
genericLiftShowbPrec sp sl p = gShowbPrec (Show1FunsB sp sl) p . from1
genericShowbPrec1 :: ( Generic a, Generic1 f
, GTextShowB Zero (Rep a)
, GTextShowB One (Rep1 f)
)
=> Int -> f a -> Builder
genericShowbPrec1 = genericLiftShowbPrec genericShowbPrec genericShowbList
data ConType = Rec | Tup | Pref | Inf String
deriving ( Data
, Eq
, Generic
, Ord
, Read
, Show
, Typeable
#if __GLASGOW_HASKELL__ >= 800
, Lift
#endif
)
data Zero
data One
#if __GLASGOW_HASKELL__ >= 708
#define DERIVE_TYPEABLE(name) deriving instance Typeable name
#else
#define DERIVE_TYPEABLE(name)
#endif
#if __GLASGOW_HASKELL__ >= 711
#define HASH_FUNS(text_type,one_hash,two_hash,hash_prec,from_char,from_string) \
one_hash, two_hash :: text_type; \
hash_prec :: Int -> Int; \
one_hash = from_char '#'; \
two_hash = from_string "##"; \
hash_prec = const 0
#else
#define HASH_FUNS(text_type,one_hash,two_hash,hash_prec,from_char,from_string) \
one_hash, two_hash :: text_type; \
hash_prec :: Int -> Int; \
one_hash = mempty; \
two_hash = mempty; \
hash_prec = id
#endif
#define GTEXT_SHOW(text_type,show_funs,no_show_funs,show1_funs,one_hash,two_hash,hash_prec,gtext_show,gshow_prec,gtext_show_con,gshow_prec_con,show_prec,lift_show_prec,show_space,show_paren,show_list_with,from_char,from_string) \
; \
data show_funs arity a where { \
no_show_funs :: show_funs Zero a \
; show1_funs :: (Int -> a -> text_type) -> ([a] -> text_type) -> show_funs One a \
} deriving Typeable; \
\
instance Contravariant (show_funs arity) where { \
contramap _ no_show_funs = no_show_funs \
; contramap f (show1_funs sp sl) = show1_funs (\p -> sp p . f) (sl . map f) \
}; \
\
; \
class gtext_show arity f where { \
\
; gshow_prec :: show_funs arity a -> Int -> f a -> text_type \
}; \
\
DERIVE_TYPEABLE(gtext_show); \
\
instance gtext_show arity f => gtext_show arity (D1 d f) where { \
gshow_prec sfs p (M1 x) = gshow_prec sfs p x \
}; \
\
instance gtext_show Zero V1 where { \
gshow_prec _ _ !_ = error "Void show_prec" \
}; \
\
instance gtext_show One V1 where { \
gshow_prec _ _ !_ = error "Void lift_show_prec" \
}; \
\
instance (gtext_show arity f, gtext_show arity g) => gtext_show arity (f :+: g) where { \
gshow_prec sfs p (L1 x) = gshow_prec sfs p x \
; gshow_prec sfs p (R1 x) = gshow_prec sfs p x \
}; \
\
instance (Constructor c, gtext_show_con arity f, IsNullary f) \
=> gtext_show arity (C1 c f) where { \
gshow_prec sfs p c@(M1 x) = case fixity of { \
Prefix -> show_paren ( p > appPrec \
&& not (isNullary x || conIsTuple c) \
) $ \
(if conIsTuple c \
then mempty \
else let cn = conName c \
in show_paren (isInfixDataCon cn) $ from_string cn) \
<> (if isNullary x || conIsTuple c \
then mempty \
else from_char ' ') \
<> showbBraces t (gshow_prec_con t sfs appPrec1 x) \
; Infix _ m -> show_paren (p > m) $ gshow_prec_con t sfs (m+1) x \
} \
where { \
fixity :: Fixity \
; fixity = conFixity c \
\
; t :: ConType \
; t = if conIsRecord c \
then Rec \
else case conIsTuple c of { \
True -> Tup \
; False -> case fixity of { \
Prefix -> Pref \
; Infix _ _ -> Inf $ conName c \
}; \
} \
\
; showbBraces :: ConType -> text_type -> text_type \
; showbBraces Rec b = from_char '{' <> b <> from_char '}' \
; showbBraces Tup b = from_char '(' <> b <> from_char ')' \
; showbBraces Pref b = b \
; showbBraces (Inf _) b = b \
\
; conIsTuple :: C1 c f p -> Bool \
; conIsTuple = isTupleString . conName \
}; \
}; \
\
; \
class gtext_show_con arity f where { \
\
; gshow_prec_con :: ConType -> show_funs arity a -> Int -> f a -> text_type \
}; \
\
DERIVE_TYPEABLE(gtext_show_con); \
\
instance gtext_show_con arity U1 where { \
gshow_prec_con _ _ _ U1 = mempty \
}; \
\
instance gtext_show_con One Par1 where { \
gshow_prec_con _ (show1_funs sp _) p (Par1 x) = sp p x \
}; \
\
instance TextShow c => gtext_show_con arity (K1 i c) where { \
gshow_prec_con _ _ p (K1 x) = show_prec p x \
}; \
\
instance TextShow1 f => gtext_show_con One (Rec1 f) where { \
gshow_prec_con _ (show1_funs sp sl) p (Rec1 x) = lift_show_prec sp sl p x \
}; \
\
instance (Selector s, gtext_show_con arity f) => gtext_show_con arity (S1 s f) where { \
gshow_prec_con t sfs p sel@(M1 x) \
| selName sel == "" = gshow_prec_con t sfs p x \
| otherwise = infixRec \
<> " = " \
<> gshow_prec_con t sfs 0 x \
where { \
infixRec :: text_type \
; infixRec | isSymVar selectorName \
= from_char '(' <> from_string selectorName <> from_char ')' \
| otherwise \
= from_string selectorName \
\
; selectorName :: String \
; selectorName = selName sel \
} \
}; \
\
instance (gtext_show_con arity f, gtext_show_con arity g) \
=> gtext_show_con arity (f :*: g) where { \
gshow_prec_con t@Rec sfs _ (a :*: b) = \
gshow_prec_con t sfs 0 a \
<> ", " \
<> gshow_prec_con t sfs 0 b \
; gshow_prec_con t@(Inf o) sfs p (a :*: b) = \
gshow_prec_con t sfs p a \
<> show_space \
<> infixOp \
<> show_space \
<> gshow_prec_con t sfs p b \
where { \
infixOp :: text_type \
; infixOp = if isInfixDataCon o \
then from_string o \
else from_char '`' <> from_string o <> from_char '`' \
} \
; gshow_prec_con t@Tup sfs _ (a :*: b) = \
gshow_prec_con t sfs 0 a \
<> from_char ',' \
<> gshow_prec_con t sfs 0 b \
; gshow_prec_con t@Pref sfs p (a :*: b) = \
gshow_prec_con t sfs p a \
<> show_space \
<> gshow_prec_con t sfs p b \
}; \
\
instance (TextShow1 f, gtext_show_con One g) => gtext_show_con One (f :.: g) where { \
gshow_prec_con t sfs p (Comp1 x) = \
let gspc = gshow_prec_con t sfs \
in lift_show_prec gspc (show_list_with (gspc 0)) p x \
}; \
\
instance gtext_show_con arity UChar where { \
gshow_prec_con _ _ p (UChar c) = show_prec (hash_prec p) (C# c) <> one_hash \
}; \
\
instance gtext_show_con arity UDouble where { \
gshow_prec_con _ _ p (UDouble d) = show_prec (hash_prec p) (D# d) <> two_hash \
}; \
\
instance gtext_show_con arity UFloat where { \
gshow_prec_con _ _ p (UFloat f) = show_prec (hash_prec p) (F# f) <> one_hash \
}; \
\
instance gtext_show_con arity UInt where { \
gshow_prec_con _ _ p (UInt i) = show_prec (hash_prec p) (I# i) <> one_hash \
}; \
\
instance gtext_show_con arity UWord where { \
gshow_prec_con _ _ p (UWord w) = show_prec (hash_prec p) (W# w) <> two_hash \
}; \
\
HASH_FUNS(text_type,one_hash,two_hash,hash_prec,from_char,from_string);
GTEXT_SHOW(Builder,ShowFunsB,NoShowFunsB,Show1FunsB,oneHashB,twoHashB,hashPrecB,GTextShowB,gShowbPrec,GTextShowConB,gShowbPrecCon,showbPrec,liftShowbPrec,showbSpace,showbParen,showbListWith,TB.singleton,TB.fromString)
GTEXT_SHOW(TS.Text,ShowFunsT,NoShowFunsT,Show1FunsT,oneHashT,twoHashT,hashPrecT,GTextShowT,gShowtPrec,GTextShowConT,gShowtPrecCon,showtPrec,liftShowtPrec,showtSpace,showtParen,showtListWith,TS.singleton,TS.pack)
GTEXT_SHOW(TL.Text,ShowFunsTL,NoShowFunsTL,Show1FunsTL,oneHashTL,twoHashTL,hashPrecTL,GTextShowTL,gShowtlPrec,GTextShowConTL,gShowtlPrecCon,showtlPrec,liftShowtlPrec,showtlSpace,showtlParen,showtlListWith,TL.singleton,TL.pack)
class IsNullary f where
isNullary :: f a -> Bool
instance IsNullary U1 where
isNullary _ = True
instance IsNullary Par1 where
isNullary _ = False
instance IsNullary (K1 i c) where
isNullary _ = False
instance IsNullary f => IsNullary (S1 s f) where
isNullary (M1 x) = isNullary x
instance IsNullary (Rec1 f) where
isNullary _ = False
instance IsNullary (f :*: g) where
isNullary _ = False
instance IsNullary (f :.: g) where
isNullary _ = False
instance IsNullary UChar where
isNullary _ = False
instance IsNullary UDouble where
isNullary _ = False
instance IsNullary UFloat where
isNullary _ = False
instance IsNullary UInt where
isNullary _ = False
instance IsNullary UWord where
isNullary _ = False
$(deriveTextShow ''ConType)
#if __GLASGOW_HASKELL__ < 800
$(deriveLift ''ConType)
#endif