X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FhsSyn%2FHsBinds.lhs;h=47302c50505453ab748da8ebc16582accb7a3e54;hb=853e20a3eb86137cdb8accf69c6caa9db83a3d34;hp=c02c435256eae33205d9fd093e847b1fed09322a;hpb=9af77fa423926fbda946b31e174173d0ec5ebac8;p=ghc-hetmet.git diff --git a/ghc/compiler/hsSyn/HsBinds.lhs b/ghc/compiler/hsSyn/HsBinds.lhs index c02c435..47302c5 100644 --- a/ghc/compiler/hsSyn/HsBinds.lhs +++ b/ghc/compiler/hsSyn/HsBinds.lhs @@ -3,84 +3,54 @@ % \section[HsBinds]{Abstract syntax: top-level bindings and signatures} -Datatype for: @HsBinds@, @Bind@, @Sig@, @MonoBinds@. +Datatype for: @BindGroup@, @Bind@, @Sig@, @Bind@. \begin{code} module HsBinds where #include "HsVersions.h" -import {-# SOURCE #-} HsExpr ( HsExpr, pprExpr, - Match, pprFunBind, - GRHSs, pprPatBind ) +import {-# SOURCE #-} HsExpr ( HsExpr, pprExpr, LHsExpr, + MatchGroup, pprFunBind, + GRHSs, pprPatBind ) +import {-# SOURCE #-} HsPat ( LPat ) --- friends: -import HsImpExp ( pprHsVar ) -import HsPat ( Pat ) -import HsTypes ( HsType ) -import CoreSyn ( CoreExpr ) -import PprCore ( {- instance Outputable (Expr a) -} ) - ---others: +import HsTypes ( LHsType, PostTcType ) import Name ( Name ) -import PrelNames ( isUnboundName ) import NameSet ( NameSet, elemNameSet, nameSetToList ) -import BasicTypes ( RecFlag(..), FixitySig(..), Activation(..) ) +import BasicTypes ( IPName, RecFlag(..), Activation(..), Fixity ) import Outputable -import SrcLoc ( SrcLoc ) +import SrcLoc ( Located(..), unLoc ) import Var ( TyVar ) -import Class ( DefMeth (..) ) +import Bag ( Bag, emptyBag, isEmptyBag, bagToList ) \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: - -\begin{code} -data HsBinds id -- binders and bindees - = EmptyBinds - - | ThenBinds (HsBinds id) - (HsBinds id) - - | MonoBind (MonoBinds id) - [Sig id] -- Empty on typechecker output, Type Signatures - RecFlag -\end{code} +Global bindings (where clauses) \begin{code} -nullBinds :: HsBinds id -> Bool - -nullBinds EmptyBinds = True -nullBinds (ThenBinds b1 b2) = nullBinds b1 && nullBinds b2 -nullBinds (MonoBind b _ _) = nullMonoBinds b +data HsBindGroup id + = HsBindGroup -- A mutually recursive group + (LHsBinds id) + [LSig id] -- Empty on typechecker output, Type Signatures + RecFlag -mkMonoBind :: MonoBinds id -> [Sig id] -> RecFlag -> HsBinds id -mkMonoBind EmptyMonoBinds _ _ = EmptyBinds -mkMonoBind mbinds sigs is_rec = MonoBind mbinds sigs is_rec -\end{code} + | HsIPBinds + [LIPBind id] -- Not allowed at top level -\begin{code} -instance (OutputableBndr id) => Outputable (HsBinds id) where - ppr binds = ppr_binds binds - -ppr_binds EmptyBinds = empty -ppr_binds (ThenBinds binds1 binds2) - = ppr_binds binds1 $$ ppr_binds binds2 -ppr_binds (MonoBind bind sigs is_rec) +instance OutputableBndr id => Outputable (HsBindGroup id) where + ppr (HsBindGroup binds sigs is_rec) = vcat [ppr_isrec, vcat (map ppr sigs), - ppr bind + vcat (map ppr (bagToList binds)) + -- *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. ] where ppr_isrec = getPprStyle $ \ sty -> @@ -88,52 +58,68 @@ ppr_binds (MonoBind bind sigs is_rec) case is_rec of Recursive -> ptext SLIT("{- rec -}") NonRecursive -> ptext SLIT("{- nonrec -}") -\end{code} -%************************************************************************ -%* * -\subsection{Bindings: @MonoBinds@} -%* * -%************************************************************************ + ppr (HsIPBinds ipbinds) + = vcat (map ppr ipbinds) -Global bindings (where clauses) +-- ----------------------------------------------------------------------------- +-- Implicit parameter bindings -\begin{code} -data MonoBinds id - = EmptyMonoBinds - - | AndMonoBinds (MonoBinds id) - (MonoBinds id) - - | FunMonoBind id -- 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 - -- FunMonoBinds, so if you change this, you'll need to - -- change e.g. rnMethodBinds - Bool -- True => infix declaration - [Match id] - SrcLoc - - | PatMonoBind (Pat id) -- The pattern is never a simple variable; - -- That case is done by FunMonoBind - (GRHSs id) - SrcLoc - - | VarMonoBind id -- TRANSLATION - (HsExpr id) - - | CoreMonoBind id -- TRANSLATION - CoreExpr -- No zonking; this is a final CoreExpr with Ids and Types! +type LIPBind id = Located (IPBind id) + +-- | Implicit parameter bindings. +data IPBind id + = IPBind + (IPName id) + (LHsExpr id) + +instance (OutputableBndr id) => Outputable (IPBind id) where + ppr (IPBind id rhs) = pprBndr LetBind id <+> equals <+> pprExpr (unLoc rhs) + +-- ----------------------------------------------------------------------------- + +type LHsBinds id = Bag (LHsBind id) +type DictBinds id = LHsBinds id -- Used for dictionary or method bindings +type LHsBind id = Located (HsBind id) + +emptyLHsBinds :: LHsBinds id +emptyLHsBinds = emptyBag + +isEmptyLHsBinds :: LHsBinds id -> Bool +isEmptyLHsBinds = isEmptyBag + +pprLHsBinds :: OutputableBndr id => LHsBinds id -> SDoc +pprLHsBinds binds + | isEmptyLHsBinds binds = empty + | otherwise = lbrace <+> vcat (map ppr (bagToList binds)) <+> rbrace + +data HsBind id + = FunBind (Located id) + -- 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 + Bool -- True => infix declaration + (MatchGroup id) + + | PatBind (LPat id) -- The pattern is never a simple variable; + -- That case is done by FunBind + (GRHSs id) + PostTcType -- Type of the GRHSs + + | VarBind id (Located (HsExpr id)) -- Dictionary binding and suchlike; + -- located only for consistency | AbsBinds -- Binds abstraction; TRANSLATION [TyVar] -- Type variables [id] -- Dicts [([TyVar], id, id)] -- (type variables, polymorphic, momonmorphic) triples NameSet -- Set of *polymorphic* variables that have an INLINE pragma - (MonoBinds id) -- The "business end" + (LHsBinds id) -- The "business end" -- Creates bindings for *new* (polymorphic, overloaded) locals -- in terms of *old* (monomorphic, non-overloaded) ones. @@ -168,53 +154,16 @@ So the desugarer tries to do a better job: in (fm,gm) \begin{code} --- We keep the invariant that a MonoBinds is only empty --- if it is exactly EmptyMonoBinds - -nullMonoBinds :: MonoBinds id -> Bool -nullMonoBinds EmptyMonoBinds = True -nullMonoBinds other_monobind = False - -andMonoBinds :: MonoBinds id -> MonoBinds id -> MonoBinds id -andMonoBinds EmptyMonoBinds mb = mb -andMonoBinds mb EmptyMonoBinds = mb -andMonoBinds mb1 mb2 = AndMonoBinds mb1 mb2 - -andMonoBindList :: [MonoBinds id] -> MonoBinds id -andMonoBindList binds - = loop1 binds - where - loop1 [] = EmptyMonoBinds - loop1 (EmptyMonoBinds : binds) = loop1 binds - loop1 (b:bs) = loop2 b bs - - -- acc is non-empty - loop2 acc [] = acc - loop2 acc (EmptyMonoBinds : bs) = loop2 acc bs - loop2 acc (b:bs) = loop2 (acc `AndMonoBinds` b) bs -\end{code} - - -\begin{code} -instance OutputableBndr id => Outputable (MonoBinds id) where +instance OutputableBndr id => Outputable (HsBind id) where ppr mbind = ppr_monobind mbind +ppr_monobind :: OutputableBndr id => HsBind id -> SDoc -ppr_monobind :: OutputableBndr id => MonoBinds id -> SDoc -ppr_monobind EmptyMonoBinds = empty -ppr_monobind (AndMonoBinds binds1 binds2) - = ppr_monobind binds1 $$ ppr_monobind binds2 - -ppr_monobind (PatMonoBind pat grhss locn) = pprPatBind pat grhss -ppr_monobind (FunMonoBind fun inf matches locn) = pprFunBind fun matches +ppr_monobind (PatBind pat grhss ty) = pprPatBind pat grhss +ppr_monobind (VarBind var rhs) = ppr var <+> equals <+> pprExpr (unLoc rhs) +ppr_monobind (FunBind fun inf matches) = pprFunBind (unLoc fun) matches -- ToDo: print infix if appropriate -ppr_monobind (VarMonoBind name expr) - = sep [pprBndr LetBind name <+> equals, nest 4 (pprExpr expr)] - -ppr_monobind (CoreMonoBind name expr) - = sep [pprBndr LetBind name <+> equals, nest 4 (ppr expr)] - ppr_monobind (AbsBinds tyvars dictvars exports inlines val_binds) = sep [ptext SLIT("AbsBinds"), brackets (interpp'SP tyvars), @@ -225,7 +174,7 @@ ppr_monobind (AbsBinds tyvars dictvars exports inlines val_binds) nest 4 ( vcat [pprBndr LetBind x | (_,x,_) <- exports] -- Print type signatures $$ - ppr val_binds ) + pprLHsBinds val_binds ) \end{code} %************************************************************************ @@ -240,140 +189,119 @@ signatures. Then all the machinery to move them into place, etc., serves for both. \begin{code} -data Sig name - = Sig name -- a bog-std type signature - (HsType name) - SrcLoc +type LSig name = Located (Sig name) - | ClassOpSig name -- Selector name - (DefMeth name) -- Default-method info - -- See "THE NAMING STORY" in HsDecls - (HsType name) - SrcLoc +data Sig name + = Sig (Located name) -- a bog-std type signature + (LHsType name) - | SpecSig name -- specialise a function or datatype ... - (HsType name) -- ... to these types - SrcLoc + | SpecSig (Located name) -- specialise a function or datatype ... + (LHsType name) -- ... to these types | InlineSig Bool -- True <=> INLINE f, False <=> NOINLINE f - name -- Function name + (Located name) -- Function name Activation -- When inlining is *active* - SrcLoc - | SpecInstSig (HsType name) -- (Class tys); should be a specialisation of the + | SpecInstSig (LHsType name) -- (Class tys); should be a specialisation of the -- current instance decl - SrcLoc | FixSig (FixitySig name) -- Fixity declaration + +type LFixitySig name = Located (FixitySig name) +data FixitySig name = FixitySig (Located name) Fixity \end{code} \begin{code} -okBindSig :: NameSet -> Sig Name -> Bool -okBindSig ns (ClassOpSig _ _ _ _) = False +okBindSig :: NameSet -> LSig Name -> Bool okBindSig ns sig = sigForThisGroup ns sig -okClsDclSig :: NameSet -> Sig Name -> Bool -okClsDclSig ns (Sig _ _ _) = False -okClsDclSig ns sig = sigForThisGroup ns sig +okClsDclSig :: LSig Name -> Bool +okClsDclSig (L _ (SpecInstSig _)) = False +okClsDclSig sig = True -- All others OK -okInstDclSig :: NameSet -> Sig Name -> Bool -okInstDclSig ns (Sig _ _ _) = False -okInstDclSig ns (FixSig _) = False -okInstDclSig ns (SpecInstSig _ _) = True -okInstDclSig ns sig = sigForThisGroup ns sig +okInstDclSig :: NameSet -> LSig Name -> Bool +okInstDclSig ns lsig@(L _ sig) = ok ns sig + where + ok ns (Sig _ _) = False + ok ns (FixSig _) = False + ok ns (SpecInstSig _) = True + ok ns sig = sigForThisGroup ns lsig -sigForThisGroup ns sig +sigForThisGroup :: NameSet -> LSig Name -> Bool +sigForThisGroup ns sig = case sigName sig of - Nothing -> False - Just n | isUnboundName n -> True -- Don't complain about an unbound name again - | otherwise -> n `elemNameSet` ns - -sigName :: Sig name -> Maybe name -sigName (Sig n _ _) = Just n -sigName (ClassOpSig n _ _ _) = Just n -sigName (SpecSig n _ _) = Just n -sigName (InlineSig _ n _ _) = Just n -sigName (FixSig (FixitySig n _ _)) = Just n -sigName other = Nothing - -isFixitySig :: Sig name -> Bool -isFixitySig (FixSig _) = True -isFixitySig _ = False - -isClassOpSig :: Sig name -> Bool -isClassOpSig (ClassOpSig _ _ _ _) = True -isClassOpSig _ = False - -isPragSig :: Sig name -> Bool + Nothing -> False + Just n -> n `elemNameSet` ns + +sigName :: LSig name -> Maybe name +sigName (L _ sig) = f sig + where + f (Sig 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 _(Sig name _)) = True +isVanillaLSig sig = False + +isPragLSig :: LSig name -> Bool -- Identifies pragmas -isPragSig (SpecSig _ _ _) = True -isPragSig (InlineSig _ _ _ _) = True -isPragSig (SpecInstSig _ _) = True -isPragSig other = False +isPragLSig (L _ (SpecSig _ _)) = True +isPragLSig (L _ (InlineSig _ _ _)) = True +isPragLSig (L _ (SpecInstSig _)) = True +isPragLSig other = False + +hsSigDoc (Sig _ _) = ptext SLIT("type signature") +hsSigDoc (SpecSig _ _) = ptext SLIT("SPECIALISE pragma") +hsSigDoc (InlineSig True _ _) = ptext SLIT("INLINE pragma") +hsSigDoc (InlineSig False _ _) = ptext SLIT("NOINLINE pragma") +hsSigDoc (SpecInstSig _) = ptext SLIT("SPECIALISE instance pragma") +hsSigDoc (FixSig (FixitySig _ _)) = ptext SLIT("fixity declaration") \end{code} +Signature equality is used when checking for duplicate signatures + \begin{code} -hsSigDoc (Sig _ _ loc) = (ptext SLIT("type signature"),loc) -hsSigDoc (ClassOpSig _ _ _ loc) = (ptext SLIT("class-method type signature"), loc) -hsSigDoc (SpecSig _ _ loc) = (ptext SLIT("SPECIALISE pragma"),loc) -hsSigDoc (InlineSig True _ _ loc) = (ptext SLIT("INLINE pragma"),loc) -hsSigDoc (InlineSig False _ _ loc) = (ptext SLIT("NOINLINE pragma"),loc) -hsSigDoc (SpecInstSig _ loc) = (ptext SLIT("SPECIALISE instance pragma"),loc) -hsSigDoc (FixSig (FixitySig _ _ loc)) = (ptext SLIT("fixity declaration"), loc) +eqHsSig :: Sig Name -> Sig Name -> Bool +eqHsSig (FixSig (FixitySig n1 _)) (FixSig (FixitySig n2 _)) = unLoc n1 == unLoc n2 +eqHsSig (Sig n1 _) (Sig n2 _) = unLoc n1 == unLoc n2 +eqHsSig (InlineSig b1 n1 _) (InlineSig b2 n2 _) = b1 == b2 && 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} -instance (Outputable name) => Outputable (Sig name) where +instance (OutputableBndr name) => Outputable (Sig name) where ppr sig = ppr_sig sig -ppr_sig :: Outputable name => Sig name -> SDoc -ppr_sig (Sig var ty _) +ppr_sig :: OutputableBndr name => Sig name -> SDoc +ppr_sig (Sig var ty) = sep [ppr var <+> dcolon, nest 4 (ppr ty)] -ppr_sig (ClassOpSig var dm ty _) - = sep [ pprHsVar var <+> dcolon, - nest 4 (ppr ty), - nest 4 (pp_dm_comment) ] - where - pp_dm = case dm of - DefMeth _ -> equals -- Default method indicator - GenDefMeth -> semi -- Generic method indicator - NoDefMeth -> empty -- No Method at all - pp_dm_comment = case dm of - DefMeth _ -> text "{- has default method -}" - GenDefMeth -> text "{- has generic method -}" - NoDefMeth -> empty -- No Method at all - -ppr_sig (SpecSig var ty _) +ppr_sig (SpecSig var ty) = sep [ hsep [text "{-# SPECIALIZE", ppr var, dcolon], nest 4 (ppr ty <+> text "#-}") ] -ppr_sig (InlineSig True var phase _) +ppr_sig (InlineSig True var phase) = hsep [text "{-# INLINE", ppr phase, ppr var, text "#-}"] -ppr_sig (InlineSig False var phase _) +ppr_sig (InlineSig False var phase) = hsep [text "{-# NOINLINE", ppr phase, ppr var, text "#-}"] -ppr_sig (SpecInstSig ty _) +ppr_sig (SpecInstSig ty) = hsep [text "{-# SPECIALIZE instance", ppr ty, text "#-}"] ppr_sig (FixSig fix_sig) = ppr fix_sig -\end{code} - -Checking for distinct signatures; oh, so boring - -\begin{code} -eqHsSig :: Sig Name -> Sig Name -> Bool -eqHsSig (Sig n1 _ _) (Sig n2 _ _) = n1 == n2 -eqHsSig (InlineSig b1 n1 _ _)(InlineSig b2 n2 _ _) = b1 == b2 && n1 == n2 - -eqHsSig (SpecInstSig ty1 _) (SpecInstSig ty2 _) = ty1 == ty2 -eqHsSig (SpecSig n1 ty1 _) (SpecSig n2 ty2 _) = - -- may have many specialisations for one value; - -- but not ones that are exactly the same... - (n1 == n2) && (ty1 == ty2) - -eqHsSig _other1 _other2 = False +instance Outputable name => Outputable (FixitySig name) where + ppr (FixitySig name fixity) = sep [ppr fixity, ppr name] \end{code}