module LLVM.General.Internal.Coding where
import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Control.Monad
import Control.Monad.AnyCont
import Control.Monad.IO.Class
import Data.Data (Data)
import Data.Word (Word, Word32, Word64)
import Data.Int (Int32)
import Foreign.C
import Foreign.Ptr
import Foreign.Storable
import Foreign.Marshal.Alloc
import Foreign.Marshal.Array
import qualified LLVM.General.Internal.FFI.LLVMCTypes as FFI
class EncodeM e h c where
encodeM :: h -> e c
class DecodeM d h c where
decodeM :: c -> d h
genCodingInstance :: (Data c, Data h) => TypeQ -> Name -> [(c, h)] -> Q [Dec]
genCodingInstance ht ctn chs = do
let n = const Nothing
[d|
instance Monad m => EncodeM m $(ht) $(conT ctn) where
encodeM h = return $ $(
caseE [| h |] [ match (dataToPatQ n h) (normalB (dataToExpQ n c)) [] | (c,h) <- chs ]
)
instance Monad m => DecodeM m $(ht) $(conT ctn) where
decodeM c = return $ $(
caseE [| c |] [ match (dataToPatQ n c) (normalB (dataToExpQ n h)) [] | (c,h) <- chs ]
)
|]
allocaArray :: (Integral i, Storable a, MonadAnyCont IO m) => i -> m (Ptr a)
allocaArray p = anyContToM $ Foreign.Marshal.Array.allocaArray (fromIntegral p)
alloca :: (Storable a, MonadAnyCont IO m) => m (Ptr a)
alloca = anyContToM Foreign.Marshal.Alloc.alloca
peek :: (Storable a, MonadIO m) => Ptr a -> m a
peek p = liftIO $ Foreign.Storable.peek p
peekByteOff :: (Storable a, MonadIO m) => Ptr a -> Int -> m a
peekByteOff p i = liftIO $ Foreign.Storable.peekByteOff p i
poke :: (Storable a, MonadIO m) => Ptr a -> a -> m ()
poke p a = liftIO $ Foreign.Storable.poke p a
pokeByteOff :: (Storable a, MonadIO m) => Ptr a -> Int -> a -> m ()
pokeByteOff p i a = liftIO $ Foreign.Storable.pokeByteOff p i a
peekArray :: (Integral i, Storable a, MonadIO m) => i -> Ptr a -> m [a]
peekArray n p = liftIO $ Foreign.Marshal.Array.peekArray (fromIntegral n) p
instance (Monad m, EncodeM m h c, Storable c, MonadAnyCont IO m) => EncodeM m [h] (CUInt, Ptr c) where
encodeM hs = do
hs <- mapM encodeM hs
(anyContToM $ \x -> Foreign.Marshal.Array.withArrayLen hs $ \n hs -> x (fromIntegral n, hs))
instance (Monad m, DecodeM m h c, Storable c, MonadIO m) => DecodeM m [h] (CUInt, Ptr c) where
decodeM (n, ca) = do
cs <- liftIO $ Foreign.Marshal.Array.peekArray (fromIntegral n) ca
mapM decodeM cs
instance Monad m => EncodeM m Bool FFI.LLVMBool where
encodeM False = return $ FFI.LLVMBool 0
encodeM True = return $ FFI.LLVMBool 1
instance Monad m => DecodeM m Bool FFI.LLVMBool where
decodeM (FFI.LLVMBool 0) = return $ False
decodeM (FFI.LLVMBool _) = return $ True
instance (Monad m, EncodeM m h (Ptr c)) => EncodeM m (Maybe h) (Ptr c) where
encodeM = maybe (return nullPtr) encodeM
instance (Monad m, DecodeM m h (Ptr c)) => DecodeM m (Maybe h) (Ptr c) where
decodeM p | p == nullPtr = return Nothing
| otherwise = liftM Just $ decodeM p
instance Monad m => EncodeM m (Maybe Bool) (FFI.NothingAsMinusOne Bool) where
encodeM = return . FFI.NothingAsMinusOne . maybe (1) (fromIntegral . fromEnum)
instance Monad m => EncodeM m (Maybe Word) (FFI.NothingAsMinusOne Word) where
encodeM = return . FFI.NothingAsMinusOne . maybe (1) fromIntegral
instance Monad m => EncodeM m Word CUInt where
encodeM = return . fromIntegral
instance Monad m => EncodeM m Word32 CUInt where
encodeM = return . fromIntegral
instance Monad m => EncodeM m Word64 CULong where
encodeM = return . fromIntegral
instance Monad m => DecodeM m Word32 CUInt where
decodeM = return . fromIntegral
instance Monad m => DecodeM m Word64 CULong where
decodeM = return . fromIntegral
instance Monad m => EncodeM m Int32 CInt where
encodeM = return . fromIntegral
instance Monad m => DecodeM m Int32 CInt where
decodeM = return . fromIntegral
instance Monad m => DecodeM m Int CInt where
decodeM = return . fromIntegral
instance Monad m => EncodeM m Word64 Word64 where
encodeM = return
instance Monad m => DecodeM m Word64 Word64 where
decodeM = return