module Data.GI.CodeGen.GObject
    ( isGObject
    , apiIsGObject
    , nameIsGObject
    ) where

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
#endif

import Data.GI.CodeGen.API
import Data.GI.CodeGen.Code
import Data.GI.CodeGen.Type

-- Returns whether the given type is a descendant of the given parent.
typeDoParentSearch :: Name -> Type -> CodeGen Bool
typeDoParentSearch :: Name -> Type -> CodeGen Bool
typeDoParentSearch Name
parent (TInterface Name
n) = HasCallStack => Name -> CodeGen API
Name -> CodeGen API
findAPIByName Name
n BaseCodeGen e API
-> (API
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool)
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
                                           Name -> Name -> API -> CodeGen Bool
apiDoParentSearch Name
parent Name
n
typeDoParentSearch Name
_ Type
_ = Bool
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False

apiDoParentSearch :: Name -> Name -> API -> CodeGen Bool
apiDoParentSearch :: Name -> Name -> API -> CodeGen Bool
apiDoParentSearch Name
parent Name
n API
api
    | Name
parent Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
n = Bool
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
    | Bool
otherwise   = case API
api of
      APIObject Object
o ->
        case Object -> Maybe Name
objParent Object
o of
          Just  Name
p -> Name -> Type -> CodeGen Bool
typeDoParentSearch Name
parent (Name -> Type
TInterface Name
p)
          Maybe Name
Nothing -> Bool
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
      APIInterface Interface
iface ->
        do let prs :: [Name]
prs = Interface -> [Name]
ifPrerequisites Interface
iface
           [(Name, API)]
prereqs <- [Name] -> [API] -> [(Name, API)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
prs ([API] -> [(Name, API)])
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [API]
-> ReaderT
     CodeGenConfig
     (StateT (CGState, ModuleInfo) (Except e))
     [(Name, API)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Name
 -> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) API)
-> [Name]
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [API]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM HasCallStack => Name -> CodeGen API
Name
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) API
findAPIByName [Name]
prs
           [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool)
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Bool]
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Name, API)
 -> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool)
-> [(Name, API)]
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) [Bool]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((Name
 -> API
 -> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool)
-> (Name, API)
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (Name -> Name -> API -> CodeGen Bool
apiDoParentSearch Name
parent)) [(Name, API)]
prereqs
      API
_ -> Bool
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False

-- | Check whether the given type descends from GObject.
isGObject :: Type -> CodeGen Bool
isGObject :: Type -> CodeGen Bool
isGObject = Name -> Type -> CodeGen Bool
typeDoParentSearch (Name -> Type -> CodeGen Bool) -> Name -> Type -> CodeGen Bool
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Name
Name Text
"GObject" Text
"Object"

-- | Check whether the given name descends from GObject.
nameIsGObject :: Name -> CodeGen Bool
nameIsGObject :: Name -> CodeGen Bool
nameIsGObject Name
n = HasCallStack => Name -> CodeGen API
Name -> CodeGen API
findAPIByName Name
n BaseCodeGen e API
-> (API
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool)
-> ReaderT
     CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Name -> API -> CodeGen Bool
apiIsGObject Name
n

-- | Check whether the given API descends from GObject.
apiIsGObject :: Name -> API -> CodeGen Bool
apiIsGObject :: Name -> API -> CodeGen Bool
apiIsGObject = Name -> Name -> API -> CodeGen Bool
apiDoParentSearch (Name -> Name -> API -> CodeGen Bool)
-> Name -> Name -> API -> CodeGen Bool
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Name
Name Text
"GObject" Text
"Object"