fb-util-0.1.0.1: Foreign/CPP/HsStruct/HsSet.hs
{-
Copyright (c) Meta Platforms, Inc. and affiliates.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.
-}
{-# LANGUAGE TemplateHaskell #-}
module Foreign.CPP.HsStruct.HsSet (
deriveHsHashSetUnsafe,
) where
import qualified Control.Monad
import Data.Char (isAlphaNum)
import Language.Haskell.TH
import Foreign (Ptr)
import Foreign.C.Types (CSize)
import Foreign.CPP.Marshallable
-- HsHashSet -------------------------------------------------------------------
deriveHsHashSetUnsafe ::
String -> TypeQ -> Q [Dec]
deriveHsHashSetUnsafe cppType hsType = do
hashSetTypeStr <-
map (\i -> if isAlphaNum i then i else '_') . pprint
<$> hashSetType
let cppConstructName = "set_construct" ++ cppName
hsConstructName = mkName $ "c_set_construct" ++ hashSetTypeStr
constructImport <-
forImpD
cCall
unsafe
cppConstructName
hsConstructName
[t|Ptr () -> CSize -> IO ()|]
let cppAddName = "set_add" ++ cppName
hsAddName = mkName $ "c_set_add" ++ hashSetTypeStr
addImport <-
forImpD
cCall
unsafe
cppAddName
hsAddName
[t|Ptr () -> Ptr $hsType -> IO ()|]
hsT <- hsType
isDestructible <- isInstance (mkName "Destructible") [hsT]
let withFn = mkName $ if isDestructible then "withCxxObject" else "with"
pN = mkName "p"
keysN = mkName "keys"
addChunk =
[|
Control.Monad.forM_ keys $ \key ->
$(varE withFn) key $ \key_ptr ->
$(varE hsAddName) (castPtr p) key_ptr
|]
-- newValue (HsHashSet _h) = error "HsHashSet cannot be made on the heap"
newValueFn =
funD
(mkName "newValue")
[ clause
[conP (mkName "HsHashSet") [varP $ mkName "_h"]]
(normalB [|error "HsHashSet cannot be made on the heap"|])
[]
]
-- constructValue (HsHashSet h) = do
-- $(varE hsConstructName) (castPtr p) (fromIntegral (length keys)
-- Control.Monad.forM_ keys $ \key ->
-- $(varE withFn) key $ \key_ptr ->
-- $(varE hsAddName) (castPtr p) key_ptr
constructValueFn =
funD
(mkName "constructValue")
[ clause
[varP pN, conP (mkName "HsHashSet") [varP keysN]]
( normalB $
doE
[ noBindS
[|
$(varE hsConstructName)
(castPtr p)
(fromIntegral (length keys))
|]
, noBindS addChunk
]
)
[]
]
-- instance Constructible (HsHashSet <TYPE>) where
constructibleHashSetInst <-
instanceD
(cxt [])
[t|Constructible $hashSetType|]
[ newValueFn
, constructValueFn
]
return
[ constructibleHashSetInst
, constructImport
, addImport
]
where
hashSetType = conT (mkName "HsHashSet") `appT` hsType
cppName = "HsSet" ++ cppType