{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -- Wrinkle in Note [Trees That Grow] -- in module Language.Haskell.Syntax.Extension {-# LANGUAGE ViewPatterns #-} {- (c) The University of Glasgow 2006 (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 \section[HsBinds]{Abstract syntax: top-level bindings and signatures} Datatype for: @BindGroup@, @Bind@, @Sig@, @Bind@. -} -- See Note [Language.Haskell.Syntax.* Hierarchy] for why not GHC.Hs.* module Language.Haskell.Syntax.Binds where import {-# SOURCE #-} Language.Haskell.Syntax.Expr ( LHsExpr , MatchGroup , GRHSs ) import {-# SOURCE #-} Language.Haskell.Syntax.Pat ( LPat ) import Language.Haskell.Syntax.Extension import Language.Haskell.Syntax.Type import GHC.Types.Fixity (Fixity) import GHC.Types.Basic (InlinePragma) import GHC.Data.BooleanFormula (LBooleanFormula) import GHC.Types.SourceText (StringLiteral) import Data.Void import Data.Bool import Data.Maybe {- ************************************************************************ * * \subsection{Bindings: @BindGroup@} * * ************************************************************************ Global bindings (where clauses) -} -- During renaming, we need bindings where the left-hand sides -- have been renamed but the right-hand sides have not. -- Other than during renaming, these will be the same. -- | Haskell Local Bindings type HsLocalBinds id = HsLocalBindsLR id id -- | Located Haskell local bindings type LHsLocalBinds id = XRec id (HsLocalBinds id) -- | Haskell Local Bindings with separate Left and Right identifier types -- -- Bindings in a 'let' expression -- or a 'where' clause data HsLocalBindsLR idL idR = HsValBinds (XHsValBinds idL idR) (HsValBindsLR idL idR) -- ^ Haskell Value Bindings -- There should be no pattern synonyms in the HsValBindsLR -- These are *local* (not top level) bindings -- The parser accepts them, however, leaving the -- renamer to report them | HsIPBinds (XHsIPBinds idL idR) (HsIPBinds idR) -- ^ Haskell Implicit Parameter Bindings | EmptyLocalBinds (XEmptyLocalBinds idL idR) -- ^ Empty Local Bindings | XHsLocalBindsLR !(XXHsLocalBindsLR idL idR) type LHsLocalBindsLR idL idR = XRec idL (HsLocalBindsLR idL idR) -- | Haskell Value Bindings type HsValBinds id = HsValBindsLR id id -- | Haskell Value bindings with separate Left and Right identifier types -- (not implicit parameters) -- Used for both top level and nested bindings -- May contain pattern synonym bindings data HsValBindsLR idL idR = -- | Value Bindings In -- -- Before renaming RHS; idR is always RdrName -- Not dependency analysed -- Recursive by default ValBinds (XValBinds idL idR) (LHsBindsLR idL idR) [LSig idR] -- | Value Bindings Out -- -- After renaming RHS; idR can be Name or Id Dependency analysed, -- later bindings in the list may depend on earlier ones. | XValBindsLR !(XXValBindsLR idL idR) -- --------------------------------------------------------------------- -- | Located Haskell Binding type LHsBind id = LHsBindLR id id -- | Located Haskell Bindings type LHsBinds id = LHsBindsLR id id -- | Haskell Binding type HsBind id = HsBindLR id id -- | Located Haskell Bindings with separate Left and Right identifier types type LHsBindsLR idL idR = [LHsBindLR idL idR] -- | Located Haskell Binding with separate Left and Right identifier types type LHsBindLR idL idR = XRec idL (HsBindLR idL idR) {- Note [FunBind vs PatBind] ~~~~~~~~~~~~~~~~~~~~~~~~~ The distinction between FunBind and PatBind is a bit subtle. FunBind covers patterns which resemble function bindings and simple variable bindings. f x = e f !x = e f = e !x = e -- FunRhs has SrcStrict x `f` y = e -- FunRhs has Infix The actual patterns and RHSs of a FunBind are encoding in fun_matches. The m_ctxt field of each Match in fun_matches will be FunRhs and carries two bits of information about the match, * The mc_fixity field on each Match describes the fixity of the function binder in that match. E.g. this is legal: f True False = e1 True `f` True = e2 * The mc_strictness field is used /only/ for nullary FunBinds: ones with one Match, which has no pats. For these, it describes whether the match is decorated with a bang (e.g. `!x = e`). By contrast, PatBind represents data constructor patterns, as well as a few other interesting cases. Namely, Just x = e (x) = e x :: Ty = e Note [Multiplicity annotations] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Multiplicity annotations are stored in the pat_mult field on PatBinds, represented by the HsMultAnn data type HsNoMultAnn <=> no annotation in the source file HsPct1Ann <=> the %1 annotation HsMultAnn <=> the %t annotation, where `t` is some type In case of HsNoMultAnn the typechecker infers a multiplicity. We don't need to store a multiplicity on FunBinds: - let %1 x = … is parsed as a PatBind. So we don't need an annotation before typechecking. - the multiplicity that the typechecker infers is stored in the binder's Var for the desugarer to use. It's only relevant for strict FunBinds, see Wrinkle 1 in Note [Desugar Strict binds] in GHC.HsToCore.Binds as, in Core, let expressions don't have multiplicity annotations. -} -- | Haskell Binding with separate Left and Right id's data HsBindLR idL idR = -- | Function-like Binding -- -- FunBind is used for both functions @f x = e@ -- and variables @f = \x -> e@ -- and strict variables @!x = x + 1@ -- -- Reason 1: Special case for type inference: see 'GHC.Tc.Gen.Bind.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) = ... @ -- -- Strict bindings have their strictness recorded in the 'SrcStrictness' of their -- 'MatchContext'. See Note [FunBind vs PatBind] for -- details about the relationship between FunBind and PatBind. -- -- 'GHC.Parser.Annotation.AnnKeywordId's -- -- - 'GHC.Parser.Annotation.AnnFunId', attached to each element of fun_matches -- -- - 'GHC.Parser.Annotation.AnnEqual','GHC.Parser.Annotation.AnnWhere', -- 'GHC.Parser.Annotation.AnnOpen','GHC.Parser.Annotation.AnnClose', -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation FunBind { forall idL idR. HsBindLR idL idR -> XFunBind idL idR fun_ext :: XFunBind idL idR, forall idL idR. HsBindLR idL idR -> LIdP idL fun_id :: LIdP idL, -- Note [fun_id in Match] in GHC.Hs.Expr forall idL idR. HsBindLR idL idR -> MatchGroup idR (LHsExpr idR) fun_matches :: MatchGroup idR (LHsExpr idR) -- ^ The payload } -- | Pattern Binding -- -- The pattern is never a simple variable; -- That case is done by FunBind. -- See Note [FunBind vs PatBind] for details about the -- relationship between FunBind and PatBind. -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnBang', -- 'GHC.Parser.Annotation.AnnEqual','GHC.Parser.Annotation.AnnWhere', -- 'GHC.Parser.Annotation.AnnOpen','GHC.Parser.Annotation.AnnClose', -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | PatBind { forall idL idR. HsBindLR idL idR -> XPatBind idL idR pat_ext :: XPatBind idL idR, forall idL idR. HsBindLR idL idR -> LPat idL pat_lhs :: LPat idL, forall idL idR. HsBindLR idL idR -> HsMultAnn idL pat_mult :: HsMultAnn idL, -- ^ See Note [Multiplicity annotations]. forall idL idR. HsBindLR idL idR -> GRHSs idR (LHsExpr idR) pat_rhs :: GRHSs idR (LHsExpr idR) } -- | Variable Binding -- -- Dictionary binding and suchlike. -- All VarBinds are introduced by the type checker | VarBind { forall idL idR. HsBindLR idL idR -> XVarBind idL idR var_ext :: XVarBind idL idR, forall idL idR. HsBindLR idL idR -> IdP idL var_id :: IdP idL, forall idL idR. HsBindLR idL idR -> LHsExpr idR var_rhs :: LHsExpr idR -- ^ Located only for consistency } -- | Patterns Synonym Binding | PatSynBind (XPatSynBind idL idR) (PatSynBind idL idR) -- ^ - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnPattern', -- 'GHC.Parser.Annotation.AnnLarrow','GHC.Parser.Annotation.AnnEqual', -- 'GHC.Parser.Annotation.AnnWhere' -- 'GHC.Parser.Annotation.AnnOpen' @'{'@,'GHC.Parser.Annotation.AnnClose' @'}'@ -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | XHsBindsLR !(XXHsBindsLR idL idR) -- | - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnPattern', -- 'GHC.Parser.Annotation.AnnEqual','GHC.Parser.Annotation.AnnLarrow', -- 'GHC.Parser.Annotation.AnnWhere','GHC.Parser.Annotation.AnnOpen' @'{'@, -- 'GHC.Parser.Annotation.AnnClose' @'}'@, -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation -- | Pattern Synonym binding data PatSynBind idL idR = PSB { forall idL idR. PatSynBind idL idR -> XPSB idL idR psb_ext :: XPSB idL idR, forall idL idR. PatSynBind idL idR -> LIdP idL psb_id :: LIdP idL, -- ^ Name of the pattern synonym forall idL idR. PatSynBind idL idR -> HsPatSynDetails idR psb_args :: HsPatSynDetails idR, -- ^ Formal parameter names forall idL idR. PatSynBind idL idR -> LPat idR psb_def :: LPat idR, -- ^ Right-hand side forall idL idR. PatSynBind idL idR -> HsPatSynDir idR psb_dir :: HsPatSynDir idR -- ^ Directionality } | XPatSynBind !(XXPatSynBind idL idR) -- | Multiplicity annotations, on binders, are always resolved (to a unification -- variable if there is no annotation) during type-checking. The resolved -- multiplicity is stored in the extension fields. data HsMultAnn pass = HsNoMultAnn !(XNoMultAnn pass) | HsPct1Ann !(XPct1Ann pass) | HsMultAnn !(XMultAnn pass) (LHsType (NoGhcTc pass)) | XMultAnn !(XXMultAnn pass) type family XNoMultAnn p type family XPct1Ann p type family XMultAnn p type family XXMultAnn p {- ************************************************************************ * * Implicit parameter bindings * * ************************************************************************ -} -- | Haskell Implicit Parameter Bindings data HsIPBinds id = IPBinds (XIPBinds id) [LIPBind id] -- TcEvBinds -- Only in typechecker output; binds -- -- uses of the implicit parameters | XHsIPBinds !(XXHsIPBinds id) -- | Located Implicit Parameter Binding type LIPBind id = XRec id (IPBind id) -- ^ May have 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnSemi' when in a -- list -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation -- | Implicit parameter bindings. -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnEqual' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation data IPBind id = IPBind (XCIPBind id) (XRec id HsIPName) (LHsExpr id) | XIPBind !(XXIPBind id) {- ************************************************************************ * * \subsection{@Sig@: type signatures and value-modifying user pragmas} * * ************************************************************************ It is convenient to lump ``value-modifying'' user-pragmas (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. -} -- | Located Signature type LSig pass = XRec pass (Sig pass) -- | Signatures and pragmas data Sig pass = -- | An ordinary type signature -- -- > f :: Num a => a -> a -- -- After renaming, this list of Names contains the named -- wildcards brought into scope by this signature. For a signature -- @_ -> _a -> Bool@, the renamer will leave the unnamed wildcard @_@ -- untouched, and the named wildcard @_a@ is then replaced with -- fresh meta vars in the type. Their names are stored in the type -- signature that brought them into scope, in this third field to be -- more specific. -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnDcolon', -- 'GHC.Parser.Annotation.AnnComma' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation TypeSig (XTypeSig pass) [LIdP pass] -- LHS of the signature; e.g. f,g,h :: blah (LHsSigWcType pass) -- RHS of the signature; can have wildcards -- | A pattern synonym type signature -- -- > pattern Single :: () => (Show a) => a -> [a] -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnPattern', -- 'GHC.Parser.Annotation.AnnDcolon','GHC.Parser.Annotation.AnnForall' -- 'GHC.Parser.Annotation.AnnDot','GHC.Parser.Annotation.AnnDarrow' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | PatSynSig (XPatSynSig pass) [LIdP pass] (LHsSigType pass) -- P :: forall a b. Req => Prov => ty -- | A signature for a class method -- False: ordinary class-method signature -- True: generic-default class method signature -- e.g. class C a where -- op :: a -> a -- Ordinary -- default op :: Eq a => a -> a -- Generic default -- No wildcards allowed here -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnDefault', -- 'GHC.Parser.Annotation.AnnDcolon' | ClassOpSig (XClassOpSig pass) Bool [LIdP pass] (LHsSigType pass) -- | An ordinary fixity declaration -- -- > infixl 8 *** -- -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnInfix', -- 'GHC.Parser.Annotation.AnnVal' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | FixSig (XFixSig pass) (FixitySig pass) -- | An inline pragma -- -- > {#- INLINE f #-} -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : -- 'GHC.Parser.Annotation.AnnOpen' @'{-\# INLINE'@ and @'['@, -- 'GHC.Parser.Annotation.AnnClose','GHC.Parser.Annotation.AnnOpen', -- 'GHC.Parser.Annotation.AnnVal','GHC.Parser.Annotation.AnnTilde', -- 'GHC.Parser.Annotation.AnnClose' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | InlineSig (XInlineSig pass) (LIdP pass) -- Function name InlinePragma -- Never defaultInlinePragma -- | A specialisation pragma -- -- > {-# SPECIALISE f :: Int -> Int #-} -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnOpen', -- 'GHC.Parser.Annotation.AnnOpen' @'{-\# SPECIALISE'@ and @'['@, -- 'GHC.Parser.Annotation.AnnTilde', -- 'GHC.Parser.Annotation.AnnVal', -- 'GHC.Parser.Annotation.AnnClose' @']'@ and @'\#-}'@, -- 'GHC.Parser.Annotation.AnnDcolon' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | SpecSig (XSpecSig pass) (LIdP pass) -- Specialise a function or datatype ... [LHsSigType pass] -- ... 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] #-} -- -- (Class tys); should be a specialisation of the -- current instance declaration -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnOpen', -- 'GHC.Parser.Annotation.AnnInstance','GHC.Parser.Annotation.AnnClose' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | SpecInstSig (XSpecInstSig pass) (LHsSigType pass) -- | A minimal complete definition pragma -- -- > {-# MINIMAL a | (b, c | (d | e)) #-} -- -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnOpen', -- 'GHC.Parser.Annotation.AnnVbar','GHC.Parser.Annotation.AnnComma', -- 'GHC.Parser.Annotation.AnnClose' -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation | MinimalSig (XMinimalSig pass) (LBooleanFormula (LIdP pass)) -- | A "set cost centre" pragma for declarations -- -- > {-# SCC funName #-} -- -- or -- -- > {-# SCC funName "cost_centre_name" #-} | SCCFunSig (XSCCFunSig pass) (LIdP pass) -- Function name (Maybe (XRec pass StringLiteral)) -- | A complete match pragma -- -- > {-# COMPLETE C, D [:: T] #-} -- -- Used to inform the pattern match checker about additional -- complete matchings which, for example, arise from pattern -- synonym definitions. | CompleteMatchSig (XCompleteMatchSig pass) [LIdP pass] (Maybe (LIdP pass)) | XSig !(XXSig pass) -- | Located Fixity Signature type LFixitySig pass = XRec pass (FixitySig pass) -- | Fixity Signature data FixitySig pass = FixitySig (XFixitySig pass) [LIdP pass] Fixity | XFixitySig !(XXFixitySig pass) isFixityLSig :: forall p. UnXRec p => LSig p -> Bool isFixityLSig :: forall p. UnXRec p => LSig p -> Bool isFixityLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> FixSig {}) = Bool True isFixityLSig LSig p _ = Bool False isTypeLSig :: forall p. UnXRec p => LSig p -> Bool -- Type signatures isTypeLSig :: forall p. UnXRec p => LSig p -> Bool isTypeLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> TypeSig {}) = Bool True isTypeLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> ClassOpSig {}) = Bool True isTypeLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> XSig {}) = Bool True isTypeLSig LSig p _ = Bool False isSpecLSig :: forall p. UnXRec p => LSig p -> Bool isSpecLSig :: forall p. UnXRec p => LSig p -> Bool isSpecLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> SpecSig {}) = Bool True isSpecLSig LSig p _ = Bool False isSpecInstLSig :: forall p. UnXRec p => LSig p -> Bool isSpecInstLSig :: forall p. UnXRec p => LSig p -> Bool isSpecInstLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> SpecInstSig {}) = Bool True isSpecInstLSig LSig p _ = Bool False isPragLSig :: forall p. UnXRec p => LSig p -> Bool -- Identifies pragmas isPragLSig :: forall p. UnXRec p => LSig p -> Bool isPragLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> SpecSig {}) = Bool True isPragLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> InlineSig {}) = Bool True isPragLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> SCCFunSig {}) = Bool True isPragLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> CompleteMatchSig {}) = Bool True isPragLSig LSig p _ = Bool False isInlineLSig :: forall p. UnXRec p => LSig p -> Bool -- Identifies inline pragmas isInlineLSig :: forall p. UnXRec p => LSig p -> Bool isInlineLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> InlineSig {}) = Bool True isInlineLSig LSig p _ = Bool False isMinimalLSig :: forall p. UnXRec p => LSig p -> Bool isMinimalLSig :: forall p. UnXRec p => LSig p -> Bool isMinimalLSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> MinimalSig {}) = Bool True isMinimalLSig LSig p _ = Bool False isSCCFunSig :: forall p. UnXRec p => LSig p -> Bool isSCCFunSig :: forall p. UnXRec p => LSig p -> Bool isSCCFunSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> SCCFunSig {}) = Bool True isSCCFunSig LSig p _ = Bool False isCompleteMatchSig :: forall p. UnXRec p => LSig p -> Bool isCompleteMatchSig :: forall p. UnXRec p => LSig p -> Bool isCompleteMatchSig (forall p a. UnXRec p => XRec p a -> a unXRec @p -> CompleteMatchSig {} ) = Bool True isCompleteMatchSig LSig p _ = Bool False {- ************************************************************************ * * \subsection[PatSynBind]{A pattern synonym definition} * * ************************************************************************ -} -- | Haskell Pattern Synonym Details type HsPatSynDetails pass = HsConDetails Void (LIdP pass) [RecordPatSynField pass] -- See Note [Record PatSyn Fields] -- | Record Pattern Synonym Field data RecordPatSynField pass = RecordPatSynField { forall pass. RecordPatSynField pass -> FieldOcc pass recordPatSynField :: FieldOcc pass -- ^ Field label visible in rest of the file , forall pass. RecordPatSynField pass -> LIdP pass recordPatSynPatVar :: LIdP pass -- ^ Filled in by renamer, the name used internally by the pattern } {- Note [Record PatSyn Fields] ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider the following two pattern synonyms. pattern P x y = ([x,True], [y,'v']) pattern Q{ x, y } =([x,True], [y,'v']) In P, we just have two local binders, x and y. In Q, we have local binders but also top-level record selectors x :: ([Bool], [Char]) -> Bool y :: ([Bool], [Char]) -> Char Both are recorded in the `RecordPatSynField`s for `x` and `y`: * recordPatSynField: the top-level record selector * recordPatSynPatVar: the local `x`, bound only in the RHS of the pattern synonym. It would make sense to support record-like syntax pattern Q{ x=x1, y=y1 } = ([x1,True], [y1,'v']) when we have a different name for the local and top-level binder, making the distinction between the two names clear. -} -- | Haskell Pattern Synonym Direction data HsPatSynDir id = Unidirectional | ImplicitBidirectional | ExplicitBidirectional (MatchGroup id (LHsExpr id))