X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FhsSyn%2FHsBinds.lhs;h=23208f078e347352892287b40eeeec45555a07f7;hb=ac10f8408520a30e8437496d320b8b86afda2e8f;hp=a725c1d6fdbc7906dceda852a878165916efdcfc;hpb=2f51f1402e6869c0f049ffbe7b019bf6ab80558f;p=ghc-hetmet.git diff --git a/ghc/compiler/hsSyn/HsBinds.lhs b/ghc/compiler/hsSyn/HsBinds.lhs index a725c1d..23208f0 100644 --- a/ghc/compiler/hsSyn/HsBinds.lhs +++ b/ghc/compiler/hsSyn/HsBinds.lhs @@ -1,112 +1,320 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996 +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[HsBinds]{Abstract syntax: top-level bindings and signatures} -Datatype for: @HsBinds@, @Bind@, @Sig@, @MonoBinds@. +Datatype for: @BindGroup@, @Bind@, @Sig@, @Bind@. \begin{code} -#include "HsVersions.h" - module HsBinds where -import Ubiq - --- friends: -import HsLoop -import HsMatches ( pprMatches, pprGRHSsAndBinds, - Match, GRHSsAndBinds ) -import HsPat ( collectPatBinders, InPat ) -import HsPragmas ( GenPragmas, ClassOpPragmas ) -import HsTypes ( PolyType ) - ---others: -import Id ( DictVar(..), Id(..), GenId ) -import Name ( pprNonSym ) -import Outputable ( interpp'SP, ifnotPprForUser, - Outputable(..){-instance * (,)-} - ) -import Pretty -import SrcLoc ( SrcLoc{-instances-} ) ---import TyVar ( GenTyVar{-instances-} ) +#include "HsVersions.h" + +import {-# SOURCE #-} HsExpr ( HsExpr, pprExpr, LHsExpr, + MatchGroup, pprFunBind, + GRHSs, pprPatBind ) +import {-# SOURCE #-} HsPat ( LPat ) + +import HsTypes ( LHsType, PostTcType ) +import Type ( Type ) +import Name ( Name ) +import NameSet ( NameSet, elemNameSet ) +import BasicTypes ( IPName, RecFlag(..), InlineSpec(..), Fixity ) +import Outputable +import SrcLoc ( Located(..), SrcSpan, unLoc ) +import Util ( sortLe ) +import Var ( TyVar, DictId, Id ) +import Bag ( Bag, emptyBag, isEmptyBag, bagToList, unionBags, unionManyBags ) \end{code} %************************************************************************ %* * -\subsection{Bindings: @HsBinds@} +\subsection{Bindings: @BindGroup@} %* * %************************************************************************ -The following syntax may produce new syntax which is not part of the input, -and which is instead a translation of the input to the typechecker. -Syntax translations are marked TRANSLATION in comments. New empty -productions are useful in development but may not appear in the final -grammar. - -Collections of bindings, created by dependency analysis and translation: +Global bindings (where clauses) \begin{code} -data HsBinds tyvar uvar id pat -- binders and bindees - = EmptyBinds +data HsLocalBinds id -- Bindings in a 'let' expression + -- or a 'where' clause + = HsValBinds (HsValBinds id) + | HsIPBinds (HsIPBinds id) + | EmptyLocalBinds + +data HsValBinds id -- Value bindings (not implicit parameters) + = ValBindsIn -- Before typechecking + (LHsBinds id) [LSig id] -- Not dependency analysed + -- Recursive by default + + | ValBindsOut -- After renaming + [(RecFlag, LHsBinds id)] -- Dependency analysed + [LSig Name] + +type LHsBinds id = Bag (LHsBind id) +type DictBinds id = LHsBinds id -- Used for dictionary or method bindings +type LHsBind id = Located (HsBind id) + +data HsBind id + = FunBind { -- FunBind is used for both functions f x = e + -- and variables f = \x -> e + -- Reason: the Match stuff lets us have an optional + -- result type sig f :: a->a = ...mentions a... + -- + -- This also means that instance decls can only have + -- FunBinds, so if you change this, you'll need to + -- change e.g. rnMethodBinds + + fun_id :: Located id, + + fun_infix :: Bool, -- True => infix declaration + + fun_matches :: MatchGroup id, -- The payload + + fun_co_fn :: ExprCoFn, -- Coercion from the type of the MatchGroup to the type of + -- the Id. Example: + -- f :: Int -> forall a. a -> a + -- f x y = y + -- Then the MatchGroup will have type (Int -> a' -> a') + -- (with a free type variable a'). The coercion will take + -- a CoreExpr of this type and convert it to a CoreExpr of + -- type Int -> forall a'. a' -> a' + -- Notice that the coercion captures the free a'. That's + -- why coercions are (CoreExpr -> CoreExpr), rather than + -- just CoreExpr (with a functional type) + + bind_fvs :: NameSet -- After the renamer, this contains a superset of the + -- Names of the other binders in this binding group that + -- are free in the RHS of the defn + -- Before renaming, and after typechecking, + -- the field is unused; it's just an error thunk + } + + | PatBind { -- The pattern is never a simple variable; + -- That case is done by FunBind + pat_lhs :: LPat id, + pat_rhs :: GRHSs id, + pat_rhs_ty :: PostTcType, -- Type of the GRHSs + bind_fvs :: NameSet -- Same as for FunBind + } + + | VarBind { -- Dictionary binding and suchlike + var_id :: id, -- All VarBinds are introduced by the type checker + var_rhs :: LHsExpr id -- Located only for consistency + } + + | AbsBinds { -- Binds abstraction; TRANSLATION + abs_tvs :: [TyVar], + abs_dicts :: [DictId], + abs_exports :: [([TyVar], id, id, [Prag])], -- (tvs, poly_id, mono_id, prags) + abs_binds :: LHsBinds id -- The dictionary bindings and typechecked user bindings + -- mixed up together; you can tell the dict bindings because + -- they are all VarBinds + } + -- Consider (AbsBinds tvs ds [(ftvs, poly_f, mono_f) binds] + -- + -- Creates bindings for (polymorphic, overloaded) poly_f + -- in terms of monomorphic, non-overloaded mono_f + -- + -- Invariants: + -- 1. 'binds' binds mono_f + -- 2. ftvs is a subset of tvs + -- 3. ftvs includes all tyvars free in ds + -- + -- See section 9 of static semantics paper for more details. + -- (You can get a PhD for explaining the True Meaning + -- of this last construct.) - | ThenBinds (HsBinds tyvar uvar id pat) - (HsBinds tyvar uvar id pat) +placeHolderNames :: NameSet +-- Used for the NameSet in FunBind and PatBind prior to the renamer +placeHolderNames = panic "placeHolderNames" + +------------ +instance OutputableBndr id => Outputable (HsLocalBinds id) where + ppr (HsValBinds bs) = ppr bs + ppr (HsIPBinds bs) = ppr bs + ppr EmptyLocalBinds = empty + +instance OutputableBndr id => Outputable (HsValBinds id) where + ppr (ValBindsIn binds sigs) + = pprValBindsForUser binds sigs + + ppr (ValBindsOut sccs sigs) + = getPprStyle $ \ sty -> + if debugStyle sty then -- Print with sccs showing + 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") + +-- *not* pprLHsBinds because we don't want braces; 'let' and +-- 'where' include a list of HsBindGroups and we don't want +-- several groups of bindings each with braces around. +-- Sort by location before printing +pprValBindsForUser binds sigs + = 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 id => LHsBinds id -> SDoc +pprLHsBinds binds + | isEmptyLHsBinds binds = empty + | otherwise = lbrace <+> vcat (map ppr (bagToList binds)) <+> rbrace + +------------ +emptyLocalBinds :: HsLocalBinds a +emptyLocalBinds = EmptyLocalBinds + +isEmptyLocalBinds :: HsLocalBinds a -> Bool +isEmptyLocalBinds (HsValBinds ds) = isEmptyValBinds ds +isEmptyLocalBinds (HsIPBinds ds) = isEmptyIPBinds ds +isEmptyLocalBinds EmptyLocalBinds = True + +isEmptyValBinds :: HsValBinds a -> Bool +isEmptyValBinds (ValBindsIn ds sigs) = isEmptyLHsBinds ds && null sigs +isEmptyValBinds (ValBindsOut ds sigs) = null ds && null sigs + +emptyValBindsIn, emptyValBindsOut :: HsValBinds a +emptyValBindsIn = ValBindsIn emptyBag [] +emptyValBindsOut = ValBindsOut [] [] + +emptyLHsBinds :: LHsBinds id +emptyLHsBinds = emptyBag + +isEmptyLHsBinds :: LHsBinds id -> 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} - | SingleBind (Bind tyvar uvar id pat) +What AbsBinds means +~~~~~~~~~~~~~~~~~~~ + AbsBinds tvs + [d1,d2] + [(tvs1, f1p, f1m), + (tvs2, f2p, f2m)] + BIND +means - | BindWith -- Bind with a type signature. - -- These appear only on typechecker input - -- (PolyType [in Sigs] can't appear on output) - (Bind tyvar uvar id pat) - [Sig id] + f1p = /\ tvs -> \ [d1,d2] -> letrec DBINDS and BIND + in fm - | AbsBinds -- Binds abstraction; TRANSLATION - [tyvar] - [id] -- Dicts - [(id, id)] -- (old, new) pairs - [(id, HsExpr tyvar uvar id pat)] -- local dictionaries - (Bind tyvar uvar id pat) -- "the business end" + gp = ...same again, with gm instead of fm - -- Creates bindings for *new* (polymorphic, overloaded) locals - -- in terms of *old* (monomorphic, non-overloaded) ones. - -- - -- See section 9 of static semantics paper for more details. - -- (You can get a PhD for explaining the True Meaning - -- of this last construct.) +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 id => Outputable (HsBind id) where + ppr mbind = ppr_monobind mbind + +ppr_monobind :: OutputableBndr id => HsBind id -> SDoc + +ppr_monobind (PatBind { pat_lhs = pat, pat_rhs = grhss }) = pprPatBind pat grhss +ppr_monobind (VarBind { var_id = var, var_rhs = rhs }) = ppr var <+> equals <+> pprExpr (unLoc rhs) +ppr_monobind (FunBind { fun_id = fun, fun_matches = matches }) = pprFunBind (unLoc fun) matches + -- ToDo: print infix if appropriate + +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] + -- Print type signatures + $$ 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} +%************************************************************************ +%* * + Implicit parameter bindings +%* * +%************************************************************************ + \begin{code} -nullBinds :: HsBinds tyvar uvar id pat -> Bool +data HsIPBinds id + = IPBinds + [LIPBind id] + (DictBinds id) -- Only in typechecker output; binds + -- uses of the implicit parameters + +isEmptyIPBinds :: HsIPBinds id -> Bool +isEmptyIPBinds (IPBinds is ds) = null is && isEmptyBag ds + +type LIPBind id = Located (IPBind id) -nullBinds EmptyBinds = True -nullBinds (ThenBinds b1 b2) = nullBinds b1 && nullBinds b2 -nullBinds (SingleBind b) = nullBind b -nullBinds (BindWith b _) = nullBind b -nullBinds (AbsBinds _ _ _ ds b) = null ds && nullBind b +-- | Implicit parameter bindings. +data IPBind id + = IPBind + (IPName id) + (LHsExpr id) + +instance (OutputableBndr id) => Outputable (HsIPBinds id) where + ppr (IPBinds bs ds) = 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} -instance (Outputable pat, NamedThing id, Outputable id, - Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar) => - Outputable (HsBinds tyvar uvar id pat) where - - ppr sty EmptyBinds = ppNil - ppr sty (ThenBinds binds1 binds2) - = ppAbove (ppr sty binds1) (ppr sty binds2) - ppr sty (SingleBind bind) = ppr sty bind - ppr sty (BindWith bind sigs) - = ppAbove (if null sigs - then ppNil - else ppAboves (map (ppr sty) sigs)) - (ppr sty bind) - ppr sty (AbsBinds tyvars dictvars local_pairs dict_binds val_binds) - = ppAbove (ppSep [ppPStr SLIT("AbsBinds"), - ppBesides[ppLbrack, interpp'SP sty tyvars, ppRbrack], - ppBesides[ppLbrack, interpp'SP sty dictvars, ppRbrack], - ppBesides[ppLbrack, interpp'SP sty local_pairs, ppRbrack]]) - (ppNest 4 (ppAbove (ppAboves (map (ppr sty) dict_binds)) (ppr sty val_binds))) +-- A Coercion is an expression with a hole in it +-- We need coercions to have concrete form so that we can zonk them + +data ExprCoFn + = CoHole -- The identity coercion + | CoCompose ExprCoFn ExprCoFn + | CoApps ExprCoFn [Id] -- Non-empty list + | CoTyApps ExprCoFn [Type] -- in all of these + | CoLams [Id] ExprCoFn -- so that the identity coercion + | CoTyLams [TyVar] ExprCoFn -- is just Hole + | CoLet (LHsBinds Id) ExprCoFn -- Would be nicer to be core bindings + +(<.>) :: ExprCoFn -> ExprCoFn -> ExprCoFn +(<.>) = CoCompose + +idCoercion :: ExprCoFn +idCoercion = CoHole + +isIdCoercion :: ExprCoFn -> Bool +isIdCoercion CoHole = True +isIdCoercion other = False \end{code} + %************************************************************************ %* * \subsection{@Sig@: type signatures and value-modifying user pragmas} @@ -119,215 +327,151 @@ 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 - = Sig name -- a bog-std type signature - (PolyType name) - (GenPragmas name) -- only interface ones have pragmas - SrcLoc - - | ClassOpSig name -- class-op sigs have different pragmas - (PolyType name) - (ClassOpPragmas name) -- only interface ones have pragmas - SrcLoc - - | SpecSig name -- specialise a function or datatype ... - (PolyType name) -- ... to these types - (Maybe name) -- ... maybe using this as the code for it - SrcLoc - - | InlineSig name -- INLINE f - SrcLoc - - -- ToDo: strictly speaking, could omit based on -DOMIT_DEFORESTER - | DeforestSig name -- Deforest using this function definition - SrcLoc - - | MagicUnfoldingSig - name -- Associate the "name"d function with - FAST_STRING -- the compiler-builtin unfolding (known - SrcLoc -- by the String name) -\end{code} + = TypeSig (Located name) -- A bog-std type signature + (LHsType name) -\begin{code} -instance (NamedThing name, Outputable name) => Outputable (Sig name) where - ppr sty (Sig var ty pragmas _) - = ppHang (ppCat [pprNonSym sty var, ppPStr SLIT("::")]) - 4 (ppHang (ppr sty ty) - 4 (ifnotPprForUser sty (ppr sty pragmas))) - - ppr sty (ClassOpSig var ty pragmas _) - = ppHang (ppCat [pprNonSym sty var, ppPStr SLIT("::")]) - 4 (ppHang (ppr sty ty) - 4 (ifnotPprForUser sty (ppr sty pragmas))) - - ppr sty (DeforestSig var _) - = ppHang (ppCat [ppStr "{-# DEFOREST", pprNonSym sty var]) - 4 (ppStr "#-}") - - ppr sty (SpecSig var ty using _) - = ppHang (ppCat [ppPStr SLIT("{-# SPECIALIZE"), pprNonSym sty var, ppPStr SLIT("::")]) - 4 (ppCat [ppr sty ty, pp_using using, ppPStr SLIT("#-}")]) - where - pp_using Nothing = ppNil - pp_using (Just me) = ppCat [ppChar '=', ppr sty me] - - ppr sty (InlineSig var _) - = ppCat [ppPStr SLIT("{-# INLINE"), pprNonSym sty var, ppPStr SLIT("#-}")] - - ppr sty (MagicUnfoldingSig var str _) - = ppCat [ppPStr SLIT("{-# MAGIC_UNFOLDING"), pprNonSym sty var, ppPStr str, ppPStr SLIT("#-}")] -\end{code} + | SpecSig (Located name) -- Specialise a function or datatype ... + (LHsType name) -- ... to these types + InlineSpec -%************************************************************************ -%* * -\subsection{Binding: @Bind@} -%* * -%************************************************************************ + | InlineSig (Located name) -- Function name + InlineSpec -\begin{code} -data Bind tyvar uvar id pat -- binders and bindees - = EmptyBind -- because it's convenient when parsing signatures - | NonRecBind (MonoBinds tyvar uvar id pat) - | RecBind (MonoBinds tyvar uvar id pat) -\end{code} + | SpecInstSig (LHsType name) -- (Class tys); should be a specialisation of the + -- current instance decl -\begin{code} -nullBind :: Bind tyvar uvar id pat -> Bool + | FixSig (FixitySig name) -- Fixity declaration -nullBind EmptyBind = True -nullBind (NonRecBind bs) = nullMonoBinds bs -nullBind (RecBind bs) = nullMonoBinds bs -\end{code} +type LFixitySig name = Located (FixitySig name) +data FixitySig name = FixitySig (Located name) Fixity -\begin{code} -bindIsRecursive :: Bind tyvar uvar id pat -> Bool +-- A Prag conveys pragmas from the type checker to the desugarer +data Prag + = InlinePrag + InlineSpec -bindIsRecursive EmptyBind = False -bindIsRecursive (NonRecBind _) = False -bindIsRecursive (RecBind _) = True + | SpecPrag + (HsExpr Id) -- An expression, of the given specialised type, which + PostTcType -- specialises the polymorphic function + [Id] -- Dicts mentioned free in the expression + InlineSpec -- Inlining spec for the specialised function + +isInlinePrag (InlinePrag _) = True +isInlinePrag prag = False + +isSpecPrag (SpecPrag _ _ _ _) = True +isSpecPrag prag = False \end{code} \begin{code} -instance (NamedThing id, Outputable id, Outputable pat, - Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar) => - Outputable (Bind tyvar uvar id pat) where - ppr sty EmptyBind = ppNil - ppr sty (NonRecBind binds) - = ppAbove (ifnotPprForUser sty (ppStr "{- nonrec -}")) - (ppr sty binds) - ppr sty (RecBind binds) - = ppAbove (ifnotPprForUser sty (ppStr "{- rec -}")) - (ppr sty binds) +okBindSig :: NameSet -> LSig Name -> Bool +okBindSig ns sig = sigForThisGroup ns sig + +okHsBootSig :: LSig Name -> Bool +okHsBootSig (L _ (TypeSig _ _)) = True +okHsBootSig (L _ (FixSig _)) = True +okHsBootSig sig = False + +okClsDclSig :: LSig Name -> Bool +okClsDclSig (L _ (SpecInstSig _)) = False +okClsDclSig sig = True -- All others OK + +okInstDclSig :: NameSet -> LSig Name -> Bool +okInstDclSig ns lsig@(L _ sig) = ok ns sig + where + ok ns (TypeSig _ _) = False + ok ns (FixSig _) = False + ok ns (SpecInstSig _) = True + ok ns sig = sigForThisGroup ns lsig + +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) = f sig + where + f (TypeSig n _) = Just (unLoc n) + f (SpecSig n _ _) = Just (unLoc n) + f (InlineSig n _) = Just (unLoc n) + f (FixSig (FixitySig n _)) = Just (unLoc n) + f other = Nothing + +isFixityLSig :: LSig name -> Bool +isFixityLSig (L _ (FixSig {})) = True +isFixityLSig _ = False + +isVanillaLSig :: LSig name -> Bool +isVanillaLSig (L _(TypeSig {})) = True +isVanillaLSig sig = False + +isSpecLSig :: LSig name -> Bool +isSpecLSig (L _(SpecSig {})) = True +isSpecLSig sig = False + +isSpecInstLSig (L _ (SpecInstSig {})) = True +isSpecInstLSig sig = False + +isPragLSig :: LSig name -> Bool + -- Identifies pragmas +isPragLSig (L _ (SpecSig {})) = True +isPragLSig (L _ (InlineSig {})) = True +isPragLSig other = False + +isInlineLSig :: LSig name -> Bool + -- Identifies inline pragmas +isInlineLSig (L _ (InlineSig {})) = True +isInlineLSig other = False + +hsSigDoc (TypeSig {}) = ptext SLIT("type signature") +hsSigDoc (SpecSig {}) = ptext SLIT("SPECIALISE pragma") +hsSigDoc (InlineSig _ spec) = ppr spec <+> ptext SLIT("pragma") +hsSigDoc (SpecInstSig {}) = ptext SLIT("SPECIALISE instance pragma") +hsSigDoc (FixSig {}) = ptext SLIT("fixity declaration") \end{code} -%************************************************************************ -%* * -\subsection{Bindings: @MonoBinds@} -%* * -%************************************************************************ - -Global bindings (where clauses) +Signature equality is used when checking for duplicate signatures \begin{code} -data MonoBinds tyvar uvar id pat - = EmptyMonoBinds - | AndMonoBinds (MonoBinds tyvar uvar id pat) - (MonoBinds tyvar uvar id pat) - | PatMonoBind pat - (GRHSsAndBinds tyvar uvar id pat) - SrcLoc - | FunMonoBind id - Bool -- True => infix declaration - [Match tyvar uvar id pat] -- must have at least one Match - SrcLoc - | VarMonoBind id -- TRANSLATION - (HsExpr tyvar uvar id pat) +eqHsSig :: LSig Name -> LSig Name -> Bool +eqHsSig (L _ (FixSig (FixitySig n1 _))) (L _ (FixSig (FixitySig n2 _))) = unLoc n1 == unLoc n2 +eqHsSig (L _ (TypeSig n1 _)) (L _ (TypeSig n2 _)) = unLoc n1 == unLoc n2 +eqHsSig (L _ (InlineSig n1 s1)) (L _ (InlineSig n2 s2)) = s1 == s2 && unLoc n1 == unLoc n2 + -- For specialisations, we don't have equality over + -- HsType, so it's not convenient to spot duplicate + -- specialisations here. Check for this later, when we're in Type land +eqHsSig _other1 _other2 = False \end{code} \begin{code} -nullMonoBinds :: MonoBinds tyvar uvar id pat -> Bool +instance (OutputableBndr name) => Outputable (Sig name) where + ppr sig = ppr_sig sig -nullMonoBinds EmptyMonoBinds = True -nullMonoBinds (AndMonoBinds bs1 bs2) = nullMonoBinds bs1 && nullMonoBinds bs2 -nullMonoBinds other_monobind = False -\end{code} +ppr_sig :: OutputableBndr name => Sig name -> SDoc +ppr_sig (TypeSig var ty) = pprVarSig (unLoc var) ty +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) -\begin{code} -instance (NamedThing id, Outputable id, Outputable pat, - Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar) => - Outputable (MonoBinds tyvar uvar id pat) where - ppr sty EmptyMonoBinds = ppNil - ppr sty (AndMonoBinds binds1 binds2) - = ppAbove (ppr sty binds1) (ppr sty binds2) - - ppr sty (PatMonoBind pat grhss_n_binds locn) - = ppHang (ppr sty pat) 4 (pprGRHSsAndBinds sty False grhss_n_binds) - - ppr sty (FunMonoBind fun inf matches locn) - = pprMatches sty (False, pprNonSym sty fun) matches - -- ToDo: print infix if appropriate +instance Outputable name => Outputable (FixitySig name) where + ppr (FixitySig name fixity) = sep [ppr fixity, ppr name] - ppr sty (VarMonoBind name expr) - = ppHang (ppCat [pprNonSym sty name, ppEquals]) 4 (ppr sty expr) -\end{code} +pragBrackets :: SDoc -> SDoc +pragBrackets doc = ptext SLIT("{-#") <+> doc <+> ptext SLIT("#-}") -%************************************************************************ -%* * -\subsection{Collecting binders from @HsBinds@} -%* * -%************************************************************************ +pprVarSig :: (Outputable id, Outputable ty) => id -> ty -> SDoc +pprVarSig var ty = sep [ppr var <+> dcolon, nest 2 (ppr ty)] -Get all the binders in some @MonoBinds@, IN THE ORDER OF -APPEARANCE; e.g., in: -\begin{verbatim} -... -where - (x, y) = ... - f i j = ... - [a, b] = ... -\end{verbatim} -it should return @[x, y, f, a, b]@ (remember, order important). +pprSpec :: (Outputable id, Outputable ty) => id -> ty -> InlineSpec -> SDoc +pprSpec var ty inl = sep [ptext SLIT("SPECIALIZE") <+> ppr inl <+> pprVarSig var ty] -\begin{code} -collectTopLevelBinders :: HsBinds tyvar uvar name (InPat name) -> [name] -collectTopLevelBinders EmptyBinds = [] -collectTopLevelBinders (SingleBind b) = collectBinders b -collectTopLevelBinders (BindWith b _) = collectBinders b -collectTopLevelBinders (ThenBinds b1 b2) - = collectTopLevelBinders b1 ++ collectTopLevelBinders b2 - -collectBinders :: Bind tyvar uvar name (InPat name) -> [name] -collectBinders EmptyBind = [] -collectBinders (NonRecBind monobinds) = collectMonoBinders monobinds -collectBinders (RecBind monobinds) = collectMonoBinders monobinds - -collectMonoBinders :: MonoBinds tyvar uvar name (InPat name) -> [name] -collectMonoBinders EmptyMonoBinds = [] -collectMonoBinders (PatMonoBind pat grhss_w_binds _) = collectPatBinders pat -collectMonoBinders (FunMonoBind f _ matches _) = [f] -collectMonoBinders (VarMonoBind v expr) = error "collectMonoBinders" -collectMonoBinders (AndMonoBinds bs1 bs2) - = collectMonoBinders bs1 ++ collectMonoBinders bs2 - --- We'd like the binders -- and where they came from -- --- so we can make new ones with equally-useful origin info. - -collectMonoBindersAndLocs - :: MonoBinds tyvar uvar name (InPat name) -> [(name, SrcLoc)] - -collectMonoBindersAndLocs EmptyMonoBinds = [] - -collectMonoBindersAndLocs (AndMonoBinds bs1 bs2) - = collectMonoBindersAndLocs bs1 ++ collectMonoBindersAndLocs bs2 - -collectMonoBindersAndLocs (PatMonoBind pat grhss_w_binds locn) - = collectPatBinders pat `zip` repeat locn - -collectMonoBindersAndLocs (FunMonoBind f _ matches locn) = [(f, locn)] - -#ifdef DEBUG -collectMonoBindersAndLocs (VarMonoBind v expr) - = trace "collectMonoBindersAndLocs:VarMonoBind" [] - -- ToDo: this is dubious, i.e., wrong, but harmless? -#endif +pprPrag :: Outputable id => id -> Prag -> SDoc +pprPrag var (InlinePrag inl) = ppr inl <+> ppr var +pprPrag var (SpecPrag expr ty _ inl) = pprSpec var ty inl \end{code}