Fix #1476 by making splice patterns work.
authorRichard Eisenberg <eir@cis.upenn.edu>
Tue, 4 Nov 2014 16:34:53 +0000 (11:34 -0500)
committerRichard Eisenberg <eir@cis.upenn.edu>
Fri, 21 Nov 2014 16:15:47 +0000 (11:15 -0500)
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.

compiler/rename/RnPat.lhs
compiler/rename/RnSplice.lhs
compiler/rename/RnSplice.lhs-boot
testsuite/tests/th/all.T

index 9d03805..370f6b4 100644 (file)
@@ -440,10 +440,12 @@ rnPatAndThen mk (TuplePat pats boxed _)
        ; pats' <- rnLPatsAndThen mk pats
        ; return (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
 rnPatAndThen mk (QuasiQuotePat qq)
   = do { pat <- liftCps $ runQuasiQuotePat qq
          -- Wrap the result of the quasi-quoter in parens so that we don't
index 59c8c62..8918e39 100644 (file)
@@ -206,13 +206,40 @@ rnSpliceType splice k
                                   }
             ; return (unLoc hs_ty3, fvs) }
 
                                   }
             ; 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)
 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')
 
     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 <- 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)
 
 ----------------------
 rnSpliceDecl :: SpliceDecl RdrName -> RnM (SpliceDecl Name, FreeVars)
index 45a2a10..de6da77 100644 (file)
@@ -11,6 +11,7 @@ import Kind
 
 rnSpliceType :: HsSplice RdrName   -> PostTc Name Kind
              -> RnM (HsType Name, FreeVars)
 
 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}
 rnSpliceDecl :: SpliceDecl RdrName -> RnM (SpliceDecl Name, FreeVars)
 \end{code}
index 3f8ff16..366858e 100644 (file)
@@ -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('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'])
 test('T1476b', normal, compile_fail, ['-v0'])