module Data.GI.GIR.Callable
    ( Callable(..)
    , parseCallable
    ) where

import Data.GI.GIR.Arg (Arg(..), parseArg, parseTransfer)
import Data.GI.GIR.BasicTypes (Transfer(..), Type)
import Data.GI.GIR.Parser
import Data.GI.GIR.Type (parseOptionalType)

data Callable = Callable {
        Callable -> Maybe Type
returnType :: Maybe Type,
        Callable -> Bool
returnMayBeNull :: Bool,
        Callable -> Transfer
returnTransfer :: Transfer,
        Callable -> Documentation
returnDocumentation :: Documentation,
        Callable -> [Arg]
args :: [Arg],
        Callable -> Bool
skipReturn :: Bool,
        Callable -> Bool
callableThrows :: Bool,
        Callable -> Maybe DeprecationInfo
callableDeprecated :: Maybe DeprecationInfo,
        Callable -> Documentation
callableDocumentation :: Documentation,
        -- | Whether the symbol for this callable can be resolved in
        -- the dynamical library associated with the current
        -- introspection data. 'Nothing' means that we have not
        -- checked yet.
        Callable -> Maybe Bool
callableResolvable :: Maybe Bool
    } deriving (Int -> Callable -> ShowS
[Callable] -> ShowS
Callable -> String
(Int -> Callable -> ShowS)
-> (Callable -> String) -> ([Callable] -> ShowS) -> Show Callable
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Callable -> ShowS
showsPrec :: Int -> Callable -> ShowS
$cshow :: Callable -> String
show :: Callable -> String
$cshowList :: [Callable] -> ShowS
showList :: [Callable] -> ShowS
Show, Callable -> Callable -> Bool
(Callable -> Callable -> Bool)
-> (Callable -> Callable -> Bool) -> Eq Callable
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Callable -> Callable -> Bool
== :: Callable -> Callable -> Bool
$c/= :: Callable -> Callable -> Bool
/= :: Callable -> Callable -> Bool
Eq)

parseArgs :: Parser [Arg]
parseArgs :: Parser [Arg]
parseArgs = do
  [[Arg]]
paramSets <- ParseError -> Parser [Arg] -> Parser [[Arg]]
forall a. ParseError -> Parser a -> Parser [a]
parseChildrenWithLocalName ParseError
"parameters" Parser [Arg]
parseArgSet
  case [[Arg]]
paramSets of
    [] -> [Arg] -> Parser [Arg]
forall a. a -> ReaderT ParseContext (Except ParseError) a
forall (m :: * -> *) a. Monad m => a -> m a
return []
    ([Arg]
ps:[]) -> [Arg] -> Parser [Arg]
forall a. a -> ReaderT ParseContext (Except ParseError) a
forall (m :: * -> *) a. Monad m => a -> m a
return [Arg]
ps
    [[Arg]]
_ -> ParseError -> Parser [Arg]
forall a. ParseError -> Parser a
parseError (ParseError -> Parser [Arg]) -> ParseError -> Parser [Arg]
forall a b. (a -> b) -> a -> b
$ ParseError
"Unexpected multiple \"parameters\" tag"
  where parseArgSet :: Parser [Arg]
parseArgSet = ParseError -> Parser Arg -> Parser [Arg]
forall a. ParseError -> Parser a -> Parser [a]
parseChildrenWithLocalName ParseError
"parameter" Parser Arg
parseArg

parseOneReturn :: Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
parseOneReturn :: Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
parseOneReturn = do
  Maybe Type
returnType <- Parser (Maybe Type)
parseOptionalType
  Bool
allowNone <- Name -> Bool -> (ParseError -> Parser Bool) -> Parser Bool
forall a. Name -> a -> (ParseError -> Parser a) -> Parser a
optionalAttr Name
"allow-none" Bool
False ParseError -> Parser Bool
parseBool
  Bool
nullable <- Name -> Bool -> (ParseError -> Parser Bool) -> Parser Bool
forall a. Name -> a -> (ParseError -> Parser a) -> Parser a
optionalAttr Name
"nullable" Bool
False ParseError -> Parser Bool
parseBool
  Transfer
transfer <- Parser Transfer
parseTransfer
  Documentation
doc <- Parser Documentation
parseDocumentation
  Bool
skip <- Name -> Bool -> (ParseError -> Parser Bool) -> Parser Bool
forall a. Name -> a -> (ParseError -> Parser a) -> Parser a
optionalAttr Name
"skip" Bool
False ParseError -> Parser Bool
parseBool
  (Maybe Type, Bool, Transfer, Bool, Documentation)
-> Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
forall a. a -> ReaderT ParseContext (Except ParseError) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Type
returnType, Bool
allowNone Bool -> Bool -> Bool
|| Bool
nullable, Transfer
transfer, Bool
skip, Documentation
doc)

parseReturn :: Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
parseReturn :: Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
parseReturn = do
  [(Maybe Type, Bool, Transfer, Bool, Documentation)]
returnSets <- ParseError
-> Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
-> Parser [(Maybe Type, Bool, Transfer, Bool, Documentation)]
forall a. ParseError -> Parser a -> Parser [a]
parseChildrenWithLocalName ParseError
"return-value" Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
parseOneReturn
  case [(Maybe Type, Bool, Transfer, Bool, Documentation)]
returnSets of
    ((Maybe Type, Bool, Transfer, Bool, Documentation)
r:[]) -> (Maybe Type, Bool, Transfer, Bool, Documentation)
-> Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
forall a. a -> ReaderT ParseContext (Except ParseError) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Type, Bool, Transfer, Bool, Documentation)
r
    [] -> ParseError
-> Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
forall a. ParseError -> Parser a
parseError (ParseError
 -> Parser (Maybe Type, Bool, Transfer, Bool, Documentation))
-> ParseError
-> Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
forall a b. (a -> b) -> a -> b
$ ParseError
"No return information found"
    [(Maybe Type, Bool, Transfer, Bool, Documentation)]
_ -> ParseError
-> Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
forall a. ParseError -> Parser a
parseError (ParseError
 -> Parser (Maybe Type, Bool, Transfer, Bool, Documentation))
-> ParseError
-> Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
forall a b. (a -> b) -> a -> b
$ ParseError
"Multiple return values found"

parseCallable :: Parser Callable
parseCallable :: Parser Callable
parseCallable = do
  [Arg]
args <- Parser [Arg]
parseArgs
  (Maybe Type
returnType, Bool
mayBeNull, Transfer
transfer, Bool
skip, Documentation
returnDoc) <- Parser (Maybe Type, Bool, Transfer, Bool, Documentation)
parseReturn
  Maybe DeprecationInfo
deprecated <- Parser (Maybe DeprecationInfo)
parseDeprecation
  Documentation
docs <- Parser Documentation
parseDocumentation
  Bool
throws <- Name -> Bool -> (ParseError -> Parser Bool) -> Parser Bool
forall a. Name -> a -> (ParseError -> Parser a) -> Parser a
optionalAttr Name
"throws" Bool
False ParseError -> Parser Bool
parseBool
  Callable -> Parser Callable
forall a. a -> ReaderT ParseContext (Except ParseError) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Callable -> Parser Callable) -> Callable -> Parser Callable
forall a b. (a -> b) -> a -> b
$ Callable {
                  returnType :: Maybe Type
returnType = Maybe Type
returnType
                , returnMayBeNull :: Bool
returnMayBeNull = Bool
mayBeNull
                , returnTransfer :: Transfer
returnTransfer = Transfer
transfer
                , returnDocumentation :: Documentation
returnDocumentation = Documentation
returnDoc
                , args :: [Arg]
args = [Arg]
args
                , skipReturn :: Bool
skipReturn = Bool
skip
                , callableThrows :: Bool
callableThrows = Bool
throws
                , callableDeprecated :: Maybe DeprecationInfo
callableDeprecated = Maybe DeprecationInfo
deprecated
                , callableDocumentation :: Documentation
callableDocumentation = Documentation
docs
                  -- Some symbols are present in the @.gir@ file, but
                  -- they are absent from the library
                  -- itself. Generating bindings for such symbols
                  -- could then lead to linker errors, so later on we
                  -- check whether the callables are actually
                  -- resolvable, and adjust the callable info
                  -- appropriately.
                , callableResolvable :: Maybe Bool
callableResolvable = Maybe Bool
forall a. Maybe a
Nothing
                }