module GHC.Utils.Outputable (
Outputable(..), OutputableBndr(..),
SDoc, runSDoc, initSDocContext,
docToSDoc,
interppSP, interpp'SP,
pprQuotedList, pprWithCommas, quotedListWithOr, quotedListWithNor,
pprWithBars,
empty, isEmpty, nest,
char,
text, ftext, ptext, ztext,
int, intWithCommas, integer, word, float, double, rational, doublePrec,
parens, cparen, brackets, braces, quotes, quote,
doubleQuotes, angleBrackets,
semi, comma, colon, dcolon, space, equals, dot, vbar,
arrow, lollipop, larrow, darrow, arrowt, larrowt, arrowtt, larrowtt,
lparen, rparen, lbrack, rbrack, lbrace, rbrace, underscore, mulArrow,
blankLine, forAllLit, bullet,
(<>), (<+>), hcat, hsep,
($$), ($+$), vcat,
sep, cat,
fsep, fcat,
hang, hangNotEmpty, punctuate, ppWhen, ppUnless,
ppWhenOption, ppUnlessOption,
speakNth, speakN, speakNOf, plural, isOrAre, doOrDoes, itsOrTheir,
unicodeSyntax,
coloured, keyword,
printSDoc, printSDocLn, printForUser,
printForC, bufLeftRenderSDoc,
pprCode, mkCodeStyle,
showSDoc, showSDocUnsafe, showSDocOneLine,
showSDocForUser, showSDocDebug, showSDocDump, showSDocDumpOneLine,
showSDocUnqual, showPpr,
renderWithStyle,
pprInfixVar, pprPrefixVar,
pprHsChar, pprHsString, pprHsBytes,
primFloatSuffix, primCharSuffix, primWordSuffix, primDoubleSuffix,
primInt64Suffix, primWord64Suffix, primIntSuffix,
pprPrimChar, pprPrimInt, pprPrimWord, pprPrimInt64, pprPrimWord64,
pprFastFilePath, pprFilePathString,
BindingSite(..),
PprStyle(..), CodeStyle(..), PrintUnqualified(..),
QueryQualifyName, QueryQualifyModule, QueryQualifyPackage,
reallyAlwaysQualify, reallyAlwaysQualifyNames,
alwaysQualify, alwaysQualifyNames, alwaysQualifyModules,
neverQualify, neverQualifyNames, neverQualifyModules,
alwaysQualifyPackages, neverQualifyPackages,
QualifyName(..), queryQual,
sdocWithDynFlags, sdocOption,
updSDocContext,
SDocContext (..), sdocWithContext,
getPprStyle, withPprStyle, setStyleColoured,
pprDeeper, pprDeeperList, pprSetDepth,
codeStyle, userStyle, dumpStyle, asmStyle,
qualName, qualModule, qualPackage,
mkErrStyle, defaultErrStyle, defaultDumpStyle, mkDumpStyle, defaultUserStyle,
mkUserStyle, cmdlineParserStyle, Depth(..),
withUserStyle, withErrStyle,
ifPprDebug, whenPprDebug, getPprDebug,
pprPanic, pprSorry, assertPprPanic, pprPgmError,
pprTrace, pprTraceDebug, pprTraceWith, pprTraceIt, warnPprTrace,
pprSTrace, pprTraceException, pprTraceM, pprTraceWithFlags,
trace, pgmError, panic, sorry, assertPanic,
pprDebugAndThen, callStackDoc,
) where
import GHC.Prelude
import GHC.Driver.Session
( DynFlags, hasPprDebug, hasNoDebugOutput
, unsafeGlobalDynFlags, initSDocContext
)
import GHC.Unit.Types ( Unit, Module, moduleName )
import GHC.Unit.Module.Name( ModuleName )
import GHC.Types.Name.Occurrence( OccName )
import GHC.Utils.BufHandle (BufHandle)
import GHC.Data.FastString
import qualified GHC.Utils.Ppr as Pretty
import GHC.Utils.Misc
import qualified GHC.Utils.Ppr.Colour as Col
import GHC.Utils.Ppr ( Doc, Mode(..) )
import GHC.Utils.Panic
import GHC.Serialized
import GHC.LanguageExtensions (Extension)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Data.Char
import qualified Data.Map as M
import Data.Int
import qualified Data.IntMap as IM
import Data.Set (Set)
import qualified Data.Set as Set
import Data.String
import Data.Word
import System.IO ( Handle )
import System.FilePath
import Text.Printf
import Numeric (showFFloat)
import Data.Graph (SCC(..))
import Data.List (intersperse)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NEL
import GHC.Fingerprint
import GHC.Show ( showMultiLineString )
import GHC.Stack ( callStack, prettyCallStack )
import Control.Monad.IO.Class
import GHC.Utils.Exception
data PprStyle
= PprUser PrintUnqualified Depth Coloured
| PprDump PrintUnqualified
| PprCode CodeStyle
data CodeStyle = CStyle
| AsmStyle
data Depth
= AllTheWay
| PartWay Int
| DefaultDepth
data Coloured
= Uncoloured
| Coloured
data PrintUnqualified = QueryQualify {
queryQualifyName :: QueryQualifyName,
queryQualifyModule :: QueryQualifyModule,
queryQualifyPackage :: QueryQualifyPackage
}
type QueryQualifyName = Module -> OccName -> QualifyName
type QueryQualifyModule = Module -> Bool
type QueryQualifyPackage = Unit -> Bool
data QualifyName
= NameUnqual
| NameQual ModuleName
| NameNotInScope1
| NameNotInScope2
instance Outputable QualifyName where
ppr NameUnqual = text "NameUnqual"
ppr (NameQual _mod) = text "NameQual"
ppr NameNotInScope1 = text "NameNotInScope1"
ppr NameNotInScope2 = text "NameNotInScope2"
reallyAlwaysQualifyNames :: QueryQualifyName
reallyAlwaysQualifyNames _ _ = NameNotInScope2
alwaysQualifyNames :: QueryQualifyName
alwaysQualifyNames m _ = NameQual (moduleName m)
neverQualifyNames :: QueryQualifyName
neverQualifyNames _ _ = NameUnqual
alwaysQualifyModules :: QueryQualifyModule
alwaysQualifyModules _ = True
neverQualifyModules :: QueryQualifyModule
neverQualifyModules _ = False
alwaysQualifyPackages :: QueryQualifyPackage
alwaysQualifyPackages _ = True
neverQualifyPackages :: QueryQualifyPackage
neverQualifyPackages _ = False
reallyAlwaysQualify, alwaysQualify, neverQualify :: PrintUnqualified
reallyAlwaysQualify
= QueryQualify reallyAlwaysQualifyNames
alwaysQualifyModules
alwaysQualifyPackages
alwaysQualify = QueryQualify alwaysQualifyNames
alwaysQualifyModules
alwaysQualifyPackages
neverQualify = QueryQualify neverQualifyNames
neverQualifyModules
neverQualifyPackages
defaultUserStyle :: PprStyle
defaultUserStyle = mkUserStyle neverQualify AllTheWay
defaultDumpStyle :: PprStyle
defaultDumpStyle = PprDump neverQualify
mkDumpStyle :: PrintUnqualified -> PprStyle
mkDumpStyle print_unqual = PprDump print_unqual
defaultErrStyle :: PprStyle
defaultErrStyle = mkErrStyle neverQualify
mkErrStyle :: PrintUnqualified -> PprStyle
mkErrStyle unqual = mkUserStyle unqual DefaultDepth
cmdlineParserStyle :: PprStyle
cmdlineParserStyle = mkUserStyle alwaysQualify AllTheWay
mkUserStyle :: PrintUnqualified -> Depth -> PprStyle
mkUserStyle unqual depth = PprUser unqual depth Uncoloured
withUserStyle :: PrintUnqualified -> Depth -> SDoc -> SDoc
withUserStyle unqual depth doc = withPprStyle (PprUser unqual depth Uncoloured) doc
withErrStyle :: PrintUnqualified -> SDoc -> SDoc
withErrStyle unqual doc =
withPprStyle (mkErrStyle unqual) doc
setStyleColoured :: Bool -> PprStyle -> PprStyle
setStyleColoured col style =
case style of
PprUser q d _ -> PprUser q d c
_ -> style
where
c | col = Coloured
| otherwise = Uncoloured
instance Outputable PprStyle where
ppr (PprUser {}) = text "user-style"
ppr (PprCode {}) = text "code-style"
ppr (PprDump {}) = text "dump-style"
newtype SDoc = SDoc { runSDoc :: SDocContext -> Doc }
data SDocContext = SDC
{ sdocStyle :: !PprStyle
, sdocColScheme :: !Col.Scheme
, sdocLastColour :: !Col.PprColour
, sdocShouldUseColor :: !Bool
, sdocDefaultDepth :: !Int
, sdocLineLength :: !Int
, sdocCanUseUnicode :: !Bool
, sdocHexWordLiterals :: !Bool
, sdocPprDebug :: !Bool
, sdocPrintUnicodeSyntax :: !Bool
, sdocPrintCaseAsLet :: !Bool
, sdocPrintTypecheckerElaboration :: !Bool
, sdocPrintAxiomIncomps :: !Bool
, sdocPrintExplicitKinds :: !Bool
, sdocPrintExplicitCoercions :: !Bool
, sdocPrintExplicitRuntimeReps :: !Bool
, sdocPrintExplicitForalls :: !Bool
, sdocPrintPotentialInstances :: !Bool
, sdocPrintEqualityRelations :: !Bool
, sdocSuppressTicks :: !Bool
, sdocSuppressTypeSignatures :: !Bool
, sdocSuppressTypeApplications :: !Bool
, sdocSuppressIdInfo :: !Bool
, sdocSuppressCoercions :: !Bool
, sdocSuppressUnfoldings :: !Bool
, sdocSuppressVarKinds :: !Bool
, sdocSuppressUniques :: !Bool
, sdocSuppressModulePrefixes :: !Bool
, sdocSuppressStgExts :: !Bool
, sdocErrorSpans :: !Bool
, sdocStarIsType :: !Bool
, sdocLinearTypes :: !Bool
, sdocImpredicativeTypes :: !Bool
, sdocPrintTypeAbbreviations :: !Bool
, sdocDynFlags :: DynFlags
}
instance IsString SDoc where
fromString = text
instance Outputable SDoc where
ppr = id
withPprStyle :: PprStyle -> SDoc -> SDoc
withPprStyle sty d = SDoc $ \ctxt -> runSDoc d ctxt{sdocStyle=sty}
pprDeeper :: SDoc -> SDoc
pprDeeper d = SDoc $ \ctx -> case sdocStyle ctx of
PprUser q depth c ->
let deeper 0 = Pretty.text "..."
deeper n = runSDoc d ctx{sdocStyle = PprUser q (PartWay (n1)) c}
in case depth of
DefaultDepth -> deeper (sdocDefaultDepth ctx)
PartWay n -> deeper n
AllTheWay -> runSDoc d ctx
_ -> runSDoc d ctx
pprDeeperList :: ([SDoc] -> SDoc) -> [SDoc] -> SDoc
pprDeeperList f ds
| null ds = f []
| otherwise = SDoc work
where
work ctx@SDC{sdocStyle=PprUser q depth c}
| DefaultDepth <- depth
= work (ctx { sdocStyle = PprUser q (PartWay (sdocDefaultDepth ctx)) c })
| PartWay 0 <- depth
= Pretty.text "..."
| PartWay n <- depth
= let
go _ [] = []
go i (d:ds) | i >= n = [text "...."]
| otherwise = d : go (i+1) ds
in runSDoc (f (go 0 ds)) ctx{sdocStyle = PprUser q (PartWay (n1)) c}
work other_ctx = runSDoc (f ds) other_ctx
pprSetDepth :: Depth -> SDoc -> SDoc
pprSetDepth depth doc = SDoc $ \ctx ->
case ctx of
SDC{sdocStyle=PprUser q _ c} ->
runSDoc doc ctx{sdocStyle = PprUser q depth c}
_ ->
runSDoc doc ctx
getPprStyle :: (PprStyle -> SDoc) -> SDoc
getPprStyle df = SDoc $ \ctx -> runSDoc (df (sdocStyle ctx)) ctx
sdocWithDynFlags :: (DynFlags -> SDoc) -> SDoc
sdocWithDynFlags f = SDoc $ \ctx -> runSDoc (f (sdocDynFlags ctx)) ctx
sdocWithContext :: (SDocContext -> SDoc) -> SDoc
sdocWithContext f = SDoc $ \ctx -> runSDoc (f ctx) ctx
sdocOption :: (SDocContext -> a) -> (a -> SDoc) -> SDoc
sdocOption f g = sdocWithContext (g . f)
updSDocContext :: (SDocContext -> SDocContext) -> SDoc -> SDoc
updSDocContext upd doc
= SDoc $ \ctx -> runSDoc doc (upd ctx)
qualName :: PprStyle -> QueryQualifyName
qualName (PprUser q _ _) mod occ = queryQualifyName q mod occ
qualName (PprDump q) mod occ = queryQualifyName q mod occ
qualName _other mod _ = NameQual (moduleName mod)
qualModule :: PprStyle -> QueryQualifyModule
qualModule (PprUser q _ _) m = queryQualifyModule q m
qualModule (PprDump q) m = queryQualifyModule q m
qualModule _other _m = True
qualPackage :: PprStyle -> QueryQualifyPackage
qualPackage (PprUser q _ _) m = queryQualifyPackage q m
qualPackage (PprDump q) m = queryQualifyPackage q m
qualPackage _other _m = True
queryQual :: PprStyle -> PrintUnqualified
queryQual s = QueryQualify (qualName s)
(qualModule s)
(qualPackage s)
codeStyle :: PprStyle -> Bool
codeStyle (PprCode _) = True
codeStyle _ = False
asmStyle :: PprStyle -> Bool
asmStyle (PprCode AsmStyle) = True
asmStyle _other = False
dumpStyle :: PprStyle -> Bool
dumpStyle (PprDump {}) = True
dumpStyle _other = False
userStyle :: PprStyle -> Bool
userStyle (PprUser {}) = True
userStyle _other = False
getPprDebug :: (Bool -> SDoc) -> SDoc
getPprDebug d = sdocWithContext $ \ctx -> d (sdocPprDebug ctx)
ifPprDebug :: SDoc -> SDoc -> SDoc
ifPprDebug yes no = getPprDebug $ \dbg -> if dbg then yes else no
whenPprDebug :: SDoc -> SDoc
whenPprDebug d = ifPprDebug d empty
printSDoc :: SDocContext -> Mode -> Handle -> SDoc -> IO ()
printSDoc ctx mode handle doc =
Pretty.printDoc_ mode cols handle (runSDoc doc ctx)
`finally`
Pretty.printDoc_ mode cols handle
(runSDoc (coloured Col.colReset empty) ctx)
where
cols = sdocLineLength ctx
printSDocLn :: SDocContext -> Mode -> Handle -> SDoc -> IO ()
printSDocLn ctx mode handle doc =
printSDoc ctx mode handle (doc $$ text "")
printForUser :: DynFlags -> Handle -> PrintUnqualified -> Depth -> SDoc -> IO ()
printForUser dflags handle unqual depth doc
= printSDocLn ctx PageMode handle doc
where ctx = initSDocContext dflags (mkUserStyle unqual depth)
printForC :: DynFlags -> Handle -> SDoc -> IO ()
printForC dflags handle doc =
printSDocLn ctx LeftMode handle doc
where ctx = initSDocContext dflags (PprCode CStyle)
bufLeftRenderSDoc :: SDocContext -> BufHandle -> SDoc -> IO ()
bufLeftRenderSDoc ctx bufHandle doc =
Pretty.bufLeftRender bufHandle (runSDoc doc ctx)
pprCode :: CodeStyle -> SDoc -> SDoc
pprCode cs d = withPprStyle (PprCode cs) d
mkCodeStyle :: CodeStyle -> PprStyle
mkCodeStyle = PprCode
showSDoc :: DynFlags -> SDoc -> String
showSDoc dflags sdoc = renderWithStyle (initSDocContext dflags defaultUserStyle) sdoc
showSDocUnsafe :: SDoc -> String
showSDocUnsafe sdoc = showSDoc unsafeGlobalDynFlags sdoc
showPpr :: Outputable a => DynFlags -> a -> String
showPpr dflags thing = showSDoc dflags (ppr thing)
showSDocUnqual :: DynFlags -> SDoc -> String
showSDocUnqual dflags sdoc = showSDoc dflags sdoc
showSDocForUser :: DynFlags -> PrintUnqualified -> SDoc -> String
showSDocForUser dflags unqual doc
= renderWithStyle (initSDocContext dflags (mkUserStyle unqual AllTheWay)) doc
showSDocDump :: DynFlags -> SDoc -> String
showSDocDump dflags d = renderWithStyle (initSDocContext dflags defaultDumpStyle) d
showSDocDebug :: DynFlags -> SDoc -> String
showSDocDebug dflags d = renderWithStyle ctx d
where
ctx = (initSDocContext dflags defaultDumpStyle)
{ sdocPprDebug = True
}
renderWithStyle :: SDocContext -> SDoc -> String
renderWithStyle ctx sdoc
= let s = Pretty.style{ Pretty.mode = PageMode,
Pretty.lineLength = sdocLineLength ctx }
in Pretty.renderStyle s $ runSDoc sdoc ctx
showSDocOneLine :: SDocContext -> SDoc -> String
showSDocOneLine ctx d
= let s = Pretty.style{ Pretty.mode = OneLineMode,
Pretty.lineLength = sdocLineLength ctx } in
Pretty.renderStyle s $
runSDoc d ctx
showSDocDumpOneLine :: DynFlags -> SDoc -> String
showSDocDumpOneLine dflags d
= let s = Pretty.style{ Pretty.mode = OneLineMode,
Pretty.lineLength = irrelevantNCols } in
Pretty.renderStyle s $
runSDoc d (initSDocContext dflags defaultDumpStyle)
irrelevantNCols :: Int
irrelevantNCols = 1
isEmpty :: SDocContext -> SDoc -> Bool
isEmpty ctx sdoc = Pretty.isEmpty $ runSDoc sdoc (ctx {sdocPprDebug = True})
docToSDoc :: Doc -> SDoc
docToSDoc d = SDoc (\_ -> d)
empty :: SDoc
char :: Char -> SDoc
text :: String -> SDoc
ftext :: FastString -> SDoc
ptext :: PtrString -> SDoc
ztext :: FastZString -> SDoc
int :: Int -> SDoc
integer :: Integer -> SDoc
word :: Integer -> SDoc
float :: Float -> SDoc
double :: Double -> SDoc
rational :: Rational -> SDoc
empty = docToSDoc $ Pretty.empty
char c = docToSDoc $ Pretty.char c
text s = docToSDoc $ Pretty.text s
ftext s = docToSDoc $ Pretty.ftext s
ptext s = docToSDoc $ Pretty.ptext s
ztext s = docToSDoc $ Pretty.ztext s
int n = docToSDoc $ Pretty.int n
integer n = docToSDoc $ Pretty.integer n
float n = docToSDoc $ Pretty.float n
double n = docToSDoc $ Pretty.double n
rational n = docToSDoc $ Pretty.rational n
word n = sdocOption sdocHexWordLiterals $ \case
True -> docToSDoc $ Pretty.hex n
False -> docToSDoc $ Pretty.integer n
doublePrec :: Int -> Double -> SDoc
doublePrec p n = text (showFFloat (Just p) n "")
parens, braces, brackets, quotes, quote,
doubleQuotes, angleBrackets :: SDoc -> SDoc
parens d = SDoc $ Pretty.parens . runSDoc d
braces d = SDoc $ Pretty.braces . runSDoc d
brackets d = SDoc $ Pretty.brackets . runSDoc d
quote d = SDoc $ Pretty.quote . runSDoc d
doubleQuotes d = SDoc $ Pretty.doubleQuotes . runSDoc d
angleBrackets d = char '<' <> d <> char '>'
cparen :: Bool -> SDoc -> SDoc
cparen b d = SDoc $ Pretty.maybeParens b . runSDoc d
quotes d = sdocOption sdocCanUseUnicode $ \case
True -> char '‘' <> d <> char '’'
False -> SDoc $ \sty ->
let pp_d = runSDoc d sty
str = show pp_d
in case (str, lastMaybe str) of
(_, Just '\'') -> pp_d
('\'' : _, _) -> pp_d
_other -> Pretty.quotes pp_d
semi, comma, colon, equals, space, dcolon, underscore, dot, vbar :: SDoc
arrow, lollipop, larrow, darrow, arrowt, larrowt, arrowtt, larrowtt :: SDoc
lparen, rparen, lbrack, rbrack, lbrace, rbrace, blankLine :: SDoc
blankLine = docToSDoc $ Pretty.text ""
dcolon = unicodeSyntax (char '∷') (docToSDoc $ Pretty.text "::")
arrow = unicodeSyntax (char '→') (docToSDoc $ Pretty.text "->")
lollipop = unicodeSyntax (char '⊸') (docToSDoc $ Pretty.text "#->")
larrow = unicodeSyntax (char '←') (docToSDoc $ Pretty.text "<-")
darrow = unicodeSyntax (char '⇒') (docToSDoc $ Pretty.text "=>")
arrowt = unicodeSyntax (char '⤚') (docToSDoc $ Pretty.text ">-")
larrowt = unicodeSyntax (char '⤙') (docToSDoc $ Pretty.text "-<")
arrowtt = unicodeSyntax (char '⤜') (docToSDoc $ Pretty.text ">>-")
larrowtt = unicodeSyntax (char '⤛') (docToSDoc $ Pretty.text "-<<")
semi = docToSDoc $ Pretty.semi
comma = docToSDoc $ Pretty.comma
colon = docToSDoc $ Pretty.colon
equals = docToSDoc $ Pretty.equals
space = docToSDoc $ Pretty.space
underscore = char '_'
dot = char '.'
vbar = char '|'
lparen = docToSDoc $ Pretty.lparen
rparen = docToSDoc $ Pretty.rparen
lbrack = docToSDoc $ Pretty.lbrack
rbrack = docToSDoc $ Pretty.rbrack
lbrace = docToSDoc $ Pretty.lbrace
rbrace = docToSDoc $ Pretty.rbrace
mulArrow :: SDoc -> SDoc
mulArrow d = text "#" <+> d <+> arrow
forAllLit :: SDoc
forAllLit = unicodeSyntax (char '∀') (text "forall")
bullet :: SDoc
bullet = unicode (char '•') (char '*')
unicodeSyntax :: SDoc -> SDoc -> SDoc
unicodeSyntax unicode plain =
sdocOption sdocCanUseUnicode $ \can_use_unicode ->
sdocOption sdocPrintUnicodeSyntax $ \print_unicode_syntax ->
if can_use_unicode && print_unicode_syntax
then unicode
else plain
unicode :: SDoc -> SDoc -> SDoc
unicode unicode plain = sdocOption sdocCanUseUnicode $ \case
True -> unicode
False -> plain
nest :: Int -> SDoc -> SDoc
(<>) :: SDoc -> SDoc -> SDoc
(<+>) :: SDoc -> SDoc -> SDoc
($$) :: SDoc -> SDoc -> SDoc
($+$) :: SDoc -> SDoc -> SDoc
nest n d = SDoc $ Pretty.nest n . runSDoc d
(<>) d1 d2 = SDoc $ \sty -> (Pretty.<>) (runSDoc d1 sty) (runSDoc d2 sty)
(<+>) d1 d2 = SDoc $ \sty -> (Pretty.<+>) (runSDoc d1 sty) (runSDoc d2 sty)
($$) d1 d2 = SDoc $ \sty -> (Pretty.$$) (runSDoc d1 sty) (runSDoc d2 sty)
($+$) d1 d2 = SDoc $ \sty -> (Pretty.$+$) (runSDoc d1 sty) (runSDoc d2 sty)
hcat :: [SDoc] -> SDoc
hsep :: [SDoc] -> SDoc
vcat :: [SDoc] -> SDoc
sep :: [SDoc] -> SDoc
cat :: [SDoc] -> SDoc
fsep :: [SDoc] -> SDoc
fcat :: [SDoc] -> SDoc
hcat ds = SDoc $ \sty -> Pretty.hcat [runSDoc d sty | d <- ds]
hsep ds = SDoc $ \sty -> Pretty.hsep [runSDoc d sty | d <- ds]
vcat ds = SDoc $ \sty -> Pretty.vcat [runSDoc d sty | d <- ds]
sep ds = SDoc $ \sty -> Pretty.sep [runSDoc d sty | d <- ds]
cat ds = SDoc $ \sty -> Pretty.cat [runSDoc d sty | d <- ds]
fsep ds = SDoc $ \sty -> Pretty.fsep [runSDoc d sty | d <- ds]
fcat ds = SDoc $ \sty -> Pretty.fcat [runSDoc d sty | d <- ds]
hang :: SDoc
-> Int
-> SDoc
-> SDoc
hang d1 n d2 = SDoc $ \sty -> Pretty.hang (runSDoc d1 sty) n (runSDoc d2 sty)
hangNotEmpty :: SDoc -> Int -> SDoc -> SDoc
hangNotEmpty d1 n d2 =
SDoc $ \sty -> Pretty.hangNotEmpty (runSDoc d1 sty) n (runSDoc d2 sty)
punctuate :: SDoc
-> [SDoc]
-> [SDoc]
punctuate _ [] = []
punctuate p (d:ds) = go d ds
where
go d [] = [d]
go d (e:es) = (d <> p) : go e es
ppWhen, ppUnless :: Bool -> SDoc -> SDoc
ppWhen True doc = doc
ppWhen False _ = empty
ppUnless True _ = empty
ppUnless False doc = doc
ppWhenOption :: (SDocContext -> Bool) -> SDoc -> SDoc
ppWhenOption f doc = sdocOption f $ \case
True -> doc
False -> empty
ppUnlessOption :: (SDocContext -> Bool) -> SDoc -> SDoc
ppUnlessOption f doc = sdocOption f $ \case
True -> empty
False -> doc
coloured :: Col.PprColour -> SDoc -> SDoc
coloured col sdoc = sdocOption sdocShouldUseColor $ \case
True -> SDoc $ \case
ctx@SDC{ sdocLastColour = lastCol, sdocStyle = PprUser _ _ Coloured } ->
let ctx' = ctx{ sdocLastColour = lastCol `mappend` col } in
Pretty.zeroWidthText (Col.renderColour col)
Pretty.<> runSDoc sdoc ctx'
Pretty.<> Pretty.zeroWidthText (Col.renderColourAfresh lastCol)
ctx -> runSDoc sdoc ctx
False -> sdoc
keyword :: SDoc -> SDoc
keyword = coloured Col.colBold
class Outputable a where
ppr :: a -> SDoc
pprPrec :: Rational -> a -> SDoc
ppr = pprPrec 0
pprPrec _ = ppr
instance Outputable Char where
ppr c = text [c]
instance Outputable Bool where
ppr True = text "True"
ppr False = text "False"
instance Outputable Ordering where
ppr LT = text "LT"
ppr EQ = text "EQ"
ppr GT = text "GT"
instance Outputable Int32 where
ppr n = integer $ fromIntegral n
instance Outputable Int64 where
ppr n = integer $ fromIntegral n
instance Outputable Int where
ppr n = int n
instance Outputable Integer where
ppr n = integer n
instance Outputable Word16 where
ppr n = integer $ fromIntegral n
instance Outputable Word32 where
ppr n = integer $ fromIntegral n
instance Outputable Word64 where
ppr n = integer $ fromIntegral n
instance Outputable Word where
ppr n = integer $ fromIntegral n
instance Outputable Float where
ppr f = float f
instance Outputable Double where
ppr f = double f
instance Outputable () where
ppr _ = text "()"
instance (Outputable a) => Outputable [a] where
ppr xs = brackets (fsep (punctuate comma (map ppr xs)))
instance (Outputable a) => Outputable (NonEmpty a) where
ppr = ppr . NEL.toList
instance (Outputable a) => Outputable (Set a) where
ppr s = braces (fsep (punctuate comma (map ppr (Set.toList s))))
instance (Outputable a, Outputable b) => Outputable (a, b) where
ppr (x,y) = parens (sep [ppr x <> comma, ppr y])
instance Outputable a => Outputable (Maybe a) where
ppr Nothing = text "Nothing"
ppr (Just x) = text "Just" <+> ppr x
instance (Outputable a, Outputable b) => Outputable (Either a b) where
ppr (Left x) = text "Left" <+> ppr x
ppr (Right y) = text "Right" <+> ppr y
instance (Outputable a, Outputable b, Outputable c) => Outputable (a, b, c) where
ppr (x,y,z) =
parens (sep [ppr x <> comma,
ppr y <> comma,
ppr z ])
instance (Outputable a, Outputable b, Outputable c, Outputable d) =>
Outputable (a, b, c, d) where
ppr (a,b,c,d) =
parens (sep [ppr a <> comma,
ppr b <> comma,
ppr c <> comma,
ppr d])
instance (Outputable a, Outputable b, Outputable c, Outputable d, Outputable e) =>
Outputable (a, b, c, d, e) where
ppr (a,b,c,d,e) =
parens (sep [ppr a <> comma,
ppr b <> comma,
ppr c <> comma,
ppr d <> comma,
ppr e])
instance (Outputable a, Outputable b, Outputable c, Outputable d, Outputable e, Outputable f) =>
Outputable (a, b, c, d, e, f) where
ppr (a,b,c,d,e,f) =
parens (sep [ppr a <> comma,
ppr b <> comma,
ppr c <> comma,
ppr d <> comma,
ppr e <> comma,
ppr f])
instance (Outputable a, Outputable b, Outputable c, Outputable d, Outputable e, Outputable f, Outputable g) =>
Outputable (a, b, c, d, e, f, g) where
ppr (a,b,c,d,e,f,g) =
parens (sep [ppr a <> comma,
ppr b <> comma,
ppr c <> comma,
ppr d <> comma,
ppr e <> comma,
ppr f <> comma,
ppr g])
instance Outputable FastString where
ppr fs = ftext fs
instance (Outputable key, Outputable elt) => Outputable (M.Map key elt) where
ppr m = ppr (M.toList m)
instance (Outputable elt) => Outputable (IM.IntMap elt) where
ppr m = ppr (IM.toList m)
instance Outputable Fingerprint where
ppr (Fingerprint w1 w2) = text (printf "%016x%016x" w1 w2)
instance Outputable a => Outputable (SCC a) where
ppr (AcyclicSCC v) = text "NONREC" $$ (nest 3 (ppr v))
ppr (CyclicSCC vs) = text "REC" $$ (nest 3 (vcat (map ppr vs)))
instance Outputable Serialized where
ppr (Serialized the_type bytes) = int (length bytes) <+> text "of type" <+> text (show the_type)
instance Outputable Extension where
ppr = text . show
data BindingSite
= LambdaBind
| CaseBind
| CasePatBind
| LetBind
class Outputable a => OutputableBndr a where
pprBndr :: BindingSite -> a -> SDoc
pprBndr _b x = ppr x
pprPrefixOcc, pprInfixOcc :: a -> SDoc
bndrIsJoin_maybe :: a -> Maybe Int
bndrIsJoin_maybe _ = Nothing
pprHsChar :: Char -> SDoc
pprHsChar c | c > '\x10ffff' = char '\\' <> text (show (fromIntegral (ord c) :: Word32))
| otherwise = text (show c)
pprHsString :: FastString -> SDoc
pprHsString fs = vcat (map text (showMultiLineString (unpackFS fs)))
pprHsBytes :: ByteString -> SDoc
pprHsBytes bs = let escaped = concatMap escape $ BS.unpack bs
in vcat (map text (showMultiLineString escaped)) <> char '#'
where escape :: Word8 -> String
escape w = let c = chr (fromIntegral w)
in if isAscii c
then [c]
else '\\' : show w
primCharSuffix, primFloatSuffix, primIntSuffix :: SDoc
primDoubleSuffix, primWordSuffix, primInt64Suffix, primWord64Suffix :: SDoc
primCharSuffix = char '#'
primFloatSuffix = char '#'
primIntSuffix = char '#'
primDoubleSuffix = text "##"
primWordSuffix = text "##"
primInt64Suffix = text "L#"
primWord64Suffix = text "L##"
pprPrimChar :: Char -> SDoc
pprPrimInt, pprPrimWord, pprPrimInt64, pprPrimWord64 :: Integer -> SDoc
pprPrimChar c = pprHsChar c <> primCharSuffix
pprPrimInt i = integer i <> primIntSuffix
pprPrimWord w = word w <> primWordSuffix
pprPrimInt64 i = integer i <> primInt64Suffix
pprPrimWord64 w = word w <> primWord64Suffix
pprPrefixVar :: Bool -> SDoc -> SDoc
pprPrefixVar is_operator pp_v
| is_operator = parens pp_v
| otherwise = pp_v
pprInfixVar :: Bool -> SDoc -> SDoc
pprInfixVar is_operator pp_v
| is_operator = pp_v
| otherwise = char '`' <> pp_v <> char '`'
pprFastFilePath :: FastString -> SDoc
pprFastFilePath path = text $ normalise $ unpackFS path
pprFilePathString :: FilePath -> SDoc
pprFilePathString path = doubleQuotes $ text (escape (normalise path))
where
escape [] = []
escape ('\\':xs) = '\\':'\\':escape xs
escape (x:xs) = x:escape xs
pprWithCommas :: (a -> SDoc)
-> [a]
-> SDoc
pprWithCommas pp xs = fsep (punctuate comma (map pp xs))
pprWithBars :: (a -> SDoc)
-> [a]
-> SDoc
pprWithBars pp xs = fsep (intersperse vbar (map pp xs))
interppSP :: Outputable a => [a] -> SDoc
interppSP xs = sep (map ppr xs)
interpp'SP :: Outputable a => [a] -> SDoc
interpp'SP xs = sep (punctuate comma (map ppr xs))
pprQuotedList :: Outputable a => [a] -> SDoc
pprQuotedList = quotedList . map ppr
quotedList :: [SDoc] -> SDoc
quotedList xs = fsep (punctuate comma (map quotes xs))
quotedListWithOr :: [SDoc] -> SDoc
quotedListWithOr xs@(_:_:_) = quotedList (init xs) <+> text "or" <+> quotes (last xs)
quotedListWithOr xs = quotedList xs
quotedListWithNor :: [SDoc] -> SDoc
quotedListWithNor xs@(_:_:_) = quotedList (init xs) <+> text "nor" <+> quotes (last xs)
quotedListWithNor xs = quotedList xs
intWithCommas :: Integral a => a -> SDoc
intWithCommas n
| n < 0 = char '-' <> intWithCommas (n)
| q == 0 = int (fromIntegral r)
| otherwise = intWithCommas q <> comma <> zeroes <> int (fromIntegral r)
where
(q,r) = n `quotRem` 1000
zeroes | r >= 100 = empty
| r >= 10 = char '0'
| otherwise = text "00"
speakNth :: Int -> SDoc
speakNth 1 = text "first"
speakNth 2 = text "second"
speakNth 3 = text "third"
speakNth 4 = text "fourth"
speakNth 5 = text "fifth"
speakNth 6 = text "sixth"
speakNth n = hcat [ int n, text suffix ]
where
suffix | n <= 20 = "th"
| last_dig == 1 = "st"
| last_dig == 2 = "nd"
| last_dig == 3 = "rd"
| otherwise = "th"
last_dig = n `rem` 10
speakN :: Int -> SDoc
speakN 0 = text "none"
speakN 1 = text "one"
speakN 2 = text "two"
speakN 3 = text "three"
speakN 4 = text "four"
speakN 5 = text "five"
speakN 6 = text "six"
speakN n = int n
speakNOf :: Int -> SDoc -> SDoc
speakNOf 0 d = text "no" <+> d <> char 's'
speakNOf 1 d = text "one" <+> d
speakNOf n d = speakN n <+> d <> char 's'
plural :: [a] -> SDoc
plural [_] = empty
plural _ = char 's'
isOrAre :: [a] -> SDoc
isOrAre [_] = text "is"
isOrAre _ = text "are"
doOrDoes :: [a] -> SDoc
doOrDoes [_] = text "does"
doOrDoes _ = text "do"
itsOrTheir :: [a] -> SDoc
itsOrTheir [_] = text "its"
itsOrTheir _ = text "their"
callStackDoc :: HasCallStack => SDoc
callStackDoc =
hang (text "Call stack:")
4 (vcat $ map text $ lines (prettyCallStack callStack))
pprPanic :: HasCallStack => String -> SDoc -> a
pprPanic s doc = panicDoc s (doc $$ callStackDoc)
pprSorry :: String -> SDoc -> a
pprSorry = sorryDoc
pprPgmError :: String -> SDoc -> a
pprPgmError = pgmErrorDoc
pprTraceDebug :: String -> SDoc -> a -> a
pprTraceDebug str doc x
| debugIsOn && hasPprDebug unsafeGlobalDynFlags = pprTrace str doc x
| otherwise = x
pprTrace :: String -> SDoc -> a -> a
pprTrace str doc x = pprTraceWithFlags unsafeGlobalDynFlags str doc x
pprTraceWithFlags :: DynFlags -> String -> SDoc -> a -> a
pprTraceWithFlags dflags str doc x
| hasNoDebugOutput dflags = x
| otherwise = pprDebugAndThen dflags trace (text str) doc x
pprTraceM :: Applicative f => String -> SDoc -> f ()
pprTraceM str doc = pprTrace str doc (pure ())
pprTraceWith :: String -> (a -> SDoc) -> a -> a
pprTraceWith desc f x = pprTrace desc (f x) x
pprTraceIt :: Outputable a => String -> a -> a
pprTraceIt desc x = pprTraceWith desc ppr x
pprTraceException :: ExceptionMonad m => String -> SDoc -> m a -> m a
pprTraceException heading doc =
handleGhcException $ \exc -> liftIO $ do
putStrLn $ showSDocDump unsafeGlobalDynFlags (sep [text heading, nest 2 doc])
throwGhcExceptionIO exc
pprSTrace :: HasCallStack => SDoc -> a -> a
pprSTrace doc = pprTrace "" (doc $$ callStackDoc)
warnPprTrace :: HasCallStack => Bool -> String -> Int -> SDoc -> a -> a
warnPprTrace _ _ _ _ x | not debugIsOn = x
warnPprTrace _ _file _line _msg x
| hasNoDebugOutput unsafeGlobalDynFlags = x
warnPprTrace False _file _line _msg x = x
warnPprTrace True file line msg x
= pprDebugAndThen unsafeGlobalDynFlags trace heading
(msg $$ callStackDoc )
x
where
heading = hsep [text "WARNING: file", text file <> comma, text "line", int line]
assertPprPanic :: HasCallStack => String -> Int -> SDoc -> a
assertPprPanic _file _line msg
= pprPanic "ASSERT failed!" msg
pprDebugAndThen :: DynFlags -> (String -> a) -> SDoc -> SDoc -> a
pprDebugAndThen dflags cont heading pretty_msg
= cont (showSDocDump dflags doc)
where
doc = sep [heading, nest 2 pretty_msg]