{-# LANGUAGE ViewPatterns #-}
module Data.GI.CodeGen.SymbolNaming
( lowerName
, lowerSymbol
, upperName
, noName
, escapedArgName
, classConstraint
, typeConstraint
, hyphensToCamelCase
, underscoresToCamelCase
, callbackCType
, callbackHTypeWithClosures
, callbackDropClosures
, callbackDynamicWrapper
, callbackWrapperAllocator
, callbackHaskellToForeign
, callbackHaskellToForeignWithClosures
, callbackClosureGenerator
, signalHaskellName
, signalInfoName
, submoduleLocation
, qualifiedAPI
, qualifiedSymbol
) where
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid ((<>))
#endif
import Data.Text (Text)
import qualified Data.Text as T
import Data.GI.CodeGen.API
import Data.GI.CodeGen.Code (CodeGen, group, line, exportDecl,
qualified, getAPI)
import Data.GI.CodeGen.ModulePath (ModulePath, (/.), toModulePath)
import Data.GI.CodeGen.Type (Type(TInterface))
import Data.GI.CodeGen.Util (lcFirst, ucFirst, modifyQualified)
classConstraint :: Name -> CodeGen Text
classConstraint :: Name -> CodeGen Text
classConstraint n :: Name
n@(Name _ s :: Text
s) = Text -> Name -> CodeGen Text
qualifiedSymbol ("Is" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s) Name
n
typeConstraint :: Type -> CodeGen Text
typeConstraint :: Type -> CodeGen Text
typeConstraint (TInterface n :: Name
n) = Name -> CodeGen Text
classConstraint Name
n
typeConstraint t :: Type
t = [Char] -> BaseCodeGen e Text
forall a. HasCallStack => [Char] -> a
error ([Char] -> BaseCodeGen e Text) -> [Char] -> BaseCodeGen e Text
forall a b. (a -> b) -> a -> b
$ "Class constraint for non-interface type: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Type -> [Char]
forall a. Show a => a -> [Char]
show Type
t
callbackCType :: Text -> Text
callbackCType :: Text -> Text
callbackCType = (Text -> Text) -> Text -> Text
modifyQualified ("C_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
callbackHTypeWithClosures :: Text -> Text
callbackHTypeWithClosures :: Text -> Text
callbackHTypeWithClosures = (Text -> Text) -> Text -> Text
modifyQualified (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "_WithClosures")
callbackDynamicWrapper :: Text -> Text
callbackDynamicWrapper :: Text -> Text
callbackDynamicWrapper = (Text -> Text) -> Text -> Text
modifyQualified ("dynamic_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
callbackHaskellToForeign :: Text -> Text
callbackHaskellToForeign :: Text -> Text
callbackHaskellToForeign = (Text -> Text) -> Text -> Text
modifyQualified ("wrap_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
callbackHaskellToForeignWithClosures :: Text -> Text
callbackHaskellToForeignWithClosures :: Text -> Text
callbackHaskellToForeignWithClosures = (Text -> Text) -> Text -> Text
modifyQualified ("with_closures_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
callbackDropClosures :: Text -> Text
callbackDropClosures :: Text -> Text
callbackDropClosures = (Text -> Text) -> Text -> Text
modifyQualified ("drop_closures_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
callbackWrapperAllocator :: Text -> Text
callbackWrapperAllocator :: Text -> Text
callbackWrapperAllocator = (Text -> Text) -> Text -> Text
modifyQualified ("mk_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
callbackClosureGenerator :: Text -> Text
callbackClosureGenerator :: Text -> Text
callbackClosureGenerator = (Text -> Text) -> Text -> Text
modifyQualified ("genClosure_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
sanitize :: Text -> Text
sanitize :: Text -> Text
sanitize (Text -> Maybe (Char, Text)
T.uncons -> Just ('_', xs :: Text
xs)) = Text -> Text
sanitize Text
xs Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "_"
sanitize xs :: Text
xs = Text
xs
lowerName :: Name -> Text
lowerName :: Name -> Text
lowerName (Name _ s :: Text
s) = Text -> Text
lowerSymbol Text
s
lowerSymbol :: Text -> Text
lowerSymbol :: Text -> Text
lowerSymbol s :: Text
s = case Text -> Text
underscoresToCamelCase (Text -> Text
sanitize Text
s) of
"" -> [Char] -> Text
forall a. HasCallStack => [Char] -> a
error "empty name!!"
n :: Text
n -> Text -> Text
lcFirst Text
n
upperName :: Name -> Text
upperName :: Name -> Text
upperName (Name _ s :: Text
s) = Text -> Text
underscoresToCamelCase (Text -> Text
sanitize Text
s)
submoduleLocation :: Name -> API -> ModulePath
submoduleLocation :: Name -> API -> ModulePath
submoduleLocation _ (APIConst _) = "Constants"
submoduleLocation _ (APIFunction _) = "Functions"
submoduleLocation _ (APICallback _) = "Callbacks"
submoduleLocation _ (APIEnum _) = "Enums"
submoduleLocation _ (APIFlags _) = "Flags"
submoduleLocation n :: Name
n (APIInterface _) = "Interfaces" ModulePath -> Text -> ModulePath
/. Name -> Text
upperName Name
n
submoduleLocation n :: Name
n (APIObject _) = "Objects" ModulePath -> Text -> ModulePath
/. Name -> Text
upperName Name
n
submoduleLocation n :: Name
n (APIStruct _) = "Structs" ModulePath -> Text -> ModulePath
/. Name -> Text
upperName Name
n
submoduleLocation n :: Name
n (APIUnion _) = "Unions" ModulePath -> Text -> ModulePath
/. Name -> Text
upperName Name
n
qualifiedAPI :: Name -> CodeGen Text
qualifiedAPI :: Name -> CodeGen Text
qualifiedAPI n :: Name
n@(Name ns :: Text
ns _) = do
API
api <- Type -> CodeGen API
getAPI (Name -> Type
TInterface Name
n)
ModulePath -> Name -> CodeGen Text
qualified (Text -> ModulePath
toModulePath (Text -> Text
ucFirst Text
ns) ModulePath -> ModulePath -> ModulePath
forall a. Semigroup a => a -> a -> a
<> Name -> API -> ModulePath
submoduleLocation Name
n API
api) Name
n
qualifiedSymbol :: Text -> Name -> CodeGen Text
qualifiedSymbol :: Text -> Name -> CodeGen Text
qualifiedSymbol s :: Text
s n :: Name
n@(Name ns :: Text
ns _) = do
API
api <- Type -> CodeGen API
getAPI (Name -> Type
TInterface Name
n)
ModulePath -> Name -> CodeGen Text
qualified (Text -> ModulePath
toModulePath (Text -> Text
ucFirst Text
ns) ModulePath -> ModulePath -> ModulePath
forall a. Semigroup a => a -> a -> a
<> Name -> API -> ModulePath
submoduleLocation Name
n API
api) (Text -> Text -> Name
Name Text
ns Text
s)
noName :: Text -> CodeGen ()
noName :: Text -> CodeGen ()
noName name' :: Text
name' = BaseCodeGen e () -> BaseCodeGen e ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
group (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
Text -> BaseCodeGen e ()
Text -> CodeGen ()
line (Text -> BaseCodeGen e ()) -> Text -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ "-- | A convenience alias for `Nothing` :: `Maybe` `" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "`."
Text -> BaseCodeGen e ()
Text -> CodeGen ()
line (Text -> BaseCodeGen e ()) -> Text -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ "no" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> " :: Maybe " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name'
Text -> BaseCodeGen e ()
Text -> CodeGen ()
line (Text -> BaseCodeGen e ()) -> Text -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ "no" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> " = Nothing"
Text -> CodeGen ()
exportDecl ("no" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name')
hyphensToCamelCase :: Text -> Text
hyphensToCamelCase :: Text -> Text
hyphensToCamelCase = [Text] -> Text
T.concat ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
ucFirst ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> [Text]
T.split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '-')
underscoresToCamelCase :: Text -> Text
underscoresToCamelCase :: Text -> Text
underscoresToCamelCase =
[Text] -> Text
T.concat ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
normalize ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
ucFirst ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> [Text]
T.split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '_')
where normalize :: Text -> Text
normalize :: Text -> Text
normalize "" = "_"
normalize s :: Text
s = Text
s
escapedArgName :: Arg -> Text
escapedArgName :: Arg -> Text
escapedArgName arg :: Arg
arg
| "_" Text -> Text -> Bool
`T.isPrefixOf` Arg -> Text
argCName Arg
arg = Arg -> Text
argCName Arg
arg
| Bool
otherwise =
Text -> Text
escapeReserved (Text -> Text) -> (Arg -> Text) -> Arg -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
lcFirst (Text -> Text) -> (Arg -> Text) -> Arg -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
underscoresToCamelCase (Text -> Text) -> (Arg -> Text) -> Arg -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arg -> Text
argCName (Arg -> Text) -> Arg -> Text
forall a b. (a -> b) -> a -> b
$ Arg
arg
escapeReserved :: Text -> Text
escapeReserved :: Text -> Text
escapeReserved "type" = "type_"
escapeReserved "in" = "in_"
escapeReserved "data" = "data_"
escapeReserved "instance" = "instance_"
escapeReserved "where" = "where_"
escapeReserved "module" = "module_"
escapeReserved "result" = "result_"
escapeReserved "return" = "return_"
escapeReserved "show" = "show_"
escapeReserved "fromEnum" = "fromEnum_"
escapeReserved "toEnum" = "toEnum_"
escapeReserved "undefined" = "undefined_"
escapeReserved "error" = "error_"
escapeReserved "map" = "map_"
escapeReserved "length" = "length_"
escapeReserved "mapM" = "mapM__"
escapeReserved "mapM_" = "mapM___"
escapeReserved "fromIntegral" = "fromIntegral_"
escapeReserved "realToFrac" = "realToFrac_"
escapeReserved "peek" = "peek_"
escapeReserved "poke" = "poke_"
escapeReserved "sizeOf" = "sizeOf_"
escapeReserved "when" = "when_"
escapeReserved "default" = "default_"
escapeReserved s :: Text
s
| "set_" Text -> Text -> Bool
`T.isPrefixOf` Text
s = Text
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "_"
| "get_" Text -> Text -> Bool
`T.isPrefixOf` Text
s = Text
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "_"
| Bool
otherwise = Text
s
signalInfoName :: Name -> Signal -> CodeGen Text
signalInfoName :: Name -> Signal -> CodeGen Text
signalInfoName n :: Name
n signal :: Signal
signal = do
let infoName :: Text
infoName = Name -> Text
upperName Name
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> Text
ucFirst (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
signalHaskellName (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal -> Text
sigName) Signal
signal
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "SignalInfo"
Text -> Name -> CodeGen Text
qualifiedSymbol Text
infoName Name
n
signalHaskellName :: Text -> Text
signalHaskellName :: Text -> Text
signalHaskellName sn :: Text
sn = let (w :: Text
w:ws :: [Text]
ws) = (Char -> Bool) -> Text -> [Text]
T.split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '-') Text
sn
in Text
w Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.concat ((Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
ucFirst [Text]
ws)