module Language.Haskell.Syntax.Module.Name where

import Prelude

import Data.Data
import Data.Char (isAlphaNum)
import Control.DeepSeq
import qualified Text.ParserCombinators.ReadP as Parse
import System.FilePath

import GHC.Utils.Misc (abstractConstr)
import GHC.Data.FastString

-- | A ModuleName is essentially a simple string, e.g. @Data.List@.
newtype ModuleName = ModuleName FastString deriving (Int -> ModuleName -> ShowS
[ModuleName] -> ShowS
ModuleName -> String
(Int -> ModuleName -> ShowS)
-> (ModuleName -> String)
-> ([ModuleName] -> ShowS)
-> Show ModuleName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ModuleName -> ShowS
showsPrec :: Int -> ModuleName -> ShowS
$cshow :: ModuleName -> String
show :: ModuleName -> String
$cshowList :: [ModuleName] -> ShowS
showList :: [ModuleName] -> ShowS
Show, ModuleName -> ModuleName -> Bool
(ModuleName -> ModuleName -> Bool)
-> (ModuleName -> ModuleName -> Bool) -> Eq ModuleName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ModuleName -> ModuleName -> Bool
== :: ModuleName -> ModuleName -> Bool
$c/= :: ModuleName -> ModuleName -> Bool
/= :: ModuleName -> ModuleName -> Bool
Eq)

instance Ord ModuleName where
  ModuleName
nm1 compare :: ModuleName -> ModuleName -> Ordering
`compare` ModuleName
nm2 = ModuleName -> ModuleName -> Ordering
stableModuleNameCmp ModuleName
nm1 ModuleName
nm2

instance Data ModuleName where
  -- don't traverse?
  toConstr :: ModuleName -> Constr
toConstr ModuleName
_   = String -> Constr
abstractConstr String
"ModuleName"
  gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ModuleName
gunfold forall b r. Data b => c (b -> r) -> c r
_ forall r. r -> c r
_  = String -> Constr -> c ModuleName
forall a. HasCallStack => String -> a
error String
"gunfold"
  dataTypeOf :: ModuleName -> DataType
dataTypeOf ModuleName
_ = String -> DataType
mkNoRepType String
"ModuleName"

instance NFData ModuleName where
  rnf :: ModuleName -> ()
rnf ModuleName
x = ModuleName
x ModuleName -> () -> ()
forall a b. a -> b -> b
`seq` ()

stableModuleNameCmp :: ModuleName -> ModuleName -> Ordering
-- ^ Compares module names lexically, rather than by their 'Unique's
stableModuleNameCmp :: ModuleName -> ModuleName -> Ordering
stableModuleNameCmp ModuleName
n1 ModuleName
n2 = ModuleName -> FastString
moduleNameFS ModuleName
n1 FastString -> FastString -> Ordering
`lexicalCompareFS` ModuleName -> FastString
moduleNameFS ModuleName
n2

moduleNameFS :: ModuleName -> FastString
moduleNameFS :: ModuleName -> FastString
moduleNameFS (ModuleName FastString
mod) = FastString
mod

moduleNameString :: ModuleName -> String
moduleNameString :: ModuleName -> String
moduleNameString (ModuleName FastString
mod) = FastString -> String
unpackFS FastString
mod

mkModuleName :: String -> ModuleName
mkModuleName :: String -> ModuleName
mkModuleName String
s = FastString -> ModuleName
ModuleName (String -> FastString
mkFastString String
s)

mkModuleNameFS :: FastString -> ModuleName
mkModuleNameFS :: FastString -> ModuleName
mkModuleNameFS FastString
s = FastString -> ModuleName
ModuleName FastString
s

-- |Returns the string version of the module name, with dots replaced by slashes.
--
moduleNameSlashes :: ModuleName -> String
moduleNameSlashes :: ModuleName -> String
moduleNameSlashes = ShowS
dots_to_slashes ShowS -> (ModuleName -> String) -> ModuleName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleName -> String
moduleNameString
  where dots_to_slashes :: ShowS
dots_to_slashes = (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map (\Char
c -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.' then Char
pathSeparator else Char
c)

-- |Returns the string version of the module name, with dots replaced by colons.
--
moduleNameColons :: ModuleName -> String
moduleNameColons :: ModuleName -> String
moduleNameColons = ShowS
dots_to_colons ShowS -> (ModuleName -> String) -> ModuleName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleName -> String
moduleNameString
  where dots_to_colons :: ShowS
dots_to_colons = (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map (\Char
c -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.' then Char
':' else Char
c)

parseModuleName :: Parse.ReadP ModuleName
parseModuleName :: ReadP ModuleName
parseModuleName = (String -> ModuleName) -> ReadP String -> ReadP ModuleName
forall a b. (a -> b) -> ReadP a -> ReadP b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> ModuleName
mkModuleName
                (ReadP String -> ReadP ModuleName)
-> ReadP String -> ReadP ModuleName
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> ReadP String
Parse.munch1 (\Char
c -> Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
"_.")