X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Futils%2FOutputable.lhs;h=5a4368c09ab6e5dc6fdfe66dfe40d3b6bea3e30a;hb=2daf91758edf8a9a1116ad2ad1468627cf151303;hp=3ba5f55b7379d0daaea12c4cdf101a830b441c8c;hpb=6c381e873e222417d9a67aeec77b9555eca7b7a8;p=ghc-hetmet.git diff --git a/ghc/compiler/utils/Outputable.lhs b/ghc/compiler/utils/Outputable.lhs index 3ba5f55..5a4368c 100644 --- a/ghc/compiler/utils/Outputable.lhs +++ b/ghc/compiler/utils/Outputable.lhs @@ -1,5 +1,5 @@ % -% (c) The GRASP Project, Glasgow University, 1992-1996 +% (c) The GRASP Project, Glasgow University, 1992-1998 % \section[Outputable]{Classes for pretty-printing} @@ -7,150 +7,320 @@ Defines classes for pretty-printing and forcing, both forms of ``output.'' \begin{code} -#include "HsVersions.h" module Outputable ( - -- NAMED-THING-ERY - NamedThing(..), -- class - ExportFlag(..), - isExported, getLocalName, ltLexical, + Outputable(..), OutputableBndr(..), -- Class + + BindingSite(..), + + PprStyle, CodeStyle(..), PrintUnqualified, alwaysQualify, + getPprStyle, withPprStyle, withPprStyleDoc, pprDeeper, + codeStyle, userStyle, debugStyle, dumpStyle, asmStyle, + ifPprDebug, unqualStyle, + mkErrStyle, defaultErrStyle, + + SDoc, -- Abstract + docToSDoc, + interppSP, interpp'SP, pprQuotedList, pprWithCommas, + empty, nest, + text, char, ftext, ptext, + int, integer, float, double, rational, + parens, brackets, braces, quotes, doubleQuotes, angleBrackets, + semi, comma, colon, dcolon, space, equals, dot, arrow, + lparen, rparen, lbrack, rbrack, lbrace, rbrace, underscore, + (<>), (<+>), hcat, hsep, + ($$), ($+$), vcat, + sep, cat, + fsep, fcat, + hang, punctuate, + speakNth, speakNTimes, + + printSDoc, printErrs, printDump, + printForC, printForAsm, printForUser, + pprCode, mkCodeStyle, + showSDoc, showSDocForUser, showSDocDebug, + showSDocUnqual, showsPrecSDoc, + pprHsChar, pprHsString, + + -- error handling + pprPanic, assertPprPanic, pprPanic#, pprPgmError, + pprTrace, warnPprTrace, + trace, pgmError, panic, panic#, assertPanic + ) where - -- PRINTERY AND FORCERY - Outputable(..), -- class +#include "HsVersions.h" - interppSP, interpp'SP, - ifnotPprForUser, - ifPprDebug, - ifPprShowAll, ifnotPprShowAll, - ifPprInterface, - isOpLexeme, pprOp, pprNonOp, - isConop, isAconop, isAvarid, isAvarop +import {-# SOURCE #-} Module( Module ) +import {-# SOURCE #-} OccName( OccName ) - -- and to make the interface self-sufficient... - ) where +import CmdLineOpts ( opt_PprStyle_Debug, opt_PprUserLength ) +import PackageConfig ( PackageId, packageIdString ) +import FastString +import qualified Pretty +import Pretty ( Doc, Mode(..) ) +import Panic -import Ubiq{-uitous-} +import DATA_WORD ( Word32 ) -import PprStyle ( PprStyle(..) ) -import Pretty -import Util ( cmpPString ) +import IO ( Handle, stderr, stdout, hFlush ) +import Char ( ord ) \end{code} + %************************************************************************ %* * -\subsection[NamedThing-class]{The @NamedThing@ class} +\subsection{The @PprStyle@ data type} %* * %************************************************************************ \begin{code} -class NamedThing a where - getExportFlag :: a -> ExportFlag - isLocallyDefined :: a -> Bool - getOrigName :: a -> (FAST_STRING{-module-}, FAST_STRING{-name therein-}) - getOccurrenceName :: a -> FAST_STRING - getInformingModules :: a -> [FAST_STRING] - getSrcLoc :: a -> SrcLoc - getItsUnique :: a -> Unique - fromPreludeCore :: a -> Bool - -- see also friendly functions that follow... -\end{code} +data PprStyle + = PprUser PrintUnqualified Depth + -- Pretty-print in a way that will make sense to the + -- ordinary user; must be very close to Haskell + -- syntax, etc. + -- Assumes printing tidied code: non-system names are + -- printed without uniques. -\begin{description} -\item[@getExportFlag@:] -Obvious. + | PprCode CodeStyle + -- Print code; either C or assembler -\item[@getOrigName@:] -Obvious. + | PprDump -- For -ddump-foo; less verbose than PprDebug. + -- Does not assume tidied code: non-external names + -- are printed with uniques. -\item[@isLocallyDefined@:] -Whether the thing is defined in this module or not. + | PprDebug -- Full debugging output -\item[@getOccurrenceName@:] -Gets the name by which a thing is known in this module (e.g., if -renamed, or whatever)... +data CodeStyle = CStyle -- The format of labels differs for C and assembler + | AsmStyle -\item[@getInformingModules@:] -Gets the name of the modules that told me about this @NamedThing@. +data Depth = AllTheWay + | PartWay Int -- 0 => stop -\item[@getSrcLoc@:] -Obvious. -\item[@fromPreludeCore@:] -Tests a quite-delicate property: it is \tr{True} iff the entity is -actually defined in \tr{PreludeCore} (or \tr{PreludeBuiltin}), or if -it is re-exported by \tr{PreludeCore}. See the @FullName@ type in -module \tr{NameTypes}. +type PrintUnqualified = Module -> OccName -> Bool + -- This function tells when it's ok to print + -- a (Global) name unqualified -NB: Some of the types in, e.g., \tr{PreludeGlaST} {\em fail} this test. -This is a bummer for types that are wired into the compiler. -\end{description} +alwaysQualify,neverQualify :: PrintUnqualified +alwaysQualify m n = False +neverQualify m n = True -Some functions to go with: -\begin{code} -isExported a - = case (getExportFlag a) of - NotExported -> False - _ -> True +defaultUserStyle = mkUserStyle alwaysQualify AllTheWay + +defaultDumpStyle | opt_PprStyle_Debug = PprDebug + | otherwise = PprDump -getLocalName :: (NamedThing a) => a -> FAST_STRING +mkErrStyle :: PrintUnqualified -> PprStyle +-- Style for printing error messages +mkErrStyle print_unqual = mkUserStyle print_unqual (PartWay opt_PprUserLength) -getLocalName = snd . getOrigName +defaultErrStyle :: PprStyle +-- Default style for error messages +-- It's a bit of a hack because it doesn't take into account what's in scope +-- Only used for desugarer warnings, and typechecker errors in interface sigs +defaultErrStyle + | opt_PprStyle_Debug = mkUserStyle alwaysQualify AllTheWay + | otherwise = mkUserStyle alwaysQualify (PartWay opt_PprUserLength) -#ifdef USE_ATTACK_PRAGMAS -{-# SPECIALIZE isExported :: Class -> Bool #-} -{-# SPECIALIZE isExported :: Id -> Bool #-} -{-# SPECIALIZE isExported :: TyCon -> Bool #-} -{-# SPECIALIZE getLocalName :: ShortName -> FAST_STRING #-} -#endif +mkUserStyle unqual depth | opt_PprStyle_Debug = PprDebug + | otherwise = PprUser unqual depth \end{code} -@ltLexical@ is used for sorting things into lexicographical order, so -as to canonicalize interfaces. [Regular @(<)@ should be used for fast -comparison.] +Orthogonal to the above printing styles are (possibly) some +command-line flags that affect printing (often carried with the +style). The most likely ones are variations on how much type info is +shown. -\begin{code} -a `ltLexical` b - = BIND isLocallyDefined a _TO_ a_local -> - BIND isLocallyDefined b _TO_ b_local -> - BIND getOrigName a _TO_ (a_mod, a_name) -> - BIND getOrigName b _TO_ (b_mod, b_name) -> - if a_local || b_local then - a_name < b_name -- can't compare module names - else - case _CMP_STRING_ a_mod b_mod of - LT_ -> True - EQ_ -> a_name < b_name - GT__ -> False - BEND BEND BEND BEND - -#ifdef USE_ATTACK_PRAGMAS -{-# SPECIALIZE ltLexical :: Class -> Class -> Bool #-} -{-# SPECIALIZE ltLexical :: Id -> Id -> Bool #-} -{-# SPECIALIZE ltLexical :: TyCon -> TyCon -> Bool #-} -#endif -\end{code} +The following test decides whether or not we are actually generating +code (either C or assembly), or generating interface files. %************************************************************************ %* * -\subsection[ExportFlag-datatype]{The @ExportFlag@ datatype} +\subsection{The @SDoc@ data type} %* * %************************************************************************ -The export flag @ExportAll@ means `export all there is', so there are -times when it is attached to a class or data type which has no -ops/constructors (if the class/type was imported abstractly). In -fact, @ExportAll@ is attached to everything except to classes/types -which are being {\em exported} abstractly, regardless of how they were -imported. +\begin{code} +type SDoc = PprStyle -> Doc + +withPprStyle :: PprStyle -> SDoc -> SDoc +withPprStyle sty d sty' = d sty + +withPprStyleDoc :: PprStyle -> SDoc -> Doc +withPprStyleDoc sty d = d sty + +pprDeeper :: SDoc -> SDoc +pprDeeper d (PprUser unqual (PartWay 0)) = Pretty.text "..." +pprDeeper d (PprUser unqual (PartWay n)) = d (PprUser unqual (PartWay (n-1))) +pprDeeper d other_sty = d other_sty + +getPprStyle :: (PprStyle -> SDoc) -> SDoc +getPprStyle df sty = df sty sty +\end{code} + +\begin{code} +unqualStyle :: PprStyle -> PrintUnqualified +unqualStyle (PprUser unqual _) m n = unqual m n +unqualStyle other m n = False + +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 + +debugStyle :: PprStyle -> Bool +debugStyle PprDebug = True +debugStyle other = False + +userStyle :: PprStyle -> Bool +userStyle (PprUser _ _) = True +userStyle other = False + +ifPprDebug :: SDoc -> SDoc -- Empty for non-debug style +ifPprDebug d sty@PprDebug = d sty +ifPprDebug d sty = Pretty.empty +\end{code} + +\begin{code} +-- Unused [7/02 sof] +printSDoc :: SDoc -> PprStyle -> IO () +printSDoc d sty = do + Pretty.printDoc PageMode stdout (d sty) + hFlush stdout + +-- I'm not sure whether the direct-IO approach of Pretty.printDoc +-- above is better or worse than the put-big-string approach here +printErrs :: Doc -> IO () +printErrs doc = do Pretty.printDoc PageMode stderr doc + hFlush stderr + +printDump :: SDoc -> IO () +printDump doc = do + Pretty.printDoc PageMode stdout (better_doc defaultDumpStyle) + hFlush stdout + where + better_doc = doc $$ text "" + -- We used to always print in debug style, but I want + -- to try the effect of a more user-ish style (unless you + -- say -dppr-debug) + +printForUser :: Handle -> PrintUnqualified -> SDoc -> IO () +printForUser handle unqual doc + = Pretty.printDoc PageMode handle (doc (mkUserStyle unqual AllTheWay)) + +-- printForC, printForAsm do what they sound like +printForC :: Handle -> SDoc -> IO () +printForC handle doc = Pretty.printDoc LeftMode handle (doc (PprCode CStyle)) + +printForAsm :: Handle -> SDoc -> IO () +printForAsm handle doc = Pretty.printDoc LeftMode handle (doc (PprCode AsmStyle)) + +pprCode :: CodeStyle -> SDoc -> SDoc +pprCode cs d = withPprStyle (PprCode cs) d + +mkCodeStyle :: CodeStyle -> PprStyle +mkCodeStyle = PprCode + +-- Can't make SDoc an instance of Show because SDoc is just a function type +-- However, Doc *is* an instance of Show +-- showSDoc just blasts it out as a string +showSDoc :: SDoc -> String +showSDoc d = show (d defaultUserStyle) + +showSDocForUser :: PrintUnqualified -> SDoc -> String +showSDocForUser unqual doc = show (doc (mkUserStyle unqual AllTheWay)) + +showSDocUnqual :: SDoc -> String +-- Only used in the gruesome HsExpr.isOperator +showSDocUnqual d = show (d (mkUserStyle neverQualify AllTheWay)) + +showsPrecSDoc :: Int -> SDoc -> ShowS +showsPrecSDoc p d = showsPrec p (d defaultUserStyle) + +showSDocDebug :: SDoc -> String +showSDocDebug d = show (d PprDebug) +\end{code} \begin{code} -data ExportFlag - = ExportAll -- export with all constructors/methods - | ExportAbs -- export abstractly - | NotExported +docToSDoc :: Doc -> SDoc +docToSDoc d = \_ -> d + +empty sty = Pretty.empty +text s sty = Pretty.text s +char c sty = Pretty.char c +ftext s sty = Pretty.ftext s +ptext s sty = Pretty.ptext s +int n sty = Pretty.int n +integer n sty = Pretty.integer n +float n sty = Pretty.float n +double n sty = Pretty.double n +rational n sty = Pretty.rational n + +parens d sty = Pretty.parens (d sty) +braces d sty = Pretty.braces (d sty) +brackets d sty = Pretty.brackets (d sty) +doubleQuotes d sty = Pretty.doubleQuotes (d sty) +angleBrackets d = char '<' <> d <> char '>' + +-- quotes encloses something in single quotes... +-- but it omits them if the thing ends in a single quote +-- so that we don't get `foo''. Instead we just have foo'. +quotes d sty = case show pp_d of + ('\'' : _) -> pp_d + other -> Pretty.quotes pp_d + where + pp_d = d sty + +semi sty = Pretty.semi +comma sty = Pretty.comma +colon sty = Pretty.colon +equals sty = Pretty.equals +space sty = Pretty.space +lparen sty = Pretty.lparen +rparen sty = Pretty.rparen +lbrack sty = Pretty.lbrack +rbrack sty = Pretty.rbrack +lbrace sty = Pretty.lbrace +rbrace sty = Pretty.rbrace +dcolon sty = Pretty.ptext SLIT("::") +arrow sty = Pretty.ptext SLIT("->") +underscore = char '_' +dot = char '.' + +nest n d sty = Pretty.nest n (d sty) +(<>) d1 d2 sty = (Pretty.<>) (d1 sty) (d2 sty) +(<+>) d1 d2 sty = (Pretty.<+>) (d1 sty) (d2 sty) +($$) d1 d2 sty = (Pretty.$$) (d1 sty) (d2 sty) +($+$) d1 d2 sty = (Pretty.$+$) (d1 sty) (d2 sty) + +hcat ds sty = Pretty.hcat [d sty | d <- ds] +hsep ds sty = Pretty.hsep [d sty | d <- ds] +vcat ds sty = Pretty.vcat [d sty | d <- ds] +sep ds sty = Pretty.sep [d sty | d <- ds] +cat ds sty = Pretty.cat [d sty | d <- ds] +fsep ds sty = Pretty.fsep [d sty | d <- ds] +fcat ds sty = Pretty.fcat [d sty | d <- ds] + +hang d1 n d2 sty = Pretty.hang (d1 sty) n (d2 sty) + +punctuate :: SDoc -> [SDoc] -> [SDoc] +punctuate p [] = [] +punctuate p (d:ds) = go d ds + where + go d [] = [d] + go d (e:es) = (d <> p) : go e es \end{code} + %************************************************************************ %* * \subsection[Outputable-class]{The @Outputable@ class} @@ -159,136 +329,196 @@ data ExportFlag \begin{code} class Outputable a where - ppr :: PprStyle -> a -> Pretty + ppr :: a -> SDoc \end{code} \begin{code} --- the ppSep in the ppInterleave puts in the spaces --- Death to ppSep! (WDP 94/11) +instance Outputable Bool where + ppr True = ptext SLIT("True") + ppr False = ptext SLIT("False") -interppSP :: Outputable a => PprStyle -> [a] -> Pretty -interppSP sty xs = ppIntersperse ppSP (map (ppr sty) xs) +instance Outputable Int where + ppr n = int n -interpp'SP :: Outputable a => PprStyle -> [a] -> Pretty -interpp'SP sty xs - = ppInterleave sep (map (ppr sty) xs) - where - sep = ppBeside ppComma ppSP - -#ifdef USE_ATTACK_PRAGMAS -{-# SPECIALIZE interppSP :: PprStyle -> [Id] -> Pretty #-} -{-# SPECIALIZE interppSP :: PprStyle -> [TyVar] -> Pretty #-} - -{-# SPECIALIZE interpp'SP :: PprStyle -> [(Id, Id)] -> Pretty #-} -{-# SPECIALIZE interpp'SP :: PprStyle -> [Id] -> Pretty #-} -{-# SPECIALIZE interpp'SP :: PprStyle -> [ProtoName] -> Pretty #-} -{-# SPECIALIZE interpp'SP :: PprStyle -> [TyVarTemplate] -> Pretty #-} -{-# SPECIALIZE interpp'SP :: PprStyle -> [TyVar] -> Pretty #-} -{-# SPECIALIZE interpp'SP :: PprStyle -> [Type] -> Pretty #-} -#endif +instance Outputable () where + ppr _ = text "()" + +instance (Outputable a) => Outputable [a] where + ppr xs = brackets (fsep (punctuate comma (map ppr xs))) + +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 = ptext SLIT("Nothing") + ppr (Just x) = ptext SLIT("Just") <+> ppr x + +-- ToDo: may not be used +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 (x,y,z,w) = + parens (sep [ppr x <> comma, + ppr y <> comma, + ppr z <> comma, + ppr w]) + +instance Outputable FastString where + ppr fs = text (unpackFS fs) -- Prints an unadorned string, + -- no double quotes or anything + +instance Outputable PackageId where + ppr pid = text (packageIdString pid) \end{code} + +%************************************************************************ +%* * +\subsection{The @OutputableBndr@ class} +%* * +%************************************************************************ + +When we print a binder, we often want to print its type too. +The @OutputableBndr@ class encapsulates this idea. + +@BindingSite@ is used to tell the thing that prints binder what +language construct is binding the identifier. This can be used +to decide how much info to print. + \begin{code} -ifPprDebug sty p = case sty of PprDebug -> p ; _ -> ppNil -ifPprShowAll sty p = case sty of PprShowAll -> p ; _ -> ppNil -ifPprInterface sty p = case sty of PprInterface -> p ; _ -> ppNil +data BindingSite = LambdaBind | CaseBind | LetBind -ifnotPprForUser sty p = case sty of PprForUser -> ppNil ; _ -> p -ifnotPprShowAll sty p = case sty of PprShowAll -> ppNil ; _ -> p +class Outputable a => OutputableBndr a where + pprBndr :: BindingSite -> a -> SDoc + pprBndr b x = ppr x \end{code} -These functions test strings to see if they fit the lexical categories -defined in the Haskell report. Normally applied as in, e.g., -@isConop (getOccurrenceName foo)@... [just for pretty-printing] + + +%************************************************************************ +%* * +\subsection{Random printing helpers} +%* * +%************************************************************************ \begin{code} -isConop, isAconop, isAvarid, isAvarop :: FAST_STRING -> Bool - -isConop cs - | _NULL_ cs = False - | c == '_' = isConop (_TAIL_ cs) -- allow for leading _'s - | otherwise = isUpper c || c == ':' - || c == '[' || c == '(' -- [] () and (,,) come is as Conop strings !!! - || isUpperISO c - where - c = _HEAD_ cs - -isAconop cs - | _NULL_ cs = False - | otherwise = c == ':' - where - c = _HEAD_ cs - -isAvarid cs - | _NULL_ cs = False - | c == '_' = isAvarid (_TAIL_ cs) -- allow for leading _'s - | isLower c = True - | isLowerISO c = True - | otherwise = False - where - c = _HEAD_ cs - -isAvarop cs - | _NULL_ cs = False - | isLower c = False - | isUpper c = False - | c `elem` "!#$%&*+./<=>?@\\^|~-" = True - | isSymbolISO c = True - | otherwise = False - where - c = _HEAD_ cs +-- We have 31-bit Chars and will simply use Show instances +-- of Char and String. + +pprHsChar :: Char -> SDoc +pprHsChar c | c > '\x10ffff' = char '\\' <> text (show (fromIntegral (ord c) :: Word32)) + | otherwise = text (show c) + +pprHsString :: FastString -> SDoc +pprHsString fs = text (show (unpackFS fs)) -isSymbolISO c = ord c `elem` (0xd7 : 0xf7 : [0xa1 .. 0xbf]) -isUpperISO c = 0xc0 <= oc && oc <= 0xde && oc /= 0xd7 where oc = ord c -isLowerISO c = 0xdf <= oc && oc <= 0xff && oc /= 0xf7 where oc = ord c +instance Show FastString where + showsPrec p fs = showsPrecSDoc p (ppr fs) \end{code} -And one ``higher-level'' interface to those: + +%************************************************************************ +%* * +\subsection{Other helper functions} +%* * +%************************************************************************ \begin{code} -isOpLexeme :: NamedThing a => a -> Bool - -isOpLexeme v - = let str = getOccurrenceName v in isAvarop str || isAconop str - --- print `vars`, (op) correctly -pprOp, pprNonOp :: (NamedThing name, Outputable name) => PprStyle -> name -> Pretty - -pprOp sty var - = if isOpLexeme var - then ppr sty var - else ppBesides [ppChar '`', ppr sty var, ppChar '`'] - -pprNonOp sty var - = if isOpLexeme var - then ppBesides [ppLparen, ppr sty var, ppRparen] - else ppr sty var - -#ifdef USE_ATTACK_PRAGMAS -{-# SPECIALIZE isOpLexeme :: Id -> Bool #-} -{-# SPECIALIZE pprNonOp :: PprStyle -> Id -> Pretty #-} -{-# SPECIALIZE pprNonOp :: PprStyle -> TyCon -> Pretty #-} -{-# SPECIALIZE pprOp :: PprStyle -> Id -> Pretty #-} -#endif +pprWithCommas :: (a -> SDoc) -> [a] -> SDoc +pprWithCommas pp xs = fsep (punctuate comma (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 +-- [x,y,z] ==> `x', `y', `z' +pprQuotedList xs = hsep (punctuate comma (map (quotes . ppr) xs)) \end{code} + +%************************************************************************ +%* * +\subsection{Printing numbers verbally} +%* * +%************************************************************************ + +@speakNth@ converts an integer to a verbal index; eg 1 maps to +``first'' etc. + \begin{code} -instance Outputable Bool where - ppr sty True = ppPStr SLIT("True") - ppr sty False = ppPStr SLIT("False") +speakNth :: Int -> SDoc + +speakNth 1 = ptext SLIT("first") +speakNth 2 = ptext SLIT("second") +speakNth 3 = ptext SLIT("third") +speakNth 4 = ptext SLIT("fourth") +speakNth 5 = ptext SLIT("fifth") +speakNth 6 = ptext SLIT("sixth") +speakNth n = hcat [ int n, text suffix ] + where + suffix | n <= 20 = "th" -- 11,12,13 are non-std + | last_dig == 1 = "st" + | last_dig == 2 = "nd" + | last_dig == 3 = "rd" + | otherwise = "th" -instance (Outputable a) => Outputable [a] where - ppr sty xs = - ppBesides [ ppLbrack, ppInterleave ppComma (map (ppr sty) xs), ppRbrack ] + last_dig = n `rem` 10 +\end{code} -instance (Outputable a, Outputable b) => Outputable (a, b) where - ppr sty (x,y) = - ppHang (ppBesides [ppLparen, ppr sty x, ppComma]) 4 (ppBeside (ppr sty y) ppRparen) +\begin{code} +speakNTimes :: Int {- >=1 -} -> SDoc +speakNTimes t | t == 1 = ptext SLIT("once") + | t == 2 = ptext SLIT("twice") + | otherwise = int t <+> ptext SLIT("times") +\end{code} --- ToDo: may not be used -instance (Outputable a, Outputable b, Outputable c) => Outputable (a, b, c) where - ppr sty (x,y,z) = - ppSep [ ppBesides [ppLparen, ppr sty x, ppComma], - ppBeside (ppr sty y) ppComma, - ppBeside (ppr sty z) ppRparen ] + +%************************************************************************ +%* * +\subsection{Error handling} +%* * +%************************************************************************ + +\begin{code} +pprPanic, pprPgmError :: String -> SDoc -> a +pprTrace :: String -> SDoc -> a -> a +pprPanic = pprAndThen panic -- Throw an exn saying "bug in GHC" + +pprPgmError = pprAndThen pgmError -- Throw an exn saying "bug in pgm being compiled" + -- (used for unusual pgm errors) +pprTrace = pprAndThen trace + +pprPanic# heading pretty_msg = panic# (show (doc PprDebug)) + where + doc = text heading <+> pretty_msg + +pprAndThen :: (String -> a) -> String -> SDoc -> a +pprAndThen cont heading pretty_msg = cont (show (doc PprDebug)) + where + doc = sep [text heading, nest 4 pretty_msg] + +assertPprPanic :: String -> Int -> SDoc -> a +assertPprPanic file line msg + = panic (show (doc PprDebug)) + where + doc = sep [hsep[text "ASSERT failed! file", + text file, + text "line", int line], + msg] + +warnPprTrace :: Bool -> String -> Int -> SDoc -> a -> a +warnPprTrace False file line msg x = x +warnPprTrace True file line msg x + = trace (show (doc PprDebug)) x + where + doc = sep [hsep [text "WARNING: file", text file, text "line", int line], + msg] \end{code}