paragon-0.1.28: src/Language/Java/Paragon/Pretty.hs
{-# LANGUAGE TupleSections #-}
module Language.Java.Paragon.Pretty
(
prettyPrint, Pretty(..),
opt,
module Text.PrettyPrint
) where
import Text.PrettyPrint
import Data.Char (toLower)
import Control.Arrow (first)
import Language.Java.Paragon.Syntax
-- import Language.Java.Paragon.Interaction (panic)
import qualified Data.ByteString.Char8 as B
prettyPrint :: Pretty a => a -> String
prettyPrint = show . pretty
class Pretty a where
pretty :: a -> Doc
pretty = prettyPrec 0
prettyPrec :: Int -> a -> Doc
prettyPrec _ = pretty
instance Pretty a => Pretty [a] where
pretty as = brackets $ hcat (punctuate (char ',') $ map pretty as)
instance Pretty B.ByteString where
pretty bs = text (B.unpack bs)
-----------------------------------------------------------------------
-- Packages
instance Pretty (CompilationUnit a) where
pretty (CompilationUnit _ mpd ids tds) =
vcat $ maybePP mpd: map pretty ids ++ map pretty tds
instance Pretty (PackageDecl a) where
pretty (PackageDecl _ name) = text "package" <+> pretty name <> semi
instance Pretty (ImportDecl a) where
-- pretty (ImportDecl _ st name wc) =
-- text "import" <+> opt st (text "static")
-- <+> pretty name <> opt wc (text ".*")
-- <> semi
pretty imp =
let (st, name, mId, dem) = aux imp
in text "import" <+> opt st (text "static")
<+> pretty name
<> maybe empty (\i -> char '.' <> pretty i) mId
<> opt dem (text ".*")
<> semi
where aux (SingleTypeImport _ n) = (False, n, Nothing, False)
aux (TypeImportOnDemand _ n) = (False, n, Nothing, True )
aux (SingleStaticImport _ n i) = (True, n, Just i, False)
aux (StaticImportOnDemand _ n) = (True, n, Nothing, True )
-----------------------------------------------------------------------
-- Declarations
instance Pretty (TypeDecl a) where
pretty (ClassTypeDecl _ cdecl) = pretty cdecl
pretty (InterfaceTypeDecl _ idecl) = pretty idecl
instance Pretty (ClassDecl a) where
pretty (EnumDecl _ mods ident impls body) =
hsep [hsep (map pretty mods)
, text "enum"
, pretty ident
, ppImplements impls
] $$ pretty body
pretty (ClassDecl _ mods ident tParams mSuper impls body) =
hsep [hsep (map pretty mods)
, text "class"
, pretty ident
, ppTypeParams tParams
, ppExtends (maybe [] return mSuper)
, ppImplements impls
] $$ pretty body
instance Pretty (ClassBody a) where
pretty (ClassBody _ ds) =
braceBlock (map pretty ds)
instance Pretty (EnumBody a) where
pretty (EnumBody _ cs ds) =
braceBlock $
punctuate comma (map pretty cs) ++
opt (not $ null ds) semi : map pretty ds
instance Pretty (EnumConstant a) where
pretty (EnumConstant _ ident args mBody) =
pretty ident
-- needs special treatment since even the parens are optional
<> opt (not $ null args) (ppArgs args)
$$ maybePP mBody
instance Pretty (InterfaceDecl a) where
pretty (InterfaceDecl _ mods ident tParams impls body) =
hsep [hsep (map pretty mods)
, text "interface"
, pretty ident
, ppTypeParams tParams
, ppImplements impls
] $$ pretty body
instance Pretty (InterfaceBody a) where
pretty (InterfaceBody _ mds) =
braceBlock (map pretty mds)
instance Pretty (Decl a) where
pretty (MemberDecl _ md) = pretty md
pretty (InitDecl _ b bl) =
opt b (text "static") <+> pretty bl
instance Pretty (MemberDecl a) where
pretty (FieldDecl _ mods t vds) =
hsep (map pretty mods ++ pretty t:map pretty vds) <> semi
pretty (MethodDecl _ mods tParams ret ident fParams throws body) =
hsep [hsep (map pretty mods)
, ppTypeParams tParams
, pretty ret
, pretty ident <> ppArgs fParams
, ppThrows throws
] $$ pretty body
pretty (ConstructorDecl _ mods tParams ident fParams throws body) =
hsep [hsep (map pretty mods)
, ppTypeParams tParams
, pretty ident
, ppArgs fParams
, ppThrows throws
] $$ pretty body
pretty (MemberClassDecl _ cdecl) = pretty cdecl
pretty (MemberInterfaceDecl _ idecl) = pretty idecl
-- Paragon
pretty (LockDecl _ mods ident arity lockProps) =
hsep [hsep (map pretty mods)
, text "lock"
, pretty ident <> ppArity arity
] <> maybe empty (\lp -> char ' ' <> pretty lp) lockProps <> semi
ppArity :: [Maybe (Ident x)] -> Doc
ppArity [] = empty
ppArity mis = parens $ hsep $ punctuate comma $ map (\i -> {- char '?' <> -} maybePP i) mis
instance Pretty (VarDecl a) where
pretty (VarDecl _ vdId mInitz) =
pretty vdId
<+> maybe empty (\initz -> char '=' <+> pretty initz) mInitz
instance Pretty (VarDeclId a) where
pretty (VarId _ ident) = pretty ident
pretty (VarDeclArray _ vId) = pretty vId
instance Pretty (VarInit a) where
pretty (InitExp _ e) = pretty e
pretty (InitArray _ arrInit) = pretty arrInit
instance Pretty (FormalParam a) where
pretty (FormalParam _ mods t b vId) =
hsep [hsep (map pretty mods)
, pretty t <> opt b (text "...")
, pretty vId
]
instance Pretty (MethodBody a) where
pretty (MethodBody _ mBlock) = maybe semi pretty mBlock
instance Pretty (ConstructorBody a) where
pretty (ConstructorBody _ mECI stmts) =
braceBlock $ maybePP mECI : map pretty stmts
instance Pretty (ExplConstrInv a) where
pretty (ThisInvoke _ rts args) =
ppTypeParams rts <+> text "this" <> ppArgs args <> semi
pretty (SuperInvoke _ rts args) =
ppTypeParams rts <+> text "super" <> ppArgs args <> semi
pretty (PrimarySuperInvoke _ e rts args) =
pretty e <> char '.' <>
ppTypeParams rts <+> text "super" <> ppArgs args <> semi
instance Pretty (Modifier a) where
pretty m = case m of
Reads _ pol -> char '?' <> pretty pol
Writes _ pol -> char '!' <> pretty pol
Expects _ locks -> char '~' <> prettyLocks locks
Opens _ locks -> char '+' <> prettyLocks locks
Closes _ locks -> char '-' <> prettyLocks locks
Typemethod _ -> text "typemethod"
Reflexive _ -> text "reflexive"
Transitive _ -> text "transitive"
Symmetric _ -> text "symmetric"
Readonly _ -> text "readonly"
Public _ -> text "public"
Private _ -> text "private"
Protected _ -> text "protected"
Abstract _ -> text "abstract"
Final _ -> text "final"
Static _ -> text "static"
StrictFP _ -> text "strictfp"
Transient _ -> text "transient"
Volatile _ -> text "volatile"
Native _ -> text "native"
-----------------------------------------------------------------------
-- Statements
instance Pretty (Block a) where
pretty (Block _ stmts) = braceBlock $ map pretty stmts
instance Pretty (BlockStmt a) where
pretty (BlockStmt _ stmt) = pretty stmt
pretty (LocalClass _ cd) = pretty cd
pretty (LocalVars _ mods t vds) =
hsep (map pretty mods) <+> pretty t <+>
hsep (punctuate comma $ map pretty vds) <> semi
-- Paragon
pretty (LocalLock _ mods ident arity lockProps) =
hsep [hsep (map pretty mods)
, text "lock"
, pretty ident <> ppArity arity
] <> maybe empty (\lp -> char ' ' <> pretty lp) lockProps <> semi
{- pretty (LocalPolicy mods ident pol) =
hsep [hsep (map pretty mods)
, text "policy"
, pretty ident
, char '='
, pretty pol
] <> semi
pretty (LocalActor mods ident mInit) =
hsep [hsep (map pretty mods)
, text "actor"
, pretty ident
, maybe empty (\init -> char '=' <+> pretty init) mInit
] <> semi -}
instance Pretty (Stmt a) where
pretty (StmtBlock _ block) = pretty block
pretty (IfThen _ c th) =
hsep [text "if", parens (pretty c) , pretty th
]
pretty (IfThenElse _ c th el) =
hsep [text "if", parens (pretty c)
, pretty th , text "else", pretty el
]
pretty (While _ c stmt) =
hsep [text "while", parens (pretty c), pretty stmt]
pretty (BasicFor _ mInit mE mUp stmt) =
hsep [text "for"
, parens $ hsep [maybePP mInit, semi
, maybePP mE, semi
, maybe empty (hsep . punctuate comma . map pretty) mUp
]
, pretty stmt
]
pretty (EnhancedFor _ mods t ident e stmt) =
hsep [text "for"
, parens $ hsep [
hsep (map pretty mods)
, pretty t
, pretty ident
, colon
, pretty e
]
, pretty stmt
]
pretty (Empty _) = semi
pretty (ExpStmt _ e) = pretty e <> semi
pretty (Assert _ ass mE) =
text "assert" <+> pretty ass
<+> maybe empty ((colon <>) . pretty) mE <> semi
pretty (Switch _ e sBlocks) =
text "switch" <+> parens (pretty e)
$$ braceBlock (map pretty sBlocks)
pretty (Do _ stmt e) =
hsep [text "do", pretty stmt, text "while"
, parens (pretty e)] <> semi
pretty (Break _ mIdent) =
text "break" <+> maybePP mIdent <> semi
pretty (Continue _ mIdent) =
text "continue" <+> maybePP mIdent <> semi
pretty (Return _ mE) =
text "return" <+> maybePP mE <> semi
pretty (Synchronized _ e block) =
text "synchronized" <+> parens (pretty e) $$ pretty block
pretty (Throw _ e) =
text "throw" <+> pretty e <> semi
pretty (Try _ block catches mFinally) =
text "try" $$ pretty block $$
vcat (map pretty catches ++ [ppFinally mFinally])
where ppFinally Nothing = empty
ppFinally (Just bl) = text "finally" <+> pretty bl
pretty (Labeled _ ident stmt) =
pretty ident <> colon <+> pretty stmt
-- Paragon
pretty (Open _ lock) = text "open" <+> pretty lock <> semi
pretty (Close _ lock) = text "close" <+> pretty lock <> semi
pretty (OpenBlock _ lock block) = text "open" <+> pretty lock <+> pretty block
pretty (CloseBlock _ lock block) = text "close" <+> pretty lock <+> pretty block
{- pretty (WhenThen lock th) =
hsep [text "when", parens (pretty lock)
,text "then", pretty th
]
pretty (WhenThenElse lock th el) =
hsep [text "when", parens (pretty lock)
, text "then", pretty th
, text "else", pretty el
]
-}
instance Pretty (Catch a) where
pretty (Catch _ fParam block) =
hsep [text "catch", parens (pretty fParam)] $$ pretty block
instance Pretty (SwitchBlock a) where
pretty (SwitchBlock _ lbl stmts) =
vcat (pretty lbl : map (nest 2 . pretty) stmts)
instance Pretty (SwitchLabel a) where
pretty (SwitchCase _ e) =
text "case" <+> pretty e <> colon
pretty (Default _) = text "default:"
instance Pretty (ForInit a) where
pretty (ForLocalVars _ mods t vds) =
hsep $ map pretty mods ++
pretty t: punctuate comma (map pretty vds)
pretty (ForInitExps _ es) = hsep $ punctuate comma $ map pretty es
-----------------------------------------------------------------------
-- Expressions
instance Pretty (Exp a) where
pretty (Lit _ l) = pretty l
pretty (ClassLit _ mT) =
maybe (text "void") pretty mT <> text ".class"
pretty (This _) = text "this"
pretty (ThisClass _ name) =
pretty name <> text ".this"
pretty (Paren _ e) = parens (pretty e)
pretty (InstanceCreation _ tArgs ct args mBody) =
hsep [text "new"
, ppTypeParams tArgs
, pretty ct <> ppArgs args
] $$ maybePP mBody
pretty (QualInstanceCreation _ e tArgs ident args mBody) =
hsep [pretty e <> char '.' <> text "new"
, ppTypeParams tArgs
, pretty ident <> ppArgs args
] $$ maybePP mBody
pretty (ArrayCreate _ t eps ps) =
text "new" <+>
hcat (pretty t :
map ppArrayDim
(map (first Just) eps ++
map (Nothing,) ps))
-- hcat (pretty t : map (brackets . pretty) es
-- ++ replicate k (text "[]"))
pretty (ArrayCreateInit _ t ps ainit) =
text "new"
<+> hcat (pretty t : map ppArrayDim (map (Nothing,) ps))
<+> pretty ainit
pretty (FieldAccess _ fa) = pretty fa
pretty (MethodInv _ mi) = pretty mi
pretty (ArrayAccess _ ain) = pretty ain
pretty (ExpName _ name) = pretty name
pretty (PostIncrement _ e) = pretty e <> text "++"
pretty (PostDecrement _ e) = pretty e <> text "--"
pretty (PreIncrement _ e) = text "++" <> pretty e
pretty (PreDecrement _ e) = text "--" <> pretty e
pretty (PrePlus _ e) = char '+' <> pretty e
pretty (PreMinus _ e) = char '-' <> pretty e
pretty (PreBitCompl _ e) = char '~' <> pretty e
pretty (PreNot _ e) = char '!' <> pretty e
pretty (Cast _ t e) = parens (pretty t) <+> pretty e
pretty (BinOp _ e1 op e2) =
hsep [pretty e1, pretty op, pretty e2]
pretty (InstanceOf _ e rt) =
hsep [pretty e, text "instanceof", pretty rt]
pretty (Cond _ c th el) =
hsep [pretty c, char '?', pretty th, colon, pretty el]
pretty (Assign _ lhs aop e) =
hsep [pretty lhs, pretty aop, pretty e]
-- Paragon
pretty (PolicyExp _ pl) = pretty pl
-- pretty (PolicyOf i) = text "policyof" <> parens (pretty i)
pretty (LockExp _ l) = char '?' <> pretty l
pretty (AntiQExp _ s) = text "#E#" <> text s
instance Pretty (Literal a) where
pretty (Int _ i) = text (show i)
pretty (Word _ i) = text (show i) <> char 'L'
pretty (Float _ f) = text (show f) <> char 'F'
pretty (Double _ d) = text (show d)
pretty (Boolean _ b) = text . map toLower $ show b
pretty (Char _ c) = text (show c)
pretty (String _ s) = text (show s)
pretty (Null _ ) = text "null"
instance Pretty (Op a) where
pretty op = text $ case op of
Mult _ -> "*"
Div _ -> "/"
Rem _ -> "%"
Add _ -> "+"
Sub _ -> "-"
LShift _ -> "<<"
RShift _ -> ">>"
RRShift _ -> ">>>"
LThan _ -> "<"
GThan _ -> ">"
LThanE _ -> "<="
GThanE _ -> ">="
Equal _ -> "=="
NotEq _ -> "!="
And _ -> "&"
Xor _ -> "^"
Or _ -> "|"
CAnd _ -> "&&"
COr _ -> "||"
instance Pretty (AssignOp a) where
pretty aop = text $ case aop of
EqualA _ -> "="
MultA _ -> "*="
DivA _ -> "/="
RemA _ -> "%="
AddA _ -> "+="
SubA _ -> "-="
LShiftA _ -> "<<="
RShiftA _ -> ">>="
RRShiftA _ -> ">>>="
AndA _ -> "&="
XorA _ -> "^="
OrA _ -> "|="
instance Pretty (Lhs a) where
pretty (NameLhs _ name) = pretty name
pretty (FieldLhs _ fa) = pretty fa
pretty (ArrayLhs _ ain) = pretty ain
instance Pretty (ArrayIndex a) where
pretty (ArrayIndex _ ref e) = pretty ref <> brackets (pretty e)
instance Pretty (FieldAccess a) where
pretty (PrimaryFieldAccess _ e ident) =
pretty e <> char '.' <> pretty ident
pretty (SuperFieldAccess _ ident) =
text "super." <> pretty ident
pretty (ClassFieldAccess _ name ident) =
pretty name <> text ".super." <> pretty ident
instance Pretty (MethodInvocation a) where
pretty (MethodCallOrLockQuery _ name args) =
pretty name <> ppArgs args
pretty (PrimaryMethodCall _ e tArgs ident args) =
hcat [pretty e, char '.', ppTypeParams tArgs,
pretty ident, ppArgs args]
pretty (SuperMethodCall _ tArgs ident args) =
hcat [text "super.", ppTypeParams tArgs,
pretty ident, ppArgs args]
pretty (ClassMethodCall _ name tArgs ident args) =
hcat [pretty name, text ".super.", ppTypeParams tArgs,
pretty ident, ppArgs args]
pretty (TypeMethodCall _ name tArgs ident args) =
hcat [pretty name, char '.', ppTypeParams tArgs,
pretty ident, ppArgs args]
instance Pretty (ArrayInit a) where
pretty (ArrayInit _ vInits) =
braces $ hsep (punctuate comma (map pretty vInits))
ppArgs :: Pretty a => [a] -> Doc
ppArgs = parens . hsep . punctuate comma . map pretty
ppArrayDim :: (Maybe (Exp a), Maybe (Policy a)) -> Doc
ppArrayDim (mE, mP) =
brackets (maybe empty pretty mE) <>
maybe empty (angles . pretty) mP
-----------------------------------------------------------------------
-- Types
instance Pretty (Type a) where
pretty (PrimType _ pt) = pretty pt
pretty (RefType _ rt) = pretty rt
pretty (AntiQType _ s) = text "#T#" <> text s
instance Pretty (RefType a) where
pretty (ClassRefType _ ct) = pretty ct
pretty (TypeVariable _ i) = pretty i
pretty (ArrayType _ ty mPols) =
pretty ty <> hcat ((flip map) mPols
(\mP -> brackets empty <> maybe empty (angles . pretty) mP))
instance Pretty (ClassType a) where
pretty (ClassType _ n tas) =
pretty n <> ppTypeParams tas
-- hcat . punctuate (char '.') $
-- map (\(i,tas) -> pretty i <> ppTypeParams tas) itas
instance Pretty (TypeArgument a) where
pretty (ActualArg _ aa) = pretty aa
pretty (Wildcard _ mBound) = char '?' <+> maybePP mBound
instance Pretty (NonWildTypeArgument a) where
pretty (ActualName _ n) = pretty n
pretty (ActualType _ t) = pretty t
pretty (ActualExp _ e) = pretty e
pretty (ActualLockState _ ls) = {- text "lock[]" <+> -} ppArgs ls -- HACK ALERT
instance Pretty (WildcardBound a) where
pretty (ExtendsBound _ rt) = text "extends" <+> pretty rt
pretty (SuperBound _ rt) = text "super" <+> pretty rt
instance Pretty (PrimType a) where
pretty (BooleanT _) = text "boolean"
pretty (ByteT _) = text "byte"
pretty (ShortT _) = text "short"
pretty (IntT _) = text "int"
pretty (LongT _) = text "long"
pretty (CharT _) = text "char"
pretty (FloatT _) = text "float"
pretty (DoubleT _) = text "double"
-- Paragon
pretty (ActorT _) = text "actor"
pretty (PolicyT _) = text "policy"
instance Pretty (TypeParam a) where
pretty (TypeParam _ ident rts) =
pretty ident
<+> opt (not $ null rts)
(hsep $ text "extends":
punctuate (text " &") (map pretty rts))
pretty (ActorParam _ ident) = text "actor" <+> pretty ident
pretty (PolicyParam _ ident) = text "policy" <+> pretty ident
pretty (LockStateParam _ ident) = text "lock[]" <+> pretty ident
ppTypeParams :: Pretty a => [a] -> Doc
ppTypeParams [] = empty
ppTypeParams tps = angles $ hsep (punctuate comma (map pretty tps))
ppImplements :: [ClassType x] -> Doc
ppImplements [] = empty
ppImplements rts = text "implements"
<+> hsep (punctuate comma (map pretty rts))
ppExtends :: [ClassType x] -> Doc
ppExtends [] = empty
ppExtends rts = text "extends"
<+> hsep (punctuate comma (map pretty rts))
ppThrows :: [ExceptionSpec x] -> Doc
ppThrows [] = empty
ppThrows ess = text "throws"
<+> hsep (punctuate comma (map pretty ess))
instance Pretty (ExceptionSpec a) where
pretty (ExceptionSpec _ mods t) =
hsep (map pretty mods) <+> pretty t
instance Pretty (ReturnType a) where
pretty (VoidType _) = text "void"
pretty (LockType _) = text "lock"
pretty (Type _ ty ) = pretty ty
--ppResultType :: Maybe (Type x) -> Doc
--ppResultType Nothing = text "void"
--ppResultType (Just a) = pretty a
-----------------------------------------------------------------------
-- Paragon Policies
instance Pretty (PolicyExp a) where
pretty (PolicyLit _ []) = braces (char ':')
pretty (PolicyLit _ cs) = braces $ hcat (punctuate (char ';') $ map pretty cs)
pretty (PolicyOf _ i) = text "policyof" <> parens (pretty i)
pretty (PolicyThis _) = text "policyof" <> parens (text "this")
pretty (PolicyTypeVar _ i) = pretty i
instance Pretty (Clause a) where
pretty (Clause _ h b) = pretty h <>
char ':' <+> hcat (punctuate (char ',') $ map pretty b)
instance Pretty (LClause a) where
pretty (LClause _ h b) = pretty h <>
char ':' <+> hcat (punctuate (char ',') $ map pretty b)
instance Pretty (Actor a) where
pretty (Actor _ str) = pretty str
pretty (Var _ str) = char '\'' <> pretty str
instance Pretty (ActorName a) where
pretty (ActorName _ n) = pretty n
pretty (ActorTypeVar _ i) = pretty i
instance Pretty (Atom a) where
pretty (Atom _ pr vs) = pretty pr <>
opt (not $ null vs) (parens (hcat (punctuate (char ',') $ map pretty vs)))
instance Pretty (Lock a) where
pretty (Lock _ i as) = pretty i <>
opt (not $ null as) (parens (hcat (punctuate (char ',') $ map pretty as)))
pretty (LockVar _ i) = pretty i
instance Pretty (LockProperties a) where
pretty (LockProperties _ cs) = braces $ hcat (punctuate (char ';') $ map pretty cs)
prettyLocks :: [Lock x] -> Doc
--prettyLocks [l] = pretty l
prettyLocks ls = parens . hsep . punctuate (char ',') $ map pretty ls
--instance Pretty (LockExp a) where
-- pretty (LockExp ls) = parens $ hcat (map pretty ls)
-- pretty (LockVar v) = pretty v
-----------------------------------------------------------------------
-- Names and identifiers
instance Pretty (Name a) where
pretty (Name _ _ mPrefix i) =
maybe empty (\pre -> pretty pre <> char '.') mPrefix
<> pretty i
pretty (AntiQName _ s) = text "#N#" <> text s
instance Pretty NameType where
pretty EName = text "expression name"
pretty TName = text "type name"
pretty PName = text "package name"
pretty LName = text "lock name"
pretty MName = text "method name"
pretty POrTName = text "package or type name"
pretty MOrLName = text "method or lock name"
pretty EOrLName = text "expression or lock name"
pretty AmbName = text "name"
{-
instance Pretty (Name a) where
pretty (Name _ is) =
hcat (punctuate (char '.') $ map pretty is)
pretty (AntiQName _ s) = text "#N#" <> text s
pretty n = pretty (flattenName n)
flattenName :: Name a -> Name a
flattenName n@(Name{}) = n
flattenName n@(AntiQName{}) = n
flattenName n =
let is = reverse $ flName n
in case is of
i:_ -> Name (ann i) is
[] -> panic "flattenName" "empty name"
where flName :: Name a -> [Ident a]
flName (EName _ mPre i) = i : maybe [] flName mPre
flName (MName _ mPre i) = i : maybe [] flName mPre
flName (TName _ mPre i) = i : maybe [] flName mPre
flName (PName _ mPre i) = i : maybe [] flName mPre
flName (LName _ mPre i) = i : maybe [] flName mPre
flName (POrTName _ mPre i) = i : maybe [] flName mPre
flName (MOrLName _ mPre i) = i : maybe [] flName mPre
flName _ = panic "flattenName" ("Malformed name in parser")
-}
instance Pretty (Ident a) where
pretty (Ident _ s) = text $ B.unpack s
pretty (AntiQIdent _ s) = text "#" <> text s
-----------------------------------------------------------------------
-- Help functionality
maybePP :: Pretty a => Maybe a -> Doc
maybePP = maybe empty pretty
opt :: Bool -> Doc -> Doc
opt x a = if x then a else empty
braceBlock :: [Doc] -> Doc
braceBlock xs = char '{'
$+$ nest 2 (vcat xs)
$+$ char '}'
angles :: Doc -> Doc
angles d = char '<' <> d <> char '>'