% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
-HsDecls: Abstract syntax: global declarations
-Definitions for: @TyDecl@ and @oCnDecl@, @ClassDecl@,
-@InstDecl@, @DefaultDecl@ and @ForeignDecl@.
\begin{code}
{-# OPTIONS -fno-warn-incomplete-patterns #-}
-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
-- for details
+-- | Abstract syntax of global declarations.
+--
+-- Definitions for: @TyDecl@ and @ConDecl@, @ClassDecl@,
+-- @InstDecl@, @DefaultDecl@ and @ForeignDecl@.
module HsDecls (
- HsDecl(..), LHsDecl, TyClDecl(..), LTyClDecl,
- InstDecl(..), LInstDecl, DerivDecl(..), LDerivDecl, NewOrData(..),
- FamilyFlavour(..),
- RuleDecl(..), LRuleDecl, RuleBndr(..),
- DefaultDecl(..), LDefaultDecl, SpliceDecl(..),
- ForeignDecl(..), LForeignDecl, ForeignImport(..), ForeignExport(..),
- CImportSpec(..), FoType(..),
- ConDecl(..), ResType(..), ConDeclField(..), LConDecl,
- HsConDeclDetails, hsConDeclArgTys,
- DocDecl(..), LDocDecl, docDeclDoc,
- DeprecDecl(..), LDeprecDecl,
- HsGroup(..), emptyRdrGroup, emptyRnGroup, appendGroups,
- tcdName, tyClDeclNames, tyClDeclTyVars,
- isClassDecl, isSynDecl, isDataDecl, isTypeDecl, isFamilyDecl,
- isFamInstDecl,
- countTyClDecls,
- instDeclATs,
- collectRuleBndrSigTys,
+ -- * Toplevel declarations
+ HsDecl(..), LHsDecl,
+ -- ** Class or type declarations
+ TyClDecl(..), LTyClDecl,
+ isClassDecl, isSynDecl, isDataDecl, isTypeDecl, isFamilyDecl,
+ isFamInstDecl, tcdName, tyClDeclNames, tyClDeclTyVars,
+ countTyClDecls,
+ -- ** Instance declarations
+ InstDecl(..), LInstDecl, NewOrData(..), FamilyFlavour(..),
+ instDeclATs,
+ -- ** Standalone deriving declarations
+ DerivDecl(..), LDerivDecl,
+ -- ** @RULE@ declarations
+ RuleDecl(..), LRuleDecl, RuleBndr(..),
+ collectRuleBndrSigTys,
+ -- ** @default@ declarations
+ DefaultDecl(..), LDefaultDecl,
+ -- ** Top-level template haskell splice
+ SpliceDecl(..),
+ -- ** Foreign function interface declarations
+ ForeignDecl(..), LForeignDecl, ForeignImport(..), ForeignExport(..),
+ CImportSpec(..), FoType(..),
+ -- ** Data-constructor declarations
+ ConDecl(..), LConDecl, ResType(..), ConDeclField(..),
+ HsConDeclDetails, hsConDeclArgTys,
+ -- ** Document comments
+ DocDecl(..), LDocDecl, docDeclDoc,
+ -- ** Deprecations
+ WarnDecl(..), LWarnDecl,
+ -- ** Annotations
+ AnnDecl(..), LAnnDecl,
+ AnnProvenance(..), annProvenanceName_maybe, modifyAnnProvenanceNameM,
+
+ -- * Grouping
+ HsGroup(..), emptyRdrGroup, emptyRnGroup, appendGroups
) where
-- friends:
import HsBinds
import HsPat
-import HsImpExp
import HsTypes
import HsDoc
import NameSet
-import CoreSyn
import {- Kind parts of -} Type
import BasicTypes
import ForeignCall
import SrcLoc
import FastString
+import Control.Monad ( liftM )
import Data.Maybe ( isJust )
\end{code}
\begin{code}
type LHsDecl id = Located (HsDecl id)
+-- | A Haskell Declaration
data HsDecl id
- = TyClD (TyClDecl id)
- | InstD (InstDecl id)
+ = TyClD (TyClDecl id) -- ^ A type or class declaration.
+ | InstD (InstDecl id) -- ^ An instance declaration.
| DerivD (DerivDecl id)
| ValD (HsBind id)
| SigD (Sig id)
| DefD (DefaultDecl id)
| ForD (ForeignDecl id)
- | DeprecD (DeprecDecl id)
+ | WarningD (WarnDecl id)
+ | AnnD (AnnDecl id)
| RuleD (RuleDecl id)
| SpliceD (SpliceDecl id)
| DocD (DocDecl id)
--
-- The latter is for class methods only
--- A [HsDecl] is categorised into a HsGroup before being
+-- | A 'HsDecl' is categorised into a 'HsGroup' before being
-- fed to the renamer.
data HsGroup id
= HsGroup {
hs_defds :: [LDefaultDecl id],
hs_fords :: [LForeignDecl id],
- hs_depds :: [LDeprecDecl id],
+ hs_warnds :: [LWarnDecl id],
+ hs_annds :: [LAnnDecl id],
hs_ruleds :: [LRuleDecl id],
hs_docs :: [LDocDecl id]
emptyRnGroup = emptyGroup { hs_valds = emptyValBindsOut }
emptyGroup = HsGroup { hs_tyclds = [], hs_instds = [], hs_derivds = [],
- hs_fixds = [], hs_defds = [], hs_fords = [],
- hs_depds = [], hs_ruleds = [],
+ hs_fixds = [], hs_defds = [], hs_annds = [],
+ hs_fords = [], hs_warnds = [], hs_ruleds = [],
hs_valds = error "emptyGroup hs_valds: Can't happen",
hs_docs = [] }
hs_derivds = derivds1,
hs_fixds = fixds1,
hs_defds = defds1,
+ hs_annds = annds1,
hs_fords = fords1,
- hs_depds = depds1,
+ hs_warnds = warnds1,
hs_ruleds = rulds1,
hs_docs = docs1 }
HsGroup {
hs_derivds = derivds2,
hs_fixds = fixds2,
hs_defds = defds2,
+ hs_annds = annds2,
hs_fords = fords2,
- hs_depds = depds2,
+ hs_warnds = warnds2,
hs_ruleds = rulds2,
hs_docs = docs2 }
=
hs_tyclds = tyclds1 ++ tyclds2,
hs_instds = instds1 ++ instds2,
hs_derivds = derivds1 ++ derivds2,
- hs_fixds = fixds1 ++ fixds2,
+ hs_fixds = fixds1 ++ fixds2,
+ hs_annds = annds1 ++ annds2,
hs_defds = defds1 ++ defds2,
hs_fords = fords1 ++ fords2,
- hs_depds = depds1 ++ depds2,
+ hs_warnds = warnds1 ++ warnds2,
hs_ruleds = rulds1 ++ rulds2,
hs_docs = docs1 ++ docs2 }
\end{code}
ppr (ForD fd) = ppr fd
ppr (SigD sd) = ppr sd
ppr (RuleD rd) = ppr rd
- ppr (DeprecD dd) = ppr dd
+ ppr (WarningD wd) = ppr wd
+ ppr (AnnD ad) = ppr ad
ppr (SpliceD dd) = ppr dd
ppr (DocD doc) = ppr doc
hs_instds = inst_decls,
hs_derivds = deriv_decls,
hs_fixds = fix_decls,
- hs_depds = deprec_decls,
+ hs_warnds = deprec_decls,
+ hs_annds = ann_decls,
hs_fords = foreign_decls,
hs_defds = default_decls,
hs_ruleds = rule_decls })
= vcat [ppr_ds fix_decls, ppr_ds default_decls,
- ppr_ds deprec_decls, ppr_ds rule_decls,
+ ppr_ds deprec_decls, ppr_ds ann_decls,
+ ppr_ds rule_decls,
ppr val_decls,
ppr_ds tycl_decls, ppr_ds inst_decls,
ppr_ds deriv_decls,
type LTyClDecl name = Located (TyClDecl name)
+-- | A type or class declaration.
data TyClDecl name
= ForeignType {
tcdLName :: Located name,
tcdFoType :: FoType
}
- -- type/data/newtype family T :: *->*
- | TyFamily { tcdFlavour:: FamilyFlavour, -- type, new, or data
+
+ | -- | @type/data/newtype family T :: *->*@
+ TyFamily { tcdFlavour:: FamilyFlavour, -- type, new, or data
tcdLName :: Located name, -- type constructor
tcdTyVars :: [LHsTyVarBndr name], -- type variables
tcdKind :: Maybe Kind -- result kind
}
- -- Declares a data type or newtype, giving its construcors
- -- data/newtype T a = <constrs>
- -- data/newtype instance T [a] = <constrs>
- | TyData { tcdND :: NewOrData,
- tcdCtxt :: LHsContext name, -- Context
- tcdLName :: Located name, -- Type constructor
-
- tcdTyVars :: [LHsTyVarBndr name], -- Type variables
-
- tcdTyPats :: Maybe [LHsType name], -- Type patterns
- -- Just [t1..tn] for data instance T t1..tn = ...
- -- in this case tcdTyVars = fv( tcdTyPats )
- -- Nothing for everything else
- tcdKindSig:: Maybe Kind, -- Optional kind sig
- -- (Just k) for a GADT-style 'data', or 'data
- -- instance' decl with explicit kind sig
+ | -- | Declares a data type or newtype, giving its construcors
+ -- @
+ -- data/newtype T a = <constrs>
+ -- data/newtype instance T [a] = <constrs>
+ -- @
+ TyData { tcdND :: NewOrData,
+ tcdCtxt :: LHsContext name, -- ^ Context
+ tcdLName :: Located name, -- ^ Type constructor
- tcdCons :: [LConDecl name], -- Data constructors
- -- For data T a = T1 | T2 a
- -- the LConDecls all have ResTyH98
- -- For data T a where { T1 :: T a }
- -- the LConDecls all have ResTyGADT
+ tcdTyVars :: [LHsTyVarBndr name], -- ^ Type variables
+
+ tcdTyPats :: Maybe [LHsType name],
+ -- ^ Type patterns.
+ --
+ -- @Just [t1..tn]@ for @data instance T t1..tn = ...@
+ -- in this case @tcdTyVars = fv( tcdTyPats )@.
+ -- @Nothing@ for everything else.
+
+ tcdKindSig:: Maybe Kind,
+ -- ^ Optional kind signature.
+ --
+ -- @(Just k)@ for a GADT-style @data@, or @data
+ -- instance@ decl with explicit kind sig
+
+ tcdCons :: [LConDecl name],
+ -- ^ Data constructors
+ --
+ -- For @data T a = T1 | T2 a@
+ -- the 'LConDecl's all have 'ResTyH98'.
+ -- For @data T a where { T1 :: T a }@
+ -- the 'LConDecls' all have 'ResTyGADT'.
tcdDerivs :: Maybe [LHsType name]
- -- Derivings; Nothing => not specified
- -- Just [] => derive exactly what is asked
+ -- ^ Derivings; @Nothing@ => not specified,
+ -- @Just []@ => derive exactly what is asked
+ --
-- These "types" must be of form
+ -- @
-- forall ab. C ty1 ty2
+ -- @
-- Typically the foralls and ty args are empty, but they
-- are non-empty for the newtype-deriving case
}
- | TySynonym { tcdLName :: Located name, -- type constructor
- tcdTyVars :: [LHsTyVarBndr name], -- type variables
- tcdTyPats :: Maybe [LHsType name], -- Type patterns
+ | TySynonym { tcdLName :: Located name, -- ^ type constructor
+ tcdTyVars :: [LHsTyVarBndr name], -- ^ type variables
+ tcdTyPats :: Maybe [LHsType name], -- ^ Type patterns
-- See comments for tcdTyPats in TyData
-- 'Nothing' => vanilla type synonym
- tcdSynRhs :: LHsType name -- synonym expansion
+ tcdSynRhs :: LHsType name -- ^ synonym expansion
}
- | ClassDecl { tcdCtxt :: LHsContext name, -- Context...
- tcdLName :: Located name, -- Name of the class
- tcdTyVars :: [LHsTyVarBndr name], -- Class type variables
- tcdFDs :: [Located (FunDep name)], -- Functional deps
- tcdSigs :: [LSig name], -- Methods' signatures
- tcdMeths :: LHsBinds name, -- Default methods
- tcdATs :: [LTyClDecl name], -- Associated types; ie
+ | ClassDecl { tcdCtxt :: LHsContext name, -- ^ Context...
+ tcdLName :: Located name, -- ^ Name of the class
+ tcdTyVars :: [LHsTyVarBndr name], -- ^ Class type variables
+ tcdFDs :: [Located (FunDep name)], -- ^ Functional deps
+ tcdSigs :: [LSig name], -- ^ Methods' signatures
+ tcdMeths :: LHsBinds name, -- ^ Default methods
+ tcdATs :: [LTyClDecl name], -- ^ Associated types; ie
-- only 'TyFamily' and
-- 'TySynonym'; the
-- latter for defaults
- tcdDocs :: [LDocDecl name] -- Haddock docs
+ tcdDocs :: [LDocDecl name] -- ^ Haddock docs
}
data NewOrData
- = NewType -- "newtype Blah ..."
- | DataType -- "data Blah ..."
+ = NewType -- ^ @newtype Blah ...@
+ | DataType -- ^ @data Blah ...@
deriving( Eq ) -- Needed because Demand derives Eq
data FamilyFlavour
- = TypeFamily -- "type family ..."
- | DataFamily -- "data family ..."
+ = TypeFamily -- ^ @type family ...@
+ | DataFamily -- ^ @data family ...@
\end{code}
Simple classifiers
\begin{code}
-isDataDecl, isTypeDecl, isSynDecl, isClassDecl, isFamilyDecl, isFamInstDecl ::
- TyClDecl name -> Bool
-
--- data/newtype or data/newtype instance declaration
+-- | @True@ <=> argument is a @data@\/@newtype@ or @data@\/@newtype instance@
+-- declaration.
+isDataDecl :: TyClDecl name -> Bool
isDataDecl (TyData {}) = True
isDataDecl _other = False
--- type or type instance declaration
+-- | type or type instance declaration
+isTypeDecl :: TyClDecl name -> Bool
isTypeDecl (TySynonym {}) = True
isTypeDecl _other = False
--- vanilla Haskell type synonym (ie, not a type instance)
+-- | vanilla Haskell type synonym (ie, not a type instance)
+isSynDecl :: TyClDecl name -> Bool
isSynDecl (TySynonym {tcdTyPats = Nothing}) = True
isSynDecl _other = False
--- type class
+-- | type class
+isClassDecl :: TyClDecl name -> Bool
isClassDecl (ClassDecl {}) = True
isClassDecl _ = False
--- type family declaration
+-- | type family declaration
+isFamilyDecl :: TyClDecl name -> Bool
isFamilyDecl (TyFamily {}) = True
isFamilyDecl _other = False
--- family instance (types, newtypes, and data types)
+-- | family instance (types, newtypes, and data types)
+isFamInstDecl :: TyClDecl name -> Bool
isFamInstDecl tydecl
| isTypeDecl tydecl
|| isDataDecl tydecl = isJust (tcdTyPats tydecl)
tcdName decl = unLoc (tcdLName decl)
tyClDeclNames :: Eq name => TyClDecl name -> [Located name]
--- Returns all the *binding* names of the decl, along with their SrcLocs
--- The first one is guaranteed to be the name of the decl
--- For record fields, the first one counts as the SrcLoc
--- We use the equality to filter out duplicate field names
+-- ^ Returns all the /binding/ names of the decl, along with their SrcLocs.
+-- The first one is guaranteed to be the name of the decl. For record fields
+-- mentioned in multiple constructors, the SrcLoc will be from the first
+-- occurence. We use the equality to filter out duplicate field names
tyClDeclNames (TyFamily {tcdLName = name}) = [name]
tyClDeclNames (TySynonym {tcdLName = name}) = [name]
data ConDecl name
= ConDecl
- { con_name :: Located name -- Constructor name; this is used for the
- -- DataCon itself, and for the user-callable wrapper Id
+ { con_name :: Located name
+ -- ^ Constructor name. This is used for the DataCon itself, and for
+ -- the user-callable wrapper Id.
- , con_explicit :: HsExplicitForAll -- Is there an user-written forall? (cf. HStypes.HsForAllTy)
+ , con_explicit :: HsExplicitForAll
+ -- ^ Is there an user-written forall? (cf. 'HsTypes.HsForAllTy')
- , con_qvars :: [LHsTyVarBndr name] -- ResTyH98: the constructor's existential type variables
- -- ResTyGADT: all the constructor's quantified type variables
+ , con_qvars :: [LHsTyVarBndr name]
+ -- ^ Type variables. Depending on 'con_res' this describes the
+ -- follewing entities
+ --
+ -- - ResTyH98: the constructor's existential type variables
+ --
+ -- - ResTyGADT: all the constructor's quantified type variables
- , con_cxt :: LHsContext name -- The context. This *does not* include the
- -- "stupid theta" which lives only in the TyData decl
+ , con_cxt :: LHsContext name
+ -- ^ The context. This /does not/ include the \"stupid theta\" which
+ -- lives only in the 'TyData' decl.
- , con_details :: HsConDeclDetails name -- The main payload
+ , con_details :: HsConDeclDetails name
+ -- ^ The main payload
- , con_res :: ResType name -- Result type of the constructor
+ , con_res :: ResType name
+ -- ^ Result type of the constructor
- , con_doc :: Maybe (LHsDoc name) -- A possible Haddock comment
+ , con_doc :: Maybe (LHsDoc name)
+ -- ^ A possible Haddock comment.
}
type HsConDeclDetails name = HsConDetails (LBangType name) [ConDeclField name]
pprConDecl (ConDecl con expl tvs cxt details ResTyH98 doc)
= sep [ppr_mbDoc doc, pprHsForAll expl tvs cxt, ppr_details con details]
where
- ppr_details con (InfixCon t1 t2) = hsep [ppr t1, pprHsVar con, ppr t2]
+ ppr_details con (InfixCon t1 t2) = hsep [ppr t1, pprHsInfix con, ppr t2]
ppr_details con (PrefixCon tys) = hsep (pprHsVar con : map ppr tys)
ppr_details con (RecCon fields) = ppr con <+> ppr_fields fields
We use exported entities for things to deprecate.
\begin{code}
-type LDeprecDecl name = Located (DeprecDecl name)
+type LWarnDecl name = Located (WarnDecl name)
-data DeprecDecl name = Deprecation name DeprecTxt
+data WarnDecl name = Warning name WarningTxt
-instance OutputableBndr name => Outputable (DeprecDecl name) where
- ppr (Deprecation thing txt)
+instance OutputableBndr name => Outputable (WarnDecl name) where
+ ppr (Warning thing txt)
= hsep [text "{-# DEPRECATED", ppr thing, doubleQuotes (ppr txt), text "#-}"]
\end{code}
+
+%************************************************************************
+%* *
+\subsection[AnnDecl]{Annotations}
+%* *
+%************************************************************************
+
+\begin{code}
+type LAnnDecl name = Located (AnnDecl name)
+
+data AnnDecl name = HsAnnotation (AnnProvenance name) (Located (HsExpr name))
+
+instance (OutputableBndr name) => Outputable (AnnDecl name) where
+ ppr (HsAnnotation provenance expr)
+ = hsep [text "{-#", pprAnnProvenance provenance, pprExpr (unLoc expr), text "#-}"]
+
+
+data AnnProvenance name = ValueAnnProvenance name
+ | TypeAnnProvenance name
+ | ModuleAnnProvenance
+
+annProvenanceName_maybe :: AnnProvenance name -> Maybe name
+annProvenanceName_maybe (ValueAnnProvenance name) = Just name
+annProvenanceName_maybe (TypeAnnProvenance name) = Just name
+annProvenanceName_maybe ModuleAnnProvenance = Nothing
+
+-- TODO: Replace with Traversable instance when GHC bootstrap version rises high enough
+modifyAnnProvenanceNameM :: Monad m => (before -> m after) -> AnnProvenance before -> m (AnnProvenance after)
+modifyAnnProvenanceNameM fm prov =
+ case prov of
+ ValueAnnProvenance name -> liftM ValueAnnProvenance (fm name)
+ TypeAnnProvenance name -> liftM TypeAnnProvenance (fm name)
+ ModuleAnnProvenance -> return ModuleAnnProvenance
+
+pprAnnProvenance :: OutputableBndr name => AnnProvenance name -> SDoc
+pprAnnProvenance ModuleAnnProvenance = ptext (sLit "ANN module")
+pprAnnProvenance (ValueAnnProvenance name) = ptext (sLit "ANN") <+> ppr name
+pprAnnProvenance (TypeAnnProvenance name) = ptext (sLit "ANN type") <+> ppr name
+\end{code}