module Language.Haskell.Liquid.Types.PrettyPrint
(
OkRT
, rtypeDoc
, ppr_rtype
, pprManyOrdered
, pprintLongList
, pprintSymbol
) where
import Prelude hiding (error)
import TypeRep hiding (maybeParen)
import ErrUtils (ErrMsg)
import HscTypes (SourceError)
import SrcLoc
import GHC (Name, Class)
import Var (Var)
import TyCon (TyCon)
import qualified Data.List as L
import qualified Data.HashMap.Strict as M
import Text.PrettyPrint.HughesPJ
import Language.Fixpoint.Misc
import Language.Haskell.Liquid.Misc
import Language.Haskell.Liquid.GHC.Misc
import Language.Fixpoint.Types hiding (Error, SrcSpan, Predicate)
import Language.Haskell.Liquid.Types hiding (sort)
pprManyOrdered :: (PPrint a, Ord a) => Tidy -> String -> [a] -> [Doc]
pprManyOrdered k msg = map ((text msg <+>) . pprintTidy k) . L.sort
pprintLongList :: PPrint a => [a] -> Doc
pprintLongList = brackets . vcat . map pprint
pprintSymbol :: Symbol -> Doc
pprintSymbol x = char '‘' <> pprint x <> char '’'
instance PPrint ErrMsg where
pprintTidy _ = text . show
instance PPrint SourceError where
pprintTidy _ = text . show
instance PPrint Var where
pprintTidy _ = pprDoc
instance PPrint Name where
pprintTidy _ = pprDoc
instance PPrint TyCon where
pprintTidy _ = pprDoc
instance PPrint Type where
pprintTidy _ = pprDoc
instance PPrint Class where
pprintTidy _ = pprDoc
instance Show Predicate where
show = showpp
instance (PPrint t) => PPrint (Annot t) where
pprintTidy k (AnnUse t) = text "AnnUse" <+> pprintTidy k t
pprintTidy k (AnnDef t) = text "AnnDef" <+> pprintTidy k t
pprintTidy k (AnnRDf t) = text "AnnRDf" <+> pprintTidy k t
pprintTidy _ (AnnLoc l) = text "AnnLoc" <+> pprDoc l
instance PPrint a => PPrint (AnnInfo a) where
pprintTidy _ (AI m) = vcat $ map pprAnnInfoBinds $ M.toList m
instance PPrint a => Show (AnnInfo a) where
show = showpp
pprAnnInfoBinds (l, xvs)
= vcat $ map (pprAnnInfoBind . (l,)) xvs
pprAnnInfoBind (RealSrcSpan k, xv)
= xd $$ pprDoc l $$ pprDoc c $$ pprint n $$ vd $$ text "\n\n\n"
where
l = srcSpanStartLine k
c = srcSpanStartCol k
(xd, vd) = pprXOT xv
n = length $ lines $ render vd
pprAnnInfoBind (_, _)
= empty
pprXOT (x, v) = (xd, pprint v)
where
xd = maybe (text "unknown") pprint x
type OkRT c tv r = ( TyConable c
, PPrint tv
, PPrint c
, PPrint r
, Reftable r
, Reftable (RTProp c tv ())
, Reftable (RTProp c tv r)
, RefTypable c tv ()
, RefTypable c tv r
, PPrint (RType c tv r)
, PPrint (RType c tv ())
)
rtypeDoc :: (OkRT c tv r) => Tidy -> RType c tv r -> Doc
rtypeDoc k = ppr_rtype (ppE k) TopPrec
where
ppE Lossy = ppEnvShort ppEnv
ppE Full = ppEnv
ppr_rtype :: (OkRT c tv r) => PPEnv -> Prec -> RType c tv r -> Doc
ppr_rtype bb p t@(RAllT _ _)
= ppr_forall bb p t
ppr_rtype bb p t@(RAllP _ _)
= ppr_forall bb p t
ppr_rtype bb p t@(RAllS _ _)
= ppr_forall bb p t
ppr_rtype _ _ (RVar a r)
= ppTy r $ pprint a
ppr_rtype bb p t@(RFun _ _ _ r)
= ppTy r $ maybeParen p FunPrec $ ppr_rty_fun bb empty t
ppr_rtype bb p (RApp c [t] rs r)
| isList c
= ppTy r $ brackets (ppr_rtype bb p t) <> ppReftPs bb p rs
ppr_rtype bb p (RApp c ts rs r)
| isTuple c
= ppTy r $ parens (intersperse comma (ppr_rtype bb p <$> ts)) <> ppReftPs bb p rs
ppr_rtype bb p (RApp c ts rs r)
| isEmpty rsDoc && isEmpty tsDoc
= ppTy r $ ppT c
| otherwise
= ppTy r $ parens $ ppT c <+> rsDoc <+> tsDoc
where
rsDoc = ppReftPs bb p rs
tsDoc = hsep (ppr_rtype bb p <$> ts)
ppT = ppTyConB bb
ppr_rtype bb p t@(REx _ _ _)
= ppExists bb p t
ppr_rtype bb p t@(RAllE _ _ _)
= ppAllExpr bb p t
ppr_rtype _ _ (RExprArg e)
= braces $ pprint e
ppr_rtype bb p (RAppTy t t' r)
= ppTy r $ ppr_rtype bb p t <+> ppr_rtype bb p t'
ppr_rtype bb p (RRTy e _ OCons t)
= sep [braces (ppr_rsubtype bb p e) <+> "=>", ppr_rtype bb p t]
ppr_rtype bb p (RRTy e r o t)
= sep [ppp (pprint o <+> ppe <+> pprint r), ppr_rtype bb p t]
where
ppe = (hsep $ punctuate comma (ppxt <$> e)) <+> dcolon
ppp = \doc -> text "<<" <+> doc <+> text ">>"
ppxt = \(x, t) -> pprint x <+> ":" <+> ppr_rtype bb p t
ppr_rtype _ _ (RHole r)
= ppTy r $ text "_"
ppTyConB bb
| ppShort bb = text . symbolString . dropModuleNames . symbol . render . ppTycon
| otherwise = ppTycon
ppr_rsubtype bb p e
= pprint_env <+> text "|-" <+> ppr_rtype bb p tl <+> "<:" <+> ppr_rtype bb p tr
where
(el, r) = (init e, last e)
(env, l) = (init el, last el)
tr = snd $ r
tl = snd $ l
pprint_bind (x, t) = pprint x <+> colon <> colon <+> ppr_rtype bb p t
pprint_env = hsep $ punctuate comma (pprint_bind <$> env)
maybeParen :: Prec -> Prec -> Doc -> Doc
maybeParen ctxt_prec inner_prec pretty
| ctxt_prec < inner_prec = pretty
| otherwise = parens pretty
ppExists bb p t
= text "exists" <+> brackets (intersperse comma [ppr_dbind bb TopPrec x t | (x, t) <- zs]) <> dot <> ppr_rtype bb p t'
where (zs, t') = split [] t
split zs (REx x t t') = split ((x,t):zs) t'
split zs t = (reverse zs, t)
ppAllExpr bb p t
= text "forall" <+> brackets (intersperse comma [ppr_dbind bb TopPrec x t | (x, t) <- zs]) <> dot <> ppr_rtype bb p t'
where (zs, t') = split [] t
split zs (RAllE x t t') = split ((x,t):zs) t'
split zs t = (reverse zs, t)
ppReftPs _ _ rs
| all isTauto rs = empty
| not (ppPs ppEnv) = empty
| otherwise = angleBrackets $ hsep $ punctuate comma $ ppr_ref <$> rs
ppr_dbind bb p x t
| isNonSymbol x || (x == dummySymbol)
= ppr_rtype bb p t
| otherwise
= pprint x <> colon <> ppr_rtype bb p t
ppr_rty_fun bb prefix t
= prefix <+> ppr_rty_fun' bb t
ppr_rty_fun' bb (RFun b t t' _)
= ppr_dbind bb FunPrec b t <+> ppr_rty_fun bb arrow t'
ppr_rty_fun' bb t
= ppr_rtype bb TopPrec t
ppr_forall :: (OkRT c tv r) => PPEnv -> Prec -> RType c tv r -> Doc
ppr_forall bb p t = maybeParen p FunPrec $ sep [
ppr_foralls (ppPs bb) (ty_vars trep) (ty_preds trep) (ty_labels trep)
, ppr_clss cls
, ppr_rtype bb TopPrec t'
]
where
trep = toRTypeRep t
(cls, t') = bkClass $ fromRTypeRep $ trep {ty_vars = [], ty_preds = [], ty_labels = []}
ppr_foralls False _ _ _ = empty
ppr_foralls _ [] [] [] = empty
ppr_foralls True αs πs ss = text "forall" <+> dαs αs <+> dπs (ppPs bb) πs <+> ppr_symbols ss <> dot
ppr_clss [] = empty
ppr_clss cs = (parens $ hsep $ punctuate comma (uncurry (ppr_cls bb p) <$> cs)) <+> text "=>"
dαs αs = sep $ pprint <$> αs
dπs _ [] = empty
dπs False _ = empty
dπs True πs = angleBrackets $ intersperse comma $ ppr_pvar_def bb p <$> πs
ppr_symbols :: [Symbol] -> Doc
ppr_symbols [] = empty
ppr_symbols ss = angleBrackets $ intersperse comma $ pprint <$> ss
ppr_cls bb p c ts
= pp c <+> hsep (map (ppr_rtype bb p) ts)
where
pp | ppShort bb = text . symbolString . dropModuleNames . symbol . render . pprint
| otherwise = pprint
ppr_pvar_def :: (OkRT c tv ()) => PPEnv -> Prec -> PVar (RType c tv ()) -> Doc
ppr_pvar_def bb p (PV s t _ xts)
= pprint s <+> dcolon <+> intersperse arrow dargs <+> ppr_pvar_kind bb p t
where
dargs = [ppr_pvar_sort bb p xt | (xt,_,_) <- xts]
ppr_pvar_kind :: (OkRT c tv ()) => PPEnv -> Prec -> PVKind (RType c tv ()) -> Doc
ppr_pvar_kind bb p (PVProp t) = ppr_pvar_sort bb p t <+> arrow <+> ppr_name propConName
ppr_pvar_kind _ _ (PVHProp) = ppr_name hpropConName
ppr_name = text . symbolString
ppr_pvar_sort :: (OkRT c tv ()) => PPEnv -> Prec -> RType c tv () -> Doc
ppr_pvar_sort bb p t = ppr_rtype bb p t
ppr_ref :: (OkRT c tv r) => Ref (RType c tv ()) (RType c tv r) -> Doc
ppr_ref (RProp ss s) = ppRefArgs (fst <$> ss) <+> pprint s
ppRefArgs :: [Symbol] -> Doc
ppRefArgs [] = empty
ppRefArgs ss = text "\\" <> hsep (ppRefSym <$> ss ++ [vv Nothing]) <+> text "->"
ppRefSym "" = text "_"
ppRefSym s = pprint s
dot = char '.'
instance (PPrint r, Reftable r) => PPrint (UReft r) where
pprintTidy k (MkUReft r p _)
| otherwise = pprintTidy k p <> text " & " <> pprintTidy k r