{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_HADDOCK not-home #-}
module GHC.TypeLits.Printf.Internal (
ParseFmtStr,
ParseFmtStr_,
ParseFmt,
ParseFmt_,
FormatAdjustment (..),
ShowFormat,
FormatSign (..),
WidthMod (..),
Flags (..),
EmptyFlags,
FieldFormat (..),
Demote,
Reflect (..),
FormatType (..),
Printf (..),
FormatFun (..),
PFmt (..),
pfmt,
mkPFmt,
mkPFmt_,
PHelp (..),
) where
import Data.Int
import Data.Proxy
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Word
import GHC.OverloadedLabels
import GHC.TypeLits
import GHC.TypeLits.Printf.Internal.Unsatisfiable
import GHC.TypeLits.Printf.Parse
import qualified Text.Printf as P
class FormatType (t :: Char) a where
formatArg :: p t -> a -> P.FieldFormat -> ShowS
default formatArg :: P.PrintfArg a => p t -> a -> P.FieldFormat -> ShowS
formatArg p t
_ = a -> FieldFormat -> ShowS
forall a. PrintfArg a => a -> FieldFormat -> ShowS
P.formatArg
instance FormatType 'c' Char
instance FormatType 'c' Word8
instance FormatType 'c' Word16
instance FormatType 'd' Char
instance FormatType 'd' Int
instance FormatType 'd' Int8
instance FormatType 'd' Int16
instance FormatType 'd' Int32
instance FormatType 'd' Int64
instance FormatType 'd' Integer
instance FormatType 'd' Natural
instance FormatType 'd' Word
instance FormatType 'd' Word8
instance FormatType 'd' Word16
instance FormatType 'd' Word32
instance FormatType 'd' Word64
instance FormatType 'o' Char
instance FormatType 'o' Int
instance FormatType 'o' Int8
instance FormatType 'o' Int16
instance FormatType 'o' Int32
instance FormatType 'o' Int64
instance FormatType 'o' Integer
instance FormatType 'o' Natural
instance FormatType 'o' Word
instance FormatType 'o' Word8
instance FormatType 'o' Word16
instance FormatType 'o' Word32
instance FormatType 'o' Word64
instance FormatType 'x' Int
instance FormatType 'x' Int8
instance FormatType 'x' Int16
instance FormatType 'x' Int32
instance FormatType 'x' Int64
instance FormatType 'x' Integer
instance FormatType 'x' Natural
instance FormatType 'x' Word
instance FormatType 'x' Word8
instance FormatType 'x' Word16
instance FormatType 'x' Word32
instance FormatType 'x' Word64
instance FormatType 'X' Char
instance FormatType 'X' Int
instance FormatType 'X' Int8
instance FormatType 'X' Int16
instance FormatType 'X' Int32
instance FormatType 'X' Int64
instance FormatType 'X' Integer
instance FormatType 'X' Natural
instance FormatType 'X' Word
instance FormatType 'X' Word8
instance FormatType 'X' Word16
instance FormatType 'X' Word32
instance FormatType 'X' Word64
instance FormatType 'b' Char
instance FormatType 'b' Int
instance FormatType 'b' Int8
instance FormatType 'b' Int16
instance FormatType 'b' Int32
instance FormatType 'b' Int64
instance FormatType 'b' Integer
instance FormatType 'b' Natural
instance FormatType 'b' Word
instance FormatType 'b' Word8
instance FormatType 'b' Word16
instance FormatType 'b' Word32
instance FormatType 'b' Word64
instance FormatType 'u' Char
instance FormatType 'u' Int
instance FormatType 'u' Int8
instance FormatType 'u' Int16
instance FormatType 'u' Int32
instance FormatType 'u' Int64
instance FormatType 'u' Integer
instance FormatType 'u' Natural
instance FormatType 'u' Word
instance FormatType 'u' Word8
instance FormatType 'u' Word16
instance FormatType 'u' Word32
instance FormatType 'u' Word64
instance FormatType 'f' Double
instance FormatType 'f' Float
instance FormatType 'F' Double
instance FormatType 'F' Float
instance FormatType 'g' Double
instance FormatType 'g' Float
instance FormatType 'G' Double
instance FormatType 'G' Float
instance FormatType 'e' Double
instance FormatType 'e' Float
instance FormatType 'E' Double
instance FormatType 'E' Float
instance P.IsChar c => FormatType 's' [c]
instance FormatType 's' T.Text where
formatArg :: forall (p :: Char -> *). p 's' -> Text -> FieldFormat -> ShowS
formatArg p 's'
_ = String -> FieldFormat -> ShowS
forall a. PrintfArg a => a -> FieldFormat -> ShowS
P.formatArg (String -> FieldFormat -> ShowS)
-> (Text -> String) -> Text -> FieldFormat -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack
instance FormatType 's' TL.Text where
formatArg :: forall (p :: Char -> *). p 's' -> Text -> FieldFormat -> ShowS
formatArg p 's'
_ = String -> FieldFormat -> ShowS
forall a. PrintfArg a => a -> FieldFormat -> ShowS
P.formatArg (String -> FieldFormat -> ShowS)
-> (Text -> String) -> Text -> FieldFormat -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
TL.unpack
instance FormatType 'v' Char
instance FormatType 'v' Int
instance FormatType 'v' Int8
instance FormatType 'v' Int16
instance FormatType 'v' Int32
instance FormatType 'v' Int64
instance FormatType 'v' Integer
instance FormatType 'v' Natural
instance FormatType 'v' Word
instance FormatType 'v' Word8
instance FormatType 'v' Word16
instance FormatType 'v' Word32
instance FormatType 'v' Word64
instance FormatType 'v' Double
instance FormatType 'v' Float
instance FormatType 'v' String
instance FormatType 'v' T.Text where
formatArg :: forall (p :: Char -> *). p 'v' -> Text -> FieldFormat -> ShowS
formatArg p 'v'
_ = String -> FieldFormat -> ShowS
forall a. PrintfArg a => a -> FieldFormat -> ShowS
P.formatArg (String -> FieldFormat -> ShowS)
-> (Text -> String) -> Text -> FieldFormat -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack
instance FormatType 'v' TL.Text where
formatArg :: forall (p :: Char -> *). p 'v' -> Text -> FieldFormat -> ShowS
formatArg p 'v'
_ = String -> FieldFormat -> ShowS
forall a. PrintfArg a => a -> FieldFormat -> ShowS
P.formatArg (String -> FieldFormat -> ShowS)
-> (Text -> String) -> Text -> FieldFormat -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
TL.unpack
class FormatFun (ffs :: [Either Symbol FieldFormat]) fun where
formatFun :: p ffs -> String -> fun
newtype PHelp = PHelp
{ PHelp -> String
pHelp :: String
}
instance {-# INCOHERENT #-} a ~ String => FormatFun '[] a where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p '[] -> String -> a
formatFun p '[]
_ = String -> a
ShowS
forall a. a -> a
id
instance FormatFun '[] PHelp where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p '[] -> String -> PHelp
formatFun p '[]
_ = String -> PHelp
PHelp
instance FormatFun '[] T.Text where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p '[] -> String -> Text
formatFun p '[]
_ = String -> Text
T.pack
instance FormatFun '[] TL.Text where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p '[] -> String -> Text
formatFun p '[]
_ = String -> Text
TL.pack
instance a ~ () => FormatFun '[] (IO a) where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p '[] -> String -> IO a
formatFun p '[]
_ = String -> IO a
String -> IO ()
putStr
instance
Unsatisfiable
( 'Text "An extra argument of type "
':<>: 'ShowType a
':<>: 'Text " was given to a call to printf."
':$$: 'Text "Either remove the argument, or rewrite the format string to include the appropriate hole"
) =>
FormatFun '[] (a -> b)
where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p '[] -> String -> a -> b
formatFun = p '[] -> String -> a -> b
forall a. Bottom => a
forall a. a
unsatisfiable
instance (KnownSymbol str, FormatFun ffs fun) => FormatFun (Left str ': ffs) fun where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p ('Left str : ffs) -> String -> fun
formatFun p ('Left str : ffs)
_ String
str = Proxy ffs -> String -> fun
forall (ffs :: [Either Symbol FieldFormat]) fun
(p :: [Either Symbol FieldFormat] -> *).
FormatFun ffs fun =>
p ffs -> String -> fun
forall (p :: [Either Symbol FieldFormat] -> *).
p ffs -> String -> fun
formatFun (forall (t :: [Either Symbol FieldFormat]). Proxy t
forall {k} (t :: k). Proxy t
Proxy @ffs) (String
str String -> ShowS
forall a. [a] -> [a] -> [a]
++ Proxy str -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @str))
type family IsFunction fun where
IsFunction (_ -> _) = True
IsFunction _ = False
instance FormatFun' (IsFunction afun) ff ffs afun => FormatFun (Right ff ': ffs) afun where
formatFun :: forall (p :: [Either Symbol FieldFormat] -> *).
p ('Right ff : ffs) -> String -> afun
formatFun p ('Right ff : ffs)
_ = forall (is_function :: Bool) (ff :: FieldFormat)
(ffs :: [Either Symbol FieldFormat]) fun
(p :: (FieldFormat, [Either Symbol FieldFormat]) -> *).
FormatFun' is_function ff ffs fun =>
p '(ff, ffs) -> String -> fun
formatFun' @(IsFunction afun) (forall {k} (t :: k). Proxy t
forall (t :: (FieldFormat, [Either Symbol FieldFormat])). Proxy t
Proxy @'(ff, ffs))
class FormatFun' (is_function :: Bool) (ff :: FieldFormat) (ffs :: [Either Symbol FieldFormat]) fun where
formatFun' :: p '(ff, ffs) -> String -> fun
instance
{-# INCOHERENT #-}
(afun ~ (arg -> fun), Reflect ff, ff ~ 'FF f w p m c, FormatType c arg, FormatFun ffs fun) =>
FormatFun' is_function ff ffs afun
where
formatFun' :: forall (p :: (FieldFormat, [Either Symbol FieldFormat]) -> *).
p '(ff, ffs) -> String -> afun
formatFun' p '(ff, ffs)
_ String
str arg
x = Proxy ffs -> String -> fun
forall (ffs :: [Either Symbol FieldFormat]) fun
(p :: [Either Symbol FieldFormat] -> *).
FormatFun ffs fun =>
p ffs -> String -> fun
forall (p :: [Either Symbol FieldFormat] -> *).
p ffs -> String -> fun
formatFun (forall (t :: [Either Symbol FieldFormat]). Proxy t
forall {k} (t :: k). Proxy t
Proxy @ffs) (String
str String -> ShowS
forall a. [a] -> [a] -> [a]
++ Proxy c -> arg -> FieldFormat -> ShowS
forall (t :: Char) a (p :: Char -> *).
FormatType t a =>
p t -> a -> FieldFormat -> ShowS
forall (p :: Char -> *). p c -> arg -> FieldFormat -> ShowS
formatArg (forall (t :: Char). Proxy t
forall {k} (t :: k). Proxy t
Proxy @c) arg
x FieldFormat
Demote FieldFormat
ff String
"")
where
ff :: Demote FieldFormat
ff = Proxy ff -> Demote FieldFormat
forall a (x :: a) (p :: a -> *). Reflect x => p x -> Demote a
forall (p :: FieldFormat -> *). p ff -> Demote FieldFormat
reflect (forall {k} (t :: k). Proxy t
forall (t :: FieldFormat). Proxy t
Proxy @ff)
instance Unsatisfiable (MissingError ff) => FormatFun' False ff ffs notafun where
formatFun' :: forall (p :: (FieldFormat, [Either Symbol FieldFormat]) -> *).
p '(ff, ffs) -> String -> notafun
formatFun' = p '(ff, ffs) -> String -> notafun
forall a. Bottom => a
forall a. a
unsatisfiable
type family MissingError ff where
MissingError ff =
'Text "Call to printf missing an argument fulfilling \"%"
':<>: 'Text (ShowFormat ff)
':<>: 'Text "\""
':$$: 'Text "Either provide an argument or rewrite the format string to not expect one."
class Printf (str :: Symbol) fun where
printf_ :: p str -> fun
instance (ffs ~ ParseFmtStr_ str, FormatFun ffs fun) => Printf str fun where
printf_ :: forall (p :: Symbol -> *). p str -> fun
printf_ p str
_ = Proxy ffs -> String -> fun
forall (ffs :: [Either Symbol FieldFormat]) fun
(p :: [Either Symbol FieldFormat] -> *).
FormatFun ffs fun =>
p ffs -> String -> fun
forall (p :: [Either Symbol FieldFormat] -> *).
p ffs -> String -> fun
formatFun (forall (t :: [Either Symbol FieldFormat]). Proxy t
forall {k} (t :: k). Proxy t
Proxy @ffs) String
""
newtype PFmt c = PFmt P.FieldFormat
mkPFmt_ ::
forall str ff f w q m c p.
(ff ~ ParseFmt_ str, Reflect ff, ff ~ 'FF f w q m c) =>
p str ->
PFmt c
mkPFmt_ :: forall (str :: Symbol) (ff :: FieldFormat) (f :: Flags)
(w :: Maybe Natural) (q :: Maybe Natural) (m :: Maybe WidthMod)
(c :: Char) (p :: Symbol -> *).
(ff ~ ParseFmt_ str, Reflect ff, ff ~ 'FF f w q m c) =>
p str -> PFmt c
mkPFmt_ p str
_ = FieldFormat -> PFmt c
forall {k} (c :: k). FieldFormat -> PFmt c
PFmt FieldFormat
Demote FieldFormat
ff
where
ff :: Demote FieldFormat
ff = Proxy ff -> Demote FieldFormat
forall a (x :: a) (p :: a -> *). Reflect x => p x -> Demote a
forall (p :: FieldFormat -> *). p ff -> Demote FieldFormat
reflect (forall {k} (t :: k). Proxy t
forall (t :: FieldFormat). Proxy t
Proxy @ff)
mkPFmt ::
forall str ff f w q m c.
(ff ~ ParseFmt_ str, Reflect ff, ff ~ 'FF f w q m c) =>
PFmt c
mkPFmt :: forall (str :: Symbol) (ff :: FieldFormat) (f :: Flags)
(w :: Maybe Natural) (q :: Maybe Natural) (m :: Maybe WidthMod)
(c :: Char).
(ff ~ ParseFmt_ str, Reflect ff, ff ~ 'FF f w q m c) =>
PFmt c
mkPFmt = forall (str :: Symbol) (ff :: FieldFormat) (f :: Flags)
(w :: Maybe Natural) (q :: Maybe Natural) (m :: Maybe WidthMod)
(c :: Char) (p :: Symbol -> *).
(ff ~ ParseFmt_ str, Reflect ff, ff ~ 'FF f w q m c) =>
p str -> PFmt c
mkPFmt_ @str (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @str)
instance (ff ~ ParseFmt_ str, Reflect ff, ff ~ 'FF f w p m c) => IsLabel str (PFmt c) where
fromLabel :: PFmt c
fromLabel = forall (str :: Symbol) (ff :: FieldFormat) (f :: Flags)
(w :: Maybe Natural) (q :: Maybe Natural) (m :: Maybe WidthMod)
(c :: Char).
(ff ~ ParseFmt_ str, Reflect ff, ff ~ 'FF f w q m c) =>
PFmt c
mkPFmt @str
pfmt :: forall c a. FormatType c a => PFmt c -> a -> String
pfmt :: forall (c :: Char) a. FormatType c a => PFmt c -> a -> String
pfmt (PFmt FieldFormat
ff) a
x = Proxy c -> a -> FieldFormat -> ShowS
forall (t :: Char) a (p :: Char -> *).
FormatType t a =>
p t -> a -> FieldFormat -> ShowS
forall (p :: Char -> *). p c -> a -> FieldFormat -> ShowS
formatArg (forall (t :: Char). Proxy t
forall {k} (t :: k). Proxy t
Proxy @c) a
x FieldFormat
ff String
""