%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 19921998
%
\section[HsBinds]{Abstract syntax: toplevel bindings and signatures}
Datatype for: @BindGroup@, @Bind@, @Sig@, @Bind@.
\begin{code}
module HsBinds where
import HsExpr ( HsExpr, pprExpr, LHsExpr,
MatchGroup, pprFunBind,
GRHSs, pprPatBind )
import HsPat ( LPat )
import HsTypes
import PprCore ()
import Coercion
import Type
import Name
import NameSet
import BasicTypes
import Outputable
import SrcLoc
import Util
import Var
import Bag
import FastString
\end{code}
%************************************************************************
%* *
\subsection{Bindings: @BindGroup@}
%* *
%************************************************************************
Global bindings (where clauses)
\begin{code}
type HsLocalBinds id = HsLocalBindsLR id id
data HsLocalBindsLR idL idR
= HsValBinds (HsValBindsLR idL idR)
| HsIPBinds (HsIPBinds idR)
| EmptyLocalBinds
type HsValBinds id = HsValBindsLR id id
data HsValBindsLR idL idR
= ValBindsIn
(LHsBindsLR idL idR) [LSig idR]
| ValBindsOut
[(RecFlag, LHsBinds idL)]
[LSig Name]
type LHsBinds id = Bag (LHsBind id)
type DictBinds id = LHsBinds id
type LHsBind id = Located (HsBind id)
type HsBind id = HsBindLR id id
type LHsBindLR idL idR = Located (HsBindLR idL idR)
type LHsBindsLR idL idR = Bag (LHsBindLR idL idR)
data HsBindLR idL idR
=
FunBind {
fun_id :: Located idL,
fun_infix :: Bool,
fun_matches :: MatchGroup idR,
fun_co_fn :: HsWrapper,
bind_fvs :: NameSet,
fun_tick :: Maybe (Int,[idR])
}
| PatBind {
pat_lhs :: LPat idL,
pat_rhs :: GRHSs idR,
pat_rhs_ty :: PostTcType,
bind_fvs :: NameSet
}
| VarBind {
var_id :: idL,
var_rhs :: LHsExpr idR
}
| AbsBinds {
abs_tvs :: [TyVar],
abs_dicts :: [DictId],
abs_exports :: [([TyVar], idL, idL, [LPrag])],
abs_binds :: LHsBinds idL
}
placeHolderNames :: NameSet
placeHolderNames = panic "placeHolderNames"
instance (OutputableBndr idL, OutputableBndr idR) => Outputable (HsLocalBindsLR idL idR) where
ppr (HsValBinds bs) = ppr bs
ppr (HsIPBinds bs) = ppr bs
ppr EmptyLocalBinds = empty
instance (OutputableBndr idL, OutputableBndr idR) => Outputable (HsValBindsLR idL idR) where
ppr (ValBindsIn binds sigs)
= pprValBindsForUser binds sigs
ppr (ValBindsOut sccs sigs)
= getPprStyle $ \ sty ->
if debugStyle sty then
vcat (map ppr sigs) $$ vcat (map ppr_scc sccs)
else
pprValBindsForUser (unionManyBags (map snd sccs)) sigs
where
ppr_scc (rec_flag, binds) = pp_rec rec_flag <+> pprLHsBinds binds
pp_rec Recursive = ptext (sLit "rec")
pp_rec NonRecursive = ptext (sLit "nonrec")
pprValBindsForUser :: (OutputableBndr idL, OutputableBndr idR, OutputableBndr id2)
=> LHsBindsLR idL idR -> [LSig id2] -> SDoc
pprValBindsForUser binds sigs
= pprDeeperList vcat (map snd (sort_by_loc decls))
where
decls :: [(SrcSpan, SDoc)]
decls = [(loc, ppr sig) | L loc sig <- sigs] ++
[(loc, ppr bind) | L loc bind <- bagToList binds]
sort_by_loc decls = sortLe (\(l1,_) (l2,_) -> l1 <= l2) decls
pprLHsBinds :: (OutputableBndr idL, OutputableBndr idR) => LHsBindsLR idL idR -> SDoc
pprLHsBinds binds
| isEmptyLHsBinds binds = empty
| otherwise = lbrace <+> pprDeeperList vcat (map ppr (bagToList binds)) <+> rbrace
emptyLocalBinds :: HsLocalBindsLR a b
emptyLocalBinds = EmptyLocalBinds
isEmptyLocalBinds :: HsLocalBindsLR a b -> Bool
isEmptyLocalBinds (HsValBinds ds) = isEmptyValBinds ds
isEmptyLocalBinds (HsIPBinds ds) = isEmptyIPBinds ds
isEmptyLocalBinds EmptyLocalBinds = True
isEmptyValBinds :: HsValBindsLR a b -> Bool
isEmptyValBinds (ValBindsIn ds sigs) = isEmptyLHsBinds ds && null sigs
isEmptyValBinds (ValBindsOut ds sigs) = null ds && null sigs
emptyValBindsIn, emptyValBindsOut :: HsValBindsLR a b
emptyValBindsIn = ValBindsIn emptyBag []
emptyValBindsOut = ValBindsOut [] []
emptyLHsBinds :: LHsBindsLR idL idR
emptyLHsBinds = emptyBag
isEmptyLHsBinds :: LHsBindsLR idL idR -> Bool
isEmptyLHsBinds = isEmptyBag
plusHsValBinds :: HsValBinds a -> HsValBinds a -> HsValBinds a
plusHsValBinds (ValBindsIn ds1 sigs1) (ValBindsIn ds2 sigs2)
= ValBindsIn (ds1 `unionBags` ds2) (sigs1 ++ sigs2)
plusHsValBinds (ValBindsOut ds1 sigs1) (ValBindsOut ds2 sigs2)
= ValBindsOut (ds1 ++ ds2) (sigs1 ++ sigs2)
\end{code}
What AbsBinds means
~~~~~~~~~~~~~~~~~~~
AbsBinds tvs
[d1,d2]
[(tvs1, f1p, f1m),
(tvs2, f2p, f2m)]
BIND
means
f1p = /\ tvs -> \ [d1,d2] -> letrec DBINDS and BIND
in fm
gp = ...same again, with gm instead of fm
This is a pretty bad translation, because it duplicates all the bindings.
So the desugarer tries to do a better job:
fp = /\ [a,b] -> \ [d1,d2] -> case tp [a,b] [d1,d2] of
(fm,gm) -> fm
..ditto for gp..
tp = /\ [a,b] -> \ [d1,d2] -> letrec DBINDS and BIND
in (fm,gm)
\begin{code}
instance (OutputableBndr idL, OutputableBndr idR) => Outputable (HsBindLR idL idR) where
ppr mbind = ppr_monobind mbind
ppr_monobind :: (OutputableBndr idL, OutputableBndr idR) => HsBindLR idL idR -> SDoc
ppr_monobind (PatBind { pat_lhs = pat, pat_rhs = grhss }) = pprPatBind pat grhss
ppr_monobind (VarBind { var_id = var, var_rhs = rhs }) = pprBndr CaseBind var <+> equals <+> pprExpr (unLoc rhs)
ppr_monobind (FunBind { fun_id = fun, fun_infix = inf,
fun_matches = matches,
fun_tick = tick })
= pprTicks empty (case tick of
Nothing -> empty
Just t -> text "-- tick id = " <> ppr t)
$$ pprFunBind (unLoc fun) inf matches
ppr_monobind (AbsBinds { abs_tvs = tyvars, abs_dicts = dictvars,
abs_exports = exports, abs_binds = val_binds })
= sep [ptext (sLit "AbsBinds"),
brackets (interpp'SP tyvars),
brackets (interpp'SP dictvars),
brackets (sep (punctuate comma (map ppr_exp exports)))]
$$
nest 2 ( vcat [pprBndr LetBind x | (_,x,_,_) <- exports]
$$ pprLHsBinds val_binds )
where
ppr_exp (tvs, gbl, lcl, prags)
= vcat [ppr gbl <+> ptext (sLit "<=") <+> ppr tvs <+> ppr lcl,
nest 2 (vcat (map (pprPrag gbl) prags))]
\end{code}
\begin{code}
pprTicks :: SDoc -> SDoc -> SDoc
pprTicks pp_no_debug pp_when_debug
= getPprStyle (\ sty -> if debugStyle sty then pp_when_debug
else pp_no_debug)
\end{code}
%************************************************************************
%* *
Implicit parameter bindings
%* *
%************************************************************************
\begin{code}
data HsIPBinds id
= IPBinds
[LIPBind id]
(DictBinds id)
isEmptyIPBinds :: HsIPBinds id -> Bool
isEmptyIPBinds (IPBinds is ds) = null is && isEmptyBag ds
type LIPBind id = Located (IPBind id)
data IPBind id
= IPBind
(IPName id)
(LHsExpr id)
instance (OutputableBndr id) => Outputable (HsIPBinds id) where
ppr (IPBinds bs ds) = pprDeeperList vcat (map ppr bs)
$$ pprLHsBinds ds
instance (OutputableBndr id) => Outputable (IPBind id) where
ppr (IPBind id rhs) = pprBndr LetBind id <+> equals <+> pprExpr (unLoc rhs)
\end{code}
%************************************************************************
%* *
\subsection{Coercion functions}
%* *
%************************************************************************
\begin{code}
data HsWrapper
= WpHole
| WpCompose HsWrapper HsWrapper
| WpCast Coercion
| WpApp Var
| WpTyApp Type
| WpLam Var
| WpTyLam TyVar
| WpInline
| WpLet (LHsBinds Id)
instance Outputable HsWrapper where
ppr co_fn = pprHsWrapper (ptext (sLit "<>")) co_fn
pprHsWrapper :: SDoc -> HsWrapper -> SDoc
pprHsWrapper it wrap =
let
help it WpHole = it
help it (WpCompose f1 f2) = help (help it f2) f1
help it (WpCast co) = sep [it, nest 2 (ptext (sLit "`cast`") <+> pprParendType co)]
help it (WpApp id) = sep [it, nest 2 (ppr id)]
help it (WpTyApp ty) = sep [it, ptext (sLit "@") <+> pprParendType ty]
help it (WpLam id) = sep [ptext (sLit "\\") <> pprBndr LambdaBind id <> dot, it]
help it (WpTyLam tv) = sep [ptext (sLit "/\\") <> pprBndr LambdaBind tv <> dot, it]
help it (WpLet binds) = sep [ptext (sLit "let") <+> braces (ppr binds), it]
help it WpInline = sep [ptext (sLit "_inline_me_"), it]
in
getPprStyle (\ s -> if debugStyle s then (help it wrap) else it)
(<.>) :: HsWrapper -> HsWrapper -> HsWrapper
WpHole <.> c = c
c <.> WpHole = c
c1 <.> c2 = c1 `WpCompose` c2
mkWpTyApps :: [Type] -> HsWrapper
mkWpTyApps tys = mk_co_fn WpTyApp (reverse tys)
mkWpApps :: [Var] -> HsWrapper
mkWpApps ids = mk_co_fn WpApp (reverse ids)
mkWpTyLams :: [TyVar] -> HsWrapper
mkWpTyLams ids = mk_co_fn WpTyLam ids
mkWpLams :: [Var] -> HsWrapper
mkWpLams ids = mk_co_fn WpLam ids
mk_co_fn :: (a -> HsWrapper) -> [a] -> HsWrapper
mk_co_fn f as = foldr (WpCompose . f) WpHole as
idHsWrapper :: HsWrapper
idHsWrapper = WpHole
isIdHsWrapper :: HsWrapper -> Bool
isIdHsWrapper WpHole = True
isIdHsWrapper _ = False
\end{code}
%************************************************************************
%* *
\subsection{@Sig@: type signatures and valuemodifying user pragmas}
%* *
%************************************************************************
It is convenient to lump ``valuemodifying'' userpragmas (e.g.,
``specialise this function to these four types...'') in with type
signatures. Then all the machinery to move them into place, etc.,
serves for both.
\begin{code}
type LSig name = Located (Sig name)
data Sig name
=
TypeSig (Located name) (LHsType name)
| IdSig Id
| FixSig (FixitySig name)
| InlineSig (Located name)
InlineSpec
| SpecSig (Located name)
(LHsType name)
InlineSpec
| SpecInstSig (LHsType name)
type LFixitySig name = Located (FixitySig name)
data FixitySig name = FixitySig (Located name) Fixity
type LPrag = Located Prag
data Prag
= InlinePrag
InlineSpec
| SpecPrag
(HsExpr Id)
PostTcType
InlineSpec
isInlinePrag :: Prag -> Bool
isInlinePrag (InlinePrag _) = True
isInlinePrag _ = False
isSpecPrag :: Prag -> Bool
isSpecPrag (SpecPrag {}) = True
isSpecPrag _ = False
\end{code}
\begin{code}
okBindSig :: Sig a -> Bool
okBindSig _ = True
okHsBootSig :: Sig a -> Bool
okHsBootSig (TypeSig _ _) = True
okHsBootSig (FixSig _) = True
okHsBootSig _ = False
okClsDclSig :: Sig a -> Bool
okClsDclSig (SpecInstSig _) = False
okClsDclSig _ = True
okInstDclSig :: Sig a -> Bool
okInstDclSig (TypeSig _ _) = False
okInstDclSig (FixSig _) = False
okInstDclSig _ = True
sigForThisGroup :: NameSet -> LSig Name -> Bool
sigForThisGroup ns sig
= case sigName sig of
Nothing -> False
Just n -> n `elemNameSet` ns
sigName :: LSig name -> Maybe name
sigName (L _ sig) = sigNameNoLoc sig
sigNameNoLoc :: Sig name -> Maybe name
sigNameNoLoc (TypeSig n _) = Just (unLoc n)
sigNameNoLoc (SpecSig n _ _) = Just (unLoc n)
sigNameNoLoc (InlineSig n _) = Just (unLoc n)
sigNameNoLoc (FixSig (FixitySig n _)) = Just (unLoc n)
sigNameNoLoc _ = Nothing
isFixityLSig :: LSig name -> Bool
isFixityLSig (L _ (FixSig {})) = True
isFixityLSig _ = False
isVanillaLSig :: LSig name -> Bool
isVanillaLSig (L _(TypeSig {})) = True
isVanillaLSig _ = False
isTypeLSig :: LSig name -> Bool
isTypeLSig (L _(TypeSig {})) = True
isTypeLSig (L _(IdSig {})) = True
isTypeLSig _ = False
isSpecLSig :: LSig name -> Bool
isSpecLSig (L _(SpecSig {})) = True
isSpecLSig _ = False
isSpecInstLSig :: LSig name -> Bool
isSpecInstLSig (L _ (SpecInstSig {})) = True
isSpecInstLSig _ = False
isPragLSig :: LSig name -> Bool
isPragLSig (L _ (SpecSig {})) = True
isPragLSig (L _ (InlineSig {})) = True
isPragLSig _ = False
isInlineLSig :: LSig name -> Bool
isInlineLSig (L _ (InlineSig {})) = True
isInlineLSig _ = False
hsSigDoc :: Sig name -> SDoc
hsSigDoc (TypeSig {}) = ptext (sLit "type signature")
hsSigDoc (IdSig {}) = ptext (sLit "id signature")
hsSigDoc (SpecSig {}) = ptext (sLit "SPECIALISE pragma")
hsSigDoc (InlineSig {}) = ptext (sLit "INLINE pragma")
hsSigDoc (SpecInstSig {}) = ptext (sLit "SPECIALISE instance pragma")
hsSigDoc (FixSig {}) = ptext (sLit "fixity declaration")
\end{code}
Signature equality is used when checking for duplicate signatures
\begin{code}
eqHsSig :: Eq a => LSig a -> LSig a -> Bool
eqHsSig (L _ (FixSig (FixitySig n1 _))) (L _ (FixSig (FixitySig n2 _))) = unLoc n1 == unLoc n2
eqHsSig (L _ (IdSig n1)) (L _ (IdSig n2)) = n1 == n2
eqHsSig (L _ (TypeSig n1 _)) (L _ (TypeSig n2 _)) = unLoc n1 == unLoc n2
eqHsSig (L _ (InlineSig n1 _)) (L _ (InlineSig n2 _)) = unLoc n1 == unLoc n2
eqHsSig _other1 _other2 = False
\end{code}
\begin{code}
instance (OutputableBndr name) => Outputable (Sig name) where
ppr sig = ppr_sig sig
ppr_sig :: OutputableBndr name => Sig name -> SDoc
ppr_sig (TypeSig var ty) = pprVarSig (unLoc var) ty
ppr_sig (IdSig id) = pprVarSig id (varType id)
ppr_sig (FixSig fix_sig) = ppr fix_sig
ppr_sig (SpecSig var ty inl) = pragBrackets (pprSpec var ty inl)
ppr_sig (InlineSig var inl) = pragBrackets (ppr inl <+> ppr var)
ppr_sig (SpecInstSig ty) = pragBrackets (ptext (sLit "SPECIALIZE instance") <+> ppr ty)
instance Outputable name => Outputable (FixitySig name) where
ppr (FixitySig name fixity) = sep [ppr fixity, ppr name]
pragBrackets :: SDoc -> SDoc
pragBrackets doc = ptext (sLit "{-#") <+> doc <+> ptext (sLit "#-}")
pprVarSig :: (Outputable id, Outputable ty) => id -> ty -> SDoc
pprVarSig var ty = sep [ppr var <+> dcolon, nest 2 (ppr ty)]
pprSpec :: (Outputable id, Outputable ty) => id -> ty -> InlineSpec -> SDoc
pprSpec var ty inl = sep [ptext (sLit "SPECIALIZE") <+> ppr inl <+> pprVarSig var ty]
pprPrag :: Outputable id => id -> LPrag -> SDoc
pprPrag var (L _ (InlinePrag inl)) = ppr inl <+> ppr var
pprPrag var (L _ (SpecPrag _expr ty inl)) = pprSpec var ty inl
\end{code}