1
- {-# LANGUAGE DeriveDataTypeable #-}
2
- {-# LANGUAGE DeriveGeneric #-}
3
-
1
+ {-# LANGUAGE BangPatterns #-}
2
+ {-# LANGUAGE DeriveDataTypeable #-}
3
+ {-# LANGUAGE DeriveGeneric #-}
4
+ {-# LANGUAGE ScopedTypeVariables #-}
4
5
-----------------------------------------------------------------------------
5
6
-- |
6
7
-- Module : Distribution.ModuleName
13
14
-- Data type for Haskell module names.
14
15
15
16
module Distribution.ModuleName (
16
- ModuleName ( .. ), -- TODO: move Parsec instance here, don't export constructor
17
+ ModuleName ,
17
18
fromString ,
18
19
fromComponents ,
19
20
components ,
@@ -33,41 +34,65 @@ import Distribution.Utils.ShortText (ShortText, fromShortText, toShortTex
33
34
import System.FilePath (pathSeparator )
34
35
35
36
import qualified Distribution.Compat.CharParsing as P
37
+ import qualified Distribution.Compat.DList as DList
36
38
import qualified Text.PrettyPrint as Disp
37
39
38
40
-- | A valid Haskell module name.
39
41
--
40
- newtype ModuleName = ModuleName ShortTextLst
42
+ newtype ModuleName = ModuleName ShortText
41
43
deriving (Eq , Generic , Ord , Read , Show , Typeable , Data )
42
44
45
+ unModuleName :: ModuleName -> String
46
+ unModuleName (ModuleName s) = fromShortText s
47
+
43
48
instance Binary ModuleName
44
49
instance Structured ModuleName
45
50
46
51
instance NFData ModuleName where
47
52
rnf (ModuleName ms) = rnf ms
48
53
49
54
instance Pretty ModuleName where
50
- pretty (ModuleName ms) =
51
- Disp. hcat (intersperse (Disp. char ' .' ) (map Disp. text $ stlToStrings ms))
55
+ pretty = Disp. text . unModuleName
52
56
53
57
instance Parsec ModuleName where
54
- parsec = fromComponents <$> toList <$> P. sepByNonEmpty component (P. char ' .' )
55
- where
56
- component = do
57
- c <- P. satisfy isUpper
58
- cs <- P. munch validModuleChar
59
- return (c: cs)
58
+ parsec = parsecModuleName
59
+
60
+ parsecModuleName :: forall m . CabalParsing m => m ModuleName
61
+ parsecModuleName = state0 DList. empty where
62
+ upper :: m Char
63
+ ! upper = P. satisfy isUpper
64
+
65
+ ch :: m Char
66
+ ! ch = P. satisfy (\ c -> validModuleChar c || c == ' .' )
67
+
68
+ alt :: m ModuleName -> m ModuleName -> m ModuleName
69
+ ! alt = (<|>)
70
+
71
+ state0 :: DList. DList Char -> m ModuleName
72
+ state0 acc = do
73
+ c <- upper
74
+ state1 (DList. snoc acc c)
75
+
76
+ state1 :: DList. DList Char -> m ModuleName
77
+ state1 acc = state1' acc `alt` return (fromString (DList. toList acc))
78
+
79
+ state1' :: DList. DList Char -> m ModuleName
80
+ state1' acc = do
81
+ c <- ch
82
+ case c of
83
+ ' .' -> state0 (DList. snoc acc c)
84
+ _ -> state1 (DList. snoc acc c)
60
85
61
86
instance Described ModuleName where
62
- describe _ = RETodo
87
+ describe _ = REMunch1 (reChar ' .' ) component where
88
+ component = RECharSet csUpper <> reMunchCS (csAlphaNum <> fromString " _'" )
63
89
64
90
validModuleChar :: Char -> Bool
65
91
validModuleChar c = isAlphaNum c || c == ' _' || c == ' \' '
66
92
67
93
validModuleComponent :: String -> Bool
68
94
validModuleComponent [] = False
69
- validModuleComponent (c: cs) = isUpper c
70
- && all validModuleChar cs
95
+ validModuleComponent (c: cs) = isUpper c && all validModuleChar cs
71
96
72
97
-- | Construct a 'ModuleName' from a valid module name 'String'.
73
98
--
@@ -76,77 +101,36 @@ validModuleComponent (c:cs) = isUpper c
76
101
-- are parsing user input then use 'Distribution.Text.simpleParse' instead.
77
102
--
78
103
instance IsString ModuleName where
79
- fromString string = fromComponents (split string)
80
- where
81
- split cs = case break (== ' .' ) cs of
82
- (chunk,[] ) -> chunk : []
83
- (chunk,_: rest) -> chunk : split rest
104
+ fromString = ModuleName . toShortText
84
105
85
106
-- | Construct a 'ModuleName' from valid module components, i.e. parts
86
107
-- separated by dots.
87
108
fromComponents :: [String ] -> ModuleName
88
- fromComponents components'
89
- | null components' = error zeroComponents
90
- | all validModuleComponent components' = ModuleName (stlFromStrings components')
91
- | otherwise = error badName
92
- where
93
- zeroComponents = " ModuleName.fromComponents: zero components"
94
- badName = " ModuleName.fromComponents: invalid components " ++ show components'
109
+ fromComponents comps = fromString (intercalate " ." comps)
110
+ {-# DEPRECATED fromComponents "Exists for cabal-install only" #-}
95
111
96
112
-- | The module name @Main@.
97
113
--
98
114
main :: ModuleName
99
- main = ModuleName (stlFromStrings [ " Main" ] )
115
+ main = ModuleName (fromString " Main" )
100
116
101
117
-- | The individual components of a hierarchical module name. For example
102
118
--
103
119
-- > components (fromString "A.B.C") = ["A", "B", "C"]
104
120
--
105
121
components :: ModuleName -> [String ]
106
- components (ModuleName ms) = stlToStrings ms
122
+ components mn = split (unModuleName mn)
123
+ where
124
+ split cs = case break (== ' .' ) cs of
125
+ (chunk,[] ) -> chunk : []
126
+ (chunk,_: rest) -> chunk : split rest
107
127
108
128
-- | Convert a module name to a file path, but without any file extension.
109
129
-- For example:
110
130
--
111
131
-- > toFilePath (fromString "A.B.C") = "A/B/C"
112
132
--
113
133
toFilePath :: ModuleName -> FilePath
114
- toFilePath = intercalate [pathSeparator] . components
115
-
116
- ----------------------------------------------------------------------------
117
- -- internal helper
118
-
119
- -- | Strict/unpacked representation of @[ShortText]@
120
- data ShortTextLst = STLNil
121
- | STLCons ! ShortText ! ShortTextLst
122
- deriving (Eq , Generic , Ord , Typeable , Data )
123
-
124
- instance NFData ShortTextLst where
125
- rnf = flip seq ()
126
-
127
- instance Show ShortTextLst where
128
- showsPrec p = showsPrec p . stlToList
129
-
130
-
131
- instance Read ShortTextLst where
132
- readsPrec p = map (first stlFromList) . readsPrec p
133
-
134
- instance Binary ShortTextLst where
135
- put = put . stlToList
136
- get = stlFromList <$> get
137
-
138
- instance Structured ShortTextLst
139
-
140
- stlToList :: ShortTextLst -> [ShortText ]
141
- stlToList STLNil = []
142
- stlToList (STLCons st next) = st : stlToList next
143
-
144
- stlToStrings :: ShortTextLst -> [String ]
145
- stlToStrings = map fromShortText . stlToList
146
-
147
- stlFromList :: [ShortText ] -> ShortTextLst
148
- stlFromList [] = STLNil
149
- stlFromList (x: xs) = STLCons x (stlFromList xs)
150
-
151
- stlFromStrings :: [String ] -> ShortTextLst
152
- stlFromStrings = stlFromList . map toShortText
134
+ toFilePath = map f . unModuleName where
135
+ f ' .' = pathSeparator
136
+ f c = c
0 commit comments