% % (c) The Foo Project, University of Glasgow, 1998 % % @(#) $Docid: Mar. 31th 2003 08:36 Sigbjorn Finne $ % @(#) $Contactid: sof@galois.com $ % Converting the data representing Haskell programs into source form. Apart from the pretty printing of the data constructors of the various data types representing Haskell constructs (see @AbstractH.lhs@), this module also performs the following tasks: - if the user requested that names shouldn't be qualified, obey this when outputting VarNames. - choose the right FFI to do call-outs (and call-ins). The options (all controllable from the command line) are one of: "new FFI", ghc FFI, or GreenCard stubs. \begin{code} module PpAbstractH ( ppHTopDecls , ppType , showAbstractH , ppExpr ) where import PP hiding ( integer ) import AbstractH import AbsHUtils ( splitFunTys, isVarPat, tyInt32 ) import Opts ( optGreenCard, optTargetGhc, optNoQualNames , optNoOutput, optNoModuleHeader, optNoImports , optQualInstanceMethods, optHugs , optUnsafeCalls, optNoDllName , optPatternAsLambda , optLongLongIsInteger ) import Literal import BasicTypes import Char ( isAlpha ) import Utils ( notNull ) import LibUtils \end{code} \begin{code} type AbsHDoc a = PPDoc a showAbstractH :: AbsHDoc a -> String showAbstractH ad = showPPDoc ad undefined \end{code} \begin{code} ppHTopDecls :: [HTopDecl] -> AbsHDoc a ppHTopDecls ls = vcat (map ppHTopDecl ls) ppHTopDecl :: HTopDecl -> AbsHDoc a ppHTopDecl (HMod hm) = ppHModule hm ppHTopDecl (HLit s) = text s ppHTopDecl (CLit _) = empty ppHTopDecl (HInclude s) | optGreenCard = text "%include" <+> text s -- Only GHC understands this pragma, but its presence shouldn't -- seriously offend anyone else... | otherwise = text "{-# OPTIONS -#include" <+> text str <+> text "#-}" where -- make sure we escape those double quotes. str = case s of '<':_ -> s '"':_ -> s _ -> show s \end{code} \begin{code} ppHModule :: HModule -> AbsHDoc a ppHModule (HModule nm flg exports imports decls) = (if optNoModuleHeader then empty else (case exports of [] -> text "module" <+> ppName nm <+> text "where" $$ text "" _ -> hang (text "module" <+> ppName nm) 7 (vsep (zipWith (\ x y -> x <+> ppExport y) (char '(':repeat comma) --) exports) $$ text ") where" $$ text ""))) $$ (if optNoImports then empty else vsep (map ppImport imports')) $$ text "" $$ ppHDecl decls $$ if (optHugs && flg) then text "needPrims_hugs 4" else text "" where generateGreenCard = not optNoOutput && optGreenCard imports' | not generateGreenCard = imports | otherwise = ((HImport False Nothing ("StdDIS") Nothing):imports) ppExport :: HExport -> AbsHDoc a ppExport (HExport expo comment) = ppIEEntity expo <+> ppComment comment where -- one-line comment ppComment Nothing = empty ppComment (Just c) = text "--" <+> text c ppIEEntity :: HIEEntity -> AbsHDoc a ppIEEntity (IEModule nm) = text "module" <+> ppName nm ppIEEntity (IEVal nm) = ppName nm ppIEEntity (IEClass c) = ppName c ppIEEntity (IEType nm isAbs) = ppName nm <> if isAbs then empty else text "(..)" ppImport :: HImport -> AbsHDoc a ppImport (HImport qual as_name nm stuff) = text "import" <+> (if qual && not optNoQualNames then text "qualified" else empty) <+> (case as_name of { Nothing -> empty ; Just a -> text "as" <+> ppName a} ) <+> ppName nm <+> case stuff of Nothing -> empty Just ls -> parens (fcat (punctuate (text ", ") (map ppIEEntity ls))) \end{code} \begin{code} ppHDecl :: HDecl -> AbsHDoc a ppHDecl (AndDecl d1 d2) = ppHDecl d1 $$ ppHDecl d2 ppHDecl (TypeSig i mb_ctxt t) = ppName i <+> vcat pp_sig {- One-line style: ppName i <+> text "::" <+> (case mb_ctxt of Nothing -> empty Just ct -> ppContext True ct) <+> ppType t -} where (args,res) = splitFunTys t pp_tys = pp_ctxt (map ppFunType (args ++ [res])) pp_sig = zipWith (<+>) seps pp_tys pp_ctxt rest = case mb_ctxt of Nothing -> rest Just x -> ppContext False x : rest seps = text "::" : case mb_ctxt of Nothing -> arrows Just _ -> text "=>" : arrows arrows = text "->" : arrows ppHDecl (ValDecl i [p1,p2] ges) | isOpName i = (ppPat p1 <+> ppValName i <+> ppPat p2) $$ (nest 2 (ppGuardedExprs ges)) $$ text "" ppHDecl (ValDecl i pats [g]) | isSimple g = sep [ppValName i <+> pp_pats, nest 2 (ppGuardedExpr (char '=') g)] $$ text "" | otherwise = hang (ppValName i <+> pp_pats) 2 (ppGuardedExpr (char '=') g) $$ text "" where shufflePats = optPatternAsLambda && all isVarPat pats pp_pats | shufflePats = equals <+> hsep (map (\ x -> char '\\' <+> ppPat x <+> text "->") pats) | otherwise = hsep (map ppPat pats) <+> equals isSimple (GExpr _ (Bind _ _ _)) = False isSimple (GExpr _ (Bind_ _ _)) = False isSimple (GExpr _ (Let _ _)) = False isSimple _ = True ppHDecl (ValDecl i pats ges) = (ppValName i <+> hsep (map ppPat pats)) $$ (nest 2 (ppGuardedExprs ges)) $$ text "" ppHDecl (Primitive safe cconv (dllname,_,fun,_) i t has_structs _ _) | optTargetGhc = -- GHC specific (ppName i <+> text "::" <+> ppType t) $$ ppName i <+> hsep arg_names <+> equals <+> text "_ccall_" <+> hsep (text fun:arg_names) | optGreenCard = -- GreenCard output (text "%fun" <+> ppName i <+> text "::" <+> ppType t') $$ text "%code" <+> assignRes <+> text fun <> ppTuple (arg_names) | optHugs = text "primitive" <+> ppName i <+> text "::" <+> ppType t' | otherwise = -- FFI decls. text "foreign import" <+> ppCallConv False cconv <+> -- this is not quite right in the case of Hugs, -- since we will need to supply the name of the stub DLL. (if (null dllname || has_structs || optNoDllName) then empty else text (show dllname)) <+> let fun_name | has_structs = doubleQuotes (ppName i) | otherwise = text (show fun) in fun_name <+> (if optUnsafeCalls || not safe then text "unsafe" else empty) <+> ppName i <+> text "::" <+> ppType t where {- We keep the illusion that Integers are valid FFI types on the Hugs side right until the very last, when we expand out an Integer into a pair of Int32 arguments and results. -} t' | optLongLongIsInteger = expandIntegers t | otherwise = t -- Use the next line instead if you haven't go the latest -- GC sources (i.e., ones which support qualified names). -- t' = unqualTy t assignRes = case res of TyApply _{-io-} [(TyCon tc)] -> case qName tc of "()" -> empty _ -> text "res1 =" _ -> empty (args,res) = splitFunTys t arg_names = zipWith (\ arg _ -> text ("arg" ++ show arg)) [(1::Int)..] args ppHDecl (PrimCast cconv i ty has_structs args res_ty) | optGreenCard = text "" $$ text "%fun" <+> ppName i <+> text "::" <+> ppType ty' $$ text "%code" $$ vsepPrefix (text "% ") [ ppDeclResult , text "typedef" <+> ppResultType <+> parens ( text "__" <> ppCallConv True cconv <+> char '*' <+> text "__funptr") <+> ppTuple ppArgs <> semi , text "__funptr" <+> ppName i <> semi , ppName i <+> equals <+> text "(__funptr)arg1" <> semi , ppAssignResult <+> ppName i <> ppTuple ppCasmArgs <> semi ] $$ text "" | optHugs = text "primitive" <+> ppName i <+> text "::" <+> ppType ty' | optTargetGhc = ppName i <+> text "::" <+> ppType ty $$ ppName i <+> hsep params <+> equals <+> text "_casm_" <+> ppLitLit ( ppDeclResult $$ text "typedef" <+> ppResultType <+> parens ( text "__" <> ppCallConv True cconv <+> char '*' <+> text "__funptr") <+> ppTuple ppArgs <> semi $$ text "__funptr" <+> ppName i <> semi $$ ppName i <+> equals <+> text "(__funptr)%0" <> semi $$ ppAssignResult <+> ppName i <> ppTuple ppMethArgs <> semi $$ ppReturnResult <> semi) <+> hsep params | otherwise = text "foreign import" <+> ppCallConv False cconv <+> (if has_structs then text (show i) else text "\"dynamic\"") <+> (if optUnsafeCalls then text "unsafe" else empty) <+> ppName i <+> text "::" <+> ppType ty where ppLitLit x = text "``" <> x <> text "\'\'" ty' | optLongLongIsInteger = expandIntegers ty | otherwise = ty -- Use the next line instead if you haven't go the latest -- GC sources (i.e., ones which support qualified names). --ty' = unqualTy ty params = map (\ x -> text ('a':show x)) [1..(length args)] ppMethArgs = map (\ x -> text ('%':show x)) (tail [0..(length args - 1)]) ppCasmArgs = map (\ x -> text ("arg"++show x)) [2..(length args)] ppArgs = map (\ (x, arg_ty) -> text (snd arg_ty) <+> text ('a':show x)) (zip [(1::Int)..] (tail args)) (ppDeclResult, ppResultType, ppAssignResult, ppReturnResult) = case res_ty of (_,"void") -> ( empty, text "void", empty, empty ) (_,res) -> ( text res <+> text "res1" <> semi , text res , text "res1" <+> equals , text "%r=res1" ) ppHDecl (Entry cconv ci hi t) = text "foreign export" <+> ppCallConv False cconv <+> text (show ci) <+> ppName hi <+> text "::" <+> ppType t ppHDecl (Callback cconv i t) = text "foreign export" <+> ppCallConv False cconv <+> text "dynamic" <+> ppName i <+> text "::" <+> ppType t ppHDecl (ExtLabel c_name h_name t) = text "foreign label" <+> text (show c_name) <+> text h_name <+> text "::" <+> ppType t ppHDecl (TyD td) = ppTyDecl td ppHDecl (Class ctxt cname tvrs decls) = hang (text "class" <+> ppContext True ctxt <+> ppQName cname <+> hsep (map ppTyVar tvrs) <+> if (notNull decls) then text "where" else empty) 2 (vsep (map ppHDecl decls)) ppHDecl (Instance ctxt cname t decls) = hang (text "instance" <+> ppContext True ctxt <+> ppQName cname <+> parens (ppType t) <+> if (notNull decls) then text "where" else empty) 2 (vsep (map ppHDecl decls)) ppHDecl (Include s) | optGreenCard = text "%#include" <+> text s | otherwise = empty ppHDecl (Haskell s) = text s ppHDecl (CCode s) = text "{- BEGIN_C_CODE" $$ text s $$ text "END_C_CODE-}" ppHDecl EmptyDecl = empty \end{code} \begin{code} expandIntegers :: Type -> Type expandIntegers (TyFun t1@(TyCon t) t2) | qName t == "Integer" = TyFun tyInt32 (TyFun tyInt32 (expandIntegers t2)) | otherwise = TyFun t1 (expandIntegers t2) expandIntegers (TyFun t1 t2) = TyFun (expandIntegers t1) (expandIntegers t2) expandIntegers t@(TyApply (TyCon tc) [(TyCon x)]) | qName tc == "IO" && qName x == "Integer" = TyApply (TyCon tc) [TyTuple [tyInt32, tyInt32]] | otherwise = t expandIntegers t = t \end{code} \begin{code} ppPat :: Pat -> AbsHDoc a ppPat (PatVar v) = ppVarName v ppPat (PatLit v) = ppLit v ppPat PatWildCard = char '_' ppPat (PatTuple pats) = ppTuple (map ppPat pats) ppPat (PatAs v p) = ppVarName v <> char '@' <> parens (ppPat p) ppPat (PatCon v []) = ppVarName v ppPat (PatCon v pats) = parens (ppVarName v <+> hsep (map ppPat pats)) ppPat (PatList pats) = ppList (map ppPat pats) ppPat (PatIrrefut p) = char '~' <> parens (ppPat p) ppPat (PatRecord v fields) = ppVarName v <> braces (hsep (punctuate comma (map ppField fields))) where ppField (var,p) = ppVarName var <+> equals <+> ppPat p ppCaseAlt :: CaseAlt -> AbsHDoc a ppCaseAlt (Alt p [GExpr [] e]) = ppPat p <+> text "->" <+> ppExpr e ppCaseAlt (Alt p ls) = hang (ppPat p) 2 (vsep (map (ppGuardedExpr (text "->")) ls)) ppCaseAlt (Default mb_v e) = pp_v <+> text "->" <+> ppExpr e where pp_v = case mb_v of Nothing -> char '_' ; Just v -> ppVarName v \end{code} \begin{code} type ExprDoc = PPDoc (Bool,Bool) ifTop :: (ExprDoc -> ExprDoc ) -> (ExprDoc -> ExprDoc ) -> ExprDoc -> ExprDoc ifTop onTrueF onFalseF d = getPPEnv $ \ (top,flg) -> setPPEnv (False,flg) $ if top then onTrueF d else onFalseF d ifOnTop :: ExprDoc -> ExprDoc -> ExprDoc ifOnTop ifIs ifIsn't = getPPEnv $ \ (top,flg) -> setPPEnv (False,flg) $ if top then ifIs else ifIsn't ifDo :: ExprDoc -> ExprDoc -> ExprDoc ifDo onTrue onFalse = getPPEnv $ \ (_,flg) -> if flg then onTrue else onFalse setDo :: Bool -> ExprDoc -> ExprDoc setDo flg d = getPPEnv $ \ (top,_) -> setPPEnv (top,flg) d setTop :: Bool -> ExprDoc -> ExprDoc setTop flg d = getPPEnv $ \ (_,dof) -> setPPEnv (flg,dof) d \end{code} \begin{code} ppExpr :: Expr -> PPDoc a ppExpr e = setPPEnv (True, False) (ppExprDo e) ppExprDo :: Expr -> ExprDoc ppExprDo (Lit l) = ppLit l ppExprDo (Var v) = ppVarName v ppExprDo (Con v) = ppConName v ppExprDo (Lam [] e) = ppExprDo e ppExprDo (Lam pats e) = char '\\' <+> hsep (map ppPat pats) <+> text "->" <+> setDo False (ppExprDo e) ppExprDo (Apply (Apply e args1) args2) = ppExprDo (Apply e (args1++args2)) ppExprDo (Apply e []) = ppExprDo e ppExprDo (Apply e@(Lam _ _) args) = parens (ppExprDo e) <+> hsep (map ppArg args) ppExprDo (Apply e args) = ifOnTop (ppExprDo e <+> vsep (map ppArg args)) (ppExprDo e <+> hsep (map ppArg args)) ppExprDo (RApply e1 (Lam pats e2)) = ppExprDo e1 <+> ppVarName dollarName <+> char '\\' <+> hsep (map ppPat pats) <+> text "->" $$ ppExprDo e2 ppExprDo (RApply e1 e2) = ppExprDo e1 <+> ppVarName dollarName <+> ppExprDo e2 ppExprDo (Tup args) = ppTuple (map ppExprDo args) ppExprDo (List elts) = ppListVert (map ppExprDo elts) ppExprDo (InfixOp e1 op e2) = ppExprDo e1 <+> ppr_op <+> ppExprDo e2 where ppr_op | not (isOpName op) = ppVarName op | otherwise = char '`' <> ppVarName op <> char '`' ppExprDo (BinOp bop e1 e2) = parens ( ppExprDo e1 <+> ppBinOp bop <+> ppExprDo e2) ppExprDo (UnOp uop e) = parens ( ppUnOp uop <+> ppExprDo e) ppExprDo (Bind m p n) = ifTop (\ d -> hang (text "do") 2 (setDo True d)) (id) (ifDo ((ppPat p <+> text "<-" <+> ppExprDo m) $$ ppExprDo n) (hang (ppExprDo m <+> ppQualName bindName <+> char '\\' <+> ppPat p <+> text "->") 0 (ppExprDo n))) -- this assumes that m has type "M ()", which is the -- case for HaskellDirect. ToDo: Record return type -- for the left arg to a bind, so that we can make sure -- that this is really the case. -- ppExprDo (Bind_ m (Return (Tup []))) = ppExprDo m ppExprDo (Bind_ m n) = ifTop (\ d -> hang (text "do") 2 (setDo True d)) (id) (ifDo ((ppExprDo m) $$ ppExprDo n) (hang (ppExprDo m <+> ppQualName bind_Name) 0 (ppExprDo n))) ppExprDo (Return e@(Tup _)) = ppQualName prelReturn <+> ppExprDo e ppExprDo (Return e) = ppQualName prelReturn <+> parens (ppExprDo e) ppExprDo (If c e1 e2) = hang (text "if" <+> ppExprDo c) 2 (text "then" <+> ppExprDo e1 $$ text "else" <+> ppExprDo e2) ppExprDo (Case e alts) = hang (text "case" <+> ppExprDo e <+> text "of") 3 (vsep (map ppCaseAlt alts)) ppExprDo (Let [] e) = ppExprDo e ppExprDo (Let binders (Let binders2 e)) = ppExprDo (Let (binders++binders2) e) ppExprDo (Let binders e) = ifDo ((text "let" <+> (vsep (map ppBinding binders))) $$ ppExprDo e) ((hang (text "let") 1 (vsep (map ppBinding binders))) $$ text "in" $$ ppExprDo e) ppExprDo (WithTy e ty) = parens (ppExprDo e <+> text "::" <+> ppType ty) \end{code} Expressions in argument position - leave out as many parens as possible: \begin{code} ppArg :: Expr -> ExprDoc ppArg (Lit l) = ppLit l ppArg (Var v) = ppVarName v ppArg (Con v) = ppConName v ppArg e@(Tup _) = ppExprDo e ppArg e@(List _) = ppExprDo e ppArg e = parens (ppExprDo e) \end{code} \begin{code} ppBinding :: Binding -> ExprDoc ppBinding (Binder v e) = ppName v <+> equals <+> setTop False (ppExprDo e) ppBinOp :: BinaryOp -> PPDoc a ppBinOp op = case op of Xor -> ppQName xorName Or -> ppQName orName And -> ppQName andName Shift d -> ppQOp (case d of { L -> shiftLName ; R -> shiftRName }) Add -> ppQName addName Sub -> ppQName subName Div -> ppQOp divName Mod -> ppQOp modName Mul -> ppQName mulName LogAnd -> ppQName logAndName LogOr -> ppQName logOrName Gt -> ppQName gtName Ge -> ppQName geName Eq -> ppQName eqName Le -> ppQName leName Lt -> ppQName ltName Ne -> ppQName neName ppUnOp :: UnaryOp -> PPDoc a ppUnOp op = case op of Minus -> ppQName negateName Plus -> ppQName addName Not -> ppQName complementName Negate -> ppQName notName Deref -> empty \end{code} \begin{code} ppType :: Type -> AbsHDoc a ppType ty = setPPEnv top_prec (ppTypePrec ty) ppFunType :: Type -> AbsHDoc a ppFunType ty = setPPEnv fun_prec (ppTypePrec ty) ppConType :: Type -> AbsHDoc a ppConType ty = setPPEnv tycon_prec (ppTypePrec ty) type TypeDoc = PPDoc Int setPrec :: Int -> TypeDoc -> TypeDoc setPrec = setPPEnv gePrec :: Int -> TypeDoc -> TypeDoc -> TypeDoc gePrec prec onTrue onFalse = getPPEnv $ \ val -> if val >= prec then onTrue else onFalse ppTypePrec :: Type -> TypeDoc ppTypePrec (TyVar _ tv) = ppTyVar tv ppTypePrec (TyCon tc) = ppTyCon tc ppTypePrec (TyApply con []) = ppTypePrec con ppTypePrec (TyApply con args) = mbParen tycon_prec (setPrec tycon_prec $ hsep (map ppTypePrec (con:args))) ppTypePrec (TyList t) = brackets (setPrec top_prec (ppTypePrec t)) ppTypePrec (TyTuple ts) = setPrec top_prec (ppTuple (map ppTypePrec ts)) ppTypePrec (TyCtxt ctxt t) = ppContext True ctxt <+> ppTypePrec t ppTypePrec (TyFun a b) = mbParen fun_prec ((setPrec fun_prec (ppTypePrec a)) <+> text "->" <+> setPrec top_prec (ppTypePrec b)) mbParen :: Int -> TypeDoc -> TypeDoc mbParen new_prec d = gePrec new_prec (parens d) d top_prec, fun_prec, tycon_prec :: Int top_prec = (0::Int) fun_prec = (1::Int) tycon_prec = (2::Int) ppVarName :: VarName -> PPDoc a ppVarName v = ppQName v ppConName :: ConName -> PPDoc a ppConName cn = ppQName cn ppTyVar :: TyVar -> PPDoc a ppTyVar tv = ppQName tv ppTyCon :: TyCon -> PPDoc a ppTyCon s = ppQName s ppQName :: QualName -> PPDoc a ppQName = ppQualName ppQOp :: QualName -> PPDoc a ppQOp op = char '`' <> ppQualName op <> char '`' {- = Con_1 ... | Con_2 ... ... -} ppConDecls :: [ConDecl] -> AbsHDoc a ppConDecls [] = error "ppConDecls: shouldn't happen, invalid Haskell." ppConDecls (dcon:dcons) = vsep ( (equals <+> ppConDecl dcon) : (map (\ dc -> text "|" <+> ppConDecl dc) dcons)) ppConDecl :: ConDecl -> AbsHDoc a ppConDecl (RecDecl nm fields) | null fields = ppName nm | otherwise = ppName nm <+> braces (vsep (punctuate comma (map ppField fields))) where ppField (v, t) = ppName v <+> text "::" <+> ppBangType t ppConDecl (ConDecl nm args) = ppName nm <+> hsep (map ppBangType args) ppBangType :: BangType -> AbsHDoc a ppBangType (Banged ty) = char '!' <> setPPEnv tycon_prec (ppTypePrec ty) ppBangType (Unbanged ty) = setPPEnv tycon_prec (ppTypePrec ty) \end{code} \begin{code} ppContext :: Bool -> Context -> AbsHDoc a ppContext _ (CtxtTuple []) = empty ppContext withDArrow (CtxtTuple ts) = ppTuple (map (ppContext False) ts) <+> (if withDArrow then text "=>" else empty) ppContext withDArrow (CtxtClass c ts) = ppQName c <+> hsep (map ppConType ts) <+> (if withDArrow then text "=>" else empty) ppTyDeclKind :: TyDeclKind -> AbsHDoc a ppTyDeclKind Newtype = text "newtype" ppTyDeclKind Data = text "data" \end{code} \begin{code} vsepPrefix :: PPDoc a -> [PPDoc a] -> PPDoc a vsepPrefix pre ls = vsep (map ((<>) pre) ls) {- UNUSED: unqualTy :: Type -> Type unqualTy t = case t of TyVar f tv -> TyVar f (unqualName tv) TyCon tc -> TyCon (unqualName tc) TyApply f args -> TyApply (unqualTy f) (map unqualTy args) TyList tl -> TyList (unqualTy tl) TyTuple ts -> TyTuple (map unqualTy ts) TyCtxt c t1 -> TyCtxt c (unqualTy t1) TyFun a b -> TyFun (unqualTy a) (unqualTy b) where unqualName qv = qv{qModule=Nothing,qDefModule=Nothing} -} \end{code} \begin{code} ppGuardedExprs :: [GuardedExpr] -> AbsHDoc a ppGuardedExprs [] = empty -- bogus, but we won't flag this fact here. ppGuardedExprs [(GExpr [] e)] = equals <+> (ppExpr e) ppGuardedExprs ls = vcat (map (\ (GExpr gs e) -> text "|" <+> hsep (punctuate comma (map ppExpr gs)) <+> equals <+> (ppExpr e)) ls) ppGuardedExpr :: AbsHDoc a -> GuardedExpr -> AbsHDoc a ppGuardedExpr _ (GExpr [] e) = ppExpr e ppGuardedExpr sepr (GExpr gs e) = text "|" <+> hsep (punctuate comma (map ppExpr gs)) <+> sepr <+> ppExpr e \end{code} \begin{code} ppTyDecl :: TyDecl -> AbsHDoc a ppTyDecl (TypeSyn nm args ty) = text "type" <+> hsep (map text (nm:args)) <+> equals <+> ppType ty ppTyDecl (TyDecl Data tycon ty_args [con_decl] derivs) = ppTyDeclKind Data <+> ppName tycon <+> hsep (map text ty_args) <+> equals <+> hang (ppConDecl con_decl) 2 (ppDeriving derivs) ppTyDecl (TyDecl kind tycon ty_args con_decls derivs) = hang (ppTyDeclKind kind <+> ppName tycon <+> hsep (map text ty_args)) 1 (ppConDecls con_decls $$ -- nb: ppConDecls insert the '=' ppDeriving derivs) \end{code} \begin{code} ppDeriving :: [QualName] -> AbsHDoc a ppDeriving [] = text "" -- want a new line ppDeriving ds = text "deriving" <+> ppTuple (map ppQName ds) <> text "" \end{code} \begin{code} ppValName :: QualName -> AbsHDoc a ppValName i | not optQualInstanceMethods = ppName (qName i) | otherwise = ppQName i \end{code} \begin{code} isOpName :: QualName -> Bool isOpName q = case qName q of "" -> False (n:_) -> not (isAlpha n) && n /= '_' \end{code}