#8633 closed bug (fixed)

template haskell mkName parses operator ^.. as a qualified operator

Reported by: aavogt Owned by:
Priority: normal Milestone:
Component: Template Haskell Version: 7.6.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: th/T8633
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description

The operator ^.. (provided by lens) is parsed as the operator . from module ^. In other words:

import Language.Haskell.TH.Syntax
main = case mkName "^.." of
   Name (OccName ".")  (NameQ (ModName "^")) -> error "bug"
   Name (OccName "^..") NameS                -> print "desired"

The context here is that I get ^.. out-of-scope when I try to use that operator in code that is handled by haskell-src-meta.

Attachments (1)

mkName.hs (1.5 KB) - added by aavogt 15 months ago.
mkName.hs

Download all attachments as: .zip

Change History (4)

Changed 15 months ago by aavogt

mkName.hs

comment:1 Changed 15 months ago by aavogt

Attached is a mkName function, which does not have the issues above.

comment:2 Changed 15 months ago by Simon Peyton Jones <simonpj@…>

comment:3 Changed 15 months ago by simonpj

  • Resolution set to fixed
  • Status changed from new to closed
  • Test Case set to th/T8633

Thanks for the patch. I adjusted it a bit

commit 21a48605d856ca334bb3a018e02255349d69a8c4
Author: Simon Peyton Jones <[email protected]>
Date:   Sat Dec 28 11:05:31 2013 +0000

    Improve mkName, so that it correctly parses the name ^..
    
    This fixes Trac #8633; thanks to aavogt for a first draft.


>---------------------------------------------------------------

21a48605d856ca334bb3a018e02255349d69a8c4
 Language/Haskell/TH/Syntax.hs |   24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/Language/Haskell/TH/Syntax.hs b/Language/Haskell/TH/Syntax.hs index f3868d1..3606f9d 100644
--- a/Language/Haskell/TH/Syntax.hs
+++ b/Language/Haskell/TH/Syntax.hs
@@ -24,7 +24,7 @@ import Data.IORef
 import System.IO.Unsafe	( unsafePerformIO )
 import Control.Monad (liftM)
 import System.IO	( hPutStrLn, stderr )
-import Data.Char        ( isAlpha )
+import Data.Char        ( isAlpha, isAlphaNum, isUpper )
 import Data.Word        ( Word8 )
 
 -----------------------------------------------------
@@ -758,17 +758,33 @@ mkName str
   = split [] (reverse str)
   where
     split occ []        = Name (mkOccName occ) NameS
-    split occ ('.':rev)	| not (null occ),
-			  not (null rev), head rev /= '.'
+    split occ ('.':rev)	| not (null occ)
+			, is_rev_mod_name rev
 			= Name (mkOccName occ) (NameQ (mkModName (reverse rev)))
 	-- The 'not (null occ)' guard ensures that
 	-- 	mkName "&." = Name "&." NameS
-	-- The 'rev' guards ensure that
+	-- The 'is_rev_mod' guards ensure that
 	--	mkName ".&" = Name ".&" NameS
+	--	mkName "^.." = Name "^.." NameS      -- Trac #8633
 	--	mkName "Data.Bits..&" = Name ".&" (NameQ "Data.Bits")
 	-- This rather bizarre case actually happened; (.&.) is in Data.Bits
     split occ (c:rev)   = split (c:occ) rev
 
+    -- Recognises a reversed module name xA.yB.C, 
+    -- with at least one component, 
+    -- and each component looks like a module name
+    --   (i.e. non-empty, starts with capital, all alpha)
+    is_rev_mod_name rev_mod_str
+      | (compt, rest) <- break (== '.') rev_mod_str
+      , not (null compt), isUpper (last compt), all is_mod_char compt
+      = case rest of
+          []             -> True
+          (_dot : rest') -> is_rev_mod_name rest'
+      | otherwise
+      = False
+
+    is_mod_char c = isAlphaNum c || c == '_' || c == '\''
+
 -- | Only used internally
 mkNameU :: String -> Uniq -> Name
 mkNameU s (I# u) = Name (mkOccName s) (NameU u)
Note: See TracTickets for help on using tickets.