X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2FhsSyn%2FHsBinds.lhs;h=f3648832f3c6c4e39d0fc4781c4d070e5b28ffe6;hp=8f9279e923e04b3b2895a5588bea6f2f3def5d22;hb=77166b1729061531eeb77c33f4d3b2581f7d4c41;hpb=5653634ead7a7f31f1a584483e53b23e78b047c2 diff --git a/compiler/hsSyn/HsBinds.lhs b/compiler/hsSyn/HsBinds.lhs index 8f9279e..f364883 100644 --- a/compiler/hsSyn/HsBinds.lhs +++ b/compiler/hsSyn/HsBinds.lhs @@ -1,4 +1,5 @@ % +% (c) The University of Glasgow 2006 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[HsBinds]{Abstract syntax: top-level bindings and signatures} @@ -6,27 +7,33 @@ Datatype for: @BindGroup@, @Bind@, @Sig@, @Bind@. \begin{code} -module HsBinds where +{-# OPTIONS -fno-warn-incomplete-patterns #-} +-- The above warning supression flag is a temporary kludge. +-- While working on this module you are encouraged to remove it and fix +-- any warnings in the module. See +-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings +-- for details -#include "HsVersions.h" +module HsBinds where -import {-# SOURCE #-} HsExpr ( HsExpr, pprExpr, LHsExpr, +import {-# SOURCE #-} HsExpr ( pprExpr, LHsExpr, MatchGroup, pprFunBind, GRHSs, pprPatBind ) import {-# SOURCE #-} HsPat ( LPat ) -import HsTypes ( LHsType, PostTcType ) -import PprCore ( {- instances -} ) -import Coercion ( Coercion ) -import Type ( Type, pprParendType ) -import Name ( Name ) -import NameSet ( NameSet, elemNameSet ) -import BasicTypes ( IPName, RecFlag(..), InlineSpec(..), Fixity ) +import HsTypes +import PprCore () +import Coercion +import Type +import Name +import NameSet +import BasicTypes import Outputable -import SrcLoc ( Located(..), SrcSpan, unLoc ) -import Util ( sortLe ) -import Var ( TyVar, DictId, Id ) -import Bag ( Bag, emptyBag, isEmptyBag, bagToList, unionBags, unionManyBags ) +import SrcLoc +import Util +import Var +import Bag +import FastString \end{code} %************************************************************************ @@ -38,81 +45,106 @@ import Bag ( Bag, emptyBag, isEmptyBag, bagToList, unionBags, unionManyBags ) Global bindings (where clauses) \begin{code} -data HsLocalBinds id -- Bindings in a 'let' expression - -- or a 'where' clause - = HsValBinds (HsValBinds id) - | HsIPBinds (HsIPBinds id) - +-- During renaming, we need bindings where the left-hand sides +-- have been renamed but the the right-hand sides have not. +-- the ...LR datatypes are parametrized by two id types, +-- one for the left and one for the right. +-- Other than during renaming, these will be the same. + +type HsLocalBinds id = HsLocalBindsLR id id + +data HsLocalBindsLR idL idR -- Bindings in a 'let' expression + -- or a 'where' clause + = HsValBinds (HsValBindsLR idL idR) + | HsIPBinds (HsIPBinds idR) | EmptyLocalBinds -data HsValBinds id -- Value bindings (not implicit parameters) - = ValBindsIn -- Before typechecking - (LHsBinds id) [LSig id] -- Not dependency analysed +type HsValBinds id = HsValBindsLR id id + +data HsValBindsLR idL idR -- Value bindings (not implicit parameters) + = ValBindsIn -- Before typechecking + (LHsBindsLR idL idR) [LSig idR] -- Not dependency analysed -- Recursive by default - | ValBindsOut -- After renaming - [(RecFlag, LHsBinds id)] -- Dependency analysed + | ValBindsOut -- After renaming + [(RecFlag, LHsBinds idL)] -- Dependency analysed, later bindings + -- in the list may depend on earlier + -- ones. [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) +type HsBind id = HsBindLR id id -data HsBind id - = FunBind { -- FunBind is used for both functions f x = e - -- and variables f = \x -> e --- Reason 1: Special case for type inference: see TcBinds.tcMonoBinds --- --- Reason 2: instance decls can only have FunBinds, which is convenient --- If you change this, you'll need tochange e.g. rnMethodBinds +type LHsBindLR idL idR = Located (HsBindLR idL idR) +type LHsBindsLR idL idR = Bag (LHsBindLR idL idR) --- But note that the form f :: a->a = ... --- parses as a pattern binding, just like --- (f :: a -> a) = ... +data HsBindLR idL idR + = -- | FunBind is used for both functions @f x = e@ + -- and variables @f = \x -> e@ + -- + -- Reason 1: Special case for type inference: see 'TcBinds.tcMonoBinds'. + -- + -- Reason 2: Instance decls can only have FunBinds, which is convenient. + -- If you change this, you'll need to change e.g. rnMethodBinds + -- + -- But note that the form @f :: a->a = ...@ + -- parses as a pattern binding, just like + -- @(f :: a -> a) = ... @ + FunBind { - fun_id :: Located id, + fun_id :: Located idL, - fun_infix :: Bool, -- True => infix declaration + fun_infix :: Bool, -- ^ True => infix declaration - fun_matches :: MatchGroup id, -- The payload + fun_matches :: MatchGroup idR, -- ^ The payload - fun_co_fn :: ExprCoFn, -- Coercion from the type of the MatchGroup to the type of + fun_co_fn :: HsWrapper, -- ^ 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) + -- Notice that the coercion captures the free a'. - bind_fvs :: NameSet -- After the renamer, this contains a superset of the + 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 + + fun_tick :: Maybe (Int,[idR]) -- ^ This is the (optional) module-local tick number. } | PatBind { -- The pattern is never a simple variable; -- That case is done by FunBind - pat_lhs :: LPat id, - pat_rhs :: GRHSs id, + pat_lhs :: LPat idL, + pat_rhs :: GRHSs idR, 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 + var_id :: idL, -- All VarBinds are introduced by the type checker + var_rhs :: LHsExpr idR, -- Located only for consistency + var_inline :: Bool -- True <=> inline this binding regardless + -- (used for implication constraints only) } | 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 + abs_tvs :: [TyVar], + abs_dicts :: [DictId], -- Includes equality constraints + + -- AbsBinds only gets used when idL = idR after renaming, + -- but these need to be idL's for the collect... code in HsUtil to have + -- the right type + abs_exports :: [([TyVar], idL, idL, TcSpecPrags)], -- (tvs, poly_id, mono_id, prags) + abs_binds :: LHsBinds idL -- The dictionary bindings and typechecked user bindings -- mixed up together; you can tell the dict bindings because -- they are all VarBinds } @@ -135,12 +167,12 @@ placeHolderNames :: NameSet placeHolderNames = panic "placeHolderNames" ------------ -instance OutputableBndr id => Outputable (HsLocalBinds id) where +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 id => Outputable (HsValBinds id) where +instance (OutputableBndr idL, OutputableBndr idR) => Outputable (HsValBindsLR idL idR) where ppr (ValBindsIn binds sigs) = pprValBindsForUser binds sigs @@ -152,51 +184,51 @@ instance OutputableBndr id => Outputable (HsValBinds id) where 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") + 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 :: (OutputableBndr id1, OutputableBndr id2) - => LHsBinds id1 -> [LSig id2] -> SDoc +pprValBindsForUser :: (OutputableBndr idL, OutputableBndr idR, OutputableBndr id2) + => LHsBindsLR idL idR -> [LSig id2] -> SDoc pprValBindsForUser binds sigs - = vcat (map snd (sort_by_loc decls)) + = 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] + [(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 :: (OutputableBndr idL, OutputableBndr idR) => LHsBindsLR idL idR -> SDoc pprLHsBinds binds | isEmptyLHsBinds binds = empty - | otherwise = lbrace <+> vcat (map ppr (bagToList binds)) <+> rbrace + | otherwise = lbrace <+> pprDeeperList vcat (map ppr (bagToList binds)) <+> rbrace ------------ -emptyLocalBinds :: HsLocalBinds a +emptyLocalBinds :: HsLocalBindsLR a b emptyLocalBinds = EmptyLocalBinds -isEmptyLocalBinds :: HsLocalBinds a -> Bool +isEmptyLocalBinds :: HsLocalBindsLR a b -> Bool isEmptyLocalBinds (HsValBinds ds) = isEmptyValBinds ds isEmptyLocalBinds (HsIPBinds ds) = isEmptyIPBinds ds isEmptyLocalBinds EmptyLocalBinds = True -isEmptyValBinds :: HsValBinds a -> Bool +isEmptyValBinds :: HsValBindsLR a b -> Bool isEmptyValBinds (ValBindsIn ds sigs) = isEmptyLHsBinds ds && null sigs isEmptyValBinds (ValBindsOut ds sigs) = null ds && null sigs -emptyValBindsIn, emptyValBindsOut :: HsValBinds a +emptyValBindsIn, emptyValBindsOut :: HsValBindsLR a b emptyValBindsIn = ValBindsIn emptyBag [] emptyValBindsOut = ValBindsOut [] [] -emptyLHsBinds :: LHsBinds id +emptyLHsBinds :: LHsBindsLR idL idR emptyLHsBinds = emptyBag -isEmptyLHsBinds :: LHsBinds id -> Bool +isEmptyLHsBinds :: LHsBindsLR idL idR -> Bool isEmptyLHsBinds = isEmptyBag ------------ @@ -232,30 +264,45 @@ So the desugarer tries to do a better job: in (fm,gm) \begin{code} -instance OutputableBndr id => Outputable (HsBind id) where +instance (OutputableBndr idL, OutputableBndr idR) => Outputable (HsBindLR idL idR) where ppr mbind = ppr_monobind mbind -ppr_monobind :: OutputableBndr id => HsBind id -> SDoc +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 }) = 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 (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] - -- Print type signatures - $$ pprLHsBinds 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))] + = vcat [ppr gbl <+> ptext (sLit "<=") <+> ppr tvs <+> ppr lcl, + nest 2 (pprTcSpecPrags gbl prags)] +\end{code} + + +\begin{code} +pprTicks :: SDoc -> SDoc -> SDoc +-- Print stuff about ticks only when -dppr-debug is on, to avoid +-- them appearing in error messages (from the desugarer); see Trac # 3263 +pprTicks pp_no_debug pp_when_debug + = getPprStyle (\ sty -> if debugStyle sty then pp_when_debug + else pp_no_debug) \end{code} %************************************************************************ @@ -283,7 +330,7 @@ data IPBind id (LHsExpr id) instance (OutputableBndr id) => Outputable (HsIPBinds id) where - ppr (IPBinds bs ds) = vcat (map ppr bs) + ppr (IPBinds bs ds) = pprDeeperList vcat (map ppr bs) $$ pprLHsBinds ds instance (OutputableBndr id) => Outputable (IPBind id) where @@ -298,51 +345,77 @@ instance (OutputableBndr id) => Outputable (IPBind id) where %************************************************************************ \begin{code} --- A ExprCoFn is an expression with a hole in it +-- A HsWrapper 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 +data HsWrapper + = WpHole -- The identity coercion - | CoCompose ExprCoFn ExprCoFn -- (\a1..an. []) `CoCompose` (\x1..xn. []) + | WpCompose HsWrapper HsWrapper -- (\a1..an. []) `WpCompose` (\x1..xn. []) -- = (\a1..an \x1..xn. []) - | ExprCoFn Coercion -- A cast: [] `cast` co - -- Guaranteedn not the identity coercion - - -- Non-empty list in all of these, so that the identity coercion - -- is always exactly CoHole, not, say, (CoTyLams []) - | CoApps [Var] -- [] x1 .. xn; the xi are dicts or coercions - | CoTyApps [Type] -- [] t1 .. tn - | CoLams [Id] -- \x1..xn. []; the xi are dicts or coercions - | CoTyLams [TyVar] -- \a1..an. [] - | CoLet (LHsBinds Id) -- let binds in [] - -- (ould be nicer to be core bindings) - -instance Outputable ExprCoFn where - ppr CoHole = ptext SLIT("<>") - ppr (ExprCoFn co) = ppr co - ppr (CoApps ids) = ppr CoHole <+> interppSP ids - ppr (CoTyApps tys) = ppr CoHole <+> hsep (map pprParendType tys) - ppr (CoTyLams tvs) = sep [ptext SLIT("/\\") <> hsep (map (pprBndr LambdaBind) tvs), - ptext SLIT("->") <+> ppr CoHole] - ppr (CoLams ids) = sep [ptext SLIT("\\") <> hsep (map (pprBndr LambdaBind) ids), - ptext SLIT("->") <+> ppr CoHole] - ppr (CoLet binds) = sep [ptext SLIT("let") <+> braces (ppr binds), - ppr CoHole] - ppr (CoCompose co1 co2) = sep [ppr co1, ptext SLIT("<.>"), ppr co2] - -(<.>) :: ExprCoFn -> ExprCoFn -> ExprCoFn -CoHole <.> c = c -c <.> CoHole = c -c1 <.> c2 = c1 `CoCompose` c2 - -idCoercion :: ExprCoFn -idCoercion = CoHole - -isIdCoercion :: ExprCoFn -> Bool -isIdCoercion CoHole = True -isIdCoercion other = False + | WpCast Coercion -- A cast: [] `cast` co + -- Guaranteed not the identity coercion + + | WpApp Var -- [] d the 'd' is a type-class dictionary or coercion variable + + | WpTyApp Type -- [] t the 't' is a type or corecion + -- ToDo: it'd be tidier if 't' was always a type (not coercion), + -- but that is inconvenient in Inst.instCallDicts + + | WpLam Var -- \d. [] the 'd' is a type-class dictionary or coercion variable + | WpTyLam TyVar -- \a. [] the 'a' is a type variable (not coercion var) + + -- Non-empty bindings, so that the identity coercion + -- is always exactly WpHole + | WpLet (LHsBinds Id) -- let binds in [] + -- (would be nicer to be core bindings) + +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] + in + -- in debug mode, print the wrapper + -- otherwise just print what's inside + 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} @@ -360,63 +433,85 @@ serves for both. \begin{code} type LSig name = Located (Sig name) -data Sig name - = TypeSig (Located name) -- A bog-std type signature - (LHsType name) +data Sig name -- Signatures and pragmas + = -- An ordinary type signature + -- f :: Num a => a -> a + TypeSig (Located name) (LHsType name) - | SpecSig (Located name) -- Specialise a function or datatype ... - (LHsType name) -- ... to these types - InlineSpec + -- A type signature in generated code, notably the code + -- generated for record selectors. We simply record + -- the desired Id itself, replete with its name, type + -- and IdDetails. Otherwise it's just like a type + -- signature: there should be an accompanying binding + | IdSig Id + -- An ordinary fixity declaration + -- infixl *** 8 + | FixSig (FixitySig name) + + -- An inline pragma + -- {#- INLINE f #-} | InlineSig (Located name) -- Function name - InlineSpec + InlinePragma -- Never defaultInlinePragma + -- A specialisation pragma + -- {-# SPECIALISE f :: Int -> Int #-} + | SpecSig (Located name) -- Specialise a function or datatype ... + (LHsType name) -- ... to these types + InlinePragma -- The pragma on SPECIALISE_INLINE form + -- If it's just defaultInlinePragma, then we said + -- SPECIALISE, not SPECIALISE_INLINE + + -- A specialisation pragma for instance declarations only + -- {-# SPECIALISE instance Eq [Int] #-} | SpecInstSig (LHsType name) -- (Class tys); should be a specialisation of the -- current instance decl - | FixSig (FixitySig name) -- Fixity declaration type LFixitySig name = Located (FixitySig name) data FixitySig name = FixitySig (Located name) Fixity --- A Prag conveys pragmas from the type checker to the desugarer -data Prag - = InlinePrag - InlineSpec +-- TsSpecPrags conveys pragmas from the type checker to the desugarer +data TcSpecPrags + = IsDefaultMethod -- Super-specialised: a default method should + -- be macro-expanded at every call site + | SpecPrags [Located TcSpecPrag] + +data TcSpecPrag + = SpecPrag + HsWrapper -- An wrapper, that specialises the polymorphic function + InlinePragma -- Inlining spec for the specialised function - | 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 +noSpecPrags :: TcSpecPrags +noSpecPrags = SpecPrags [] -isInlinePrag (InlinePrag _) = True -isInlinePrag prag = False +hasSpecPrags :: TcSpecPrags -> Bool +hasSpecPrags (SpecPrags ps) = not (null ps) +hasSpecPrags IsDefaultMethod = False + +isDefaultMethod :: TcSpecPrags -> Bool +isDefaultMethod IsDefaultMethod = True +isDefaultMethod (SpecPrags {}) = False -isSpecPrag (SpecPrag _ _ _ _) = True -isSpecPrag prag = False \end{code} \begin{code} -okBindSig :: NameSet -> LSig Name -> Bool -okBindSig ns sig = sigForThisGroup ns sig +okBindSig :: Sig a -> Bool +okBindSig _ = True -okHsBootSig :: LSig Name -> Bool -okHsBootSig (L _ (TypeSig _ _)) = True -okHsBootSig (L _ (FixSig _)) = True -okHsBootSig sig = False +okHsBootSig :: Sig a -> Bool +okHsBootSig (TypeSig _ _) = True +okHsBootSig (FixSig _) = True +okHsBootSig _ = False -okClsDclSig :: LSig Name -> Bool -okClsDclSig (L _ (SpecInstSig _)) = False -okClsDclSig sig = True -- All others OK +okClsDclSig :: Sig a -> Bool +okClsDclSig (SpecInstSig _) = False +okClsDclSig _ = 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 +okInstDclSig :: Sig a -> Bool +okInstDclSig (TypeSig _ _) = False +okInstDclSig (FixSig _) = False +okInstDclSig _ = True sigForThisGroup :: NameSet -> LSig Name -> Bool sigForThisGroup ns sig @@ -425,54 +520,66 @@ sigForThisGroup ns sig 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 +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 :: LSig name -> Bool -- User type signatures +-- A badly-named function, but it's part of the GHCi (used +-- by Haddock) so I don't want to change it gratuitously. isVanillaLSig (L _(TypeSig {})) = True -isVanillaLSig sig = False +isVanillaLSig _ = False + +isTypeLSig :: LSig name -> Bool -- Type signatures +isTypeLSig (L _(TypeSig {})) = True +isTypeLSig (L _(IdSig {})) = True +isTypeLSig _ = False isSpecLSig :: LSig name -> Bool isSpecLSig (L _(SpecSig {})) = True -isSpecLSig sig = False +isSpecLSig _ = False +isSpecInstLSig :: LSig name -> Bool isSpecInstLSig (L _ (SpecInstSig {})) = True -isSpecInstLSig sig = False +isSpecInstLSig _ = False isPragLSig :: LSig name -> Bool -- Identifies pragmas isPragLSig (L _ (SpecSig {})) = True isPragLSig (L _ (InlineSig {})) = True -isPragLSig other = False +isPragLSig _ = 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") +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 :: LSig Name -> LSig Name -> Bool +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 s1)) (L _ (InlineSig n2 s2)) = s1 == s2 && unLoc n1 == unLoc n2 +eqHsSig (L _ (InlineSig n1 _)) (L _ (InlineSig n2 _)) = 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 @@ -484,25 +591,36 @@ 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 (TypeSig var ty) = pprVarSig (unLoc var) (ppr ty) +ppr_sig (IdSig id) = pprVarSig id (ppr (varType id)) ppr_sig (FixSig fix_sig) = ppr fix_sig -ppr_sig (SpecSig var ty inl) = pragBrackets (pprSpec var ty inl) +ppr_sig (SpecSig var ty inl) = pragBrackets (pprSpec var (ppr ty) inl) ppr_sig (InlineSig var inl) = pragBrackets (ppr inl <+> ppr var) -ppr_sig (SpecInstSig ty) = pragBrackets (ptext SLIT("SPECIALIZE instance") <+> ppr ty) +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("#-}") +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)] +pprVarSig :: (Outputable id) => id -> SDoc -> SDoc +pprVarSig var pp_ty = sep [ppr var <+> dcolon, nest 2 pp_ty] -pprSpec :: (Outputable id, Outputable ty) => id -> ty -> InlineSpec -> SDoc -pprSpec var ty inl = sep [ptext SLIT("SPECIALIZE") <+> ppr inl <+> pprVarSig var ty] +pprSpec :: (Outputable id) => id -> SDoc -> InlinePragma -> SDoc +pprSpec var pp_ty inl = ptext (sLit "SPECIALIZE") <+> pp_inl <+> pprVarSig var pp_ty + where + pp_inl | isDefaultInlinePragma inl = empty + | otherwise = ppr inl + +pprTcSpecPrags :: Outputable id => id -> TcSpecPrags -> SDoc +pprTcSpecPrags _ IsDefaultMethod = ptext (sLit "") +pprTcSpecPrags gbl (SpecPrags ps) = vcat (map (pprSpecPrag gbl) ps) -pprPrag :: Outputable id => id -> Prag -> SDoc -pprPrag var (InlinePrag inl) = ppr inl <+> ppr var -pprPrag var (SpecPrag expr ty _ inl) = pprSpec var ty inl +pprSpecPrag :: Outputable id => id -> Located TcSpecPrag -> SDoc +pprSpecPrag var (L _ (SpecPrag _expr inl)) = pprSpec var (ptext (sLit "")) inl + +instance Outputable TcSpecPrag where + ppr (SpecPrag _ p) = ptext (sLit "SpecPrag") <+> ppr p \end{code} +