{-# LANGUAGE MagicHash, UnliftedFFITypes #-}
{-# LANGUAGE ForeignFunctionInterface #-}

-- Based on ghc/testsuite/tests/ffi/should_compile contents
module ForeignDecl where

import Foreign
import GHC.Exts
import Data.Int
import Data.Word

-- simple functions

foreign import ccall unsafe "a" a :: IO Int

foreign import ccall unsafe "b" b :: Int -> IO Int

foreign import ccall unsafe "c"
  c :: Int -> Char -> Float -> Double -> IO Float

-- simple monadic code

d =     a               >>= \ x ->
        b x             >>= \ y ->
        c y 'f' 1.0 2.0

-- We can't import the same function using both stdcall and ccall
-- calling conventions in the same file when compiling via C (this is a
-- restriction in the C backend caused by the need to emit a prototype
-- for stdcall functions).
foreign import stdcall        "p" m_stdcall :: StablePtr a -> IO (StablePtr b)
foreign import ccall   unsafe "q" m_ccall   :: ByteArray# -> IO Int

-- We can't redefine the calling conventions of certain functions (those from
-- math.h).
foreign import stdcall "my_sin" my_sin :: Double -> IO Double
foreign import stdcall "my_cos" my_cos :: Double -> IO Double

foreign import stdcall "m1" m8  :: IO Int8
foreign import stdcall "m2" m16 :: IO Int16
foreign import stdcall "m3" m32 :: IO Int32
foreign import stdcall "m4" m64 :: IO Int64

foreign import stdcall "dynamic" d8  :: FunPtr (IO Int8) -> IO Int8
foreign import stdcall "dynamic" d16 :: FunPtr (IO Int16) -> IO Int16
foreign import stdcall "dynamic" d32 :: FunPtr (IO Int32) -> IO Int32
foreign import stdcall "dynamic" d64 :: FunPtr (IO Int64) -> IO Int64

foreign import ccall unsafe "safe_qd.h safe_qd_add" c_qd_add :: Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> IO ();

foreign import ccall unsafe "kitchen"
   sink :: Ptr a
        -> ByteArray#
        -> MutableByteArray# RealWorld
        -> Int
        -> Int8
        -> Int16
        -> Int32
        -> Int64
        -> Word8
        -> Word16
        -> Word32
        -> Word64
        -> Float
        -> Double
        -> IO ()


type Sink2 b = Ptr b
            -> ByteArray#
            -> MutableByteArray# RealWorld
            -> Int
            -> Int8
            -> Int16
            -> Int32
            -> Word8
            -> Word16
            -> Word32
            -> Float
            -> Double
            -> IO ()

foreign import ccall unsafe "dynamic"
  sink2 :: Ptr (Sink2 b) -> Sink2 b

-- exports
foreign export ccall "plusInt" (+) :: Int -> Int -> Int

listToJSArray :: ToJSRef a => [a] -> IO (JSArray a)
listToJSArray = toJSArray deconstr
        where deconstr (x : xs) = Just (x, xs)
              deconstr [] = Nothing

foreign import javascript unsafe "$r = new Float32Array($1);"
        float32Array :: JSArray Float -> IO Float32Array

foreign import javascript unsafe "$r = new Int32Array($1);"
        int32Array :: JSArray Int32 -> IO Int32Array

foreign import javascript unsafe "$r = new Uint16Array($1);"
        uint16Array :: JSArray Word16 -> IO Uint16Array

foreign import javascript unsafe "$r = new Uint8Array($1);"
        uint8Array :: JSArray Word8 -> IO Uint8Array

foreign import javascript unsafe "$r = $1.getContext(\"webgl\");"
        getCtx :: JSRef a -> IO Ctx
