% % Derived pretty printing functionality % The @PP@ interface augments the standard @Pretty@ interface a little for the task at hand. \begin{code}
module PP
       (
	 PPDoc
       , showPPDoc
       , getPPEnv
       , setPPEnv
       
	 -- additional pp combinators
	 -- (pinched from GC source.)
       , vsep
       , joinedBy
       , ppDecls
       , withSemi
       , ppTuple
       , ppTupleVert
       , ppList
       , ppListVert

       -- re-export of (lifted) Pretty 
       -- functionality
       , empty
       , isEmpty
       , nest
       , text
       , ptext
       , char
       , int
       , integer
       , float
       , double
       , rational
       , parens
       , brackets
       , braces
       , quotes
       , doubleQuotes
       , semi
       , comma
       , colon
       , space
       , equals
       , lparen, rparen
       , lbrack, rbrack
       , lbrace, rbrace
       , (<>)
       , (<+>)
       , hcat
       , hsep
       , ($$)
       , ($+$)
       , vcat
       , sep
       , cat
       , fsep
       , fcat
       , hang
       , punctuate

       , render
	
       ) where

import qualified Text.PrettyPrint as P

type PPDoc a = a -> P.Doc

showPPDoc ::PPDoc a -> a -> String
showPPDoc f v = show (f v)

\end{code} \begin{code}
vsep :: [PPDoc a] -> PPDoc a
vsep ds = ds `joinedBy` ($+$)

joinedBy :: [PPDoc a] -> (PPDoc a -> PPDoc a -> PPDoc a) -> PPDoc a
[] `joinedBy` _    = empty
xs `joinedBy` sep1 = foldr1 sep1 xs

ppDecls :: [PPDoc a] -> PPDoc a
ppDecls [] = empty
ppDecls ls = vsep (punctuate semi ls) <> semi

withSemi :: PPDoc a -> PPDoc a
withSemi d 
  | isEmpty d = d
  | otherwise = d <> semi

ppTuple :: [PPDoc a] -> PPDoc a
ppTuple ls = parens (hsep (punctuate comma ls))

ppTupleVert :: [PPDoc a] -> PPDoc a
ppTupleVert []     = ppTuple []
ppTupleVert (a:as) =
  vsep (char '(' <+> a : map ((<+>) comma) as) <+> char ')'

ppListVert :: [PPDoc a] -> PPDoc a
ppListVert []     = brackets empty
ppListVert [a]    = brackets ( a )
ppListVert (a:as) =
  vsep (char '[' <+> a : map ((<+>) comma) as) $$
  char ']'

ppList :: [PPDoc a] -> PPDoc a
ppList ls = brackets (hsep (punctuate comma ls))

getPPEnv :: (a -> PPDoc a) -> PPDoc a
getPPEnv f = \ v -> (f v) v

setPPEnv :: a -> PPDoc a -> PPDoc b
setPPEnv v f = \ _ -> f v
\end{code} Lifting Pretty's functionality up into PPDocs. \begin{code}
empty :: PPDoc a
empty _ = P.empty

isEmpty :: PPDoc a -> Bool
isEmpty d      = P.isEmpty (d undefined)

nest :: Int -> PPDoc a -> PPDoc a
nest i d       = \ v -> P.nest i (d v)

text :: String -> PPDoc a
text nm        = \ _ -> P.text nm

ptext :: String -> PPDoc a
ptext nm       = \ _ -> P.ptext nm

char :: Char -> PPDoc a
char c         = \ _ -> P.char c

int :: Int -> PPDoc a
int i          = \ _ -> P.int i

integer :: Integer -> PPDoc a
integer i      = \ _ -> P.integer i

float :: Float -> PPDoc a
float f        = \ _ -> P.float f

double :: Double -> PPDoc a
double d       = \ _ -> P.double d

rational :: Rational -> PPDoc a
rational r     = \ _ -> P.rational r

parens :: PPDoc a -> PPDoc a
parens d       = \ v -> P.parens   (d v)

brackets :: PPDoc a -> PPDoc a
brackets d     = \ v -> P.brackets (d v)

braces :: PPDoc a -> PPDoc a
braces d       = \ v -> P.braces (d v)

quotes :: PPDoc a -> PPDoc a
quotes d       = \ v -> P.quotes (d v)

doubleQuotes :: PPDoc a -> PPDoc a
doubleQuotes d = \ v -> P.doubleQuotes (d v)

semi :: PPDoc a
semi           = \ _ -> P.semi

comma :: PPDoc a
comma          = \ _ -> P.comma

colon :: PPDoc a
colon          = \ _ -> P.colon

space :: PPDoc a
space          = \ _ -> P.space

equals :: PPDoc a
equals         = \ _ -> P.equals

lparen :: PPDoc a
lparen         = \ _ -> P.lparen

rparen :: PPDoc a
rparen         = \ _ -> P.rparen

lbrack :: PPDoc a
lbrack         = \ _ -> P.lbrack

rbrack :: PPDoc a
rbrack         = \ _ -> P.rbrack

lbrace :: PPDoc a
lbrace         = \ _ -> P.lbrace

rbrace :: PPDoc a
rbrace         = \ _ -> P.rbrace

(<>) :: PPDoc a -> PPDoc a -> PPDoc a
(<>) d1 d2     = \ v -> (P.<>) (d1 v) (d2 v)

(<+>) :: PPDoc a -> PPDoc a -> PPDoc a
(<+>) d1 d2    = \ v -> (P.<+>) (d1 v) (d2 v)

hcat :: [PPDoc a] -> PPDoc a
hcat ds        = \ v -> P.hcat (map ($ v) ds)

hsep :: [PPDoc a] -> PPDoc a
hsep ds        = \ v -> P.hsep (map ($ v) ds)

($$) :: PPDoc a -> PPDoc a -> PPDoc a
($$) d1 d2     = \ v -> (P.$$)  (d1 v) (d2 v)

($+$) :: PPDoc a -> PPDoc a -> PPDoc a
($+$) d1 d2    = \ v -> (P.$+$) (d1 v) (d2 v)

vcat :: [PPDoc a] -> PPDoc a
vcat ds        = \ v -> P.vcat (map ($ v) ds)

sep  :: [PPDoc a] -> PPDoc a
sep  ds        = \ v -> P.sep (map ($ v) ds)

cat  :: [PPDoc a] -> PPDoc a
cat  ds        = \ v -> P.cat (map ($ v) ds)

fsep :: [PPDoc a] -> PPDoc a
fsep ds        = \ v -> P.fsep (map ($ v) ds)

fcat :: [PPDoc a] -> PPDoc a
fcat ds        = \ v -> P.fcat (map ($ v) ds)

hang :: PPDoc a -> Int -> PPDoc a -> PPDoc a
hang d1 i d2   = \ v -> P.hang (d1 v) i (d2 v)

render :: PPDoc a -> a -> String
render d       = \ v -> P.render (d v)

punctuate :: PPDoc a -> [PPDoc a] -> [PPDoc a]
punctuate _ []     = []
punctuate p (d:ds) = go d ds
		   where
		     go s [] = [s]
		     go s (e:es) = (s <> p) : go e es

\end{code}