{-# LANGUAGE TemplateHaskell #-}
module STD.MapIterator.TH where
import Data.Char
import Data.List
import Data.Monoid
import Foreign.C.Types
import Foreign.Ptr
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import FFICXX.Runtime.CodeGen.Cxx
import FFICXX.Runtime.TH
import STD.MapIterator.Template
import STD.Pair.Template

t_deRef :: (Type, Type) -> String -> Q Exp
t_deRef :: (Type, Type) -> String -> Q Exp
t_deRef (Type
typ1, Type
typ2) String
suffix
  = forall types.
(types, String, String -> String, types -> Q Type) -> Q Exp
mkTFunc
      ((Type
typ1, Type
typ2), String
suffix, \ String
n -> String
"MapIterator_deRef" forall a. Semigroup a => a -> a -> a
<> String
n, forall {m :: * -> *} {p}. Quote m => p -> m Type
tyf)
  where tyf :: p -> m Type
tyf p
_
          = let tpk :: m Type
tpk = forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
typ1
                tpv :: m Type
tpv = forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
typ2
              in
              [t| MapIterator $( tpk ) $( tpv ) -> IO (Pair $( tpk ) $( tpv )) |]

t_increment :: (Type, Type) -> String -> Q Exp
t_increment :: (Type, Type) -> String -> Q Exp
t_increment (Type
typ1, Type
typ2) String
suffix
  = forall types.
(types, String, String -> String, types -> Q Type) -> Q Exp
mkTFunc
      ((Type
typ1, Type
typ2), String
suffix, \ String
n -> String
"MapIterator_increment" forall a. Semigroup a => a -> a -> a
<> String
n, forall {m :: * -> *} {p}. Quote m => p -> m Type
tyf)
  where tyf :: p -> m Type
tyf p
_
          = let tpk :: m Type
tpk = forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
typ1
                tpv :: m Type
tpv = forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
typ2
              in
              [t|
                MapIterator $( tpk ) $( tpv ) -> IO (MapIterator $( tpk ) $( tpv ))
                |]

genMapIteratorInstanceFor ::
                          IsCPrimitive ->
                            (Q Type, TemplateParamInfo) ->
                              (Q Type, TemplateParamInfo) -> Q [Dec]
genMapIteratorInstanceFor :: IsCPrimitive
-> (Q Type, TemplateParamInfo)
-> (Q Type, TemplateParamInfo)
-> Q [Dec]
genMapIteratorInstanceFor IsCPrimitive
isCprim (Q Type
qtyp1, TemplateParamInfo
param1) (Q Type
qtyp2, TemplateParamInfo
param2)
  = do let params :: [String]
params = forall a b. (a -> b) -> [a] -> [b]
map TemplateParamInfo -> String
tpinfoSuffix [TemplateParamInfo
param1, TemplateParamInfo
param2]
       let suffix :: String
suffix
             = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\ TemplateParamInfo
x -> String
"_" forall a. [a] -> [a] -> [a]
++ TemplateParamInfo -> String
tpinfoSuffix TemplateParamInfo
x) [TemplateParamInfo
param1, TemplateParamInfo
param2]
       String
callmod_ <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Loc -> String
loc_module Q Loc
location
       let callmod :: String
callmod = String -> String
dot2_ String
callmod_
       Type
typ1 <- Q Type
qtyp1
       Type
typ2 <- Q Type
qtyp2
       Dec
f1 <- forall types.
String -> (types -> String -> Q Exp) -> types -> String -> Q Dec
mkMember String
"deRef" (Type, Type) -> String -> Q Exp
t_deRef (Type
typ1, Type
typ2) String
suffix
       Dec
f2 <- forall types.
String -> (types -> String -> Q Exp) -> types -> String -> Q Dec
mkMember String
"increment" (Type, Type) -> String -> Q Exp
t_increment (Type
typ1, Type
typ2) String
suffix
       Q () -> Q ()
addModFinalizer
         (ForeignSrcLang -> String -> Q ()
addForeignSource ForeignSrcLang
LangCxx
            (String
"\n#include \"MacroPatternMatch.h\"\n\n\n#include \"map\"\n\n\n#define MapIterator_deRef(callmod, tpk, tpv) \\\nextern \"C\" {\\\nvoid* MapIterator_deRef_##tpk##_##tpv ( void* p );}\\\ninline void* MapIterator_deRef_##tpk##_##tpv ( void* p ) {\\\nstd::pair<tpk,tpv>* r=new std::pair<tpk,tpv>((static_cast<std::map<tpk, tpv>::iterator*>(p))->operator*());return static_cast<void*>(r);\\\n}\\\nauto a_##callmod##_MapIterator_deRef_##tpk##_##tpv=MapIterator_deRef_##tpk##_##tpv;\n\n\n#define MapIterator_increment(callmod, tpk, tpv) \\\nextern \"C\" {\\\nvoid* MapIterator_increment_##tpk##_##tpv ( void* p );}\\\ninline void* MapIterator_increment_##tpk##_##tpv ( void* p ) {\\\nstd::map<tpk,tpv>::iterator* r=new std::map<tpk,tpv>::iterator((static_cast<std::map<tpk, tpv>::iterator*>(p))->operator++());return static_cast<void*>(r);\\\n}\\\nauto a_##callmod##_MapIterator_increment_##tpk##_##tpv=MapIterator_increment_##tpk##_##tpv;\n\n\n#define MapIterator_deRef_s(callmod, tpk, tpv) \\\nextern \"C\" {\\\nvoid* MapIterator_deRef_##tpk##_##tpv ( void* p );}\\\ninline void* MapIterator_deRef_##tpk##_##tpv ( void* p ) {\\\nstd::pair<tpk,tpv>* r=new std::pair<tpk,tpv>((static_cast<std::map<tpk, tpv>::iterator*>(p))->operator*());return static_cast<void*>(r);\\\n}\\\nauto a_##callmod##_MapIterator_deRef_##tpk##_##tpv=MapIterator_deRef_##tpk##_##tpv;\n\n\n#define MapIterator_increment_s(callmod, tpk, tpv) \\\nextern \"C\" {\\\nvoid* MapIterator_increment_##tpk##_##tpv ( void* p );}\\\ninline void* MapIterator_increment_##tpk##_##tpv ( void* p ) {\\\nstd::map<tpk,tpv>::iterator* r=new std::map<tpk,tpv>::iterator((static_cast<std::map<tpk, tpv>::iterator*>(p))->operator++());return static_cast<void*>(r);\\\n}\\\nauto a_##callmod##_MapIterator_increment_##tpk##_##tpv=MapIterator_increment_##tpk##_##tpv;\n\n\n#define MapIterator_instance(callmod, tpk, tpv) \\\nMapIterator_deRef(callmod, tpk, tpv)\\\nMapIterator_increment(callmod, tpk, tpv)\n\n\n#define MapIterator_instance_s(callmod, tpk, tpv) \\\nMapIterator_deRef_s(callmod, tpk, tpv)\\\nMapIterator_increment_s(callmod, tpk, tpv)\n\n"
               forall a. [a] -> [a] -> [a]
++
               let headers :: [HeaderName]
headers = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap TemplateParamInfo -> [HeaderName]
tpinfoCxxHeaders [TemplateParamInfo
param1, TemplateParamInfo
param2]
                   f :: HeaderName -> String
f HeaderName
x = CMacro Identity -> String
renderCMacro (forall (f :: * -> *). HeaderName -> CMacro f
Include HeaderName
x)
                 in forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap HeaderName -> String
f [HeaderName]
headers
                 forall a. [a] -> [a] -> [a]
++
                 let nss :: [Namespace]
nss = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap TemplateParamInfo -> [Namespace]
tpinfoCxxNamespaces [TemplateParamInfo
param1, TemplateParamInfo
param2]
                     f :: Namespace -> String
f Namespace
x = CStatement Identity -> String
renderCStmt (forall (f :: * -> *). Namespace -> CStatement f
UsingNamespace Namespace
x)
                   in forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Namespace -> String
f [Namespace]
nss
                   forall a. [a] -> [a] -> [a]
++
                   String
"MapIterator_instance" forall a. [a] -> [a] -> [a]
++
                     (case IsCPrimitive
isCprim of
                          IsCPrimitive
CPrim -> String
"_s"
                          IsCPrimitive
NonCPrim -> String
"")
                       forall a. [a] -> [a] -> [a]
++ String
"(" forall a. [a] -> [a] -> [a]
++ forall a. [a] -> [[a]] -> [a]
intercalate String
", " (String
callmod forall a. a -> [a] -> [a]
: [String]
params) forall a. [a] -> [a] -> [a]
++ String
")\n"))
       let lst :: [Dec]
lst = [Dec
f1, Dec
f2]
       forall (f :: * -> *) a. Applicative f => a -> f a
pure
         [Cxt -> Type -> [Dec] -> Dec
mkInstance [] (Type -> Type -> Type
AppT (Type -> Type -> Type
AppT (String -> Type
con String
"IMapIterator") Type
typ1) Type
typ2) [Dec]
lst]