module PprTyThing (
PrintExplicitForalls,
pprTyThing,
pprTyThingInContext,
pprTyThingLoc,
pprTyThingInContextLoc,
pprTyThingHdr,
pprTypeForUser
) where
import qualified GHC
import GHC ( TyThing(..) )
import DataCon
import Id
import TyCon
import Coercion( pprCoAxiom, pprCoAxBranch )
import CoAxiom( CoAxiom(..), brListMap )
import HscTypes( tyThingParent_maybe )
import Type( tidyTopType, tidyOpenType )
import TypeRep( pprTvBndrs )
import TcType
import Name
import VarEnv( emptyTidyEnv )
import StaticFlags( opt_PprStyle_Debug )
import Outputable
import FastString
type PrintExplicitForalls = Bool
type ShowSub = [Name]
showAll :: ShowSub
showAll = []
showSub :: NamedThing n => ShowSub -> n -> Bool
showSub [] _ = True
showSub (n:_) thing = n == getName thing
showSub_maybe :: NamedThing n => ShowSub -> n -> Maybe ShowSub
showSub_maybe [] _ = Just []
showSub_maybe (n:ns) thing = if n == getName thing then Just ns
else Nothing
pprTyThingLoc :: PrintExplicitForalls -> TyThing -> SDoc
pprTyThingLoc pefas tyThing
= showWithLoc (pprDefinedAt (GHC.getName tyThing)) (pprTyThing pefas tyThing)
pprTyThing :: PrintExplicitForalls -> TyThing -> SDoc
pprTyThing pefas thing = ppr_ty_thing pefas showAll thing
pprTyThingInContext :: PrintExplicitForalls -> TyThing -> SDoc
pprTyThingInContext pefas thing
= go [] thing
where
go ss thing = case tyThingParent_maybe thing of
Just parent -> go (getName thing : ss) parent
Nothing -> ppr_ty_thing pefas ss thing
pprTyThingInContextLoc :: PrintExplicitForalls -> TyThing -> SDoc
pprTyThingInContextLoc pefas tyThing
= showWithLoc (pprDefinedAt (GHC.getName tyThing))
(pprTyThingInContext pefas tyThing)
pprTyThingHdr :: PrintExplicitForalls -> TyThing -> SDoc
pprTyThingHdr pefas (AnId id) = pprId pefas id
pprTyThingHdr pefas (ADataCon dataCon) = pprDataConSig pefas dataCon
pprTyThingHdr pefas (ATyCon tyCon) = pprTyConHdr pefas tyCon
pprTyThingHdr _ (ACoAxiom ax) = pprCoAxiom ax
ppr_ty_thing :: PrintExplicitForalls -> ShowSub -> TyThing -> SDoc
ppr_ty_thing pefas _ (AnId id) = pprId pefas id
ppr_ty_thing pefas _ (ADataCon dataCon) = pprDataConSig pefas dataCon
ppr_ty_thing pefas ss (ATyCon tyCon) = pprTyCon pefas ss tyCon
ppr_ty_thing _ _ (ACoAxiom ax) = pprCoAxiom ax
pprTyConHdr :: PrintExplicitForalls -> TyCon -> SDoc
pprTyConHdr pefas tyCon
| Just (fam_tc, tys) <- tyConFamInst_maybe tyCon
= ptext keyword <+> ptext (sLit "instance") <+> pprTypeApp fam_tc tys
| Just cls <- tyConClass_maybe tyCon
= pprClassHdr pefas cls
| otherwise
= ptext keyword <+> opt_family <+> opt_stupid <+> ppr_bndr tyCon <+> pprTvBndrs vars
where
vars | GHC.isPrimTyCon tyCon ||
GHC.isFunTyCon tyCon = take (GHC.tyConArity tyCon) GHC.alphaTyVars
| otherwise = GHC.tyConTyVars tyCon
keyword | GHC.isSynTyCon tyCon = sLit "type"
| GHC.isNewTyCon tyCon = sLit "newtype"
| otherwise = sLit "data"
opt_family
| GHC.isFamilyTyCon tyCon = ptext (sLit "family")
| otherwise = empty
opt_stupid
| isAlgTyCon tyCon = GHC.pprThetaArrowTy (tyConStupidTheta tyCon)
| otherwise = empty
pprDataConSig :: PrintExplicitForalls -> GHC.DataCon -> SDoc
pprDataConSig pefas dataCon
= ppr_bndr dataCon <+> dcolon <+> pprTypeForUser pefas (GHC.dataConType dataCon)
pprClassHdr :: PrintExplicitForalls -> GHC.Class -> SDoc
pprClassHdr _ cls
= ptext (sLit "class") <+>
sep [ GHC.pprThetaArrowTy (GHC.classSCTheta cls)
, ppr_bndr cls <+> pprTvBndrs tyVars
, GHC.pprFundeps funDeps ]
where
(tyVars, funDeps) = GHC.classTvsFds cls
pprId :: PrintExplicitForalls -> Var -> SDoc
pprId pefas ident
= hang (ppr_bndr ident <+> dcolon)
2 (pprTypeForUser pefas (GHC.idType ident))
pprTypeForUser :: PrintExplicitForalls -> GHC.Type -> SDoc
pprTypeForUser print_foralls ty
| print_foralls = ppr tidy_ty
| otherwise = ppr (mkPhiTy ctxt ty')
where
(_, ctxt, ty') = tcSplitSigmaTy tidy_ty
(_, tidy_ty) = tidyOpenType emptyTidyEnv ty
pprTyCon :: PrintExplicitForalls -> ShowSub -> TyCon -> SDoc
pprTyCon pefas ss tyCon
| Just syn_rhs <- GHC.synTyConRhs_maybe tyCon
= case syn_rhs of
OpenSynFamilyTyCon -> pprTyConHdr pefas tyCon <+> dcolon <+>
pprTypeForUser pefas (GHC.synTyConResKind tyCon)
ClosedSynFamilyTyCon (CoAxiom { co_ax_branches = branches }) ->
hang closed_family_header
2 (vcat (brListMap (pprCoAxBranch tyCon) branches))
AbstractClosedSynFamilyTyCon -> closed_family_header <+> ptext (sLit "..")
SynonymTyCon rhs_ty -> hang (pprTyConHdr pefas tyCon <+> equals)
2 (ppr rhs_ty)
| Just cls <- GHC.tyConClass_maybe tyCon
= pprClass pefas ss cls
| otherwise
= pprAlgTyCon pefas ss tyCon
where
closed_family_header
= pprTyConHdr pefas tyCon <+> dcolon <+>
pprTypeForUser pefas (GHC.synTyConResKind tyCon) <+> ptext (sLit "where")
pprAlgTyCon :: PrintExplicitForalls -> ShowSub -> TyCon -> SDoc
pprAlgTyCon pefas ss tyCon
| gadt = pprTyConHdr pefas tyCon <+> ptext (sLit "where") $$
nest 2 (vcat (ppr_trim (map show_con datacons)))
| otherwise = hang (pprTyConHdr pefas tyCon)
2 (add_bars (ppr_trim (map show_con datacons)))
where
datacons = GHC.tyConDataCons tyCon
gadt = any (not . GHC.isVanillaDataCon) datacons
ok_con dc = showSub ss dc || any (showSub ss) (dataConFieldLabels dc)
show_con dc
| ok_con dc = Just (pprDataConDecl pefas ss gadt dc)
| otherwise = Nothing
pprDataConDecl :: PrintExplicitForalls -> ShowSub -> Bool -> GHC.DataCon -> SDoc
pprDataConDecl pefas ss gadt_style dataCon
| not gadt_style = ppr_fields tys_w_strs
| otherwise = ppr_bndr dataCon <+> dcolon <+>
sep [ pp_foralls, GHC.pprThetaArrowTy theta, pp_tau ]
where
(forall_tvs, theta, tau) = tcSplitSigmaTy (GHC.dataConUserType dataCon)
(arg_tys, res_ty) = tcSplitFunTys tau
labels = GHC.dataConFieldLabels dataCon
stricts = GHC.dataConStrictMarks dataCon
tys_w_strs = zip (map user_ify stricts) arg_tys
pp_foralls | pefas = GHC.pprForAll forall_tvs
| otherwise = empty
pp_tau = foldr add (ppr res_ty) tys_w_strs
add str_ty pp_ty = pprParendBangTy str_ty <+> arrow <+> pp_ty
pprParendBangTy (bang,ty) = ppr bang <> GHC.pprParendType ty
pprBangTy (bang,ty) = ppr bang <> ppr ty
user_ify :: HsBang -> HsBang
user_ify bang | opt_PprStyle_Debug = bang
user_ify HsStrict = HsUserBang Nothing True
user_ify (HsUnpack {}) = HsUserBang (Just True) True
user_ify bang = bang
maybe_show_label (lbl,bty)
| showSub ss lbl = Just (ppr_bndr lbl <+> dcolon <+> pprBangTy bty)
| otherwise = Nothing
ppr_fields [ty1, ty2]
| GHC.dataConIsInfix dataCon && null labels
= sep [pprParendBangTy ty1, pprInfixName dataCon, pprParendBangTy ty2]
ppr_fields fields
| null labels
= ppr_bndr dataCon <+> sep (map pprParendBangTy fields)
| otherwise
= ppr_bndr dataCon
<+> (braces $ sep $ punctuate comma $ ppr_trim $
map maybe_show_label (zip labels fields))
pprClass :: PrintExplicitForalls -> ShowSub -> GHC.Class -> SDoc
pprClass pefas ss cls
| null methods && null assoc_ts
= pprClassHdr pefas cls
| otherwise
= vcat [ pprClassHdr pefas cls <+> ptext (sLit "where")
, nest 2 (vcat $ ppr_trim $
map show_at assoc_ts ++ map show_meth methods)]
where
methods = GHC.classMethods cls
assoc_ts = GHC.classATs cls
show_meth id | showSub ss id = Just (pprClassMethod pefas id)
| otherwise = Nothing
show_at tc = case showSub_maybe ss tc of
Just ss' -> Just (pprTyCon pefas ss' tc)
Nothing -> Nothing
pprClassMethod :: PrintExplicitForalls -> Id -> SDoc
pprClassMethod pefas id
= hang (ppr_bndr id <+> dcolon) 2 (pprTypeForUser pefas op_ty)
where
tidy_sel_ty = tidyTopType (GHC.idType id)
(_sel_tyvars, rho_ty) = GHC.splitForAllTys tidy_sel_ty
op_ty = GHC.funResultTy rho_ty
ppr_trim :: [Maybe SDoc] -> [SDoc]
ppr_trim xs
= snd (foldr go (False, []) xs)
where
go (Just doc) (_, so_far) = (False, doc : so_far)
go Nothing (True, so_far) = (True, so_far)
go Nothing (False, so_far) = (True, ptext (sLit "...") : so_far)
add_bars :: [SDoc] -> SDoc
add_bars [] = empty
add_bars [c] = equals <+> c
add_bars (c:cs) = sep ((equals <+> c) : map (char '|' <+>) cs)
ppr_bndr :: GHC.NamedThing a => a -> SDoc
ppr_bndr a = GHC.pprParenSymName a
showWithLoc :: SDoc -> SDoc -> SDoc
showWithLoc loc doc
= hang doc 2 (char '\t' <> comment <+> loc)
where
comment = ptext (sLit "--")