{-# LANGUAGE ViewPatterns #-}
module Data.GI.CodeGen.SymbolNaming
( lowerName
, lowerSymbol
, upperName
, noName
, escapedArgName
, classConstraint
, typeConstraint
, hyphensToCamelCase
, underscoresToCamelCase
, callbackCType
, callbackHTypeWithClosures
, callbackDropClosures
, callbackDynamicWrapper
, callbackWrapperAllocator
, callbackHaskellToForeign
, callbackHaskellToForeignWithClosures
, callbackClosureGenerator
, submoduleLocation
, qualifiedAPI
, qualifiedSymbol
) where
import Data.Monoid ((<>))
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 n@(Name _ s) = qualifiedSymbol ("Is" <> s) n
typeConstraint :: Type -> CodeGen Text
typeConstraint (TInterface n) = classConstraint n
typeConstraint t = error $ "Class constraint for non-interface type: " <> show t
callbackCType :: Text -> Text
callbackCType = modifyQualified ("C_" <>)
callbackHTypeWithClosures :: Text -> Text
callbackHTypeWithClosures = modifyQualified (<> "_WithClosures")
callbackDynamicWrapper :: Text -> Text
callbackDynamicWrapper = modifyQualified ("dynamic_" <>)
callbackHaskellToForeign :: Text -> Text
callbackHaskellToForeign = modifyQualified ("wrap_" <>)
callbackHaskellToForeignWithClosures :: Text -> Text
callbackHaskellToForeignWithClosures = modifyQualified ("with_closures_" <>)
callbackDropClosures :: Text -> Text
callbackDropClosures = modifyQualified ("drop_closures_" <>)
callbackWrapperAllocator :: Text -> Text
callbackWrapperAllocator = modifyQualified ("mk_" <>)
callbackClosureGenerator :: Text -> Text
callbackClosureGenerator = modifyQualified ("genClosure_" <>)
sanitize :: Text -> Text
sanitize (T.uncons -> Just ('_', xs)) = sanitize xs <> "_"
sanitize xs = xs
lowerName :: Name -> Text
lowerName (Name _ s) = lowerSymbol s
lowerSymbol :: Text -> Text
lowerSymbol s = case underscoresToCamelCase (sanitize s) of
"" -> error "empty name!!"
n -> lcFirst n
upperName :: Name -> Text
upperName (Name _ s) = underscoresToCamelCase (sanitize s)
submoduleLocation :: Name -> API -> ModulePath
submoduleLocation _ (APIConst _) = "Constants"
submoduleLocation _ (APIFunction _) = "Functions"
submoduleLocation _ (APICallback _) = "Callbacks"
submoduleLocation _ (APIEnum _) = "Enums"
submoduleLocation _ (APIFlags _) = "Flags"
submoduleLocation n (APIInterface _) = "Interfaces" /. upperName n
submoduleLocation n (APIObject _) = "Objects" /. upperName n
submoduleLocation n (APIStruct _) = "Structs" /. upperName n
submoduleLocation n (APIUnion _) = "Unions" /. upperName n
qualifiedAPI :: Name -> CodeGen Text
qualifiedAPI n@(Name ns _) = do
api <- getAPI (TInterface n)
qualified (toModulePath (ucFirst ns) <> submoduleLocation n api) n
qualifiedSymbol :: Text -> Name -> CodeGen Text
qualifiedSymbol s n@(Name ns _) = do
api <- getAPI (TInterface n)
qualified (toModulePath (ucFirst ns) <> submoduleLocation n api) (Name ns s)
noName :: Text -> CodeGen ()
noName name' = group $ do
line $ "-- | A convenience alias for `Nothing` :: `Maybe` `" <> name' <> "`."
line $ "no" <> name' <> " :: Maybe " <> name'
line $ "no" <> name' <> " = Nothing"
exportDecl ("no" <> name')
hyphensToCamelCase :: Text -> Text
hyphensToCamelCase = T.concat . map ucFirst . T.split (== '-')
underscoresToCamelCase :: Text -> Text
underscoresToCamelCase =
T.concat . map normalize . map ucFirst . T.split (== '_')
where normalize :: Text -> Text
normalize "" = "_"
normalize s = s
escapedArgName :: Arg -> Text
escapedArgName arg
| "_" `T.isPrefixOf` argCName arg = argCName arg
| otherwise =
escapeReserved . lcFirst . underscoresToCamelCase . argCName $ arg
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
| "set_" `T.isPrefixOf` s = s <> "_"
| "get_" `T.isPrefixOf` s = s <> "_"
| otherwise = s