module GHC.Utils.Outputable (
Outputable(..), OutputableBndr(..), OutputableP(..),
SDoc, runSDoc, PDoc(..),
docToSDoc,
interppSP, interpp'SP, 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,
lambda,
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,
bufLeftRenderSDoc,
pprCode,
showSDocOneLine,
renderWithContext,
pprInfixVar, pprPrefixVar,
pprHsChar, pprHsString, pprHsBytes,
primFloatSuffix, primCharSuffix, primDoubleSuffix,
primInt8Suffix, primWord8Suffix,
primInt16Suffix, primWord16Suffix,
primInt32Suffix, primWord32Suffix,
primInt64Suffix, primWord64Suffix,
primIntSuffix, primWordSuffix,
pprPrimChar, pprPrimInt, pprPrimWord,
pprPrimInt8, pprPrimWord8,
pprPrimInt16, pprPrimWord16,
pprPrimInt32, pprPrimWord32,
pprPrimInt64, pprPrimWord64,
pprFastFilePath, pprFilePathString,
BindingSite(..),
PprStyle(..), LabelStyle(..), PrintUnqualified(..),
QueryQualifyName, QueryQualifyModule, QueryQualifyPackage,
reallyAlwaysQualify, reallyAlwaysQualifyNames,
alwaysQualify, alwaysQualifyNames, alwaysQualifyModules,
neverQualify, neverQualifyNames, neverQualifyModules,
alwaysQualifyPackages, neverQualifyPackages,
QualifyName(..), queryQual,
sdocOption,
updSDocContext,
SDocContext (..), sdocWithContext, defaultSDocContext,
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,
) where
import GHC.Prelude
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 qualified GHC.Utils.Ppr.Colour as Col
import GHC.Utils.Ppr ( Doc, Mode(..) )
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 qualified Data.IntSet as IntSet
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.Utils.Exception
import GHC.Exts (oneShot)
data PprStyle
= PprUser PrintUnqualified Depth Coloured
| PprDump PrintUnqualified
| PprCode LabelStyle
data LabelStyle
= CStyle
| AsmStyle
deriving (Eq,Ord,Show)
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' (SDocContext -> Doc)
pattern SDoc :: (SDocContext -> Doc) -> SDoc
pattern SDoc m <- SDoc' m
where
SDoc m = SDoc' (oneShot m)
runSDoc :: SDoc -> (SDocContext -> Doc)
runSDoc (SDoc m) = m
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
, sdocUnitIdForUser :: !(FastString -> SDoc)
}
instance IsString SDoc where
fromString = text
instance Outputable SDoc where
ppr = id
defaultSDocContext :: SDocContext
defaultSDocContext = SDC
{ sdocStyle = defaultDumpStyle
, sdocColScheme = Col.defaultScheme
, sdocLastColour = Col.colReset
, sdocShouldUseColor = False
, sdocDefaultDepth = 5
, sdocLineLength = 100
, sdocCanUseUnicode = False
, sdocHexWordLiterals = False
, sdocPprDebug = False
, sdocPrintUnicodeSyntax = False
, sdocPrintCaseAsLet = False
, sdocPrintTypecheckerElaboration = False
, sdocPrintAxiomIncomps = False
, sdocPrintExplicitKinds = False
, sdocPrintExplicitCoercions = False
, sdocPrintExplicitRuntimeReps = False
, sdocPrintExplicitForalls = False
, sdocPrintPotentialInstances = False
, sdocPrintEqualityRelations = False
, sdocSuppressTicks = False
, sdocSuppressTypeSignatures = False
, sdocSuppressTypeApplications = False
, sdocSuppressIdInfo = False
, sdocSuppressCoercions = False
, sdocSuppressUnfoldings = False
, sdocSuppressVarKinds = False
, sdocSuppressUniques = False
, sdocSuppressModulePrefixes = False
, sdocSuppressStgExts = False
, sdocErrorSpans = False
, sdocStarIsType = False
, sdocImpredicativeTypes = False
, sdocLinearTypes = False
, sdocPrintTypeAbbreviations = True
, sdocUnitIdForUser = ftext
}
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
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 "")
bufLeftRenderSDoc :: SDocContext -> BufHandle -> SDoc -> IO ()
bufLeftRenderSDoc ctx bufHandle doc =
Pretty.bufLeftRender bufHandle (runSDoc doc ctx)
pprCode :: LabelStyle -> SDoc -> SDoc
pprCode cs d = withPprStyle (PprCode cs) d
renderWithContext :: SDocContext -> SDoc -> String
renderWithContext ctx sdoc
= let s = Pretty.style{ Pretty.mode = PageMode False,
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
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 of
[] -> Pretty.quotes pp_d
'\'' : _ -> pp_d
_ | '\'' <- last str -> pp_d
| otherwise -> Pretty.quotes pp_d
semi, comma, colon, equals, space, dcolon, underscore, dot, vbar :: SDoc
arrow, lollipop, larrow, darrow, arrowt, larrowt, arrowtt, larrowtt, lambda :: 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 "%1 ->")
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 "-<<")
lambda = unicodeSyntax (char 'λ') (char '\\')
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
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 IntSet.IntSet where
ppr s = braces (fsep (punctuate comma (map ppr (IntSet.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
deriving newtype instance Outputable NonDetFastString
deriving newtype instance Outputable LexicalFastString
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
class OutputableP env a where
pdoc :: env -> a -> SDoc
newtype PDoc a = PDoc a
instance Outputable a => OutputableP env (PDoc a) where
pdoc _ (PDoc a) = ppr a
instance OutputableP env a => OutputableP env [a] where
pdoc env xs = ppr (fmap (pdoc env) xs)
instance OutputableP env a => OutputableP env (Maybe a) where
pdoc env xs = ppr (fmap (pdoc env) xs)
instance (OutputableP env a, OutputableP env b) => OutputableP env (a, b) where
pdoc env (a,b) = ppr (pdoc env a, pdoc env b)
instance (OutputableP env a, OutputableP env b, OutputableP env c) => OutputableP env (a, b, c) where
pdoc env (a,b,c) = ppr (pdoc env a, pdoc env b, pdoc env c)
instance (OutputableP env key, OutputableP env elt) => OutputableP env (M.Map key elt) where
pdoc env m = ppr $ fmap (\(x,y) -> (pdoc env x, pdoc env y)) $ M.toList m
instance OutputableP env a => OutputableP env (SCC a) where
pdoc env scc = ppr (fmap (pdoc env) scc)
instance OutputableP env SDoc where
pdoc _ x = x
instance (OutputableP env a) => OutputableP env (Set a) where
pdoc env s = braces (fsep (punctuate comma (map (pdoc env) (Set.toList s))))
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, primDoubleSuffix,
primIntSuffix, primWordSuffix,
primInt8Suffix, primWord8Suffix,
primInt16Suffix, primWord16Suffix,
primInt32Suffix, primWord32Suffix,
primInt64Suffix, primWord64Suffix
:: SDoc
primCharSuffix = char '#'
primFloatSuffix = char '#'
primIntSuffix = char '#'
primDoubleSuffix = text "##"
primWordSuffix = text "##"
primInt8Suffix = text "#8"
primWord8Suffix = text "##8"
primInt16Suffix = text "#16"
primWord16Suffix = text "##16"
primInt32Suffix = text "#32"
primWord32Suffix = text "##32"
primInt64Suffix = text "#64"
primWord64Suffix = text "##64"
pprPrimChar :: Char -> SDoc
pprPrimInt, pprPrimWord,
pprPrimInt8, pprPrimWord8,
pprPrimInt16, pprPrimWord16,
pprPrimInt32, pprPrimWord32,
pprPrimInt64, pprPrimWord64
:: Integer -> SDoc
pprPrimChar c = pprHsChar c <> primCharSuffix
pprPrimInt i = integer i <> primIntSuffix
pprPrimWord w = word w <> primWordSuffix
pprPrimInt8 i = integer i <> primInt8Suffix
pprPrimInt16 i = integer i <> primInt16Suffix
pprPrimInt32 i = integer i <> primInt32Suffix
pprPrimInt64 i = integer i <> primInt64Suffix
pprPrimWord8 w = word w <> primWord8Suffix
pprPrimWord16 w = word w <> primWord16Suffix
pprPrimWord32 w = word w <> primWord32Suffix
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 = interpp'SP' ppr xs
interpp'SP' :: (a -> SDoc) -> [a] -> SDoc
interpp'SP' f xs = sep (punctuate comma (map f 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"