module Data.GI.CodeGen.OverloadedSignals
( genObjectSignals
, genInterfaceSignals
, genOverloadedSignalConnectors
) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
#endif
import Control.Monad (forM_, when)
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid ((<>))
#endif
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Set as S
import Data.GI.CodeGen.API
import Data.GI.CodeGen.Code
import Data.GI.CodeGen.Inheritance (fullObjectSignalList, fullInterfaceSignalList)
import Data.GI.CodeGen.GObject (apiIsGObject)
import Data.GI.CodeGen.SymbolNaming (upperName, hyphensToCamelCase,
signalInfoName)
import Data.GI.CodeGen.Util (lcFirst)
findSignalNames :: [(Name, API)] -> CodeGen [Text]
findSignalNames :: [(Name, API)] -> CodeGen [Text]
findSignalNames [(Name, API)]
apis = Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text])
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) (Set Text)
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Name, API)] -> Set Text -> CodeGen (Set Text)
go [(Name, API)]
apis Set Text
forall a. Set a
S.empty
where
go :: [(Name, API)] -> S.Set Text -> CodeGen (S.Set Text)
go :: [(Name, API)] -> Set Text -> CodeGen (Set Text)
go [] Set Text
set = Set Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) (Set Text)
forall (m :: * -> *) a. Monad m => a -> m a
return Set Text
set
go ((Name
_, API
api):[(Name, API)]
apis) Set Text
set =
case API
api of
APIInterface Interface
iface ->
[(Name, API)] -> Set Text -> CodeGen (Set Text)
go [(Name, API)]
apis (Set Text -> CodeGen (Set Text)) -> Set Text -> CodeGen (Set Text)
forall a b. (a -> b) -> a -> b
$ [Signal] -> Set Text -> Set Text
insertSignals (Interface -> [Signal]
ifSignals Interface
iface) Set Text
set
APIObject Object
object ->
[(Name, API)] -> Set Text -> CodeGen (Set Text)
go [(Name, API)]
apis (Set Text -> CodeGen (Set Text)) -> Set Text -> CodeGen (Set Text)
forall a b. (a -> b) -> a -> b
$ [Signal] -> Set Text -> Set Text
insertSignals (Object -> [Signal]
objSignals Object
object) Set Text
set
API
_ -> [(Name, API)] -> Set Text -> CodeGen (Set Text)
go [(Name, API)]
apis Set Text
set
insertSignals :: [Signal] -> S.Set Text -> S.Set Text
insertSignals :: [Signal] -> Set Text -> Set Text
insertSignals [Signal]
props Set Text
set = (Signal -> Set Text -> Set Text)
-> Set Text -> [Signal] -> Set Text
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Text -> Set Text -> Set Text
forall a. Ord a => a -> Set a -> Set a
S.insert (Text -> Set Text -> Set Text)
-> (Signal -> Text) -> Signal -> Set Text -> Set Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal -> Text
sigName) Set Text
set [Signal]
props
genOverloadedSignalConnectors :: [(Name, API)] -> CodeGen ()
genOverloadedSignalConnectors :: [(Name, API)] -> CodeGen ()
genOverloadedSignalConnectors [(Name, API)]
allAPIs = do
[Text] -> CodeGen ()
setLanguagePragmas [Text
"DataKinds", Text
"PatternSynonyms", Text
"CPP",
Text
"RankNTypes", Text
"ScopedTypeVariables", Text
"TypeFamilies"]
[ModuleFlag] -> CodeGen ()
setModuleFlags [ModuleFlag
ImplicitPrelude]
Text -> CodeGen ()
line Text
"import Data.GI.Base.Signals (SignalProxy(..))"
Text -> CodeGen ()
line Text
"import Data.GI.Base.Overloading (ResolveSignal)"
BaseCodeGen e ()
CodeGen ()
blank
[Text]
signalNames <- [(Name, API)] -> CodeGen [Text]
findSignalNames [(Name, API)]
allAPIs
[Text] -> (Text -> BaseCodeGen e ()) -> BaseCodeGen e ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Text]
signalNames ((Text -> BaseCodeGen e ()) -> BaseCodeGen e ())
-> (Text -> BaseCodeGen e ()) -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ \Text
sn -> 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
let camelName :: Text
camelName = Text -> Text
hyphensToCamelCase Text
sn
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"pattern " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
camelName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
" :: SignalProxy object (ResolveSignal \""
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
lcFirst Text
camelName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\" object)"
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"pattern " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
camelName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = SignalProxy"
Text -> CodeGen ()
exportDecl (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"pattern " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
camelName
genObjectSignals :: Name -> Object -> CodeGen ()
genObjectSignals :: Name -> Object -> CodeGen ()
genObjectSignals Name
n Object
o = do
let name :: Text
name = Name -> Text
upperName Name
n
Bool
isGO <- Name -> API -> CodeGen Bool
apiIsGObject Name
n (Object -> API
APIObject Object
o)
Bool -> BaseCodeGen e () -> BaseCodeGen e ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isGO (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
[Text]
infos <- Name -> Object -> CodeGen [(Name, Signal)]
fullObjectSignalList Name
n Object
o BaseCodeGen e [(Name, Signal)]
-> ([(Name, Signal)]
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text])
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
((Name, Signal)
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> [(Name, Signal)]
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\(Name
owner, Signal
signal) -> do
Text
si <- Name -> Signal -> CodeGen Text
signalInfoName Name
owner Signal
signal
Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a b. (a -> b) -> a -> b
$ Text
"'(\"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> Text
lcFirst (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
hyphensToCamelCase (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
<> Text
"\", " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
si Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
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
let signalListType :: Text
signalListType = Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"SignalList"
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"type instance O.SignalList " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"type " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = ('[ "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " [Text]
infos Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"] :: [(Symbol, *)])"
genInterfaceSignals :: Name -> Interface -> CodeGen ()
genInterfaceSignals :: Name -> Interface -> CodeGen ()
genInterfaceSignals Name
n Interface
iface = do
let name :: Text
name = Name -> Text
upperName Name
n
[Text]
infos <- Name -> Interface -> CodeGen [(Name, Signal)]
fullInterfaceSignalList Name
n Interface
iface BaseCodeGen e [(Name, Signal)]
-> ([(Name, Signal)]
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text])
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
((Name, Signal)
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> [(Name, Signal)]
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\(Name
owner, Signal
signal) -> do
Text
si <- Name -> Signal -> CodeGen Text
signalInfoName Name
owner Signal
signal
Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a b. (a -> b) -> a -> b
$ Text
"'(\"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> Text
lcFirst (Text -> Text) -> (Signal -> Text) -> Signal -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
hyphensToCamelCase (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
<> Text
"\", " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
si Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
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
let signalListType :: Text
signalListType = Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"SignalList"
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"type instance O.SignalList " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"type " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
signalListType Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = ('[ "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " [Text]
infos Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"] :: [(Symbol, *)])"