% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
-
-HsExpr: Abstract Haskell syntax: expressions
-
\begin{code}
+
+-- | Abstract Haskell syntax for expressions.
module HsExpr where
#include "HsVersions.h"
import HsPat
import HsLit
import HsTypes
-import HsImpExp
import HsBinds
-- others:
%************************************************************************
\begin{code}
+-- * Expressions proper
+
type LHsExpr id = Located (HsExpr id)
-------------------------
--- PostTcExpr is an evidence expression attached to the
--- syntax tree by the type checker (c.f. postTcType)
--- We use a PostTcTable where there are a bunch of pieces of
--- evidence, more than is convenient to keep individually
+-- | PostTcExpr is an evidence expression attached to the syntax tree by the
+-- type checker (c.f. postTcType).
type PostTcExpr = HsExpr Id
+-- | We use a PostTcTable where there are a bunch of pieces of evidence, more
+-- than is convenient to keep individually.
type PostTcTable = [(Name, Id)]
noPostTcExpr :: PostTcExpr
noPostTcTable = []
-------------------------
--- SyntaxExpr is like PostTcExpr, but it's filled in a little earlier,
+-- | SyntaxExpr is like 'PostTcExpr', but it's filled in a little earlier,
-- by the renamer. It's used for rebindable syntax.
--- E.g. (>>=) is filled in before the renamer by the appropriate Name
--- for (>>=), and then instantiated by the type checker with its
--- type args tec
+--
+-- E.g. @(>>=)@ is filled in before the renamer by the appropriate 'Name' for
+-- @(>>=)@, and then instantiated by the type checker with its type args
+-- tec
type SyntaxExpr id = HsExpr id
type SyntaxTable id = [(Name, SyntaxExpr id)]
--- *** Currently used only for CmdTop (sigh) ***
--- * Before the renamer, this list is noSyntaxTable
+-- ^ Currently used only for 'CmdTop' (sigh)
--
--- * After the renamer, it takes the form [(std_name, HsVar actual_name)]
+-- * Before the renamer, this list is 'noSyntaxTable'
+--
+-- * After the renamer, it takes the form @[(std_name, HsVar actual_name)]@
-- For example, for the 'return' op of a monad
--- normal case: (GHC.Base.return, HsVar GHC.Base.return)
--- with rebindable syntax: (GHC.Base.return, return_22)
--- where return_22 is whatever "return" is in scope
--
--- * After the type checker, it takes the form [(std_name, <expression>)]
--- where <expression> is the evidence for the method
+-- * normal case: @(GHC.Base.return, HsVar GHC.Base.return)@
+--
+-- * with rebindable syntax: @(GHC.Base.return, return_22)@
+-- where @return_22@ is whatever @return@ is in scope
+--
+-- * After the type checker, it takes the form @[(std_name, <expression>)]@
+-- where @<expression>@ is the evidence for the method
noSyntaxTable :: SyntaxTable id
noSyntaxTable = []
-------------------------
+-- | A Haskell expression.
data HsExpr id
- = HsVar id -- variable
- | HsIPVar (IPName id) -- implicit parameter
- | HsOverLit (HsOverLit id) -- Overloaded literals
+ = HsVar id -- ^ variable
+ | HsIPVar (IPName id) -- ^ implicit parameter
+ | HsOverLit (HsOverLit id) -- ^ Overloaded literals
- | HsLit HsLit -- Simple (non-overloaded) literals
+ | HsLit HsLit -- ^ Simple (non-overloaded) literals
| HsLam (MatchGroup id) -- Currently always a single match
-- Record update
| RecordUpd (LHsExpr id)
(HsRecordBinds id)
+-- (HsMatchGroup Id) -- Filled in by the type checker to be
+-- -- a match that does the job
[DataCon] -- Filled in by the type checker to the
-- _non-empty_ list of DataCons that have
-- all the upd'd fields
= hang (ppr op) 2 (sep [pp_e1, pp_e2])
pp_infixly v
- = sep [nest 2 pp_e1, pprInfix v, nest 2 pp_e2]
+ = sep [nest 2 pp_e1, pprHsInfix v, nest 2 pp_e2]
ppr_expr (NegApp e _) = char '-' <+> pprDebugParendExpr e
pp_prefixly = hang (hsep [text " \\ x_ ->", ppr op])
4 (hsep [pp_expr, ptext (sLit "x_ )")])
- pp_infixly v = (sep [pp_expr, pprInfix v])
+ pp_infixly v = (sep [pp_expr, pprHsInfix v])
ppr_expr (SectionR op expr)
= case unLoc op of
pp_prefixly = hang (hsep [text "( \\ x_ ->", ppr op, ptext (sLit "x_")])
4 ((<>) pp_expr rparen)
pp_infixly v
- = (sep [pprInfix v, pp_expr])
+ = (sep [pprHsInfix v, pp_expr])
--avoid using PatternSignatures for stage1 code portability
ppr_expr exprType@(HsLam matches)
where idType :: HsExpr id -> HsMatchContext id; idType = undefined
ppr_expr exprType@(HsCase expr matches)
- = sep [ sep [ptext (sLit "case"), nest 4 (ppr expr), ptext (sLit "of")],
- nest 2 (pprMatches (CaseAlt `asTypeOf` idType exprType) matches) ]
+ = sep [ sep [ptext (sLit "case"), nest 4 (ppr expr), ptext (sLit "of {")],
+ nest 2 (pprMatches (CaseAlt `asTypeOf` idType exprType) matches <+> char '}') ]
where idType :: HsExpr id -> HsMatchContext id; idType = undefined
ppr_expr (HsIf e1 e2 e3)
= hsep [ppr_lexpr arg, ptext (sLit ">>-"), ppr_lexpr arrow]
ppr_expr (HsArrForm (L _ (HsVar v)) (Just _) [arg1, arg2])
- = sep [pprCmdArg (unLoc arg1), hsep [pprInfix v, pprCmdArg (unLoc arg2)]]
+ = sep [pprCmdArg (unLoc arg1), hsep [pprHsInfix v, pprCmdArg (unLoc arg2)]]
ppr_expr (HsArrForm op _ args)
= hang (ptext (sLit "(|") <> ppr_lexpr op)
4 (sep (map (pprCmdArg.unLoc) args) <> ptext (sLit "|)"))
instance OutputableBndr id => Outputable (HsCmdTop id) where
ppr = pprCmdArg
--- Put a var in backquotes if it's not an operator already
-pprInfix :: Outputable name => name -> SDoc
-pprInfix v | isOperator ppr_v = ppr_v
- | otherwise = char '`' <> ppr_v <> char '`'
- where ppr_v = ppr v
-
-- add parallel array brackets around a document
--
pa_brackets :: SDoc -> SDoc
-- Nothing after typechecking
(GRHSs id)
+isEmptyMatchGroup :: MatchGroup id -> Bool
+isEmptyMatchGroup (MatchGroup ms _) = null ms
+
matchGroupArity :: MatchGroup id -> Arity
matchGroupArity (MatchGroup [] _)
- = panic "matchGroupArity" -- MatchGroup is never empty
+ = panic "matchGroupArity" -- Precondition: MatchGroup is non-empty
matchGroupArity (MatchGroup (match:matches) _)
= ASSERT( all ((== n_pats) . length . hsLMatchPats) matches )
-- Assertion just checks that all the matches have the same number of pats
hsLMatchPats :: LMatch id -> [LPat id]
hsLMatchPats (L _ (Match pats _ _)) = pats
--- GRHSs are used both for pattern bindings and for Matches
+-- | GRHSs are used both for pattern bindings and for Matches
data GRHSs id
- = GRHSs [LGRHS id] -- Guarded RHSs
- (HsLocalBinds id) -- The where clause
+ = GRHSs {
+ grhssGRHSs :: [LGRHS id], -- ^ Guarded RHSs
+ grhssLocalBinds :: (HsLocalBinds id) -- ^ The where clause
+ }
type LGRHS id = Located (GRHS id)
+-- | Guarded Right Hand Side.
data GRHS id = GRHS [LStmt id] -- Guards
(LHsExpr id) -- Right hand side
\end{code}
\begin{code}
data HsMatchContext id -- Context of a Match
= FunRhs id Bool -- Function binding for f; True <=> written infix
- | CaseAlt -- Guard on a case alternative
- | LambdaExpr -- Pattern of a lambda
- | ProcExpr -- Pattern of a proc
- | PatBindRhs -- Pattern binding
+ | CaseAlt -- Patterns and guards on a case alternative
+ | LambdaExpr -- Patterns of a lambda
+ | ProcExpr -- Patterns of a proc
+ | PatBindRhs -- Patterns in the *guards* of a pattern binding
| RecUpd -- Record update [used only in DsExpr to
-- tell matchWrapper what sort of
-- runtime error message to generate]