[commit: ghc] master: Fix #1476 by making splice patterns work. (2346de4)
git at git.haskell.org
git at git.haskell.org
Fri Nov 21 16:18:33 UTC 2014
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/2346de44330a4309b840e26ddd1ded23f92c6f81/ghc
>---------------------------------------------------------------
commit 2346de44330a4309b840e26ddd1ded23f92c6f81
Author: Richard Eisenberg <eir at cis.upenn.edu>
Date: Tue Nov 4 11:34:53 2014 -0500
Fix #1476 by making splice patterns work.
Unfortunately, splice patterns in brackets still do not work
because we don't run splices in brackets. Without running a pattern
splice, we can't know what variables it binds, so we're stuck.
This is still a substantial improvement, and it may be the best
we can do. Still must document new behavior.
>---------------------------------------------------------------
2346de44330a4309b840e26ddd1ded23f92c6f81
compiler/rename/RnPat.lhs | 10 ++++++----
compiler/rename/RnSplice.lhs | 38 +++++++++++++++++++++++++++++++-------
compiler/rename/RnSplice.lhs-boot | 3 ++-
testsuite/tests/th/all.T | 2 +-
4 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/compiler/rename/RnPat.lhs b/compiler/rename/RnPat.lhs
index 9d03805..370f6b4 100644
--- a/compiler/rename/RnPat.lhs
+++ b/compiler/rename/RnPat.lhs
@@ -440,10 +440,12 @@ rnPatAndThen mk (TuplePat pats boxed _)
; pats' <- rnLPatsAndThen mk pats
; return (TuplePat pats' boxed []) }
-rnPatAndThen _ (SplicePat splice)
- = do { -- XXX How to deal with free variables?
- ; (pat, _) <- liftCps $ rnSplicePat splice
- ; return pat }
+rnPatAndThen mk (SplicePat splice)
+ = do { eith <- liftCpsFV $ rnSplicePat splice
+ ; case eith of -- See Note [rnSplicePat] in RnSplice
+ Left not_yet_renamed -> rnPatAndThen mk not_yet_renamed
+ Right already_renamed -> return already_renamed }
+
rnPatAndThen mk (QuasiQuotePat qq)
= do { pat <- liftCps $ runQuasiQuotePat qq
-- Wrap the result of the quasi-quoter in parens so that we don't
diff --git a/compiler/rename/RnSplice.lhs b/compiler/rename/RnSplice.lhs
index 59c8c62..8918e39 100644
--- a/compiler/rename/RnSplice.lhs
+++ b/compiler/rename/RnSplice.lhs
@@ -206,13 +206,40 @@ rnSpliceType splice k
}
; return (unLoc hs_ty3, fvs) }
-----------------------
-rnSplicePat :: HsSplice RdrName -> RnM (Pat Name, FreeVars)
+\end{code}
+
+Note [rnSplicePat]
+~~~~~~~~~~~~~~~~~~
+Renaming a pattern splice is a bit tricky, because we need the variables
+bound in the pattern to be in scope in the RHS of the pattern. This scope
+management is effectively done by using continuation-passing style in
+RnPat, through the CpsRn monad. We don't wish to be in that monad here
+(it would create import cycles and generally conflict with renaming other
+splices), so we really want to return a (Pat RdrName) -- the result of
+running the splice -- which can then be further renamed in RnPat, in
+the CpsRn monad.
+
+The problem is that if we're renaming a splice within a bracket, we
+*don't* want to run the splice now. We really do just want to rename
+it to an HsSplice Name. Of course, then we can't know what variables
+are bound within the splice, so pattern splices within brackets aren't
+all that useful.
+
+In any case, when we're done in rnSplicePat, we'll either have a
+Pat RdrName (the result of running a top-level splice) or a Pat Name
+(the renamed nested splice). Thus, the awkward return type of
+rnSplicePat.
+
+\begin{code}
+
+-- | Rename a splice pattern. See Note [rnSplicePat]
+rnSplicePat :: HsSplice RdrName -> RnM ( Either (Pat RdrName) (Pat Name)
+ , FreeVars)
rnSplicePat splice
= rnSpliceGen False run_pat_splice pend_pat_splice splice
where
pend_pat_splice rn_splice@(HsSplice n e)
- = (PendingRnPatSplice (PendSplice n e), SplicePat rn_splice)
+ = (PendingRnPatSplice (PendSplice n e), Right $ SplicePat rn_splice)
run_pat_splice (HsSplice _ expr')
= do { expr <- getHooked runRnSpliceHook return >>= ($ expr')
@@ -227,10 +254,7 @@ rnSplicePat splice
; pat <- runMetaP zonked_q_expr
; showSplice "pattern" expr (ppr pat)
- ; (pat', fvs) <- checkNoErrs $
- rnPat ThPatSplice pat $ \pat' -> return (pat', emptyFVs)
-
- ; return (unLoc pat', fvs) }
+ ; return (Left $ unLoc pat, emptyFVs) }
----------------------
rnSpliceDecl :: SpliceDecl RdrName -> RnM (SpliceDecl Name, FreeVars)
diff --git a/compiler/rename/RnSplice.lhs-boot b/compiler/rename/RnSplice.lhs-boot
index 45a2a10..de6da77 100644
--- a/compiler/rename/RnSplice.lhs-boot
+++ b/compiler/rename/RnSplice.lhs-boot
@@ -11,6 +11,7 @@ import Kind
rnSpliceType :: HsSplice RdrName -> PostTc Name Kind
-> RnM (HsType Name, FreeVars)
-rnSplicePat :: HsSplice RdrName -> RnM (Pat Name, FreeVars)
+rnSplicePat :: HsSplice RdrName -> RnM ( Either (Pat RdrName) (Pat Name)
+ , FreeVars )
rnSpliceDecl :: SpliceDecl RdrName -> RnM (SpliceDecl Name, FreeVars)
\end{code}
diff --git a/testsuite/tests/th/all.T b/testsuite/tests/th/all.T
index 3f8ff16..366858e 100644
--- a/testsuite/tests/th/all.T
+++ b/testsuite/tests/th/all.T
@@ -344,5 +344,5 @@ test('T8100', normal, compile, ['-v0'])
test('T9064', normal, compile, ['-v0'])
test('T9209', normal, compile_fail, ['-v0'])
test('T7484', normal, compile_fail, ['-v0'])
-test('T1476', expect_broken(1476), compile, ['-v0'])
+test('T1476', normal, compile, ['-v0'])
test('T1476b', normal, compile_fail, ['-v0'])
More information about the ghc-commits
mailing list