summaryrefslogtreecommitdiff
path: root/libraries/template-haskell/Language/Haskell/TH
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2013-12-28 11:05:31 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2013-12-30 12:14:39 +0000
commit78e7066612a8e0b9cac2c4e63bd8059b57ea9ed6 (patch)
tree3b47181ad48e690fa042a1ec2763b4ef160fd54f /libraries/template-haskell/Language/Haskell/TH
parentd9179a505b42121ecf0e7e051e9943dcec57e65c (diff)
downloadhaskell-78e7066612a8e0b9cac2c4e63bd8059b57ea9ed6.tar.gz
Improve mkName, so that it correctly parses the name ^..
This fixes Trac #8633; thanks to aavogt for a first draft.
Diffstat (limited to 'libraries/template-haskell/Language/Haskell/TH')
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs24
1 files changed, 20 insertions, 4 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
index f3868d1872..3606f9d975 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
+++ b/libraries/template-haskell/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)