{-# LANGUAGE LambdaCase #-}
module Data.GI.CodeGen.Callable
( genCCallableWrapper
, genDynamicCallableWrapper
, ForeignSymbol(..)
, hOutType
, skipRetVal
, arrayLengths
, arrayLengthsMap
, callableSignature
, Signature(..)
, fixupCallerAllocates
, callableHInArgs
, callableHOutArgs
, wrapMaybe
, inArgInterfaces
) where
import Control.Monad (forM, forM_, when, void)
import Data.Bool (bool)
import Data.List (nub)
import Data.Maybe (isJust)
#if !MIN_VERSION_base(4,13,0)
import Data.Monoid ((<>))
#endif
import Data.Tuple (swap)
import qualified Data.Map as Map
import qualified Data.Text as T
import Data.Text (Text)
import Data.GI.CodeGen.API
import Data.GI.CodeGen.Code
import Data.GI.CodeGen.Conversions
import Data.GI.CodeGen.Haddock (deprecatedPragma, writeHaddock,
writeDocumentation, RelativeDocPosition(..),
writeArgDocumentation, writeReturnDocumentation)
import Data.GI.CodeGen.SymbolNaming
import Data.GI.CodeGen.Transfer
import Data.GI.CodeGen.Type
import Data.GI.CodeGen.Util
import Text.Show.Pretty (ppShow)
hOutType :: Callable -> [Arg] -> ExcCodeGen TypeRep
hOutType :: Callable -> [Arg] -> ExcCodeGen TypeRep
hOutType Callable
callable [Arg]
outArgs = do
TypeRep
hReturnType <- case Callable -> Maybe Type
returnType Callable
callable of
Maybe Type
Nothing -> TypeRep -> ExcCodeGen TypeRep
forall (m :: * -> *) a. Monad m => a -> m a
return (TypeRep -> ExcCodeGen TypeRep) -> TypeRep -> ExcCodeGen TypeRep
forall a b. (a -> b) -> a -> b
$ Text -> TypeRep
con0 Text
"()"
Just Type
r -> if Callable -> Bool
skipRetVal Callable
callable
then TypeRep -> ExcCodeGen TypeRep
forall (m :: * -> *) a. Monad m => a -> m a
return (TypeRep -> ExcCodeGen TypeRep) -> TypeRep -> ExcCodeGen TypeRep
forall a b. (a -> b) -> a -> b
$ Text -> TypeRep
con0 Text
"()"
else Type -> CodeGen TypeRep
haskellType Type
r
[TypeRep]
hOutArgTypes <- [Arg]
-> (Arg -> ExcCodeGen TypeRep)
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[TypeRep]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Arg]
outArgs ((Arg -> ExcCodeGen TypeRep)
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[TypeRep])
-> (Arg -> ExcCodeGen TypeRep)
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[TypeRep]
forall a b. (a -> b) -> a -> b
$ \Arg
outarg ->
Arg -> CodeGen Bool
wrapMaybe Arg
outarg BaseCodeGen CGError Bool
-> (Bool -> ExcCodeGen TypeRep) -> ExcCodeGen TypeRep
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ExcCodeGen TypeRep
-> ExcCodeGen TypeRep -> Bool -> ExcCodeGen TypeRep
forall a. a -> a -> Bool -> a
bool
(Type -> CodeGen TypeRep
haskellType (Arg -> Type
argType Arg
outarg))
(TypeRep -> TypeRep
maybeT (TypeRep -> TypeRep) -> ExcCodeGen TypeRep -> ExcCodeGen TypeRep
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Type -> CodeGen TypeRep
haskellType (Arg -> Type
argType Arg
outarg))
Bool
nullableReturnType <- BaseCodeGen CGError Bool
-> (Type -> BaseCodeGen CGError Bool)
-> Maybe Type
-> BaseCodeGen CGError Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Bool -> BaseCodeGen CGError Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False) Type -> BaseCodeGen CGError Bool
Type -> CodeGen Bool
typeIsNullable (Callable -> Maybe Type
returnType Callable
callable)
let maybeHReturnType :: TypeRep
maybeHReturnType = if Callable -> Bool
returnMayBeNull Callable
callable
Bool -> Bool -> Bool
&& Bool -> Bool
not (Callable -> Bool
skipRetVal Callable
callable)
Bool -> Bool -> Bool
&& Bool
nullableReturnType
then TypeRep -> TypeRep
maybeT TypeRep
hReturnType
else TypeRep
hReturnType
TypeRep -> ExcCodeGen TypeRep
forall (m :: * -> *) a. Monad m => a -> m a
return (TypeRep -> ExcCodeGen TypeRep) -> TypeRep -> ExcCodeGen TypeRep
forall a b. (a -> b) -> a -> b
$ case ([Arg]
outArgs, TypeRep -> Text
typeShow TypeRep
maybeHReturnType) of
([], Text
_) -> TypeRep
maybeHReturnType
([Arg]
_, Text
"()") -> Text
"(,)" Text -> [TypeRep] -> TypeRep
`con` [TypeRep]
hOutArgTypes
([Arg], Text)
_ -> Text
"(,)" Text -> [TypeRep] -> TypeRep
`con` (TypeRep
maybeHReturnType TypeRep -> [TypeRep] -> [TypeRep]
forall a. a -> [a] -> [a]
: [TypeRep]
hOutArgTypes)
mkForeignImport :: Text -> Callable -> CodeGen Text
mkForeignImport :: Text -> Callable -> CodeGen Text
mkForeignImport Text
cSymbol Callable
callable = do
Text -> CodeGen ()
line Text
first
BaseCodeGen e () -> BaseCodeGen e ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
(Arg -> BaseCodeGen e ()) -> [Arg] -> BaseCodeGen e ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\Arg
a -> Text -> BaseCodeGen e ()
Text -> CodeGen ()
line (Text -> BaseCodeGen e ())
-> BaseCodeGen e Text -> BaseCodeGen e ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Arg -> BaseCodeGen e Text
forall e.
Arg
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
fArgStr Arg
a) (Callable -> [Arg]
args Callable
callable)
Bool -> BaseCodeGen e () -> BaseCodeGen e ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Callable -> Bool
callableThrows Callable
callable) (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
padTo Int
40 Text
"Ptr (Ptr GError) -> " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"-- error"
Text -> BaseCodeGen e ()
Text -> CodeGen ()
line (Text -> BaseCodeGen e ())
-> BaseCodeGen e Text -> BaseCodeGen e ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BaseCodeGen e Text
CodeGen Text
last
Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
hSymbol
where
hSymbol :: Text
hSymbol = if (Char -> Bool) -> Text -> Bool
T.any (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_') Text
cSymbol
then Text -> Text
lcFirst Text
cSymbol
else Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cSymbol
first :: Text
first = Text
"foreign import ccall \"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cSymbol Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
hSymbol Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" :: "
fArgStr :: Arg
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
fArgStr Arg
arg = do
TypeRep
ft <- Type -> CodeGen TypeRep
foreignType (Type -> CodeGen TypeRep) -> Type -> CodeGen TypeRep
forall a b. (a -> b) -> a -> b
$ Arg -> Type
argType Arg
arg
let ft' :: TypeRep
ft' = if Arg -> Direction
direction Arg
arg Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
DirectionIn Bool -> Bool -> Bool
|| Arg -> Bool
argCallerAllocates Arg
arg
then TypeRep
ft
else TypeRep -> TypeRep
ptr TypeRep
ft
let start :: Text
start = TypeRep -> Text
typeShow TypeRep
ft' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> "
Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
padTo Int
40 Text
start Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"-- " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Arg -> Text
argCName Arg
arg)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" : " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Type -> Text
forall a. Show a => a -> Text
tshow (Arg -> Type
argType Arg
arg)
last :: ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
last = TypeRep -> Text
typeShow (TypeRep -> Text) -> (TypeRep -> TypeRep) -> TypeRep -> Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypeRep -> TypeRep
io (TypeRep -> Text)
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) TypeRep
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> case Callable -> Maybe Type
returnType Callable
callable of
Maybe Type
Nothing -> TypeRep
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) TypeRep
forall (m :: * -> *) a. Monad m => a -> m a
return (TypeRep
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) TypeRep)
-> TypeRep
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) TypeRep
forall a b. (a -> b) -> a -> b
$ Text -> TypeRep
con0 Text
"()"
Just Type
r -> Type -> CodeGen TypeRep
foreignType Type
r
mkDynamicImport :: Text -> CodeGen Text
mkDynamicImport :: Text -> CodeGen Text
mkDynamicImport Text
typeSynonym = do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"foreign import ccall \"dynamic\" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
dynamic Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" :: FunPtr "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
typeSynonym Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
typeSynonym
Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
dynamic
where dynamic :: Text
dynamic = Text
"__dynamic_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
typeSynonym
wrapMaybe :: Arg -> CodeGen Bool
wrapMaybe :: Arg -> CodeGen Bool
wrapMaybe Arg
arg = if Arg -> Bool
mayBeNull Arg
arg
then Type -> CodeGen Bool
typeIsNullable (Arg -> Type
argType Arg
arg)
else Bool -> BaseCodeGen e Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
inArgInterfaces :: [Arg] -> ExposeClosures -> ExcCodeGen ([Text], [Text])
inArgInterfaces :: [Arg] -> ExposeClosures -> ExcCodeGen ([Text], [Text])
inArgInterfaces [Arg]
args ExposeClosures
expose = do
BaseCodeGen CGError ()
CodeGen ()
resetTypeVariableScope
[Arg] -> ExcCodeGen ([Text], [Text])
forall e.
[Arg]
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
([Text], [Text])
go [Arg]
args
where go :: [Arg]
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
([Text], [Text])
go [] = ([Text], [Text])
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
([Text], [Text])
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [])
go (Arg
arg:[Arg]
args) = do
(Text
t, [Text]
cons) <- Type -> ExposeClosures -> CodeGen (Text, [Text])
argumentType (Arg -> Type
argType Arg
arg) ExposeClosures
expose
Text
t' <- Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen e Bool
-> (Bool
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
-> Bool
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a. a -> a -> Bool -> a
bool (Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
t)
(Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text)
-> Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
forall a b. (a -> b) -> a -> b
$ Text
"Maybe (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
([Text]
restCons, [Text]
restTypes) <- [Arg]
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
([Text], [Text])
go [Arg]
args
([Text], [Text])
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
([Text], [Text])
forall (m :: * -> *) a. Monad m => a -> m a
return ([Text]
cons [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [Text]
restCons, Text
t' Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
restTypes)
arrayLengthsMap :: Callable -> [(Arg, Arg)]
arrayLengthsMap :: Callable -> [(Arg, Arg)]
arrayLengthsMap Callable
callable = [Arg] -> [(Arg, Arg)] -> [(Arg, Arg)]
go (Callable -> [Arg]
args Callable
callable) []
where
go :: [Arg] -> [(Arg, Arg)] -> [(Arg, Arg)]
go :: [Arg] -> [(Arg, Arg)] -> [(Arg, Arg)]
go [] [(Arg, Arg)]
acc = [(Arg, Arg)]
acc
go (Arg
a:[Arg]
as) [(Arg, Arg)]
acc = case Arg -> Type
argType Arg
a of
TCArray Bool
False Int
fixedSize Int
length Type
_ ->
if Int
fixedSize Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> -Int
1 Bool -> Bool -> Bool
|| Int
length Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== -Int
1
then [Arg] -> [(Arg, Arg)] -> [(Arg, Arg)]
go [Arg]
as [(Arg, Arg)]
acc
else [Arg] -> [(Arg, Arg)] -> [(Arg, Arg)]
go [Arg]
as ([(Arg, Arg)] -> [(Arg, Arg)]) -> [(Arg, Arg)] -> [(Arg, Arg)]
forall a b. (a -> b) -> a -> b
$ (Arg
a, (Callable -> [Arg]
args Callable
callable)[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!Int
length) (Arg, Arg) -> [(Arg, Arg)] -> [(Arg, Arg)]
forall a. a -> [a] -> [a]
: [(Arg, Arg)]
acc
Type
_ -> [Arg] -> [(Arg, Arg)] -> [(Arg, Arg)]
go [Arg]
as [(Arg, Arg)]
acc
arrayLengths :: Callable -> [Arg]
arrayLengths :: Callable -> [Arg]
arrayLengths Callable
callable = ((Arg, Arg) -> Arg) -> [(Arg, Arg)] -> [Arg]
forall a b. (a -> b) -> [a] -> [b]
map (Arg, Arg) -> Arg
forall a b. (a, b) -> b
snd (Callable -> [(Arg, Arg)]
arrayLengthsMap Callable
callable) [Arg] -> [Arg] -> [Arg]
forall a. Semigroup a => a -> a -> a
<>
case Callable -> Maybe Type
returnType Callable
callable of
Just (TCArray Bool
False (-1) Int
length Type
_) ->
if Int
length Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> -Int
1
then [(Callable -> [Arg]
args Callable
callable)[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!Int
length]
else []
Maybe Type
_ -> []
classifyDuplicates :: Ord b => [(a, b)] -> [(a, b, Maybe a)]
classifyDuplicates :: [(a, b)] -> [(a, b, Maybe a)]
classifyDuplicates [(a, b)]
args = Map b a -> [(a, b)] -> [(a, b, Maybe a)]
forall b a. Ord b => Map b a -> [(a, b)] -> [(a, b, Maybe a)]
doClassify Map b a
forall k a. Map k a
Map.empty [(a, b)]
args
where doClassify :: Ord b => Map.Map b a -> [(a, b)] -> [(a, b, Maybe a)]
doClassify :: Map b a -> [(a, b)] -> [(a, b, Maybe a)]
doClassify Map b a
_ [] = []
doClassify Map b a
found ((a
value, b
key):[(a, b)]
args) =
(a
value, b
key, b -> Map b a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup b
key Map b a
found) (a, b, Maybe a) -> [(a, b, Maybe a)] -> [(a, b, Maybe a)]
forall a. a -> [a] -> [a]
:
Map b a -> [(a, b)] -> [(a, b, Maybe a)]
forall b a. Ord b => Map b a -> [(a, b)] -> [(a, b, Maybe a)]
doClassify (b -> a -> Map b a -> Map b a
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert b
key a
value Map b a
found) [(a, b)]
args
readInArrayLengths :: Name -> Callable -> [Arg] -> ExcCodeGen ()
readInArrayLengths :: Name -> Callable -> [Arg] -> BaseCodeGen CGError ()
readInArrayLengths Name
name Callable
callable [Arg]
hInArgs = do
let lengthMaps :: [(Arg, Arg, Maybe Arg)]
lengthMaps = [(Arg, Arg)] -> [(Arg, Arg, Maybe Arg)]
forall b a. Ord b => [(a, b)] -> [(a, b, Maybe a)]
classifyDuplicates ([(Arg, Arg)] -> [(Arg, Arg, Maybe Arg)])
-> [(Arg, Arg)] -> [(Arg, Arg, Maybe Arg)]
forall a b. (a -> b) -> a -> b
$ Callable -> [(Arg, Arg)]
arrayLengthsMap Callable
callable
[(Arg, Arg, Maybe Arg)]
-> ((Arg, Arg, Maybe Arg) -> BaseCodeGen CGError ())
-> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(Arg, Arg, Maybe Arg)]
lengthMaps (((Arg, Arg, Maybe Arg) -> BaseCodeGen CGError ())
-> BaseCodeGen CGError ())
-> ((Arg, Arg, Maybe Arg) -> BaseCodeGen CGError ())
-> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ \(Arg
array, Arg
length, Maybe Arg
duplicate) ->
Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Arg
array Arg -> [Arg] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Arg]
hInArgs) (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$
case Maybe Arg
duplicate of
Maybe Arg
Nothing -> Arg -> Arg -> BaseCodeGen CGError ()
readInArrayLength Arg
array Arg
length
Just Arg
previous -> Name -> Arg -> Arg -> Arg -> BaseCodeGen CGError ()
checkInArrayLength Name
name Arg
array Arg
length Arg
previous
readInArrayLength :: Arg -> Arg -> ExcCodeGen ()
readInArrayLength :: Arg -> Arg -> BaseCodeGen CGError ()
readInArrayLength Arg
array Arg
length = do
let lvar :: Text
lvar = Arg -> Text
escapedArgName Arg
length
avar :: Text
avar = Arg -> Text
escapedArgName Arg
array
Arg -> CodeGen Bool
wrapMaybe Arg
array BaseCodeGen CGError Bool
-> (Bool -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BaseCodeGen CGError ()
-> BaseCodeGen CGError () -> Bool -> BaseCodeGen CGError ()
forall a. a -> a -> Bool -> a
bool
(do
Text
al <- Text -> Type -> ExcCodeGen Text
computeArrayLength Text
avar (Arg -> Type
argType Arg
array)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
lvar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
al)
(do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
lvar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = case " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
avar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" of"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Nothing -> 0"
let jarray :: Text
jarray = Text
"j" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
avar
Text
al <- Text -> Type -> ExcCodeGen Text
computeArrayLength Text
jarray (Arg -> Type
argType Arg
array)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Just " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
jarray Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
al)
checkInArrayLength :: Name -> Arg -> Arg -> Arg -> ExcCodeGen ()
checkInArrayLength :: Name -> Arg -> Arg -> Arg -> BaseCodeGen CGError ()
checkInArrayLength Name
n Arg
array Arg
length Arg
previous = do
let name :: Text
name = Name -> Text
lowerName Name
n
funcName :: Text
funcName = Name -> Text
namespace Name
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name
lvar :: Text
lvar = Arg -> Text
escapedArgName Arg
length
avar :: Text
avar = Arg -> Text
escapedArgName Arg
array
expectedLength :: Text
expectedLength = Text
avar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_expected_length_"
pvar :: Text
pvar = Arg -> Text
escapedArgName Arg
previous
Arg -> CodeGen Bool
wrapMaybe Arg
array BaseCodeGen CGError Bool
-> (Bool -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BaseCodeGen CGError ()
-> BaseCodeGen CGError () -> Bool -> BaseCodeGen CGError ()
forall a. a -> a -> Bool -> a
bool
(do
Text
al <- Text -> Type -> ExcCodeGen Text
computeArrayLength Text
avar (Arg -> Type
argType Arg
array)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
expectedLength Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
al)
(do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
expectedLength Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = case " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
avar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" of"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Nothing -> 0"
let jarray :: Text
jarray = Text
"j" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
avar
Text
al <- Text -> Type -> ExcCodeGen Text
computeArrayLength Text
jarray (Arg -> Type
argType Arg
array)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Just " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
jarray Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
al)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"when (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
expectedLength Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" /= " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
lvar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") $"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"error \"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
funcName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" : length of '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
avar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
"' does not agree with that of '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pvar Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"'.\""
skipRetVal :: Callable -> Bool
skipRetVal :: Callable -> Bool
skipRetVal Callable
callable = (Callable -> Bool
skipReturn Callable
callable) Bool -> Bool -> Bool
||
(Callable -> Bool
callableThrows Callable
callable Bool -> Bool -> Bool
&&
Callable -> Maybe Type
returnType Callable
callable Maybe Type -> Maybe Type -> Bool
forall a. Eq a => a -> a -> Bool
== Type -> Maybe Type
forall a. a -> Maybe a
Just (BasicType -> Type
TBasicType BasicType
TBoolean))
freeInArgs' :: (Arg -> Text -> Text -> ExcCodeGen [Text]) ->
Callable -> Map.Map Text Text -> ExcCodeGen [Text]
freeInArgs' :: (Arg -> Text -> Text -> ExcCodeGen [Text])
-> Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgs' Arg -> Text -> Text -> ExcCodeGen [Text]
freeFn Callable
callable Map Text Text
nameMap = [[Text]] -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Text]] -> [Text])
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[[Text]]
-> ExcCodeGen [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[[Text]]
actions
where
actions :: ExcCodeGen [[Text]]
actions :: ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[[Text]]
actions = [Arg]
-> (Arg -> ExcCodeGen [Text])
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[[Text]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (Callable -> [Arg]
args Callable
callable) ((Arg -> ExcCodeGen [Text])
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[[Text]])
-> (Arg -> ExcCodeGen [Text])
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
[[Text]]
forall a b. (a -> b) -> a -> b
$ \Arg
arg ->
case Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Arg -> Text
escapedArgName Arg
arg) Map Text Text
nameMap of
Just Text
name -> Arg -> Text -> Text -> ExcCodeGen [Text]
freeFn Arg
arg Text
name (Text -> ExcCodeGen [Text]) -> Text -> ExcCodeGen [Text]
forall a b. (a -> b) -> a -> b
$
case Arg -> Type
argType Arg
arg of
TCArray Bool
False (-1) (-1) Type
_ ->
Text -> Text
parenthesize (Text
"length " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Arg -> Text
escapedArgName Arg
arg)
TCArray Bool
False (-1) Int
length Type
_ ->
Arg -> Text
escapedArgName (Arg -> Text) -> Arg -> Text
forall a b. (a -> b) -> a -> b
$ (Callable -> [Arg]
args Callable
callable)[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!Int
length
Type
_ -> Text
forall a. HasCallStack => a
undefined
Maybe Text
Nothing -> Text -> ExcCodeGen [Text]
forall a. Text -> ExcCodeGen a
badIntroError (Text -> ExcCodeGen [Text]) -> Text -> ExcCodeGen [Text]
forall a b. (a -> b) -> a -> b
$ Text
"freeInArgs: do not understand " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Arg -> Text
forall a. Show a => a -> Text
tshow Arg
arg
freeInArgs :: Callable -> Map.Map Text Text -> ExcCodeGen [Text]
freeInArgs :: Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgs = (Arg -> Text -> Text -> ExcCodeGen [Text])
-> Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgs' Arg -> Text -> Text -> ExcCodeGen [Text]
freeInArg
freeInArgsOnError :: Callable -> Map.Map Text Text -> ExcCodeGen [Text]
freeInArgsOnError :: Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgsOnError = (Arg -> Text -> Text -> ExcCodeGen [Text])
-> Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgs' Arg -> Text -> Text -> ExcCodeGen [Text]
freeInArgOnError
prepareArgForCall :: [Arg] -> Arg -> ExposeClosures -> ExcCodeGen Text
prepareArgForCall :: [Arg] -> Arg -> ExposeClosures -> ExcCodeGen Text
prepareArgForCall [Arg]
omitted Arg
arg ExposeClosures
expose = do
Maybe Callback
callback <- HasCallStack => Type -> CodeGen (Maybe API)
Type -> CodeGen (Maybe API)
findAPI (Arg -> Type
argType Arg
arg) BaseCodeGen CGError (Maybe API)
-> (Maybe API
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
(Maybe Callback))
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
(Maybe Callback)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
\case Just (APICallback Callback
c) -> Maybe Callback
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
(Maybe Callback)
forall (m :: * -> *) a. Monad m => a -> m a
return (Callback -> Maybe Callback
forall a. a -> Maybe a
Just Callback
c)
Maybe API
_ -> Maybe Callback
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except CGError))
(Maybe Callback)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Callback
forall a. Maybe a
Nothing
Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Callback -> Bool
forall a. Maybe a -> Bool
isJust Maybe Callback
callback Bool -> Bool -> Bool
&& Arg -> Direction
direction Arg
arg Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
/= Direction
DirectionIn) (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$
Text -> BaseCodeGen CGError ()
forall a. Text -> ExcCodeGen a
notImplementedError Text
"Only callbacks with DirectionIn are supported"
case Arg -> Direction
direction Arg
arg of
Direction
DirectionIn -> if Arg
arg Arg -> [Arg] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Arg]
omitted
then Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ExcCodeGen Text)
-> (Arg -> Text) -> Arg -> ExcCodeGen Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arg -> Text
escapedArgName (Arg -> ExcCodeGen Text) -> Arg -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Arg
arg
else case Maybe Callback
callback of
Just Callback
c -> if Callable -> Bool
callableThrows (Callback -> Callable
cbCallable Callback
c)
then Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Arg -> Text
escapedArgName Arg
arg)
else Arg -> Callback -> ExposeClosures -> CodeGen Text
prepareInCallback Arg
arg Callback
c ExposeClosures
expose
Maybe Callback
Nothing -> Arg -> ExcCodeGen Text
prepareInArg Arg
arg
Direction
DirectionInout -> Arg -> ExcCodeGen Text
prepareInoutArg Arg
arg
Direction
DirectionOut -> Arg -> ExcCodeGen Text
prepareOutArg Arg
arg
prepareInArg :: Arg -> ExcCodeGen Text
prepareInArg :: Arg -> ExcCodeGen Text
prepareInArg Arg
arg = do
let name :: Text
name = Arg -> Text
escapedArgName Arg
arg
Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen CGError Bool
-> (Bool -> ExcCodeGen Text) -> ExcCodeGen Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ExcCodeGen Text -> ExcCodeGen Text -> Bool -> ExcCodeGen Text
forall a. a -> a -> Bool -> a
bool
(Text -> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall e. Text -> BaseCodeGen e Converter -> BaseCodeGen e Text
convert Text
name (BaseCodeGen CGError Converter -> ExcCodeGen Text)
-> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Type -> Transfer -> BaseCodeGen CGError Converter
hToF (Arg -> Type
argType Arg
arg) (Arg -> Transfer
transfer Arg
arg))
(do
let maybeName :: Text
maybeName = Text
"maybe" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
name
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
maybeName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- case " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" of"
ExcCodeGen Text -> ExcCodeGen Text
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (ExcCodeGen Text -> ExcCodeGen Text)
-> ExcCodeGen Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Nothing -> return nullPtr"
let jName :: Text
jName = Text
"j" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
name
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Just " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
jName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> do"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
Text
converted <- Text -> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall e. Text -> BaseCodeGen e Converter -> BaseCodeGen e Text
convert Text
jName (BaseCodeGen CGError Converter -> ExcCodeGen Text)
-> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Type -> Transfer -> BaseCodeGen CGError Converter
hToF (Arg -> Type
argType Arg
arg)
(Arg -> Transfer
transfer Arg
arg)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
converted
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
maybeName)
prepareInCallback :: Arg -> Callback -> ExposeClosures -> CodeGen Text
prepareInCallback :: Arg -> Callback -> ExposeClosures -> CodeGen Text
prepareInCallback Arg
arg callback :: Callback
callback@(Callback {cbCallable :: Callback -> Callable
cbCallable = Callable
cb}) ExposeClosures
expose = do
let name :: Text
name = Arg -> Text
escapedArgName Arg
arg
ptrName :: Text
ptrName = Text
"ptr" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name
scope :: Scope
scope = Arg -> Scope
argScope Arg
arg
(Text
maker, Text
wrapper, Maybe Text
drop) <-
case Arg -> Type
argType Arg
arg of
TInterface Name
tn ->
do
let Name Text
_ Text
n = API -> Name -> Name
normalizedAPIName (Callback -> API
APICallback Callback
callback) Name
tn
Maybe Text
drop <- if Callable -> Bool
callableHasClosures Callable
cb Bool -> Bool -> Bool
&& ExposeClosures
expose ExposeClosures -> ExposeClosures -> Bool
forall a. Eq a => a -> a -> Bool
== ExposeClosures
WithoutClosures
then Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text)
-> BaseCodeGen e Text
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
(Maybe Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Name -> CodeGen Text
qualifiedSymbol (Text -> Text
callbackDropClosures Text
n) Name
tn
else Maybe Text
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
(Maybe Text)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Text
forall a. Maybe a
Nothing
Text
wrapper <- Text -> Name -> CodeGen Text
qualifiedSymbol (Text -> Text
callbackHaskellToForeign Text
n) Name
tn
Text
maker <- Text -> Name -> CodeGen Text
qualifiedSymbol (Text -> Text
callbackWrapperAllocator Text
n) Name
tn
(Text, Text, Maybe Text)
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
(Text, Text, Maybe Text)
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
maker, Text
wrapper, Maybe Text
drop)
Type
_ -> Text
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
(Text, Text, Maybe Text)
forall a. HasCallStack => Text -> a
terror (Text
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
(Text, Text, Maybe Text))
-> Text
-> ReaderT
CodeGenConfig
(StateT (CGState, ModuleInfo) (Except e))
(Text, Text, Maybe Text)
forall a b. (a -> b) -> a -> b
$ Text
"prepareInCallback : Not an interface! " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Arg -> String
forall a. Show a => a -> String
ppShow Arg
arg)
Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen e Bool
-> (Bool -> BaseCodeGen e Text) -> BaseCodeGen e Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BaseCodeGen e Text
-> BaseCodeGen e Text -> Bool -> BaseCodeGen e Text
forall a. a -> a -> Bool -> a
bool
(do
let name' :: Text
name' = Text -> Text
prime Text
name
dropped :: Text
dropped =
case Maybe Text
drop of
Just Text
dropper -> Text -> Text
parenthesize (Text
dropper Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name)
Maybe Text
Nothing -> Text
name
Text
p <- if (Scope
scope Scope -> Scope -> Bool
forall a. Eq a => a -> a -> Bool
== Scope
ScopeTypeAsync)
then do Text
ft <- TypeRep -> Text
typeShow (TypeRep -> Text)
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) TypeRep
-> BaseCodeGen e Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Type -> CodeGen TypeRep
foreignType (Arg -> Type
argType Arg
arg)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
ptrName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- callocMem :: IO (Ptr (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ft Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"))"
Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> BaseCodeGen e Text) -> Text -> BaseCodeGen e Text
forall a b. (a -> b) -> a -> b
$ Text -> Text
parenthesize (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text
"Just " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ptrName
else Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"Nothing"
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
name' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
maker Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
parenthesize (Text
wrapper Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
dropped)
Bool -> BaseCodeGen e () -> BaseCodeGen e ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Scope
scope Scope -> Scope -> Bool
forall a. Eq a => a -> a -> Bool
== Scope
ScopeTypeAsync) (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"poke " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ptrName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name'
Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
name')
(do
let maybeName :: Text
maybeName = Text
"maybe" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
name
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
maybeName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- case " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" of"
BaseCodeGen e () -> BaseCodeGen e ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Nothing -> return (castPtrToFunPtr nullPtr)"
let jName :: Text
jName = Text
"j" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
name
jName' :: Text
jName' = Text -> Text
prime Text
jName
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"Just " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
jName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> do"
BaseCodeGen e () -> BaseCodeGen e ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
let dropped :: Text
dropped = case Maybe Text
drop of
Just Text
dropper ->
Text -> Text
parenthesize (Text
dropper Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
jName)
Maybe Text
Nothing -> Text
jName
Text
p <- if (Scope
scope Scope -> Scope -> Bool
forall a. Eq a => a -> a -> Bool
== Scope
ScopeTypeAsync)
then do Text
ft <- TypeRep -> Text
typeShow (TypeRep -> Text)
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) TypeRep
-> BaseCodeGen e Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Type -> CodeGen TypeRep
foreignType (Arg -> Type
argType Arg
arg)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
ptrName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- callocMem :: IO (Ptr (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ft Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"))"
Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> BaseCodeGen e Text) -> Text -> BaseCodeGen e Text
forall a b. (a -> b) -> a -> b
$ Text -> Text
parenthesize (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text
"Just " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ptrName
else Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"Nothing"
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
jName' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
maker Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
parenthesize (Text
wrapper Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
dropped)
Bool -> BaseCodeGen e () -> BaseCodeGen e ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Scope
scope Scope -> Scope -> Bool
forall a. Eq a => a -> a -> Bool
== Scope
ScopeTypeAsync) (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"poke " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ptrName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
jName'
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
jName'
Text -> BaseCodeGen e Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
maybeName)
prepareInoutArg :: Arg -> ExcCodeGen Text
prepareInoutArg :: Arg -> ExcCodeGen Text
prepareInoutArg Arg
arg = do
Text
name' <- Arg -> ExcCodeGen Text
prepareInArg Arg
arg
TypeRep
ft <- Type -> CodeGen TypeRep
foreignType (Type -> CodeGen TypeRep) -> Type -> CodeGen TypeRep
forall a b. (a -> b) -> a -> b
$ Arg -> Type
argType Arg
arg
Maybe TypeAllocInfo
allocInfo <- Type -> CodeGen (Maybe TypeAllocInfo)
typeAllocInfo (Arg -> Type
argType Arg
arg)
case Maybe TypeAllocInfo
allocInfo of
Just (TypeAlloc Text
allocator Int
n) -> do
Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen CGError Bool
-> (Bool -> ExcCodeGen Text) -> ExcCodeGen Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ExcCodeGen Text -> ExcCodeGen Text -> Bool -> ExcCodeGen Text
forall a. a -> a -> Bool -> a
bool
(do
Text
name'' <- Text -> Converter -> CodeGen Text
genConversion (Text -> Text
prime Text
name') (Converter -> CodeGen Text) -> Converter -> CodeGen Text
forall a b. (a -> b) -> a -> b
$
Constructor -> Converter
literal (Constructor -> Converter) -> Constructor -> Converter
forall a b. (a -> b) -> a -> b
$ Text -> Constructor
M (Text -> Constructor) -> Text -> Constructor
forall a b. (a -> b) -> a -> b
$ Text
allocator Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
" :: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TypeRep -> Text
typeShow (TypeRep -> TypeRep
io TypeRep
ft)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"memcpy " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name'' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
n
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
name'')
(Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
notImplementedError Text
"Nullable inout structs not supported")
Maybe TypeAllocInfo
Nothing -> do
if Arg -> Bool
argCallerAllocates Arg
arg
then Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
name'
else do
Text
name'' <- Text -> Converter -> CodeGen Text
genConversion (Text -> Text
prime Text
name') (Converter -> CodeGen Text) -> Converter -> CodeGen Text
forall a b. (a -> b) -> a -> b
$
Constructor -> Converter
literal (Constructor -> Converter) -> Constructor -> Converter
forall a b. (a -> b) -> a -> b
$ Text -> Constructor
M (Text -> Constructor) -> Text -> Constructor
forall a b. (a -> b) -> a -> b
$ Text
"allocMem :: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TypeRep -> Text
typeShow (TypeRep -> TypeRep
io (TypeRep -> TypeRep) -> TypeRep -> TypeRep
forall a b. (a -> b) -> a -> b
$ TypeRep -> TypeRep
ptr TypeRep
ft)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"poke " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name'' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name'
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
name''
prepareOutArg :: Arg -> ExcCodeGen Text
prepareOutArg :: Arg -> ExcCodeGen Text
prepareOutArg Arg
arg = do
let name :: Text
name = Arg -> Text
escapedArgName Arg
arg
TypeRep
ft <- Type -> CodeGen TypeRep
foreignType (Type -> CodeGen TypeRep) -> Type -> CodeGen TypeRep
forall a b. (a -> b) -> a -> b
$ Arg -> Type
argType Arg
arg
if Arg -> Bool
argCallerAllocates Arg
arg
then do
Maybe TypeAllocInfo
allocInfo <- Type -> CodeGen (Maybe TypeAllocInfo)
typeAllocInfo (Arg -> Type
argType Arg
arg)
case Maybe TypeAllocInfo
allocInfo of
Just (TypeAlloc Text
allocator Int
_) -> do
Text -> Converter -> CodeGen Text
genConversion Text
name (Converter -> CodeGen Text) -> Converter -> CodeGen Text
forall a b. (a -> b) -> a -> b
$ Constructor -> Converter
literal (Constructor -> Converter) -> Constructor -> Converter
forall a b. (a -> b) -> a -> b
$ Text -> Constructor
M (Text -> Constructor) -> Text -> Constructor
forall a b. (a -> b) -> a -> b
$ Text
allocator Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
" :: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TypeRep -> Text
typeShow (TypeRep -> TypeRep
io TypeRep
ft)
Maybe TypeAllocInfo
Nothing ->
Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
notImplementedError (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ (Text
"Don't know how to allocate \""
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Arg -> Text
argCName Arg
arg Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\" of type "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Type -> Text
forall a. Show a => a -> Text
tshow (Arg -> Type
argType Arg
arg))
else do
Bool
isPtr <- Type -> CodeGen Bool
typeIsPtr (Arg -> Type
argType Arg
arg)
let alloc :: Text
alloc = if Bool
isPtr
then Text
"callocMem"
else Text
"allocMem"
Text -> Converter -> CodeGen Text
genConversion Text
name (Converter -> CodeGen Text) -> Converter -> CodeGen Text
forall a b. (a -> b) -> a -> b
$ Constructor -> Converter
literal (Constructor -> Converter) -> Constructor -> Converter
forall a b. (a -> b) -> a -> b
$ Text -> Constructor
M (Text -> Constructor) -> Text -> Constructor
forall a b. (a -> b) -> a -> b
$ Text
alloc Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" :: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TypeRep -> Text
typeShow (TypeRep -> TypeRep
io (TypeRep -> TypeRep) -> TypeRep -> TypeRep
forall a b. (a -> b) -> a -> b
$ TypeRep -> TypeRep
ptr TypeRep
ft)
convertOutCArray :: Callable -> Type -> Text -> Map.Map Text Text ->
Transfer -> (Text -> Text) -> ExcCodeGen Text
convertOutCArray :: Callable
-> Type
-> Text
-> Map Text Text
-> Transfer
-> (Text -> Text)
-> ExcCodeGen Text
convertOutCArray Callable
callable t :: Type
t@(TCArray Bool
False Int
fixed Int
length Type
_) Text
aname
Map Text Text
nameMap Transfer
transfer Text -> Text
primeLength = do
if Int
fixed Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> -Int
1
then do
Text
unpacked <- Text -> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall e. Text -> BaseCodeGen e Converter -> BaseCodeGen e Text
convert Text
aname (BaseCodeGen CGError Converter -> ExcCodeGen Text)
-> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text -> Type -> Transfer -> BaseCodeGen CGError Converter
unpackCArray (Int -> Text
forall a. Show a => a -> Text
tshow Int
fixed) Type
t Transfer
transfer
Transfer -> Type -> Text -> Text -> BaseCodeGen CGError ()
freeContainerType Transfer
transfer Type
t Text
aname Text
forall a. HasCallStack => a
undefined
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
unpacked
else do
Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
length Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== -Int
1) (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$
Text -> BaseCodeGen CGError ()
forall a. Text -> ExcCodeGen a
badIntroError (Text -> BaseCodeGen CGError ()) -> Text -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ Text
"Unknown length for \"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
aname Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\""
let lname :: Text
lname = Arg -> Text
escapedArgName (Arg -> Text) -> Arg -> Text
forall a b. (a -> b) -> a -> b
$ (Callable -> [Arg]
args Callable
callable)[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!Int
length
Text
lname' <- case Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
lname Map Text Text
nameMap of
Just Text
n -> Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
n
Maybe Text
Nothing ->
Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
badIntroError (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"Couldn't find out array length " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
lname
let lname'' :: Text
lname'' = Text -> Text
primeLength Text
lname'
Text
unpacked <- Text -> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall e. Text -> BaseCodeGen e Converter -> BaseCodeGen e Text
convert Text
aname (BaseCodeGen CGError Converter -> ExcCodeGen Text)
-> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text -> Type -> Transfer -> BaseCodeGen CGError Converter
unpackCArray Text
lname'' Type
t Transfer
transfer
Transfer -> Type -> Text -> Text -> BaseCodeGen CGError ()
freeContainerType Transfer
transfer Type
t Text
aname Text
lname''
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
unpacked
convertOutCArray Callable
_ Type
t Text
_ Map Text Text
_ Transfer
_ Text -> Text
_ =
Text -> ExcCodeGen Text
forall a. HasCallStack => Text -> a
terror (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"convertOutCArray : unexpected " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Type -> Text
forall a. Show a => a -> Text
tshow Type
t
readOutArrayLengths :: Callable -> Map.Map Text Text -> ExcCodeGen ()
readOutArrayLengths :: Callable -> Map Text Text -> BaseCodeGen CGError ()
readOutArrayLengths Callable
callable Map Text Text
nameMap = do
let lNames :: [Text]
lNames = [Text] -> [Text]
forall a. Eq a => [a] -> [a]
nub ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Arg -> Text) -> [Arg] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Text
escapedArgName ([Arg] -> [Text]) -> [Arg] -> [Text]
forall a b. (a -> b) -> a -> b
$
(Arg -> Bool) -> [Arg] -> [Arg]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
/= Direction
DirectionIn) (Direction -> Bool) -> (Arg -> Direction) -> Arg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arg -> Direction
direction) ([Arg] -> [Arg]) -> [Arg] -> [Arg]
forall a b. (a -> b) -> a -> b
$
Callable -> [Arg]
arrayLengths Callable
callable
[Text] -> (Text -> ExcCodeGen Text) -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Text]
lNames ((Text -> ExcCodeGen Text) -> BaseCodeGen CGError ())
-> (Text -> ExcCodeGen Text) -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ \Text
lname -> do
Text
lname' <- case Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
lname Map Text Text
nameMap of
Just Text
n -> Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
n
Maybe Text
Nothing ->
Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
badIntroError (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"Couldn't find out array length " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
lname
Text -> Converter -> CodeGen Text
genConversion Text
lname' (Converter -> CodeGen Text) -> Converter -> CodeGen Text
forall a b. (a -> b) -> a -> b
$ Constructor -> Converter
apply (Constructor -> Converter) -> Constructor -> Converter
forall a b. (a -> b) -> a -> b
$ Text -> Constructor
M Text
"peek"
touchInArg :: Arg -> ExcCodeGen ()
touchInArg :: Arg -> BaseCodeGen CGError ()
touchInArg Arg
arg = Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Arg -> Direction
direction Arg
arg Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
/= Direction
DirectionOut) (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
let name :: Text
name = Arg -> Text
escapedArgName Arg
arg
case Type -> Maybe Type
elementType (Arg -> Type
argType Arg
arg) of
Just Type
a -> do
Bool
managed <- Type -> CodeGen Bool
isManaged Type
a
Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
managed (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen CGError Bool
-> (Bool -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BaseCodeGen CGError ()
-> BaseCodeGen CGError () -> Bool -> BaseCodeGen CGError ()
forall a. a -> a -> Bool -> a
bool
(Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"mapM_ touchManagedPtr " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name)
(Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"whenJust " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" (mapM_ touchManagedPtr)")
Maybe Type
Nothing -> do
Bool
managed <- Type -> CodeGen Bool
isManaged (Arg -> Type
argType Arg
arg)
Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
managed (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen CGError Bool
-> (Bool -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BaseCodeGen CGError ()
-> BaseCodeGen CGError () -> Bool -> BaseCodeGen CGError ()
forall a. a -> a -> Bool -> a
bool
(Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"touchManagedPtr " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name)
(Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"whenJust " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" touchManagedPtr")
closureToCallbackMap :: Callable -> ExcCodeGen (Map.Map Int Arg)
closureToCallbackMap :: Callable -> ExcCodeGen (Map Int Arg)
closureToCallbackMap Callable
callable =
[Arg] -> Map Int Arg -> ExcCodeGen (Map Int Arg)
go ((Arg -> Bool) -> [Arg] -> [Arg]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Arg -> Bool) -> Arg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg -> [Arg] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Arg]
destroyers)) ([Arg] -> [Arg]) -> [Arg] -> [Arg]
forall a b. (a -> b) -> a -> b
$ Callable -> [Arg]
args Callable
callable) Map Int Arg
forall k a. Map k a
Map.empty
where destroyers :: [Arg]
destroyers = (Int -> Arg) -> [Int] -> [Arg]
forall a b. (a -> b) -> [a] -> [b]
map (Callable -> [Arg]
args Callable
callable[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!) ([Int] -> [Arg]) -> ([Arg] -> [Int]) -> [Arg] -> [Arg]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= -Int
1) ([Int] -> [Int]) -> ([Arg] -> [Int]) -> [Arg] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg -> Int) -> [Arg] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Int
argDestroy
([Arg] -> [Arg]) -> [Arg] -> [Arg]
forall a b. (a -> b) -> a -> b
$ Callable -> [Arg]
args Callable
callable
go :: [Arg] -> Map.Map Int Arg -> ExcCodeGen (Map.Map Int Arg)
go :: [Arg] -> Map Int Arg -> ExcCodeGen (Map Int Arg)
go [] Map Int Arg
m = Map Int Arg -> ExcCodeGen (Map Int Arg)
forall (m :: * -> *) a. Monad m => a -> m a
return Map Int Arg
m
go (Arg
arg:[Arg]
as) Map Int Arg
m =
if Arg -> Scope
argScope Arg
arg Scope -> Scope -> Bool
forall a. Eq a => a -> a -> Bool
== Scope
ScopeTypeInvalid
then [Arg] -> Map Int Arg -> ExcCodeGen (Map Int Arg)
go [Arg]
as Map Int Arg
m
else case Arg -> Int
argClosure Arg
arg of
(-1) -> [Arg] -> Map Int Arg -> ExcCodeGen (Map Int Arg)
go [Arg]
as Map Int Arg
m
Int
c -> case Int -> Map Int Arg -> Maybe Arg
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Int
c Map Int Arg
m of
Just Arg
_ -> Text -> ExcCodeGen (Map Int Arg)
forall a. Text -> ExcCodeGen a
notImplementedError (Text -> ExcCodeGen (Map Int Arg))
-> Text -> ExcCodeGen (Map Int Arg)
forall a b. (a -> b) -> a -> b
$
Text
"Closure for multiple callbacks unsupported"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Arg -> String
forall a. Show a => a -> String
ppShow Arg
arg) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Callable -> String
forall a. Show a => a -> String
ppShow Callable
callable)
Maybe Arg
Nothing -> [Arg] -> Map Int Arg -> ExcCodeGen (Map Int Arg)
go [Arg]
as (Map Int Arg -> ExcCodeGen (Map Int Arg))
-> Map Int Arg -> ExcCodeGen (Map Int Arg)
forall a b. (a -> b) -> a -> b
$ Int -> Arg -> Map Int Arg -> Map Int Arg
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Int
c Arg
arg Map Int Arg
m
prepareClosures :: Callable -> Map.Map Text Text -> ExcCodeGen ()
prepareClosures :: Callable -> Map Text Text -> BaseCodeGen CGError ()
prepareClosures Callable
callable Map Text Text
nameMap = do
Map Int Arg
m <- Callable -> ExcCodeGen (Map Int Arg)
closureToCallbackMap Callable
callable
let closures :: [Int]
closures = (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= -Int
1) ([Int] -> [Int]) -> ([Arg] -> [Int]) -> [Arg] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg -> Int) -> [Arg] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Int
argClosure ([Arg] -> [Int]) -> [Arg] -> [Int]
forall a b. (a -> b) -> a -> b
$ Callable -> [Arg]
args Callable
callable
[Int] -> (Int -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int]
closures ((Int -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ())
-> (Int -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ \Int
closure ->
case Int -> Map Int Arg -> Maybe Arg
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Int
closure Map Int Arg
m of
Maybe Arg
Nothing -> Text -> BaseCodeGen CGError ()
forall a. Text -> ExcCodeGen a
badIntroError (Text -> BaseCodeGen CGError ()) -> Text -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ Text
"Closure not found! "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Callable -> String
forall a. Show a => a -> String
ppShow Callable
callable)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Map Int Arg -> String
forall a. Show a => a -> String
ppShow Map Int Arg
m)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
closure
Just Arg
cb -> do
let closureName :: Text
closureName = Arg -> Text
escapedArgName (Arg -> Text) -> Arg -> Text
forall a b. (a -> b) -> a -> b
$ (Callable -> [Arg]
args Callable
callable)[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!Int
closure
n :: Text
n = Arg -> Text
escapedArgName Arg
cb
Text
n' <- case Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
n Map Text Text
nameMap of
Just Text
n -> Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
n
Maybe Text
Nothing -> Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
badIntroError (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"Cannot find closure name!! "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Callable -> String
forall a. Show a => a -> String
ppShow Callable
callable) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Map Text Text -> String
forall a. Show a => a -> String
ppShow Map Text Text
nameMap)
Maybe API
maybeAPI <- HasCallStack => Type -> CodeGen (Maybe API)
Type -> CodeGen (Maybe API)
findAPI (Arg -> Type
argType Arg
cb)
case Maybe API
maybeAPI of
Just (APICallback Callback
_) -> do
case Arg -> Scope
argScope Arg
cb of
Scope
ScopeTypeInvalid -> Text -> BaseCodeGen CGError ()
forall a. Text -> ExcCodeGen a
badIntroError (Text -> BaseCodeGen CGError ()) -> Text -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ Text
"Invalid scope! "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Callable -> String
forall a. Show a => a -> String
ppShow Callable
callable)
Scope
ScopeTypeNotified -> do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
closureName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = castFunPtrToPtr " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n'
case Arg -> Int
argDestroy Arg
cb of
(-1) -> Text -> BaseCodeGen CGError ()
forall a. Text -> ExcCodeGen a
badIntroError (Text -> BaseCodeGen CGError ()) -> Text -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$
Text
"ScopeTypeNotified without destructor! "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Callable -> String
forall a. Show a => a -> String
ppShow Callable
callable)
Int
k -> let destroyName :: Text
destroyName =
Arg -> Text
escapedArgName (Arg -> Text) -> Arg -> Text
forall a b. (a -> b) -> a -> b
$ (Callable -> [Arg]
args Callable
callable)[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!Int
k in
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
destroyName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = safeFreeFunPtrPtr"
Scope
ScopeTypeAsync ->
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
closureName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = nullPtr"
Scope
ScopeTypeCall -> Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"let " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
closureName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = nullPtr"
Maybe API
_ -> Text -> BaseCodeGen CGError ()
forall a. Text -> ExcCodeGen a
badIntroError (Text -> BaseCodeGen CGError ()) -> Text -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ Text
"Closure \"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\" is not a callback."
freeCallCallbacks :: Callable -> Map.Map Text Text -> ExcCodeGen ()
freeCallCallbacks :: Callable -> Map Text Text -> BaseCodeGen CGError ()
freeCallCallbacks Callable
callable Map Text Text
nameMap =
[Arg] -> (Arg -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Callable -> [Arg]
args Callable
callable) ((Arg -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ())
-> (Arg -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ \Arg
arg -> do
let name :: Text
name = Arg -> Text
escapedArgName Arg
arg
Text
name' <- case Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
name Map Text Text
nameMap of
Just Text
n -> Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
n
Maybe Text
Nothing -> Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
badIntroError (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"Could not find " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" in " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Callable -> String
forall a. Show a => a -> String
ppShow Callable
callable) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Map Text Text -> String
forall a. Show a => a -> String
ppShow Map Text Text
nameMap)
Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Arg -> Scope
argScope Arg
arg Scope -> Scope -> Bool
forall a. Eq a => a -> a -> Bool
== Scope
ScopeTypeCall) (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"safeFreeFunPtr $ castFunPtrToPtr " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name'
formatHSignature :: Callable -> ForeignSymbol -> ExposeClosures -> ExcCodeGen ()
formatHSignature :: Callable
-> ForeignSymbol -> ExposeClosures -> BaseCodeGen CGError ()
formatHSignature Callable
callable ForeignSymbol
symbol ExposeClosures
expose = do
Signature
sig <- Callable -> ForeignSymbol -> ExposeClosures -> ExcCodeGen Signature
callableSignature Callable
callable ForeignSymbol
symbol ExposeClosures
expose
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
let constraints :: [Text]
constraints = Text
"B.CallStack.HasCallStack" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Signature -> [Text]
signatureConstraints Signature
sig
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " [Text]
constraints Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") =>"
[(Text, (Maybe Arg, Text))]
-> ((Text, (Maybe Arg, Text)) -> BaseCodeGen CGError ())
-> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Text] -> [(Maybe Arg, Text)] -> [(Text, (Maybe Arg, Text))]
forall a b. [a] -> [b] -> [(a, b)]
zip (Text
"" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Text -> [Text]
forall a. a -> [a]
repeat Text
"-> ") (Signature -> [(Maybe Arg, Text)]
signatureArgTypes Signature
sig)) (((Text, (Maybe Arg, Text)) -> BaseCodeGen CGError ())
-> BaseCodeGen CGError ())
-> ((Text, (Maybe Arg, Text)) -> BaseCodeGen CGError ())
-> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$
\(Text
prefix, (Maybe Arg
maybeArg, Text
t)) -> do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
prefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t
case Maybe Arg
maybeArg of
Maybe Arg
Nothing -> () -> BaseCodeGen CGError ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just Arg
arg -> Arg -> CodeGen ()
writeArgDocumentation Arg
arg
let resultPrefix :: Text
resultPrefix = if [(Maybe Arg, Text)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Signature -> [(Maybe Arg, Text)]
signatureArgTypes Signature
sig)
then Text
""
else Text
"-> "
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
resultPrefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Signature -> Text
signatureReturnType Signature
sig
Callable -> Bool -> CodeGen ()
writeReturnDocumentation (Signature -> Callable
signatureCallable Signature
sig) (Callable -> Bool
skipRetVal Callable
callable)
funPtr :: Text
funPtr :: Text
funPtr = Text
"__funPtr"
data Signature = Signature { Signature -> Callable
signatureCallable :: Callable
, Signature -> [Text]
signatureConstraints :: [Text]
, Signature -> [(Maybe Arg, Text)]
signatureArgTypes :: [(Maybe Arg, Text)]
, Signature -> Text
signatureReturnType :: Text
}
callableSignature :: Callable -> ForeignSymbol -> ExposeClosures
-> ExcCodeGen Signature
callableSignature :: Callable -> ForeignSymbol -> ExposeClosures -> ExcCodeGen Signature
callableSignature Callable
callable ForeignSymbol
symbol ExposeClosures
expose = do
let ([Arg]
hInArgs, [Arg]
_) = Callable -> ExposeClosures -> ([Arg], [Arg])
callableHInArgs Callable
callable
(case ForeignSymbol
symbol of
KnownForeignSymbol Text
_ -> ExposeClosures
WithoutClosures
DynamicForeignSymbol DynamicWrapper
_ -> ExposeClosures
WithClosures)
([Text]
argConstraints, [Text]
types) <- [Arg] -> ExposeClosures -> ExcCodeGen ([Text], [Text])
inArgInterfaces [Arg]
hInArgs ExposeClosures
expose
let constraints :: [Text]
constraints = (Text
"MonadIO m" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
argConstraints)
TypeRep
outType <- Callable -> [Arg] -> ExcCodeGen TypeRep
hOutType Callable
callable (Callable -> [Arg]
callableHOutArgs Callable
callable)
Signature -> ExcCodeGen Signature
forall (m :: * -> *) a. Monad m => a -> m a
return (Signature -> ExcCodeGen Signature)
-> Signature -> ExcCodeGen Signature
forall a b. (a -> b) -> a -> b
$ Signature :: Callable -> [Text] -> [(Maybe Arg, Text)] -> Text -> Signature
Signature {
signatureCallable :: Callable
signatureCallable = Callable
callable,
signatureConstraints :: [Text]
signatureConstraints = [Text]
constraints,
signatureReturnType :: Text
signatureReturnType = TypeRep -> Text
typeShow (Text
"m" Text -> [TypeRep] -> TypeRep
`con` [TypeRep
outType]),
signatureArgTypes :: [(Maybe Arg, Text)]
signatureArgTypes = case ForeignSymbol
symbol of
KnownForeignSymbol Text
_ -> [Maybe Arg] -> [Text] -> [(Maybe Arg, Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Arg -> Maybe Arg) -> [Arg] -> [Maybe Arg]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Maybe Arg
forall a. a -> Maybe a
Just [Arg]
hInArgs) [Text]
types
DynamicForeignSymbol DynamicWrapper
w -> [Maybe Arg] -> [Text] -> [(Maybe Arg, Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Maybe Arg
forall a. Maybe a
Nothing Maybe Arg -> [Maybe Arg] -> [Maybe Arg]
forall a. a -> [a] -> [a]
: (Arg -> Maybe Arg) -> [Arg] -> [Maybe Arg]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Maybe Arg
forall a. a -> Maybe a
Just [Arg]
hInArgs)
(Text
"FunPtr " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DynamicWrapper -> Text
dynamicType DynamicWrapper
w Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
types)
}
callableHInArgs :: Callable -> ExposeClosures -> ([Arg], [Arg])
callableHInArgs :: Callable -> ExposeClosures -> ([Arg], [Arg])
callableHInArgs Callable
callable ExposeClosures
expose =
let inArgs :: [Arg]
inArgs = (Arg -> Bool) -> [Arg] -> [Arg]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
/= Direction
DirectionOut) (Direction -> Bool) -> (Arg -> Direction) -> Arg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arg -> Direction
direction) ([Arg] -> [Arg]) -> [Arg] -> [Arg]
forall a b. (a -> b) -> a -> b
$ Callable -> [Arg]
args Callable
callable
closures :: [Arg]
closures = (Int -> Arg) -> [Int] -> [Arg]
forall a b. (a -> b) -> [a] -> [b]
map (Callable -> [Arg]
args Callable
callable[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!) ([Int] -> [Arg]) -> ([Arg] -> [Int]) -> [Arg] -> [Arg]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= -Int
1) ([Int] -> [Int]) -> ([Arg] -> [Int]) -> [Arg] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg -> Int) -> [Arg] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Int
argClosure ([Arg] -> [Arg]) -> [Arg] -> [Arg]
forall a b. (a -> b) -> a -> b
$ [Arg]
inArgs
destroyers :: [Arg]
destroyers = (Int -> Arg) -> [Int] -> [Arg]
forall a b. (a -> b) -> [a] -> [b]
map (Callable -> [Arg]
args Callable
callable[Arg] -> Int -> Arg
forall a. [a] -> Int -> a
!!) ([Int] -> [Arg]) -> ([Arg] -> [Int]) -> [Arg] -> [Arg]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= -Int
1) ([Int] -> [Int]) -> ([Arg] -> [Int]) -> [Arg] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg -> Int) -> [Arg] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Int
argDestroy ([Arg] -> [Arg]) -> [Arg] -> [Arg]
forall a b. (a -> b) -> a -> b
$ [Arg]
inArgs
omitted :: [Arg]
omitted = case ExposeClosures
expose of
ExposeClosures
WithoutClosures -> Callable -> [Arg]
arrayLengths Callable
callable [Arg] -> [Arg] -> [Arg]
forall a. Semigroup a => a -> a -> a
<> [Arg]
closures [Arg] -> [Arg] -> [Arg]
forall a. Semigroup a => a -> a -> a
<> [Arg]
destroyers
ExposeClosures
WithClosures -> Callable -> [Arg]
arrayLengths Callable
callable
in ((Arg -> Bool) -> [Arg] -> [Arg]
forall a. (a -> Bool) -> [a] -> [a]
filter (Arg -> [Arg] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Arg]
omitted) [Arg]
inArgs, [Arg]
omitted)
callableHOutArgs :: Callable -> [Arg]
callableHOutArgs :: Callable -> [Arg]
callableHOutArgs Callable
callable =
let outArgs :: [Arg]
outArgs = (Arg -> Bool) -> [Arg] -> [Arg]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
/= Direction
DirectionIn) (Direction -> Bool) -> (Arg -> Direction) -> Arg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arg -> Direction
direction) ([Arg] -> [Arg]) -> [Arg] -> [Arg]
forall a b. (a -> b) -> a -> b
$ Callable -> [Arg]
args Callable
callable
in (Arg -> Bool) -> [Arg] -> [Arg]
forall a. (a -> Bool) -> [a] -> [a]
filter (Arg -> [Arg] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` (Callable -> [Arg]
arrayLengths Callable
callable)) [Arg]
outArgs
convertResult :: Name -> Callable -> Map.Map Text Text ->
ExcCodeGen Text
convertResult :: Name -> Callable -> Map Text Text -> ExcCodeGen Text
convertResult Name
n Callable
callable Map Text Text
nameMap =
if Callable -> Bool
skipRetVal Callable
callable Bool -> Bool -> Bool
|| Callable -> Maybe Type
returnType Callable
callable Maybe Type -> Maybe Type -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Type
forall a. Maybe a
Nothing
then Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Text
forall a. HasCallStack => String -> a
error String
"convertResult: unreachable code reached, bug!")
else do
Bool
nullableReturnType <- BaseCodeGen CGError Bool
-> (Type -> BaseCodeGen CGError Bool)
-> Maybe Type
-> BaseCodeGen CGError Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Bool -> BaseCodeGen CGError Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False) Type -> BaseCodeGen CGError Bool
Type -> CodeGen Bool
typeIsNullable (Callable -> Maybe Type
returnType Callable
callable)
if Callable -> Bool
returnMayBeNull Callable
callable Bool -> Bool -> Bool
&& Bool
nullableReturnType
then do
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"maybeResult <- convertIfNonNull result $ \\result' -> do"
ExcCodeGen Text -> ExcCodeGen Text
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (ExcCodeGen Text -> ExcCodeGen Text)
-> ExcCodeGen Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ do
Text
converted <- Text -> ExcCodeGen Text
unwrappedConvertResult Text
"result'"
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
converted
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"maybeResult"
else do
Bool -> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
nullableReturnType (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"checkUnexpectedReturnNULL \"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Name -> Text
lowerName Name
n
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\" result"
Text -> ExcCodeGen Text
unwrappedConvertResult Text
"result"
where
unwrappedConvertResult :: Text -> ExcCodeGen Text
unwrappedConvertResult Text
rname =
case Callable -> Maybe Type
returnType Callable
callable of
Just (t :: Type
t@(TCArray Bool
False (-1) (-1) Type
_)) ->
Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
badIntroError (Text
"`" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Type -> Text
forall a. Show a => a -> Text
tshow Type
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
"' is an array type, but contains no length information,\n"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"so it cannot be unpacked.")
Just (t :: Type
t@(TCArray Bool
False Int
_ Int
_ Type
_)) ->
Callable
-> Type
-> Text
-> Map Text Text
-> Transfer
-> (Text -> Text)
-> ExcCodeGen Text
convertOutCArray Callable
callable Type
t Text
rname Map Text Text
nameMap
(Callable -> Transfer
returnTransfer Callable
callable) Text -> Text
prime
Just Type
t -> do
Text
result <- Text -> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall e. Text -> BaseCodeGen e Converter -> BaseCodeGen e Text
convert Text
rname (BaseCodeGen CGError Converter -> ExcCodeGen Text)
-> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Type -> Transfer -> BaseCodeGen CGError Converter
fToH Type
t (Callable -> Transfer
returnTransfer Callable
callable)
Transfer -> Type -> Text -> Text -> BaseCodeGen CGError ()
freeContainerType (Callable -> Transfer
returnTransfer Callable
callable) Type
t Text
rname Text
forall a. HasCallStack => a
undefined
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
result
Maybe Type
Nothing -> Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Text
forall a. HasCallStack => String -> a
error String
"unwrappedConvertResult: bug!")
convertOutArg :: Callable -> Map.Map Text Text -> Arg -> ExcCodeGen Text
convertOutArg :: Callable -> Map Text Text -> Arg -> ExcCodeGen Text
convertOutArg Callable
callable Map Text Text
nameMap Arg
arg = do
let name :: Text
name = Arg -> Text
escapedArgName Arg
arg
Text
inName <- case Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
name Map Text Text
nameMap of
Just Text
name' -> Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
name'
Maybe Text
Nothing -> Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
badIntroError (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"Parameter " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" not found!"
case Arg -> Type
argType Arg
arg of
t :: Type
t@(TCArray Bool
False (-1) (-1) Type
_) ->
if Arg -> Bool
argCallerAllocates Arg
arg
then Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
inName
else Text -> ExcCodeGen Text
forall a. Text -> ExcCodeGen a
badIntroError (Text
"`" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Type -> Text
forall a. Show a => a -> Text
tshow Type
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
"' is an array type, but contains no length information,\n"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"so it cannot be unpacked.")
t :: Type
t@(TCArray Bool
False Int
_ Int
_ Type
_) -> do
Text
aname' <- if Arg -> Bool
argCallerAllocates Arg
arg
then Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
inName
else Text -> Converter -> CodeGen Text
genConversion Text
inName (Converter -> CodeGen Text) -> Converter -> CodeGen Text
forall a b. (a -> b) -> a -> b
$ Constructor -> Converter
apply (Constructor -> Converter) -> Constructor -> Converter
forall a b. (a -> b) -> a -> b
$ Text -> Constructor
M Text
"peek"
let arrayLength :: Text -> Text
arrayLength = if Arg -> Bool
argCallerAllocates Arg
arg
then Text -> Text
forall a. a -> a
id
else Text -> Text
prime
wrapArray :: Text -> ExcCodeGen Text
wrapArray Text
a = Callable
-> Type
-> Text
-> Map Text Text
-> Transfer
-> (Text -> Text)
-> ExcCodeGen Text
convertOutCArray Callable
callable Type
t Text
a
Map Text Text
nameMap (Arg -> Transfer
transfer Arg
arg) Text -> Text
arrayLength
Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen CGError Bool
-> (Bool -> ExcCodeGen Text) -> ExcCodeGen Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ExcCodeGen Text -> ExcCodeGen Text -> Bool -> ExcCodeGen Text
forall a. a -> a -> Bool -> a
bool
(Text -> ExcCodeGen Text
wrapArray Text
aname')
(do Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"maybe" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
aname'
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- convertIfNonNull " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
aname'
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" $ \\" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
prime Text
aname' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> do"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
Text
wrapped <- Text -> ExcCodeGen Text
wrapArray (Text -> Text
prime Text
aname')
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
wrapped
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"maybe" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
aname')
Type
t -> do
Text
peeked <- if Arg -> Bool
argCallerAllocates Arg
arg
then Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
inName
else Text -> Converter -> CodeGen Text
genConversion Text
inName (Converter -> CodeGen Text) -> Converter -> CodeGen Text
forall a b. (a -> b) -> a -> b
$ Constructor -> Converter
apply (Constructor -> Converter) -> Constructor -> Converter
forall a b. (a -> b) -> a -> b
$ Text -> Constructor
M Text
"peek"
let transfer' :: Transfer
transfer' = if Arg -> Bool
argCallerAllocates Arg
arg
then Transfer
TransferEverything
else Arg -> Transfer
transfer Arg
arg
Text
result <- do
let wrap :: Text -> ExcCodeGen Text
wrap Text
ptr = Text -> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall e. Text -> BaseCodeGen e Converter -> BaseCodeGen e Text
convert Text
ptr (BaseCodeGen CGError Converter -> ExcCodeGen Text)
-> BaseCodeGen CGError Converter -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Type -> Transfer -> BaseCodeGen CGError Converter
fToH (Arg -> Type
argType Arg
arg) Transfer
transfer'
Arg -> CodeGen Bool
wrapMaybe Arg
arg BaseCodeGen CGError Bool
-> (Bool -> ExcCodeGen Text) -> ExcCodeGen Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ExcCodeGen Text -> ExcCodeGen Text -> Bool -> ExcCodeGen Text
forall a. a -> a -> Bool -> a
bool
(Text -> ExcCodeGen Text
wrap Text
peeked)
(do Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"maybe" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
peeked
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" <- convertIfNonNull " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
peeked
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" $ \\" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
prime Text
peeked Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" -> do"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
Text
wrapped <- Text -> ExcCodeGen Text
wrap (Text -> Text
prime Text
peeked)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
wrapped
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ExcCodeGen Text) -> Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ Text
"maybe" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucFirst Text
peeked)
Transfer -> Type -> Text -> Text -> BaseCodeGen CGError ()
freeContainerType Transfer
transfer' Type
t Text
peeked Text
forall a. HasCallStack => a
undefined
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
result
convertOutArgs :: Callable -> Map.Map Text Text -> [Arg] -> ExcCodeGen [Text]
convertOutArgs :: Callable -> Map Text Text -> [Arg] -> ExcCodeGen [Text]
convertOutArgs Callable
callable Map Text Text
nameMap [Arg]
hOutArgs =
[Arg] -> (Arg -> ExcCodeGen Text) -> ExcCodeGen [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Arg]
hOutArgs (Callable -> Map Text Text -> Arg -> ExcCodeGen Text
convertOutArg Callable
callable Map Text Text
nameMap)
invokeCFunction :: Callable -> ForeignSymbol -> [Text] -> CodeGen ()
invokeCFunction :: Callable -> ForeignSymbol -> [Text] -> CodeGen ()
invokeCFunction Callable
callable ForeignSymbol
symbol [Text]
argNames = do
let returnBind :: Text
returnBind = case Callable -> Maybe Type
returnType Callable
callable of
Maybe Type
Nothing -> Text
""
Maybe Type
_ -> if Callable -> Bool
skipRetVal Callable
callable
then Text
"_ <- "
else Text
"result <- "
maybeCatchGErrors :: Text
maybeCatchGErrors = if Callable -> Bool
callableThrows Callable
callable
then Text
"propagateGError $ "
else Text
""
call :: Text
call = case ForeignSymbol
symbol of
KnownForeignSymbol Text
s -> Text
s
DynamicForeignSymbol DynamicWrapper
w -> Text -> Text
parenthesize (DynamicWrapper -> Text
dynamicWrapper DynamicWrapper
w
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
funPtr)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
returnBind Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
maybeCatchGErrors
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
call Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ([Text] -> Text
T.concat ([Text] -> Text) -> ([Text] -> [Text]) -> [Text] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)) [Text]
argNames
returnResult :: Callable -> Text -> [Text] -> CodeGen ()
returnResult :: Callable -> Text -> [Text] -> CodeGen ()
returnResult Callable
callable Text
result [Text]
pps =
if Callable -> Bool
skipRetVal Callable
callable Bool -> Bool -> Bool
|| Callable -> Maybe Type
returnType Callable
callable Maybe Type -> Maybe Type -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Type
forall a. Maybe a
Nothing
then case [Text]
pps of
[] -> Text -> CodeGen ()
line Text
"return ()"
(Text
pp:[]) -> Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pp
[Text]
_ -> Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " [Text]
pps Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
else case [Text]
pps of
[] -> Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
result
[Text]
_ -> Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " (Text
result Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
pps) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
genHaskellWrapper :: Name -> ForeignSymbol -> Callable ->
ExposeClosures -> ExcCodeGen Text
genHaskellWrapper :: Name
-> ForeignSymbol -> Callable -> ExposeClosures -> ExcCodeGen Text
genHaskellWrapper Name
n ForeignSymbol
symbol Callable
callable ExposeClosures
expose = ExcCodeGen Text -> ExcCodeGen Text
forall e a. BaseCodeGen e a -> BaseCodeGen e a
group (ExcCodeGen Text -> ExcCodeGen Text)
-> ExcCodeGen Text -> ExcCodeGen Text
forall a b. (a -> b) -> a -> b
$ do
let name :: Text
name = case ForeignSymbol
symbol of
KnownForeignSymbol Text
_ -> Name -> Text
lowerName Name
n
DynamicForeignSymbol DynamicWrapper
_ -> Text -> Text
callbackDynamicWrapper (Name -> Text
upperName Name
n)
([Arg]
hInArgs, [Arg]
omitted) = Callable -> ExposeClosures -> ([Arg], [Arg])
callableHInArgs Callable
callable ExposeClosures
expose
hOutArgs :: [Arg]
hOutArgs = Callable -> [Arg]
callableHOutArgs Callable
callable
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ::"
Callable
-> ForeignSymbol -> ExposeClosures -> BaseCodeGen CGError ()
formatHSignature Callable
callable ForeignSymbol
symbol ExposeClosures
expose
let argNames :: [Text]
argNames = case ForeignSymbol
symbol of
KnownForeignSymbol Text
_ -> (Arg -> Text) -> [Arg] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Text
escapedArgName [Arg]
hInArgs
DynamicForeignSymbol DynamicWrapper
_ ->
Text
funPtr Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: (Arg -> Text) -> [Arg] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Text
escapedArgName [Arg]
hInArgs
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
" " [Text]
argNames Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" = liftIO $ do"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (Name
-> ForeignSymbol
-> Callable
-> [Arg]
-> [Arg]
-> [Arg]
-> ExposeClosures
-> BaseCodeGen CGError ()
genWrapperBody Name
n ForeignSymbol
symbol Callable
callable [Arg]
hInArgs [Arg]
hOutArgs [Arg]
omitted ExposeClosures
expose)
Text -> ExcCodeGen Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
name
genWrapperBody :: Name -> ForeignSymbol -> Callable ->
[Arg] -> [Arg] -> [Arg] ->
ExposeClosures ->
ExcCodeGen ()
genWrapperBody :: Name
-> ForeignSymbol
-> Callable
-> [Arg]
-> [Arg]
-> [Arg]
-> ExposeClosures
-> BaseCodeGen CGError ()
genWrapperBody Name
n ForeignSymbol
symbol Callable
callable [Arg]
hInArgs [Arg]
hOutArgs [Arg]
omitted ExposeClosures
expose = do
Name -> Callable -> [Arg] -> BaseCodeGen CGError ()
readInArrayLengths Name
n Callable
callable [Arg]
hInArgs
[Text]
inArgNames <- [Arg] -> (Arg -> ExcCodeGen Text) -> ExcCodeGen [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (Callable -> [Arg]
args Callable
callable) ((Arg -> ExcCodeGen Text) -> ExcCodeGen [Text])
-> (Arg -> ExcCodeGen Text) -> ExcCodeGen [Text]
forall a b. (a -> b) -> a -> b
$ \Arg
arg ->
[Arg] -> Arg -> ExposeClosures -> ExcCodeGen Text
prepareArgForCall [Arg]
omitted Arg
arg ExposeClosures
expose
let nameMap :: Map Text Text
nameMap = [(Text, Text)] -> Map Text Text
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(Text, Text)] -> Map Text Text)
-> [(Text, Text)] -> Map Text Text
forall a b. (a -> b) -> a -> b
$ ([Text] -> [Text] -> [(Text, Text)])
-> [Text] -> [Text] -> [(Text, Text)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip [Text] -> [Text] -> [(Text, Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Text]
inArgNames
([Text] -> [(Text, Text)]) -> [Text] -> [(Text, Text)]
forall a b. (a -> b) -> a -> b
$ (Arg -> Text) -> [Arg] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Text
escapedArgName ([Arg] -> [Text]) -> [Arg] -> [Text]
forall a b. (a -> b) -> a -> b
$ Callable -> [Arg]
args Callable
callable
Callable -> Map Text Text -> BaseCodeGen CGError ()
prepareClosures Callable
callable Map Text Text
nameMap
if Callable -> Bool
callableThrows Callable
callable
then do
Text -> CodeGen ()
line Text
"onException (do"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
Callable -> ForeignSymbol -> [Text] -> CodeGen ()
invokeCFunction Callable
callable ForeignSymbol
symbol [Text]
inArgNames
Callable -> Map Text Text -> BaseCodeGen CGError ()
readOutArrayLengths Callable
callable Map Text Text
nameMap
Text
result <- Name -> Callable -> Map Text Text -> ExcCodeGen Text
convertResult Name
n Callable
callable Map Text Text
nameMap
[Text]
pps <- Callable -> Map Text Text -> [Arg] -> ExcCodeGen [Text]
convertOutArgs Callable
callable Map Text Text
nameMap [Arg]
hOutArgs
Callable -> Map Text Text -> BaseCodeGen CGError ()
freeCallCallbacks Callable
callable Map Text Text
nameMap
[Arg] -> (Arg -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Callable -> [Arg]
args Callable
callable) Arg -> BaseCodeGen CGError ()
touchInArg
(Text -> BaseCodeGen CGError ())
-> [Text] -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Text -> BaseCodeGen CGError ()
Text -> CodeGen ()
line ([Text] -> BaseCodeGen CGError ())
-> ExcCodeGen [Text] -> BaseCodeGen CGError ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgs Callable
callable Map Text Text
nameMap
Callable -> Text -> [Text] -> CodeGen ()
returnResult Callable
callable Text
result [Text]
pps
Text -> CodeGen ()
line Text
" ) (do"
BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
indent (BaseCodeGen CGError () -> BaseCodeGen CGError ())
-> BaseCodeGen CGError () -> BaseCodeGen CGError ()
forall a b. (a -> b) -> a -> b
$ do
Callable -> Map Text Text -> BaseCodeGen CGError ()
freeCallCallbacks Callable
callable Map Text Text
nameMap
[Text]
actions <- Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgsOnError Callable
callable Map Text Text
nameMap
case [Text]
actions of
[] -> Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"return ()"
[Text]
_ -> (Text -> BaseCodeGen CGError ())
-> [Text] -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Text -> BaseCodeGen CGError ()
Text -> CodeGen ()
line [Text]
actions
Text -> CodeGen ()
line Text
" )"
else do
Callable -> ForeignSymbol -> [Text] -> CodeGen ()
invokeCFunction Callable
callable ForeignSymbol
symbol [Text]
inArgNames
Callable -> Map Text Text -> BaseCodeGen CGError ()
readOutArrayLengths Callable
callable Map Text Text
nameMap
Text
result <- Name -> Callable -> Map Text Text -> ExcCodeGen Text
convertResult Name
n Callable
callable Map Text Text
nameMap
[Text]
pps <- Callable -> Map Text Text -> [Arg] -> ExcCodeGen [Text]
convertOutArgs Callable
callable Map Text Text
nameMap [Arg]
hOutArgs
Callable -> Map Text Text -> BaseCodeGen CGError ()
freeCallCallbacks Callable
callable Map Text Text
nameMap
[Arg] -> (Arg -> BaseCodeGen CGError ()) -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Callable -> [Arg]
args Callable
callable) Arg -> BaseCodeGen CGError ()
touchInArg
(Text -> BaseCodeGen CGError ())
-> [Text] -> BaseCodeGen CGError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Text -> BaseCodeGen CGError ()
Text -> CodeGen ()
line ([Text] -> BaseCodeGen CGError ())
-> ExcCodeGen [Text] -> BaseCodeGen CGError ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Callable -> Map Text Text -> ExcCodeGen [Text]
freeInArgs Callable
callable Map Text Text
nameMap
Callable -> Text -> [Text] -> CodeGen ()
returnResult Callable
callable Text
result [Text]
pps
fixupCallerAllocates :: Callable -> Callable
fixupCallerAllocates :: Callable -> Callable
fixupCallerAllocates Callable
c =
Callable
c{args :: [Arg]
args = (Arg -> Arg) -> [Arg] -> [Arg]
forall a b. (a -> b) -> [a] -> [b]
map (Arg -> Arg
fixupLength (Arg -> Arg) -> (Arg -> Arg) -> Arg -> Arg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arg -> Arg
fixupDir) (Callable -> [Arg]
args Callable
c)}
where fixupDir :: Arg -> Arg
fixupDir :: Arg -> Arg
fixupDir Arg
a = case Arg -> Type
argType Arg
a of
TCArray Bool
_ Int
_ Int
l Type
_ ->
if Arg -> Bool
argCallerAllocates Arg
a Bool -> Bool -> Bool
&& Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> -Int
1
then Arg
a { direction :: Direction
direction = Direction
DirectionInout
, transfer :: Transfer
transfer = Transfer
TransferEverything }
else Arg
a
Type
_ -> Arg
a
lengthsMap :: Map.Map Arg Arg
lengthsMap :: Map Arg Arg
lengthsMap = [(Arg, Arg)] -> Map Arg Arg
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList (((Arg, Arg) -> (Arg, Arg)) -> [(Arg, Arg)] -> [(Arg, Arg)]
forall a b. (a -> b) -> [a] -> [b]
map (Arg, Arg) -> (Arg, Arg)
forall a b. (a, b) -> (b, a)
swap (Callable -> [(Arg, Arg)]
arrayLengthsMap Callable
c))
fixupLength :: Arg -> Arg
fixupLength :: Arg -> Arg
fixupLength Arg
a = case Arg -> Map Arg Arg -> Maybe Arg
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Arg
a Map Arg Arg
lengthsMap of
Maybe Arg
Nothing -> Arg
a
Just Arg
array ->
if Arg -> Bool
argCallerAllocates Arg
array
then Arg
a {direction :: Direction
direction = Direction
DirectionIn}
else Arg
a
data ForeignSymbol = KnownForeignSymbol Text
| DynamicForeignSymbol DynamicWrapper
data DynamicWrapper = DynamicWrapper {
DynamicWrapper -> Text
dynamicWrapper :: Text
, DynamicWrapper -> Text
dynamicType :: Text
}
genCallableDebugInfo :: Callable -> CodeGen ()
genCallableDebugInfo :: Callable -> CodeGen ()
genCallableDebugInfo Callable
callable =
BaseCodeGen e () -> BaseCodeGen e ()
forall e a. BaseCodeGen e a -> BaseCodeGen e a
group (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$ do
Text -> [Arg] -> CodeGen ()
forall a. Show a => Text -> a -> CodeGen ()
commentShow Text
"Args" (Callable -> [Arg]
args Callable
callable)
Text -> [Arg] -> CodeGen ()
forall a. Show a => Text -> a -> CodeGen ()
commentShow Text
"Lengths" (Callable -> [Arg]
arrayLengths Callable
callable)
Text -> Maybe Type -> CodeGen ()
forall a. Show a => Text -> a -> CodeGen ()
commentShow Text
"returnType" (Callable -> Maybe Type
returnType Callable
callable)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"-- throws : " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Bool -> Text
forall a. Show a => a -> Text
tshow (Bool -> Text) -> Bool -> Text
forall a b. (a -> b) -> a -> b
$ Callable -> Bool
callableThrows Callable
callable)
Text -> CodeGen ()
line (Text -> CodeGen ()) -> Text -> CodeGen ()
forall a b. (a -> b) -> a -> b
$ Text
"-- Skip return : " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Bool -> Text
forall a. Show a => a -> Text
tshow (Bool -> Text) -> Bool -> Text
forall a b. (a -> b) -> a -> b
$ Callable -> Bool
skipReturn Callable
callable)
Bool -> BaseCodeGen e () -> BaseCodeGen e ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Callable -> Bool
skipReturn Callable
callable Bool -> Bool -> Bool
&& Callable -> Maybe Type
returnType Callable
callable Maybe Type -> Maybe Type -> Bool
forall a. Eq a => a -> a -> Bool
/= Type -> Maybe Type
forall a. a -> Maybe a
Just (BasicType -> Type
TBasicType BasicType
TBoolean)) (BaseCodeGen e () -> BaseCodeGen e ())
-> BaseCodeGen e () -> BaseCodeGen e ()
forall a b. (a -> b) -> a -> b
$
do Text -> CodeGen ()
line Text
"-- XXX return value ignored, but it is not a boolean."
Text -> CodeGen ()
line Text
"-- This may be a memory leak?"
where commentShow :: Show a => Text -> a -> CodeGen ()
commentShow :: Text -> a -> CodeGen ()
commentShow Text
prefix a
s =
let padding :: Text
padding = Int -> Text -> Text
T.replicate (Text -> Int
T.length Text
prefix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) Text
" "
padded :: [Text]
padded = case Text -> [Text]
T.lines (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ a -> String
forall a. Show a => a -> String
ppShow a
s) of
[] -> []
(Text
f:[Text]
rest) -> Text
"-- " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
prefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
f Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:
(Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ((Text
"-- " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
padding) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) [Text]
rest
in (Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) ())
-> [Text]
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Text
-> ReaderT
CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) ()
Text -> CodeGen ()
line [Text]
padded
genCCallableWrapper :: Name -> Text -> Callable -> ExcCodeGen ()
genCCallableWrapper :: Name -> Text -> Callable -> BaseCodeGen CGError ()
genCCallableWrapper Name
n Text
cSymbol Callable
callable
| Callable -> Maybe Bool
callableResolvable Callable
callable Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Bool
forall a. Maybe a
Nothing =
Text -> BaseCodeGen CGError ()
forall a. HasCallStack => Text -> a
terror (Text
"Resolvability of “" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cSymbol Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"” unkown.")
| Callable -> Maybe Bool
callableResolvable Callable
callable Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False =
Text -> BaseCodeGen CGError ()
forall a. Text -> ExcCodeGen a
badIntroError (Text
"Could not resolve the symbol “" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cSymbol
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"” in the “" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Name -> Text
namespace Name
n
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"” namespace, ignoring.")
| Bool
otherwise = do
Callable -> CodeGen ()
genCallableDebugInfo Callable
callable
let callable' :: Callable
callable' = Callable -> Callable
fixupCallerAllocates Callable
callable
Text
hSymbol <- Text -> Callable -> CodeGen Text
mkForeignImport Text
cSymbol Callable
callable'
BaseCodeGen CGError ()
CodeGen ()
blank
Text -> Maybe DeprecationInfo -> CodeGen ()
deprecatedPragma (Name -> Text
lowerName Name
n) (Callable -> Maybe DeprecationInfo
callableDeprecated Callable
callable)
RelativeDocPosition -> Documentation -> CodeGen ()
writeDocumentation RelativeDocPosition
DocBeforeSymbol (Callable -> Documentation
callableDocumentation Callable
callable)
ExcCodeGen Text -> BaseCodeGen CGError ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Name
-> ForeignSymbol -> Callable -> ExposeClosures -> ExcCodeGen Text
genHaskellWrapper Name
n (Text -> ForeignSymbol
KnownForeignSymbol Text
hSymbol) Callable
callable'
ExposeClosures
WithoutClosures)
forgetClosures :: Callable -> Callable
forgetClosures :: Callable -> Callable
forgetClosures Callable
c = Callable
c {args :: [Arg]
args = (Arg -> Arg) -> [Arg] -> [Arg]
forall a b. (a -> b) -> [a] -> [b]
map Arg -> Arg
forgetClosure (Callable -> [Arg]
args Callable
c)}
where forgetClosure :: Arg -> Arg
forgetClosure :: Arg -> Arg
forgetClosure Arg
arg = Arg
arg {argClosure :: Int
argClosure = -Int
1}
genDynamicCallableWrapper :: Name -> Text -> Callable ->
ExcCodeGen Text
genDynamicCallableWrapper :: Name -> Text -> Callable -> ExcCodeGen Text
genDynamicCallableWrapper Name
n Text
typeSynonym Callable
callable = do
Callable -> CodeGen ()
genCallableDebugInfo Callable
callable
let callable' :: Callable
callable' = Callable -> Callable
forgetClosures (Callable -> Callable
fixupCallerAllocates Callable
callable)
Text
wrapper <- Text -> CodeGen Text
mkDynamicImport Text
typeSynonym
BaseCodeGen CGError ()
CodeGen ()
blank
RelativeDocPosition -> Text -> CodeGen ()
writeHaddock RelativeDocPosition
DocBeforeSymbol Text
dynamicDoc
let dyn :: DynamicWrapper
dyn = DynamicWrapper :: Text -> Text -> DynamicWrapper
DynamicWrapper { dynamicWrapper :: Text
dynamicWrapper = Text
wrapper
, dynamicType :: Text
dynamicType = Text
typeSynonym }
Name
-> ForeignSymbol -> Callable -> ExposeClosures -> ExcCodeGen Text
genHaskellWrapper Name
n (DynamicWrapper -> ForeignSymbol
DynamicForeignSymbol DynamicWrapper
dyn) Callable
callable' ExposeClosures
WithClosures
where
dynamicDoc :: Text
dynamicDoc :: Text
dynamicDoc = Text
"Given a pointer to a foreign C function, wrap it into a function callable from Haskell."