% % Copyright (C) 1997 Thomas Nordin and Alastair Reid % \begin{code} module PrettyUtils ( textline , indent , around , joinedBy, sepdBy , vsep, hsepMap, hcatMap, vsepMap, vcatMap , commaList, semiList, ppList , ppParen -- Haskell constructs , ppTuple, ppApply, ppRecord , ppBind, ppReturn , ppCase, ppCases, ppIf -- C constructs , ppCIf, ppAssign, ppCDeclare, ppCDecl, ppCast, ppBlock, ppStruct ) where import Pretty import List ( intersperse ) import Maybe ( maybeToList ) textline :: [String] -> Doc textline = hsep . map text indent :: Doc -> Doc indent = nest 2 around :: (String, String) -> Doc -> Doc (a, b) `around` d = text a <> d <> text b joinedBy :: [Doc] -> (Doc -> Doc -> Doc) -> Doc [] `joinedBy` sep = empty xs `joinedBy` sep = foldr1 sep xs sepdBy :: [Doc] -> Doc -> Doc ds `sepdBy` sep = hcat (intersperse sep ds) hsepMap, hcatMap, vcatMap, vsepMap :: (a -> Doc) -> [a] -> Doc hsepMap pp xs = hsep (map pp xs) hcatMap pp xs = hcat (map pp xs) vcatMap pp xs = vcat (map pp xs) vsepMap pp xs = vsep (map pp xs) vsep :: [Doc] -> Doc vsep ds = ds `joinedBy` ($+$) --($+$) :: Doc -> Doc -> Doc --d1 $+$ d2 = d1 $$ text "" $$ d2 commaList :: [Doc] -> Doc commaList ds = ds `sepdBy` comma semiList :: [Doc] -> Doc semiList ds = ds `sepdBy` semi ppList :: Doc -> Doc -> [Doc] -> Doc ppList sep = foldr (\a as -> a <> sep <> as) ppTuple :: [Doc] -> Doc ppTuple ds = parens (commaList ds) ppApply :: Doc -> [Doc] -> Doc ppApply d ds = ppParen (not (null ds)) ((d:ds) `sepdBy` space) ppRecord :: Doc -> [Doc] -> [Doc] -> Doc ppRecord c fs vs = c <> braces (commaList (zipWith (\f v -> f <> equals <> v) fs vs)) -- inspired by Prelude.showParen ppParen :: Bool -> Doc -> Doc ppParen True = parens ppParen False = id ppBind :: Doc -> (Doc, Doc) -> Doc ppBind m (pat, k) = m <> text " >>= \\ " <> pat <> text " ->" $$ k ppReturn :: Doc -> Doc ppReturn x = ppApply (text "return") [parens x] \end{code} \begin{code} ppCase :: Doc -> Doc -> (Doc -> Doc) ppCase v d b = text "case" <+> v <+> text "of {" <+> d <+> text "->" $$ b <> text "}" ppIf :: Doc -> Doc -> Doc -> Doc ppIf cond t e = text "if" <+> cond $$ text "then" <+> t $$ text "else" <+> e \end{code} \begin{code} ppCases :: Doc -> [(Doc, Doc)] -> Doc ppCases exp alts = text "case" <+> exp <+> text "of" <+> braces (semiList [ pat <+> text "->" <+> body | (pat, body) <- alts ]) \end{code} Print: if (..) {..} else if (..) {..} .. else if (..) {..} else {..} \begin{code} ppCIf :: [(Doc,Doc)] -> Maybe Doc -> Doc ppCIf xs mbe = (map mkIf xs ++ map braces (maybeToList mbe)) `joinedBy` mkElse where mkIf (c,s) = text "if" <+> parens c <+> braces s d1 `mkElse` d2 = d1 $$ text "else" <+> d2 \end{code} Print a C assignment, C declaration (with initialisation), C cast, ... \begin{code} ppAssign :: String -> Doc -> Doc ppAssign lhs rhs = text lhs <+> equals <+> rhs <> semi ppCDeclare :: Doc -> Doc -> Doc -> Doc ppCDeclare ty var init = ty <+> var <+> equals <+> init <> semi ppCDecl :: String -> String -> Doc ppCDecl t n = text t <+> text n <> semi ppCast :: Doc -> Doc -> Doc ppCast ty expr = parens (parens ty <+> expr) ppBlock :: Doc -> Doc ppBlock d = ("do {", "} while(0);") `around` (indent d) ppStruct :: [Doc] -> Doc ppStruct ds = braces (commaList ds) \end{code}