diff options
author | Simon Marlow <marlowsd@gmail.com> | 2017-10-26 11:23:23 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2017-10-27 14:48:23 +0100 |
commit | 41f905596dc2560f29657753e4c69ce695161786 (patch) | |
tree | 071774ec3b99b5644f3b16f25e464f2da2558eef /compiler/hsSyn/HsExpr.hs | |
parent | 7d7d94fb4876dc7e58263abc9dd65921e09cddac (diff) | |
download | haskell-41f905596dc2560f29657753e4c69ce695161786.tar.gz |
ApplicativeDo: handle BodyStmt (#12143)
Summary:
It's simple to treat BodyStmt just like a BindStmt with a wildcard
pattern, which is enough to fix #12143 without going all the way to
using `<*` and `*>` (#10892).
Test Plan:
* new test cases in `ado004.hs`
* validate
Reviewers: niteria, simonpj, bgamari, austin, erikd
Subscribers: rwbarton, thomie
GHC Trac Issues: #12143
Differential Revision: https://phabricator.haskell.org/D4128
Diffstat (limited to 'compiler/hsSyn/HsExpr.hs')
-rw-r--r-- | compiler/hsSyn/HsExpr.hs | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/compiler/hsSyn/HsExpr.hs b/compiler/hsSyn/HsExpr.hs index 1cfaa79af5..fedaa4491a 100644 --- a/compiler/hsSyn/HsExpr.hs +++ b/compiler/hsSyn/HsExpr.hs @@ -1777,13 +1777,18 @@ deriving instance (DataId idL, DataId idR) => Data (ParStmtBlock idL idR) -- | Applicative Argument data ApplicativeArg idL idR - = ApplicativeArgOne -- pat <- expr (pat must be irrefutable) - (LPat idL) + = ApplicativeArgOne -- A single statement (BindStmt or BodyStmt) + (LPat idL) -- WildPat if it was a BodyStmt (see below) (LHsExpr idL) - | ApplicativeArgMany -- do { stmts; return vars } - [ExprLStmt idL] -- stmts - (HsExpr idL) -- return (v1,..,vn), or just (v1,..,vn) - (LPat idL) -- (v1,...,vn) + Bool -- True <=> was a BodyStmt + -- False <=> was a BindStmt + -- See Note [Applicative BodyStmt] + + | ApplicativeArgMany -- do { stmts; return vars } + [ExprLStmt idL] -- stmts + (HsExpr idL) -- return (v1,..,vn), or just (v1,..,vn) + (LPat idL) -- (v1,...,vn) + deriving instance (DataId idL, DataId idR) => Data (ApplicativeArg idL idR) {- @@ -1921,6 +1926,34 @@ Parallel statements require the 'Control.Monad.Zip.mzip' function: In any other context than 'MonadComp', the fields for most of these 'SyntaxExpr's stay bottom. + + +Note [Applicative BodyStmt] + +(#12143) For the purposes of ApplicativeDo, we treat any BodyStmt +as if it was a BindStmt with a wildcard pattern. For example, + + do + x <- A + B + return x + +is transformed as if it were + + do + x <- A + _ <- B + return x + +so it transforms to + + (\(x,_) -> x) <$> A <*> B + +But we have to remember when we treat a BodyStmt like a BindStmt, +because in error messages we want to emit the original syntax the user +wrote, not our internal representation. So ApplicativeArgOne has a +Bool flag that is True when the original statement was a BodyStmt, so +that we can pretty-print it correctly. -} instance (SourceTextX idL, OutputableBndrId idL) @@ -1973,7 +2006,11 @@ pprStmt (ApplicativeStmt args mb_join _) flattenStmt (L _ (ApplicativeStmt args _ _)) = concatMap flattenArg args flattenStmt stmt = [ppr stmt] - flattenArg (_, ApplicativeArgOne pat expr) = + flattenArg (_, ApplicativeArgOne pat expr isBody) + | isBody = -- See Note [Applicative BodyStmt] + [ppr (BodyStmt expr noSyntaxExpr noSyntaxExpr (panic "pprStmt") + :: ExprStmt idL)] + | otherwise = [ppr (BindStmt pat expr noSyntaxExpr noSyntaxExpr (panic "pprStmt") :: ExprStmt idL)] flattenArg (_, ApplicativeArgMany stmts _ _) = @@ -1987,7 +2024,11 @@ pprStmt (ApplicativeStmt args mb_join _) then ap_expr else text "join" <+> parens ap_expr - pp_arg (_, ApplicativeArgOne pat expr) = + pp_arg (_, ApplicativeArgOne pat expr isBody) + | isBody = -- See Note [Applicative BodyStmt] + ppr (BodyStmt expr noSyntaxExpr noSyntaxExpr (panic "pprStmt") + :: ExprStmt idL) + | otherwise = ppr (BindStmt pat expr noSyntaxExpr noSyntaxExpr (panic "pprStmt") :: ExprStmt idL) pp_arg (_, ApplicativeArgMany stmts return pat) = |