content: {-# LANGUAGE ConstraintKinds #-}
  {-# LANGUAGE FlexibleContexts #-}
  
  module Clang.Type
  ( isSameType
  , getTypeSpelling
  , getKind
  , getCanonicalType
  , getPointeeType
  , getResultType
  , getNumArgTypes
  , getArgType
  , isFunctionTypeVariadic
  
  , getTypedefDeclUnderlyingType
  , getEnumDeclIntegerType
  , getEnumConstantDeclValue
  , getEnumConstantDeclUnsignedValue
  , getFieldDeclBitWidth
  
  , isConstQualifiedType
  , isVolatileQualifiedType
  , isRestrictQualifiedType
  , isPODType
  , getElementType
  , getNumElements
  , getArrayElementType
  , getArraySize
  , getAlignOf
  , getSizeOf
  , getOffsetOf
  , getClassType
  , getCXXRefQualifier
  , isVirtualBase
  , getFunctionTypeCallingConv
  
  , getTypeKindSpelling
  ) where
  
  import Control.Monad.IO.Class
  import qualified Data.ByteString as B
  import Data.Int (Int64)
  import Data.Word (Word64)
  
  import qualified Clang.Internal.FFI as FFI
  import Clang.Internal.Monad
  
  isSameType :: ClangBase m => FFI.Type s' -> FFI.Type s'' -> ClangT s m Bool
  isSameType a b = liftIO $ FFI.equalTypes a b
  
  getTypeSpelling :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.ClangString s)
  getTypeSpelling = FFI.getTypeSpelling
  
  getTypedefDeclUnderlyingType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
  getTypedefDeclUnderlyingType c = liftIO $ FFI.getTypedefDeclUnderlyingType mkProxy c
  
  getEnumDeclIntegerType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
  getEnumDeclIntegerType c = liftIO $ FFI.getEnumDeclIntegerType mkProxy c
  
  getEnumConstantDeclValue :: ClangBase m => FFI.Cursor s' -> ClangT s m Int64
  getEnumConstantDeclValue c = liftIO $ FFI.getEnumConstantDeclValue c
  
  getEnumConstantDeclUnsignedValue :: ClangBase m => FFI.Cursor s' -> ClangT s m Word64
  getEnumConstantDeclUnsignedValue c = liftIO $ FFI.getEnumConstantDeclUnsignedValue c
  
  getFieldDeclBitWidth :: ClangBase m => FFI.Cursor s' -> ClangT s m (Maybe Int)
  getFieldDeclBitWidth c = do
    bitWidth <- liftIO $ FFI.getFieldDeclBitWidth c
    return $ if bitWidth < 0 then Nothing
                             else Just bitWidth
      
  getKind :: ClangBase m => FFI.Type s' -> ClangT s m FFI.TypeKind
  getKind = return . FFI.getTypeKind
  
  getCanonicalType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
  getCanonicalType t = liftIO $ FFI.getCanonicalType mkProxy t
  
  getPointeeType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
  getPointeeType t = liftIO $ FFI.getPointeeType mkProxy t
  
  getResultType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
  getResultType t = liftIO $ FFI.getResultType mkProxy t
  
  getNumArgTypes :: ClangBase m => FFI.Type s' -> ClangT s m Int
  getNumArgTypes t = liftIO $ FFI.getNumArgTypes t
  
  getArgType :: ClangBase m => FFI.Type s' -> Int -> ClangT s m (FFI.Type s)
  getArgType t i = liftIO $ FFI.getArgType mkProxy t i
  
  isFunctionTypeVariadic :: ClangBase m => FFI.Type s' -> ClangT s m Bool
  isFunctionTypeVariadic t = liftIO $ FFI.isFunctionTypeVariadic t
  
  isConstQualifiedType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
  isConstQualifiedType t = liftIO $ FFI.isConstQualifiedType t
  
  isVolatileQualifiedType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
  isVolatileQualifiedType t = liftIO $ FFI.isVolatileQualifiedType t
  
  isRestrictQualifiedType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
  isRestrictQualifiedType t = liftIO $ FFI.isRestrictQualifiedType t
  
  isPODType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
  isPODType t = liftIO $ FFI.isPODType t
  
  getElementType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
  getElementType t = liftIO $ FFI.getElementType mkProxy t
  
  getNumElements :: ClangBase m => FFI.Type s' -> ClangT s m Int64
  getNumElements t = liftIO $ FFI.getNumElements t
  
  getArrayElementType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
  getArrayElementType t = liftIO $ FFI.getArrayElementType mkProxy t
  
  getArraySize :: ClangBase m => FFI.Type s' -> ClangT s m Int64
  getArraySize t = liftIO $ FFI.getArraySize t
  
  getAlignOf :: ClangBase m => FFI.Type s' -> ClangT s m (Either FFI.TypeLayoutError Int64)
  getAlignOf t = liftIO $ FFI.type_getAlignOf t
  
  getSizeOf :: ClangBase m => FFI.Type s' -> ClangT s m (Either FFI.TypeLayoutError Int64)
  getSizeOf t = liftIO $ FFI.type_getSizeOf t
  
  getOffsetOf :: ClangBase m => FFI.Type s' -> B.ByteString
              -> ClangT s m (Either FFI.TypeLayoutError Int64)
  getOffsetOf = FFI.type_getOffsetOf
  
  getClassType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
  getClassType t = liftIO $ FFI.type_getClassType mkProxy t
  
  getCXXRefQualifier :: ClangBase m => FFI.Type s' -> ClangT s m FFI.RefQualifierKind
  getCXXRefQualifier t = liftIO $ FFI.type_getCXXRefQualifier t
  
  isVirtualBase :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
  isVirtualBase c = liftIO $ FFI.isVirtualBase c
  
  getFunctionTypeCallingConv :: ClangBase m => FFI.Type s' -> ClangT s m FFI.CallingConv
  getFunctionTypeCallingConv t = liftIO $ FFI.getFunctionTypeCallingConv t
  
  
  -- Typekind functions
  getTypeKindSpelling :: ClangBase m => FFI.TypeKind -> ClangT s m (FFI.ClangString s)
  getTypeKindSpelling = FFI.getTypeKindSpelling
  