-% ------------------------------------------------------------------------------
-% $Id: Show.lhs,v 1.5 2002/04/11 12:03:44 simonpj Exp $
-%
-% (c) The University of Glasgow, 1992-2000
-%
-
-\section{Module @GHC.Show@}
-
-
\begin{code}
{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module : GHC.Show
+-- Copyright : (c) The University of Glasgow, 1992-2002
+-- License : see libraries/base/LICENSE
+--
+-- Maintainer : cvs-ghc@haskell.org
+-- Stability : internal
+-- Portability : non-portable (GHC Extensions)
+--
+-- The 'Show' class, and related operations.
+--
+-----------------------------------------------------------------------------
module GHC.Show
(
-- Show support code
shows, showChar, showString, showParen, showList__, showSpace,
showLitChar, protectEsc,
- intToDigit, digitToInt, showSignedInt,
+ intToDigit, showSignedInt,
+ appPrec, appPrec1,
-- Character operations
- isAscii, isLatin1, isControl, isPrint, isSpace, isUpper,
- isLower, isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum,
- toUpper, toLower,
asciiTab,
-
- -- String operations
- lines, unlines, words, unwords
)
where
import GHC.Enum
import Data.Maybe
import Data.Either
-import GHC.List ( (!!), break, dropWhile
+import GHC.List ( (!!),
#ifdef USE_REPORT_PRELUDE
, concatMap, foldr1
#endif
where
showl [] = ']' : s
showl (y:ys) = ',' : showx y (showl ys)
+
+appPrec, appPrec1 :: Int
+ -- Use unboxed stuff because we don't have overloaded numerics yet
+appPrec = I# 10# -- Precedence of application:
+ -- one more than the maximum operator precedence of 9
+appPrec1 = I# 11# -- appPrec + 1
\end{code}
%*********************************************************
instance Show a => Show (Maybe a) where
showsPrec _p Nothing s = showString "Nothing" s
- showsPrec (I# p#) (Just x) s
- = (showParen (p# >=# 10#) $
+ showsPrec p (Just x) s
+ = (showParen (p > appPrec) $
showString "Just " .
- showsPrec (I# 10#) x) s
+ showsPrec appPrec1 x) s
instance (Show a, Show b) => Show (Either a b) where
- showsPrec (I# p#) e s =
- (showParen (p# >=# 10#) $
+ showsPrec p e s =
+ (showParen (p > appPrec) $
case e of
- Left a -> showString "Left " . showsPrec (I# 10#) a
- Right b -> showString "Right " . showsPrec (I# 10#) b)
+ Left a -> showString "Left " . showsPrec appPrec1 a
+ Right b -> showString "Right " . showsPrec appPrec1 b)
s
-
\end{code}
Code specific for characters
\begin{code}
+-- | Convert a character to a string using only printable characters,
+-- using Haskell source-language escape conventions. For example:
+--
+-- > showLitChar '\n' s = "\\n" ++ s
+--
showLitChar :: Char -> ShowS
-showLitChar c s | c > '\DEL' = showChar '\\' (protectEsc isDigit (shows (ord c)) s)
+showLitChar c s | c > '\DEL' = showChar '\\' (protectEsc isDec (shows (ord c)) s)
showLitChar '\DEL' s = showString "\\DEL" s
showLitChar '\\' s = showString "\\\\" s
showLitChar c s | c >= ' ' = showChar c s
-- I've done manual eta-expansion here, becuase otherwise it's
-- impossible to stop (asciiTab!!ord) getting floated out as an MFE
+isDec c = c >= '0' && c <= '9'
+
protectEsc :: (Char -> Bool) -> ShowS -> ShowS
protectEsc p f = f . cont
where cont s@(c:_) | p c = "\\&" ++ s
cont s = s
+
+
+asciiTab :: [String]
+asciiTab = -- Using an array drags in the array module. listArray ('\NUL', ' ')
+ ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
+ "SP"]
\end{code}
Code specific for Ints.
\begin{code}
+-- | Convert an 'Int' in the range @0@..@15@ to the corresponding single
+-- digit 'Char'. This function fails on other inputs, and generates
+-- lower-case hexadecimal digits.
intToDigit :: Int -> Char
intToDigit (I# i)
| i >=# 0# && i <=# 9# = unsafeChr (ord '0' `plusInt` I# i)
| i >=# 10# && i <=# 15# = unsafeChr (ord 'a' `minusInt` ten `plusInt` I# i)
| otherwise = error ("Char.intToDigit: not a digit " ++ show (I# i))
-digitToInt :: Char -> Int
-digitToInt c
- | isDigit c = ord c `minusInt` ord '0'
- | c >= 'a' && c <= 'f' = ord c `minusInt` ord 'a' `plusInt` ten
- | c >= 'A' && c <= 'F' = ord c `minusInt` ord 'A' `plusInt` ten
- | otherwise = error ("Char.digitToInt: not a digit " ++ show c) -- sigh
-
ten = I# 10#
showSignedInt :: Int -> Int -> ShowS
| otherwise = case chr# (ord# '0'# +# (n# `remInt#` 10#)) of { c# ->
itos' (n# `quotInt#` 10#) (C# c# : cs) }
\end{code}
-
-
-%*********************************************************
-%* *
-\subsection{Character stuff}
-%* *
-%*********************************************************
-
-\begin{code}
-isAscii, isLatin1, isControl, isPrint, isSpace, isUpper,
- isLower, isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum,
- isAsciiUpper, isAsciiLower :: Char -> Bool
-isAscii c = c < '\x80'
-isLatin1 c = c <= '\xff'
-isControl c = c < ' ' || c >= '\DEL' && c <= '\x9f'
-isPrint c = not (isControl c)
-
--- isSpace includes non-breaking space
--- Done with explicit equalities both for efficiency, and to avoid a tiresome
--- recursion with GHC.List elem
-isSpace c = c == ' ' ||
- c == '\t' ||
- c == '\n' ||
- c == '\r' ||
- c == '\f' ||
- c == '\v' ||
- c == '\xa0'
-
--- The upper case ISO characters have the multiplication sign dumped
--- randomly in the middle of the range. Go figure.
-isUpper c = c >= 'A' && c <= 'Z' ||
- c >= '\xC0' && c <= '\xD6' ||
- c >= '\xD8' && c <= '\xDE'
--- The lower case ISO characters have the division sign dumped
--- randomly in the middle of the range. Go figure.
-isLower c = c >= 'a' && c <= 'z' ||
- c >= '\xDF' && c <= '\xF6' ||
- c >= '\xF8' && c <= '\xFF'
-isAsciiLower c = c >= 'a' && c <= 'z'
-isAsciiUpper c = c >= 'A' && c <= 'Z'
-
-isAlpha c = isLower c || isUpper c
-isDigit c = c >= '0' && c <= '9'
-isOctDigit c = c >= '0' && c <= '7'
-isHexDigit c = isDigit c || c >= 'A' && c <= 'F' ||
- c >= 'a' && c <= 'f'
-isAlphaNum c = isAlpha c || isDigit c
-
--- Case-changing operations
-
-toUpper, toLower :: Char -> Char
-toUpper c@(C# c#)
- | isAsciiLower c = C# (chr# (ord# c# -# 32#))
- | isAscii c = c
- -- fall-through to the slower stuff.
- | isLower c && c /= '\xDF' && c /= '\xFF'
- = unsafeChr (ord c `minusInt` ord 'a' `plusInt` ord 'A')
- | otherwise
- = c
-
-
-toLower c@(C# c#)
- | isAsciiUpper c = C# (chr# (ord# c# +# 32#))
- | isAscii c = c
- | isUpper c = unsafeChr (ord c `minusInt` ord 'A' `plusInt` ord 'a')
- | otherwise = c
-
-asciiTab :: [String]
-asciiTab = -- Using an array drags in the array module. listArray ('\NUL', ' ')
- ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
- "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
- "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
- "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
- "SP"]
-\end{code}
-
-%*********************************************************
-%* *
-\subsection{Functions on strings}
-%* *
-%*********************************************************
-
-lines breaks a string up into a list of strings at newline characters.
-The resulting strings do not contain newlines. Similary, words
-breaks a string up into a list of words, which were delimited by
-white space. unlines and unwords are the inverse operations.
-unlines joins lines with terminating newlines, and unwords joins
-words with separating spaces.
-
-\begin{code}
-lines :: String -> [String]
-lines "" = []
-lines s = let (l, s') = break (== '\n') s
- in l : case s' of
- [] -> []
- (_:s'') -> lines s''
-
-words :: String -> [String]
-words s = case dropWhile {-partain:Char.-}isSpace s of
- "" -> []
- s' -> w : words s''
- where (w, s'') =
- break {-partain:Char.-}isSpace s'
-
-unlines :: [String] -> String
-#ifdef USE_REPORT_PRELUDE
-unlines = concatMap (++ "\n")
-#else
--- HBC version (stolen)
--- here's a more efficient version
-unlines [] = []
-unlines (l:ls) = l ++ '\n' : unlines ls
-#endif
-
-unwords :: [String] -> String
-#ifdef USE_REPORT_PRELUDE
-unwords [] = ""
-unwords ws = foldr1 (\w s -> w ++ ' ':s) ws
-#else
--- HBC version (stolen)
--- here's a more efficient version
-unwords [] = ""
-unwords [w] = w
-unwords (w:ws) = w ++ ' ' : unwords ws
-#endif
-
-\end{code}