fficxx 0.5.1 → 0.6
raw patch · 46 files changed
+5280/−4604 lines, 46 filesdep +fficxx-runtimesetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: fficxx-runtime
API changes (from Hackage documentation)
- FFICXX.Generate.Code.Cpp: accessorsToDefs :: [Variable] -> String
- FFICXX.Generate.Code.Cpp: funcsToDecls :: Class -> [Function] -> String
- FFICXX.Generate.Code.Cpp: funcsToDefs :: Class -> [Function] -> String
- FFICXX.Generate.Code.Cpp: genTopLevelFuncCppDefinition :: TopLevelFunction -> String
- FFICXX.Generate.Code.Cpp: genTopLevelFuncCppHeader :: TopLevelFunction -> String
- FFICXX.Generate.Code.HsFFI: genTopLevelFuncFFI :: TopLevelImportHeader -> TopLevelFunction -> Decl ()
- FFICXX.Generate.Code.HsFrontEnd: genImportForTopLevelFunction :: TopLevelFunction -> [ImportDecl ()]
- FFICXX.Generate.Code.HsFrontEnd: genTopLevelFuncDef :: TopLevelFunction -> [Decl ()]
- FFICXX.Generate.Code.Primitive: argToCallString :: (Types, String) -> String
- FFICXX.Generate.Code.Primitive: argToString :: (Types, String) -> String
- FFICXX.Generate.Code.Primitive: argsToCallString :: Args -> String
- FFICXX.Generate.Code.Primitive: argsToString :: Args -> String
- FFICXX.Generate.Code.Primitive: argsToStringNoSelf :: Args -> String
- FFICXX.Generate.Code.Primitive: castC2Cpp :: Types -> String -> String
- FFICXX.Generate.Code.Primitive: castCpp2C :: Types -> String -> String
- FFICXX.Generate.Code.Primitive: ctypToStr :: CTypes -> IsConst -> String
- FFICXX.Generate.Code.Primitive: cvarToStr :: CTypes -> IsConst -> String -> String
- FFICXX.Generate.Code.Primitive: rettypeToString :: Types -> String
- FFICXX.Generate.Code.Primitive: tmplAllArgsToCallString :: Bool -> Args -> String
- FFICXX.Generate.Code.Primitive: tmplAllArgsToString :: Bool -> Selfness -> TemplateClass -> Args -> String
- FFICXX.Generate.Code.Primitive: tmplArgToCallString :: Bool -> (Types, String) -> String
- FFICXX.Generate.Code.Primitive: tmplArgToString :: Bool -> TemplateClass -> (Types, String) -> String
- FFICXX.Generate.Code.Primitive: tmplMemFuncArgToString :: Class -> (Types, String) -> String
- FFICXX.Generate.Code.Primitive: tmplMemFuncRetTypeToString :: Class -> Types -> String
- FFICXX.Generate.Code.Primitive: tmplRetTypeToString :: Bool -> Types -> String
- FFICXX.Generate.ContentMaker: buildTemplateHeader :: TypeMacro -> TemplateClass -> String
- FFICXX.Generate.ContentMaker: declarationTemplate :: Text
- FFICXX.Generate.ContentMaker: definitionTemplate :: Text
- FFICXX.Generate.Dependency: extractClassDepForTopLevelFunction :: TopLevelFunction -> Dep4Func
- FFICXX.Generate.Name: hsFrontNameForTopLevelFunction :: TopLevelFunction -> String
- FFICXX.Generate.Type.Class: [tapp_tparam] :: TemplateAppInfo -> TemplateArgType
- FFICXX.Generate.Type.Class: [tclass_oname] :: TemplateClass -> String
- FFICXX.Generate.Type.Class: [tclass_param] :: TemplateClass -> String
- FFICXX.Generate.Type.Class: [tfun_alias] :: TemplateFunction -> Maybe String
- FFICXX.Generate.Type.Class: [tmf_param] :: TemplateMemberFunction -> String
- FFICXX.Generate.Type.Class: [var_name] :: Variable -> String
- FFICXX.Generate.Type.Class: [var_type] :: Variable -> Types
- FFICXX.Generate.Type.Class: data TopLevelFunction
- FFICXX.Generate.Type.Class: data Variable
- FFICXX.Generate.Type.Class: instance GHC.Show.Show FFICXX.Generate.Type.Class.TopLevelFunction
- FFICXX.Generate.Type.Class: type Args = [(Types, String)]
- FFICXX.Generate.Type.Module: [cmClass] :: ClassModule -> [Class]
- FFICXX.Generate.Type.Module: [tcihSelfHeader] :: TemplateClassImportHeader -> HeaderName
- FFICXX.Generate.Type.Module: [tcmTemplateClasses] :: TemplateClassModule -> [TemplateClass]
- FFICXX.Generate.Type.PackageInterface: HdrName :: String -> HeaderName
- FFICXX.Generate.Type.PackageInterface: NS :: String -> Namespace
- FFICXX.Generate.Type.PackageInterface: TypMcro :: String -> TypeMacro
- FFICXX.Generate.Type.PackageInterface: [unHdrName] :: HeaderName -> String
- FFICXX.Generate.Type.PackageInterface: [unNamespace] :: Namespace -> String
- FFICXX.Generate.Type.PackageInterface: [unTypMcro] :: TypeMacro -> String
- FFICXX.Generate.Type.PackageInterface: instance Data.Hashable.Class.Hashable FFICXX.Generate.Type.PackageInterface.HeaderName
- FFICXX.Generate.Type.PackageInterface: instance Data.String.IsString FFICXX.Generate.Type.PackageInterface.HeaderName
- FFICXX.Generate.Type.PackageInterface: instance GHC.Classes.Eq FFICXX.Generate.Type.PackageInterface.HeaderName
- FFICXX.Generate.Type.PackageInterface: instance GHC.Classes.Eq FFICXX.Generate.Type.PackageInterface.TypeMacro
- FFICXX.Generate.Type.PackageInterface: instance GHC.Classes.Ord FFICXX.Generate.Type.PackageInterface.HeaderName
- FFICXX.Generate.Type.PackageInterface: instance GHC.Classes.Ord FFICXX.Generate.Type.PackageInterface.TypeMacro
- FFICXX.Generate.Type.PackageInterface: instance GHC.Show.Show FFICXX.Generate.Type.PackageInterface.HeaderName
- FFICXX.Generate.Type.PackageInterface: instance GHC.Show.Show FFICXX.Generate.Type.PackageInterface.Namespace
- FFICXX.Generate.Type.PackageInterface: instance GHC.Show.Show FFICXX.Generate.Type.PackageInterface.TypeMacro
- FFICXX.Generate.Type.PackageInterface: newtype HeaderName
- FFICXX.Generate.Type.PackageInterface: newtype Namespace
- FFICXX.Generate.Type.PackageInterface: newtype TypeMacro
- FFICXX.Generate.Util.HaskellSrcExts: lambda :: [Pat ()] -> Exp () -> Exp ()
- FFICXX.Generate.Util.HaskellSrcExts: list :: [Exp ()] -> Exp ()
+ FFICXX.Generate.Code.Cpp: genTmplVarCpp :: IsCPrimitive -> TemplateClass -> Variable -> [CMacro Identity]
+ FFICXX.Generate.Code.Cpp: genTopLevelCppDefinition :: TopLevel -> CStatement Identity
+ FFICXX.Generate.Code.Cpp: tmplVarToDef :: IsCPrimitive -> TemplateClass -> Variable -> Accessor -> CStatement Identity
+ FFICXX.Generate.Code.Cpp: topLevelDecl :: TopLevel -> CFunDecl Identity
+ FFICXX.Generate.Code.Cpp: typedefStmts :: String -> [CStatement Identity]
+ FFICXX.Generate.Code.HsFFI: genTopLevelFFI :: TopLevelImportHeader -> TopLevel -> Decl ()
+ FFICXX.Generate.Code.HsFrontEnd: genImportForTopLevel :: TopLevel -> [ImportDecl ()]
+ FFICXX.Generate.Code.HsFrontEnd: genTopLevelDef :: TopLevel -> [Decl ()]
+ FFICXX.Generate.Code.HsProxy: genProxyInstance :: [Decl ()]
+ FFICXX.Generate.Code.HsTemplate: genImportInTH :: TemplateClass -> [ImportDecl ()]
+ FFICXX.Generate.Code.HsTemplate: genImportInTemplate :: TemplateClass -> [ImportDecl ()]
+ FFICXX.Generate.Code.Primitive: argToCTypVar :: Arg -> (CType Identity, CName Identity)
+ FFICXX.Generate.Code.Primitive: argToCallCExp :: Arg -> CExp Identity
+ FFICXX.Generate.Code.Primitive: argsToCTypVar :: [Arg] -> [(CType Identity, CName Identity)]
+ FFICXX.Generate.Code.Primitive: argsToCTypVarNoSelf :: [Arg] -> [(CType Identity, CName Identity)]
+ FFICXX.Generate.Code.Primitive: c2Cxx :: Types -> CExp Identity -> CExp Identity
+ FFICXX.Generate.Code.Primitive: ctypToCType :: CTypes -> IsConst -> CType Identity
+ FFICXX.Generate.Code.Primitive: cxx2C :: Types -> CExp Identity -> CExp Identity
+ FFICXX.Generate.Code.Primitive: returnCType :: Types -> CType Identity
+ FFICXX.Generate.Code.Primitive: tmplAccessorToTFun :: Variable -> Accessor -> TemplateFunction
+ FFICXX.Generate.Code.Primitive: tmplAllArgsToCTypVar :: IsCPrimitive -> Selfness -> TemplateClass -> [Arg] -> [(CType Identity, CName Identity)]
+ FFICXX.Generate.Code.Primitive: tmplAppTypeFromForm :: Form -> [CType Identity] -> CType Identity
+ FFICXX.Generate.Code.Primitive: tmplArgToCTypVar :: IsCPrimitive -> TemplateClass -> Arg -> (CType Identity, CName Identity)
+ FFICXX.Generate.Code.Primitive: tmplArgToCallCExp :: IsCPrimitive -> Arg -> CExp Identity
+ FFICXX.Generate.Code.Primitive: tmplMemFuncArgToCTypVar :: Class -> Arg -> (CType Identity, CName Identity)
+ FFICXX.Generate.Code.Primitive: tmplMemFuncReturnCType :: Class -> Types -> CType Identity
+ FFICXX.Generate.Code.Primitive: tmplReturnCType :: IsCPrimitive -> Types -> CType Identity
+ FFICXX.Generate.ContentMaker: buildProxyHs :: ClassModule -> Module ()
+ FFICXX.Generate.Dependency: classFromArg :: Arg -> [Either TemplateClass Class]
+ FFICXX.Generate.Dependency: extractClassDepForTopLevel :: TopLevel -> Dep4Func
+ FFICXX.Generate.Name: hsFrontNameForTopLevel :: TopLevel -> String
+ FFICXX.Generate.Name: tmplAccessorName :: Variable -> Accessor -> String
+ FFICXX.Generate.Type.Class: Arg :: Types -> String -> Arg
+ FFICXX.Generate.Type.Class: FormNested :: String -> String -> Form
+ FFICXX.Generate.Type.Class: FormSimple :: String -> Form
+ FFICXX.Generate.Type.Class: OpFPPlus :: OpExp
+ FFICXX.Generate.Type.Class: OpStar :: OpExp
+ FFICXX.Generate.Type.Class: TFunOp :: Types -> String -> OpExp -> TemplateFunction
+ FFICXX.Generate.Type.Class: [arg_name] :: Arg -> String
+ FFICXX.Generate.Type.Class: [arg_type] :: Arg -> Types
+ FFICXX.Generate.Type.Class: [class_has_proxy] :: Class -> Bool
+ FFICXX.Generate.Type.Class: [tapp_tparams] :: TemplateAppInfo -> [TemplateArgType]
+ FFICXX.Generate.Type.Class: [tclass_cxxform] :: TemplateClass -> Form
+ FFICXX.Generate.Type.Class: [tclass_params] :: TemplateClass -> [String]
+ FFICXX.Generate.Type.Class: [tclass_vars] :: TemplateClass -> [Variable]
+ FFICXX.Generate.Type.Class: [tfun_opexp] :: TemplateFunction -> OpExp
+ FFICXX.Generate.Type.Class: [tmf_params] :: TemplateMemberFunction -> [String]
+ FFICXX.Generate.Type.Class: [unVariable] :: Variable -> Arg
+ FFICXX.Generate.Type.Class: argsFromOpExp :: OpExp -> [Arg]
+ FFICXX.Generate.Type.Class: data Arg
+ FFICXX.Generate.Type.Class: data Form
+ FFICXX.Generate.Type.Class: data OpExp
+ FFICXX.Generate.Type.Class: data TopLevel
+ FFICXX.Generate.Type.Class: hasProxy :: Class -> Bool
+ FFICXX.Generate.Type.Class: instance GHC.Show.Show FFICXX.Generate.Type.Class.Arg
+ FFICXX.Generate.Type.Class: instance GHC.Show.Show FFICXX.Generate.Type.Class.TopLevel
+ FFICXX.Generate.Type.Class: newtype Variable
+ FFICXX.Generate.Type.Class: opSymbol :: OpExp -> String
+ FFICXX.Generate.Type.Config: modImports :: String -> [String] -> [HeaderName] -> (ModuleUnit, ModuleUnitImports)
+ FFICXX.Generate.Type.Module: [tcihCxxHeaders] :: TemplateClassImportHeader -> [HeaderName]
+ FFICXX.Generate.Util.HaskellSrcExts: if_ :: Exp () -> Exp () -> Exp () -> Exp ()
+ FFICXX.Generate.Util.HaskellSrcExts: inapp :: Exp () -> QOp () -> Exp () -> Exp ()
+ FFICXX.Generate.Util.HaskellSrcExts: infixl 2 `tyapp`
+ FFICXX.Generate.Util.HaskellSrcExts: infixr 2 `tyfun`
+ FFICXX.Generate.Util.HaskellSrcExts: match :: Pat () -> Exp () -> Alt ()
+ FFICXX.Generate.Util.HaskellSrcExts: op :: String -> QOp ()
+ FFICXX.Generate.Util.HaskellSrcExts: pbind_ :: Pat () -> Exp () -> Decl ()
+ FFICXX.Generate.Util.HaskellSrcExts: qualifier :: Exp () -> Stmt ()
+ FFICXX.Generate.Util.HaskellSrcExts: urhs :: Exp () -> Rhs ()
- FFICXX.Generate.Code.Cpp: accessorToDecl :: Variable -> Accessor -> String
+ FFICXX.Generate.Code.Cpp: accessorToDecl :: Variable -> Accessor -> CFunDecl Identity
- FFICXX.Generate.Code.Cpp: accessorToDef :: Variable -> Accessor -> String
+ FFICXX.Generate.Code.Cpp: accessorToDef :: Variable -> Accessor -> CStatement Identity
- FFICXX.Generate.Code.Cpp: accessorsToDecls :: [Variable] -> String
+ FFICXX.Generate.Code.Cpp: accessorsToDecls :: [Variable] -> [CFunDecl Identity]
- FFICXX.Generate.Code.Cpp: funcToDecl :: Class -> Function -> String
+ FFICXX.Generate.Code.Cpp: funcToDecl :: Class -> Function -> CFunDecl Identity
- FFICXX.Generate.Code.Cpp: funcToDef :: Class -> Function -> String
+ FFICXX.Generate.Code.Cpp: funcToDef :: Class -> Function -> CStatement Identity
- FFICXX.Generate.Code.Cpp: genAllCppHeaderInclude :: ClassImportHeader -> String
+ FFICXX.Generate.Code.Cpp: genAllCppHeaderInclude :: ClassImportHeader -> [CMacro Identity]
- FFICXX.Generate.Code.Cpp: genCppDefInstAccessor :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppDefInstAccessor :: Class -> CStatement Identity
- FFICXX.Generate.Code.Cpp: genCppDefInstNonVirtual :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppDefInstNonVirtual :: Class -> CStatement Identity
- FFICXX.Generate.Code.Cpp: genCppDefInstVirtual :: (Class, Class) -> String
+ FFICXX.Generate.Code.Cpp: genCppDefInstVirtual :: (Class, Class) -> CStatement Identity
- FFICXX.Generate.Code.Cpp: genCppDefMacroAccessor :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppDefMacroAccessor :: Class -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genCppDefMacroNonVirtual :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppDefMacroNonVirtual :: Class -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genCppDefMacroTemplateMemberFunction :: Class -> TemplateMemberFunction -> String
+ FFICXX.Generate.Code.Cpp: genCppDefMacroTemplateMemberFunction :: Class -> TemplateMemberFunction -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genCppDefMacroVirtual :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppDefMacroVirtual :: Class -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genCppHeaderInstAccessor :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppHeaderInstAccessor :: Class -> CStatement Identity
- FFICXX.Generate.Code.Cpp: genCppHeaderInstNonVirtual :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppHeaderInstNonVirtual :: Class -> CStatement Identity
- FFICXX.Generate.Code.Cpp: genCppHeaderInstVirtual :: (Class, Class) -> String
+ FFICXX.Generate.Code.Cpp: genCppHeaderInstVirtual :: (Class, Class) -> CStatement Identity
- FFICXX.Generate.Code.Cpp: genCppHeaderMacroAccessor :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppHeaderMacroAccessor :: Class -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genCppHeaderMacroNonVirtual :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppHeaderMacroNonVirtual :: Class -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genCppHeaderMacroType :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppHeaderMacroType :: Class -> [CStatement Identity]
- FFICXX.Generate.Code.Cpp: genCppHeaderMacroVirtual :: Class -> String
+ FFICXX.Generate.Code.Cpp: genCppHeaderMacroVirtual :: Class -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genTmplClassCpp :: Bool -> TemplateClass -> [TemplateFunction] -> String
+ FFICXX.Generate.Code.Cpp: genTmplClassCpp :: IsCPrimitive -> TemplateClass -> ([TemplateFunction], [Variable]) -> CMacro Identity
- FFICXX.Generate.Code.Cpp: genTmplFunCpp :: Bool -> TemplateClass -> TemplateFunction -> String
+ FFICXX.Generate.Code.Cpp: genTmplFunCpp :: IsCPrimitive -> TemplateClass -> TemplateFunction -> CMacro Identity
- FFICXX.Generate.Code.Cpp: returnCpp :: Bool -> Types -> String -> String
+ FFICXX.Generate.Code.Cpp: returnCpp :: IsCPrimitive -> Types -> CExp Identity -> [CStatement Identity]
- FFICXX.Generate.Code.Cpp: tmplFunToDecl :: Bool -> TemplateClass -> TemplateFunction -> String
+ FFICXX.Generate.Code.Cpp: tmplFunToDecl :: IsCPrimitive -> TemplateClass -> TemplateFunction -> CFunDecl Identity
- FFICXX.Generate.Code.Cpp: tmplFunToDef :: Bool -> TemplateClass -> TemplateFunction -> String
+ FFICXX.Generate.Code.Cpp: tmplFunToDef :: IsCPrimitive -> TemplateClass -> TemplateFunction -> CStatement Identity
- FFICXX.Generate.Code.Cpp: tmplMemberFunToDecl :: Class -> TemplateMemberFunction -> String
+ FFICXX.Generate.Code.Cpp: tmplMemberFunToDecl :: Class -> TemplateMemberFunction -> CFunDecl Identity
- FFICXX.Generate.Code.Cpp: tmplMemberFunToDef :: Class -> TemplateMemberFunction -> String
+ FFICXX.Generate.Code.Cpp: tmplMemberFunToDef :: Class -> TemplateMemberFunction -> CStatement Identity
- FFICXX.Generate.Code.HsFrontEnd: genImportInModule :: [Class] -> [ImportDecl ()]
+ FFICXX.Generate.Code.HsFrontEnd: genImportInModule :: Class -> [ImportDecl ()]
- FFICXX.Generate.Code.HsTemplate: genTMFInstance :: Class -> TemplateMemberFunction -> [Decl ()]
+ FFICXX.Generate.Code.HsTemplate: genTMFInstance :: ClassImportHeader -> TemplateMemberFunction -> [Decl ()]
- FFICXX.Generate.Code.HsTemplate: genTemplateMemberFunctions :: Class -> [Decl ()]
+ FFICXX.Generate.Code.HsTemplate: genTemplateMemberFunctions :: ClassImportHeader -> [Decl ()]
- FFICXX.Generate.Code.HsTemplate: genTmplInstance :: TemplateClass -> [TemplateFunction] -> [Decl ()]
+ FFICXX.Generate.Code.HsTemplate: genTmplInstance :: TemplateClassImportHeader -> [Decl ()]
- FFICXX.Generate.Code.Primitive: CFunSig :: Args -> Types -> CFunSig
+ FFICXX.Generate.Code.Primitive: CFunSig :: [Arg] -> Types -> CFunSig
- FFICXX.Generate.Code.Primitive: [cArgTypes] :: CFunSig -> Args
+ FFICXX.Generate.Code.Primitive: [cArgTypes] :: CFunSig -> [Arg]
- FFICXX.Generate.Code.Primitive: bool :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: bool :: String -> Arg
- FFICXX.Generate.Code.Primitive: cchar :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cchar :: String -> Arg
- FFICXX.Generate.Code.Primitive: cdouble :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cdouble :: String -> Arg
- FFICXX.Generate.Code.Primitive: cfloat :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cfloat :: String -> Arg
- FFICXX.Generate.Code.Primitive: char :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: char :: String -> Arg
- FFICXX.Generate.Code.Primitive: charpp :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: charpp :: String -> Arg
- FFICXX.Generate.Code.Primitive: cint :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cint :: String -> Arg
- FFICXX.Generate.Code.Primitive: clong :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: clong :: String -> Arg
- FFICXX.Generate.Code.Primitive: convertCpp2HS4Tmpl :: Type () -> Maybe Class -> Type () -> Types -> Type ()
+ FFICXX.Generate.Code.Primitive: convertCpp2HS4Tmpl :: Type () -> Maybe Class -> [Type ()] -> Types -> Type ()
- FFICXX.Generate.Code.Primitive: cppclass :: Class -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cppclass :: Class -> String -> Arg
- FFICXX.Generate.Code.Primitive: cppclassconst :: Class -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cppclassconst :: Class -> String -> Arg
- FFICXX.Generate.Code.Primitive: cppclasscopy :: Class -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cppclasscopy :: Class -> String -> Arg
- FFICXX.Generate.Code.Primitive: cppclassmove :: Class -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cppclassmove :: Class -> String -> Arg
- FFICXX.Generate.Code.Primitive: cppclassref :: Class -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cppclassref :: Class -> String -> Arg
- FFICXX.Generate.Code.Primitive: cshort :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cshort :: String -> Arg
- FFICXX.Generate.Code.Primitive: cstar :: CTypes -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cstar :: CTypes -> String -> Arg
- FFICXX.Generate.Code.Primitive: cstring :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: cstring :: String -> Arg
- FFICXX.Generate.Code.Primitive: culong :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: culong :: String -> Arg
- FFICXX.Generate.Code.Primitive: double :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: double :: String -> Arg
- FFICXX.Generate.Code.Primitive: doublep :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: doublep :: String -> Arg
- FFICXX.Generate.Code.Primitive: float :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: float :: String -> Arg
- FFICXX.Generate.Code.Primitive: genericFuncArgs :: Function -> Args
+ FFICXX.Generate.Code.Primitive: genericFuncArgs :: Function -> [Arg]
- FFICXX.Generate.Code.Primitive: int :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: int :: String -> Arg
- FFICXX.Generate.Code.Primitive: intp :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: intp :: String -> Arg
- FFICXX.Generate.Code.Primitive: intref :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: intref :: String -> Arg
- FFICXX.Generate.Code.Primitive: long :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: long :: String -> Arg
- FFICXX.Generate.Code.Primitive: ref :: CTypes -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: ref :: CTypes -> String -> Arg
- FFICXX.Generate.Code.Primitive: self :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: self :: String -> Arg
- FFICXX.Generate.Code.Primitive: short :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: short :: String -> Arg
- FFICXX.Generate.Code.Primitive: star :: CTypes -> String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: star :: CTypes -> String -> Arg
- FFICXX.Generate.Code.Primitive: uint :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: uint :: String -> Arg
- FFICXX.Generate.Code.Primitive: ulong :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: ulong :: String -> Arg
- FFICXX.Generate.Code.Primitive: voidp :: String -> (Types, String)
+ FFICXX.Generate.Code.Primitive: voidp :: String -> Arg
- FFICXX.Generate.Config: SimpleBuilderConfig :: String -> ModuleUnitMap -> Cabal -> [Class] -> [TopLevelFunction] -> [(TemplateClass, HeaderName)] -> [String] -> [(String, [String])] -> [String] -> SimpleBuilderConfig
+ FFICXX.Generate.Config: SimpleBuilderConfig :: String -> ModuleUnitMap -> Cabal -> [Class] -> [TopLevel] -> [TemplateClassImportHeader] -> [String] -> [(String, [String])] -> [String] -> SimpleBuilderConfig
- FFICXX.Generate.Config: [sbcTemplates] :: SimpleBuilderConfig -> [(TemplateClass, HeaderName)]
+ FFICXX.Generate.Config: [sbcTemplates] :: SimpleBuilderConfig -> [TemplateClassImportHeader]
- FFICXX.Generate.Config: [sbcTopLevels] :: SimpleBuilderConfig -> [TopLevelFunction]
+ FFICXX.Generate.Config: [sbcTopLevels] :: SimpleBuilderConfig -> [TopLevel]
- FFICXX.Generate.ContentMaker: buildDeclHeader :: TypeMacro -> String -> ClassImportHeader -> String
+ FFICXX.Generate.ContentMaker: buildDeclHeader :: String -> ClassImportHeader -> String
- FFICXX.Generate.ContentMaker: buildParentDef :: ((Class, Class) -> String) -> Class -> String
+ FFICXX.Generate.ContentMaker: buildParentDef :: ((Class, Class) -> [CStatement Identity]) -> Class -> [CStatement Identity]
- FFICXX.Generate.ContentMaker: buildTopLevelHeader :: TypeMacro -> String -> TopLevelImportHeader -> String
+ FFICXX.Generate.ContentMaker: buildTopLevelHeader :: String -> TopLevelImportHeader -> String
- FFICXX.Generate.ContentMaker: buildTypeDeclHeader :: TypeMacro -> [Class] -> String
+ FFICXX.Generate.ContentMaker: buildTypeDeclHeader :: [Class] -> String
- FFICXX.Generate.ContentMaker: mkProtectedFunctionList :: Class -> String
+ FFICXX.Generate.ContentMaker: mkProtectedFunctionList :: Class -> [CMacro Identity]
- FFICXX.Generate.Dependency: getparents :: () => Either b Class -> [Either a Class]
+ FFICXX.Generate.Dependency: getparents :: Either b Class -> [Either a Class]
- FFICXX.Generate.Dependency: mkPackageConfig :: (CabalName, ModuleUnit -> ModuleUnitImports) -> ([Class], [TopLevelFunction], [(TemplateClass, HeaderName)], [(String, [String])]) -> [AddCInc] -> [AddCSrc] -> PackageConfig
+ FFICXX.Generate.Dependency: mkPackageConfig :: (CabalName, ModuleUnit -> ModuleUnitImports) -> ([Class], [TopLevel], [TemplateClassImportHeader], [(String, [String])]) -> [AddCInc] -> [AddCSrc] -> PackageConfig
- FFICXX.Generate.Dependency: mkTCM :: (TemplateClass, HeaderName) -> TemplateClassModule
+ FFICXX.Generate.Dependency: mkTCM :: TemplateClassImportHeader -> TemplateClassModule
- FFICXX.Generate.Dependency: mkTIH :: CabalName -> (ModuleUnit -> ModuleUnitImports) -> [ClassImportHeader] -> [TopLevelFunction] -> TopLevelImportHeader
+ FFICXX.Generate.Dependency: mkTIH :: CabalName -> (ModuleUnit -> ModuleUnitImports) -> [ClassImportHeader] -> [TopLevel] -> TopLevelImportHeader
- FFICXX.Generate.Type.Class: Class :: Cabal -> String -> [Class] -> ProtectedMethod -> Maybe ClassAlias -> [Function] -> [Variable] -> [TemplateMemberFunction] -> Class
+ FFICXX.Generate.Type.Class: Class :: Cabal -> String -> [Class] -> ProtectedMethod -> Maybe ClassAlias -> [Function] -> [Variable] -> [TemplateMemberFunction] -> Bool -> Class
- FFICXX.Generate.Type.Class: Constructor :: Args -> Maybe String -> Function
+ FFICXX.Generate.Type.Class: Constructor :: [Arg] -> Maybe String -> Function
- FFICXX.Generate.Type.Class: NonVirtual :: Types -> String -> Args -> Maybe String -> Function
+ FFICXX.Generate.Type.Class: NonVirtual :: Types -> String -> [Arg] -> Maybe String -> Function
- FFICXX.Generate.Type.Class: Static :: Types -> String -> Args -> Maybe String -> Function
+ FFICXX.Generate.Type.Class: Static :: Types -> String -> [Arg] -> Maybe String -> Function
- FFICXX.Generate.Type.Class: TFun :: Types -> String -> String -> Args -> Maybe String -> TemplateFunction
+ FFICXX.Generate.Type.Class: TFun :: Types -> String -> String -> [Arg] -> TemplateFunction
- FFICXX.Generate.Type.Class: TFunNew :: Args -> Maybe String -> TemplateFunction
+ FFICXX.Generate.Type.Class: TFunNew :: [Arg] -> Maybe String -> TemplateFunction
- FFICXX.Generate.Type.Class: TemplateAppInfo :: TemplateClass -> TemplateArgType -> String -> TemplateAppInfo
+ FFICXX.Generate.Type.Class: TemplateAppInfo :: TemplateClass -> [TemplateArgType] -> String -> TemplateAppInfo
- FFICXX.Generate.Type.Class: TemplateMemberFunction :: String -> Types -> String -> Args -> Maybe String -> TemplateMemberFunction
+ FFICXX.Generate.Type.Class: TemplateMemberFunction :: [String] -> Types -> String -> [Arg] -> Maybe String -> TemplateMemberFunction
- FFICXX.Generate.Type.Class: TmplCls :: Cabal -> String -> String -> String -> [TemplateFunction] -> TemplateClass
+ FFICXX.Generate.Type.Class: TmplCls :: Cabal -> String -> Form -> [String] -> [TemplateFunction] -> [Variable] -> TemplateClass
- FFICXX.Generate.Type.Class: TopLevelFunction :: Types -> String -> Args -> Maybe String -> TopLevelFunction
+ FFICXX.Generate.Type.Class: TopLevelFunction :: Types -> String -> [Arg] -> Maybe String -> TopLevel
- FFICXX.Generate.Type.Class: TopLevelVariable :: Types -> String -> Maybe String -> TopLevelFunction
+ FFICXX.Generate.Type.Class: TopLevelVariable :: Types -> String -> Maybe String -> TopLevel
- FFICXX.Generate.Type.Class: Variable :: Types -> String -> Variable
+ FFICXX.Generate.Type.Class: Variable :: Arg -> Variable
- FFICXX.Generate.Type.Class: Virtual :: Types -> String -> Args -> Maybe String -> Function
+ FFICXX.Generate.Type.Class: Virtual :: Types -> String -> [Arg] -> Maybe String -> Function
- FFICXX.Generate.Type.Class: [func_args] :: Function -> Args
+ FFICXX.Generate.Type.Class: [func_args] :: Function -> [Arg]
- FFICXX.Generate.Type.Class: [tfun_args] :: TemplateFunction -> Args
+ FFICXX.Generate.Type.Class: [tfun_args] :: TemplateFunction -> [Arg]
- FFICXX.Generate.Type.Class: [tfun_new_args] :: TemplateFunction -> Args
+ FFICXX.Generate.Type.Class: [tfun_new_args] :: TemplateFunction -> [Arg]
- FFICXX.Generate.Type.Class: [tmf_args] :: TemplateMemberFunction -> Args
+ FFICXX.Generate.Type.Class: [tmf_args] :: TemplateMemberFunction -> [Arg]
- FFICXX.Generate.Type.Class: [toplevelfunc_alias] :: TopLevelFunction -> Maybe String
+ FFICXX.Generate.Type.Class: [toplevelfunc_alias] :: TopLevel -> Maybe String
- FFICXX.Generate.Type.Class: [toplevelfunc_args] :: TopLevelFunction -> Args
+ FFICXX.Generate.Type.Class: [toplevelfunc_args] :: TopLevel -> [Arg]
- FFICXX.Generate.Type.Class: [toplevelfunc_name] :: TopLevelFunction -> String
+ FFICXX.Generate.Type.Class: [toplevelfunc_name] :: TopLevel -> String
- FFICXX.Generate.Type.Class: [toplevelfunc_ret] :: TopLevelFunction -> Types
+ FFICXX.Generate.Type.Class: [toplevelfunc_ret] :: TopLevel -> Types
- FFICXX.Generate.Type.Class: [toplevelvar_alias] :: TopLevelFunction -> Maybe String
+ FFICXX.Generate.Type.Class: [toplevelvar_alias] :: TopLevel -> Maybe String
- FFICXX.Generate.Type.Class: [toplevelvar_name] :: TopLevelFunction -> String
+ FFICXX.Generate.Type.Class: [toplevelvar_name] :: TopLevel -> String
- FFICXX.Generate.Type.Class: [toplevelvar_ret] :: TopLevelFunction -> Types
+ FFICXX.Generate.Type.Class: [toplevelvar_ret] :: TopLevel -> Types
- FFICXX.Generate.Type.Module: ClassModule :: String -> [Class] -> [ClassImportHeader] -> [Either TemplateClass Class] -> [Either TemplateClass Class] -> [Either TemplateClass Class] -> [Either TemplateClass Class] -> [String] -> ClassModule
+ FFICXX.Generate.Type.Module: ClassModule :: String -> ClassImportHeader -> [Either TemplateClass Class] -> [Either TemplateClass Class] -> [Either TemplateClass Class] -> [Either TemplateClass Class] -> [String] -> ClassModule
- FFICXX.Generate.Type.Module: TCIH :: TemplateClass -> HeaderName -> TemplateClassImportHeader
+ FFICXX.Generate.Type.Module: TCIH :: TemplateClass -> [HeaderName] -> TemplateClassImportHeader
- FFICXX.Generate.Type.Module: TCM :: String -> [TemplateClass] -> [TemplateClassImportHeader] -> TemplateClassModule
+ FFICXX.Generate.Type.Module: TCM :: String -> TemplateClassImportHeader -> TemplateClassModule
- FFICXX.Generate.Type.Module: TopLevelImportHeader :: String -> [ClassImportHeader] -> [Either TemplateClass Class] -> [TopLevelFunction] -> [Namespace] -> [HeaderName] -> [HeaderName] -> TopLevelImportHeader
+ FFICXX.Generate.Type.Module: TopLevelImportHeader :: String -> [ClassImportHeader] -> [Either TemplateClass Class] -> [TopLevel] -> [Namespace] -> [HeaderName] -> [HeaderName] -> TopLevelImportHeader
- FFICXX.Generate.Type.Module: [cmCIH] :: ClassModule -> [ClassImportHeader]
+ FFICXX.Generate.Type.Module: [cmCIH] :: ClassModule -> ClassImportHeader
- FFICXX.Generate.Type.Module: [tcmTCIH] :: TemplateClassModule -> [TemplateClassImportHeader]
+ FFICXX.Generate.Type.Module: [tcmTCIH] :: TemplateClassModule -> TemplateClassImportHeader
- FFICXX.Generate.Type.Module: [tihFuncs] :: TopLevelImportHeader -> [TopLevelFunction]
+ FFICXX.Generate.Type.Module: [tihFuncs] :: TopLevelImportHeader -> [TopLevel]
Files
- LICENSE +1/−1
- Setup.lhs +0/−10
- fficxx.cabal +33/−34
- lib/FFICXX/Generate/Builder.hs +0/−267
- lib/FFICXX/Generate/Code/Cabal.hs +0/−291
- lib/FFICXX/Generate/Code/Cpp.hs +0/−490
- lib/FFICXX/Generate/Code/HsCast.hs +0/−37
- lib/FFICXX/Generate/Code/HsFFI.hs +0/−104
- lib/FFICXX/Generate/Code/HsFrontEnd.hs +0/−334
- lib/FFICXX/Generate/Code/HsTemplate.hs +0/−180
- lib/FFICXX/Generate/Code/Primitive.hs +0/−882
- lib/FFICXX/Generate/Config.hs +0/−39
- lib/FFICXX/Generate/ContentMaker.hs +0/−485
- lib/FFICXX/Generate/Dependency.hs +0/−430
- lib/FFICXX/Generate/Name.hs +0/−140
- lib/FFICXX/Generate/QQ/Verbatim.hs +0/−25
- lib/FFICXX/Generate/Type/Annotate.hs +0/−23
- lib/FFICXX/Generate/Type/Cabal.hs +0/−88
- lib/FFICXX/Generate/Type/Class.hs +0/−295
- lib/FFICXX/Generate/Type/Config.hs +0/−25
- lib/FFICXX/Generate/Type/Module.hs +0/−76
- lib/FFICXX/Generate/Type/PackageInterface.hs +0/−36
- lib/FFICXX/Generate/Util.hs +0/−99
- lib/FFICXX/Generate/Util/HaskellSrcExts.hs +0/−213
- src/FFICXX/Generate/Builder.hs +264/−0
- src/FFICXX/Generate/Code/Cabal.hs +283/−0
- src/FFICXX/Generate/Code/Cpp.hs +711/−0
- src/FFICXX/Generate/Code/HsCast.hs +37/−0
- src/FFICXX/Generate/Code/HsFFI.hs +111/−0
- src/FFICXX/Generate/Code/HsFrontEnd.hs +322/−0
- src/FFICXX/Generate/Code/HsProxy.hs +37/−0
- src/FFICXX/Generate/Code/HsTemplate.hs +440/−0
- src/FFICXX/Generate/Code/Primitive.hs +1006/−0
- src/FFICXX/Generate/Config.hs +26/−0
- src/FFICXX/Generate/ContentMaker.hs +531/−0
- src/FFICXX/Generate/Dependency.hs +434/−0
- src/FFICXX/Generate/Name.hs +160/−0
- src/FFICXX/Generate/QQ/Verbatim.hs +13/−0
- src/FFICXX/Generate/Type/Annotate.hs +11/−0
- src/FFICXX/Generate/Type/Cabal.hs +76/−0
- src/FFICXX/Generate/Type/Class.hs +341/−0
- src/FFICXX/Generate/Type/Config.hs +39/−0
- src/FFICXX/Generate/Type/Module.hs +80/−0
- src/FFICXX/Generate/Type/PackageInterface.hs +15/−0
- src/FFICXX/Generate/Util.hs +86/−0
- src/FFICXX/Generate/Util/HaskellSrcExts.hs +223/−0
LICENSE view
@@ -1,7 +1,7 @@ The following license covers this documentation, and the source code, except where otherwise indicated. -Copyright 2011-2013, Ian-Woo Kim. All rights reserved.+Copyright 2011-2019, Ian-Woo Kim. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
− Setup.lhs
@@ -1,10 +0,0 @@-#! /usr/bin/env runhaskell--> import Distribution.Simple-> import Distribution.PackageDescription-> --import System.Process-> main = defaultMain-> --main = defaultMainWithHooks testUserHooks-> --testUserHooks = simpleUserHooks { -> -- preConf = \_ _ -> runCommand "cd rootcode; make; cd .." >>return emptyHookedBuildInfo-> -- }
fficxx.cabal view
@@ -1,21 +1,22 @@ Name: fficxx-Version: 0.5.1-Synopsis: automatic C++ binding generation-Description: automatic C++ binding generation+Version: 0.6+Synopsis: Automatic C++ binding generation+Description: fficxx is an automatic haskell Foreign Function Interface (FFI) generator to C++. License: BSD3 License-file: LICENSE Author: Ian-Woo Kim Maintainer: Ian-Woo Kim <ianwookim@gmail.com> Build-Type: Simple Category: FFI Tools-Cabal-Version: >= 1.8+Cabal-Version: >= 1.10 Source-repository head type: git location: http://www.github.com/wavewave/fficxx Library- hs-source-dirs: lib+ hs-source-dirs: src+ default-language: Haskell2010 Build-Depends: base == 4.* , aeson , aeson-pretty@@ -26,6 +27,7 @@ , directory , either , errors+ , fficxx-runtime , filepath>1 , hashable , haskell-src-exts >= 1.18@@ -39,33 +41,30 @@ , template-haskell , text , unordered-containers-- Exposed-Modules:- FFICXX.Generate.Builder- FFICXX.Generate.Config- FFICXX.Generate.Code.Cpp- FFICXX.Generate.Code.HsCast- FFICXX.Generate.Code.HsFrontEnd- FFICXX.Generate.Code.HsFFI- FFICXX.Generate.Code.HsTemplate- FFICXX.Generate.Code.Cabal- FFICXX.Generate.Code.Primitive- FFICXX.Generate.ContentMaker- FFICXX.Generate.Dependency- FFICXX.Generate.Name- FFICXX.Generate.QQ.Verbatim- FFICXX.Generate.Util- FFICXX.Generate.Util.HaskellSrcExts- FFICXX.Generate.Type.Annotate- FFICXX.Generate.Type.Cabal- FFICXX.Generate.Type.Config- FFICXX.Generate.Type.Class- FFICXX.Generate.Type.Module- FFICXX.Generate.Type.PackageInterface- ghc-options: -Wall- -funbox-strict-fields- -fno-warn-unused-do-bind- -fno-warn-missing-signatures- -O2- ghc-prof-options: -caf-all -auto-all+ FFICXX.Generate.Builder+ FFICXX.Generate.Config+ FFICXX.Generate.Code.Cpp+ FFICXX.Generate.Code.HsCast+ FFICXX.Generate.Code.HsFFI+ FFICXX.Generate.Code.HsFrontEnd+ FFICXX.Generate.Code.HsProxy+ FFICXX.Generate.Code.HsTemplate+ FFICXX.Generate.Code.Cabal+ FFICXX.Generate.Code.Primitive+ FFICXX.Generate.ContentMaker+ FFICXX.Generate.Dependency+ FFICXX.Generate.Name+ FFICXX.Generate.QQ.Verbatim+ FFICXX.Generate.Util+ FFICXX.Generate.Util.HaskellSrcExts+ FFICXX.Generate.Type.Annotate+ FFICXX.Generate.Type.Cabal+ FFICXX.Generate.Type.Config+ FFICXX.Generate.Type.Class+ FFICXX.Generate.Type.Module+ FFICXX.Generate.Type.PackageInterface+ ghc-options: -Wall+ -funbox-strict-fields+ -fno-warn-unused-do-bind+ -fno-warn-missing-signatures
− lib/FFICXX/Generate/Builder.hs
@@ -1,267 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Builder--- Copyright : (c) 2011-2019 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Builder where--import Control.Monad ( void, when )-import qualified Data.ByteString.Lazy.Char8 as L-import Data.Char ( toUpper )-import Data.Digest.Pure.MD5 ( md5 )-import Data.Foldable ( for_ )-import Data.Monoid ( (<>), mempty )-import Language.Haskell.Exts.Pretty ( prettyPrint )-import System.FilePath ( (</>), (<.>), splitExtension )-import System.Directory ( copyFile- , createDirectoryIfMissing- , doesFileExist- )-import System.IO ( hPutStrLn, withFile, IOMode(..) )-import System.Process ( readProcess )----import FFICXX.Generate.Code.Cabal-import FFICXX.Generate.Dependency-import FFICXX.Generate.Config ( FFICXXConfig(..)- , SimpleBuilderConfig(..)- )-import FFICXX.Generate.ContentMaker-import FFICXX.Generate.Type.Cabal ( Cabal(..)- , CabalName(..)- , AddCInc(..)- , AddCSrc(..)- )-import FFICXX.Generate.Type.Module-import FFICXX.Generate.Type.PackageInterface-import FFICXX.Generate.Util-----macrofy :: String -> String-macrofy = map ((\x->if x=='-' then '_' else x) . toUpper)---simpleBuilder :: FFICXXConfig -> SimpleBuilderConfig -> IO ()-simpleBuilder cfg sbc = do- putStrLn "----------------------------------------------------"- putStrLn "-- fficxx code generation for Haskell-C++ binding --"- putStrLn "----------------------------------------------------"- let SimpleBuilderConfig- topLevelMod- mumap- cabal- classes- toplevelfunctions- templates- extralibs- extramods- staticFiles- = sbc- pkgname = cabal_pkgname cabal- putStrLn ("Generating " <> unCabalName pkgname)- let workingDir = fficxxconfig_workingDir cfg- installDir = fficxxconfig_installBaseDir cfg- staticDir = fficxxconfig_staticFileDir cfg-- pkgconfig@(PkgConfig mods cihs tih tcms _tcihs _ _) =- mkPackageConfig- (pkgname, findModuleUnitImports mumap)- (classes, toplevelfunctions,templates,extramods)- (cabal_additional_c_incs cabal)- (cabal_additional_c_srcs cabal)- hsbootlst = mkHSBOOTCandidateList mods- cabalFileName = unCabalName pkgname <.> "cabal"- jsonFileName = unCabalName pkgname <.> "json"- --- createDirectoryIfMissing True workingDir- createDirectoryIfMissing True installDir- createDirectoryIfMissing True (installDir </> "src")- createDirectoryIfMissing True (installDir </> "csrc")- --- putStrLn "Copying static files"- mapM_ (\x->copyFileWithMD5Check (staticDir </> x) (installDir </> x)) staticFiles- --- putStrLn "Generating Cabal file"- buildCabalFile cabal topLevelMod pkgconfig extralibs (workingDir</>cabalFileName)- --- putStrLn "Generating JSON file"- buildJSONFile cabal topLevelMod pkgconfig extralibs (workingDir</>jsonFileName)- --- putStrLn "Generating Header file"- let typmacro = TypMcro ("__" <> macrofy (unCabalName (cabal_pkgname cabal)) <> "__")- gen :: FilePath -> String -> IO ()- gen file str =- let path = workingDir </> file in withFile path WriteMode (flip hPutStrLn str)--- gen (unCabalName pkgname <> "Type.h") (buildTypeDeclHeader typmacro (map cihClass cihs))- for_ cihs $ \hdr -> gen- (unHdrName (cihSelfHeader hdr))- (buildDeclHeader typmacro (unCabalName pkgname) hdr)- gen- (tihHeaderFileName tih <.> "h")- (buildTopLevelHeader typmacro (unCabalName pkgname) tih)- for_ tcms $ \m ->- let tcihs = tcmTCIH m- in for_ tcihs $ \tcih ->- let t = tcihTClass tcih- hdr = unHdrName (tcihSelfHeader tcih)- in gen hdr (buildTemplateHeader typmacro t)- --- putStrLn "Generating Cpp file"- for_ cihs (\hdr -> gen (cihSelfCpp hdr) (buildDefMain hdr))- gen (tihHeaderFileName tih <.> "cpp") (buildTopLevelCppDef tih)- --- putStrLn "Generating Additional Header/Source"- for_ (cabal_additional_c_incs cabal) (\(AddCInc hdr txt) -> gen hdr txt)- for_ (cabal_additional_c_srcs cabal) (\(AddCSrc hdr txt) -> gen hdr txt)- --- putStrLn "Generating RawType.hs"- for_ mods $ \m -> gen- (cmModule m <.> "RawType" <.> "hs")- (prettyPrint (buildRawTypeHs m))- --- putStrLn "Generating FFI.hsc"- for_ mods $ \m -> gen- (cmModule m <.> "FFI" <.> "hsc")- (prettyPrint (buildFFIHsc m))- --- putStrLn "Generating Interface.hs"- for_ mods $ \m -> gen- (cmModule m <.> "Interface" <.> "hs")- (prettyPrint (buildInterfaceHs mempty m))- --- putStrLn "Generating Cast.hs"- for_ mods $ \m -> gen- (cmModule m <.> "Cast" <.> "hs")- (prettyPrint (buildCastHs m))- --- putStrLn "Generating Implementation.hs"- for_ mods $ \m -> gen- (cmModule m <.> "Implementation" <.> "hs")- (prettyPrint (buildImplementationHs mempty m))- --- putStrLn "Generating Template.hs"- for_ tcms $ \m -> gen- (tcmModule m <.> "Template" <.> "hs")- (prettyPrint (buildTemplateHs m))- --- putStrLn "Generating TH.hs"- for_ tcms $ \m -> gen- (tcmModule m <.> "TH" <.> "hs")- (prettyPrint (buildTHHs m))-- --- -- TODO: Template.hs-boot need to be generated as well- putStrLn "Generating hs-boot file"- for_ hsbootlst $ \m -> gen- (m <.> "Interface" <.> "hs-boot")- (prettyPrint (buildInterfaceHSBOOT m))- --- putStrLn "Generating Module summary file"- for_ mods $ \m -> gen- (cmModule m <.> "hs")- (prettyPrint (buildModuleHs m))- --- putStrLn "Generating Top-level Module"- gen (topLevelMod <.> "hs") (prettyPrint (buildTopLevelHs topLevelMod (mods,tcms) tih))- --- putStrLn "Copying generated files to target directory"- touch (workingDir </> "LICENSE")- copyFileWithMD5Check (workingDir </> cabalFileName) (installDir </> cabalFileName)- copyFileWithMD5Check (workingDir </> jsonFileName) (installDir </> jsonFileName)- copyFileWithMD5Check (workingDir </> "LICENSE") (installDir </> "LICENSE")-- copyCppFiles workingDir (csrcDir installDir) (unCabalName pkgname) pkgconfig- for_ mods (copyModule workingDir (srcDir installDir))- for_ tcms (copyTemplateModule workingDir (srcDir installDir))- moduleFileCopy workingDir (srcDir installDir) $ topLevelMod <.> "hs"-- putStrLn "----------------------------------------------------"- putStrLn "-- Code generation has been completed. Enjoy! --"- putStrLn "----------------------------------------------------"----- | some dirty hack. later, we will do it with more proper approcah.--touch :: FilePath -> IO ()-touch fp = void (readProcess "touch" [fp] "")---copyFileWithMD5Check :: FilePath -> FilePath -> IO ()-copyFileWithMD5Check src tgt = do- b <- doesFileExist tgt- if b- then do- srcmd5 <- md5 <$> L.readFile src- tgtmd5 <- md5 <$> L.readFile tgt- if srcmd5 == tgtmd5 then return () else copyFile src tgt- else copyFile src tgt---copyCppFiles :: FilePath -> FilePath -> String -> PackageConfig -> IO ()-copyCppFiles wdir ddir cprefix (PkgConfig _ cihs tih _ tcihs acincs acsrcs) = do- let thfile = cprefix <> "Type.h"- tlhfile = tihHeaderFileName tih <.> "h"- tlcppfile = tihHeaderFileName tih <.> "cpp"- copyFileWithMD5Check (wdir </> thfile) (ddir </> thfile)- doesFileExist (wdir </> tlhfile)- >>= flip when (copyFileWithMD5Check (wdir </> tlhfile) (ddir </> tlhfile))- doesFileExist (wdir </> tlcppfile)- >>= flip when (copyFileWithMD5Check (wdir </> tlcppfile) (ddir </> tlcppfile))- for_ cihs $ \header-> do- let hfile = unHdrName (cihSelfHeader header)- cppfile = cihSelfCpp header- copyFileWithMD5Check (wdir </> hfile) (ddir </> hfile)- copyFileWithMD5Check (wdir </> cppfile) (ddir </> cppfile)-- for_ tcihs $ \header-> do- let hfile = unHdrName (tcihSelfHeader header)- copyFileWithMD5Check (wdir </> hfile) (ddir </> hfile)-- for_ acincs $ \(AddCInc header _) ->- copyFileWithMD5Check (wdir </> header) (ddir </> header)-- for_ acsrcs $ \(AddCSrc csrc _) ->- copyFileWithMD5Check (wdir </> csrc) (ddir </> csrc)---moduleFileCopy :: FilePath -> FilePath -> FilePath -> IO ()-moduleFileCopy wdir ddir fname = do- let (fnamebody,fnameext) = splitExtension fname- (mdir,mfile) = moduleDirFile fnamebody- origfpath = wdir </> fname- (mfile',_mext') = splitExtension mfile- newfpath = ddir </> mdir </> mfile' <> fnameext- b <- doesFileExist origfpath- when b $ do- createDirectoryIfMissing True (ddir </> mdir)- copyFileWithMD5Check origfpath newfpath---copyModule :: FilePath -> FilePath -> ClassModule -> IO ()-copyModule wdir ddir m = do- let modbase = cmModule m- moduleFileCopy wdir ddir $ modbase <> ".hs"- moduleFileCopy wdir ddir $ modbase <> ".RawType.hs"- moduleFileCopy wdir ddir $ modbase <> ".FFI.hsc"- moduleFileCopy wdir ddir $ modbase <> ".Interface.hs"- moduleFileCopy wdir ddir $ modbase <> ".Cast.hs"- moduleFileCopy wdir ddir $ modbase <> ".Implementation.hs"- moduleFileCopy wdir ddir $ modbase <> ".Interface.hs-boot"---copyTemplateModule :: FilePath -> FilePath -> TemplateClassModule -> IO ()-copyTemplateModule wdir ddir m = do- let modbase = tcmModule m- moduleFileCopy wdir ddir $ modbase <> ".Template.hs"- moduleFileCopy wdir ddir $ modbase <> ".TH.hs"
− lib/FFICXX/Generate/Code/Cabal.hs
@@ -1,291 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Code.Cabal--- Copyright : (c) 2011-2019 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Code.Cabal where--import Data.Aeson.Encode.Pretty (encodePretty)-import qualified Data.ByteString.Lazy as BL-import Data.List (intercalate, nub)-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Template (substitute)-import qualified Data.Text as T (intercalate,pack,replicate,unlines)-import qualified Data.Text.Lazy as TL (toStrict)-import qualified Data.Text.IO as TIO (writeFile)-import System.FilePath ((<.>),(</>))----import FFICXX.Generate.Type.Cabal ( AddCInc(..)- , AddCSrc(..)- , BuildType(..)- , CabalName(..)- , Cabal(..)- , GeneratedCabalInfo(..)- )-import FFICXX.Generate.Type.Module-import FFICXX.Generate.Type.PackageInterface-import FFICXX.Generate.Util---cabalIndentation :: Text-cabalIndentation = T.replicate 23 " "---unlinesWithIndent = T.unlines . map (cabalIndentation <>)---- for source distribution-genCsrcFiles :: (TopLevelImportHeader,[ClassModule])- -> [AddCInc]- -> [AddCSrc]- -> [String]-genCsrcFiles (tih,cmods) acincs acsrcs =- let -- indent = cabalIndentation- selfheaders' = do- x <- cmods- y <- cmCIH x- return (cihSelfHeader y)- selfheaders = nub selfheaders'- selfcpp' = do- x <- cmods- y <- cmCIH x- return (cihSelfCpp y)- selfcpp = nub selfcpp'- tlh = tihHeaderFileName tih <.> "h"- tlcpp = tihHeaderFileName tih <.> "cpp"- includeFileStrsWithCsrc = map (\x->"csrc"</> x) $- (if (null.tihFuncs) tih then map unHdrName selfheaders else tlh:(map unHdrName selfheaders))- ++ map (\(AddCInc hdr _) -> hdr) acincs- cppFilesWithCsrc = map (\x->"csrc"</>x) $- (if (null.tihFuncs) tih then selfcpp else tlcpp:selfcpp)- ++ map (\(AddCSrc src _) -> src) acsrcs--- in includeFileStrsWithCsrc <> cppFilesWithCsrc---- for library-genIncludeFiles :: String -- ^ package name- -> ([ClassImportHeader],[TemplateClassImportHeader])- -> [AddCInc]- -> [String]-genIncludeFiles pkgname (cih,tcih) acincs =- let -- indent = cabalIndentation- selfheaders = map cihSelfHeader cih <> map tcihSelfHeader tcih- includeFileStrs = map unHdrName (selfheaders ++ map (\(AddCInc hdr _) -> HdrName hdr) acincs)- in (pkgname<>"Type.h") : includeFileStrs----- unlines ((indent<>----- for library-genCppFiles :: (TopLevelImportHeader,[ClassModule])- -> [AddCSrc]- -> [String]-genCppFiles (tih,cmods) acsrcs =- let -- indent = cabalIndentation- selfcpp' = do- x <- cmods- y <- cmCIH x- return (cihSelfCpp y)- selfcpp = nub selfcpp'- tlcpp = tihHeaderFileName tih <.> "cpp"- cppFileStrs = map (\x -> "csrc" </> x) $- (if (null.tihFuncs) tih then selfcpp else tlcpp:selfcpp)- ++ map (\(AddCSrc src _) -> src) acsrcs- in cppFileStrs------ | generate exposed module list in cabal file-genExposedModules :: String -> ([ClassModule],[TemplateClassModule]) -> [String]-genExposedModules summarymod (cmods,tmods) =- let -- indentspace = cabalIndentation- -- summarystrs = summarymod- cmodstrs = map cmModule cmods- rawType = map ((\x -> x <> ".RawType").cmModule) cmods- ffi = map ((\x -> x <> ".FFI").cmModule) cmods- interface= map ((\x-> x <> ".Interface").cmModule) cmods- cast = map ((\x-> x <> ".Cast").cmModule) cmods- implementation = map ((\x-> x <> ".Implementation").cmModule) cmods- template = map ((\x-> x <> ".Template").tcmModule) tmods- th = map ((\x-> x <> ".TH").tcmModule) tmods- in -- unlines- [summarymod]<>cmodstrs<>rawType<>ffi<>interface<>cast<>implementation<>template<>th---- | generate other modules in cabal file-genOtherModules :: [ClassModule] -> [String]-genOtherModules _cmods = [""]---- | generate additional package dependencies.-genPkgDeps :: [CabalName] -> [String]-genPkgDeps cs = [ "base > 4 && < 5"- , "fficxx >= 0.5"- , "fficxx-runtime >= 0.5"- , "template-haskell"- ]- ++ map unCabalName cs------ |-cabalTemplate :: Text-cabalTemplate =- "Name: $pkgname\n\- \Version: $version\n\- \Synopsis: $synopsis\n\- \Description: $description\n\- \Homepage: $homepage\n\- \$licenseField\n\- \$licenseFileField\n\- \Author: $author\n\- \Maintainer: $maintainer\n\- \Category: $category\n\- \Tested-with: GHC >= 7.6\n\- \$buildtype\n\- \cabal-version: >= 2\n\- \Extra-source-files:\n\- \$extraFiles\n\- \$csrcFiles\n\- \\n\- \$sourcerepository\n\- \\n\- \Library\n\- \ default-language: Haskell2010\n\- \ hs-source-dirs: src\n\- \ ghc-options: -Wall -funbox-strict-fields -fno-warn-unused-do-bind -fno-warn-orphans -fno-warn-unused-imports\n\- \ ghc-prof-options: -caf-all -auto-all\n\- \ cxx-options: $cxxOptions\n\- \ Build-Depends: $pkgdeps\n\- \ Exposed-Modules:\n\- \$exposedModules\n\- \ Other-Modules:\n\- \$otherModules\n\- \ extra-lib-dirs: $extralibdirs\n\- \ extra-libraries: $extraLibraries\n\- \ Include-dirs: csrc $extraincludedirs\n\- \ pkgconfig-depends: $pkgconfigDepends\n\- \ Install-includes:\n\- \$includeFiles\n\- \ C-sources:\n\- \$cppFiles\n"------ TODO: remove all T.pack after we switch over to Text-genCabalInfo- :: Cabal- -> String- -> PackageConfig- -> [String] -- ^ extra libs- -> GeneratedCabalInfo-genCabalInfo cabal summarymodule pkgconfig extralibs =- let tih = pcfg_topLevelImportHeader pkgconfig- classmodules = pcfg_classModules pkgconfig- cih = pcfg_classImportHeaders pkgconfig- tmods = pcfg_templateClassModules pkgconfig- tcih = pcfg_templateClassImportHeaders pkgconfig- acincs = pcfg_additional_c_incs pkgconfig- acsrcs = pcfg_additional_c_srcs pkgconfig- extrafiles = cabal_extrafiles cabal- in GeneratedCabalInfo {- gci_pkgname = T.pack (unCabalName (cabal_pkgname cabal))- , gci_version = T.pack (cabal_version cabal)- , gci_synopsis = ""- , gci_description = ""- , gci_homepage = ""- , gci_license = maybe "" T.pack (cabal_license cabal)- , gci_licenseFile = maybe "" T.pack (cabal_licensefile cabal)- , gci_author = ""- , gci_maintainer = ""- , gci_category = ""- , gci_buildtype = case cabal_buildType cabal of- Simple ->- "Build-Type: Simple"- Custom deps ->- "Build-Type: Custom\ncustom-setup\n setup-depends: "- <> T.pack (intercalate ", " (map unCabalName deps))- <> "\n"- , gci_extraFiles = map T.pack extrafiles- , gci_csrcFiles = map T.pack $ genCsrcFiles (tih,classmodules) acincs acsrcs- , gci_sourcerepository = ""- , gci_cxxOptions = ["-std=c++14"]- , gci_pkgdeps = map T.pack $ genPkgDeps (cabal_additional_pkgdeps cabal)- , gci_exposedModules = map T.pack $ genExposedModules summarymodule (classmodules,tmods)- , gci_otherModules = map T.pack $ genOtherModules classmodules- , gci_extraLibDirs = map T.pack $ cabal_extralibdirs cabal- , gci_extraLibraries = map T.pack extralibs- , gci_extraIncludeDirs = map T.pack $ cabal_extraincludedirs cabal- , gci_pkgconfigDepends = map T.pack $ cabal_pkg_config_depends cabal- , gci_includeFiles = map T.pack $ genIncludeFiles (unCabalName (cabal_pkgname cabal)) (cih,tcih) acincs- , gci_cppFiles = map T.pack $ genCppFiles (tih,classmodules) acsrcs- }---genCabalFile :: GeneratedCabalInfo -> Text-genCabalFile GeneratedCabalInfo {..} =- TL.toStrict $- substitute cabalTemplate $- contextT [ ("licenseField" , "license: " <> gci_license)- , ("licenseFileField", "license-file: " <> gci_licenseFile)- , ("pkgname" , gci_pkgname)- , ("version" , gci_version)- , ("buildtype" , gci_buildtype)- , ("synopsis" , gci_synopsis)- , ("description" , gci_description)- , ("homepage" , gci_homepage)- , ("author" , gci_author)- , ("maintainer" , gci_maintainer)- , ("category" , gci_category)- , ("sourcerepository", gci_sourcerepository)- , ("cxxOptions" , T.intercalate " " gci_cxxOptions)- , ("pkgdeps" , T.intercalate ", " gci_pkgdeps)- , ("extraFiles" , unlinesWithIndent gci_extraFiles)- , ("csrcFiles" , unlinesWithIndent gci_csrcFiles)- , ("includeFiles" , unlinesWithIndent gci_includeFiles)- , ("cppFiles" , unlinesWithIndent gci_cppFiles)- , ("exposedModules" , unlinesWithIndent gci_exposedModules)- , ("otherModules" , unlinesWithIndent gci_otherModules)- , ("extralibdirs" , T.intercalate ", " gci_extraLibDirs)- , ("extraincludedirs", T.intercalate ", " gci_extraIncludeDirs)- , ("extraLibraries" , T.intercalate ", " gci_extraLibraries)- , ("cabalIndentation", cabalIndentation)- , ("pkgconfigDepends", T.intercalate ", " gci_pkgconfigDepends)- ]----- |-buildCabalFile- :: Cabal- -> String- -> PackageConfig- -> [String] -- ^ Extra libs- -> FilePath -- ^ Cabal file path- -> IO ()-buildCabalFile cabal summarymodule pkgconfig extralibs cabalfile = do- let- cinfo = genCabalInfo cabal summarymodule pkgconfig extralibs- txt = genCabalFile cinfo- TIO.writeFile cabalfile txt----- |-buildJSONFile- :: Cabal- -> String- -> PackageConfig- -> [String] -- ^ Extra libs- -> FilePath -- ^ JSON file path- -> IO ()-buildJSONFile cabal summarymodule pkgconfig extralibs jsonfile = do- let cinfo = genCabalInfo cabal summarymodule pkgconfig extralibs- BL.writeFile jsonfile (encodePretty cinfo)
− lib/FFICXX/Generate/Code/Cpp.hs
@@ -1,490 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Code.Cpp--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Code.Cpp where--import Data.Char-import Data.List (intercalate)-import Data.Monoid ((<>))----import FFICXX.Generate.Code.Primitive (accessorCFunSig- ,argsToCallString- ,argsToString- ,argsToStringNoSelf- ,castCpp2C- ,castC2Cpp- ,CFunSig(..)- ,genericFuncArgs- ,genericFuncRet- ,rettypeToString- ,tmplMemFuncArgToString- ,tmplMemFuncRetTypeToString- ,tmplAllArgsToCallString- ,tmplAllArgsToString- ,tmplRetTypeToString)-import FFICXX.Generate.Name (aliasedFuncName- ,cppFuncName- ,ffiClassName- ,ffiTmplFuncName- ,hsTemplateMemberFunctionName)-import FFICXX.Generate.Type.Class-import FFICXX.Generate.Type.Module-import FFICXX.Generate.Type.PackageInterface-import FFICXX.Generate.Util---------- Class Declaration and Definition-------------- Declaration----------- "Class Type Declaration" Instances--genCppHeaderMacroType :: Class -> String-genCppHeaderMacroType c = let tmpl = "// Opaque type definition for $classname \n\- \typedef struct ${classname}_tag ${classname}_t; \n\- \typedef ${classname}_t * ${classname}_p; \n\- \typedef ${classname}_t const* const_${classname}_p; \n"- in subst tmpl (context [ ("classname", ffiClassName c) ])------- "Class Declaration Virtual" Declaration--genCppHeaderMacroVirtual :: Class -> String-genCppHeaderMacroVirtual aclass =- let tmpl = "#undef ${classname}_DECL_VIRT \n#define ${classname}_DECL_VIRT(Type) \\\n${funcdecl}"- funcDeclStr = (funcsToDecls aclass) . virtualFuncs . class_funcs $ aclass- in subst tmpl (context [ ("classname", map toUpper (ffiClassName aclass) )- , ("funcdecl" , funcDeclStr ) ])------- "Class Declaration Non-Virtual" Declaration--genCppHeaderMacroNonVirtual :: Class -> String-genCppHeaderMacroNonVirtual c =- let tmpl = "#undef ${classname}_DECL_NONVIRT \n#define ${classname}_DECL_NONVIRT(Type) \\\n$funcdecl"- declBodyStr = subst tmpl (context [ ("classname", map toUpper (ffiClassName c))- , ("funcdecl" , funcDeclStr ) ])- funcDeclStr = (funcsToDecls c) . filter (not.isVirtualFunc)- . class_funcs $ c- in declBodyStr------- "Class Declaration Accessor" Declaration--genCppHeaderMacroAccessor :: Class -> String-genCppHeaderMacroAccessor c =- let tmpl = "#undef ${classname}_DECL_ACCESSOR\n#define ${classname}_DECL_ACCESSOR(Type)\\\n$funcdecl"- declBodyStr = subst tmpl (context [ ("classname", map toUpper (ffiClassName c))- , ("funcdecl" , funcDeclStr ) ])- funcDeclStr = accessorsToDecls (class_vars c)- in declBodyStr------- "Class Declaration Virtual/NonVirtual/Accessor" Instances--genCppHeaderInstVirtual :: (Class,Class) -> String-genCppHeaderInstVirtual (p,c) =- let strc = map toUpper (ffiClassName p)- in strc<>"_DECL_VIRT(" <> ffiClassName c <> ");\n"--genCppHeaderInstNonVirtual :: Class -> String-genCppHeaderInstNonVirtual c =- let strx = map toUpper (ffiClassName c)- in strx<>"_DECL_NONVIRT(" <> ffiClassName c <> ");\n"---genCppHeaderInstAccessor :: Class -> String-genCppHeaderInstAccessor c =- let strx = map toUpper (ffiClassName c)- in strx<>"_DECL_ACCESSOR(" <> ffiClassName c <> ");\n"------------ Definition----------- "Class Definition Virtual" Declaration--genCppDefMacroVirtual :: Class -> String-genCppDefMacroVirtual aclass =- let tmpl = "#undef ${classname}_DEF_VIRT\n#define ${classname}_DEF_VIRT(Type)\\\n$funcdef"- defBodyStr = subst tmpl (context [ ("classname", map toUpper (ffiClassName aclass) )- , ("funcdef" , funcDefStr ) ])- funcDefStr = (funcsToDefs aclass) . virtualFuncs . class_funcs $ aclass- in defBodyStr------- "Class Definition NonVirtual" Declaration--genCppDefMacroNonVirtual :: Class -> String-genCppDefMacroNonVirtual aclass =- let tmpl = "#undef ${classname}_DEF_NONVIRT\n#define ${classname}_DEF_NONVIRT(Type)\\\n$funcdef"- defBodyStr = subst tmpl (context [ ("classname", map toUpper (ffiClassName aclass) )- , ("funcdef" , funcDefStr ) ])- funcDefStr = (funcsToDefs aclass) . filter (not.isVirtualFunc)- . class_funcs $ aclass- in defBodyStr------- Define Macro to provide Accessor C-C++ shim code for a class--genCppDefMacroAccessor :: Class -> String-genCppDefMacroAccessor c =- let tmpl = "#undef ${classname}_DEF_ACCESSOR\n#define ${classname}_DEF_ACCESSOR(Type)\\\n$funcdef"- defBodyStr = subst tmpl (context [ ("classname", map toUpper (ffiClassName c))- , ("funcdef" , funcDefStr ) ])- funcDefStr = accessorsToDefs (class_vars c)- in defBodyStr------ Define Macro to provide TemplateMemberFunction C-C++ shim code for a class--genCppDefMacroTemplateMemberFunction :: Class -> TemplateMemberFunction -> String-genCppDefMacroTemplateMemberFunction c f = subst tmpl ctxt- where- tmpl = "#define ${macroname}(Type) \\\n\- \ extern \"C\" { \\\n\- \ $decl; \\\n\- \ } \\\n\- \ inline $defn \\\n\- \ auto a_${macroname}_##Type = ${macroname}_##Type ;\n"- ctxt = context- [ ("macroname", hsTemplateMemberFunctionName c f)- , ("decl" , tmplMemberFunToDecl c f)- , ("defn" , tmplMemberFunToDef c f)- ]------- Invoke Macro to define Virtual/NonVirtual method for a class--genCppDefInstVirtual :: (Class,Class) -> String-genCppDefInstVirtual (p,c) =- let strc = map toUpper (ffiClassName p)- in strc<>"_DEF_VIRT(" <> ffiClassName c <> ")\n"--genCppDefInstNonVirtual :: Class -> String-genCppDefInstNonVirtual c =- subst "${capitalclassname}_DEF_NONVIRT(${classname})"- (context [ ("capitalclassname", toUppers (ffiClassName c))- , ("classname" , ffiClassName c ) ])--genCppDefInstAccessor :: Class -> String-genCppDefInstAccessor c =- subst "${capitalclassname}_DEF_ACCESSOR(${classname})"- (context [ ("capitalclassname", toUppers (ffiClassName c))- , ("classname" , ffiClassName c ) ])---------------------genAllCppHeaderInclude :: ClassImportHeader -> String-genAllCppHeaderInclude header =- intercalateWith connRet (\x->"#include \""<>x<>"\"") $- map unHdrName (cihIncludedHPkgHeadersInCPP header- <> cihIncludedCPkgHeaders header)-------------------------------------- TOP LEVEL FUNCTIONS ------------------------------genTopLevelFuncCppHeader :: TopLevelFunction -> String-genTopLevelFuncCppHeader TopLevelFunction {..} =- subst "$returntype $funcname ( $args );"- (context [ ("returntype", rettypeToString toplevelfunc_ret )- , ("funcname" , "TopLevel_"- <> maybe toplevelfunc_name id toplevelfunc_alias)- , ("args" , argsToStringNoSelf toplevelfunc_args ) ])-genTopLevelFuncCppHeader TopLevelVariable {..} =- subst "$returntype $funcname ( );"- (context [ ("returntype", rettypeToString toplevelvar_ret )- , ("funcname" , "TopLevel_"- <> maybe toplevelvar_name id toplevelvar_alias) ])--genTopLevelFuncCppDefinition :: TopLevelFunction -> String-genTopLevelFuncCppDefinition TopLevelFunction {..} =- let tmpl = "$returntype $funcname ( $args ) { \n $funcbody\n}"- callstr = toplevelfunc_name <> "("- <> argsToCallString toplevelfunc_args- <> ")"- funcDefStr = returnCpp False (toplevelfunc_ret) callstr- in subst tmpl (context [ ("returntype", rettypeToString toplevelfunc_ret )- , ("funcname" , "TopLevel_"- <> maybe toplevelfunc_name id toplevelfunc_alias)- , ("args" , argsToStringNoSelf toplevelfunc_args )- , ("funcbody" , funcDefStr ) ])-genTopLevelFuncCppDefinition TopLevelVariable {..} =- let tmpl = "$returntype $funcname ( ) { \n $funcbody\n}"- callstr = toplevelvar_name- funcDefStr = returnCpp False (toplevelvar_ret) callstr- in subst tmpl (context [ ("returntype", rettypeToString toplevelvar_ret )- , ("funcname" , "TopLevel_"- <> maybe toplevelvar_name id toplevelvar_alias)- , ("funcbody" , funcDefStr ) ])---genTmplFunCpp :: Bool -- ^ is for simple type?- -> TemplateClass- -> TemplateFunction- -> String-genTmplFunCpp b t@TmplCls {..} f = subst tmpl ctxt- where- tmpl = "#define ${tname}_${fname}${suffix}(Type) \\\n\- \ extern \"C\" { \\\n\- \ $decl; \\\n\- \ } \\\n\- \ inline $defn \\\n\- \ auto a_${tname}_${fname}_ ## Type = ${tname}_${fname}_ ## Type ;\n"- ctxt = context $- (("suffix",if b then "_s" else ""):) $- [ ("tname" , tclass_name )- , ("fname" , ffiTmplFuncName f)- , ("decl" , tmplFunToDecl b t f )- , ("defn" , tmplFunToDef b t f ) ]--genTmplClassCpp :: Bool -- ^ is for simple type- -> TemplateClass- -> [TemplateFunction]- -> String-genTmplClassCpp b TmplCls {..} fs = subst tmpl ctxt- where- tmpl = "#define ${tname}_instance${suffix}(Type) \\\n\- \$macro\n"- suffix = if b then "_s" else ""- ctxt = context [ ("tname" , tclass_name )- , ("suffix" , suffix )- , ("macro" , macro ) ]- tname = tclass_name- macro1 f@TFun {..} = " " <> tname<> "_" <> ffiTmplFuncName f <> suffix <> "(Type) \\"-- macro1 f@TFunNew {..} = " " <> tname<> "_" <> ffiTmplFuncName f <> "(Type) \\"- macro1 TFunDelete = " " <> tname<> "_delete(Type) \\"- macro = intercalateWith connRet macro1 fs--returnCpp :: Bool -- ^ for simple type- -> Types- -> String -- ^ call string- -> String-returnCpp b ret callstr =- case ret of- Void -> callstr <> ";"- SelfType -> "return to_nonconst<Type ## _t, Type>((Type *)"- <> callstr <> ") ;"- CT (CRef _) _ -> "return (&("<>callstr<>"));"- CT _ _ -> "return "<>callstr<>";"- CPT (CPTClass c') _ -> "return to_nonconst<"<>str<>"_t,"<>str- <>">(("<>str<>"*)"<>callstr<>");"- where str = ffiClassName c'- CPT (CPTClassRef c') _ -> "return to_nonconst<"<>str<>"_t,"<>str- <>">(&("<>callstr<>"));"- where str = ffiClassName c'- CPT (CPTClassCopy c') _ -> "return to_nonconst<"<>str<>"_t,"<>str- <>">(new "<>str<>"("<>callstr<>"));"- where str = ffiClassName c'- CPT (CPTClassMove c') _ -> -- TODO: check whether this is working or not.- "return std::move(to_nonconst<"<>str<>"_t,"<>str- <>">(&("<>callstr<>")));"- where str = ffiClassName c'- TemplateApp (TemplateAppInfo _ _ cpptype) ->- cpptype <> "* r = new " <> cpptype <> "(" <> callstr <> "); "- <> "return (static_cast<void*>(r));"- TemplateAppRef (TemplateAppInfo _ _ cpptype) ->- cpptype <> "* r = new " <> cpptype <> "(" <> callstr <> "); "- <> "return (static_cast<void*>(r));"- TemplateAppMove (TemplateAppInfo _ _ cpptype) ->- cpptype <> "* r = new " <> cpptype <> "(" <> callstr <> "); "- <> "return std::move(static_cast<void*>(r));"- TemplateType _ -> error "returnCpp: TemplateType"- TemplateParam _ ->- if b then "return (" <> callstr <> ");"- else "return to_nonconst<Type ## _t, Type>((Type *)&("- <> callstr <> ")) ;"- TemplateParamPointer _ ->- if b then "return (" <> callstr <> ");"- else "return to_nonconst<Type ## _t, Type>("- <> callstr <> ") ;"------ Function Declaration and Definition--funcToDecl :: Class -> Function -> String-funcToDecl c func- | isNewFunc func || isStaticFunc func =- let tmpl = "$returntype Type ## _$funcname ( $args )"- in subst tmpl (context [ ("returntype", rettypeToString (genericFuncRet func))- , ("funcname", aliasedFuncName c func)- , ("args", argsToStringNoSelf (genericFuncArgs func))- ])- | otherwise =- let tmpl = "$returntype Type ## _$funcname ( $args )"- in subst tmpl (context [ ("returntype", rettypeToString (genericFuncRet func))- , ("funcname", aliasedFuncName c func)- , ("args", argsToString (genericFuncArgs func))- ])----funcsToDecls :: Class -> [Function] -> String-funcsToDecls c = intercalateWith connSemicolonBSlash (funcToDecl c)---funcToDef :: Class -> Function -> String-funcToDef c func- | isNewFunc func =- let declstr = funcToDecl c func- callstr = "(" <> argsToCallString (genericFuncArgs func) <> ")"- returnstr = "Type * newp = new Type " <> callstr <> "; \\\nreturn to_nonconst<Type ## _t, Type >(newp);"- in intercalateWith connBSlash id [declstr, "{", returnstr, "}"]- | isDeleteFunc func =- let declstr = funcToDecl c func- returnstr = "delete (to_nonconst<Type,Type ## _t>(p)) ; "- in intercalateWith connBSlash id [declstr, "{", returnstr, "}"]- | isStaticFunc func =- let declstr = funcToDecl c func- callstr = cppFuncName c func <> "("- <> argsToCallString (genericFuncArgs func)- <> ")"- returnstr = returnCpp False (genericFuncRet func) callstr- in intercalateWith connBSlash id [declstr, "{", returnstr, "}"]- | otherwise =- let declstr = funcToDecl c func- callstr = "TYPECASTMETHOD(Type,"<> aliasedFuncName c func <> "," <> class_name c <> ")(p)->"- <> cppFuncName c func <> "("- <> argsToCallString (genericFuncArgs func)- <> ")"- returnstr = returnCpp False (genericFuncRet func) callstr- in intercalateWith connBSlash id [declstr, "{", returnstr, "}"]----funcsToDefs :: Class -> [Function] -> String-funcsToDefs c = intercalateWith connBSlash (funcToDef c)---tmplFunToDecl :: Bool -> TemplateClass -> TemplateFunction -> String-tmplFunToDecl b t@TmplCls {..} f@TFun {..} =- subst "$ret ${tname}_${fname}_ ## Type ( $args )"- (context [ ("tname", tclass_name)- , ("fname", ffiTmplFuncName f)- , ("args" , tmplAllArgsToString b Self t tfun_args)- , ("ret" , tmplRetTypeToString b tfun_ret) ])-tmplFunToDecl b t@TmplCls {..} f@TFunNew {..} =- subst "$ret ${tname}_${fname}_ ## Type ( $args )"- (context [ ("tname", tclass_name)- , ("fname", ffiTmplFuncName f)- , ("args" , tmplAllArgsToString b NoSelf t tfun_new_args)- , ("ret" , tmplRetTypeToString b (TemplateType t)) ])-tmplFunToDecl b t@TmplCls {..} TFunDelete =- subst "$ret ${tname}_delete_ ## Type ( $args )"- (context [ ("tname", tclass_name )- , ("args" , tmplAllArgsToString b Self t [] )- , ("ret" , "void" ) ])----tmplFunToDef :: Bool -- ^ for simple type- -> TemplateClass- -> TemplateFunction- -> String-tmplFunToDef b t@TmplCls {..} f = intercalateWith connBSlash id [declstr, " {", " "<>returnstr, " }"]- where- declstr = tmplFunToDecl b t f- callstr =- case f of- TFun {..} -> "(static_cast<" <> tclass_oname <> "<Type>*>(p))->"- <> tfun_oname <> "("- <> tmplAllArgsToCallString b tfun_args- <> ")"- TFunNew {..} -> "new " <> tclass_oname <> "<Type>("- <> tmplAllArgsToCallString b tfun_new_args- <> ")"- TFunDelete -> "delete (static_cast<" <> tclass_oname <> "<Type>*>(p))"- returnstr =- case f of- TFunNew {..} -> "return static_cast<void*>("<>callstr<>");"- TFunDelete -> callstr <> ";"- TFun {..} -> returnCpp b (tfun_ret) callstr----- Accessor Declaration and Definition--accessorToDecl :: Variable -> Accessor -> String-accessorToDecl v a =- let tmpl = "$returntype Type ## _$funcname ( $args )"- csig = accessorCFunSig (var_type v) a- in subst tmpl (context [ ("returntype", rettypeToString (cRetType csig))- , ("funcname" , var_name v <> "_" <> case a of Getter -> "get"; Setter -> "set")- , ("args" , argsToString (cArgTypes csig))- ])--accessorsToDecls :: [Variable] -> String-accessorsToDecls vs =- let dcls = concatMap (\v -> [accessorToDecl v Getter,accessorToDecl v Setter]) vs- in intercalate "; \\\n" dcls---accessorToDef :: Variable -> Accessor -> String-accessorToDef v a =- let declstr = accessorToDecl v a- varexp = "to_nonconst<Type,Type ## _t>(p)->" <> var_name v- body Getter = "return (" <> castCpp2C (var_type v) varexp <> ");"- body Setter = varexp- <> " = "- <> castC2Cpp (var_type v) "x" -- TODO: somehow clean up this hard-coded "x".- <> ";"- in intercalate "\\\n" [declstr, "{", body a, "}"]---accessorsToDefs :: [Variable] -> String-accessorsToDefs vs =- let defs = concatMap (\v -> [accessorToDef v Getter,accessorToDef v Setter]) vs- in intercalate "; \\\n" defs------ Template Member Function Declaration and Definition---- TODO: Handle simple type-tmplMemberFunToDecl :: Class -> TemplateMemberFunction -> String-tmplMemberFunToDecl c f =- subst "$ret ${macroname}_##Type ( $args )"- (context [ ("macroname", hsTemplateMemberFunctionName c f)- , ("args" , intercalateWith conncomma (tmplMemFuncArgToString c) ((SelfType,"p"):tmf_args f))- , ("ret" , tmplMemFuncRetTypeToString c (tmf_ret f))- ])----- TODO: Handle simple type-tmplMemberFunToDef :: Class -> TemplateMemberFunction -> String-tmplMemberFunToDef c f =- intercalateWith connBSlash id [ declstr- , " {"- , " " <> returnstr- , " }"- ]- where- declstr = tmplMemberFunToDecl c f- callstr = "(to_nonconst<" <> ffiClassName c <> "," <> ffiClassName c <> "_t" <> ">(p))"- <> "->"- <> tmf_name f- <> "<Type>"- <> "(" <> tmplAllArgsToCallString False (tmf_args f) <> ")"- returnstr = returnCpp False (tmf_ret f) callstr
− lib/FFICXX/Generate/Code/HsCast.hs
@@ -1,37 +0,0 @@-module FFICXX.Generate.Code.HsCast where--import Language.Haskell.Exts.Build (app)-import Language.Haskell.Exts.Syntax (Decl(..),InstDecl(..))----import FFICXX.Generate.Name (hsClassName,typeclassName)-import FFICXX.Generate.Type.Class (Class(..),isAbstractClass)-import FFICXX.Generate.Util.HaskellSrcExts (classA- ,cxEmpty,cxTuple,insDecl- ,mkBind1,mkInstance,mkPVar,mkTVar,mkVar- ,tyapp,tycon,tyPtr- ,unqual)--------castBody :: [InstDecl ()]-castBody =- [ insDecl (mkBind1 "cast" [mkPVar "x",mkPVar "f"] (app (mkVar "f") (app (mkVar "castPtr") (app (mkVar "get_fptr") (mkVar "x")))) Nothing)- , insDecl (mkBind1 "uncast" [mkPVar "x",mkPVar "f"] (app (mkVar "f") (app (mkVar "cast_fptr_to_obj") (app (mkVar "castPtr") (mkVar "x")))) Nothing)- ]--genHsFrontInstCastable :: Class -> Maybe (Decl ())-genHsFrontInstCastable c- | (not.isAbstractClass) c =- let iname = typeclassName c- (_,rname) = hsClassName c- a = mkTVar "a"- ctxt = cxTuple [ classA (unqual iname) [a], classA (unqual "FPtr") [a] ]- in Just (mkInstance ctxt "Castable" [a,tyapp tyPtr (tycon rname)] castBody)- | otherwise = Nothing--genHsFrontInstCastableSelf :: Class -> Maybe (Decl ())-genHsFrontInstCastableSelf c- | (not.isAbstractClass) c =- let (cname,rname) = hsClassName c- in Just (mkInstance cxEmpty "Castable" [tycon cname, tyapp tyPtr (tycon rname)] castBody)- | otherwise = Nothing-
− lib/FFICXX/Generate/Code/HsFFI.hs
@@ -1,104 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Code.HsFFI--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Code.HsFFI where--import Data.Maybe (fromMaybe,mapMaybe)-import Data.Monoid ((<>))-import Language.Haskell.Exts.Syntax (Decl(..),ImportDecl(..))-import System.FilePath ((<.>))----import FFICXX.Generate.Code.Primitive (CFunSig(..)- ,accessorCFunSig- ,genericFuncArgs- ,genericFuncRet- ,hsFFIFuncTyp)-import FFICXX.Generate.Dependency (class_allparents- ,getClassModuleBase- ,getTClassModuleBase)-import FFICXX.Generate.Name (aliasedFuncName- ,ffiClassName- ,hscAccessorName- ,hscFuncName)-import FFICXX.Generate.Type.Class-import FFICXX.Generate.Type.Module-import FFICXX.Generate.Type.PackageInterface-import FFICXX.Generate.Util-import FFICXX.Generate.Util.HaskellSrcExts---genHsFFI :: ClassImportHeader -> [Decl ()]-genHsFFI header =- let c = cihClass header- -- TODO: This C header information should not be necessary according to up-to-date- -- version of Haskell FFI.- h = cihSelfHeader header- -- NOTE: We need to generate FFI both for member functions at the current class level- -- and parent level. For example, consider a class A with method foo, which a- -- subclass of B with method bar. Then, A::foo (c_a_foo) and A::bar (c_a_bar)- -- are made into a FFI function.- allfns = concatMap (virtualFuncs . class_funcs)- (class_allparents c)- <> (class_funcs c)-- in mapMaybe (hsFFIClassFunc h c) allfns- <> concatMap- (\v -> [hsFFIAccessor c v Getter, hsFFIAccessor c v Setter])- (class_vars c)--hsFFIClassFunc :: HeaderName -> Class -> Function -> Maybe (Decl ())-hsFFIClassFunc headerfilename c f =- if isAbstractClass c- then Nothing- else let hfile = unHdrName headerfilename- -- TODO: Make this a separate function- cname = ffiClassName c <> "_" <> aliasedFuncName c f- csig = CFunSig (genericFuncArgs f) (genericFuncRet f)- typ = if (isNewFunc f || isStaticFunc f)- then hsFFIFuncTyp (Just (NoSelf,c)) csig- else hsFFIFuncTyp (Just (Self,c) ) csig- in Just (mkForImpCcall (hfile <> " " <> cname) (hscFuncName c f) typ)---hsFFIAccessor ::Class -> Variable -> Accessor -> Decl ()-hsFFIAccessor c v a =- let -- TODO: make this a separate function- cname = ffiClassName c <> "_" <> var_name v <> "_" <> (case a of Getter -> "get"; Setter -> "set")- typ = hsFFIFuncTyp (Just (Self,c)) (accessorCFunSig (var_type v) a)- in mkForImpCcall cname (hscAccessorName c v a) typ----- import for FFI--genImportInFFI :: ClassModule -> [ImportDecl ()]-genImportInFFI = map mkMod . cmImportedModulesForFFI- where mkMod (Left t) = mkImport (getTClassModuleBase t <.> "Template")- mkMod (Right c) = mkImport (getClassModuleBase c <.> "RawType")---------------------------------- for top level function ---------------------------------genTopLevelFuncFFI :: TopLevelImportHeader -> TopLevelFunction -> Decl ()-genTopLevelFuncFFI header tfn = mkForImpCcall (hfilename <> " TopLevel_" <> fname) cfname typ- where (fname,args,ret) =- case tfn of- TopLevelFunction {..} -> (fromMaybe toplevelfunc_name toplevelfunc_alias, toplevelfunc_args, toplevelfunc_ret)- TopLevelVariable {..} -> (fromMaybe toplevelvar_name toplevelvar_alias, [], toplevelvar_ret)- hfilename = tihHeaderFileName header <.> "h"- -- TODO: This must be exposed as a top-level function- cfname = "c_" <> toLowers fname- typ =hsFFIFuncTyp Nothing (CFunSig args ret)
− lib/FFICXX/Generate/Code/HsFrontEnd.hs
@@ -1,334 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Code.HsFrontEnd--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Code.HsFrontEnd where--import Control.Monad.Reader-import Data.Either (lefts,rights)-import Data.List-import Data.Monoid ((<>))-import Language.Haskell.Exts.Build (app,letE,name,pApp)-import Language.Haskell.Exts.Syntax (Decl(..),ExportSpec(..),ImportDecl(..))-import System.FilePath ((<.>))----import FFICXX.Generate.Code.Primitive (CFunSig(..),HsFunSig(..)- ,accessorSignature- ,classConstraints- ,convertCpp2HS- ,extractArgRetTypes- ,functionSignature- ,hsFuncXformer- )-import FFICXX.Generate.Name (accessorName- ,aliasedFuncName- ,hsClassName- ,hscAccessorName- ,hscFuncName- ,hsFuncName- ,hsFrontNameForTopLevelFunction- ,typeclassName)-import FFICXX.Generate.Dependency (class_allparents- ,extractClassDepForTopLevelFunction- ,getClassModuleBase,getTClassModuleBase- ,argumentDependency,returnDependency- )-import FFICXX.Generate.Type.Class-import FFICXX.Generate.Type.Annotate-import FFICXX.Generate.Type.Module-import FFICXX.Generate.Util-import FFICXX.Generate.Util.HaskellSrcExts---genHsFrontDecl :: Class -> Reader AnnotateMap (Decl ())-genHsFrontDecl c = do- -- TODO: revive annotation- -- for the time being, let's ignore annotation.- -- amap <- ask- -- let cann = maybe "" id $ M.lookup (PkgClass,class_name c) amap- let cdecl = mkClass (classConstraints c) (typeclassName c) [mkTBind "a"] body- sigdecl f = mkFunSig (hsFuncName c f) (functionSignature c f)- body = map (clsDecl . sigdecl) . virtualFuncs . class_funcs $ c- return cdecl-----------------------genHsFrontInst :: Class -> Class -> [Decl ()]-genHsFrontInst parent child- | (not.isAbstractClass) child =- let idecl = mkInstance cxEmpty (typeclassName parent) [convertCpp2HS (Just child) SelfType] body- defn f = mkBind1 (hsFuncName child f) [] rhs Nothing- where rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName child f))- body = map (insDecl . defn) . virtualFuncs . class_funcs $ parent- in [idecl]- | otherwise = []----------------------------genHsFrontInstNew :: Class -- ^ only concrete class- -> Reader AnnotateMap [Decl ()]-genHsFrontInstNew c = do- -- amap <- ask- let fs = filter isNewFunc (class_funcs c)- return . flip concatMap fs $ \f ->- let- -- for the time being, let's ignore annotation.- -- cann = maybe "" id $ M.lookup (PkgMethod, constructorName c) amap- -- newfuncann = mkComment 0 cann- rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName c f))- in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing--genHsFrontInstNonVirtual :: Class -> [Decl ()]-genHsFrontInstNonVirtual c =- flip concatMap nonvirtualFuncs $ \f ->- let rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName c f))- in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing- where nonvirtualFuncs = nonVirtualNotNewFuncs (class_funcs c)---------genHsFrontInstStatic :: Class -> [Decl ()]-genHsFrontInstStatic c =- flip concatMap (staticFuncs (class_funcs c)) $ \f ->- let rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName c f))- in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing---------genHsFrontInstVariables :: Class -> [Decl ()]-genHsFrontInstVariables c =- flip concatMap (class_vars c) $ \v ->- let rhs accessor =- app (mkVar (case accessor of Getter -> "xform0"; _ -> "xform1"))- (mkVar (hscAccessorName c v accessor))- in mkFun (accessorName c v Getter) (accessorSignature c v Getter) [] (rhs Getter) Nothing- <> mkFun (accessorName c v Setter) (accessorSignature c v Setter) [] (rhs Setter) Nothing---------------------------------hsClassRawType :: Class -> [Decl ()]-hsClassRawType c =- [ mkData rawname [] [] Nothing- , mkNewtype highname [] [qualConDecl Nothing Nothing (conDecl highname [tyapp tyPtr rawtype])] mderiv- , mkInstance cxEmpty "FPtr" [hightype]- [ insType (tyapp (tycon "Raw") hightype) rawtype- , insDecl (mkBind1 "get_fptr" [pApp (name highname) [mkPVar "ptr"]] (mkVar "ptr") Nothing)- , insDecl (mkBind1 "cast_fptr_to_obj" [] (con highname) Nothing)- ]-- ]- where (highname,rawname) = hsClassName c- hightype = tycon highname- rawtype = tycon rawname- mderiv = Just (mkDeriving [i_eq,i_ord,i_show])- where i_eq = irule Nothing Nothing (ihcon (unqual "Eq"))- i_ord = irule Nothing Nothing (ihcon (unqual "Ord"))- i_show = irule Nothing Nothing (ihcon (unqual "Show"))------------------ upcast -----------------genHsFrontUpcastClass :: Class -> [Decl ()]-genHsFrontUpcastClass c = mkFun ("upcast"<>highname) typ [mkPVar "h"] rhs Nothing- where (highname,rawname) = hsClassName c- hightype = tycon highname- rawtype = tycon rawname- iname = typeclassName c- a_bind = unkindedVar (name "a")- a_tvar = mkTVar "a"- typ = tyForall (Just [a_bind])- (Just (cxTuple [classA (unqual "FPtr") [a_tvar], classA (unqual iname) [a_tvar]]))- (tyfun a_tvar hightype)- rhs = letE [ pbind (mkPVar "fh") (app (mkVar "get_fptr") (mkVar "h")) Nothing- , pbind (mkPVarSig "fh2" (tyapp tyPtr rawtype))- (app (mkVar "castPtr") (mkVar "fh")) Nothing- ]- (mkVar "cast_fptr_to_obj" `app` mkVar "fh2")-------------------- downcast -------------------genHsFrontDowncastClass :: Class -> [Decl ()]-genHsFrontDowncastClass c = mkFun ("downcast"<>highname) typ [mkPVar "h"] rhs Nothing- where (highname,_rawname) = hsClassName c- hightype = tycon highname- iname = typeclassName c- a_bind = unkindedVar (name "a")- a_tvar = mkTVar "a"- typ = tyForall (Just [a_bind])- (Just (cxTuple [classA (unqual "FPtr") [a_tvar], classA (unqual iname) [a_tvar]]))- (tyfun hightype a_tvar)- rhs = letE [ pbind (mkPVar "fh") (app (mkVar "get_fptr") (mkVar "h")) Nothing- , pbind (mkPVar "fh2") (app (mkVar "castPtr") (mkVar "fh")) Nothing- ]- (mkVar "cast_fptr_to_obj" `app` mkVar "fh2")------------------------------ Top Level Function ------------------------------genTopLevelFuncDef :: TopLevelFunction -> [Decl ()]-genTopLevelFuncDef f@TopLevelFunction {..} =- let fname = hsFrontNameForTopLevelFunction f- HsFunSig typs assts =- extractArgRetTypes- Nothing- False- (CFunSig toplevelfunc_args toplevelfunc_ret)- sig = tyForall Nothing (Just (cxTuple assts)) (foldr1 tyfun typs)- xformerstr = let len = length toplevelfunc_args in if len > 0 then "xform" <> show (len-1) else "xformnull"- cfname = "c_" <> toLowers fname- rhs = app (mkVar xformerstr) (mkVar cfname)-- in mkFun fname sig [] rhs Nothing-genTopLevelFuncDef v@TopLevelVariable {..} =- let fname = hsFrontNameForTopLevelFunction v- cfname = "c_" <> toLowers fname- rtyp = convertCpp2HS Nothing toplevelvar_ret- sig = tyapp (tycon "IO") rtyp- rhs = app (mkVar "xformnull") (mkVar cfname)-- in mkFun fname sig [] rhs Nothing------------------ Export -----------------genExport :: Class -> [ExportSpec ()]-genExport c =- let espec n = if null . (filter isVirtualFunc) $ (class_funcs c)- then eabs nonamespace (unqual n)- else ethingall (unqual n)- in if isAbstractClass c- then [ espec (typeclassName c) ]- else [ ethingall (unqual ((fst.hsClassName) c))- , espec (typeclassName c)- , evar (unqual ("upcast" <> (fst.hsClassName) c))- , evar (unqual ("downcast" <> (fst.hsClassName) c)) ]- <> genExportConstructorAndNonvirtual c- <> genExportStatic c---- | constructor and non-virtual function-genExportConstructorAndNonvirtual :: Class -> [ExportSpec ()]-genExportConstructorAndNonvirtual c = map (evar . unqual) fns- where fs = class_funcs c- fns = map (aliasedFuncName c) (constructorFuncs fs- <> nonVirtualNotNewFuncs fs)---- | staic function export list-genExportStatic :: Class -> [ExportSpec ()]-genExportStatic c = map (evar . unqual) fns- where fs = class_funcs c- fns = map (aliasedFuncName c) (staticFuncs fs)------------------ Import -----------------genExtraImport :: ClassModule -> [ImportDecl ()]-genExtraImport cm = map mkImport (cmExtraImport cm)---genImportInModule :: [Class] -> [ImportDecl ()]-genImportInModule = concatMap (\x -> map (\y -> mkImport (getClassModuleBase x<.>y)) ["RawType","Interface","Implementation"])----genImportInInterface :: ClassModule -> [ImportDecl ()]-genImportInInterface m =- let modlstraw = cmImportedModulesRaw m- modlstparent = cmImportedModulesHighNonSource m- modlsthigh = cmImportedModulesHighSource m- in [mkImport (cmModule m <.> "RawType")]- <> flip map modlstraw- (\case- Left t -> mkImport (getTClassModuleBase t <.> "Template")- Right c -> mkImport (getClassModuleBase c <.>"RawType")- )- <> flip map modlstparent- (\case- Left t -> mkImport (getTClassModuleBase t <.> "Template")- Right c -> mkImport (getClassModuleBase c <.>"Interface")- )- <> flip map modlsthigh- (\case- Left t -> -- TODO: *.Template in the same package needs to have hs-boot.- -- Currently, we do not have it yet.- mkImport (getTClassModuleBase t <.> "Template")- Right c -> mkImportSrc (getClassModuleBase c<.>"Interface")- )---- |-genImportInCast :: ClassModule -> [ImportDecl ()]-genImportInCast m = [ mkImport (cmModule m <.> "RawType")- , mkImport (cmModule m <.> "Interface") ]---- |-genImportInImplementation :: ClassModule -> [ImportDecl ()]-genImportInImplementation m =- let modlstraw' = cmImportedModulesForFFI m- modlsthigh = nub $ map Right $ concatMap class_allparents (cmClass m)- modlstraw = filter (not.(flip elem modlsthigh)) modlstraw'- in [ mkImport (cmModule m <.> "RawType")- , mkImport (cmModule m <.> "FFI")- , mkImport (cmModule m <.> "Interface")- , mkImport (cmModule m <.> "Cast") ]- <> concatMap (\case Left t -> [mkImport (getTClassModuleBase t <.> "Template")]; Right c -> map (\y -> mkImport (getClassModuleBase c<.>y)) ["RawType","Cast","Interface"]) modlstraw- <> concatMap (\case Left t -> [mkImport (getTClassModuleBase t <.> "Template")]; Right c -> map (\y -> mkImport (getClassModuleBase c<.>y)) ["RawType","Cast","Interface"]) modlsthigh----- | generate import list for a given top-level function--- currently this may generate duplicate import list.--- TODO: eliminate duplicated imports.-genImportForTopLevelFunction :: TopLevelFunction -> [ImportDecl ()]-genImportForTopLevelFunction f =- let dep4func = extractClassDepForTopLevelFunction f- ecs = returnDependency dep4func ++ argumentDependency dep4func- cmods = nub $ map getClassModuleBase $ rights ecs- tmods = nub $ map getTClassModuleBase $ lefts ecs- in concatMap (\x -> map (\y -> mkImport (x<.>y)) ["RawType","Cast","Interface"]) cmods- <> concatMap (\x -> map (\y -> mkImport (x<.>y)) ["Template"]) tmods---- | generate import list for top level module-genImportInTopLevel ::- String- -> ([ClassModule],[TemplateClassModule])- -> TopLevelImportHeader- -> [ImportDecl ()]-genImportInTopLevel modname (mods,tmods) tih =- let tfns = tihFuncs tih- in map (mkImport . cmModule) mods- ++ if null tfns- then []- else map mkImport [ "Foreign.C", "Foreign.Ptr", "FFICXX.Runtime.Cast" ]- ++ map (\c -> mkImport (modname <.> (fst.hsClassName.cihClass) c <.> "RawType")) (tihClassDep tih)- ++ map (\m -> mkImport (tcmModule m <.> "Template")) tmods- ++ concatMap genImportForTopLevelFunction tfns-
− lib/FFICXX/Generate/Code/HsTemplate.hs
@@ -1,180 +0,0 @@-{-# LANGUAGE RecordWildCards #-}-module FFICXX.Generate.Code.HsTemplate where--import Data.Monoid ((<>))-import Language.Haskell.Exts.Build (app,binds,doE,letE,letStmt,name,pApp- ,qualStmt,strE,tuple)-import Language.Haskell.Exts.Syntax (Decl(..))----import FFICXX.Generate.Code.Primitive (functionSignatureT- ,functionSignatureTT- ,functionSignatureTMF)-import FFICXX.Generate.Code.HsCast (castBody)-import FFICXX.Generate.Name (ffiTmplFuncName- ,hsTemplateClassName- ,hsTemplateMemberFunctionName- ,hsTemplateMemberFunctionNameTH- ,hsTmplFuncName- ,hsTmplFuncNameTH- ,typeclassNameT)-import FFICXX.Generate.Type.Class (Class(..)- ,TemplateClass(..)- ,TemplateFunction(..)- ,TemplateMemberFunction(..))-import FFICXX.Generate.Util.HaskellSrcExts (bracketExp- ,con,conDecl,cxEmpty- ,generator- ,clsDecl,insDecl,insType- ,lambda,list- ,mkBind1,mkTBind,mkData,mkNewtype- ,mkFun,mkFunSig,mkClass,mkInstance- ,mkPVar,mkTVar,mkVar- ,pbind,qualConDecl- ,tyapp,tycon,tyfun,tylist,tyPtr- ,typeBracket)------------------------------------- Template member function -----------------------------------genTemplateMemberFunctions :: Class -> [Decl ()]-genTemplateMemberFunctions c =- concatMap (\f -> genTMFExp c f <> genTMFInstance c f) (class_tmpl_funcs c)---genTMFExp :: Class -> TemplateMemberFunction -> [Decl ()]-genTMFExp c f = mkFun nh sig [p "typ", p "suffix"] rhs (Just bstmts)- where nh = hsTemplateMemberFunctionNameTH c f- sig = tycon "Type" `tyfun` (tycon "String" `tyfun` (tyapp (tycon "Q") (tycon "Exp")))- v = mkVar- p = mkPVar- tp = tmf_param f- lit' = strE (hsTemplateMemberFunctionName c f <> "_")- lam = lambda [p "n"] ( lit' `app` v "<>" `app` v "n")- rhs = app (v "mkTFunc") (tuple [v "typ", v "suffix", lam, v "tyf"])- sig' = functionSignatureTMF c f- bstmts = binds [ mkBind1 "tyf" [mkPVar "n"]- (letE [ pbind (p tp) (v "pure" `app` (v "typ")) Nothing ]- (bracketExp (typeBracket sig')))- Nothing- ]---genTMFInstance :: Class -> TemplateMemberFunction -> [Decl ()]-genTMFInstance c f = mkFun fname sig [p "qtyp", p "suffix"] rhs Nothing- where fname = "genInstanceFor_" <> hsTemplateMemberFunctionName c f- p = mkPVar- v = mkVar- sig = (tyapp (tycon "Q") (tycon "Type")) `tyfun`- (tycon "String" `tyfun`- (tyapp (tycon "Q") (tylist (tycon "Dec"))))- rhs = doE [qtypstmt, genstmt, letStmt lststmt, qualStmt retstmt]- qtypstmt = generator (p "typ") (v "qtyp")- genstmt = generator- (p "f1")- (v "mkMember" `app` ( strE (hsTemplateMemberFunctionName c f <> "_")- `app` v "<>"- `app` v "suffix"- )- `app` v (hsTemplateMemberFunctionNameTH c f)- `app` v "typ"- `app` v "suffix"- )- lststmt = [ pbind (p "lst") (list ([v "f1"])) Nothing ]- retstmt = v "pure" `app` v "lst"------------------------- Template Class -------------------------genTmplInterface :: TemplateClass -> [Decl ()]-genTmplInterface t =- [ mkData rname [mkTBind tp] [] Nothing- , mkNewtype hname [mkTBind tp]- [ qualConDecl Nothing Nothing (conDecl hname [tyapp tyPtr rawtype]) ] Nothing- , mkClass cxEmpty (typeclassNameT t) [mkTBind tp] methods- , mkInstance cxEmpty "FPtr" [ hightype ] fptrbody- , mkInstance cxEmpty "Castable" [ hightype, tyapp tyPtr rawtype ] castBody- ]- where (hname,rname) = hsTemplateClassName t- tp = tclass_param t- fs = tclass_funcs t- rawtype = tyapp (tycon rname) (mkTVar tp)- hightype = tyapp (tycon hname) (mkTVar tp)- sigdecl f = mkFunSig (hsTmplFuncName t f) (functionSignatureT t f)- methods = map (clsDecl . sigdecl) fs- fptrbody = [ insType (tyapp (tycon "Raw") hightype) rawtype- , insDecl (mkBind1 "get_fptr" [pApp (name hname) [mkPVar "ptr"]] (mkVar "ptr") Nothing)- , insDecl (mkBind1 "cast_fptr_to_obj" [] (con hname) Nothing)- ]---genTmplImplementation :: TemplateClass -> [Decl ()]-genTmplImplementation t = concatMap gen (tclass_funcs t)- where- gen f = mkFun nh sig [p "typ", p "suffix"] rhs (Just bstmts)- where nh = hsTmplFuncNameTH t f- nc = ffiTmplFuncName f- sig = tycon "Type" `tyfun` (tycon "String" `tyfun` (tyapp (tycon "Q") (tycon "Exp")))- v = mkVar- p = mkPVar- tp = tclass_param t- prefix = tclass_name t- lit' = strE (prefix<>"_"<>nc<>"_")- lam = lambda [p "n"] ( lit' `app` v "<>" `app` v "n")- rhs = app (v "mkTFunc") (tuple [v "typ", v "suffix", lam, v "tyf"])- sig' = functionSignatureTT t f- bstmts = binds [ mkBind1 "tyf" [mkPVar "n"]- (letE [ pbind (p tp) (v "pure" `app` (v "typ")) Nothing ]- (bracketExp (typeBracket sig')))- Nothing- ]---genTmplInstance :: TemplateClass -> [TemplateFunction] -> [Decl ()]-genTmplInstance t fs = mkFun fname sig [p "qtyp", p "suffix"] rhs Nothing- where tname = tclass_name t- fname = "gen" <> tname <> "InstanceFor"- p = mkPVar- v = mkVar- sig = (tyapp (tycon "Q") (tycon "Type")) `tyfun`- (tycon "String" `tyfun`- (tyapp (tycon "Q") (tylist (tycon "Dec"))))- nfs = zip ([1..] :: [Int]) fs- rhs = doE ( [qtypstmt]- <> map genstmt nfs- <> [letStmt (lststmt nfs), qualStmt retstmt])- qtypstmt = generator (p "typ") (v "qtyp")- genstmt (n,f@TFun {..}) = generator- (p ("f"<>show n))- (v "mkMember" `app` strE (hsTmplFuncName t f)- `app` v (hsTmplFuncNameTH t f)- `app` v "typ"- `app` v "suffix"- )- genstmt (n,f@TFunNew {..}) = generator- (p ("f"<>show n))- (v "mkNew" `app` strE (hsTmplFuncName t f)- `app` v (hsTmplFuncNameTH t f)- `app` v "typ"- `app` v "suffix"- )- genstmt (n,f@TFunDelete) = generator- (p ("f"<>show n))- (v "mkDelete" `app` strE (hsTmplFuncName t f)- `app` v (hsTmplFuncNameTH t f)- `app` v "typ"- `app` v "suffix"- )- lststmt xs = [ pbind (p "lst") (list (map (v . (\n->"f"<>show n) . fst) xs)) Nothing ]- retstmt = v "pure"- `app` list [ v "mkInstance"- `app` list []- `app` (con "AppT"- `app` (v "con" `app` strE (typeclassNameT t))- `app` (v "typ")- )- `app` (v "lst")- ]
− lib/FFICXX/Generate/Code/Primitive.hs
@@ -1,882 +0,0 @@-{-# LANGUAGE RecordWildCards #-}-module FFICXX.Generate.Code.Primitive where--import Control.Monad.Trans.State (runState,put,get)-import Data.Monoid ((<>))-import Language.Haskell.Exts.Syntax (Asst(..),Context,Type(..))----import FFICXX.Generate.Name-import FFICXX.Generate.Type.Class-import FFICXX.Generate.Util-import FFICXX.Generate.Util.HaskellSrcExts--data CFunSig = CFunSig { cArgTypes :: Args- , cRetType :: Types- }--data HsFunSig = HsFunSig { hsSigTypes :: [Type ()]- , hsSigConstraints :: [Asst ()]- }--cvarToStr :: CTypes -> IsConst -> String -> String-cvarToStr ctyp isconst varname = ctypToStr ctyp isconst <> " " <> varname--ctypToStr :: CTypes -> IsConst -> String-ctypToStr ctyp isconst =- let typword = case ctyp of- CTBool -> "bool"- CTChar -> "char"- CTClock -> "clock_t"- CTDouble -> "double"- CTFile -> "FILE"- CTFloat -> "float"- CTFpos -> "fpos_t"- CTInt -> "int"- CTIntMax -> "intmax_t"- CTIntPtr -> "intptr_t"- CTJmpBuf -> "jmp_buf"- CTLLong -> "long long"- CTLong -> "long"- CTPtrdiff -> "ptrdiff_t"- CTSChar -> "sized char"- CTSUSeconds -> "suseconds_t"- CTShort -> "short"- CTSigAtomic -> "sig_atomic_t"- CTSize -> "size_t"- CTTime -> "time_t"- CTUChar -> "unsigned char"- CTUInt -> "unsigned int"- CTUIntMax -> "uintmax_t"- CTUIntPtr -> "uintptr_t"- CTULLong -> "unsigned long long"- CTULong -> "unsigned long"- CTUSeconds -> "useconds_t"- CTUShort -> "unsigned short"- CTWchar -> "wchar_t"- CTInt8 -> "int8_t"- CTInt16 -> "int16_t"- CTInt32 -> "int32_t"- CTInt64 -> "int64_t"- CTUInt8 -> "uint8_t"- CTUInt16 -> "uint16_t"- CTUInt32 -> "uint32_t"- CTUInt64 -> "uint64_t"- CTString -> "char*"- CTVoidStar -> "void*"- CEnum _ type_str -> type_str- CPointer s -> ctypToStr s NoConst <> "*"- CRef s -> ctypToStr s NoConst <> "*"- in case isconst of- Const -> "const" <> " " <> typword- NoConst -> typword--self_ :: Types-self_ = SelfType--cstring_ :: Types-cstring_ = CT CTString Const--cint_ :: Types-cint_ = CT CTInt Const--int_ :: Types-int_ = CT CTInt NoConst--uint_ :: Types-uint_ = CT CTUInt NoConst--ulong_ :: Types-ulong_ = CT CTULong NoConst--long_ :: Types-long_ = CT CTLong NoConst--culong_ :: Types-culong_ = CT CTULong Const--clong_ :: Types-clong_ = CT CTLong Const--cchar_ :: Types-cchar_ = CT CTChar Const--char_ :: Types-char_ = CT CTChar NoConst--cshort_ :: Types-cshort_ = CT CTShort Const--short_ :: Types-short_ = CT CTShort NoConst--cdouble_ :: Types-cdouble_ = CT CTDouble Const--double_ :: Types-double_ = CT CTDouble NoConst--doublep_ :: Types-doublep_ = CT (CPointer CTDouble) NoConst--cfloat_ :: Types-cfloat_ = CT CTFloat Const--float_ :: Types-float_ = CT CTFloat NoConst--bool_ :: Types-bool_ = CT CTBool NoConst--void_ :: Types-void_ = Void--voidp_ :: Types-voidp_ = CT CTVoidStar NoConst--intp_ :: Types-intp_ = CT (CPointer CTInt) NoConst--intref_ :: Types-intref_ = CT (CRef CTInt) NoConst---charpp_ :: Types-charpp_ = CT (CPointer CTString) NoConst--ref_ :: CTypes -> Types-ref_ t = CT (CRef t) NoConst--star_ :: CTypes -> Types-star_ t = CT (CPointer t) NoConst--cstar_ :: CTypes -> Types-cstar_ t = CT (CPointer t) Const--self :: String -> (Types, String)-self var = (self_, var)--voidp :: String -> (Types,String)-voidp var = (voidp_ , var)--cstring :: String -> (Types,String)-cstring var = (cstring_ , var)--cint :: String -> (Types,String)-cint var = (cint_ , var)--int :: String -> (Types,String)-int var = (int_ , var)--uint :: String -> (Types,String)-uint var = (uint_ , var)--long :: String -> (Types,String)-long var = (long_, var)--ulong :: String -> (Types,String)-ulong var = (ulong_ , var)--clong :: String -> (Types,String)-clong var = (clong_, var)--culong :: String -> (Types,String)-culong var = (culong_ , var)--cchar :: String -> (Types,String)-cchar var = (cchar_ , var)--char :: String -> (Types,String)-char var = (char_ , var)--cshort :: String -> (Types,String)-cshort var = (cshort_ , var)--short :: String -> (Types,String)-short var = (short_ , var)--cdouble :: String -> (Types,String)-cdouble var = (cdouble_ , var)--double :: String -> (Types,String)-double var = (double_ , var)--doublep :: String -> (Types,String)-doublep var = (doublep_ , var)--cfloat :: String -> (Types,String)-cfloat var = (float_ , var)--float :: String -> (Types,String)-float var = (float_ , var)--bool :: String -> (Types,String)-bool var = (bool_ , var)--intp :: String -> (Types, String)-intp var = (intp_ , var)--intref :: String -> (Types, String)-intref var = (intref_, var)--charpp :: String -> (Types, String)-charpp var = (charpp_, var)--ref :: CTypes -> String -> (Types,String)-ref t var = (ref_ t, var)--star :: CTypes -> String -> (Types, String)-star t var = (star_ t, var)--cstar :: CTypes -> String -> (Types, String)-cstar t var = (cstar_ t, var)---cppclass_ :: Class -> Types-cppclass_ c = CPT (CPTClass c) NoConst--cppclass :: Class -> String -> (Types, String)-cppclass c vname = ( cppclass_ c, vname)----cppclassconst :: Class -> String -> (Types, String)-cppclassconst c vname = ( CPT (CPTClass c) Const, vname)--cppclassref_ :: Class -> Types-cppclassref_ c = CPT (CPTClassRef c) NoConst--cppclassref :: Class -> String -> (Types, String)-cppclassref c vname = (cppclassref_ c, vname)--cppclasscopy_ :: Class -> Types-cppclasscopy_ c = CPT (CPTClassCopy c) NoConst--cppclasscopy :: Class -> String -> (Types, String)-cppclasscopy c vname = (cppclasscopy_ c, vname)--cppclassmove_ :: Class -> Types-cppclassmove_ c = CPT (CPTClassMove c) NoConst--cppclassmove :: Class -> String -> (Types, String)-cppclassmove c vname = (cppclassmove_ c, vname)---argToString :: (Types,String) -> String-argToString (CT ctyp isconst, varname) = cvarToStr ctyp isconst varname-argToString (SelfType, varname) = "Type ## _p " <> varname-argToString (CPT (CPTClass c) isconst, varname) = case isconst of- Const -> "const_" <> cname <> "_p " <> varname- NoConst -> cname <> "_p " <> varname- where cname = ffiClassName c-argToString (CPT (CPTClassRef c) isconst, varname) = case isconst of- Const -> "const_" <> cname <> "_p " <> varname- NoConst -> cname <> "_p " <> varname- where cname = ffiClassName c-argToString (CPT (CPTClassCopy c) isconst, varname) = case isconst of- Const -> "const_" <> cname <> "_p " <> varname- NoConst -> cname <> "_p " <> varname- where cname = ffiClassName c-argToString (CPT (CPTClassMove c) isconst, varname) = case isconst of- Const -> "const_" <> cname <> "_p " <> varname- NoConst -> cname <> "_p " <> varname- where cname = ffiClassName c-argToString (TemplateApp _, varname) = "void* " <> varname-argToString (TemplateAppRef _, varname) = "void* " <> varname-argToString (TemplateAppMove _, varname) = "void* " <> varname-argToString t = error ("argToString: " <> show t)--argsToString :: Args -> String-argsToString args =- let args' = (SelfType, "p") : args- in intercalateWith conncomma argToString args'--argsToStringNoSelf :: Args -> String-argsToStringNoSelf = intercalateWith conncomma argToString---- TODO: remove this function-argToCallString :: (Types,String) -> String-argToCallString = uncurry castC2Cpp---argsToCallString :: Args -> String-argsToCallString = intercalateWith conncomma argToCallString---- TODO: rename this function by castExpressionFrom/To or something like that.-rettypeToString :: Types -> String-rettypeToString (CT ctyp isconst) = ctypToStr ctyp isconst-rettypeToString Void = "void"-rettypeToString SelfType = "Type ## _p"-rettypeToString (CPT (CPTClass c) _) = ffiClassName c <> "_p"-rettypeToString (CPT (CPTClassRef c) _) = ffiClassName c <> "_p"-rettypeToString (CPT (CPTClassCopy c) _) = ffiClassName c <> "_p"-rettypeToString (CPT (CPTClassMove c) _) = ffiClassName c <> "_p"-rettypeToString (TemplateApp _) = "void*"-rettypeToString (TemplateAppRef _) = "void*"-rettypeToString (TemplateAppMove _) = "void*"-rettypeToString (TemplateType _) = "void*"-rettypeToString (TemplateParam _) = "Type ## _p"-rettypeToString (TemplateParamPointer _) = "Type ## _p"------ TODO: Rewrite this with static_cast-castC2Cpp :: Types -> String -> String-castC2Cpp t e =- case t of- CT (CRef _) _ -> "(*"<> e <> ")"- CPT (CPTClass c) _ -> "to_nonconst<" <> f <> "," <> f <> "_t>(" <> e <> ")"- where f = ffiClassName c- CPT (CPTClassRef c) _ -> "to_nonconstref<" <> f <> "," <> f <> "_t>(*" <> e <> ")"- where f = ffiClassName c- CPT (CPTClassCopy c) _ -> "*(to_nonconst<" <> f <> "," <> f <> "_t>(" <> e <> "))"- where f = ffiClassName c- CPT (CPTClassMove c) _ -> "std::move(to_nonconstref<" <> f <> "," <> f<> "_t>(*" <> e <> "))"- where f = ffiClassName c- TemplateApp p -> "to_nonconst<" <> tapp_CppTypeForParam p <> ",void>(" <> e <> ")"- TemplateAppRef p -> "*( (" <> tapp_CppTypeForParam p <> "*) " <> e <> ")"- TemplateAppMove p -> "std::move(*( (" <> tapp_CppTypeForParam p <> "*) " <> e <> "))"- _ -> e----- TODO: Rewrite this with static_cast--- Merge this with returnCpp after Void and simple type adjustment-castCpp2C :: Types -> String -> String-castCpp2C t e =- case t of- Void -> ""- SelfType -> "to_nonconst<Type ## _t, Type>((Type *)" <> e <> ")"- CT (CRef _) _ -> "&(" <> e <> ")"- CT _ _ -> e- CPT (CPTClass c) _ -> "to_nonconst<" <> f <> "_t," <> f <> ">((" <> f <> "*)" <> e <> ")"- where f = ffiClassName c- CPT (CPTClassRef c) _ -> "to_nonconst<" <> f <> "_t," <> f <> ">(&(" <> e <> "))"- where f = ffiClassName c- CPT (CPTClassCopy c) _ -> "to_nonconst<" <> f <> "_t," <> f <> ">(new " <> f <> "(" <> e <> "))"- where f = ffiClassName c- CPT (CPTClassMove c) _ -> "std::move(to_nonconst<" <> f <> "_t," <> f <>">(&(" <> e <> ")))"- where f = ffiClassName c- TemplateApp _ -> error "castCpp2C: TemplateApp"- -- g <> "* r = new " <> g <> "(" <> e <> "); "- -- <> "return (static_cast<void*>(r));"- TemplateAppRef _ -> error "castCpp2C: TemplateAppRef"- -- g <> "* r = new " <> g <> "(" <> e <> "); "- -- <> "return (static_cast<void*>(r));"- TemplateAppMove _ -> error "castCpp2C: TemplateAppMove"- TemplateType _ -> error "castCpp2C: TemplateType"- TemplateParam _ -> error "castCpp2C: TemplateParam"- -- if b then e- -- else "to_nonconst<Type ## _t, Type>((Type *)&(" <> e <> "))"- TemplateParamPointer _ -> error "castCpp2C: TemplateParamPointer"- -- if b then "(" <> callstr <> ");"- -- else "to_nonconst<Type ## _t, Type>(" <> e <> ") ;"----tmplArgToString :: Bool -> TemplateClass -> (Types,String) -> String-tmplArgToString _ _ (CT ctyp isconst, varname) = cvarToStr ctyp isconst varname-tmplArgToString _ t (SelfType, varname) = tclass_oname t <> "* " <> varname-tmplArgToString _ _ (CPT (CPTClass c) isconst, varname) =- case isconst of- Const -> "const_" <> ffiClassName c <> "_p " <> varname- NoConst -> ffiClassName c <> "_p " <> varname-tmplArgToString _ _ (CPT (CPTClassRef c) isconst, varname) =- case isconst of- Const -> "const_" <> ffiClassName c <> "_p " <> varname- NoConst -> ffiClassName c <> "_p " <> varname-tmplArgToString _ _ (CPT (CPTClassMove c) isconst, varname) =- case isconst of- Const -> "const_" <> ffiClassName c <> "_p " <> varname- NoConst -> ffiClassName c <> "_p " <> varname-tmplArgToString _ _ (TemplateApp _, v) = "void* " <> v-tmplArgToString _ _ (TemplateAppRef _, v) = "void* " <> v-tmplArgToString _ _ (TemplateAppMove _, v) = "void* " <> v-tmplArgToString _ _ (TemplateType _, v) = "void* " <> v-tmplArgToString True _ (TemplateParam _,v) = "Type " <> v-tmplArgToString False _ (TemplateParam _,v) = "Type ## _p " <> v-tmplArgToString True _ (TemplateParamPointer _,v) = "Type " <> v-tmplArgToString False _ (TemplateParamPointer _,v) = "Type ## _p " <> v-tmplArgToString _ _ _ = error "tmplArgToString: undefined"--tmplAllArgsToString :: Bool- -> Selfness- -> TemplateClass- -> Args- -> String-tmplAllArgsToString b s t args =- let args' = case s of- Self -> (TemplateType t, "p") : args- NoSelf -> args- in intercalateWith conncomma (tmplArgToString b t) args'----tmplArgToCallString- :: Bool -- ^ is primitive type?- -> (Types,String)- -> String-tmplArgToCallString _ (CPT (CPTClass c) _,varname) =- -- TODO: Rewrite this with static_cast.- "to_nonconst<"<>str<>","<>str<>"_t>("<>varname<>")" where str = ffiClassName c-tmplArgToCallString _ (CPT (CPTClassRef c) _,varname) =- -- TODO: Rewrite this with static_cast.- "to_nonconstref<"<>str<>","<>str<>"_t>(*"<>varname<>")" where str = ffiClassName c-tmplArgToCallString _ (CPT (CPTClassMove c) _,varname) =- -- TODO: Rewrite this with static_cast.- "std::move(to_nonconstref<"<>str<>","<>str<>"_t>(*"<>varname<>"))" where str = ffiClassName c-tmplArgToCallString _ (CT (CRef _) _,varname) = "(*"<> varname<> ")"-tmplArgToCallString _ (TemplateApp x,varname) =- case tapp_tparam x of- TArg_TypeParam p -> "static_cast<" <> tclass_oname (tapp_tclass x) <> "<Type>*>(" <> varname <> ")"- _ -> -- TODO: Implement this.- error "tmplArgToCallString: TemplateApp"-tmplArgToCallString _ (TemplateAppRef x,varname) =- case tapp_tparam x of- TArg_TypeParam p -> "*" <> "(static_cast<" <> tclass_oname (tapp_tclass x) <> "<Type>*>(" <> varname <> "))"- _ -> -- TODO: Implement this.- error "tmplArgToCallString: TemplateAppRef"-tmplArgToCallString _ (TemplateAppMove x,varname) =- case tapp_tparam x of- TArg_TypeParam p -> "std::move(*" <> "(static_cast<" <> tclass_oname (tapp_tclass x) <> "<Type>*>(" <> varname <> ")))"- _ -> -- TODO: Implement this.- error "tmplArgToCallString: TemplateAppMove"-tmplArgToCallString b (TemplateParam _,varname) =- case b of- True -> varname- False -> "*(to_nonconst<Type,Type ## _t>(" <> varname <> "))"-tmplArgToCallString b (TemplateParamPointer _,varname) =- case b of- True -> varname- False -> "to_nonconst<Type,Type ## _t>(" <> varname <> ")"-tmplArgToCallString _ (_,varname) = varname--tmplAllArgsToCallString- :: Bool -- ^ is primitive type?- -> Args- -> String-tmplAllArgsToCallString b = intercalateWith conncomma (tmplArgToCallString b)----tmplRetTypeToString :: Bool -- ^ is primitive type?- -> Types- -> String-tmplRetTypeToString _ (CT ctyp isconst) = ctypToStr ctyp isconst-tmplRetTypeToString _ Void = "void"-tmplRetTypeToString _ SelfType = "void*"-tmplRetTypeToString _ (CPT (CPTClass c) _) = ffiClassName c <> "_p"-tmplRetTypeToString _ (CPT (CPTClassRef c) _) = ffiClassName c <> "_p"-tmplRetTypeToString _ (CPT (CPTClassCopy c) _) = ffiClassName c <> "_p"-tmplRetTypeToString _ (CPT (CPTClassMove c) _) = ffiClassName c <> "_p"-tmplRetTypeToString _ (TemplateApp _) = "void*"-tmplRetTypeToString _ (TemplateAppRef _) = "void*"-tmplRetTypeToString _ (TemplateAppMove _) = "void*"-tmplRetTypeToString _ (TemplateType _) = "void*"-tmplRetTypeToString b (TemplateParam _) = if b then "Type" else "Type ## _p"-tmplRetTypeToString b (TemplateParamPointer _) = if b then "Type" else "Type ## _p"-------- ------------------------------ Template Member Function ----- -----------------------------tmplMemFuncArgToString :: Class -> (Types,String) -> String-tmplMemFuncArgToString _ (CT ctyp isconst, varname) = cvarToStr ctyp isconst varname-tmplMemFuncArgToString c (SelfType, varname) = ffiClassName c <> "_p " <> varname-tmplMemFuncArgToString _ (CPT (CPTClass c) isconst, varname) =- case isconst of- Const -> "const_" <> ffiClassName c <> "_p " <> varname- NoConst -> ffiClassName c <> "_p " <> varname-tmplMemFuncArgToString _ (CPT (CPTClassRef c) isconst, varname) =- case isconst of- Const -> "const_" <> ffiClassName c <> "_p " <> varname- NoConst -> ffiClassName c <> "_p " <> varname-tmplMemFuncArgToString _ (CPT (CPTClassMove c) isconst, varname) =- case isconst of- Const -> "const_" <> ffiClassName c <> "_p " <> varname- NoConst -> ffiClassName c <> "_p " <> varname-tmplMemFuncArgToString _ (TemplateApp _, v) = "void* " <> v-tmplMemFuncArgToString _ (TemplateAppRef _, v) = "void* " <> v-tmplMemFuncArgToString _ (TemplateAppMove _, v) = "void* " <> v-tmplMemFuncArgToString _ (TemplateType _, v) = "void* " <> v-tmplMemFuncArgToString _ (TemplateParam _,v) = "Type##_p " <> v-tmplMemFuncArgToString _ (TemplateParamPointer _,v) = "Type##_p " <> v-tmplMemFuncArgToString _ _ = error "tmplMemFuncArgToString: undefined"---tmplMemFuncRetTypeToString :: Class -> Types -> String-tmplMemFuncRetTypeToString _ (CT ctyp isconst) = ctypToStr ctyp isconst-tmplMemFuncRetTypeToString _ Void = "void"-tmplMemFuncRetTypeToString c SelfType = ffiClassName c <> "_p"-tmplMemFuncRetTypeToString _ (CPT (CPTClass c) _) = ffiClassName c <> "_p"-tmplMemFuncRetTypeToString _ (CPT (CPTClassRef c) _) = ffiClassName c <> "_p"-tmplMemFuncRetTypeToString _ (CPT (CPTClassCopy c) _) = ffiClassName c <> "_p"-tmplMemFuncRetTypeToString _ (CPT (CPTClassMove c) _) = ffiClassName c <> "_p"-tmplMemFuncRetTypeToString _ (TemplateApp _) = "void*"-tmplMemFuncRetTypeToString _ (TemplateAppRef _) = "void*"-tmplMemFuncRetTypeToString _ (TemplateAppMove _) = "void*"-tmplMemFuncRetTypeToString _ (TemplateType _) = "void*"-tmplMemFuncRetTypeToString _ (TemplateParam _) = "Type##_p"-tmplMemFuncRetTypeToString _ (TemplateParamPointer _) = "Type##_p"------ |-convertC2HS :: CTypes -> Type ()-convertC2HS CTBool = tycon "CBool"-convertC2HS CTChar = tycon "CChar"-convertC2HS CTClock = tycon "CClock"-convertC2HS CTDouble = tycon "CDouble"-convertC2HS CTFile = tycon "CFile"-convertC2HS CTFloat = tycon "CFloat"-convertC2HS CTFpos = tycon "CFpos"-convertC2HS CTInt = tycon "CInt"-convertC2HS CTIntMax = tycon "CIntMax"-convertC2HS CTIntPtr = tycon "CIntPtr"-convertC2HS CTJmpBuf = tycon "CJmpBuf"-convertC2HS CTLLong = tycon "CLLong"-convertC2HS CTLong = tycon "CLong"-convertC2HS CTPtrdiff = tycon "CPtrdiff"-convertC2HS CTSChar = tycon "CSChar"-convertC2HS CTSUSeconds = tycon "CSUSeconds"-convertC2HS CTShort = tycon "CShort"-convertC2HS CTSigAtomic = tycon "CSigAtomic"-convertC2HS CTSize = tycon "CSize"-convertC2HS CTTime = tycon "CTime"-convertC2HS CTUChar = tycon "CUChar"-convertC2HS CTUInt = tycon "CUInt"-convertC2HS CTUIntMax = tycon "CUIntMax"-convertC2HS CTUIntPtr = tycon "CUIntPtr"-convertC2HS CTULLong = tycon "CULLong"-convertC2HS CTULong = tycon "CULong"-convertC2HS CTUSeconds = tycon "CUSeconds"-convertC2HS CTUShort = tycon "CUShort"-convertC2HS CTWchar = tycon "CWchar"-convertC2HS CTInt8 = tycon "Int8"-convertC2HS CTInt16 = tycon "Int16"-convertC2HS CTInt32 = tycon "Int32"-convertC2HS CTInt64 = tycon "Int64"-convertC2HS CTUInt8 = tycon "Word8"-convertC2HS CTUInt16 = tycon "Word16"-convertC2HS CTUInt32 = tycon "Word32"-convertC2HS CTUInt64 = tycon "Word64"-convertC2HS CTString = tycon "CString"-convertC2HS CTVoidStar = tyapp (tycon "Ptr") unit_tycon-convertC2HS (CEnum t _) = convertC2HS t-convertC2HS (CPointer t) = tyapp (tycon "Ptr") (convertC2HS t)-convertC2HS (CRef t) = tyapp (tycon "Ptr") (convertC2HS t)---- |-convertCpp2HS :: Maybe Class -> Types -> Type ()-convertCpp2HS _c Void = unit_tycon-convertCpp2HS (Just c) SelfType = tycon ((fst.hsClassName) c)-convertCpp2HS Nothing SelfType = error "convertCpp2HS : SelfType but no class "-convertCpp2HS _c (CT t _) = convertC2HS t-convertCpp2HS _c (CPT (CPTClass c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS _c (CPT (CPTClassRef c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS _c (CPT (CPTClassCopy c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS _c (CPT (CPTClassMove c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS _c (TemplateApp x) = tyapp- (tycon (tclass_name (tapp_tclass x)))- (tycon (hsClassNameForTArg (tapp_tparam x)))-convertCpp2HS _c (TemplateAppRef x) = tyapp- (tycon (tclass_name (tapp_tclass x)))- (tycon (hsClassNameForTArg (tapp_tparam x)))-convertCpp2HS _c (TemplateAppMove x) = tyapp- (tycon (tclass_name (tapp_tclass x)))- (tycon (hsClassNameForTArg (tapp_tparam x)))-convertCpp2HS _c (TemplateType t) = tyapp- (tycon (tclass_name t))- (mkTVar (tclass_param t))-convertCpp2HS _c (TemplateParam p) = mkTVar p-convertCpp2HS _c (TemplateParamPointer p) = mkTVar p---- |-convertCpp2HS4Tmpl- :: Type () -- ^ self- -> Maybe Class- -> Type () -- ^ type paramemter splice- -> Types- -> Type ()-convertCpp2HS4Tmpl _ _c _ Void = unit_tycon-convertCpp2HS4Tmpl _ (Just c) _ SelfType = tycon ((fst.hsClassName) c)-convertCpp2HS4Tmpl _ Nothing _ SelfType = error "convertCpp2HS4Tmpl : SelfType but no class "-convertCpp2HS4Tmpl _ _c _ (CT t _) = convertC2HS t-convertCpp2HS4Tmpl _ _c _ (CPT (CPTClass c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS4Tmpl _ _c _ (CPT (CPTClassRef c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS4Tmpl _ _c _ (CPT (CPTClassCopy c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS4Tmpl _ _c _ (CPT (CPTClassMove c') _) = (tycon . fst . hsClassName) c'-convertCpp2HS4Tmpl e c s x@(TemplateApp p) =- case tapp_tparam p of- TArg_TypeParam _ -> let t = tapp_tclass p- (hname,_) = hsTemplateClassName t- in tyapp (tycon hname) s- _ -> convertCpp2HS c x-convertCpp2HS4Tmpl e c s x@(TemplateAppRef p) =- case tapp_tparam p of- TArg_TypeParam _ -> let t = tapp_tclass p- (hname,_) = hsTemplateClassName t- in tyapp (tycon hname) s- _ -> convertCpp2HS c x-convertCpp2HS4Tmpl e c s x@(TemplateAppMove p) =- case tapp_tparam p of- TArg_TypeParam _ -> let t = tapp_tclass p- (hname,_) = hsTemplateClassName t- in tyapp (tycon hname) s- _ -> convertCpp2HS c x-convertCpp2HS4Tmpl e _c _ (TemplateType _) = e-convertCpp2HS4Tmpl _ _c s (TemplateParam _) = s-convertCpp2HS4Tmpl _ _c s (TemplateParamPointer _) = s---hsFuncXformer :: Function -> String-hsFuncXformer func@(Constructor _ _) = let len = length (genericFuncArgs func)- in if len > 0- then "xform" <> show (len - 1)- else "xformnull"-hsFuncXformer func@(Static _ _ _ _) =- let len = length (genericFuncArgs func)- in if len > 0- then "xform" <> show (len - 1)- else "xformnull"-hsFuncXformer func = let len = length (genericFuncArgs func)- in "xform" <> show len----classConstraints :: Class -> Context ()-classConstraints = cxTuple . map ((\n->classA (unqual n) [mkTVar "a"]) . typeclassName) . class_parents--extractArgRetTypes- :: Maybe Class -- ^ class (Nothing for top-level function)- -> Bool -- ^ is virtual function?- -> CFunSig -- ^ C type signature information for a given function -- (Args,Types) -- ^ (argument types, return type) of a given function- -> HsFunSig -- ^ Haskell type signature information for the function -- ([Type ()],[Asst ()]) -- ^ (types, class constraints)-extractArgRetTypes mc isvirtual (CFunSig args ret) =- let (typs,s) = flip runState ([],(0 :: Int)) $ do- as <- mapM (mktyp . fst) args- r <- case ret of- SelfType -> case mc of- Nothing -> error "extractArgRetTypes: SelfType return but no class"- Just c -> if isvirtual then return (mkTVar "a") else return $ tycon ((fst.hsClassName) c)- x -> (return . convertCpp2HS Nothing) x- return (as ++ [tyapp (tycon "IO") r])- in HsFunSig { hsSigTypes = typs- , hsSigConstraints = fst s- }- where addclass c = do- (ctxts,n) <- get- let cname = (fst.hsClassName) c- iname = typeclassNameFromStr cname- tvar = mkTVar ('c' : show n)- ctxt1 = classA (unqual iname) [tvar]- ctxt2 = classA (unqual "FPtr") [tvar]- put (ctxt1:ctxt2:ctxts,n+1)- return tvar- addstring = do- (ctxts,n) <- get- let tvar = mkTVar ('c' : show n)- ctxt = classA (unqual "Castable") [tvar,tycon "CString"]- put (ctxt:ctxts,n+1)- return tvar-- mktyp typ =- case typ of- SelfType -> return (mkTVar "a")- CT CTString Const -> addstring- CT _ _ -> return $ convertCpp2HS Nothing typ- CPT (CPTClass c') _ -> addclass c'- CPT (CPTClassRef c') _ -> addclass c'- CPT (CPTClassCopy c') _ -> addclass c'- CPT (CPTClassMove c') _ -> addclass c'- -- it is not clear whether the following is okay or not.- (TemplateApp x) -> pure $- tyapp- (tycon (tclass_name (tapp_tclass x)))- (tycon (hsClassNameForTArg (tapp_tparam x)))- (TemplateAppRef x) -> pure $- tyapp- (tycon (tclass_name (tapp_tclass x)))- (tycon (hsClassNameForTArg (tapp_tparam x)))- (TemplateAppMove x)-> pure $- tyapp- (tycon (tclass_name (tapp_tclass x)))- (tycon (hsClassNameForTArg (tapp_tparam x)))- (TemplateType t) -> pure $- tyapp- (tycon (tclass_name t))- (mkTVar (tclass_param t))- (TemplateParam p) -> return (mkTVar p)- Void -> return unit_tycon- _ -> error ("No such c type : " <> show typ)--functionSignature :: Class -> Function -> Type ()-functionSignature c f =- let HsFunSig typs assts = extractArgRetTypes- (Just c)- (isVirtualFunc f)- (CFunSig (genericFuncArgs f) (genericFuncRet f))- ctxt = cxTuple assts- arg0- | isVirtualFunc f = (mkTVar "a" :)- | isNonVirtualFunc f = (mkTVar (fst (hsClassName c)) :)- | otherwise = id- in TyForall () Nothing (Just ctxt) (foldr1 tyfun (arg0 typs))--functionSignatureT :: TemplateClass -> TemplateFunction -> Type ()-functionSignatureT t TFun {..} =- let (hname,_) = hsTemplateClassName t- tp = tclass_param t- ctyp = convertCpp2HS Nothing tfun_ret- arg0 = (tyapp (tycon hname) (mkTVar tp) :)- lst = arg0 (map (convertCpp2HS Nothing . fst) tfun_args)- in foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])-functionSignatureT t TFunNew {..} =- let ctyp = convertCpp2HS Nothing (TemplateType t)- lst = map (convertCpp2HS Nothing . fst) tfun_new_args- in foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])-functionSignatureT t TFunDelete =- let ctyp = convertCpp2HS Nothing (TemplateType t)- in ctyp `tyfun` (tyapp (tycon "IO") unit_tycon)------ TODO: rename this and combine this with functionSignatureTMF-functionSignatureTT :: TemplateClass -> TemplateFunction -> Type ()-functionSignatureTT t f = foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])- where- (hname,_) = hsTemplateClassName t- ctyp = case f of- TFun {..} -> convertCpp2HS4Tmpl e Nothing spl tfun_ret- TFunNew {..} -> convertCpp2HS4Tmpl e Nothing spl (TemplateType t)- TFunDelete -> unit_tycon- e = tyapp (tycon hname) spl- spl = tySplice (parenSplice (mkVar (tclass_param t)))- lst =- case f of- TFun {..} -> e : map (convertCpp2HS4Tmpl e Nothing spl . fst) tfun_args- TFunNew {..} -> map (convertCpp2HS4Tmpl e Nothing spl . fst) tfun_new_args- TFunDelete -> [e]---- TODO: rename this and combine this with functionSignatureTT-functionSignatureTMF :: Class -> TemplateMemberFunction -> Type ()-functionSignatureTMF c f = foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])- where- ctyp = convertCpp2HS4Tmpl e Nothing spl (tmf_ret f)- e = tycon (fst (hsClassName c))- spl = tySplice (parenSplice (mkVar (tmf_param f)))- lst = e : map (convertCpp2HS4Tmpl e Nothing spl . fst) (tmf_args f)---accessorCFunSig :: Types -> Accessor -> CFunSig-accessorCFunSig typ Getter = CFunSig [] typ-accessorCFunSig typ Setter = CFunSig [(typ,"x")] Void---accessorSignature :: Class -> Variable -> Accessor -> Type ()-accessorSignature c v accessor =- let csig = accessorCFunSig (var_type v) accessor- HsFunSig typs assts = extractArgRetTypes (Just c) False csig- ctxt = cxTuple assts- arg0 = (mkTVar (fst (hsClassName c)) :)- in TyForall () Nothing (Just ctxt) (foldr1 tyfun (arg0 typs))----- | this is for FFI type.-hsFFIFuncTyp :: Maybe (Selfness, Class) -> CFunSig -> Type ()-hsFFIFuncTyp msc (CFunSig args ret) =- foldr1 tyfun $ case msc of- Nothing -> argtyps <> [tyapp (tycon "IO") rettyp]- Just (Self,_) -> selftyp: argtyps <> [tyapp (tycon "IO") rettyp]- Just (NoSelf,_) -> argtyps <> [tyapp (tycon "IO") rettyp]- where argtyps :: [Type ()]- argtyps = map (hsargtype . fst) args- rettyp :: Type ()- rettyp = hsrettype ret- selftyp = case msc of- Just (_,c) -> tyapp tyPtr (tycon (snd (hsClassName c)))- Nothing -> error "hsFFIFuncTyp: no self for top level function"- hsargtype :: Types -> Type ()- hsargtype (CT ctype _) = convertC2HS ctype- hsargtype (CPT (CPTClass d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsargtype (CPT (CPTClassRef d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsargtype (CPT (CPTClassMove d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsargtype (CPT (CPTClassCopy d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsargtype (TemplateApp x) = tyapp- tyPtr- (tyapp- (tycon rawname)- (tycon (hsClassNameForTArg (tapp_tparam x))))- where rawname = snd (hsTemplateClassName (tapp_tclass x))- hsargtype (TemplateAppRef x) = tyapp- tyPtr- (tyapp- (tycon rawname)- (tycon (hsClassNameForTArg (tapp_tparam x))))- where rawname = snd (hsTemplateClassName (tapp_tclass x))- hsargtype (TemplateAppMove x)= tyapp- tyPtr- (tyapp- (tycon rawname)- (tycon (hsClassNameForTArg (tapp_tparam x))))- where rawname = snd (hsTemplateClassName (tapp_tclass x))- hsargtype (TemplateType t) = tyapp tyPtr (tyapp (tycon rawname) (mkTVar (tclass_param t)))- where rawname = snd (hsTemplateClassName t)- hsargtype (TemplateParam p) = mkTVar p- hsargtype SelfType = selftyp- hsargtype _ = error "hsFuncTyp: undefined hsargtype"- ---------------------------------------------------------- hsrettype Void = unit_tycon- hsrettype SelfType = selftyp- hsrettype (CT ctype _) = convertC2HS ctype- hsrettype (CPT (CPTClass d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsrettype (CPT (CPTClassRef d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsrettype (CPT (CPTClassCopy d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsrettype (CPT (CPTClassMove d) _) = tyapp tyPtr (tycon rawname)- where rawname = snd (hsClassName d)- hsrettype (TemplateApp x) = tyapp- tyPtr- (tyapp- (tycon rawname)- (tycon (hsClassNameForTArg (tapp_tparam x))))- where rawname = snd (hsTemplateClassName (tapp_tclass x))- hsrettype (TemplateAppRef x) = tyapp- tyPtr- (tyapp- (tycon rawname)- (tycon (hsClassNameForTArg (tapp_tparam x))))- where rawname = snd (hsTemplateClassName (tapp_tclass x))- hsrettype (TemplateAppMove x)= tyapp- tyPtr- (tyapp- (tycon rawname)- (tycon (hsClassNameForTArg (tapp_tparam x))))- where rawname = snd (hsTemplateClassName (tapp_tclass x))- hsrettype (TemplateType t) = tyapp tyPtr (tyapp (tycon rawname) (mkTVar (tclass_param t)))- where rawname = snd (hsTemplateClassName t)- hsrettype (TemplateParam p) = mkTVar p- hsrettype (TemplateParamPointer p) = mkTVar p----genericFuncRet :: Function -> Types-genericFuncRet f =- case f of- Constructor _ _ -> self_- Virtual t _ _ _ -> t- NonVirtual t _ _ _-> t- Static t _ _ _ -> t- Destructor _ -> void_--genericFuncArgs :: Function -> Args-genericFuncArgs (Destructor _) = []-genericFuncArgs f = func_args f
− lib/FFICXX/Generate/Config.hs
@@ -1,39 +0,0 @@--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Config--- Copyright : (c) 2011-2019 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC------------------------------------------------------------------------------------module FFICXX.Generate.Config where--import FFICXX.Generate.Type.Cabal ( Cabal )-import FFICXX.Generate.Type.Class ( Class, TemplateClass, TopLevelFunction )-import FFICXX.Generate.Type.Config ( ModuleUnitMap(..) )-import FFICXX.Generate.Type.PackageInterface ( HeaderName )---data FFICXXConfig = FFICXXConfig {- fficxxconfig_workingDir :: FilePath- , fficxxconfig_installBaseDir :: FilePath- , fficxxconfig_staticFileDir :: FilePath- } deriving Show--data SimpleBuilderConfig =- SimpleBuilderConfig {- sbcTopModule :: String- , sbcModUnitMap :: ModuleUnitMap- , sbcCabal :: Cabal- , sbcClasses :: [Class]- , sbcTopLevels :: [TopLevelFunction]- , sbcTemplates :: [(TemplateClass,HeaderName)]- , sbcExtraLibs :: [String]- , sbcExtraDeps :: [(String,[String])]- , sbcStaticFiles :: [String]- }
− lib/FFICXX/Generate/ContentMaker.hs
@@ -1,485 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE OverloadedStrings #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.ContentMaker--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.ContentMaker where--import Control.Lens ((&),(.~),at)-import Control.Monad.Trans.Reader-import Data.Char (toUpper)-import Data.Either (rights)-import Data.Function (on)-import qualified Data.Map as M-import Data.Monoid ((<>))-import Data.List (intercalate,nub,nubBy)-import Data.List.Split (splitOn)-import Data.Maybe-import Data.Text (Text)-import Language.Haskell.Exts.Syntax (Module(..),Decl(..))-import System.FilePath----import FFICXX.Generate.Code.Cpp-import FFICXX.Generate.Code.HsCast (genHsFrontInstCastable- ,genHsFrontInstCastableSelf)-import FFICXX.Generate.Code.HsFFI (genHsFFI- ,genImportInFFI- ,genTopLevelFuncFFI)-import FFICXX.Generate.Code.HsFrontEnd-import FFICXX.Generate.Code.HsTemplate (genTemplateMemberFunctions- ,genTmplInstance- ,genTmplInterface- ,genTmplImplementation- )-import FFICXX.Generate.Dependency-import FFICXX.Generate.Name (ffiClassName,hsClassName- ,hsFrontNameForTopLevelFunction)-import FFICXX.Generate.Type.Annotate-import FFICXX.Generate.Type.Class-import FFICXX.Generate.Type.Module-import FFICXX.Generate.Type.PackageInterface (ClassName(..),HeaderName(..)- ,Namespace(..)- ,PackageInterface,PackageName(..)- ,TypeMacro(..))-import FFICXX.Generate.Util-import FFICXX.Generate.Util.HaskellSrcExts------srcDir :: FilePath -> FilePath-srcDir installbasedir = installbasedir </> "src"--csrcDir :: FilePath -> FilePath-csrcDir installbasedir = installbasedir </> "csrc"------ common function for daughter---- |-mkGlobal :: [Class] -> ClassGlobal-mkGlobal = ClassGlobal <$> mkDaughterSelfMap <*> mkDaughterMap----- |-buildDaughterDef :: ((String,[Class]) -> String)- -> DaughterMap- -> String-buildDaughterDef f m =- let lst = M.toList m- f' (x,xs) = f (x,filter (not.isAbstractClass) xs)- in (concatMap f' lst)---- |-buildParentDef :: ((Class,Class)->String) -> Class -> String-buildParentDef f cls = g (class_allparents cls,cls)- where g (ps,c) = concatMap (\p -> f (p,c)) ps---- |-mkProtectedFunctionList :: Class -> String-mkProtectedFunctionList c =- (unlines- . map (\x->"#define IS_" <> class_name c <> "_" <> x <> "_PROTECTED ()")- . unProtected . class_protected) c---- |-buildTypeDeclHeader :: TypeMacro -- ^ typemacro- -> [Class]- -> String-buildTypeDeclHeader (TypMcro typemacro) classes =- let typeDeclBodyStr = intercalateWith connRet2 (genCppHeaderMacroType) classes- in subst- "#ifdef __cplusplus\n\- \extern \"C\" { \n\- \#endif\n\- \\n\- \#ifndef $typemacro\n\- \#define $typemacro\n\- \\n\- \$typeDeclBody\n\- \\n\- \#endif // $typemacro\n\- \\n\- \#ifdef __cplusplus\n\- \}\n\- \#endif\n"- (context [ ("typeDeclBody", typeDeclBodyStr )- , ("typemacro" , typemacro ) ])----declarationTemplate :: Text-declarationTemplate =- "#ifdef __cplusplus\n\- \extern \"C\" { \n\- \#endif\n\- \\n\- \#ifndef $typemacro\n\- \#define $typemacro\n\- \\n\- \#include \"${cprefix}Type.h\"\n\- \ // \n\- \$declarationheader\n\- \ // \n\- \$declarationbody\n\- \\n\- \#endif // $typemacro\n\- \\n\- \#ifdef __cplusplus\n\- \}\n\- \#endif\n"---- |-buildDeclHeader :: TypeMacro -- ^ typemacro prefix- -> String -- ^ C prefix- -> ClassImportHeader- -> String-buildDeclHeader (TypMcro typemacroprefix) cprefix header =- let classes = [cihClass header]- aclass = cihClass header- typemacrostr = typemacroprefix <> ffiClassName aclass <> "__"- declHeaderStr = intercalateWith- connRet- (\x->"#include \""<>x<>"\"")- (map unHdrName (cihIncludedHPkgHeadersInH header))- declDefStr = intercalateWith connRet2 genCppHeaderMacroVirtual classes- `connRet2`- intercalateWith connRet genCppHeaderMacroNonVirtual classes- `connRet2`- intercalateWith connRet genCppHeaderMacroAccessor classes- `connRet2`- intercalateWith connRet2 genCppDefMacroVirtual classes- `connRet2`- intercalateWith connRet2 genCppDefMacroNonVirtual classes- `connRet2`- intercalateWith connRet2 genCppDefMacroAccessor classes- `connRet2`- flip (intercalateWith connRet2) classes- (\c -> intercalateWith connRet2- (genCppDefMacroTemplateMemberFunction c)- (class_tmpl_funcs c)- )- classDeclsStr = -- NOTE: Deletable is treated specially.- -- TODO: We had better make it as a separate constructor in Class.- if (fst.hsClassName) aclass /= "Deletable"- then buildParentDef genCppHeaderInstVirtual aclass- `connRet2`- genCppHeaderInstVirtual (aclass, aclass)- `connRet2`- intercalateWith connRet genCppHeaderInstNonVirtual classes- `connRet2`- intercalateWith connRet genCppHeaderInstAccessor classes- else ""- declBodyStr = declDefStr- `connRet2`- classDeclsStr- in subst declarationTemplate- (context [ ("typemacro" , typemacrostr )- , ("cprefix" , cprefix )- , ("declarationheader", declHeaderStr )- , ("declarationbody" , declBodyStr ) ])---definitionTemplate :: Text-definitionTemplate =- "#include<MacroPatternMatch.h>\n\- \$header\n\- \\n\- \$namespace\n\- \\n\- \$alias\n\- \\n\- \#define CHECKPROTECT(x,y) IS_PAREN(IS_ ## x ## _ ## y ## _PROTECTED)\n\- \\n\- \#define TYPECASTMETHOD(cname,mname,oname) \\\n\- \ IIF( CHECKPROTECT(cname,mname) ) ( \\\n\- \ (to_nonconst<oname,cname ## _t>), \\\n\- \ (to_nonconst<cname,cname ## _t>) )\n\- \\n\- \$cppbody\n"----- |-buildDefMain :: ClassImportHeader- -> String-buildDefMain cih =- let classes = [cihClass cih]- headerStr = genAllCppHeaderInclude cih <> "\n#include \"" <> (unHdrName (cihSelfHeader cih)) <> "\""- namespaceStr = (concatMap (\x->"using namespace " <> unNamespace x <> ";\n") . cihNamespace) cih- aclass = cihClass cih- aliasStr = intercalate "\n" $- mapMaybe typedefstmt $- aclass : rights (cihImportedClasses cih)- where typedefstmt c = let n1 = class_name c- n2 = ffiClassName c- in if n1 == n2- then Nothing- else Just ("typedef " <> n1 <> " " <> n2 <> ";")-- cppBody = mkProtectedFunctionList (cihClass cih)- `connRet`- buildParentDef genCppDefInstVirtual (cihClass cih)- `connRet`- if isAbstractClass aclass- then ""- else genCppDefInstVirtual (aclass, aclass)- `connRet`- intercalateWith connRet genCppDefInstNonVirtual classes- `connRet`- intercalateWith connRet genCppDefInstAccessor classes- in subst definitionTemplate (context ([ ("header" , headerStr )- , ("alias" , aliasStr )- , ("namespace", namespaceStr )- , ("cppbody" , cppBody ) ]))---- |-buildTopLevelHeader :: TypeMacro -- ^ typemacro prefix- -> String -- ^ C prefix- -> TopLevelImportHeader- -> String-buildTopLevelHeader (TypMcro typemacroprefix) cprefix tih =- let typemacrostr = typemacroprefix <> "TOPLEVEL" <> "__"- declHeaderStr = intercalateWith connRet (\x->"#include \""<>x<>"\"") $- map unHdrName $- map cihSelfHeader (tihClassDep tih)- ++ tihExtraHeadersInH tih- declBodyStr = intercalateWith connRet genTopLevelFuncCppHeader (tihFuncs tih)- in subst declarationTemplate (context [ ("typemacro" , typemacrostr )- , ("cprefix" , cprefix )- , ("declarationheader", declHeaderStr )- , ("declarationbody" , declBodyStr ) ])---- |-buildTopLevelCppDef :: TopLevelImportHeader -> String-buildTopLevelCppDef tih =- let cihs = tihClassDep tih- extclasses = tihExtraClassDep tih- declHeaderStr = "#include \"" <> tihHeaderFileName tih <.> "h" <> "\""- `connRet2`- (intercalate "\n" (nub (map genAllCppHeaderInclude cihs)))- `connRet2`- otherHeaders- otherHeaders =- intercalateWith connRet (\x->"#include \""<>x<>"\"") $- map unHdrName $- map cihSelfHeader cihs- ++ tihExtraHeadersInCPP tih-- allns = nubBy ((==) `on` unNamespace) ((tihClassDep tih >>= cihNamespace) ++ tihNamespaces tih)-- namespaceStr = do ns <- allns- ("using namespace " <> unNamespace ns <> ";\n")- aliasStr = intercalate "\n" $- mapMaybe typedefstmt $- rights (concatMap cihImportedClasses cihs ++ extclasses)- where typedefstmt c = let n1 = class_name c- n2 = ffiClassName c- in if n1 == n2- then Nothing- else Just ("typedef " <> n1 <> " " <> n2 <> ";")- declBodyStr = intercalateWith connRet genTopLevelFuncCppDefinition (tihFuncs tih)-- in subst definitionTemplate (context [ ("header" , declHeaderStr)- , ("namespace", namespaceStr )- , ("alias" , aliasStr )- , ("cppbody" , declBodyStr ) ])---- |-buildTemplateHeader :: TypeMacro -- ^ typemacro prefix- -> TemplateClass- -> String-buildTemplateHeader (TypMcro typemacroprefix) t =- let typemacrostr = typemacroprefix <> "TEMPLATE__" <> map toUpper (tclass_name t) <> "__"- fs = tclass_funcs t- deffunc = intercalateWith connRet (genTmplFunCpp False t) fs- ++ "\n\n"- ++ intercalateWith connRet (genTmplFunCpp True t) fs- classlevel = genTmplClassCpp False t fs ++ "\n\n" ++ genTmplClassCpp True t fs- in subst- "#ifndef $typemacro\n\- \#define $typemacro\n\- \\n\- \$deffunc\n\- \$classlevel\n\- \#endif\n"- (context [ ("typemacro", typemacrostr )- , ("deffunc" , deffunc )- , ("classlevel" , classlevel )- ])----- |-buildFFIHsc :: ClassModule -> Module ()-buildFFIHsc m = mkModule (mname <.> "FFI") [lang ["ForeignFunctionInterface"]] ffiImports hscBody- where mname = cmModule m- headers = cmCIH m- ffiImports = [ mkImport "Data.Word"- , mkImport "Data.Int"- , mkImport "Foreign.C"- , mkImport "Foreign.Ptr"- , mkImport (mname <.> "RawType") ]- <> genImportInFFI m- <> genExtraImport m- hscBody = concatMap genHsFFI headers----- |-buildRawTypeHs :: ClassModule -> Module ()-buildRawTypeHs m = mkModule (cmModule m <.> "RawType")- [lang [ "ForeignFunctionInterface", "TypeFamilies", "MultiParamTypeClasses"- , "FlexibleInstances", "TypeSynonymInstances"- , "EmptyDataDecls", "ExistentialQuantification", "ScopedTypeVariables" ]]- rawtypeImports rawtypeBody- where rawtypeImports = [ mkImport "Foreign.Ptr"- , mkImport "FFICXX.Runtime.Cast"- ]- rawtypeBody = concatMap hsClassRawType . filter (not.isAbstractClass) . cmClass $ m---- |-buildInterfaceHs :: AnnotateMap -> ClassModule -> Module ()-buildInterfaceHs amap m = mkModule (cmModule m <.> "Interface")- [lang [ "EmptyDataDecls", "ExistentialQuantification"- , "FlexibleContexts", "FlexibleInstances", "ForeignFunctionInterface"- , "MultiParamTypeClasses"- , "ScopedTypeVariables"- , "TypeFamilies", "TypeSynonymInstances"- ]]- ifaceImports ifaceBody- where classes = cmClass m- ifaceImports = [ mkImport "Data.Word"- , mkImport "Data.Int"- , mkImport "Foreign.C"- , mkImport "Foreign.Ptr"- , mkImport "FFICXX.Runtime.Cast" ]- <> genImportInInterface m- <> genExtraImport m- ifaceBody =- runReader (mapM genHsFrontDecl classes) amap- <> (concatMap genHsFrontUpcastClass . filter (not.isAbstractClass)) classes- <> (concatMap genHsFrontDowncastClass . filter (not.isAbstractClass)) classes---- |-buildCastHs :: ClassModule -> Module ()-buildCastHs m = mkModule (cmModule m <.> "Cast")- [ lang [ "FlexibleInstances", "FlexibleContexts", "TypeFamilies"- , "MultiParamTypeClasses", "OverlappingInstances", "IncoherentInstances" ] ]- castImports body- where classes = cmClass m- castImports = [ mkImport "Foreign.Ptr"- , mkImport "FFICXX.Runtime.Cast"- , mkImport "System.IO.Unsafe" ]- <> genImportInCast m- body = mapMaybe genHsFrontInstCastable classes- <> mapMaybe genHsFrontInstCastableSelf classes---- |-buildImplementationHs :: AnnotateMap -> ClassModule -> Module ()-buildImplementationHs amap m = mkModule (cmModule m <.> "Implementation")- [ lang [ "EmptyDataDecls"- , "FlexibleContexts"- , "FlexibleInstances"- , "ForeignFunctionInterface"- , "IncoherentInstances"- , "MultiParamTypeClasses"- , "OverlappingInstances"- , "TemplateHaskell"- , "TypeFamilies"- , "TypeSynonymInstances"- ] ]- implImports implBody- where classes = cmClass m- implImports = [ mkImport "Data.Monoid" -- for template member- , mkImport "Data.Word"- , mkImport "Data.Int"- , mkImport "Foreign.C"- , mkImport "Foreign.Ptr"- , mkImport "Language.Haskell.TH" -- for template member- , mkImport "Language.Haskell.TH.Syntax" -- for template member- , mkImport "System.IO.Unsafe"- , mkImport "FFICXX.Runtime.Cast"- , mkImport "FFICXX.Runtime.TH" -- for template member- ]- <> genImportInImplementation m- <> genExtraImport m- f :: Class -> [Decl ()]- f y = concatMap (flip genHsFrontInst y) (y:class_allparents y)-- implBody = concatMap f classes- <> runReader (concat <$> mapM genHsFrontInstNew classes) amap- <> concatMap genHsFrontInstNonVirtual classes- <> concatMap genHsFrontInstStatic classes- <> concatMap genHsFrontInstVariables classes- <> concatMap genTemplateMemberFunctions classes--buildTemplateHs :: TemplateClassModule -> Module ()-buildTemplateHs m = mkModule (tcmModule m <.> "Template")- [lang [ "EmptyDataDecls", "FlexibleInstances", "MultiParamTypeClasses"- , "TypeFamilies"] ]- [ mkImport "Foreign.C.Types"- , mkImport "Foreign.Ptr"- , mkImport "FFICXX.Runtime.Cast"- ]- body- where ts = tcmTemplateClasses m- body = concatMap genTmplInterface ts--buildTHHs :: TemplateClassModule -> Module ()-buildTHHs m = mkModule (tcmModule m <.> "TH")- [lang ["TemplateHaskell"] ]- ([ mkImport "Data.Char"- , mkImport "Data.Monoid"- , mkImport "Foreign.C.Types"- , mkImport "Foreign.Ptr"- , mkImport "Language.Haskell.TH"- , mkImport "Language.Haskell.TH.Syntax"- , mkImport "FFICXX.Runtime.TH"- ] <> imports)- body- where ts = tcmTemplateClasses m- imports = [ mkImport (tcmModule m <.> "Template") ]- body = concatMap genTmplImplementation ts- <> concatMap (\t -> genTmplInstance t (tclass_funcs t)) ts---- |-buildInterfaceHSBOOT :: String -> Module ()-buildInterfaceHSBOOT mname = mkModule (mname <.> "Interface") [] [] hsbootBody- where cname = last (splitOn "." mname)- hsbootBody = [ mkClass cxEmpty ('I':cname) [mkTBind "a"] [] ]---- |-buildModuleHs :: ClassModule -> Module ()-buildModuleHs m = mkModuleE (cmModule m) [] (concatMap genExport (cmClass m)) (genImportInModule (cmClass m)) []---- |-buildTopLevelHs :: String -> ([ClassModule],[TemplateClassModule]) -> TopLevelImportHeader -> Module ()-buildTopLevelHs modname (mods,tmods) tih =- mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody- where- tfns = tihFuncs tih- pkgExtensions = [ lang [ "FlexibleContexts", "FlexibleInstances" ] ]- pkgExports = map (emodule . cmModule) mods- ++ map (evar . unqual . hsFrontNameForTopLevelFunction) tfns-- pkgImports = genImportInTopLevel modname (mods,tmods) tih-- pkgBody = map (genTopLevelFuncFFI tih) tfns- ++ concatMap genTopLevelFuncDef tfns---- |-buildPackageInterface :: PackageInterface- -> PackageName- -> [ClassImportHeader]- -> PackageInterface-buildPackageInterface pinfc pkgname = foldr f pinfc- where f cih repo =- let name = (class_name . cihClass) cih- header = cihSelfHeader cih- in repo & at (pkgname,ClsName name) .~ (Just header)
− lib/FFICXX/Generate/Dependency.hs
@@ -1,430 +0,0 @@-{-# LANGUAGE RecordWildCards #-}--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Dependency--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Dependency where------- fficxx generates one module per one C++ class, and C++ class depends on other classes,--- so we need to import other modules corresponding to C++ classes in the dependency list.--- Calculating the import list from dependency graph is what this module does.---- Previously, we have only `Class` type, but added `TemplateClass` recently. Therefore--- we have to calculate dependency graph for both types of classes. So we needed to change--- `Class` to `Either TemplateClass Class` in many of routines that calculates module import--- list.---- `Dep4Func` contains a list of classes (both ordinary and template types) that is needed--- for the definition of a member function.--- The goal of `extractClassDep...` functions are to extract Dep4Func, and from the definition--- of a class or a template class, we get a list of `Dep4Func`s and then we deduplicate the--- dependency class list and finally get the import list for the module corresponding to--- a given class.-----import Data.Either (rights)-import Data.Function (on)-import qualified Data.HashMap.Strict as HM-import Data.List-import qualified Data.Map as M-import Data.Maybe-import Data.Monoid ((<>))-import System.FilePath----import FFICXX.Generate.Name (ffiClassName,hsClassName,hsTemplateClassName)-import FFICXX.Generate.Type.Cabal (AddCInc,AddCSrc,CabalName(..)- ,cabal_moduleprefix,cabal_pkgname- ,cabal_cheaderprefix,unCabalName)-import FFICXX.Generate.Type.Class-import FFICXX.Generate.Type.Config (ModuleUnit(..)- ,ModuleUnitImports(..),emptyModuleUnitImports- ,ModuleUnitMap(..))-import FFICXX.Generate.Type.Module-import FFICXX.Generate.Type.PackageInterface----- utility functions--getcabal = either tclass_cabal class_cabal--getparents = either (const []) (map Right . class_parents)---- TODO: replace tclass_name with appropriate FFI name when supported.-getFFIName = either tclass_name ffiClassName---getPkgName :: Either TemplateClass Class -> CabalName-getPkgName = cabal_pkgname . getcabal----- |-extractClassFromType :: Types -> [Either TemplateClass Class]-extractClassFromType Void = []-extractClassFromType SelfType = []-extractClassFromType (CT _ _) = []-extractClassFromType (CPT (CPTClass c) _) = [Right c]-extractClassFromType (CPT (CPTClassRef c) _) = [Right c]-extractClassFromType (CPT (CPTClassCopy c) _) = [Right c]-extractClassFromType (CPT (CPTClassMove c) _) = [Right c]-extractClassFromType (TemplateApp (TemplateAppInfo t p _)) =- (Left t): case p of- TArg_Class c -> [Right c]- _ -> []-extractClassFromType (TemplateAppRef (TemplateAppInfo t p _)) =- (Left t): case p of- TArg_Class c -> [Right c]- _ -> []-extractClassFromType (TemplateAppMove (TemplateAppInfo t p _)) =- (Left t): case p of- TArg_Class c -> [Right c]- _ -> []-extractClassFromType (TemplateType t) = [Left t]-extractClassFromType (TemplateParam _) = []-extractClassFromType (TemplateParamPointer _) = []---class_allparents :: Class -> [Class]-class_allparents c = let ps = class_parents c- in if null ps- then []- else nub (ps <> (concatMap class_allparents ps))---getClassModuleBase :: Class -> String-getClassModuleBase = (<.>) <$> (cabal_moduleprefix.class_cabal) <*> (fst.hsClassName)--getTClassModuleBase :: TemplateClass -> String-getTClassModuleBase = (<.>) <$> (cabal_moduleprefix.tclass_cabal) <*> (fst.hsTemplateClassName)----- | Daughter map not including itself-mkDaughterMap :: [Class] -> DaughterMap-mkDaughterMap = foldl mkDaughterMapWorker M.empty- where mkDaughterMapWorker m c = let ps = map getClassModuleBase (class_allparents c)- in foldl (addmeToYourDaughterList c) m ps- addmeToYourDaughterList c m p = let f Nothing = Just [c]- f (Just cs) = Just (c:cs)- in M.alter f p m------ | Daughter Map including itself as a daughter-mkDaughterSelfMap :: [Class] -> DaughterMap-mkDaughterSelfMap = foldl' worker M.empty- where worker m c = let ps = map getClassModuleBase (c:class_allparents c)- in foldl (addToList c) m ps- addToList c m p = let f Nothing = Just [c]- f (Just cs) = Just (c:cs)- in M.alter f p m------ | class dependency for a given function-data Dep4Func = Dep4Func { returnDependency :: [Either TemplateClass Class]- , argumentDependency :: [Either TemplateClass Class] }----- |-extractClassDep :: Function -> Dep4Func-extractClassDep (Constructor args _) =- Dep4Func [] (concatMap (extractClassFromType.fst) args)-extractClassDep (Virtual ret _ args _) =- Dep4Func (extractClassFromType ret) (concatMap (extractClassFromType.fst) args)-extractClassDep (NonVirtual ret _ args _) =- Dep4Func (extractClassFromType ret) (concatMap (extractClassFromType.fst) args)-extractClassDep (Static ret _ args _) =- Dep4Func (extractClassFromType ret) (concatMap (extractClassFromType.fst) args)-extractClassDep (Destructor _) =- Dep4Func [] []---extractClassDepForTmplFun :: TemplateFunction -> Dep4Func-extractClassDepForTmplFun (TFun ret _ _ args _) =- Dep4Func (extractClassFromType ret) (concatMap (extractClassFromType.fst) args)-extractClassDepForTmplFun (TFunNew args _) =- Dep4Func [] (concatMap (extractClassFromType.fst) args)-extractClassDepForTmplFun TFunDelete =- Dep4Func [] []---extractClassDep4TmplMemberFun :: TemplateMemberFunction -> Dep4Func-extractClassDep4TmplMemberFun (TemplateMemberFunction {..}) =- Dep4Func (extractClassFromType tmf_ret) (concatMap (extractClassFromType.fst) tmf_args)----extractClassDepForTopLevelFunction :: TopLevelFunction -> Dep4Func-extractClassDepForTopLevelFunction f =- Dep4Func (extractClassFromType ret) (concatMap (extractClassFromType.fst) args)- where ret = case f of- TopLevelFunction {..} -> toplevelfunc_ret- TopLevelVariable {..} -> toplevelvar_ret- args = case f of- TopLevelFunction {..} -> toplevelfunc_args- TopLevelVariable {..} -> []----- TODO: Confirm the answer below is correct.--- NOTE: Q: Why returnDependency only?--- A: Difference between argument and return:--- for a member function f,--- we have (f :: (IA a, IB b) => a -> b -> IO C--- return class is concrete and argument class is constraint.-mkModuleDepRaw :: Either TemplateClass Class -> [Either TemplateClass Class]-mkModuleDepRaw x@(Right c) =- nub $- filter (/= x) $- concatMap (returnDependency . extractClassDep) (class_funcs c)- ++ concatMap (returnDependency . extractClassDep4TmplMemberFun) (class_tmpl_funcs c)-mkModuleDepRaw x@(Left t) =- (nub . filter (/= x) . concatMap (returnDependency.extractClassDepForTmplFun) . tclass_funcs) t----isNotInSamePackageWith- :: Either TemplateClass Class- -> Either TemplateClass Class- -> Bool-isNotInSamePackageWith x y = (x /= y) && (getPkgName x /= getPkgName y)---- x is in the sam-isInSamePackageButNotInheritedBy- :: Either TemplateClass Class -- ^ y- -> Either TemplateClass Class -- ^ x- -> Bool-isInSamePackageButNotInheritedBy x y =- x /= y && not (x `elem` getparents y) && (getPkgName x == getPkgName y)----- TODO: Confirm the following answer--- NOTE: Q: why returnDependency is not considered?--- A: See explanation in mkModuleDepRaw-mkModuleDepHighNonSource :: Either TemplateClass Class -> [Either TemplateClass Class]-mkModuleDepHighNonSource y@(Right c) =- let extclasses = filter (`isNotInSamePackageWith` y) $- concatMap (argumentDependency.extractClassDep) (class_funcs c)- ++ concatMap (argumentDependency.extractClassDep4TmplMemberFun) (class_tmpl_funcs c)- parents = map Right (class_parents c)- in nub (parents <> extclasses)-mkModuleDepHighNonSource y@(Left t) =- let fs = tclass_funcs t- extclasses = filter (`isNotInSamePackageWith` y) $- concatMap (argumentDependency.extractClassDepForTmplFun) fs- in nub extclasses----- TODO: Confirm the following answer--- NOTE: Q: why returnDependency is not considered?--- A: See explanation in mkModuleDepRaw-mkModuleDepHighSource :: Either TemplateClass Class -> [Either TemplateClass Class]-mkModuleDepHighSource y@(Right c) =- nub $- filter (`isInSamePackageButNotInheritedBy` y) $- concatMap (argumentDependency . extractClassDep) (class_funcs c)- ++ concatMap (argumentDependency . extractClassDep4TmplMemberFun) (class_tmpl_funcs c)-mkModuleDepHighSource y@(Left t) =- let fs = tclass_funcs t- in nub $- filter (`isInSamePackageButNotInheritedBy` y) $- concatMap (argumentDependency . extractClassDepForTmplFun) fs---- |-mkModuleDepCpp :: Either TemplateClass Class -> [Either TemplateClass Class]-mkModuleDepCpp y@(Right c) =- let fs = class_funcs c- vs = class_vars c- tmfs = class_tmpl_funcs c- in nub . filter (/= y) $- concatMap (returnDependency.extractClassDep) fs- <> concatMap (argumentDependency.extractClassDep) fs- <> concatMap (extractClassFromType . var_type) vs- <> concatMap (returnDependency.extractClassDep4TmplMemberFun) tmfs- <> concatMap (argumentDependency.extractClassDep4TmplMemberFun) tmfs- <> getparents y-mkModuleDepCpp y@(Left t) =- let fs = tclass_funcs t- in nub . filter (/= y) $- concatMap (returnDependency.extractClassDepForTmplFun) fs- <> concatMap (argumentDependency.extractClassDepForTmplFun) fs- <> getparents y---- |-mkModuleDepFFI1 :: Either TemplateClass Class -> [Either TemplateClass Class]-mkModuleDepFFI1 (Right c) = let fs = class_funcs c- vs = class_vars c- tmfs = class_tmpl_funcs c- in concatMap (returnDependency.extractClassDep) fs- <> concatMap (argumentDependency.extractClassDep) fs- <> concatMap (extractClassFromType . var_type) vs- <> concatMap (returnDependency.extractClassDep4TmplMemberFun) tmfs- <> concatMap (argumentDependency.extractClassDep4TmplMemberFun) tmfs-mkModuleDepFFI1 (Left t) = let fs = tclass_funcs t- in concatMap (returnDependency.extractClassDepForTmplFun) fs- <> concatMap (argumentDependency.extractClassDepForTmplFun) fs---- |-mkModuleDepFFI :: Either TemplateClass Class -> [Either TemplateClass Class]-mkModuleDepFFI y@(Right c) =- let ps = map Right (class_allparents c)- alldeps' = (concatMap mkModuleDepFFI1 ps) <> mkModuleDepFFI1 y- in nub (filter (/= y) alldeps')-mkModuleDepFFI (Left _) = []---mkClassModule :: (ModuleUnit -> ModuleUnitImports)- -> [(String,[String])]- -> Class- -> ClassModule-mkClassModule getImports extra c =- ClassModule {- cmModule = getClassModuleBase c- , cmClass = [c]- , cmCIH = map (mkCIH getImports) [c]- , cmImportedModulesHighNonSource = highs_nonsource- , cmImportedModulesRaw =raws- , cmImportedModulesHighSource = highs_source- , cmImportedModulesForFFI = ffis- , cmExtraImport = extraimports- }- where highs_nonsource = mkModuleDepHighNonSource (Right c)- raws = mkModuleDepRaw (Right c)- highs_source = mkModuleDepHighSource (Right c)- ffis = mkModuleDepFFI (Right c)- extraimports = fromMaybe [] (lookup (class_name c) extra)---findModuleUnitImports :: ModuleUnitMap -> ModuleUnit -> ModuleUnitImports-findModuleUnitImports m u =- fromMaybe emptyModuleUnitImports (HM.lookup u (unModuleUnitMap m))---mkTCM :: (TemplateClass,HeaderName) -> TemplateClassModule-mkTCM (t,hdr) = TCM (getTClassModuleBase t) [t] [TCIH t hdr]---mkPackageConfig- :: (CabalName, ModuleUnit -> ModuleUnitImports) -- ^ (package name,getImports)- -> ([Class],[TopLevelFunction],[(TemplateClass,HeaderName)],[(String,[String])])- -> [AddCInc]- -> [AddCSrc]- -> PackageConfig-mkPackageConfig (pkgname,getImports) (cs,fs,ts,extra) acincs acsrcs =- let ms = map (mkClassModule getImports extra) cs- cmpfunc x y = class_name (cihClass x) == class_name (cihClass y)- cihs = nubBy cmpfunc (concatMap cmCIH ms)- --- tih = mkTIH pkgname getImports cihs fs- tcms = map mkTCM ts- tcihs = concatMap tcmTCIH tcms- in PkgConfig {- pcfg_classModules = ms- , pcfg_classImportHeaders = cihs- , pcfg_topLevelImportHeader = tih- , pcfg_templateClassModules = tcms- , pcfg_templateClassImportHeaders = tcihs- , pcfg_additional_c_incs = acincs- , pcfg_additional_c_srcs = acsrcs- }----- TODO: change [String] to Set String-mkHSBOOTCandidateList :: [ClassModule] -> [String]-mkHSBOOTCandidateList ms =- let- -- get only class dependencies, not template classes.- cs = rights (concatMap cmImportedModulesHighSource ms)- in- nub (map getClassModuleBase cs)------ |-mkPkgHeaderFileName ::Class -> HeaderName-mkPkgHeaderFileName c =- HdrName ( (cabal_cheaderprefix.class_cabal) c- <> fst (hsClassName c)- <.> "h"- )---- |-mkPkgCppFileName ::Class -> String-mkPkgCppFileName c =- (cabal_cheaderprefix.class_cabal) c- <> fst (hsClassName c)- <.> "cpp"---- |-mkPkgIncludeHeadersInH :: Class -> [HeaderName]-mkPkgIncludeHeadersInH c =- let pkgname = (cabal_pkgname . class_cabal) c- extclasses = filter ((/= pkgname) . getPkgName) . mkModuleDepCpp $ Right c- extheaders = nub . map ((<>"Type.h") . unCabalName . getPkgName) $ extclasses- in map mkPkgHeaderFileName (class_allparents c) <> map HdrName extheaders------ |-mkPkgIncludeHeadersInCPP :: Class -> [HeaderName]-mkPkgIncludeHeadersInCPP = map mkPkgHeaderFileName . rights . mkModuleDepCpp . Right----- |-mkCIH :: (ModuleUnit -> ModuleUnitImports) -- ^ (mk namespace and include headers)- -> Class- -> ClassImportHeader-mkCIH getImports c =- ClassImportHeader {- cihClass = c- , cihSelfHeader = mkPkgHeaderFileName c- , cihNamespace = (muimports_namespaces . getImports . MU_Class . class_name) c- , cihSelfCpp = mkPkgCppFileName c- , cihImportedClasses = mkModuleDepCpp (Right c)- , cihIncludedHPkgHeadersInH = mkPkgIncludeHeadersInH c- , cihIncludedHPkgHeadersInCPP = mkPkgIncludeHeadersInCPP c- , cihIncludedCPkgHeaders = (muimports_headers . getImports . MU_Class . class_name) c- }---- | for top-level-mkTIH- :: CabalName- -> (ModuleUnit -> ModuleUnitImports)- -> [ClassImportHeader]- -> [TopLevelFunction]- -> TopLevelImportHeader-mkTIH pkgname getImports cihs fs =- let tl_cs1 = concatMap (argumentDependency . extractClassDepForTopLevelFunction) fs- tl_cs2 = concatMap (returnDependency . extractClassDepForTopLevelFunction) fs- tl_cs = nubBy ((==) `on` either tclass_name ffiClassName) (tl_cs1 <> tl_cs2)- -- NOTE: Select only class dependencies in the current package.- -- TODO: This is clearly not a good impl. we need to look into this again- -- after reconsidering multi-package generation.- tl_cihs = catMaybes (foldr fn [] tl_cs)- where- fn c ys =- let y = find (\x -> (ffiClassName . cihClass) x == getFFIName c) cihs- in y:ys- -- NOTE: The remaining class dependencies outside the current package- extclasses = filter ((/= pkgname) . getPkgName) tl_cs- extheaders = map HdrName $- nub $- map ((<>"Type.h") . unCabalName . getPkgName) extclasses-- in- TopLevelImportHeader {- tihHeaderFileName = unCabalName pkgname <> "TopLevel"- , tihClassDep = tl_cihs- , tihExtraClassDep = extclasses- , tihFuncs = fs- , tihNamespaces = muimports_namespaces (getImports MU_TopLevel)- , tihExtraHeadersInH = extheaders- , tihExtraHeadersInCPP = muimports_headers (getImports MU_TopLevel)- }
− lib/FFICXX/Generate/Name.hs
@@ -1,140 +0,0 @@-{-# LANGUAGE RecordWildCards #-}-module FFICXX.Generate.Name where--import Data.Char (toLower)-import Data.Maybe (fromMaybe,maybe)-import Data.Monoid ((<>))----import FFICXX.Generate.Type.Class-import FFICXX.Generate.Util----hsFrontNameForTopLevelFunction :: TopLevelFunction -> String-hsFrontNameForTopLevelFunction tfn =- let (x:xs) = case tfn of- TopLevelFunction {..} -> fromMaybe toplevelfunc_name toplevelfunc_alias- TopLevelVariable {..} -> fromMaybe toplevelvar_name toplevelvar_alias- in toLower x : xs---typeclassName :: Class -> String-typeclassName c = 'I' : fst (hsClassName c)--typeclassNameT :: TemplateClass -> String-typeclassNameT c = 'I' : fst (hsTemplateClassName c)----typeclassNameFromStr :: String -> String-typeclassNameFromStr = ('I':)--hsClassName :: Class -> (String, String) -- ^ High-level, 'Raw'-level-hsClassName c =- let cname = maybe (class_name c) caHaskellName (class_alias c)- in (cname, "Raw" <> cname)--hsClassNameForTArg :: TemplateArgType -> String-hsClassNameForTArg (TArg_Class c) = fst (hsClassName c)-hsClassNameForTArg (TArg_TypeParam p) = p-hsClassNameForTArg (TArg_Other s) = s--hsTemplateClassName :: TemplateClass -> (String, String) -- ^ High-level, 'Raw'-level-hsTemplateClassName t =- let tname = tclass_name t- in (tname, "Raw" <> tname)--existConstructorName :: Class -> String-existConstructorName c = 'E' : (fst.hsClassName) c---ffiClassName :: Class -> String-ffiClassName c = maybe (class_name c) caFFIName (class_alias c)--hscFuncName :: Class -> Function -> String-hscFuncName c f = "c_"- <> toLowers (ffiClassName c)- <> "_"- <> toLowers (aliasedFuncName c f)--hsFuncName :: Class -> Function -> String-hsFuncName c f = let (x:xs) = aliasedFuncName c f- in (toLower x) : xs--aliasedFuncName :: Class -> Function -> String-aliasedFuncName c f =- case f of- Constructor _ a -> fromMaybe (constructorName c) a- Virtual _ str _ a -> fromMaybe str a- NonVirtual _ str _ a -> fromMaybe (nonvirtualName c str) a- Static _ str _ a -> fromMaybe (nonvirtualName c str) a- Destructor a -> fromMaybe destructorName a---hsTmplFuncName :: TemplateClass -> TemplateFunction -> String-hsTmplFuncName t f =- case f of- TFun {..} -> tfun_name -- TODO: alias- TFunNew {..} -> fromMaybe ("new"<> tclass_name t) tfun_new_alias- TFunDelete -> "delete" <> tclass_name t---hsTmplFuncNameTH :: TemplateClass -> TemplateFunction -> String-hsTmplFuncNameTH t f = "t_" <> hsTmplFuncName t f---hsTemplateMemberFunctionName :: Class -> TemplateMemberFunction -> String-hsTemplateMemberFunctionName c f = fromMaybe (nonvirtualName c (tmf_name f)) (tmf_alias f)- -- fst (hsClassName c) <> "_" <> tmf_name f -- TODO: alias---hsTemplateMemberFunctionNameTH :: Class -> TemplateMemberFunction -> String-hsTemplateMemberFunctionNameTH c f = "t_" <> hsTemplateMemberFunctionName c f---ffiTmplFuncName :: TemplateFunction -> String-ffiTmplFuncName f =- case f of- TFun {..} -> fromMaybe tfun_name tfun_alias- TFunNew {..} -> fromMaybe "new" tfun_new_alias- TFunDelete -> "delete"---cppTmplFuncName :: TemplateFunction -> String-cppTmplFuncName f =- case f of- TFun {..} -> tfun_name- TFunNew {..} -> "new"- TFunDelete -> "delete"--accessorName :: Class -> Variable -> Accessor -> String-accessorName c v a = nonvirtualName c (var_name v)- <> "_"- <> case a of- Getter -> "get"- Setter -> "set"--hscAccessorName :: Class -> Variable -> Accessor -> String-hscAccessorName c v a = "c_" <> toLowers (accessorName c v a)---cppStaticName :: Class -> Function -> String-cppStaticName c f = class_name c <> "::" <> func_name f--cppFuncName :: Class -> Function -> String-cppFuncName c f = case f of- Constructor _ _ -> "new"- Virtual _ _ _ _ -> func_name f- NonVirtual _ _ _ _-> func_name f- Static _ _ _ _-> cppStaticName c f- Destructor _ -> destructorName--constructorName :: Class -> String-constructorName c = "new" <> (fst.hsClassName) c--nonvirtualName :: Class -> String -> String-nonvirtualName c str = (firstLower.fst.hsClassName) c <> "_" <> str--destructorName :: String-destructorName = "delete"-
− lib/FFICXX/Generate/QQ/Verbatim.hs
@@ -1,25 +0,0 @@--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.QQ.Verbatim--- Copyright : (c) 2011-2013 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.QQ.Verbatim where--import Language.Haskell.TH.Quote-import Language.Haskell.TH.Lib--verbatim :: QuasiQuoter-verbatim = QuasiQuoter{ quoteExp = litE . stringL- , quotePat = undefined- , quoteType = undefined- , quoteDec = undefined- -- , quotePat = litP . stringP- } -
− lib/FFICXX/Generate/Type/Annotate.hs
@@ -1,23 +0,0 @@--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Type.Annotate--- Copyright : (c) 2011-2013 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Type.Annotate where--import qualified Data.Map as M--data PkgType = PkgModule | PkgClass | PkgMethod - deriving (Show,Eq,Ord)--type AnnotateMap = M.Map (PkgType,String) String---
− lib/FFICXX/Generate/Type/Cabal.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Type.Cabal--- Copyright : (c) 2011-2019 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Type.Cabal where--import Data.Aeson (FromJSON(..),ToJSON(..)- ,genericParseJSON,genericToJSON- ,defaultOptions)-import Data.Aeson.Types (fieldLabelModifier)-import Data.Text (Text)-import GHC.Generics (Generic)--data AddCInc = AddCInc FilePath String--data AddCSrc = AddCSrc FilePath String---- TODO: change String to Text-newtype CabalName = CabalName { unCabalName :: String }- deriving (Show,Eq,Ord)---data BuildType = Simple- | Custom [CabalName] -- ^ dependencies---- TODO: change String to Text-data Cabal =- Cabal {- cabal_pkgname :: CabalName- , cabal_version :: String- , cabal_cheaderprefix :: String- , cabal_moduleprefix :: String- , cabal_additional_c_incs :: [AddCInc]- , cabal_additional_c_srcs :: [AddCSrc]- , cabal_additional_pkgdeps :: [CabalName]- , cabal_license :: Maybe String- , cabal_licensefile :: Maybe String- , cabal_extraincludedirs :: [FilePath]- , cabal_extralibdirs :: [FilePath]- , cabal_extrafiles :: [FilePath]- , cabal_pkg_config_depends :: [String]- , cabal_buildType :: BuildType- }--data GeneratedCabalInfo =- GeneratedCabalInfo {- gci_pkgname :: Text- , gci_version :: Text- , gci_synopsis :: Text- , gci_description :: Text- , gci_homepage :: Text- , gci_license :: Text- , gci_licenseFile :: Text- , gci_author :: Text- , gci_maintainer :: Text- , gci_category :: Text- , gci_buildtype :: Text- , gci_extraFiles :: [Text]- , gci_csrcFiles :: [Text]- , gci_sourcerepository :: Text- , gci_cxxOptions :: [Text]- , gci_pkgdeps :: [Text]- , gci_exposedModules :: [Text]- , gci_otherModules :: [Text]- , gci_extraLibDirs :: [Text]- , gci_extraLibraries :: [Text]- , gci_extraIncludeDirs :: [Text]- , gci_pkgconfigDepends :: [Text]- , gci_includeFiles :: [Text]- , gci_cppFiles :: [Text]- }- deriving (Show,Generic)--instance ToJSON GeneratedCabalInfo where- toJSON = genericToJSON defaultOptions {fieldLabelModifier = drop 4}--instance FromJSON GeneratedCabalInfo where- parseJSON = genericParseJSON defaultOptions {fieldLabelModifier = drop 4}
− lib/FFICXX/Generate/Type/Class.hs
@@ -1,295 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RecordWildCards #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Type.Class--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Type.Class where-import qualified Data.Map as M-import Data.Monoid (Monoid(..))-import Data.Semigroup (Semigroup(..),(<>))----import FFICXX.Generate.Type.Cabal----- | C types-data CTypes = CTBool- | CTChar- | CTClock- | CTDouble- | CTFile- | CTFloat- | CTFpos- | CTInt- | CTIntMax- | CTIntPtr- | CTJmpBuf- | CTLLong- | CTLong- | CTPtrdiff- | CTSChar- | CTSUSeconds- | CTShort- | CTSigAtomic- | CTSize- | CTTime- | CTUChar- | CTUInt- | CTUIntMax- | CTUIntPtr- | CTULLong- | CTULong- | CTUSeconds- | CTUShort- | CTWchar- | CTInt8- | CTInt16- | CTInt32- | CTInt64- | CTUInt8- | CTUInt16- | CTUInt32- | CTUInt64- | CTVoidStar- | CTString- | CEnum CTypes String- | CPointer CTypes- | CRef CTypes- deriving Show---- | C++ types-data CPPTypes = CPTClass Class- | CPTClassRef Class- | CPTClassCopy Class- | CPTClassMove Class- deriving Show---- | const flag-data IsConst = Const | NoConst- deriving Show---- | Argument type which can be used as an template argument like float--- in vector<float>.--- For now, this distinguishes Class and non-Class.-data TemplateArgType = TArg_Class Class- | TArg_TypeParam String- | TArg_Other String- deriving Show--data TemplateAppInfo = TemplateAppInfo {- tapp_tclass :: TemplateClass- , tapp_tparam :: TemplateArgType- , tapp_CppTypeForParam :: String- }- deriving Show--data Types = Void- | SelfType- | CT CTypes IsConst- | CPT CPPTypes IsConst- | TemplateApp TemplateAppInfo -- ^ like vector<float>*- | TemplateAppRef TemplateAppInfo -- ^ like vector<float>&- | TemplateAppMove TemplateAppInfo -- ^ like unique_ptr<float> (using std::move)- | TemplateType TemplateClass -- ^ template self? TODO: clarify this.- | TemplateParam String- | TemplateParamPointer String -- ^ this is A* with template<A>- deriving Show-----------------type Args = [(Types,String)]--data Function = Constructor { func_args :: Args- , func_alias :: Maybe String- }- | Virtual { func_ret :: Types- , func_name :: String- , func_args :: Args- , func_alias :: Maybe String- }- | NonVirtual { func_ret :: Types- , func_name :: String- , func_args :: Args- , func_alias :: Maybe String- }- | Static { func_ret :: Types- , func_name :: String- , func_args :: Args- , func_alias :: Maybe String- }- | Destructor { func_alias :: Maybe String }- deriving Show---data Variable = Variable { var_type :: Types- , var_name :: String- }- deriving Show--data TemplateMemberFunction =- TemplateMemberFunction {- tmf_param :: String- , tmf_ret :: Types- , tmf_name :: String- , tmf_args :: Args- , tmf_alias :: Maybe String- }- deriving Show---data TopLevelFunction = TopLevelFunction { toplevelfunc_ret :: Types- , toplevelfunc_name :: String- , toplevelfunc_args :: Args- , toplevelfunc_alias :: Maybe String- }- | TopLevelVariable { toplevelvar_ret :: Types- , toplevelvar_name :: String- , toplevelvar_alias :: Maybe String }- deriving Show-----isNewFunc :: Function -> Bool-isNewFunc (Constructor _ _) = True-isNewFunc _ = False--isDeleteFunc :: Function -> Bool-isDeleteFunc (Destructor _) = True-isDeleteFunc _ = False--isVirtualFunc :: Function -> Bool-isVirtualFunc (Destructor _) = True-isVirtualFunc (Virtual _ _ _ _) = True-isVirtualFunc _ = False--isNonVirtualFunc :: Function -> Bool-isNonVirtualFunc (NonVirtual _ _ _ _) = True-isNonVirtualFunc _ = False----isStaticFunc :: Function -> Bool-isStaticFunc (Static _ _ _ _) = True-isStaticFunc _ = False--virtualFuncs :: [Function] -> [Function]-virtualFuncs = filter isVirtualFunc--constructorFuncs :: [Function] -> [Function]-constructorFuncs = filter isNewFunc--nonVirtualNotNewFuncs :: [Function] -> [Function]-nonVirtualNotNewFuncs =- filter (\x -> (not.isVirtualFunc) x && (not.isNewFunc) x && (not.isDeleteFunc) x && (not.isStaticFunc) x )--staticFuncs :: [Function] -> [Function]-staticFuncs = filter isStaticFunc------------newtype ProtectedMethod = Protected { unProtected :: [String] }- deriving (Semigroup, Monoid)--data ClassAlias = ClassAlias { caHaskellName :: String- , caFFIName :: String- }---- TODO: partial record must be avoided.-data Class = Class {- class_cabal :: Cabal- , class_name :: String- , class_parents :: [Class]- , class_protected :: ProtectedMethod- , class_alias :: Maybe ClassAlias- , class_funcs :: [Function]- , class_vars :: [Variable]- , class_tmpl_funcs :: [TemplateMemberFunction]- }- | AbstractClass {- class_cabal :: Cabal- , class_name :: String- , class_parents :: [Class]- , class_protected :: ProtectedMethod- , class_alias :: Maybe ClassAlias- , class_funcs :: [Function]- , class_vars :: [Variable]- , class_tmpl_funcs :: [TemplateMemberFunction]- }---- TODO: we had better not override standard definitions-instance Show Class where- show x = show (class_name x)---- TODO: we had better not override standard definitions-instance Eq Class where- (==) x y = class_name x == class_name y---- TODO: we had better not override standard definitions-instance Ord Class where- compare x y = compare (class_name x) (class_name y)---data TemplateFunction = TFun { tfun_ret :: Types- , tfun_name :: String- , tfun_oname :: String- , tfun_args :: Args- , tfun_alias :: Maybe String }- | TFunNew { tfun_new_args :: Args- , tfun_new_alias :: Maybe String- }- | TFunDelete---data TemplateClass = TmplCls { tclass_cabal :: Cabal- , tclass_name :: String- , tclass_oname :: String- , tclass_param :: String- , tclass_funcs :: [TemplateFunction]- }---- TODO: we had better not override standard definitions-instance Show TemplateClass where- show x = show (tclass_name x <> " " <> tclass_param x)---- TODO: we had better not override standard definitions-instance Eq TemplateClass where- (==) x y = tclass_name x == tclass_name y---- TODO: we had better not override standard definitions-instance Ord TemplateClass where- compare x y = compare (tclass_name x) (tclass_name y)---data ClassGlobal = ClassGlobal- { cgDaughterSelfMap :: DaughterMap- , cgDaughterMap :: DaughterMap- }--data Selfness = Self | NoSelf------ | Check abstract class--isAbstractClass :: Class -> Bool-isAbstractClass Class{} = False-isAbstractClass AbstractClass{} = True----type DaughterMap = M.Map String [Class]--data Accessor = Getter | Setter- deriving (Show, Eq)
− lib/FFICXX/Generate/Type/Config.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-module FFICXX.Generate.Type.Config where--import Data.Hashable (Hashable(..))-import Data.HashMap.Strict (HashMap)-import GHC.Generics (Generic)----import FFICXX.Generate.Type.PackageInterface (HeaderName(..),Namespace(..))--data ModuleUnit = MU_TopLevel - | MU_Class String- deriving (Show,Eq,Generic)--instance Hashable ModuleUnit--data ModuleUnitImports =- ModuleUnitImports {- muimports_namespaces :: [Namespace]- , muimports_headers :: [HeaderName]- }- deriving (Show)--emptyModuleUnitImports = ModuleUnitImports [] []--newtype ModuleUnitMap = ModuleUnitMap { unModuleUnitMap :: HashMap ModuleUnit ModuleUnitImports }
− lib/FFICXX/Generate/Type/Module.hs
@@ -1,76 +0,0 @@--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Type.Module--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Type.Module where--import FFICXX.Generate.Type.Cabal (AddCInc,AddCSrc)-import FFICXX.Generate.Type.Class-import FFICXX.Generate.Type.PackageInterface (HeaderName(..),Namespace(..))---- | C++ side--- HPkg is generated C++ headers by fficxx, CPkg is original C++ headers-data ClassImportHeader = ClassImportHeader- { cihClass :: Class- , cihSelfHeader :: HeaderName- , cihNamespace :: [Namespace]- , cihSelfCpp :: String- , cihImportedClasses :: [Either TemplateClass Class] -- ^ Dependencies TODO: clarify this.- , cihIncludedHPkgHeadersInH :: [HeaderName] -- TODO: Explain why we need to have these two- , cihIncludedHPkgHeadersInCPP :: [HeaderName] -- separately.- , cihIncludedCPkgHeaders :: [HeaderName]- } deriving (Show)----- | Haskell side-data ClassModule = ClassModule- { cmModule :: String- , cmClass :: [Class]- , cmCIH :: [ClassImportHeader]- , cmImportedModulesHighNonSource :: [Either TemplateClass Class] -- ^ imported modules that do not need source- -- NOTE: source means the same cabal package.- -- TODO: rename Source to something more clear.- , cmImportedModulesRaw :: [Either TemplateClass Class] -- ^ imported modules for raw types.- , cmImportedModulesHighSource :: [Either TemplateClass Class] -- ^ imported modules that need source- , cmImportedModulesForFFI :: [Either TemplateClass Class]- , cmExtraImport :: [String]- } deriving (Show)--data TemplateClassModule = TCM { tcmModule :: String- , tcmTemplateClasses :: [TemplateClass]- , tcmTCIH :: [TemplateClassImportHeader]- } deriving (Show)---data TemplateClassImportHeader = TCIH { tcihTClass :: TemplateClass- , tcihSelfHeader :: HeaderName- } deriving (Show)--data TopLevelImportHeader = TopLevelImportHeader {- tihHeaderFileName :: String- , tihClassDep :: [ClassImportHeader]- , tihExtraClassDep :: [Either TemplateClass Class]- -- ^ Extra class dependencies outside current package.- -- NOTE: we cannot fully construct ClassImportHeader for them.- , tihFuncs :: [TopLevelFunction]- , tihNamespaces :: [Namespace]- , tihExtraHeadersInH :: [HeaderName]- , tihExtraHeadersInCPP :: [HeaderName]- } deriving (Show)--data PackageConfig = PkgConfig { pcfg_classModules :: [ClassModule]- , pcfg_classImportHeaders :: [ClassImportHeader]- , pcfg_topLevelImportHeader :: TopLevelImportHeader- , pcfg_templateClassModules :: [TemplateClassModule]- , pcfg_templateClassImportHeaders :: [TemplateClassImportHeader]- , pcfg_additional_c_incs :: [AddCInc]- , pcfg_additional_c_srcs :: [AddCSrc]- }
− lib/FFICXX/Generate/Type/PackageInterface.hs
@@ -1,36 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}---------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Type.PackageInterface--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC-----------------------------------------------------------------------------------module FFICXX.Generate.Type.PackageInterface where --import Data.Hashable-import qualified Data.HashMap.Strict as HM-import Data.String--newtype PackageName = PkgName String deriving (Hashable, Show, Eq, Ord)-newtype ClassName = ClsName String deriving (Hashable, Show, Eq, Ord)--newtype HeaderName = HdrName { unHdrName :: String }- deriving (Hashable, Show, Eq, Ord)---instance IsString HeaderName where- fromString = HdrName--newtype Namespace = NS { unNamespace :: String } deriving (Show)--type PackageInterface = HM.HashMap (PackageName, ClassName) HeaderName --newtype TypeMacro = TypMcro { unTypMcro :: String } - deriving (Show,Eq,Ord)
− lib/FFICXX/Generate/Util.hs
@@ -1,99 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Util--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC------------------------------------------------------------------------------------module FFICXX.Generate.Util where--import Data.Char -import Data.List-import Data.List.Split-import Data.Maybe (fromMaybe)-import Data.Monoid ((<>))-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import Data.Text.Template---moduleDirFile :: String -> (String,String)-moduleDirFile mname = - let splitted = splitOn "." mname- moddir = intercalate "/" (init splitted )- modfile = (last splitted) <> ".hs" - in (moddir, modfile)--hline :: IO ()-hline = putStrLn "--------------------------------------------------------"--toUppers :: String -> String-toUppers = map toUpper--toLowers :: String -> String -toLowers = map toLower---firstLower :: String -> String -firstLower [] = [] -firstLower (x:xs) = (toLower x) : xs --conn :: String -> String -> String -> String -conn st x y = x <> st <> y --connspace :: String -> String -> String-connspace = conn " " --conncomma :: String -> String -> String-conncomma = conn ", " --connBSlash :: String -> String -> String -connBSlash = conn "\\\n"--connSemicolonBSlash :: String -> String -> String-connSemicolonBSlash = conn "; \\\n"--connRet :: String -> String -> String-connRet = conn "\n"--connRet2 :: String -> String -> String -connRet2 = conn "\n\n"--connArrow :: String -> String -> String -connArrow = conn " -> " --intercalateWith :: (String-> String -> String) -> (a->String) -> [a] -> String-intercalateWith f mapper x - | not (null x) = foldl1 f (map mapper x)- | otherwise = "" ---intercalateWithM :: (Monad m) => (String -> String -> String) -> (a->m String) -> [a] -> m String -intercalateWithM f mapper x - | not (null x) = do ms <- mapM mapper x- return (foldl1 f ms)- | otherwise = return "" ----- TODO: deprecate this and use contextT-context :: [(Text,String)] -> Context-context assocs x = maybe err (T.pack) . lookup x $ assocs- where err = error $ "Could not find key: " <> (T.unpack x)---- TODO: Rename this to context.--- TODO: Proper error handling.-contextT :: [(Text,Text)] -> Context-contextT assocs x = fromMaybe err . lookup x $ assocs- where err = error $ T.unpack ("Could not find key: " <> x)--subst :: Text -> Context -> String-subst t c = TL.unpack (substitute t c)-
− lib/FFICXX/Generate/Util/HaskellSrcExts.hs
@@ -1,213 +0,0 @@-{-# LANGUAGE CPP #-}--------------------------------------------------------------------------------- |--- Module : FFICXX.Generate.Util.HaskellSrcExts--- Copyright : (c) 2011-2018 Ian-Woo Kim------ License : BSD3--- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>--- Stability : experimental--- Portability : GHC------------------------------------------------------------------------------------module FFICXX.Generate.Util.HaskellSrcExts where--import Data.Maybe (maybeToList)-import Data.List (foldl')-import Language.Haskell.Exts hiding (unit_tycon)-import qualified Language.Haskell.Exts (unit_tycon)---unqual :: String -> QName ()-unqual = UnQual () . Ident ()--tycon :: String -> Type ()-tycon = TyCon () . unqual--tyapp :: Type () -> Type () -> Type ()-tyapp = TyApp ()--tyfun :: Type () -> Type () -> Type ()-tyfun = TyFun ()--tylist :: Type () -> Type ()-tylist = TyList ()--unit_tycon :: Type ()-unit_tycon = Language.Haskell.Exts.unit_tycon ()--conDecl :: String -> [Type ()] -> ConDecl ()-conDecl n ys = ConDecl () (Ident () n) ys--qualConDecl = QualConDecl ()--recDecl :: String -> [FieldDecl ()] -> ConDecl ()-recDecl n rs = RecDecl () (Ident () n) rs--app' :: String -> String -> Exp ()-app' x y = App () (mkVar x) (mkVar y)---lit :: Literal () -> Exp ()-lit = Lit ()---mkVar :: String -> Exp ()-mkVar = Var () . unqual--con :: String -> Exp ()-con = Con () . unqual--mkTVar :: String -> Type ()-mkTVar = TyVar () . Ident ()--mkPVar :: String -> Pat ()-mkPVar = PVar () . Ident ()--mkIVar :: String -> ImportSpec ()-mkIVar = IVar () . Ident ()--mkPVarSig :: String -> Type () -> Pat ()-mkPVarSig n typ = PatTypeSig () (mkPVar n) typ--pbind :: Pat () -> Exp () -> Maybe (Binds ()) -> Decl ()-pbind pat e = PatBind () pat (UnGuardedRhs () e)--mkTBind :: String -> TyVarBind ()-mkTBind = UnkindedVar () . Ident ()--mkBind1 :: String -> [Pat ()] -> Exp () -> Maybe (Binds ()) -> Decl ()-mkBind1 n pat rhs mbinds =- FunBind () [ Match () (Ident () n) pat (UnGuardedRhs () rhs) mbinds ]--mkFun :: String -> Type () -> [Pat ()] -> Exp () -> Maybe (Binds ()) -> [Decl ()]-mkFun fname typ pats rhs mbinds = [mkFunSig fname typ, mkBind1 fname pats rhs mbinds]--mkFunSig :: String -> Type () -> Decl ()-mkFunSig fname typ = TypeSig () [Ident () fname] typ--mkClass :: Context () -> String -> [TyVarBind ()] -> [ClassDecl ()] -> Decl ()-mkClass ctxt n tbinds cdecls = ClassDecl () (Just ctxt) (mkDeclHead n tbinds) [] (Just cdecls)---dhead :: String -> DeclHead ()-dhead n = DHead () (Ident () n)--mkDeclHead :: String -> [TyVarBind ()] -> DeclHead ()-mkDeclHead n tbinds = foldl' (DHApp ()) (dhead n) tbinds--mkInstance :: Context () -> String -> [Type ()] -> [InstDecl ()] -> Decl ()-mkInstance ctxt n typs idecls = InstDecl () Nothing instrule (Just idecls)- where instrule = IRule () Nothing (Just ctxt) insthead- insthead = foldl' f (IHCon () (unqual n)) typs- where f acc x = IHApp () acc (tyParen x)--mkData :: String -> [TyVarBind ()] -> [QualConDecl ()] -> Maybe (Deriving ()) -> Decl ()-#if MIN_VERSION_haskell_src_exts(1,20,0)-mkData n tbinds qdecls mderiv = DataDecl () (DataType ()) Nothing declhead qdecls (maybeToList mderiv)-#else-mkData n tbinds qdecls mderiv = DataDecl () (DataType ()) Nothing declhead qdecls mderiv-#endif- where declhead = mkDeclHead n tbinds--mkNewtype :: String -> [TyVarBind ()] -> [QualConDecl ()] -> Maybe (Deriving ()) -> Decl ()-#if MIN_VERSION_haskell_src_exts(1,20,0)-mkNewtype n tbinds qdecls mderiv = DataDecl () (NewType ()) Nothing declhead qdecls (maybeToList mderiv)-#else-mkNewtype n tbinds qdecls mderiv = DataDecl () (NewType ()) Nothing declhead qdecls mderiv-#endif- where declhead = mkDeclHead n tbinds--mkForImpCcall :: String -> String -> Type () -> Decl ()-mkForImpCcall quote n typ = ForImp () (CCall ()) (Just (PlaySafe () False)) (Just quote) (Ident () n) typ--mkModule :: String -> [ModulePragma ()] -> [ImportDecl ()] -> [Decl ()] -> Module ()-mkModule n pragmas idecls decls = Module () (Just mhead) pragmas idecls decls- where mhead = ModuleHead () (ModuleName () n) Nothing Nothing--mkModuleE :: String -> [ModulePragma ()] -> [ExportSpec ()] -> [ImportDecl ()] -> [Decl ()] -> Module ()-mkModuleE n pragmas exps idecls decls = Module () (Just mhead) pragmas idecls decls- where mhead = ModuleHead () (ModuleName () n) Nothing (Just eslist)- eslist = ExportSpecList () exps--mkImport :: String -> ImportDecl ()-mkImport m = ImportDecl () (ModuleName () m) False False False Nothing Nothing Nothing--mkImportExp :: String -> [String] -> ImportDecl ()-mkImportExp m lst =- ImportDecl () (ModuleName () m) False False False Nothing Nothing (Just islist)- where islist = ImportSpecList () False (map mkIVar lst)---mkImportSrc :: String -> ImportDecl ()-mkImportSrc m = ImportDecl () (ModuleName () m) False True False Nothing Nothing Nothing--lang :: [String] -> ModulePragma ()-lang ns = LanguagePragma () (map (Ident ()) ns)--dot :: Exp () -> Exp () -> Exp ()-x `dot` y = x `app` mkVar "." `app` y--tyForall = TyForall ()--tyParen = TyParen ()--tyPtr :: Type ()-tyPtr = tycon "Ptr"--tyForeignPtr :: Type ()-tyForeignPtr = tycon "ForeignPtr"--classA :: QName () -> [Type ()] -> Asst ()-classA = ClassA ()--cxEmpty :: Context ()-cxEmpty = CxEmpty ()--cxTuple :: [Asst ()] -> Context ()-cxTuple = CxTuple ()--tySplice :: Splice () -> Type ()-tySplice = TySplice ()--parenSplice :: Exp () -> Splice ()-parenSplice = ParenSplice ()--bracketExp = BracketExp ()-typeBracket = TypeBracket ()---#if MIN_VERSION_haskell_src_exts(1,20,0)-mkDeriving = Deriving () Nothing-#else-mkDeriving = Deriving ()-#endif--irule = IRule ()--ihcon = IHCon ()--evar = EVar ()-eabs = EAbs ()-ethingwith = EThingWith ()--ethingall q = ethingwith (EWildcard () 0) q []--emodule nm = EModuleContents () (ModuleName () nm)--nonamespace = NoNamespace ()--list = List ()-lambda = Lambda ()--insType = InsType ()-insDecl = InsDecl ()--generator = Generator ()--clsDecl = ClsDecl ()---unkindedVar = UnkindedVar ()
+ src/FFICXX/Generate/Builder.hs view
@@ -0,0 +1,264 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module FFICXX.Generate.Builder where++import Control.Monad ( void, when )+import qualified Data.ByteString.Lazy.Char8 as L+import Data.Char ( toUpper )+import Data.Digest.Pure.MD5 ( md5 )+import Data.Foldable ( for_ )+import Data.Monoid ( (<>), mempty )+import Language.Haskell.Exts.Pretty ( prettyPrint )+import System.FilePath ( (</>), (<.>), splitExtension )+import System.Directory ( copyFile+ , createDirectoryIfMissing+ , doesFileExist+ )+import System.IO ( hPutStrLn, withFile, IOMode(..) )+import System.Process ( readProcess )+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+--+import FFICXX.Generate.Code.Cabal ( buildCabalFile+ , buildJSONFile+ )+import FFICXX.Generate.Dependency ( findModuleUnitImports+ , mkHSBOOTCandidateList+ , mkPackageConfig+ )+import FFICXX.Generate.Config ( FFICXXConfig(..)+ , SimpleBuilderConfig(..)+ )+import FFICXX.Generate.ContentMaker+import FFICXX.Generate.Type.Cabal ( Cabal(..)+ , CabalName(..)+ , AddCInc(..)+ , AddCSrc(..)+ )+import FFICXX.Generate.Type.Class ( hasProxy )+import FFICXX.Generate.Type.Module ( ClassImportHeader(..)+ , ClassModule(..)+ , PackageConfig(..)+ , TemplateClassModule(..)+ , TopLevelImportHeader(..)+ )+import FFICXX.Generate.Util ( moduleDirFile )+--++macrofy :: String -> String+macrofy = map ((\x->if x=='-' then '_' else x) . toUpper)+++simpleBuilder :: FFICXXConfig -> SimpleBuilderConfig -> IO ()+simpleBuilder cfg sbc = do+ putStrLn "----------------------------------------------------"+ putStrLn "-- fficxx code generation for Haskell-C++ binding --"+ putStrLn "----------------------------------------------------"+ let SimpleBuilderConfig+ topLevelMod+ mumap+ cabal+ classes+ toplevelfunctions+ templates+ extralibs+ extramods+ staticFiles+ = sbc+ pkgname = cabal_pkgname cabal+ putStrLn ("Generating " <> unCabalName pkgname)+ let workingDir = fficxxconfig_workingDir cfg+ installDir = fficxxconfig_installBaseDir cfg+ staticDir = fficxxconfig_staticFileDir cfg++ pkgconfig@(PkgConfig mods cihs tih tcms _tcihs _ _) =+ mkPackageConfig+ (pkgname, findModuleUnitImports mumap)+ (classes, toplevelfunctions,templates,extramods)+ (cabal_additional_c_incs cabal)+ (cabal_additional_c_srcs cabal)+ hsbootlst = mkHSBOOTCandidateList mods+ cabalFileName = unCabalName pkgname <.> "cabal"+ jsonFileName = unCabalName pkgname <.> "json"+ --+ createDirectoryIfMissing True workingDir+ createDirectoryIfMissing True installDir+ createDirectoryIfMissing True (installDir </> "src")+ createDirectoryIfMissing True (installDir </> "csrc")+ --+ putStrLn "Copying static files"+ mapM_ (\x->copyFileWithMD5Check (staticDir </> x) (installDir </> x)) staticFiles+ --+ putStrLn "Generating Cabal file"+ buildCabalFile cabal topLevelMod pkgconfig extralibs (workingDir</>cabalFileName)+ --+ putStrLn "Generating JSON file"+ buildJSONFile cabal topLevelMod pkgconfig extralibs (workingDir</>jsonFileName)+ --+ putStrLn "Generating Header file"+ let+ gen :: FilePath -> String -> IO ()+ gen file str =+ let path = workingDir </> file in withFile path WriteMode (flip hPutStrLn str)+++ gen (unCabalName pkgname <> "Type.h") (buildTypeDeclHeader (map cihClass cihs))+ for_ cihs $ \hdr -> gen+ (unHdrName (cihSelfHeader hdr))+ (buildDeclHeader (unCabalName pkgname) hdr)+ gen+ (tihHeaderFileName tih <.> "h")+ (buildTopLevelHeader (unCabalName pkgname) tih)++ putStrLn "Generating Cpp file"+ for_ cihs (\hdr -> gen (cihSelfCpp hdr) (buildDefMain hdr))+ gen (tihHeaderFileName tih <.> "cpp") (buildTopLevelCppDef tih)+ --+ putStrLn "Generating Additional Header/Source"+ for_ (cabal_additional_c_incs cabal) (\(AddCInc hdr txt) -> gen hdr txt)+ for_ (cabal_additional_c_srcs cabal) (\(AddCSrc hdr txt) -> gen hdr txt)+ --+ putStrLn "Generating RawType.hs"+ for_ mods $ \m -> gen+ (cmModule m <.> "RawType" <.> "hs")+ (prettyPrint (buildRawTypeHs m))+ --+ putStrLn "Generating FFI.hsc"+ for_ mods $ \m -> gen+ (cmModule m <.> "FFI" <.> "hsc")+ (prettyPrint (buildFFIHsc m))+ --+ putStrLn "Generating Interface.hs"+ for_ mods $ \m -> gen+ (cmModule m <.> "Interface" <.> "hs")+ (prettyPrint (buildInterfaceHs mempty m))+ --+ putStrLn "Generating Cast.hs"+ for_ mods $ \m -> gen+ (cmModule m <.> "Cast" <.> "hs")+ (prettyPrint (buildCastHs m))+ --+ putStrLn "Generating Implementation.hs"+ for_ mods $ \m -> gen+ (cmModule m <.> "Implementation" <.> "hs")+ (prettyPrint (buildImplementationHs mempty m))+ --+ putStrLn "Generating Proxy.hs"+ for_ mods $ \m ->+ when (hasProxy . cihClass . cmCIH $ m) $+ gen (cmModule m <.> "Proxy" <.> "hs") (prettyPrint (buildProxyHs m))+ --+ putStrLn "Generating Template.hs"+ for_ tcms $ \m -> gen+ (tcmModule m <.> "Template" <.> "hs")+ (prettyPrint (buildTemplateHs m))+ --+ putStrLn "Generating TH.hs"+ for_ tcms $ \m -> gen+ (tcmModule m <.> "TH" <.> "hs")+ (prettyPrint (buildTHHs m))++ --+ -- TODO: Template.hs-boot need to be generated as well+ putStrLn "Generating hs-boot file"+ for_ hsbootlst $ \m -> gen+ (m <.> "Interface" <.> "hs-boot")+ (prettyPrint (buildInterfaceHSBOOT m))+ --+ putStrLn "Generating Module summary file"+ for_ mods $ \m -> gen+ (cmModule m <.> "hs")+ (prettyPrint (buildModuleHs m))+ --+ putStrLn "Generating Top-level Module"+ gen (topLevelMod <.> "hs") (prettyPrint (buildTopLevelHs topLevelMod (mods,tcms) tih))+ --+ putStrLn "Copying generated files to target directory"+ touch (workingDir </> "LICENSE")+ copyFileWithMD5Check (workingDir </> cabalFileName) (installDir </> cabalFileName)+ copyFileWithMD5Check (workingDir </> jsonFileName) (installDir </> jsonFileName)+ copyFileWithMD5Check (workingDir </> "LICENSE") (installDir </> "LICENSE")++ copyCppFiles workingDir (csrcDir installDir) (unCabalName pkgname) pkgconfig+ for_ mods (copyModule workingDir (srcDir installDir))+ for_ tcms (copyTemplateModule workingDir (srcDir installDir))+ moduleFileCopy workingDir (srcDir installDir) $ topLevelMod <.> "hs"++ putStrLn "----------------------------------------------------"+ putStrLn "-- Code generation has been completed. Enjoy! --"+ putStrLn "----------------------------------------------------"+++-- | some dirty hack. later, we will do it with more proper approcah.++touch :: FilePath -> IO ()+touch fp = void (readProcess "touch" [fp] "")+++copyFileWithMD5Check :: FilePath -> FilePath -> IO ()+copyFileWithMD5Check src tgt = do+ b <- doesFileExist tgt+ if b+ then do+ srcmd5 <- md5 <$> L.readFile src+ tgtmd5 <- md5 <$> L.readFile tgt+ if srcmd5 == tgtmd5 then return () else copyFile src tgt+ else copyFile src tgt+++copyCppFiles :: FilePath -> FilePath -> String -> PackageConfig -> IO ()+copyCppFiles wdir ddir cprefix (PkgConfig _ cihs tih _ _tcihs acincs acsrcs) = do+ let thfile = cprefix <> "Type.h"+ tlhfile = tihHeaderFileName tih <.> "h"+ tlcppfile = tihHeaderFileName tih <.> "cpp"+ copyFileWithMD5Check (wdir </> thfile) (ddir </> thfile)+ doesFileExist (wdir </> tlhfile)+ >>= flip when (copyFileWithMD5Check (wdir </> tlhfile) (ddir </> tlhfile))+ doesFileExist (wdir </> tlcppfile)+ >>= flip when (copyFileWithMD5Check (wdir </> tlcppfile) (ddir </> tlcppfile))+ for_ cihs $ \header-> do+ let hfile = unHdrName (cihSelfHeader header)+ cppfile = cihSelfCpp header+ copyFileWithMD5Check (wdir </> hfile) (ddir </> hfile)+ copyFileWithMD5Check (wdir </> cppfile) (ddir </> cppfile)++ for_ acincs $ \(AddCInc header _) ->+ copyFileWithMD5Check (wdir </> header) (ddir </> header)++ for_ acsrcs $ \(AddCSrc csrc _) ->+ copyFileWithMD5Check (wdir </> csrc) (ddir </> csrc)+++moduleFileCopy :: FilePath -> FilePath -> FilePath -> IO ()+moduleFileCopy wdir ddir fname = do+ let (fnamebody,fnameext) = splitExtension fname+ (mdir,mfile) = moduleDirFile fnamebody+ origfpath = wdir </> fname+ (mfile',_mext') = splitExtension mfile+ newfpath = ddir </> mdir </> mfile' <> fnameext+ b <- doesFileExist origfpath+ when b $ do+ createDirectoryIfMissing True (ddir </> mdir)+ copyFileWithMD5Check origfpath newfpath+++copyModule :: FilePath -> FilePath -> ClassModule -> IO ()+copyModule wdir ddir m = do+ let modbase = cmModule m+ moduleFileCopy wdir ddir $ modbase <> ".hs"+ moduleFileCopy wdir ddir $ modbase <> ".RawType.hs"+ moduleFileCopy wdir ddir $ modbase <> ".FFI.hsc"+ moduleFileCopy wdir ddir $ modbase <> ".Interface.hs"+ moduleFileCopy wdir ddir $ modbase <> ".Cast.hs"+ moduleFileCopy wdir ddir $ modbase <> ".Implementation.hs"+ moduleFileCopy wdir ddir $ modbase <> ".Interface.hs-boot"+ when (hasProxy . cihClass . cmCIH $ m) $+ moduleFileCopy wdir ddir $ modbase <> ".Proxy.hs"+++copyTemplateModule :: FilePath -> FilePath -> TemplateClassModule -> IO ()+copyTemplateModule wdir ddir m = do+ let modbase = tcmModule m+ moduleFileCopy wdir ddir $ modbase <> ".Template.hs"+ moduleFileCopy wdir ddir $ modbase <> ".TH.hs"
+ src/FFICXX/Generate/Code/Cabal.hs view
@@ -0,0 +1,283 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Code.Cabal where++import Data.Aeson.Encode.Pretty (encodePretty)+import qualified Data.ByteString.Lazy as BL+import Data.List (intercalate, nub)+import Data.Monoid ((<>))+import Data.Text (Text)+import Data.Text.Template (substitute)+import qualified Data.Text as T (intercalate,pack,replicate,unlines)+import qualified Data.Text.Lazy as TL (toStrict)+import qualified Data.Text.IO as TIO (writeFile)+import System.FilePath ((<.>),(</>))+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+--+import FFICXX.Generate.Type.Cabal ( AddCInc(..)+ , AddCSrc(..)+ , BuildType(..)+ , CabalName(..)+ , Cabal(..)+ , GeneratedCabalInfo(..)+ )+import FFICXX.Generate.Type.Class ( hasProxy )+import FFICXX.Generate.Type.Module+-- import FFICXX.Generate.Type.PackageInterface+import FFICXX.Generate.Util+++cabalIndentation :: Text+cabalIndentation = T.replicate 23 " "+++unlinesWithIndent = T.unlines . map (cabalIndentation <>)++-- for source distribution+genCsrcFiles :: (TopLevelImportHeader,[ClassModule])+ -> [AddCInc]+ -> [AddCSrc]+ -> [String]+genCsrcFiles (tih,cmods) acincs acsrcs =+ let selfheaders' = do+ x <- cmods+ let y = cmCIH x+ return (cihSelfHeader y)+ selfheaders = nub selfheaders'+ selfcpp' = do+ x <- cmods+ let y = cmCIH x+ return (cihSelfCpp y)+ selfcpp = nub selfcpp'+ tlh = tihHeaderFileName tih <.> "h"+ tlcpp = tihHeaderFileName tih <.> "cpp"+ includeFileStrsWithCsrc = map (\x->"csrc"</> x) $+ (if (null.tihFuncs) tih then map unHdrName selfheaders else tlh:(map unHdrName selfheaders))+ ++ map (\(AddCInc hdr _) -> hdr) acincs+ cppFilesWithCsrc = map (\x->"csrc"</>x) $+ (if (null.tihFuncs) tih then selfcpp else tlcpp:selfcpp)+ ++ map (\(AddCSrc src _) -> src) acsrcs+++ in includeFileStrsWithCsrc <> cppFilesWithCsrc++-- for library+genIncludeFiles :: String -- ^ package name+ -> ([ClassImportHeader],[TemplateClassImportHeader])+ -> [AddCInc]+ -> [String]+genIncludeFiles pkgname (cih,_tcih) acincs =+ let selfheaders = map cihSelfHeader cih+ includeFileStrs = map unHdrName (selfheaders ++ map (\(AddCInc hdr _) -> HdrName hdr) acincs)+ in (pkgname<>"Type.h") : includeFileStrs++-- for library+genCppFiles :: (TopLevelImportHeader,[ClassModule])+ -> [AddCSrc]+ -> [String]+genCppFiles (tih,cmods) acsrcs =+ let selfcpp' = do+ x <- cmods+ let y = cmCIH x+ return (cihSelfCpp y)+ selfcpp = nub selfcpp'+ tlcpp = tihHeaderFileName tih <.> "cpp"+ cppFileStrs = map (\x -> "csrc" </> x) $+ (if (null.tihFuncs) tih then selfcpp else tlcpp:selfcpp)+ ++ map (\(AddCSrc src _) -> src) acsrcs+ in cppFileStrs++-- | generate exposed module list in cabal file+genExposedModules :: String -> ([ClassModule],[TemplateClassModule]) -> [String]+genExposedModules summarymod (cmods,tmods) =+ let cmodstrs = map cmModule cmods+ rawType = map ((<>".RawType") . cmModule) cmods+ ffi = map (( <>".FFI") . cmModule) cmods+ interface = map ((<>".Interface") . cmModule) cmods+ cast = map ((<>".Cast") . cmModule) cmods+ implementation = map ((<>".Implementation") . cmModule) cmods+ proxy = map ((<>".Proxy") . cmModule)+ . filter (hasProxy . cihClass . cmCIH)+ $ cmods+ template = map ((<>".Template") . tcmModule) tmods+ th = map ((<>".TH") . tcmModule) tmods+ in [summarymod]+ <> cmodstrs+ <> rawType+ <> ffi+ <> interface+ <> cast+ <> implementation+ <> proxy+ <> template+ <> th++-- | generate other modules in cabal file+genOtherModules :: [ClassModule] -> [String]+genOtherModules _cmods = [""]++-- | generate additional package dependencies.+genPkgDeps :: [CabalName] -> [String]+genPkgDeps cs = [ "base > 4 && < 5"+ , "fficxx >= 0.5"+ , "fficxx-runtime >= 0.5"+ , "template-haskell"+ ]+ ++ map unCabalName cs++++-- |+cabalTemplate :: Text+cabalTemplate =+ "Name: $pkgname\n\+ \Version: $version\n\+ \Synopsis: $synopsis\n\+ \Description: $description\n\+ \Homepage: $homepage\n\+ \$licenseField\n\+ \$licenseFileField\n\+ \Author: $author\n\+ \Maintainer: $maintainer\n\+ \Category: $category\n\+ \Tested-with: GHC >= 7.6\n\+ \$buildtype\n\+ \cabal-version: >= 2\n\+ \Extra-source-files:\n\+ \$extraFiles\n\+ \$csrcFiles\n\+ \\n\+ \$sourcerepository\n\+ \\n\+ \Library\n\+ \ default-language: Haskell2010\n\+ \ hs-source-dirs: src\n\+ \ ghc-options: -Wall -funbox-strict-fields -fno-warn-unused-do-bind -fno-warn-orphans -fno-warn-unused-imports\n\+ \ ghc-prof-options: -caf-all -auto-all\n\+ \ cxx-options: $cxxOptions\n\+ \ Build-Depends: $pkgdeps\n\+ \ Exposed-Modules:\n\+ \$exposedModules\n\+ \ Other-Modules:\n\+ \$otherModules\n\+ \ extra-lib-dirs: $extralibdirs\n\+ \ extra-libraries: $extraLibraries\n\+ \ Include-dirs: csrc $extraincludedirs\n\+ \ pkgconfig-depends: $pkgconfigDepends\n\+ \ Install-includes:\n\+ \$includeFiles\n\+ \ C-sources:\n\+ \$cppFiles\n"++++-- TODO: remove all T.pack after we switch over to Text+genCabalInfo+ :: Cabal+ -> String+ -> PackageConfig+ -> [String] -- ^ extra libs+ -> GeneratedCabalInfo+genCabalInfo cabal summarymodule pkgconfig extralibs =+ let tih = pcfg_topLevelImportHeader pkgconfig+ classmodules = pcfg_classModules pkgconfig+ cih = pcfg_classImportHeaders pkgconfig+ tmods = pcfg_templateClassModules pkgconfig+ tcih = pcfg_templateClassImportHeaders pkgconfig+ acincs = pcfg_additional_c_incs pkgconfig+ acsrcs = pcfg_additional_c_srcs pkgconfig+ extrafiles = cabal_extrafiles cabal+ in GeneratedCabalInfo {+ gci_pkgname = T.pack (unCabalName (cabal_pkgname cabal))+ , gci_version = T.pack (cabal_version cabal)+ , gci_synopsis = ""+ , gci_description = ""+ , gci_homepage = ""+ , gci_license = maybe "" T.pack (cabal_license cabal)+ , gci_licenseFile = maybe "" T.pack (cabal_licensefile cabal)+ , gci_author = ""+ , gci_maintainer = ""+ , gci_category = ""+ , gci_buildtype = case cabal_buildType cabal of+ Simple ->+ "Build-Type: Simple"+ Custom deps ->+ "Build-Type: Custom\ncustom-setup\n setup-depends: "+ <> T.pack (intercalate ", " (map unCabalName deps))+ <> "\n"+ , gci_extraFiles = map T.pack extrafiles+ , gci_csrcFiles = map T.pack $ genCsrcFiles (tih,classmodules) acincs acsrcs+ , gci_sourcerepository = ""+ , gci_cxxOptions = ["-std=c++14"]+ , gci_pkgdeps = map T.pack $ genPkgDeps (cabal_additional_pkgdeps cabal)+ , gci_exposedModules = map T.pack $ genExposedModules summarymodule (classmodules,tmods)+ , gci_otherModules = map T.pack $ genOtherModules classmodules+ , gci_extraLibDirs = map T.pack $ cabal_extralibdirs cabal+ , gci_extraLibraries = map T.pack extralibs+ , gci_extraIncludeDirs = map T.pack $ cabal_extraincludedirs cabal+ , gci_pkgconfigDepends = map T.pack $ cabal_pkg_config_depends cabal+ , gci_includeFiles = map T.pack $ genIncludeFiles (unCabalName (cabal_pkgname cabal)) (cih,tcih) acincs+ , gci_cppFiles = map T.pack $ genCppFiles (tih,classmodules) acsrcs+ }+++genCabalFile :: GeneratedCabalInfo -> Text+genCabalFile GeneratedCabalInfo {..} =+ TL.toStrict $+ substitute cabalTemplate $+ contextT [ ("licenseField" , "license: " <> gci_license)+ , ("licenseFileField", "license-file: " <> gci_licenseFile)+ , ("pkgname" , gci_pkgname)+ , ("version" , gci_version)+ , ("buildtype" , gci_buildtype)+ , ("synopsis" , gci_synopsis)+ , ("description" , gci_description)+ , ("homepage" , gci_homepage)+ , ("author" , gci_author)+ , ("maintainer" , gci_maintainer)+ , ("category" , gci_category)+ , ("sourcerepository", gci_sourcerepository)+ , ("cxxOptions" , T.intercalate " " gci_cxxOptions)+ , ("pkgdeps" , T.intercalate ", " gci_pkgdeps)+ , ("extraFiles" , unlinesWithIndent gci_extraFiles)+ , ("csrcFiles" , unlinesWithIndent gci_csrcFiles)+ , ("includeFiles" , unlinesWithIndent gci_includeFiles)+ , ("cppFiles" , unlinesWithIndent gci_cppFiles)+ , ("exposedModules" , unlinesWithIndent gci_exposedModules)+ , ("otherModules" , unlinesWithIndent gci_otherModules)+ , ("extralibdirs" , T.intercalate ", " gci_extraLibDirs)+ , ("extraincludedirs", T.intercalate ", " gci_extraIncludeDirs)+ , ("extraLibraries" , T.intercalate ", " gci_extraLibraries)+ , ("cabalIndentation", cabalIndentation)+ , ("pkgconfigDepends", T.intercalate ", " gci_pkgconfigDepends)+ ]+++-- |+buildCabalFile+ :: Cabal+ -> String+ -> PackageConfig+ -> [String] -- ^ Extra libs+ -> FilePath -- ^ Cabal file path+ -> IO ()+buildCabalFile cabal summarymodule pkgconfig extralibs cabalfile = do+ let+ cinfo = genCabalInfo cabal summarymodule pkgconfig extralibs+ txt = genCabalFile cinfo+ TIO.writeFile cabalfile txt+++-- |+buildJSONFile+ :: Cabal+ -> String+ -> PackageConfig+ -> [String] -- ^ Extra libs+ -> FilePath -- ^ JSON file path+ -> IO ()+buildJSONFile cabal summarymodule pkgconfig extralibs jsonfile = do+ let cinfo = genCabalInfo cabal summarymodule pkgconfig extralibs+ BL.writeFile jsonfile (encodePretty cinfo)
+ src/FFICXX/Generate/Code/Cpp.hs view
@@ -0,0 +1,711 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Code.Cpp where++import Data.Char ( toUpper )+import Data.Functor.Identity ( Identity )+import Data.List ( intercalate, intersperse )+import Data.Monoid ( (<>) )+--+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import FFICXX.Runtime.TH ( IsCPrimitive(CPrim, NonCPrim) )+--+import FFICXX.Generate.Code.Primitive+ ( accessorCFunSig+ , argToCallCExp+ , argsToCTypVar+ , argsToCTypVarNoSelf+ , c2Cxx+ , cxx2C+ , CFunSig(..)+ , genericFuncArgs+ , genericFuncRet+ , returnCType+ , tmplAccessorToTFun+ , tmplAllArgsToCTypVar+ , tmplAppTypeFromForm+ , tmplArgToCallCExp+ , tmplMemFuncArgToCTypVar+ , tmplMemFuncReturnCType+ , tmplReturnCType+ )+import FFICXX.Generate.Name ( aliasedFuncName+ , cppFuncName+ , ffiClassName+ , ffiTmplFuncName+ , hsTemplateMemberFunctionName+ )+import FFICXX.Generate.Type.Class ( Accessor(Getter,Setter)+ , Arg(..)+ , Class(..)+ , CPPTypes(..)+ , CTypes(..)+ , Form(FormSimple,FormNested)+ , Function(..)+ , IsConst(Const,NoConst)+ , Selfness(NoSelf,Self)+ , TemplateAppInfo(..)+ , TemplateClass(..)+ , TemplateFunction(..)+ , TemplateMemberFunction(..)+ , TopLevel(..)+ , Types(..)+ , Variable(..)+ , argsFromOpExp+ , isDeleteFunc+ , isNewFunc+ , isStaticFunc+ , isVirtualFunc+ , opSymbol+ , virtualFuncs+ )+import FFICXX.Generate.Type.Module ( ClassImportHeader(..) )+import FFICXX.Generate.Util ( toUppers )++--+--+-- Class Declaration and Definition+--++----+---- Declaration+----++---- "Class Type Declaration" Instances++typedefStmts :: String -> [R.CStatement Identity]+typedefStmts classname =+ [ R.TypeDef (R.CTVerbatim ("struct " <> classname_tag)) (R.sname classname_t)+ , R.TypeDef (R.CTVerbatim (classname_t <> " *")) (R.sname classname_p)+ , R.TypeDef (R.CTVerbatim (classname_t <> " const*")) (R.sname ("const_" <> classname_p))+ ]+ where+ classname_tag = classname <> "_tag"+ classname_t = classname <> "_t"+ classname_p = classname <> "_p"+++genCppHeaderMacroType :: Class -> [R.CStatement Identity]+genCppHeaderMacroType c =+ [ R.Comment "Opaque type definition for $classname" ]+ <> typedefStmts (ffiClassName c)+++---- "Class Declaration Virtual" Declaration++genCppHeaderMacroVirtual :: Class -> R.CMacro Identity+genCppHeaderMacroVirtual aclass =+ let funcDecls = map R.CDeclaration+ . map (funcToDecl aclass)+ . virtualFuncs+ . class_funcs+ $ aclass+ macrocname = map toUpper (ffiClassName aclass)+ macroname = macrocname <> "_DECL_VIRT"+ in R.Define (R.sname macroname) [R.sname "Type"] funcDecls++genCppHeaderMacroNonVirtual :: Class -> R.CMacro Identity+genCppHeaderMacroNonVirtual c =+ let funcDecls = map R.CDeclaration+ . map (funcToDecl c)+ . filter (not.isVirtualFunc)+ . class_funcs+ $ c+ macrocname = map toUpper (ffiClassName c)+ macroname = macrocname <> "_DECL_NONVIRT"+ in R.Define (R.sname macroname) [R.sname "Type"] funcDecls+++---- "Class Declaration Accessor" Declaration++genCppHeaderMacroAccessor :: Class -> R.CMacro Identity+genCppHeaderMacroAccessor c =+ let funcDecls = map R.CDeclaration $ accessorsToDecls (class_vars c)+ macrocname = map toUpper (ffiClassName c)+ macroname = macrocname <> "_DECL_ACCESSOR"+ in R.Define (R.sname macroname) [R.sname "Type"] funcDecls+++---- "Class Declaration Virtual/NonVirtual/Accessor" Instances++genCppHeaderInstVirtual :: (Class,Class) -> R.CStatement Identity+genCppHeaderInstVirtual (p,c) =+ let macroname = map toUpper (ffiClassName p) <> "_DECL_VIRT"+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)]++genCppHeaderInstNonVirtual :: Class -> R.CStatement Identity+genCppHeaderInstNonVirtual c =+ let macroname = map toUpper (ffiClassName c) <> "_DECL_NONVIRT"+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)]++genCppHeaderInstAccessor :: Class -> R.CStatement Identity+genCppHeaderInstAccessor c =+ let macroname = map toUpper (ffiClassName c) <> "_DECL_ACCESSOR"+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)]++----+---- Definition+----++---- "Class Definition Virtual" Declaration++genCppDefMacroVirtual :: Class -> R.CMacro Identity+genCppDefMacroVirtual aclass =+ let funcDefStr = intercalate "\n"+ . map (R.renderCStmt . funcToDef aclass)+ . virtualFuncs+ . class_funcs+ $ aclass+ macrocname = map toUpper (ffiClassName aclass)+ macroname = macrocname <> "_DEF_VIRT"+ in R.Define (R.sname macroname) [R.sname "Type"] [ R.CVerbatim funcDefStr ]++---- "Class Definition NonVirtual" Declaration++genCppDefMacroNonVirtual :: Class -> R.CMacro Identity+genCppDefMacroNonVirtual aclass =+ let funcDefStr = intercalate "\n"+ . map (R.renderCStmt . funcToDef aclass)+ . filter (not.isVirtualFunc)+ . class_funcs+ $ aclass+ macrocname = map toUpper (ffiClassName aclass)+ macroname = macrocname <> "_DEF_NONVIRT"+ in R.Define (R.sname macroname) [R.sname "Type"] [ R.CVerbatim funcDefStr ]++---- Define Macro to provide Accessor C-C++ shim code for a class++genCppDefMacroAccessor :: Class -> R.CMacro Identity+genCppDefMacroAccessor c =+ let funcDefs = concatMap (\v -> [accessorToDef v Getter,accessorToDef v Setter]) (class_vars c)+ macrocname = map toUpper (ffiClassName c)+ macroname = macrocname <> "_DEF_ACCESSOR"+ in R.Define (R.sname macroname) [R.sname "Type"] funcDefs++---- Define Macro to provide TemplateMemberFunction C-C++ shim code for a class++genCppDefMacroTemplateMemberFunction ::+ Class+ -> TemplateMemberFunction+ -> R.CMacro Identity+genCppDefMacroTemplateMemberFunction c f =+ R.Define (R.sname macroname) (map R.sname (tmf_params f))+ [ R.CExtern [R.CDeclaration decl]+ , tmplMemberFunToDef c f+ , autoinst+ ]+ where+ nsuffix = intersperse (R.NamePart "_") $ map R.NamePart (tmf_params f)+ macroname = hsTemplateMemberFunctionName c f+ decl = tmplMemberFunToDecl c f+ autoinst =+ R.CInit+ (R.CVarDecl+ R.CTAuto+ (R.CName (R.NamePart ("a_" <> macroname <> "_") : nsuffix))+ )+ (R.CVar (R.CName (R.NamePart (macroname <> "_") : nsuffix)))+++---- Invoke Macro to define Virtual/NonVirtual method for a class++genCppDefInstVirtual :: (Class, Class) -> R.CStatement Identity+genCppDefInstVirtual (p,c) =+ let macroname = map toUpper (ffiClassName p) <> "_DEF_VIRT"+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)]++genCppDefInstNonVirtual :: Class -> R.CStatement Identity+genCppDefInstNonVirtual c =+ let macroname = toUppers (ffiClassName c) <> "_DEF_NONVIRT"+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)]++genCppDefInstAccessor :: Class -> R.CStatement Identity+genCppDefInstAccessor c =+ let macroname = toUppers (ffiClassName c) <> "_DEF_ACCESSOR"+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)]++-----------------++genAllCppHeaderInclude :: ClassImportHeader -> [R.CMacro Identity]+genAllCppHeaderInclude header =+ map R.Include (cihIncludedHPkgHeadersInCPP header <> cihIncludedCPkgHeaders header)++----++-------------------------+-- TOP LEVEL FUNCTIONS --+-------------------------++topLevelDecl :: TopLevel -> R.CFunDecl Identity+topLevelDecl TopLevelFunction {..} = R.CFunDecl ret func args+ where+ ret = returnCType toplevelfunc_ret+ func = R.sname ("TopLevel_" <> maybe toplevelfunc_name id toplevelfunc_alias)+ args = argsToCTypVarNoSelf toplevelfunc_args+topLevelDecl TopLevelVariable {..} = R.CFunDecl ret func []+ where+ ret = returnCType toplevelvar_ret+ func = R.sname ("TopLevel_" <> maybe toplevelvar_name id toplevelvar_alias)++genTopLevelCppDefinition :: TopLevel -> R.CStatement Identity+genTopLevelCppDefinition tf@TopLevelFunction {..} =+ let decl = topLevelDecl tf+ body = returnCpp+ NonCPrim+ (toplevelfunc_ret)+ (R.CApp (R.CVar (R.sname toplevelfunc_name)) (map argToCallCExp toplevelfunc_args))+ in R.CDefinition Nothing decl body+genTopLevelCppDefinition tv@TopLevelVariable {..} =+ let decl = topLevelDecl tv+ body = returnCpp NonCPrim (toplevelvar_ret) (R.CVar (R.sname toplevelvar_name))+ in R.CDefinition Nothing decl body++genTmplFunCpp ::+ IsCPrimitive+ -> TemplateClass+ -> TemplateFunction+ -> R.CMacro Identity+genTmplFunCpp b t@TmplCls {..} f =+ R.Define (R.sname macroname) (map R.sname ("callmod" : tclass_params))+ [ R.CExtern [R.CDeclaration decl]+ , tmplFunToDef b t f+ , autoinst+ ]+ where+ nsuffix = intersperse (R.NamePart "_") $ map R.NamePart tclass_params+ suffix = case b of { CPrim -> "_s"; NonCPrim -> "" }+ macroname = tclass_name <> "_" <> ffiTmplFuncName f <> suffix+ decl = tmplFunToDecl b t f+ autoinst =+ R.CInit+ (R.CVarDecl+ R.CTAuto+ (R.CName (R.NamePart "a_" : R.NamePart "callmod" : R.NamePart ("_" <> tclass_name <> "_" <> ffiTmplFuncName f <> "_") : nsuffix ))+ )+ (R.CVar (R.CName (R.NamePart (tclass_name <> "_" <> ffiTmplFuncName f <> "_") : nsuffix )))++genTmplVarCpp ::+ IsCPrimitive+ -> TemplateClass+ -> Variable+ -> [ R.CMacro Identity ]+genTmplVarCpp b t@TmplCls {..} var@(Variable (Arg {..})) =+ [ gen var Getter, gen var Setter ]+ where+ nsuffix = intersperse (R.NamePart "_") $ map R.NamePart tclass_params+ suffix = case b of { CPrim -> "_s"; NonCPrim -> "" }+ gen v a =+ let f = tmplAccessorToTFun v a+ macroname = tclass_name <> "_" <> ffiTmplFuncName f <> suffix+ in R.Define (R.sname macroname) (map R.sname ("callmod" : tclass_params))+ [ R.CExtern [R.CDeclaration (tmplFunToDecl b t f)]+ , tmplVarToDef b t v a+ , R.CInit+ (R.CVarDecl+ R.CTAuto+ (R.CName (R.NamePart "a_" : R.NamePart "callmod" : R.NamePart ("_" <> tclass_name <> "_" <> ffiTmplFuncName f <> "_") : nsuffix ))+ )+ (R.CVar (R.CName (R.NamePart (tclass_name <> "_" <> ffiTmplFuncName f <> "_") : nsuffix )))+ ]++-- |+genTmplClassCpp ::+ IsCPrimitive+ -> TemplateClass+ -> ([TemplateFunction],[Variable]) -- ^ (member functions, member accessors)+ -> R.CMacro Identity+genTmplClassCpp b TmplCls {..} (fs,vs) =+ R.Define (R.sname macroname) params body+ where+ params = map R.sname ("callmod" : tclass_params)+ suffix = case b of { CPrim -> "_s"; NonCPrim -> "" }+ tname = tclass_name+ macroname = tname <> "_instance" <> suffix+ macro1 f@TFun {..} = R.CMacroApp (R.sname (tname <> "_" <> ffiTmplFuncName f <> suffix)) params+ macro1 f@TFunNew {..} = R.CMacroApp (R.sname (tname <> "_" <> ffiTmplFuncName f <> suffix)) params+ macro1 TFunDelete = R.CMacroApp (R.sname (tname <> "_delete" <> suffix)) params+ macro1 f@TFunOp {..} = R.CMacroApp (R.sname (tname <> "_" <> ffiTmplFuncName f <> suffix)) params+ body = map macro1 fs+ ++ (map macro1 . concatMap (\v -> [tmplAccessorToTFun v Getter, tmplAccessorToTFun v Setter])) vs++-- |+returnCpp ::+ IsCPrimitive+ -> Types+ -> R.CExp Identity+ -> [R.CStatement Identity]+returnCpp b ret caller =+ case ret of+ Void ->+ [ R.CExpSA caller ]+ SelfType ->+ [R.CReturn $+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.CName [ R.NamePart "Type", R.NamePart "_t" ])+ , R.CTSimple (R.sname "Type") ]+ [ R.CCast (R.CTStar (R.CTSimple (R.sname "Type"))) caller ]+ ]+ CT (CRef _) _ ->+ [R.CReturn $ R.CAddr caller ]+ CT _ _ ->+ [R.CReturn caller ]+ CPT (CPTClass c') isconst ->+ [R.CReturn $+ R.CTApp+ (case isconst of+ NoConst -> R.sname "from_nonconst_to_nonconst"+ Const -> R.sname "from_const_to_nonconst" + )+ [ R.CTSimple (R.sname (str <> "_t")), R.CTSimple (R.sname str) ]+ [ R.CCast (R.CTStar (R.CTSimple (R.sname str))) caller ]+ ]+ where str = ffiClassName c'+ CPT (CPTClassRef c') isconst ->+ [R.CReturn $+ R.CTApp+ (case isconst of+ NoConst -> R.sname "from_nonconst_to_nonconst"+ Const -> R.sname "from_const_to_nonconst"+ )+ [ R.CTSimple (R.sname (str <> "_t")), R.CTSimple (R.sname str) ]+ [ R.CAddr caller ]+ ]+ where str = ffiClassName c'+ CPT (CPTClassCopy c') isconst ->+ [R.CReturn $+ R.CTApp+ (case isconst of+ NoConst -> R.sname "from_nonconst_to_nonconst"+ Const -> R.sname "from_const_to_nonconst"+ )+ [ R.CTSimple (R.sname (str <> "_t")), R.CTSimple (R.sname str) ]+ [ R.CNew (R.sname str) [ caller ] ]+ ]+ where str = ffiClassName c'+ CPT (CPTClassMove c') isconst -> -- TODO: check whether this is working or not.+ [R.CReturn $+ R.CApp+ (R.CVar (R.sname "std::move"))+ [R.CTApp+ (case isconst of+ NoConst -> R.sname "from_nonconst_to_nonconst"+ Const -> R.sname "from_const_to_nonconst"+ )+ [ R.CTSimple (R.sname (str <> "_t")), R.CTSimple (R.sname str) ]+ [ R.CAddr caller ]+ ]+ ]+ where str = ffiClassName c'+ TemplateApp (TemplateAppInfo _ _ cpptype) ->+ [ R.CInit+ (R.CVarDecl (R.CTStar (R.CTVerbatim cpptype)) (R.sname "r"))+ (R.CNew (R.sname cpptype) [ caller ])+ , R.CReturn $+ R.CTApp+ (R.sname "static_cast")+ [ R.CTStar R.CTVoid ]+ [ R.CVar (R.sname "r") ]+ ]+ TemplateAppRef (TemplateAppInfo _ _ cpptype) ->+ [ R.CInit+ (R.CVarDecl (R.CTStar (R.CTVerbatim cpptype)) (R.sname "r"))+ (R.CNew (R.sname cpptype) [ caller ])+ , R.CReturn $+ R.CTApp+ (R.sname "static_cast")+ [ R.CTStar R.CTVoid ]+ [ R.CVar (R.sname "r") ]+ ]+ TemplateAppMove (TemplateAppInfo _ _ cpptype) ->+ [ R.CInit+ (R.CVarDecl (R.CTStar (R.CTVerbatim cpptype)) (R.sname "r"))+ (R.CNew (R.sname cpptype) [ caller ])+ , R.CReturn $+ R.CApp+ (R.CVar (R.sname "std::move"))+ [R.CTApp+ (R.sname "staic_cast")+ [ R.CTStar R.CTVoid ]+ [ R.CVar (R.sname "r") ]+ ]+ ]+ TemplateType _ ->+ error "returnCpp: TemplateType"+ TemplateParam typ ->+ [ R.CReturn $+ case b of+ CPrim -> caller+ NonCPrim ->+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.CName [ R.NamePart typ, R.NamePart "_t" ]), R.CTSimple (R.sname typ) ]+ [ R.CCast (R.CTStar (R.CTSimple (R.sname typ))) $ R.CAddr caller ]+ ]+ TemplateParamPointer typ ->+ [ R.CReturn $+ case b of+ CPrim -> caller+ NonCPrim ->+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.CName [ R.NamePart typ, R.NamePart "_t"]), R.CTSimple (R.sname typ) ]+ [ caller ]+ ]++-- Function Declaration and Definition++funcToDecl :: Class -> Function -> R.CFunDecl Identity+funcToDecl c func+ | isNewFunc func || isStaticFunc func =+ let ret = returnCType (genericFuncRet func)+ fname =+ R.CName [R.NamePart "Type", R.NamePart ("_" <> aliasedFuncName c func)]+ args = argsToCTypVarNoSelf (genericFuncArgs func)+ in R.CFunDecl ret fname args+ | otherwise =+ let ret = returnCType (genericFuncRet func)+ fname =+ R.CName [R.NamePart "Type", R.NamePart ("_" <> aliasedFuncName c func)]+ args = argsToCTypVar (genericFuncArgs func)+ in R.CFunDecl ret fname args++funcToDef :: Class -> Function -> R.CStatement Identity+funcToDef c func+ | isNewFunc func =+ let body = [ R.CInit+ (R.CVarDecl (R.CTStar (R.CTSimple (R.sname "Type"))) (R.sname "newp"))+ (R.CNew (R.sname "Type") $ map argToCallCExp (genericFuncArgs func))+ , R.CReturn $+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.CName [ R.NamePart "Type", R.NamePart "_t"]), R.CTSimple (R.sname "Type") ]+ [ R.CVar (R.sname "newp") ]+ ]+ in R.CDefinition Nothing (funcToDecl c func) body+ | isDeleteFunc func =+ let body = [ R.CDelete $+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname "Type"), R.CTSimple (R.CName [ R.NamePart "Type", R.NamePart "_t" ]) ]+ [ R.CVar (R.sname "p") ]+ ]+ in R.CDefinition Nothing (funcToDecl c func) body+ | isStaticFunc func =+ let body = returnCpp NonCPrim (genericFuncRet func) $+ R.CApp (R.CVar (R.sname (cppFuncName c func))) (map argToCallCExp (genericFuncArgs func))+ in R.CDefinition Nothing (funcToDecl c func) body+ | otherwise =+ let caller =+ R.CBinOp+ R.CArrow+ (R.CApp+ (R.CEMacroApp+ (R.sname "TYPECASTMETHOD")+ [ R.sname "Type", R.sname (aliasedFuncName c func), R.sname (class_name c) ]+ )+ [ R.CVar (R.sname "p") ]+ )+ (R.CApp (R.CVar (R.sname (cppFuncName c func))) (map argToCallCExp (genericFuncArgs func)))+ body = returnCpp NonCPrim (genericFuncRet func) caller+ in R.CDefinition Nothing (funcToDecl c func) body++-- template function declaration and definition+++tmplFunToDecl ::+ IsCPrimitive+ -> TemplateClass+ -> TemplateFunction+ -> R.CFunDecl Identity+tmplFunToDecl b t@TmplCls {..} f =+ let nsuffix = intersperse (R.NamePart "_") $ map R.NamePart tclass_params+ in case f of+ TFun {..} ->+ let ret = tmplReturnCType b tfun_ret+ func = R.CName (R.NamePart (tclass_name <> "_" <> ffiTmplFuncName f <> "_") : nsuffix)+ args = tmplAllArgsToCTypVar b Self t tfun_args+ in R.CFunDecl ret func args+ TFunNew {..} ->+ let ret = tmplReturnCType b (TemplateType t)+ func = R.CName (R.NamePart (tclass_name <> "_" <> ffiTmplFuncName f <> "_") : nsuffix)+ args = tmplAllArgsToCTypVar b NoSelf t tfun_new_args+ in R.CFunDecl ret func args+ TFunDelete ->+ let ret = R.CTVoid+ func = R.CName (R.NamePart (tclass_name <> "_delete_") : nsuffix)+ args = tmplAllArgsToCTypVar b Self t []+ in R.CFunDecl ret func args+ TFunOp {..} ->+ let ret = tmplReturnCType b tfun_ret+ func = R.CName (R.NamePart (tclass_name <> "_" <> ffiTmplFuncName f <> "_") : nsuffix)+ args = tmplAllArgsToCTypVar b Self t (argsFromOpExp tfun_opexp)+ in R.CFunDecl ret func args++-- |+tmplFunToDef ::+ IsCPrimitive+ -> TemplateClass+ -> TemplateFunction+ -> R.CStatement Identity+tmplFunToDef b t@TmplCls {..} f =+ R.CDefinition (Just R.Inline) (tmplFunToDecl b t f) body+ where+ typparams = map (R.CTSimple . R.sname) tclass_params+ body =+ case f of+ TFunNew {..} ->+ let caller =+ case tclass_cxxform of+ FormSimple tclass ->+ R.CTNew+ (R.sname tclass)+ typparams+ (map (tmplArgToCallCExp b) tfun_new_args)+ FormNested tclass inner ->+ R.CTNewI+ (R.sname tclass)+ (R.sname inner)+ typparams+ (map (tmplArgToCallCExp b) tfun_new_args)+ in [ R.CReturn $ R.CTApp (R.sname "static_cast") [R.CTStar R.CTVoid] [caller] ]+ TFunDelete ->+ [ R.CDelete $+ R.CTApp+ (R.sname "static_cast")+ [ R.CTStar $ tmplAppTypeFromForm tclass_cxxform typparams ]+ [ R.CVar (R.sname "p") ]+ ]+ TFun {..} ->+ returnCpp b (tfun_ret) $+ R.CBinOp+ R.CArrow+ (R.CTApp+ (R.sname "static_cast")+ [ R.CTStar $ tmplAppTypeFromForm tclass_cxxform typparams ]+ [ R.CVar $ R.sname "p" ]+ )+ (R.CApp+ (R.CVar (R.sname tfun_oname))+ (map (tmplArgToCallCExp b) tfun_args)+ )+ TFunOp {..} ->+ returnCpp b (tfun_ret) $+ R.CBinOp+ R.CArrow+ (R.CTApp+ (R.sname "static_cast")+ [ R.CTStar $ tmplAppTypeFromForm tclass_cxxform typparams ]+ [ R.CVar $ R.sname "p" ]+ )+ (R.CApp+ (R.CVar (R.sname ("operator" <> opSymbol tfun_opexp)))+ (map (tmplArgToCallCExp b) (argsFromOpExp tfun_opexp))+ )+++tmplVarToDef ::+ IsCPrimitive+ -> TemplateClass+ -> Variable+ -> Accessor+ -> R.CStatement Identity+tmplVarToDef b t@TmplCls {..} v@(Variable (Arg {..})) a =+ R.CDefinition (Just R.Inline) (tmplFunToDecl b t f) body+ where+ f = tmplAccessorToTFun v a+ typparams = map (R.CTSimple . R.sname) tclass_params+ body =+ case f of+ TFun {..} ->+ let varexp = R.CBinOp+ R.CArrow+ (R.CTApp+ (R.sname "static_cast")+ [ R.CTStar $ tmplAppTypeFromForm tclass_cxxform typparams ]+ [ R.CVar $ R.sname "p" ]+ )+ (R.CVar (R.sname arg_name))+ in case a of+ Getter -> returnCpp b (tfun_ret) varexp+ Setter -> [ R.CExpSA $+ R.CBinOp+ R.CAssign+ varexp+ (c2Cxx arg_type (R.CVar (R.sname "value")))+ ]+ _ -> error "tmplVarToDef: should not happen"++-- Accessor Declaration and Definition++accessorToDecl :: Variable -> Accessor -> R.CFunDecl Identity+accessorToDecl v a =+ let csig = accessorCFunSig (arg_type (unVariable v)) a+ ret = returnCType (cRetType csig)+ fname =+ R.CName [ R.NamePart "Type"+ , R.NamePart ( "_"+ <> arg_name (unVariable v)+ <> "_"+ <> case a of Getter -> "get"; Setter -> "set"+ )+ ]+ args = argsToCTypVar (cArgTypes csig)+ in R.CFunDecl ret fname args++accessorsToDecls :: [Variable] -> [R.CFunDecl Identity]+accessorsToDecls vs =+ concatMap (\v -> [accessorToDecl v Getter,accessorToDecl v Setter]) vs++accessorToDef :: Variable -> Accessor -> R.CStatement Identity+accessorToDef v a =+ let varexp =+ R.CBinOp+ R.CArrow+ (R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname "Type"), R.CTSimple (R.CName [ R.NamePart "Type", R.NamePart "_t"]) ]+ [ R.CVar (R.sname "p") ]+ )+ (R.CVar (R.sname (arg_name (unVariable v))))+ body Getter = R.CReturn $ cxx2C (arg_type (unVariable v)) varexp+ body Setter = R.CExpSA $+ R.CBinOp+ R.CAssign+ varexp+ (c2Cxx (arg_type (unVariable v)) (R.CVar (R.sname "x")))+ in R.CDefinition Nothing (accessorToDecl v a) [ body a ]+++-- Template Member Function Declaration and Definition++-- TODO: Handle simple type+tmplMemberFunToDecl :: Class -> TemplateMemberFunction -> R.CFunDecl Identity+tmplMemberFunToDecl c f =+ let nsuffix = intersperse (R.NamePart "_") $ map R.NamePart (tmf_params f)+ ret = tmplMemFuncReturnCType c (tmf_ret f)+ fname =+ R.CName (R.NamePart (hsTemplateMemberFunctionName c f <> "_") : nsuffix)+ args = map (tmplMemFuncArgToCTypVar c) ((Arg SelfType "p"):tmf_args f)+ in R.CFunDecl ret fname args++-- TODO: Handle simple type+tmplMemberFunToDef :: Class -> TemplateMemberFunction -> R.CStatement Identity+tmplMemberFunToDef c f =+ R.CDefinition (Just R.Inline) (tmplMemberFunToDecl c f) body+ where+ tparams = map (R.CTSimple . R.sname) (tmf_params f)+ body = returnCpp NonCPrim (tmf_ret f) $+ R.CBinOp+ R.CArrow+ (R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname (ffiClassName c)), R.CTSimple (R.sname (ffiClassName c <> "_t")) ]+ [ R.CVar $ R.sname "p" ]+ )+ (R.CTApp+ (R.sname (tmf_name f))+ tparams+ (map (tmplArgToCallCExp NonCPrim) (tmf_args f))+ )
+ src/FFICXX/Generate/Code/HsCast.hs view
@@ -0,0 +1,37 @@+module FFICXX.Generate.Code.HsCast where++import Language.Haskell.Exts.Build (app)+import Language.Haskell.Exts.Syntax (Decl(..),InstDecl(..))+--+import FFICXX.Generate.Name (hsClassName,typeclassName)+import FFICXX.Generate.Type.Class (Class(..),isAbstractClass)+import FFICXX.Generate.Util.HaskellSrcExts (classA+ ,cxEmpty,cxTuple,insDecl+ ,mkBind1,mkInstance,mkPVar,mkTVar,mkVar+ ,tyapp,tycon,tyPtr+ ,unqual)+-----++castBody :: [InstDecl ()]+castBody =+ [ insDecl (mkBind1 "cast" [mkPVar "x",mkPVar "f"] (app (mkVar "f") (app (mkVar "castPtr") (app (mkVar "get_fptr") (mkVar "x")))) Nothing)+ , insDecl (mkBind1 "uncast" [mkPVar "x",mkPVar "f"] (app (mkVar "f") (app (mkVar "cast_fptr_to_obj") (app (mkVar "castPtr") (mkVar "x")))) Nothing)+ ]++genHsFrontInstCastable :: Class -> Maybe (Decl ())+genHsFrontInstCastable c+ | (not.isAbstractClass) c =+ let iname = typeclassName c+ (_,rname) = hsClassName c+ a = mkTVar "a"+ ctxt = cxTuple [ classA (unqual iname) [a], classA (unqual "FPtr") [a] ]+ in Just (mkInstance ctxt "Castable" [a,tyapp tyPtr (tycon rname)] castBody)+ | otherwise = Nothing++genHsFrontInstCastableSelf :: Class -> Maybe (Decl ())+genHsFrontInstCastableSelf c+ | (not.isAbstractClass) c =+ let (cname,rname) = hsClassName c+ in Just (mkInstance cxEmpty "Castable" [tycon cname, tyapp tyPtr (tycon rname)] castBody)+ | otherwise = Nothing+
+ src/FFICXX/Generate/Code/HsFFI.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Code.HsFFI where++import Data.Maybe ( fromMaybe, mapMaybe )+import Data.Monoid ( (<>) )+import Language.Haskell.Exts.Syntax ( Decl(..), ImportDecl(..) )+import System.FilePath ( (<.>) )+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+--+import FFICXX.Generate.Code.Primitive+ ( CFunSig(..)+ , accessorCFunSig+ , genericFuncArgs+ , genericFuncRet+ , hsFFIFuncTyp+ )+import FFICXX.Generate.Dependency ( class_allparents+ , getClassModuleBase+ , getTClassModuleBase+ )+import FFICXX.Generate.Name ( aliasedFuncName+ , ffiClassName+ , hscAccessorName+ , hscFuncName+ )+import FFICXX.Generate.Type.Class ( Accessor(Getter,Setter)+ , Arg(..)+ , Class(..)+ , Function(..)+ , Selfness(NoSelf,Self)+ , TopLevel(..)+ , Variable(unVariable)+ , isAbstractClass+ , isNewFunc+ , isStaticFunc+ , virtualFuncs+ )+import FFICXX.Generate.Type.Module ( ClassImportHeader(..)+ , ClassModule(..)+ , TopLevelImportHeader(..)+ )+import FFICXX.Generate.Util ( toLowers )+import FFICXX.Generate.Util.HaskellSrcExts ( mkForImpCcall, mkImport )+++genHsFFI :: ClassImportHeader -> [Decl ()]+genHsFFI header =+ let c = cihClass header+ -- TODO: This C header information should not be necessary according to up-to-date+ -- version of Haskell FFI.+ h = cihSelfHeader header+ -- NOTE: We need to generate FFI both for member functions at the current class level+ -- and parent level. For example, consider a class A with method foo, which a+ -- subclass of B with method bar. Then, A::foo (c_a_foo) and A::bar (c_a_bar)+ -- are made into a FFI function.+ allfns = concatMap (virtualFuncs . class_funcs)+ (class_allparents c)+ <> (class_funcs c)++ in mapMaybe (hsFFIClassFunc h c) allfns+ <> concatMap+ (\v -> [hsFFIAccessor c v Getter, hsFFIAccessor c v Setter])+ (class_vars c)++hsFFIClassFunc :: HeaderName -> Class -> Function -> Maybe (Decl ())+hsFFIClassFunc headerfilename c f =+ if isAbstractClass c+ then Nothing+ else let hfile = unHdrName headerfilename+ -- TODO: Make this a separate function+ cname = ffiClassName c <> "_" <> aliasedFuncName c f+ csig = CFunSig (genericFuncArgs f) (genericFuncRet f)+ typ = if (isNewFunc f || isStaticFunc f)+ then hsFFIFuncTyp (Just (NoSelf,c)) csig+ else hsFFIFuncTyp (Just (Self,c) ) csig+ in Just (mkForImpCcall (hfile <> " " <> cname) (hscFuncName c f) typ)+++hsFFIAccessor ::Class -> Variable -> Accessor -> Decl ()+hsFFIAccessor c v a =+ let -- TODO: make this a separate function+ cname = ffiClassName c <> "_" <> arg_name (unVariable v) <> "_" <> (case a of Getter -> "get"; Setter -> "set")+ typ = hsFFIFuncTyp (Just (Self,c)) (accessorCFunSig (arg_type (unVariable v)) a)+ in mkForImpCcall cname (hscAccessorName c v a) typ+++-- import for FFI++genImportInFFI :: ClassModule -> [ImportDecl ()]+genImportInFFI = map mkMod . cmImportedModulesForFFI+ where mkMod (Left t) = mkImport (getTClassModuleBase t <.> "Template")+ mkMod (Right c) = mkImport (getClassModuleBase c <.> "RawType")+++----------------------------+-- for top level function --+----------------------------++genTopLevelFFI :: TopLevelImportHeader -> TopLevel -> Decl ()+genTopLevelFFI header tfn = mkForImpCcall (hfilename <> " TopLevel_" <> fname) cfname typ+ where (fname,args,ret) =+ case tfn of+ TopLevelFunction {..} -> (fromMaybe toplevelfunc_name toplevelfunc_alias, toplevelfunc_args, toplevelfunc_ret)+ TopLevelVariable {..} -> (fromMaybe toplevelvar_name toplevelvar_alias, [], toplevelvar_ret)+ hfilename = tihHeaderFileName header <.> "h"+ -- TODO: This must be exposed as a top-level function+ cfname = "c_" <> toLowers fname+ typ =hsFFIFuncTyp Nothing (CFunSig args ret)
+ src/FFICXX/Generate/Code/HsFrontEnd.hs view
@@ -0,0 +1,322 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Code.HsFrontEnd where++import Control.Monad.Reader+import Data.Either (lefts,rights)+import Data.List+import Data.Monoid ((<>))+import Language.Haskell.Exts.Build (app,letE,name,pApp)+import Language.Haskell.Exts.Syntax (Decl(..),ExportSpec(..),ImportDecl(..))+import System.FilePath ((<.>))+--+import FFICXX.Generate.Code.Primitive (CFunSig(..),HsFunSig(..)+ ,accessorSignature+ ,classConstraints+ ,convertCpp2HS+ ,extractArgRetTypes+ ,functionSignature+ ,hsFuncXformer+ )+import FFICXX.Generate.Name (accessorName+ ,aliasedFuncName+ ,hsClassName+ ,hscAccessorName+ ,hscFuncName+ ,hsFuncName+ ,hsFrontNameForTopLevel+ ,typeclassName+ )+import FFICXX.Generate.Dependency (class_allparents+ ,extractClassDepForTopLevel+ ,getClassModuleBase,getTClassModuleBase+ ,argumentDependency,returnDependency+ )+import FFICXX.Generate.Type.Class+import FFICXX.Generate.Type.Annotate+import FFICXX.Generate.Type.Module+import FFICXX.Generate.Util+import FFICXX.Generate.Util.HaskellSrcExts+++genHsFrontDecl :: Class -> Reader AnnotateMap (Decl ())+genHsFrontDecl c = do+ -- TODO: revive annotation+ -- for the time being, let's ignore annotation.+ -- amap <- ask+ -- let cann = maybe "" id $ M.lookup (PkgClass,class_name c) amap+ let cdecl = mkClass (classConstraints c) (typeclassName c) [mkTBind "a"] body+ sigdecl f = mkFunSig (hsFuncName c f) (functionSignature c f)+ body = map (clsDecl . sigdecl) . virtualFuncs . class_funcs $ c+ return cdecl++-------------------++genHsFrontInst :: Class -> Class -> [Decl ()]+genHsFrontInst parent child+ | (not.isAbstractClass) child =+ let idecl = mkInstance cxEmpty (typeclassName parent) [convertCpp2HS (Just child) SelfType] body+ defn f = mkBind1 (hsFuncName child f) [] rhs Nothing+ where rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName child f))+ body = map (insDecl . defn) . virtualFuncs . class_funcs $ parent+ in [idecl]+ | otherwise = []+++++---------------------++genHsFrontInstNew :: Class -- ^ only concrete class+ -> Reader AnnotateMap [Decl ()]+genHsFrontInstNew c = do+ -- amap <- ask+ let fs = filter isNewFunc (class_funcs c)+ return . flip concatMap fs $ \f ->+ let+ -- for the time being, let's ignore annotation.+ -- cann = maybe "" id $ M.lookup (PkgMethod, constructorName c) amap+ -- newfuncann = mkComment 0 cann+ rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName c f))+ in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing++genHsFrontInstNonVirtual :: Class -> [Decl ()]+genHsFrontInstNonVirtual c =+ flip concatMap nonvirtualFuncs $ \f ->+ let rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName c f))+ in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing+ where nonvirtualFuncs = nonVirtualNotNewFuncs (class_funcs c)++-----++genHsFrontInstStatic :: Class -> [Decl ()]+genHsFrontInstStatic c =+ flip concatMap (staticFuncs (class_funcs c)) $ \f ->+ let rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName c f))+ in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing++-----++genHsFrontInstVariables :: Class -> [Decl ()]+genHsFrontInstVariables c =+ flip concatMap (class_vars c) $ \v ->+ let rhs accessor =+ app (mkVar (case accessor of Getter -> "xform0"; _ -> "xform1"))+ (mkVar (hscAccessorName c v accessor))+ in mkFun (accessorName c v Getter) (accessorSignature c v Getter) [] (rhs Getter) Nothing+ <> mkFun (accessorName c v Setter) (accessorSignature c v Setter) [] (rhs Setter) Nothing+++++--------------------------++hsClassRawType :: Class -> [Decl ()]+hsClassRawType c =+ [ mkData rawname [] [] Nothing+ , mkNewtype highname [] [qualConDecl Nothing Nothing (conDecl highname [tyapp tyPtr rawtype])] mderiv+ , mkInstance cxEmpty "FPtr" [hightype]+ [ insType (tyapp (tycon "Raw") hightype) rawtype+ , insDecl (mkBind1 "get_fptr" [pApp (name highname) [mkPVar "ptr"]] (mkVar "ptr") Nothing)+ , insDecl (mkBind1 "cast_fptr_to_obj" [] (con highname) Nothing)+ ]++ ]+ where (highname,rawname) = hsClassName c+ hightype = tycon highname+ rawtype = tycon rawname+ mderiv = Just (mkDeriving [i_eq,i_ord,i_show])+ where i_eq = irule Nothing Nothing (ihcon (unqual "Eq"))+ i_ord = irule Nothing Nothing (ihcon (unqual "Ord"))+ i_show = irule Nothing Nothing (ihcon (unqual "Show"))+++------------+-- upcast --+------------++genHsFrontUpcastClass :: Class -> [Decl ()]+genHsFrontUpcastClass c = mkFun ("upcast"<>highname) typ [mkPVar "h"] rhs Nothing+ where (highname,rawname) = hsClassName c+ hightype = tycon highname+ rawtype = tycon rawname+ iname = typeclassName c+ a_bind = unkindedVar (name "a")+ a_tvar = mkTVar "a"+ typ = tyForall (Just [a_bind])+ (Just (cxTuple [classA (unqual "FPtr") [a_tvar], classA (unqual iname) [a_tvar]]))+ (tyfun a_tvar hightype)+ rhs = letE [ pbind (mkPVar "fh") (app (mkVar "get_fptr") (mkVar "h")) Nothing+ , pbind (mkPVarSig "fh2" (tyapp tyPtr rawtype))+ (app (mkVar "castPtr") (mkVar "fh")) Nothing+ ]+ (mkVar "cast_fptr_to_obj" `app` mkVar "fh2")+++--------------+-- downcast --+--------------++genHsFrontDowncastClass :: Class -> [Decl ()]+genHsFrontDowncastClass c = mkFun ("downcast"<>highname) typ [mkPVar "h"] rhs Nothing+ where (highname,_rawname) = hsClassName c+ hightype = tycon highname+ iname = typeclassName c+ a_bind = unkindedVar (name "a")+ a_tvar = mkTVar "a"+ typ = tyForall (Just [a_bind])+ (Just (cxTuple [classA (unqual "FPtr") [a_tvar], classA (unqual iname) [a_tvar]]))+ (tyfun hightype a_tvar)+ rhs = letE [ pbind (mkPVar "fh") (app (mkVar "get_fptr") (mkVar "h")) Nothing+ , pbind (mkPVar "fh2") (app (mkVar "castPtr") (mkVar "fh")) Nothing+ ]+ (mkVar "cast_fptr_to_obj" `app` mkVar "fh2")+++------------------------+-- Top Level Function --+------------------------+++genTopLevelDef :: TopLevel -> [Decl ()]+genTopLevelDef f@TopLevelFunction {..} =+ let fname = hsFrontNameForTopLevel f+ HsFunSig typs assts =+ extractArgRetTypes+ Nothing+ False+ (CFunSig toplevelfunc_args toplevelfunc_ret)+ sig = tyForall Nothing (Just (cxTuple assts)) (foldr1 tyfun typs)+ xformerstr = let len = length toplevelfunc_args in if len > 0 then "xform" <> show (len-1) else "xformnull"+ cfname = "c_" <> toLowers fname+ rhs = app (mkVar xformerstr) (mkVar cfname)++ in mkFun fname sig [] rhs Nothing+genTopLevelDef v@TopLevelVariable {..} =+ let fname = hsFrontNameForTopLevel v+ cfname = "c_" <> toLowers fname+ rtyp = convertCpp2HS Nothing toplevelvar_ret+ sig = tyapp (tycon "IO") rtyp+ rhs = app (mkVar "xformnull") (mkVar cfname)++ in mkFun fname sig [] rhs Nothing+++------------+-- Export --+------------++genExport :: Class -> [ExportSpec ()]+genExport c =+ let espec n = if null . (filter isVirtualFunc) $ (class_funcs c)+ then eabs nonamespace (unqual n)+ else ethingall (unqual n)+ in if isAbstractClass c+ then [ espec (typeclassName c) ]+ else [ ethingall (unqual ((fst.hsClassName) c))+ , espec (typeclassName c)+ , evar (unqual ("upcast" <> (fst.hsClassName) c))+ , evar (unqual ("downcast" <> (fst.hsClassName) c)) ]+ <> genExportConstructorAndNonvirtual c+ <> genExportStatic c++-- | constructor and non-virtual function+genExportConstructorAndNonvirtual :: Class -> [ExportSpec ()]+genExportConstructorAndNonvirtual c = map (evar . unqual) fns+ where fs = class_funcs c+ fns = map (aliasedFuncName c) (constructorFuncs fs+ <> nonVirtualNotNewFuncs fs)++-- | staic function export list+genExportStatic :: Class -> [ExportSpec ()]+genExportStatic c = map (evar . unqual) fns+ where fs = class_funcs c+ fns = map (aliasedFuncName c) (staticFuncs fs)+++------------+-- Import --+------------++genExtraImport :: ClassModule -> [ImportDecl ()]+genExtraImport cm = map mkImport (cmExtraImport cm)+++genImportInModule :: Class -> [ImportDecl ()]+genImportInModule x = map (\y -> mkImport (getClassModuleBase x<.>y)) ["RawType","Interface","Implementation"]+++genImportInInterface :: ClassModule -> [ImportDecl ()]+genImportInInterface m =+ let modlstraw = cmImportedModulesRaw m+ modlstparent = cmImportedModulesHighNonSource m+ modlsthigh = cmImportedModulesHighSource m+ in [mkImport (cmModule m <.> "RawType")]+ <> flip map modlstraw+ (\case+ Left t -> mkImport (getTClassModuleBase t <.> "Template")+ Right c -> mkImport (getClassModuleBase c <.>"RawType")+ )+ <> flip map modlstparent+ (\case+ Left t -> mkImport (getTClassModuleBase t <.> "Template")+ Right c -> mkImport (getClassModuleBase c <.>"Interface")+ )+ <> flip map modlsthigh+ (\case+ Left t -> -- TODO: *.Template in the same package needs to have hs-boot.+ -- Currently, we do not have it yet.+ mkImport (getTClassModuleBase t <.> "Template")+ Right c -> mkImportSrc (getClassModuleBase c<.>"Interface")+ )++-- |+genImportInCast :: ClassModule -> [ImportDecl ()]+genImportInCast m = [ mkImport (cmModule m <.> "RawType")+ , mkImport (cmModule m <.> "Interface") ]++-- |+genImportInImplementation :: ClassModule -> [ImportDecl ()]+genImportInImplementation m =+ let modlstraw' = cmImportedModulesForFFI m+ modlsthigh = nub $ map Right $ class_allparents $ cihClass $ cmCIH m+ modlstraw = filter (not.(flip elem modlsthigh)) modlstraw'+ in [ mkImport (cmModule m <.> "RawType")+ , mkImport (cmModule m <.> "FFI")+ , mkImport (cmModule m <.> "Interface")+ , mkImport (cmModule m <.> "Cast") ]+ <> concatMap (\case Left t -> [mkImport (getTClassModuleBase t <.> "Template")]; Right c -> map (\y -> mkImport (getClassModuleBase c<.>y)) ["RawType","Cast","Interface"]) modlstraw+ <> concatMap (\case Left t -> [mkImport (getTClassModuleBase t <.> "Template")]; Right c -> map (\y -> mkImport (getClassModuleBase c<.>y)) ["RawType","Cast","Interface"]) modlsthigh+++-- | generate import list for a given top-level function+-- currently this may generate duplicate import list.+-- TODO: eliminate duplicated imports.+genImportForTopLevel :: TopLevel -> [ImportDecl ()]+genImportForTopLevel f =+ let dep4func = extractClassDepForTopLevel f+ ecs = returnDependency dep4func ++ argumentDependency dep4func+ cmods = nub $ map getClassModuleBase $ rights ecs+ tmods = nub $ map getTClassModuleBase $ lefts ecs+ in concatMap (\x -> map (\y -> mkImport (x<.>y)) ["RawType","Cast","Interface"]) cmods+ <> concatMap (\x -> map (\y -> mkImport (x<.>y)) ["Template"]) tmods++-- | generate import list for top level module+genImportInTopLevel ::+ String+ -> ([ClassModule],[TemplateClassModule])+ -> TopLevelImportHeader+ -> [ImportDecl ()]+genImportInTopLevel modname (mods,tmods) tih =+ let tfns = tihFuncs tih+ in map (mkImport . cmModule) mods+ ++ if null tfns+ then []+ else map mkImport [ "Foreign.C", "Foreign.Ptr", "FFICXX.Runtime.Cast" ]+ ++ map (\c -> mkImport (modname <.> (fst.hsClassName.cihClass) c <.> "RawType")) (tihClassDep tih)+ ++ map (\m -> mkImport (tcmModule m <.> "Template")) tmods+ ++ concatMap genImportForTopLevel tfns+
+ src/FFICXX/Generate/Code/HsProxy.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings #-}++module FFICXX.Generate.Code.HsProxy where++import Language.Haskell.Exts.Build ( app, doE, listE, qualStmt, strE )+import qualified Data.List as L ( foldr1 )+import Language.Haskell.Exts.Syntax ( Decl(..) )+--+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import FFICXX.Generate.Util.HaskellSrcExts+ ( con, inapp, mkFun, mkVar+ , op, qualifier+ , tyapp, tycon, tylist+ )+++genProxyInstance :: [Decl ()]+genProxyInstance =+ mkFun fname sig [] rhs Nothing+ where fname = "genImplProxy"+ v = mkVar+ sig = tycon "Q" `tyapp` tylist (tycon "Dec")+ rhs = doE [foreignSrcStmt, qualStmt retstmt]+ foreignSrcStmt =+ qualifier $+ (v "addModFinalizer")+ `app` ( v "addForeignSource"+ `app` con "LangCxx"+ `app` (L.foldr1 (\x y -> inapp x (op "++") y)+ [ includeStatic ]+ )+ )+ where+ includeStatic =+ strE $ concatMap (<> "\n")+ [ R.renderCMacro (R.Include "MacroPatternMatch.h") ]+ retstmt = v "pure" `app` listE []
+ src/FFICXX/Generate/Code/HsTemplate.hs view
@@ -0,0 +1,440 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Code.HsTemplate where++import Data.Monoid ( (<>) )+import qualified Data.List as L ( foldr1 )+import Language.Haskell.Exts.Build ( app, binds, caseE, doE+ , lamE, letE, letStmt, listE, name+ , pApp, paren, pTuple+ , qualStmt, strE, tuple, wildcard+ )+import Language.Haskell.Exts.Syntax ( Boxed(Boxed), Decl(..), ImportDecl(..), Type(TyTuple) )+import System.FilePath ( (<.>) )+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import FFICXX.Runtime.TH ( IsCPrimitive(CPrim,NonCPrim) )+--+import FFICXX.Generate.Code.Cpp ( genTmplClassCpp+ , genTmplFunCpp+ , genTmplVarCpp+ )+import FFICXX.Generate.Code.Primitive ( functionSignatureT+ , functionSignatureTT+ , functionSignatureTMF+ , tmplAccessorToTFun+ )+import FFICXX.Generate.Code.HsCast ( castBody )+import FFICXX.Generate.Dependency ( getClassModuleBase+ , getTClassModuleBase+ , mkModuleDepRaw+ , mkModuleDepHighSource+ )+import FFICXX.Generate.Name ( ffiTmplFuncName+ , hsTemplateClassName+ , hsTemplateMemberFunctionName+ , hsTemplateMemberFunctionNameTH+ , hsTmplFuncName+ , hsTmplFuncNameTH+ , tmplAccessorName+ , typeclassNameT+ )+import FFICXX.Generate.Type.Class ( Accessor(Getter,Setter)+ , Arg(..)+ , Class(..)+ , TemplateClass(..)+ , TemplateFunction(..)+ , TemplateMemberFunction(..)+ , Variable(..)+ , Types(Void)+ )+import FFICXX.Generate.Type.Module ( ClassImportHeader(..)+ , TemplateClassImportHeader(..)+ )+import FFICXX.Generate.Util.HaskellSrcExts+ ( bracketExp+ , con, conDecl, cxEmpty, clsDecl+ , generator+ , inapp, insDecl, insType+ , match, mkBind1, mkTBind, mkData, mkNewtype+ , mkFun, mkFunSig, mkClass, mkImport, mkInstance+ , mkPVar, mkTVar, mkVar+ , op, pbind_+ , qualConDecl, qualifier+ , tyapp, tycon, tyfun, tylist, tyPtr+ , typeBracket+ )+++------------------------------+-- Template member function --+------------------------------++genTemplateMemberFunctions :: ClassImportHeader -> [Decl ()]+genTemplateMemberFunctions cih =+ let c = cihClass cih+ in concatMap (\f -> genTMFExp c f <> genTMFInstance cih f) (class_tmpl_funcs c)++-- TODO: combine this with genTmplInstance+genTMFExp :: Class -> TemplateMemberFunction -> [Decl ()]+genTMFExp c f = mkFun nh sig (tvars_p ++ [p "suffix"]) rhs (Just bstmts)+ where+ nh = hsTemplateMemberFunctionNameTH c f+ v = mkVar+ p = mkPVar+ itps = zip ([1..]::[Int]) (tmf_params f)+ tvars = map (\(i,_) -> "typ" ++ show i) itps+ nparams = length itps+ tparams = if nparams == 1 then tycon "Type" else TyTuple () Boxed (replicate nparams (tycon "Type"))+ sig = foldr1 tyfun [tparams , tycon "String", tyapp (tycon "Q") (tycon "Exp") ]+ tvars_p = if nparams == 1 then map p tvars else [pTuple (map p tvars)]+ lit' = strE (hsTemplateMemberFunctionName c f <> "_")+ lam = lamE [p "n"] ( lit' `app` v "<>" `app` v "n")+ rhs = app (v "mkTFunc") $+ let typs = if nparams == 1 then map v tvars else [tuple (map v tvars)]+ in tuple (typs ++ [ v "suffix", lam, v "tyf"])+ sig' = functionSignatureTMF c f+ tassgns = map (\(i,tp) -> pbind_ (p tp) (v "pure" `app` (v ("typ" ++ show i)))) itps+ bstmts = binds [ mkBind1 "tyf" [mkPVar "n"]+ (letE tassgns+ (bracketExp (typeBracket sig')))+ Nothing+ ]++genTMFInstance :: ClassImportHeader -> TemplateMemberFunction -> [Decl ()]+genTMFInstance cih f =+ mkFun+ fname+ sig+ [p "isCprim", pTuple [p "qtyp", p "param"]]+ rhs+ Nothing+ where+ c = cihClass cih+ fname = "genInstanceFor_" <> hsTemplateMemberFunctionName c f+ p = mkPVar+ v = mkVar+ sig = tycon "IsCPrimitive"+ `tyfun` TyTuple () Boxed [tycon "Q" `tyapp` tycon "Type", tycon "TemplateParamInfo"]+ `tyfun` (tycon "Q" `tyapp` tylist (tycon "Dec"))+ rhs = doE [suffixstmt, qtypstmt, genstmt, foreignSrcStmt, letStmt lststmt, qualStmt retstmt]+ suffixstmt = letStmt [ pbind_ (p "suffix") (v "tpinfoSuffix" `app` v "param" ) ]+ qtypstmt = generator (p "typ") (v "qtyp")+ genstmt = generator+ (p "f1")+ (v "mkMember" `app` ( strE (hsTemplateMemberFunctionName c f <> "_")+ `app` v "<>"+ `app` v "suffix"+ )+ `app` v (hsTemplateMemberFunctionNameTH c f)+ `app` v "typ"+ `app` v "suffix"+ )+ lststmt = [ pbind_ (p "lst") (listE ([v "f1"])) ]+ retstmt = v "pure" `app` v "lst"+ -- TODO: refactor out the following code.+ foreignSrcStmt =+ qualifier $+ (v "addModFinalizer")+ `app` ( v "addForeignSource"+ `app` con "LangCxx"+ `app` (L.foldr1 (\x y -> inapp x (op "++") y)+ [ includeStatic+ , includeDynamic+ , namespaceStr+ , strE (hsTemplateMemberFunctionName c f)+ , strE "("+ , v "suffix"+ , strE ")\n"+ ]+ )+ )+ where+ includeStatic =+ strE $ concatMap ((<>"\n") . R.renderCMacro . R.Include) $+ [ HdrName "MacroPatternMatch.h", cihSelfHeader cih ]+ <> cihIncludedHPkgHeadersInCPP cih+ <> cihIncludedCPkgHeaders cih+ includeDynamic =+ letE+ [ pbind_ (p "headers") (v "tpinfoCxxHeaders" `app` v "param" )+ , pbind_ (pApp (name "f") [p "x"])+ (v "renderCMacro" `app` (con "Include" `app` v "x"))+ ]+ (v "concatMap" `app` v "f" `app` v "headers")+ namespaceStr =+ letE+ [ pbind_ (p "nss") (v "tpinfoCxxNamespaces" `app` v "param" )+ , pbind_ (pApp (name "f") [p "x"])+ (v "renderCStmt" `app` (con "UsingNamespace" `app` v "x"))+ ]+ (v "concatMap" `app` v "f" `app` v "nss")++--------------------+-- Template Class --+--------------------++genImportInTemplate :: TemplateClass -> [ImportDecl ()]+genImportInTemplate t0 =+ let+ deps_raw = mkModuleDepRaw (Left t0)+ deps_high = mkModuleDepHighSource (Left t0)+ in flip map deps_raw+ (\case+ Left t -> mkImport (getTClassModuleBase t <.> "Template")+ Right c -> mkImport (getClassModuleBase c <.> "RawType")+ )+ <> flip map deps_high+ (\case+ Left t -> mkImport (getTClassModuleBase t <.> "Template")+ Right c -> mkImport (getClassModuleBase c <.> "Interface")+ )++-- |+genTmplInterface :: TemplateClass -> [Decl ()]+genTmplInterface t =+ [ mkData rname (map mkTBind tps) [] Nothing+ , mkNewtype hname (map mkTBind tps)+ [ qualConDecl Nothing Nothing (conDecl hname [tyapp tyPtr rawtype]) ] Nothing+ , mkClass cxEmpty (typeclassNameT t) (map mkTBind tps) methods+ , mkInstance cxEmpty "FPtr" [ hightype ] fptrbody+ , mkInstance cxEmpty "Castable" [ hightype, tyapp tyPtr rawtype ] castBody+ ]+ where+ (hname,rname) = hsTemplateClassName t+ tps = tclass_params t+ fs = tclass_funcs t+ vfs = tclass_vars t+ rawtype = foldl1 tyapp (tycon rname : map mkTVar tps)+ hightype = foldl1 tyapp (tycon hname : map mkTVar tps)+ sigdecl f = mkFunSig (hsTmplFuncName t f) (functionSignatureT t f)+ sigdeclV vf = let f_g = tmplAccessorToTFun vf Getter+ f_s = tmplAccessorToTFun vf Setter+ in [sigdecl f_g, sigdecl f_s]+ methods = map (clsDecl . sigdecl) fs ++ (map clsDecl . concatMap sigdeclV) vfs++ fptrbody = [ insType (tyapp (tycon "Raw") hightype) rawtype+ , insDecl (mkBind1 "get_fptr" [pApp (name hname) [mkPVar "ptr"]] (mkVar "ptr") Nothing )+ , insDecl (mkBind1 "cast_fptr_to_obj" [] (con hname) Nothing)+ ]++-- |+genImportInTH :: TemplateClass -> [ImportDecl ()]+genImportInTH t0 =+ let+ deps_raw = mkModuleDepRaw (Left t0)+ deps_high = mkModuleDepHighSource (Left t0)+ in flip concatMap deps_raw+ (\case+ Left t -> [mkImport (getTClassModuleBase t <.> "Template")]+ Right c -> map (\y -> mkImport (getClassModuleBase c <.> y)) ["RawType","Cast","Interface"]+ )+ <> flip concatMap deps_high+ (\case+ Left t -> [mkImport (getTClassModuleBase t <.> "Template")]+ Right c -> map (\y -> mkImport (getClassModuleBase c <.> y)) ["RawType","Cast","Interface"]+ )++-- |+genTmplImplementation :: TemplateClass -> [Decl ()]+genTmplImplementation t =+ concatMap gen (tclass_funcs t) ++ concatMap genV (tclass_vars t)+ where+ v = mkVar+ p = mkPVar+ itps = zip ([1..]::[Int]) (tclass_params t)+ tvars = map (\(i,_) -> "typ" ++ show i) itps+ nparams = length itps+ tparams = if nparams == 1 then tycon "Type" else TyTuple () Boxed (replicate nparams (tycon "Type"))+ sig = foldr1 tyfun [tparams , tycon "String", tyapp (tycon "Q") (tycon "Exp") ]+ tvars_p = if nparams == 1 then map p tvars else [pTuple (map p tvars)]+ prefix = tclass_name t++ gen f = mkFun nh sig (tvars_p ++ [p "suffix"]) rhs (Just bstmts)+ where nh = hsTmplFuncNameTH t f+ nc = ffiTmplFuncName f+ lit' = strE (prefix<>"_"<>nc)+ lam = lamE [p "n"] ( lit' `app` v "<>" `app` v "n")+ rhs = app (v "mkTFunc") $+ let typs = if nparams == 1 then map v tvars else [tuple (map v tvars)]+ in tuple (typs ++ [ v "suffix", lam, v "tyf"])+ sig' = functionSignatureTT t f+ tassgns = map (\(i,tp) -> pbind_ (p tp) (v "pure" `app` (v ("typ" ++ show i)))) itps+ bstmts = binds [ mkBind1 "tyf" [wildcard] -- [mkPVar "n"]+ (letE tassgns+ (bracketExp (typeBracket sig')))+ Nothing+ ]++ genV vf = let f_g = tmplAccessorToTFun vf Getter+ f_s = tmplAccessorToTFun vf Setter+ in gen f_g ++ gen f_s++-- |+genTmplInstance ::+ TemplateClassImportHeader+ -> [Decl ()]+genTmplInstance tcih =+ mkFun+ fname+ sig+ (p "isCprim" : zipWith (\x y -> pTuple [p x,p y]) qtvars pvars)+ rhs+ Nothing+ where+ t = tcihTClass tcih+ fs = tclass_funcs t+ vfs = tclass_vars t+ tname = tclass_name t+ fname = "gen" <> tname <> "InstanceFor"+ p = mkPVar+ v = mkVar+ itps = zip ([1..]::[Int]) (tclass_params t)+ tvars = map (\(i,_) -> "typ" ++ show i) itps+ qtvars = map (\(i,_) -> "qtyp" ++ show i) itps+ pvars = map (\(i,_) -> "param" ++ show i) itps+ nparams = length itps+ typs_v = if nparams == 1 then v (tvars !! 0) else tuple (map v tvars)+ params_l = listE (map v pvars)+ sig = foldr1 tyfun $+ [ tycon "IsCPrimitive" ]+ ++ replicate+ nparams+ (TyTuple () Boxed [ tycon "Q" `tyapp` tycon "Type", tycon "TemplateParamInfo" ])+ ++ [ tycon "Q" `tyapp` tylist (tycon "Dec") ]+ nfs = zip ([1..] :: [Int]) fs+ nvfs = zip ([1..] :: [Int]) vfs+ --------------------------+ -- final RHS expression --+ --------------------------+ rhs = doE ( [ paramsstmt, suffixstmt ]+ <> [ generator (p "callmod_") (v "fmap" `app` v "loc_module" `app` (v "location"))+ , letStmt [ pbind_ (p "callmod")+ (v "dot2_" `app` v "callmod_") ]+ ]+ <> map genqtypstmt (zip tvars qtvars)+ <> map genstmt nfs+ <> concatMap genvarstmt nvfs+ <> [foreignSrcStmt, letStmt lststmt, qualStmt retstmt]+ )+ --------------------------+ paramsstmt = letStmt [ pbind_+ (p "params")+ (v "map" `app` (v "tpinfoSuffix") `app` params_l)+ ]++ suffixstmt = letStmt [ pbind_+ (p "suffix")+ ( v "concatMap"+ `app` (lamE [p "x"] (inapp (strE "_") (op "++") (v "tpinfoSuffix" `app` v "x")))+ `app` params_l+ )+ ]++ genqtypstmt (tvar,qtvar) = generator (p tvar) (v qtvar)+ gen prefix nm f n =+ generator+ (p (prefix<>show n))+ (v nm `app` strE (hsTmplFuncName t f)+ `app` v (hsTmplFuncNameTH t f)+ `app` typs_v+ `app` v "suffix"+ )+ genstmt (n,f@TFun {..}) = gen "f" "mkMember" f n+ genstmt (n,f@TFunNew {..}) = gen "f" "mkNew" f n+ genstmt (n,f@TFunDelete) = gen "f" "mkDelete" f n+ genstmt (n,f@TFunOp {..}) = gen "f" "mkMember" f n+ genvarstmt (n,vf) =+ let+ Variable (Arg {..}) = vf+ f_g = TFun { tfun_ret = arg_type+ , tfun_name = tmplAccessorName vf Getter+ , tfun_oname = tmplAccessorName vf Getter+ , tfun_args = []+ }+ f_s = TFun { tfun_ret = Void+ , tfun_name = tmplAccessorName vf Setter+ , tfun_oname = tmplAccessorName vf Setter+ , tfun_args = [Arg arg_type "value"]+ }+ in [ gen "vf" "mkMember" f_g (2*n-1)+ , gen "vf" "mkMember" f_s (2*n)+ ]++ lststmt = let mkElems prefix xs = map (v . (\n->prefix<>show n) . fst) xs+ in [ pbind_+ (p "lst")+ (listE ( mkElems "f" nfs+ <> mkElems "vf" (concatMap (\(n,vf) -> [(2*n-1,vf),(2*n,vf)]) nvfs)+ )+ )+ ]++ -- TODO: refactor out the following code.+ foreignSrcStmt =+ qualifier $+ (v "addModFinalizer")+ `app` ( v "addForeignSource"+ `app` con "LangCxx"+ `app` (L.foldr1 (\x y -> inapp x (op "++") y)+ [ includeStatic+ , includeDynamic+ , namespaceStr+ , strE (tname <> "_instance")+ , paren $+ caseE+ (v "isCprim")+ [ match (p "CPrim") (strE "_s")+ , match (p "NonCPrim") (strE "")+ ]+ , strE "("+ , v "intercalate" `app`+ strE ", " `app`+ paren (inapp (v "callmod") (op ":") (v "params"))+ , strE ")\n"+ ]+ )+ )+ where+ -- temporary+ body = map R.renderCMacro $+ map R.Include (tcihCxxHeaders tcih)+ ++ map (genTmplFunCpp NonCPrim t) fs+ ++ map (genTmplFunCpp CPrim t) fs+ ++ concatMap (genTmplVarCpp NonCPrim t) vfs+ ++ concatMap (genTmplVarCpp CPrim t) vfs+ ++ [ genTmplClassCpp NonCPrim t (fs,vfs)+ , genTmplClassCpp CPrim t (fs,vfs)+ ]+ includeStatic =+ strE $ concatMap (<> "\n")+ ( [ R.renderCMacro (R.Include (HdrName "MacroPatternMatch.h")) ]+ ++ body+ )+ cxxHeaders = v "concatMap" `app` (v "tpinfoCxxHeaders") `app` params_l+ cxxNamespaces = v "concatMap" `app` (v "tpinfoCxxNamespaces") `app` params_l+ includeDynamic =+ letE+ [ pbind_ (p "headers") cxxHeaders+ , pbind_ (pApp (name "f") [p "x"])+ (v "renderCMacro" `app` (con "Include" `app` v "x"))+ ]+ (v "concatMap" `app` v "f" `app` v "headers")+ namespaceStr =+ letE+ [ pbind_ (p "nss") cxxNamespaces+ , pbind_ (pApp (name "f") [p "x"])+ (v "renderCStmt" `app` (con "UsingNamespace" `app` v "x"))+ ]+ (v "concatMap" `app` v "f" `app` v "nss")++ retstmt = v "pure"+ `app` listE [ v "mkInstance"+ `app` listE []+ `app` foldl1+ (\f x -> con "AppT" `app` f `app` x)+ (v "con" `app` strE (typeclassNameT t) : map v tvars)+ `app` (v "lst")+ ]
+ src/FFICXX/Generate/Code/Primitive.hs view
@@ -0,0 +1,1006 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Code.Primitive where++import Control.Monad.Trans.State ( runState, put, get )+import Data.Functor.Identity ( Identity )+import Data.Monoid ( (<>) )+import Language.Haskell.Exts.Syntax ( Asst(..), Context, Type(..) )+--+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import FFICXX.Runtime.TH ( IsCPrimitive(CPrim,NonCPrim) )+--+import FFICXX.Generate.Name ( ffiClassName+ , hsClassName+ , hsClassNameForTArg+ , hsTemplateClassName+ , tmplAccessorName+ , typeclassName+ , typeclassNameFromStr+ )+import FFICXX.Generate.Type.Class ( Accessor(Getter,Setter)+ , Arg(..)+ , Class(..)+ , CPPTypes(..)+ , CTypes(..)+ , Form(..)+ , Function(..)+ , IsConst(Const,NoConst)+ , Selfness(NoSelf,Self)+ , TemplateAppInfo(..)+ , TemplateArgType(TArg_TypeParam)+ , TemplateClass(..)+ , TemplateFunction(..)+ , TemplateMemberFunction(..)+ , Types(..)+ , Variable(..)+ , argsFromOpExp+ , isNonVirtualFunc+ , isVirtualFunc+ )+import FFICXX.Generate.Util.HaskellSrcExts+ ( classA, cxTuple, mkTVar, mkVar, parenSplice, tyapp, tycon, tyfun, tyPtr, tySplice+ , unit_tycon, unqual )+++data CFunSig = CFunSig { cArgTypes :: [Arg]+ , cRetType :: Types+ }++data HsFunSig = HsFunSig { hsSigTypes :: [Type ()]+ , hsSigConstraints :: [Asst ()]+ }++ctypToCType :: CTypes -> IsConst -> R.CType Identity+ctypToCType ctyp isconst =+ let typ = case ctyp of+ CTBool -> R.CTSimple $ R.sname "bool"+ CTChar -> R.CTSimple $ R.sname "char"+ CTClock -> R.CTSimple $ R.sname "clock_t"+ CTDouble -> R.CTSimple $ R.sname "double"+ CTFile -> R.CTSimple $ R.sname "FILE"+ CTFloat -> R.CTSimple $ R.sname "float"+ CTFpos -> R.CTSimple $ R.sname "fpos_t"+ CTInt -> R.CTSimple $ R.sname "int"+ CTIntMax -> R.CTSimple $ R.sname "intmax_t"+ CTIntPtr -> R.CTSimple $ R.sname "intptr_t"+ CTJmpBuf -> R.CTSimple $ R.sname "jmp_buf"+ CTLLong -> R.CTSimple $ R.sname "long long"+ CTLong -> R.CTSimple $ R.sname "long"+ CTPtrdiff -> R.CTSimple $ R.sname "ptrdiff_t"+ CTSChar -> R.CTSimple $ R.sname "sized char"+ CTSUSeconds -> R.CTSimple $ R.sname "suseconds_t"+ CTShort -> R.CTSimple $ R.sname "short"+ CTSigAtomic -> R.CTSimple $ R.sname "sig_atomic_t"+ CTSize -> R.CTSimple $ R.sname "size_t"+ CTTime -> R.CTSimple $ R.sname "time_t"+ CTUChar -> R.CTSimple $ R.sname "unsigned char"+ CTUInt -> R.CTSimple $ R.sname "unsigned int"+ CTUIntMax -> R.CTSimple $ R.sname "uintmax_t"+ CTUIntPtr -> R.CTSimple $ R.sname "uintptr_t"+ CTULLong -> R.CTSimple $ R.sname "unsigned long long"+ CTULong -> R.CTSimple $ R.sname "unsigned long"+ CTUSeconds -> R.CTSimple $ R.sname "useconds_t"+ CTUShort -> R.CTSimple $ R.sname "unsigned short"+ CTWchar -> R.CTSimple $ R.sname "wchar_t"+ CTInt8 -> R.CTSimple $ R.sname "int8_t"+ CTInt16 -> R.CTSimple $ R.sname "int16_t"+ CTInt32 -> R.CTSimple $ R.sname "int32_t"+ CTInt64 -> R.CTSimple $ R.sname "int64_t"+ CTUInt8 -> R.CTSimple $ R.sname "uint8_t"+ CTUInt16 -> R.CTSimple $ R.sname "uint16_t"+ CTUInt32 -> R.CTSimple $ R.sname "uint32_t"+ CTUInt64 -> R.CTSimple $ R.sname "uint64_t"+ CTString -> R.CTStar $ R.CTSimple $ R.sname "char"+ CTVoidStar -> R.CTStar R.CTVoid+ CEnum _ type_str -> R.CTVerbatim type_str+ CPointer s -> R.CTStar (ctypToCType s NoConst)+ CRef s -> R.CTStar (ctypToCType s NoConst)+ in case isconst of+ Const -> R.CTConst typ+ NoConst -> typ++self_ :: Types+self_ = SelfType++cstring_ :: Types+cstring_ = CT CTString Const++cint_ :: Types+cint_ = CT CTInt Const++int_ :: Types+int_ = CT CTInt NoConst++uint_ :: Types+uint_ = CT CTUInt NoConst++ulong_ :: Types+ulong_ = CT CTULong NoConst++long_ :: Types+long_ = CT CTLong NoConst++culong_ :: Types+culong_ = CT CTULong Const++clong_ :: Types+clong_ = CT CTLong Const++cchar_ :: Types+cchar_ = CT CTChar Const++char_ :: Types+char_ = CT CTChar NoConst++cshort_ :: Types+cshort_ = CT CTShort Const++short_ :: Types+short_ = CT CTShort NoConst++cdouble_ :: Types+cdouble_ = CT CTDouble Const++double_ :: Types+double_ = CT CTDouble NoConst++doublep_ :: Types+doublep_ = CT (CPointer CTDouble) NoConst++cfloat_ :: Types+cfloat_ = CT CTFloat Const++float_ :: Types+float_ = CT CTFloat NoConst++bool_ :: Types+bool_ = CT CTBool NoConst++void_ :: Types+void_ = Void++voidp_ :: Types+voidp_ = CT CTVoidStar NoConst++intp_ :: Types+intp_ = CT (CPointer CTInt) NoConst++intref_ :: Types+intref_ = CT (CRef CTInt) NoConst+++charpp_ :: Types+charpp_ = CT (CPointer CTString) NoConst++ref_ :: CTypes -> Types+ref_ t = CT (CRef t) NoConst++star_ :: CTypes -> Types+star_ t = CT (CPointer t) NoConst++cstar_ :: CTypes -> Types+cstar_ t = CT (CPointer t) Const++self :: String -> Arg+self var = Arg self_ var++voidp :: String -> Arg+voidp var = Arg voidp_ var++cstring :: String -> Arg+cstring var = Arg cstring_ var++cint :: String -> Arg+cint var = Arg cint_ var++int :: String -> Arg+int var = Arg int_ var++uint :: String -> Arg+uint var = Arg uint_ var++long :: String -> Arg+long var = Arg long_ var++ulong :: String -> Arg+ulong var = Arg ulong_ var++clong :: String -> Arg+clong var = Arg clong_ var++culong :: String -> Arg+culong var = Arg culong_ var++cchar :: String -> Arg+cchar var = Arg cchar_ var++char :: String -> Arg+char var = Arg char_ var++cshort :: String -> Arg+cshort var = Arg cshort_ var++short :: String -> Arg+short var = Arg short_ var++cdouble :: String -> Arg+cdouble var = Arg cdouble_ var++double :: String -> Arg+double var = Arg double_ var++doublep :: String -> Arg+doublep var = Arg doublep_ var++cfloat :: String -> Arg+cfloat var = Arg float_ var++float :: String -> Arg+float var = Arg float_ var++bool :: String -> Arg+bool var = Arg bool_ var++intp :: String -> Arg+intp var = Arg intp_ var++intref :: String -> Arg+intref var = Arg intref_ var++charpp :: String -> Arg+charpp var = Arg charpp_ var++ref :: CTypes -> String -> Arg+ref t var = Arg (ref_ t) var++star :: CTypes -> String -> Arg+star t var = Arg (star_ t) var++cstar :: CTypes -> String -> Arg+cstar t var = Arg (cstar_ t) var+++cppclass_ :: Class -> Types+cppclass_ c = CPT (CPTClass c) NoConst++cppclass :: Class -> String -> Arg+cppclass c vname = Arg (cppclass_ c) vname++++cppclassconst :: Class -> String -> Arg+cppclassconst c vname = Arg (CPT (CPTClass c) Const) vname++cppclassref_ :: Class -> Types+cppclassref_ c = CPT (CPTClassRef c) NoConst++cppclassref :: Class -> String -> Arg+cppclassref c vname = Arg (cppclassref_ c) vname++cppclasscopy_ :: Class -> Types+cppclasscopy_ c = CPT (CPTClassCopy c) NoConst++cppclasscopy :: Class -> String -> Arg+cppclasscopy c vname = Arg (cppclasscopy_ c) vname++cppclassmove_ :: Class -> Types+cppclassmove_ c = CPT (CPTClassMove c) NoConst++cppclassmove :: Class -> String -> Arg+cppclassmove c vname = Arg (cppclassmove_ c) vname+++argToCTypVar :: Arg -> (R.CType Identity, R.CName Identity)+argToCTypVar (Arg (CT ctyp isconst) varname) =+ (ctypToCType ctyp isconst, R.sname varname)+argToCTypVar (Arg SelfType varname) =+ (R.CTSimple (R.CName [ R.NamePart "Type", R.NamePart "_p" ]), R.sname varname)+argToCTypVar (Arg (CPT (CPTClass c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> cname <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (cname <> "_p")), R.sname varname)+ where cname = ffiClassName c+argToCTypVar (Arg (CPT (CPTClassRef c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> cname <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (cname <> "_p")), R.sname varname)+ where cname = ffiClassName c+argToCTypVar (Arg (CPT (CPTClassCopy c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> cname <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (cname <> "_p")), R.sname varname)+ where cname = ffiClassName c+argToCTypVar (Arg (CPT (CPTClassMove c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> cname <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (cname <> "_p")), R.sname varname)+ where cname = ffiClassName c+argToCTypVar (Arg (TemplateApp _) varname) = (R.CTStar R.CTVoid, R.sname varname)+argToCTypVar (Arg (TemplateAppRef _) varname) = (R.CTStar R.CTVoid, R.sname varname)+argToCTypVar (Arg (TemplateAppMove _) varname) = (R.CTStar R.CTVoid, R.sname varname)+argToCTypVar t = error ("argToCTypVar: " <> show t)++argsToCTypVar :: [Arg] -> [ (R.CType Identity, R.CName Identity) ]+argsToCTypVar args =+ let args' = (Arg SelfType "p") : args+ in map argToCTypVar args'++argsToCTypVarNoSelf :: [Arg] -> [ (R.CType Identity, R.CName Identity) ]+argsToCTypVarNoSelf = map argToCTypVar++argToCallCExp :: Arg -> R.CExp Identity+argToCallCExp (Arg t e) = c2Cxx t (R.CVar (R.sname e))+++-- TODO: rename this function by castExpressionFrom/To or something like that.+returnCType :: Types -> R.CType Identity+returnCType (CT ctyp isconst) = ctypToCType ctyp isconst+returnCType Void = R.CTVoid+returnCType SelfType = R.CTSimple (R.CName [ R.NamePart "Type", R.NamePart "_p" ])+returnCType (CPT (CPTClass c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+returnCType (CPT (CPTClassRef c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+returnCType (CPT (CPTClassCopy c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+returnCType (CPT (CPTClassMove c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+returnCType (TemplateApp _) = R.CTStar R.CTVoid+returnCType (TemplateAppRef _) = R.CTStar R.CTVoid+returnCType (TemplateAppMove _) = R.CTStar R.CTVoid+returnCType (TemplateType _) = R.CTStar R.CTVoid+returnCType (TemplateParam t) = R.CTSimple (R.CName [ R.NamePart t, R.NamePart "_p" ])+returnCType (TemplateParamPointer t) = R.CTSimple (R.CName [ R.NamePart t, R.NamePart "_p" ])++-- TODO: Rewrite this with static_cast+c2Cxx :: Types -> R.CExp Identity -> R.CExp Identity+c2Cxx t e =+ case t of+ CT (CRef _) _ -> R.CStar e+ CPT (CPTClass c) _ -> R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname f), R.CTSimple (R.sname (f <> "_t")) ]+ [ e ]+ where f = ffiClassName c+ CPT (CPTClassRef c) _ -> R.CTApp+ (R.sname "from_nonconstref_to_nonconstref")+ [ R.CTSimple (R.sname f), R.CTSimple (R.sname (f <> "_t")) ]+ [ R.CStar e ]+ where f = ffiClassName c+ CPT (CPTClassCopy c) _ -> R.CStar $+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname f), R.CTSimple (R.sname (f <> "_t")) ]+ [ e ]+ where f = ffiClassName c+ CPT (CPTClassMove c) _ -> R.CApp+ (R.CVar (R.sname "std::move"))+ [ R.CTApp+ (R.sname "from_nonconstref_to_nonconstref")+ [ R.CTSimple (R.sname f), R.CTSimple (R.sname (f <> "_t")) ]+ [ R.CStar e ]+ ]+ where f = ffiClassName c+ TemplateApp p -> R.CTApp+ (R.sname "from_nonconstref_to_nonconst")+ [ R.CTVerbatim (tapp_CppTypeForParam p), R.CTVoid ]+ [ e ]+ TemplateAppRef p -> R.CStar $+ R.CCast (R.CTStar (R.CTVerbatim (tapp_CppTypeForParam p))) e+ TemplateAppMove p -> R.CApp+ (R.CVar (R.sname "std::move"))+ [ R.CStar $+ R.CCast (R.CTStar (R.CTVerbatim (tapp_CppTypeForParam p))) e+ ]+ _ -> e++-- TODO: Rewrite this with static_cast+-- Merge this with returnCpp after Void and simple type adjustment+-- TODO: Resolve all the error cases+cxx2C :: Types -> R.CExp Identity -> R.CExp Identity+cxx2C t e =+ case t of+ Void -> R.CNull+ SelfType ->+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.CName [ R.NamePart "Type", R.NamePart "_t"]), R.CTSimple (R.sname "Type") ]+ [ R.CCast (R.CTStar (R.CTSimple (R.sname "Type"))) e ]+ -- "to_nonconst<Type ## _t, Type>((Type *)" <> e <> ")"+ CT (CRef _) _ -> R.CAddr e+ -- "&(" <> e <> ")"+ CT _ _ -> e+ -- e+ CPT (CPTClass c) _ ->+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname (f <> "_t")), R.CTSimple (R.sname f) ]+ [ R.CCast (R.CTStar (R.CTSimple (R.sname f))) e ]+ where f = ffiClassName c+ -- "to_nonconst<" <> f <> "_t," <> f <> ">((" <> f <> "*)" <> e <> ")"+ CPT (CPTClassRef c) _ ->+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname (f <> "_t")), R.CTSimple (R.sname f) ]+ [ R.CAddr e ]+ where f = ffiClassName c+ -- "to_nonconst<" <> f <> "_t," <> f <> ">(&(" <> e <> "))"+ CPT (CPTClassCopy c) _ ->+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname (f <> "_t")), R.CTSimple (R.sname f) ]+ [ R.CNew (R.sname f) [e] ]+ where f = ffiClassName c+ -- "to_nonconst<" <> f <> "_t," <> f <> ">(new " <> f <> "(" <> e <> "))"+ CPT (CPTClassMove c) _ ->+ R.CApp+ (R.CVar (R.sname "std::move"))+ [ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname (f <> "_t")), R.CTSimple (R.sname f) ]+ [ R.CAddr e ]+ ]+ where f = ffiClassName c+ -- "std::move(to_nonconst<" <> f <> "_t," <> f <>">(&(" <> e <> ")))"+ TemplateApp _ ->+ error "cxx2C: TemplateApp"+ -- g <> "* r = new " <> g <> "(" <> e <> "); "+ -- <> "return (static_cast<void*>(r));"+ TemplateAppRef _ ->+ error "cxx2C: TemplateAppRef"+ -- g <> "* r = new " <> g <> "(" <> e <> "); "+ -- <> "return (static_cast<void*>(r));"+ TemplateAppMove _ ->+ error "cxx2C: TemplateAppMove"+ TemplateType _ ->+ error "cxx2C: TemplateType"+ TemplateParam _ ->+ error "cxx2C: TemplateParam"+ -- if b then e+ -- else "to_nonconst<Type ## _t, Type>((Type *)&(" <> e <> "))"+ TemplateParamPointer _ ->+ error "cxx2C: TemplateParamPointer"+ -- if b then "(" <> callstr <> ");"+ -- else "to_nonconst<Type ## _t, Type>(" <> e <> ") ;"++tmplAppTypeFromForm :: Form -> [R.CType Identity] -> R.CType Identity+tmplAppTypeFromForm (FormSimple tclass) targs = R.CTTApp (R.sname tclass) targs+tmplAppTypeFromForm (FormNested tclass inner) targs = R.CTScoped (R.CTTApp (R.sname tclass) targs) (R.CTVerbatim inner)++tmplArgToCTypVar ::+ IsCPrimitive+ -> TemplateClass+ -> Arg+ -> (R.CType Identity, R.CName Identity)+tmplArgToCTypVar _ _ (Arg (CT ctyp isconst) varname) =+ (ctypToCType ctyp isconst, R.sname varname)+tmplArgToCTypVar _ _ (Arg SelfType varname) =+ (R.CTStar R.CTVoid, R.sname varname)+tmplArgToCTypVar _ _ (Arg (CPT (CPTClass c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> ffiClassName c <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (ffiClassName c <> "_p")), R.sname varname)+tmplArgToCTypVar _ _ (Arg (CPT (CPTClassRef c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> ffiClassName c <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (ffiClassName c <> "_p")), R.sname varname)+tmplArgToCTypVar _ _ (Arg (CPT (CPTClassMove c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> ffiClassName c <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (ffiClassName c <> "_p")), R.sname varname)+tmplArgToCTypVar _ _ (Arg (TemplateApp _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplArgToCTypVar _ _ (Arg (TemplateAppRef _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplArgToCTypVar _ _ (Arg (TemplateAppMove _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplArgToCTypVar _ _ (Arg (TemplateType _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplArgToCTypVar CPrim _ (Arg (TemplateParam t) v) = (R.CTSimple (R.sname t), R.sname v)+tmplArgToCTypVar NonCPrim _ (Arg (TemplateParam t) v) = (R.CTSimple (R.CName [ R.NamePart t, R.NamePart "_p" ]), R.sname v)+tmplArgToCTypVar CPrim _ (Arg (TemplateParamPointer t) v) = (R.CTSimple (R.sname t), R.sname v)+tmplArgToCTypVar NonCPrim _ (Arg (TemplateParamPointer t) v) = (R.CTSimple (R.CName [ R.NamePart t, R.NamePart "_p"]), R.sname v)+tmplArgToCTypVar _ _ _ = error "tmplArgToCTypVar: undefined"++tmplAllArgsToCTypVar ::+ IsCPrimitive+ -> Selfness+ -> TemplateClass+ -> [Arg]+ -> [ (R.CType Identity, R.CName Identity) ]+tmplAllArgsToCTypVar b s t args =+ let args' = case s of+ Self -> (Arg (TemplateType t) "p") : args+ NoSelf -> args+ in map (tmplArgToCTypVar b t) args'++-- TODO: Rewrite this with static_cast.+-- Implement missing cases.+tmplArgToCallCExp+ :: IsCPrimitive+ -> Arg+ -> R.CExp Identity+tmplArgToCallCExp _ (Arg (CPT (CPTClass c) _) varname) =+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname str), R.CTSimple (R.sname (str <> "_t")) ]+ [ R.CVar (R.sname varname) ]+ where str = ffiClassName c+tmplArgToCallCExp _ (Arg (CPT (CPTClassRef c) _) varname) =+ R.CTApp+ (R.sname "from_nonconstref_to_nonconstref")+ [ R.CTSimple (R.sname str), R.CTSimple (R.sname (str <> "_t")) ]+ [ R.CStar $ R.CVar $ R.sname varname ]+ where str = ffiClassName c+tmplArgToCallCExp _ (Arg (CPT (CPTClassMove c) _) varname) =+ R.CApp+ (R.CVar (R.sname "std::move"))+ [R.CTApp+ (R.sname "from_nonconstref_to_nonconstref")+ [ R.CTSimple (R.sname str), R.CTSimple (R.sname (str <> "_t")) ]+ [ R.CStar $ R.CVar $ R.sname varname ]+ ]+ where str = ffiClassName c+tmplArgToCallCExp _ (Arg (CT (CRef _) _) varname) =+ R.CStar $ R.CVar $ R.sname varname+tmplArgToCallCExp _ (Arg (TemplateApp x) varname) =+ let targs = map (R.CTSimple . R.sname . hsClassNameForTArg) (tapp_tparams x)+ in R.CTApp+ (R.sname "static_cast")+ [ R.CTStar $ tmplAppTypeFromForm (tclass_cxxform (tapp_tclass x)) targs ]+ [ R.CVar $ R.sname varname ]+tmplArgToCallCExp _ (Arg (TemplateAppRef x) varname) =+ let targs = map (R.CTSimple . R.sname . hsClassNameForTArg) (tapp_tparams x)+ in R.CStar $+ R.CTApp+ (R.sname "static_cast")+ [ R.CTStar $ tmplAppTypeFromForm (tclass_cxxform (tapp_tclass x)) targs ]+ [ R.CVar $ R.sname varname ]+tmplArgToCallCExp _ (Arg (TemplateAppMove x) varname) =+ let targs = map (R.CTSimple . R.sname . hsClassNameForTArg) (tapp_tparams x)+ in R.CApp+ (R.CVar (R.sname "std::move"))+ [ R.CStar $+ R.CTApp+ (R.sname "static_cast")+ [ R.CTStar $ tmplAppTypeFromForm (tclass_cxxform (tapp_tclass x)) targs ]+ [ R.CVar $ R.sname varname ]+ ]+tmplArgToCallCExp b (Arg (TemplateParam typ) varname) =+ case b of+ CPrim -> R.CVar $ R.sname varname+ NonCPrim -> R.CStar $+ R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname typ), R.CTSimple (R.CName [ R.NamePart typ, R.NamePart "_t"]) ]+ [ R.CVar $ R.sname varname ]+tmplArgToCallCExp b (Arg (TemplateParamPointer typ) varname) =+ case b of+ CPrim -> R.CVar $ R.sname varname+ NonCPrim -> R.CTApp+ (R.sname "from_nonconst_to_nonconst")+ [ R.CTSimple (R.sname typ), R.CTSimple (R.CName [ R.NamePart typ, R.NamePart "_t"]) ]+ [ R.CVar $ R.sname varname ]+tmplArgToCallCExp _ (Arg _ varname) = R.CVar $ R.sname varname++tmplReturnCType ::+ IsCPrimitive+ -> Types+ -> R.CType Identity+tmplReturnCType _ (CT ctyp isconst) = ctypToCType ctyp isconst+tmplReturnCType _ Void = R.CTVoid+tmplReturnCType _ SelfType = R.CTStar R.CTVoid+tmplReturnCType _ (CPT (CPTClass c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplReturnCType _ (CPT (CPTClassRef c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplReturnCType _ (CPT (CPTClassCopy c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplReturnCType _ (CPT (CPTClassMove c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplReturnCType _ (TemplateApp _) = R.CTStar R.CTVoid+tmplReturnCType _ (TemplateAppRef _) = R.CTStar R.CTVoid+tmplReturnCType _ (TemplateAppMove _) = R.CTStar R.CTVoid+tmplReturnCType _ (TemplateType _) = R.CTStar R.CTVoid+tmplReturnCType b (TemplateParam t) = case b of+ CPrim -> R.CTSimple $ R.sname t+ NonCPrim -> R.CTSimple $ R.CName [ R.NamePart t, R.NamePart "_p" ]+tmplReturnCType b (TemplateParamPointer t) = case b of+ CPrim -> R.CTSimple $ R.sname t+ NonCPrim -> R.CTSimple $ R.CName [ R.NamePart t, R.NamePart "_p" ]++-- ---------------------------+-- Template Member Function --+-- ---------------------------++-- |+tmplMemFuncArgToCTypVar :: Class -> Arg -> (R.CType Identity, R.CName Identity)+tmplMemFuncArgToCTypVar _ (Arg (CT ctyp isconst) varname) =+ (ctypToCType ctyp isconst, R.sname varname)+tmplMemFuncArgToCTypVar c (Arg SelfType varname) =+ (R.CTSimple (R.sname (ffiClassName c <> "_p")), R.sname varname)+tmplMemFuncArgToCTypVar _ (Arg (CPT (CPTClass c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> ffiClassName c <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (ffiClassName c <> "_p")), R.sname varname)+tmplMemFuncArgToCTypVar _ (Arg (CPT (CPTClassRef c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> ffiClassName c <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (ffiClassName c <> "_p")), R.sname varname)+tmplMemFuncArgToCTypVar _ (Arg (CPT (CPTClassMove c) isconst) varname) =+ case isconst of+ Const -> (R.CTSimple (R.sname ("const_" <> ffiClassName c <> "_p")), R.sname varname)+ NoConst -> (R.CTSimple (R.sname (ffiClassName c <> "_p")), R.sname varname)+tmplMemFuncArgToCTypVar _ (Arg (TemplateApp _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplMemFuncArgToCTypVar _ (Arg (TemplateAppRef _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplMemFuncArgToCTypVar _ (Arg (TemplateAppMove _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplMemFuncArgToCTypVar _ (Arg (TemplateType _) v) = (R.CTStar R.CTVoid, R.sname v)+tmplMemFuncArgToCTypVar _ (Arg (TemplateParam t) v) = (R.CTSimple (R.CName [ R.NamePart t, R.NamePart "_p" ]), R.sname v)+tmplMemFuncArgToCTypVar _ (Arg (TemplateParamPointer t) v) = (R.CTSimple (R.CName [ R.NamePart t, R.NamePart "_p" ]), R.sname v)+tmplMemFuncArgToCTypVar _ _ = error "tmplMemFuncArgToString: undefined"+++-- |+tmplMemFuncReturnCType :: Class -> Types -> R.CType Identity+tmplMemFuncReturnCType _ (CT ctyp isconst) = ctypToCType ctyp isconst+tmplMemFuncReturnCType _ Void = R.CTVoid+tmplMemFuncReturnCType c SelfType = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplMemFuncReturnCType _ (CPT (CPTClass c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplMemFuncReturnCType _ (CPT (CPTClassRef c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplMemFuncReturnCType _ (CPT (CPTClassCopy c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplMemFuncReturnCType _ (CPT (CPTClassMove c) _) = R.CTSimple (R.sname (ffiClassName c <> "_p"))+tmplMemFuncReturnCType _ (TemplateApp _) = R.CTStar R.CTVoid+tmplMemFuncReturnCType _ (TemplateAppRef _) = R.CTStar R.CTVoid+tmplMemFuncReturnCType _ (TemplateAppMove _) = R.CTStar R.CTVoid+tmplMemFuncReturnCType _ (TemplateType _) = R.CTStar R.CTVoid+tmplMemFuncReturnCType _ (TemplateParam t) = R.CTSimple $ R.CName [ R.NamePart t, R.NamePart "_p" ]+tmplMemFuncReturnCType _ (TemplateParamPointer t) = R.CTSimple $ R.CName [ R.NamePart t, R.NamePart "_p" ]++-- |+convertC2HS :: CTypes -> Type ()+convertC2HS CTBool = tycon "CBool"+convertC2HS CTChar = tycon "CChar"+convertC2HS CTClock = tycon "CClock"+convertC2HS CTDouble = tycon "CDouble"+convertC2HS CTFile = tycon "CFile"+convertC2HS CTFloat = tycon "CFloat"+convertC2HS CTFpos = tycon "CFpos"+convertC2HS CTInt = tycon "CInt"+convertC2HS CTIntMax = tycon "CIntMax"+convertC2HS CTIntPtr = tycon "CIntPtr"+convertC2HS CTJmpBuf = tycon "CJmpBuf"+convertC2HS CTLLong = tycon "CLLong"+convertC2HS CTLong = tycon "CLong"+convertC2HS CTPtrdiff = tycon "CPtrdiff"+convertC2HS CTSChar = tycon "CSChar"+convertC2HS CTSUSeconds = tycon "CSUSeconds"+convertC2HS CTShort = tycon "CShort"+convertC2HS CTSigAtomic = tycon "CSigAtomic"+convertC2HS CTSize = tycon "CSize"+convertC2HS CTTime = tycon "CTime"+convertC2HS CTUChar = tycon "CUChar"+convertC2HS CTUInt = tycon "CUInt"+convertC2HS CTUIntMax = tycon "CUIntMax"+convertC2HS CTUIntPtr = tycon "CUIntPtr"+convertC2HS CTULLong = tycon "CULLong"+convertC2HS CTULong = tycon "CULong"+convertC2HS CTUSeconds = tycon "CUSeconds"+convertC2HS CTUShort = tycon "CUShort"+convertC2HS CTWchar = tycon "CWchar"+convertC2HS CTInt8 = tycon "Int8"+convertC2HS CTInt16 = tycon "Int16"+convertC2HS CTInt32 = tycon "Int32"+convertC2HS CTInt64 = tycon "Int64"+convertC2HS CTUInt8 = tycon "Word8"+convertC2HS CTUInt16 = tycon "Word16"+convertC2HS CTUInt32 = tycon "Word32"+convertC2HS CTUInt64 = tycon "Word64"+convertC2HS CTString = tycon "CString"+convertC2HS CTVoidStar = tyapp (tycon "Ptr") unit_tycon+convertC2HS (CEnum t _) = convertC2HS t+convertC2HS (CPointer t) = tyapp (tycon "Ptr") (convertC2HS t)+convertC2HS (CRef t) = tyapp (tycon "Ptr") (convertC2HS t)++-- |+convertCpp2HS :: Maybe Class -> Types -> Type ()+convertCpp2HS _c Void = unit_tycon+convertCpp2HS (Just c) SelfType = tycon ((fst.hsClassName) c)+convertCpp2HS Nothing SelfType = error "convertCpp2HS : SelfType but no class "+convertCpp2HS _c (CT t _) = convertC2HS t+convertCpp2HS _c (CPT (CPTClass c') _) = (tycon . fst . hsClassName) c'+convertCpp2HS _c (CPT (CPTClassRef c') _) = (tycon . fst . hsClassName) c'+convertCpp2HS _c (CPT (CPTClassCopy c') _) = (tycon . fst . hsClassName) c'+convertCpp2HS _c (CPT (CPTClassMove c') _) = (tycon . fst . hsClassName) c'+convertCpp2HS _c (TemplateApp x) =+ foldl1 tyapp $ map tycon $+ tclass_name (tapp_tclass x) : map hsClassNameForTArg (tapp_tparams x)+convertCpp2HS _c (TemplateAppRef x) =+ foldl1 tyapp $ map tycon $+ tclass_name (tapp_tclass x) : map hsClassNameForTArg (tapp_tparams x)+convertCpp2HS _c (TemplateAppMove x) =+ foldl1 tyapp $ map tycon $+ tclass_name (tapp_tclass x) : map hsClassNameForTArg (tapp_tparams x)+convertCpp2HS _c (TemplateType t) =+ foldl1 tyapp $+ tycon (tclass_name t) : map mkTVar (tclass_params t)+convertCpp2HS _c (TemplateParam p) = mkTVar p+convertCpp2HS _c (TemplateParamPointer p) = mkTVar p++-- |+convertCpp2HS4Tmpl+ :: Type () -- ^ self+ -> Maybe Class+ -> [Type ()] -- ^ type paramemter splice+ -> Types+ -> Type ()+convertCpp2HS4Tmpl _ c _ Void = convertCpp2HS c Void+convertCpp2HS4Tmpl _ (Just c) _ SelfType = convertCpp2HS (Just c) SelfType+convertCpp2HS4Tmpl _ Nothing _ SelfType = convertCpp2HS Nothing SelfType+convertCpp2HS4Tmpl _ c _ x@(CT _ _) = convertCpp2HS c x+convertCpp2HS4Tmpl _ c _ x@(CPT (CPTClass _) _) = convertCpp2HS c x+convertCpp2HS4Tmpl _ c _ x@(CPT (CPTClassRef _) _) = convertCpp2HS c x+convertCpp2HS4Tmpl _ c _ x@(CPT (CPTClassCopy _) _) = convertCpp2HS c x+convertCpp2HS4Tmpl _ c _ x@(CPT (CPTClassMove _) _) = convertCpp2HS c x+convertCpp2HS4Tmpl _ _ ss (TemplateApp info) =+ let pss = zip (tapp_tparams info) ss+ in foldl1 tyapp $+ tycon (tclass_name (tapp_tclass info)) : map (\case (TArg_TypeParam _,s) -> s; (p,_) -> tycon (hsClassNameForTArg p)) pss+convertCpp2HS4Tmpl _ _ ss (TemplateAppRef info) =+ let pss = zip (tapp_tparams info) ss+ in foldl1 tyapp $+ tycon (tclass_name (tapp_tclass info)) : map (\case (TArg_TypeParam _,s) -> s; (p,_) -> tycon (hsClassNameForTArg p)) pss+convertCpp2HS4Tmpl _ _ ss (TemplateAppMove info) =+ let pss = zip (tapp_tparams info) ss+ in foldl1 tyapp $+ tycon (tclass_name (tapp_tclass info)) : map (\case (TArg_TypeParam _,s) -> s; (p,_) -> tycon (hsClassNameForTArg p)) pss+convertCpp2HS4Tmpl e _ _ (TemplateType _) = e+convertCpp2HS4Tmpl _ _ _ (TemplateParam p) = tySplice . parenSplice . mkVar $ p+convertCpp2HS4Tmpl _ _ _ (TemplateParamPointer p) = tySplice . parenSplice . mkVar $ p+++hsFuncXformer :: Function -> String+hsFuncXformer func@(Constructor _ _) = let len = length (genericFuncArgs func)+ in if len > 0+ then "xform" <> show (len - 1)+ else "xformnull"+hsFuncXformer func@(Static _ _ _ _) =+ let len = length (genericFuncArgs func)+ in if len > 0+ then "xform" <> show (len - 1)+ else "xformnull"+hsFuncXformer func = let len = length (genericFuncArgs func)+ in "xform" <> show len++++classConstraints :: Class -> Context ()+classConstraints = cxTuple . map ((\n->classA (unqual n) [mkTVar "a"]) . typeclassName) . class_parents++extractArgRetTypes+ :: Maybe Class -- ^ class (Nothing for top-level function)+ -> Bool -- ^ is virtual function?+ -> CFunSig -- ^ C type signature information for a given function -- (Args,Types) -- ^ (argument types, return type) of a given function+ -> HsFunSig -- ^ Haskell type signature information for the function -- ([Type ()],[Asst ()]) -- ^ (types, class constraints)+extractArgRetTypes mc isvirtual (CFunSig args ret) =+ let (typs,s) = flip runState ([],(0 :: Int)) $ do+ as <- mapM (mktyp . arg_type) args+ r <- case ret of+ SelfType -> case mc of+ Nothing -> error "extractArgRetTypes: SelfType return but no class"+ Just c -> if isvirtual then return (mkTVar "a") else return $ tycon ((fst.hsClassName) c)+ x -> (return . convertCpp2HS Nothing) x+ return (as ++ [tyapp (tycon "IO") r])+ in HsFunSig { hsSigTypes = typs+ , hsSigConstraints = fst s+ }+ where addclass c = do+ (ctxts,n) <- get+ let cname = (fst.hsClassName) c+ iname = typeclassNameFromStr cname+ tvar = mkTVar ('c' : show n)+ ctxt1 = classA (unqual iname) [tvar]+ ctxt2 = classA (unqual "FPtr") [tvar]+ put (ctxt1:ctxt2:ctxts,n+1)+ return tvar+ addstring = do+ (ctxts,n) <- get+ let tvar = mkTVar ('c' : show n)+ ctxt = classA (unqual "Castable") [tvar,tycon "CString"]+ put (ctxt:ctxts,n+1)+ return tvar++ mktyp typ =+ case typ of+ SelfType -> return (mkTVar "a")+ CT CTString Const -> addstring+ CT _ _ -> return $ convertCpp2HS Nothing typ+ CPT (CPTClass c') _ -> addclass c'+ CPT (CPTClassRef c') _ -> addclass c'+ CPT (CPTClassCopy c') _ -> addclass c'+ CPT (CPTClassMove c') _ -> addclass c'+ -- it is not clear whether the following is okay or not.+ (TemplateApp x) -> pure $+ convertCpp2HS Nothing (TemplateApp x)+ (TemplateAppRef x) -> pure $+ convertCpp2HS Nothing (TemplateAppRef x)+ (TemplateAppMove x)-> pure $+ convertCpp2HS Nothing (TemplateAppMove x)+ (TemplateType t) -> pure $+ foldl1 tyapp (tycon (tclass_name t) : map mkTVar (tclass_params t))+ (TemplateParam p) -> return (mkTVar p)+ Void -> return unit_tycon+ _ -> error ("No such c type : " <> show typ)++functionSignature :: Class -> Function -> Type ()+functionSignature c f =+ let HsFunSig typs assts = extractArgRetTypes+ (Just c)+ (isVirtualFunc f)+ (CFunSig (genericFuncArgs f) (genericFuncRet f))+ ctxt = cxTuple assts+ arg0+ | isVirtualFunc f = (mkTVar "a" :)+ | isNonVirtualFunc f = (mkTVar (fst (hsClassName c)) :)+ | otherwise = id+ in TyForall () Nothing (Just ctxt) (foldr1 tyfun (arg0 typs))++functionSignatureT :: TemplateClass -> TemplateFunction -> Type ()+functionSignatureT t TFun {..} =+ let (hname,_) = hsTemplateClassName t+ slf = foldl1 tyapp (tycon hname : map mkTVar (tclass_params t))+ ctyp = convertCpp2HS Nothing tfun_ret+ lst = slf : map (convertCpp2HS Nothing . arg_type) tfun_args+ in foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])+functionSignatureT t TFunNew {..} =+ let ctyp = convertCpp2HS Nothing (TemplateType t)+ lst = map (convertCpp2HS Nothing . arg_type) tfun_new_args+ in foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])+functionSignatureT t TFunDelete =+ let ctyp = convertCpp2HS Nothing (TemplateType t)+ in ctyp `tyfun` (tyapp (tycon "IO") unit_tycon)+functionSignatureT t TFunOp {..} =+ let (hname,_) = hsTemplateClassName t+ slf = foldl1 tyapp (tycon hname : map mkTVar (tclass_params t))+ ctyp = convertCpp2HS Nothing tfun_ret+ lst = slf : map (convertCpp2HS Nothing . arg_type) (argsFromOpExp tfun_opexp)+ in foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])++-- TODO: rename this and combine this with functionSignatureTMF+functionSignatureTT :: TemplateClass -> TemplateFunction -> Type ()+functionSignatureTT t f = foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])+ where+ (hname,_) = hsTemplateClassName t+ ctyp = case f of+ TFun {..} -> convertCpp2HS4Tmpl e Nothing spls tfun_ret+ TFunNew {..} -> convertCpp2HS4Tmpl e Nothing spls (TemplateType t)+ TFunDelete -> unit_tycon+ TFunOp {..} -> convertCpp2HS4Tmpl e Nothing spls tfun_ret+ e = foldl1 tyapp (tycon hname : spls)+ spls = map (tySplice . parenSplice . mkVar) $ tclass_params t+ lst =+ case f of+ TFun {..} -> e : map (convertCpp2HS4Tmpl e Nothing spls . arg_type) tfun_args+ TFunNew {..} -> map (convertCpp2HS4Tmpl e Nothing spls . arg_type) tfun_new_args+ TFunDelete -> [e]+ TFunOp {..} -> e : map (convertCpp2HS4Tmpl e Nothing spls . arg_type) (argsFromOpExp tfun_opexp)++-- TODO: rename this and combine this with functionSignatureTT+functionSignatureTMF :: Class -> TemplateMemberFunction -> Type ()+functionSignatureTMF c f = foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])+ where+ spls = map (tySplice . parenSplice . mkVar) (tmf_params f)+ ctyp = convertCpp2HS4Tmpl e Nothing spls (tmf_ret f)+ e = tycon (fst (hsClassName c))+ lst = e : map (convertCpp2HS4Tmpl e Nothing spls . arg_type) (tmf_args f)+++tmplAccessorToTFun :: Variable -> Accessor -> TemplateFunction+tmplAccessorToTFun v@(Variable (Arg {..})) a =+ case a of+ Getter -> TFun { tfun_ret = arg_type+ , tfun_name = tmplAccessorName v Getter+ , tfun_oname = tmplAccessorName v Getter+ , tfun_args = []+ }+ Setter -> TFun { tfun_ret = Void+ , tfun_name = tmplAccessorName v Setter+ , tfun_oname = tmplAccessorName v Setter+ , tfun_args = [Arg arg_type "value"]+ }+++accessorCFunSig :: Types -> Accessor -> CFunSig+accessorCFunSig typ Getter = CFunSig [] typ+accessorCFunSig typ Setter = CFunSig [Arg typ "x"] Void+++accessorSignature :: Class -> Variable -> Accessor -> Type ()+accessorSignature c v accessor =+ let csig = accessorCFunSig (arg_type (unVariable v)) accessor+ HsFunSig typs assts = extractArgRetTypes (Just c) False csig+ ctxt = cxTuple assts+ arg0 = (mkTVar (fst (hsClassName c)) :)+ in TyForall () Nothing (Just ctxt) (foldr1 tyfun (arg0 typs))+++-- | this is for FFI type.+hsFFIFuncTyp :: Maybe (Selfness, Class) -> CFunSig -> Type ()+hsFFIFuncTyp msc (CFunSig args ret) =+ foldr1 tyfun $ case msc of+ Nothing -> argtyps <> [tyapp (tycon "IO") rettyp]+ Just (Self,_) -> selftyp: argtyps <> [tyapp (tycon "IO") rettyp]+ Just (NoSelf,_) -> argtyps <> [tyapp (tycon "IO") rettyp]+ where argtyps :: [Type ()]+ argtyps = map (hsargtype . arg_type) args+ rettyp :: Type ()+ rettyp = hsrettype ret+ selftyp = case msc of+ Just (_,c) -> tyapp tyPtr (tycon (snd (hsClassName c)))+ Nothing -> error "hsFFIFuncTyp: no self for top level function"+ hsargtype :: Types -> Type ()+ hsargtype (CT ctype _) = convertC2HS ctype+ hsargtype (CPT (CPTClass d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsargtype (CPT (CPTClassRef d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsargtype (CPT (CPTClassMove d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsargtype (CPT (CPTClassCopy d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsargtype (TemplateApp x) = tyapp tyPtr $+ foldl1 tyapp $+ map tycon $+ rawname : map hsClassNameForTArg (tapp_tparams x)+ where rawname = snd (hsTemplateClassName (tapp_tclass x))+ hsargtype (TemplateAppRef x) = tyapp tyPtr $+ foldl1 tyapp $+ map tycon $+ rawname : map hsClassNameForTArg (tapp_tparams x)+ where rawname = snd (hsTemplateClassName (tapp_tclass x))+ hsargtype (TemplateAppMove x)= tyapp tyPtr $+ foldl1 tyapp $+ map tycon $+ rawname : map hsClassNameForTArg (tapp_tparams x)+ where rawname = snd (hsTemplateClassName (tapp_tclass x))+ hsargtype (TemplateType t) = tyapp tyPtr $ foldl1 tyapp (tycon rawname : map mkTVar (tclass_params t))+ where rawname = snd (hsTemplateClassName t)+ hsargtype (TemplateParam p) = mkTVar p+ hsargtype SelfType = selftyp+ hsargtype _ = error "hsFuncTyp: undefined hsargtype"+ ---------------------------------------------------------+ hsrettype Void = unit_tycon+ hsrettype SelfType = selftyp+ hsrettype (CT ctype _) = convertC2HS ctype+ hsrettype (CPT (CPTClass d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsrettype (CPT (CPTClassRef d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsrettype (CPT (CPTClassCopy d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsrettype (CPT (CPTClassMove d) _) = tyapp tyPtr (tycon rawname)+ where rawname = snd (hsClassName d)+ hsrettype (TemplateApp x) = tyapp tyPtr $+ foldl1 tyapp $+ map tycon $+ rawname : map hsClassNameForTArg (tapp_tparams x)+ where rawname = snd (hsTemplateClassName (tapp_tclass x))+ hsrettype (TemplateAppRef x) = tyapp tyPtr $+ foldl1 tyapp $+ map tycon $+ rawname : map hsClassNameForTArg (tapp_tparams x)+ where rawname = snd (hsTemplateClassName (tapp_tclass x))+ hsrettype (TemplateAppMove x)= tyapp tyPtr $+ foldl1 tyapp $+ map tycon $+ rawname : map hsClassNameForTArg (tapp_tparams x)+ where rawname = snd (hsTemplateClassName (tapp_tclass x))+ hsrettype (TemplateType t) = tyapp tyPtr $+ foldl1 tyapp (tycon rawname : map mkTVar (tclass_params t))+ where rawname = snd (hsTemplateClassName t)+ hsrettype (TemplateParam p) = mkTVar p+ hsrettype (TemplateParamPointer p) = mkTVar p++++genericFuncRet :: Function -> Types+genericFuncRet f =+ case f of+ Constructor _ _ -> self_+ Virtual t _ _ _ -> t+ NonVirtual t _ _ _-> t+ Static t _ _ _ -> t+ Destructor _ -> void_++genericFuncArgs :: Function -> [Arg]+genericFuncArgs (Destructor _) = []+genericFuncArgs f = func_args f
+ src/FFICXX/Generate/Config.hs view
@@ -0,0 +1,26 @@+module FFICXX.Generate.Config where++import FFICXX.Generate.Type.Cabal ( Cabal )+import FFICXX.Generate.Type.Class ( Class, TopLevel )+import FFICXX.Generate.Type.Config ( ModuleUnitMap(..) )+import FFICXX.Generate.Type.Module ( TemplateClassImportHeader )+++data FFICXXConfig = FFICXXConfig {+ fficxxconfig_workingDir :: FilePath+ , fficxxconfig_installBaseDir :: FilePath+ , fficxxconfig_staticFileDir :: FilePath+ } deriving Show++data SimpleBuilderConfig =+ SimpleBuilderConfig {+ sbcTopModule :: String+ , sbcModUnitMap :: ModuleUnitMap+ , sbcCabal :: Cabal+ , sbcClasses :: [Class]+ , sbcTopLevels :: [TopLevel]+ , sbcTemplates :: [TemplateClassImportHeader]+ , sbcExtraLibs :: [String]+ , sbcExtraDeps :: [(String,[String])]+ , sbcStaticFiles :: [String]+ }
+ src/FFICXX/Generate/ContentMaker.hs view
@@ -0,0 +1,531 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module FFICXX.Generate.ContentMaker where++import Control.Lens ( (&), (.~), at )+import Control.Monad.Trans.Reader+import Data.Either ( rights )+import Data.Functor.Identity ( Identity )+import qualified Data.Map as M+import Data.Maybe ( mapMaybe )+import Data.Monoid ( (<>) )+import Data.List ( intercalate, nub )+import Data.List.Split ( splitOn )+import Language.Haskell.Exts.Syntax ( Module(..)+ , Decl(..)+ )+import System.FilePath ( (<.>), (</>) )+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+import qualified FFICXX.Runtime.CodeGen.Cxx as R+--+import FFICXX.Generate.Code.Cpp ( genAllCppHeaderInclude+ , genCppDefMacroAccessor+ , genCppDefMacroNonVirtual+ , genCppDefMacroTemplateMemberFunction+ , genCppDefMacroVirtual+ , genCppDefInstAccessor+ , genCppDefInstNonVirtual+ , genCppDefInstVirtual+ , genCppHeaderInstAccessor+ , genCppHeaderInstNonVirtual+ , genCppHeaderInstVirtual+ , genCppHeaderMacroAccessor+ , genCppHeaderMacroType+ , genCppHeaderMacroVirtual+ , genCppHeaderMacroNonVirtual+ , genTopLevelCppDefinition+ , topLevelDecl+ )+import FFICXX.Generate.Code.HsCast ( genHsFrontInstCastable+ , genHsFrontInstCastableSelf+ )+import FFICXX.Generate.Code.HsFFI ( genHsFFI+ , genImportInFFI+ , genTopLevelFFI+ )+import FFICXX.Generate.Code.HsFrontEnd ( genExport+ , genExtraImport+ , genHsFrontDecl+ , genHsFrontDowncastClass+ , genHsFrontInst+ , genHsFrontInstNew+ , genHsFrontInstNonVirtual+ , genHsFrontInstStatic+ , genHsFrontInstVariables+ , genHsFrontUpcastClass+ , genImportInCast+ , genImportInImplementation+ , genImportInInterface+ , genImportInModule+ , genImportInTopLevel+ , genTopLevelDef+ , hsClassRawType+ )+import FFICXX.Generate.Code.HsProxy ( genProxyInstance )+import FFICXX.Generate.Code.HsTemplate ( genImportInTemplate+ , genImportInTH+ , genTemplateMemberFunctions+ , genTmplInstance+ , genTmplInterface+ , genTmplImplementation+ )+import FFICXX.Generate.Dependency+import FFICXX.Generate.Name ( ffiClassName, hsClassName+ , hsFrontNameForTopLevel+ )+import FFICXX.Generate.Type.Annotate ( AnnotateMap )+import FFICXX.Generate.Type.Class ( Class(..)+ , ClassGlobal(..)+ , DaughterMap+ , ProtectedMethod(..)+ , isAbstractClass+ )+import FFICXX.Generate.Type.Module ( ClassImportHeader(..)+ , ClassModule(..)+ , TemplateClassImportHeader(..)+ , TemplateClassModule(..)+ , TopLevelImportHeader(..)+ )+import FFICXX.Generate.Type.PackageInterface ( ClassName(..)+ , PackageInterface+ , PackageName(..)+ )+import FFICXX.Generate.Util.HaskellSrcExts+++srcDir :: FilePath -> FilePath+srcDir installbasedir = installbasedir </> "src"++csrcDir :: FilePath -> FilePath+csrcDir installbasedir = installbasedir </> "csrc"++---- common function for daughter++-- |+mkGlobal :: [Class] -> ClassGlobal+mkGlobal = ClassGlobal <$> mkDaughterSelfMap <*> mkDaughterMap+++-- |+buildDaughterDef ::+ ((String,[Class]) -> String)+ -> DaughterMap+ -> String+buildDaughterDef f m =+ let lst = M.toList m+ f' (x,xs) = f (x,filter (not.isAbstractClass) xs)+ in (concatMap f' lst)++-- |+buildParentDef :: ((Class,Class) -> [R.CStatement Identity]) -> Class -> [R.CStatement Identity]+buildParentDef f cls = concatMap (\p -> f (p,cls)) . class_allparents $ cls++-- |+mkProtectedFunctionList :: Class -> [R.CMacro Identity]+mkProtectedFunctionList c =+ map (\x-> R.Define (R.sname ("IS_" <> class_name c <> "_" <> x <> "_PROTECTED")) [] [R.CVerbatim "()"])+ . unProtected+ . class_protected+ $ c++-- |+buildTypeDeclHeader ::+ [Class]+ -> String+buildTypeDeclHeader classes =+ let typeDeclBodyStmts =+ intercalate [R.EmptyLine] $+ map (map R.CRegular . genCppHeaderMacroType) classes+ in R.renderBlock $+ R.ExternC $+ [ R.Pragma R.Once, R.EmptyLine ] <> typeDeclBodyStmts+++-- |+buildDeclHeader ::+ String -- ^ C prefix+ -> ClassImportHeader+ -> String+buildDeclHeader cprefix header =+ let classes = [cihClass header]+ aclass = cihClass header+ declHeaderStmts =+ [ R.Include (HdrName (cprefix ++ "Type.h")) ]+ <> map R.Include (cihIncludedHPkgHeadersInH header)+ vdecl = map genCppHeaderMacroVirtual classes+ nvdecl = map genCppHeaderMacroNonVirtual classes+ acdecl = map genCppHeaderMacroAccessor classes+ vdef = map genCppDefMacroVirtual classes+ nvdef = map genCppDefMacroNonVirtual classes+ acdef = map genCppDefMacroAccessor classes+ tmpldef= map (\c -> map (genCppDefMacroTemplateMemberFunction c) (class_tmpl_funcs c)) classes+ declDefStmts =+ intercalate [R.EmptyLine] $ [vdecl,nvdecl,acdecl,vdef,nvdef,acdef]++tmpldef+ classDeclStmts =+ -- NOTE: Deletable is treated specially.+ -- TODO: We had better make it as a separate constructor in Class.+ if (fst.hsClassName) aclass /= "Deletable"+ then buildParentDef (\(p,c) -> [genCppHeaderInstVirtual (p,c), R.CEmptyLine]) aclass+ <> [genCppHeaderInstVirtual (aclass, aclass), R.CEmptyLine]+ <> concatMap (\c -> [genCppHeaderInstNonVirtual c, R.CEmptyLine]) classes+ <> concatMap (\c -> [genCppHeaderInstAccessor c, R.CEmptyLine]) classes+ else []+ in R.renderBlock $+ R.ExternC $+ [ R.Pragma R.Once, R.EmptyLine ]+ <> declHeaderStmts+ <> [ R.EmptyLine ]+ <> declDefStmts+ <> [ R.EmptyLine ]+ <> map R.CRegular classDeclStmts++-- |+buildDefMain ::+ ClassImportHeader+ -> String+buildDefMain cih =+ let classes = [cihClass cih]+ headerStmts =+ [ R.Include "MacroPatternMatch.h" ]+ <> genAllCppHeaderInclude cih+ <> [ R.Include (cihSelfHeader cih) ]+ namespaceStmts =+ (map R.UsingNamespace . cihNamespace) cih+ aclass = cihClass cih+ aliasStr = intercalate "\n" $+ mapMaybe typedefstmt $+ aclass : rights (cihImportedClasses cih)+ where typedefstmt c = let n1 = class_name c+ n2 = ffiClassName c+ in if n1 == n2+ then Nothing+ else Just ("typedef " <> n1 <> " " <> n2 <> ";")++ cppBodyStmts =+ mkProtectedFunctionList (cihClass cih)+ <> map+ R.CRegular+ ( buildParentDef (\(p,c) -> [genCppDefInstVirtual (p,c), R.CEmptyLine]) (cihClass cih)+ <> (if isAbstractClass aclass+ then []+ else [genCppDefInstVirtual (aclass, aclass), R.CEmptyLine]+ )+ <> concatMap (\c -> [genCppDefInstNonVirtual c, R.CEmptyLine]) classes+ <> concatMap (\c -> [genCppDefInstAccessor c, R.CEmptyLine]) classes+ )+ in concatMap R.renderCMacro+ ( headerStmts+ <> [ R.EmptyLine ]+ <> map R.CRegular namespaceStmts+ <> [ R.EmptyLine+ , R.Verbatim aliasStr+ , R.EmptyLine+ , R.Verbatim "#define CHECKPROTECT(x,y) FXIS_PAREN(IS_ ## x ## _ ## y ## _PROTECTED)\n"+ , R.EmptyLine+ , R.Verbatim "#define TYPECASTMETHOD(cname,mname,oname) \\\n\+ \ FXIIF( CHECKPROTECT(cname,mname) ) ( \\\n\+ \ (from_nonconst_to_nonconst<oname,cname ## _t>), \\\n\+ \ (from_nonconst_to_nonconst<cname,cname ## _t>) )\n"+ , R.EmptyLine+ ]+ <> cppBodyStmts+ )++-- |+buildTopLevelHeader ::+ String -- ^ C prefix+ -> TopLevelImportHeader+ -> String+buildTopLevelHeader cprefix tih =+ let declHeaderStmts =+ [ R.Include (HdrName (cprefix ++ "Type.h")) ]+ <> map R.Include (map cihSelfHeader (tihClassDep tih) ++ tihExtraHeadersInH tih)+ declBodyStmts = map (R.CDeclaration . topLevelDecl) $ tihFuncs tih+ in R.renderBlock $+ R.ExternC $+ [ R.Pragma R.Once, R.EmptyLine ]+ <> declHeaderStmts+ <> [ R.EmptyLine ]+ <> map R.CRegular declBodyStmts++-- |+buildTopLevelCppDef :: TopLevelImportHeader -> String+buildTopLevelCppDef tih =+ let cihs = tihClassDep tih+ extclasses = tihExtraClassDep tih+ declHeaderStmts =+ [ R.Include "MacroPatternMatch.h"+ , R.Include (HdrName (tihHeaderFileName tih <.> "h"))+ ]+ <> concatMap genAllCppHeaderInclude cihs+ <> otherHeaderStmts+ otherHeaderStmts =+ map R.Include (map cihSelfHeader cihs ++ tihExtraHeadersInCPP tih)++ allns = nub ((tihClassDep tih >>= cihNamespace) ++ tihNamespaces tih)++ namespaceStmts = map R.UsingNamespace allns+ aliasStr = intercalate "\n" $+ mapMaybe typedefstmt $+ rights (concatMap cihImportedClasses cihs ++ extclasses)+ where typedefstmt c = let n1 = class_name c+ n2 = ffiClassName c+ in if n1 == n2+ then Nothing+ else Just ("typedef " <> n1 <> " " <> n2 <> ";")+ declBodyStr =+ intercalate "\n" $+ map (R.renderCStmt . genTopLevelCppDefinition) (tihFuncs tih)++ in concatMap R.renderCMacro+ ( declHeaderStmts+ <> [R.EmptyLine]+ <> map R.CRegular namespaceStmts+ <> [ R.EmptyLine+ , R.Verbatim aliasStr+ , R.EmptyLine+ , R.Verbatim "#define CHECKPROTECT(x,y) FXIS_PAREN(IS_ ## x ## _ ## y ## _PROTECTED)\n"+ , R.EmptyLine+ , R.Verbatim "#define TYPECASTMETHOD(cname,mname,oname) \\\n\+ \ FXIIF( CHECKPROTECT(cname,mname) ) ( \\\n\+ \ (to_nonconst<oname,cname ## _t>), \\\n\+ \ (to_nonconst<cname,cname ## _t>) )\n"+ , R.EmptyLine+ , R.Verbatim declBodyStr+ ]+ )++-- |+buildFFIHsc :: ClassModule -> Module ()+buildFFIHsc m = mkModule (mname <.> "FFI") [lang ["ForeignFunctionInterface"]] ffiImports hscBody+ where mname = cmModule m+ ffiImports = [ mkImport "Data.Word"+ , mkImport "Data.Int"+ , mkImport "Foreign.C"+ , mkImport "Foreign.Ptr"+ , mkImport (mname <.> "RawType") ]+ <> genImportInFFI m+ <> genExtraImport m+ hscBody = genHsFFI (cmCIH m)+++-- |+buildRawTypeHs :: ClassModule -> Module ()+buildRawTypeHs m =+ mkModule+ (cmModule m <.> "RawType")+ [ lang+ [ "ForeignFunctionInterface"+ , "TypeFamilies"+ , "MultiParamTypeClasses"+ , "FlexibleInstances"+ , "TypeSynonymInstances"+ , "EmptyDataDecls"+ , "ExistentialQuantification"+ , "ScopedTypeVariables"+ ]+ ]+ rawtypeImports+ rawtypeBody+ where+ rawtypeImports = [ mkImport "Foreign.Ptr"+ , mkImport "FFICXX.Runtime.Cast"+ ]+ rawtypeBody = let c = cihClass (cmCIH m)+ in if isAbstractClass c then [] else hsClassRawType c++-- |+buildInterfaceHs :: AnnotateMap -> ClassModule -> Module ()+buildInterfaceHs amap m =+ mkModule+ (cmModule m <.> "Interface")+ [ lang+ [ "EmptyDataDecls"+ , "ExistentialQuantification"+ , "FlexibleContexts"+ , "FlexibleInstances"+ , "ForeignFunctionInterface"+ , "MultiParamTypeClasses"+ , "ScopedTypeVariables"+ , "TypeFamilies"+ , "TypeSynonymInstances"+ ]+ ]+ ifaceImports+ ifaceBody+ where+ classes = [cihClass (cmCIH m)]+ ifaceImports = [ mkImport "Data.Word"+ , mkImport "Data.Int"+ , mkImport "Foreign.C"+ , mkImport "Foreign.Ptr"+ , mkImport "FFICXX.Runtime.Cast"+ ]+ <> genImportInInterface m+ <> genExtraImport m+ ifaceBody =+ runReader (mapM genHsFrontDecl classes) amap+ <> (concatMap genHsFrontUpcastClass . filter (not.isAbstractClass)) classes+ <> (concatMap genHsFrontDowncastClass . filter (not.isAbstractClass)) classes++-- |+buildCastHs :: ClassModule -> Module ()+buildCastHs m = mkModule (cmModule m <.> "Cast")+ [ lang [ "FlexibleInstances", "FlexibleContexts", "TypeFamilies"+ , "MultiParamTypeClasses", "OverlappingInstances", "IncoherentInstances" ] ]+ castImports body+ where classes = [ cihClass (cmCIH m) ]+ castImports = [ mkImport "Foreign.Ptr"+ , mkImport "FFICXX.Runtime.Cast"+ , mkImport "System.IO.Unsafe" ]+ <> genImportInCast m+ body = mapMaybe genHsFrontInstCastable classes+ <> mapMaybe genHsFrontInstCastableSelf classes++-- |+buildImplementationHs :: AnnotateMap -> ClassModule -> Module ()+buildImplementationHs amap m =+ mkModule (cmModule m <.> "Implementation")+ [ lang [ "EmptyDataDecls"+ , "FlexibleContexts"+ , "FlexibleInstances"+ , "ForeignFunctionInterface"+ , "IncoherentInstances"+ , "MultiParamTypeClasses"+ , "OverlappingInstances"+ , "TemplateHaskell"+ , "TypeFamilies"+ , "TypeSynonymInstances"+ ]+ ]+ implImports implBody+ where+ classes = [ cihClass (cmCIH m) ]+ implImports = [ mkImport "Data.Monoid" -- for template member+ , mkImport "Data.Word"+ , mkImport "Data.Int"+ , mkImport "Foreign.C"+ , mkImport "Foreign.Ptr"+ , mkImport "Language.Haskell.TH" -- for template member+ , mkImport "Language.Haskell.TH.Syntax" -- for template member+ , mkImport "System.IO.Unsafe"+ , mkImport "FFICXX.Runtime.Cast"+ , mkImport "FFICXX.Runtime.CodeGen.Cxx" -- for template member+ , mkImport "FFICXX.Runtime.TH" -- for template member+ ]+ <> genImportInImplementation m+ <> genExtraImport m+ f :: Class -> [Decl ()]+ f y = concatMap (flip genHsFrontInst y) (y:class_allparents y)++ implBody = concatMap f classes+ <> runReader (concat <$> mapM genHsFrontInstNew classes) amap+ <> concatMap genHsFrontInstNonVirtual classes+ <> concatMap genHsFrontInstStatic classes+ <> concatMap genHsFrontInstVariables classes+ <> genTemplateMemberFunctions (cmCIH m)++buildProxyHs :: ClassModule -> Module ()+buildProxyHs m =+ mkModule (cmModule m <.> "Proxy")+ [ lang [ "FlexibleInstances"+ , "OverloadedStrings"+ , "TemplateHaskell"+ ]+ ]+ [ mkImport "Foreign.Ptr"+ , mkImport "FFICXX.Runtime.Cast"+ , mkImport "Language.Haskell.TH"+ , mkImport "Language.Haskell.TH.Syntax"+ , mkImport "FFICXX.Runtime.CodeGen.Cxx"+ ]+ body+ where+ body = genProxyInstance++++buildTemplateHs :: TemplateClassModule -> Module ()+buildTemplateHs m =+ mkModule (tcmModule m <.> "Template")+ [ lang+ [ "EmptyDataDecls"+ , "FlexibleInstances"+ , "MultiParamTypeClasses"+ , "TypeFamilies"+ ]+ ]+ imports+ body+ where+ t = tcihTClass $ tcmTCIH m+ imports = [ mkImport "Foreign.C.Types"+ , mkImport "Foreign.Ptr"+ , mkImport "FFICXX.Runtime.Cast"+ ]+ <> genImportInTemplate t+ body = genTmplInterface t++buildTHHs :: TemplateClassModule -> Module ()+buildTHHs m =+ mkModule (tcmModule m <.> "TH")+ [ lang ["TemplateHaskell"] ]+ ( [ mkImport "Data.Char"+ , mkImport "Data.List"+ , mkImport "Data.Monoid"+ , mkImport "Foreign.C.Types"+ , mkImport "Foreign.Ptr"+ , mkImport "Language.Haskell.TH"+ , mkImport "Language.Haskell.TH.Syntax"+ , mkImport "FFICXX.Runtime.CodeGen.Cxx"+ , mkImport "FFICXX.Runtime.TH"+ ]+ <> imports+ )+ body+ where+ t = tcihTClass $ tcmTCIH m+ imports = [ mkImport (tcmModule m <.> "Template") ]+ <> genImportInTH t+ body = tmplImpls <> tmplInsts+ tmplImpls = genTmplImplementation t+ tmplInsts = genTmplInstance (tcmTCIH m)++-- |+buildInterfaceHSBOOT :: String -> Module ()+buildInterfaceHSBOOT mname = mkModule (mname <.> "Interface") [] [] hsbootBody+ where cname = last (splitOn "." mname)+ hsbootBody = [ mkClass cxEmpty ('I':cname) [mkTBind "a"] [] ]++-- |+buildModuleHs :: ClassModule -> Module ()+buildModuleHs m = mkModuleE (cmModule m) [] (genExport c) (genImportInModule c) []+ where c = cihClass (cmCIH m)++-- |+buildTopLevelHs :: String -> ([ClassModule],[TemplateClassModule]) -> TopLevelImportHeader -> Module ()+buildTopLevelHs modname (mods,tmods) tih =+ mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody+ where+ tfns = tihFuncs tih+ pkgExtensions = [ lang [ "FlexibleContexts", "FlexibleInstances" ] ]+ pkgExports = map (emodule . cmModule) mods+ ++ map (evar . unqual . hsFrontNameForTopLevel) tfns++ pkgImports = genImportInTopLevel modname (mods,tmods) tih++ pkgBody = map (genTopLevelFFI tih) tfns+ ++ concatMap genTopLevelDef tfns++-- |+buildPackageInterface :: PackageInterface+ -> PackageName+ -> [ClassImportHeader]+ -> PackageInterface+buildPackageInterface pinfc pkgname = foldr f pinfc+ where f cih repo =+ let name = (class_name . cihClass) cih+ header = cihSelfHeader cih+ in repo & at (pkgname,ClsName name) .~ (Just header)
+ src/FFICXX/Generate/Dependency.hs view
@@ -0,0 +1,434 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Dependency where++-- fficxx generates one module per one C++ class, and C++ class depends on other classes,+-- so we need to import other modules corresponding to C++ classes in the dependency list.+-- Calculating the import list from dependency graph is what this module does.++-- Previously, we have only `Class` type, but added `TemplateClass` recently. Therefore+-- we have to calculate dependency graph for both types of classes. So we needed to change+-- `Class` to `Either TemplateClass Class` in many of routines that calculates module import+-- list.++-- `Dep4Func` contains a list of classes (both ordinary and template types) that is needed+-- for the definition of a member function.+-- The goal of `extractClassDep...` functions are to extract Dep4Func, and from the definition+-- of a class or a template class, we get a list of `Dep4Func`s and then we deduplicate the+-- dependency class list and finally get the import list for the module corresponding to+-- a given class.++import Data.Either ( rights )+import Data.Function ( on )+import qualified Data.HashMap.Strict as HM+import Data.List ( find, foldl', nub, nubBy )+import qualified Data.Map as M+import Data.Maybe ( catMaybes, fromMaybe, mapMaybe )+import Data.Monoid ( (<>) )+import System.FilePath ( (<.>) )+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+--+import FFICXX.Generate.Name ( ffiClassName, hsClassName, hsTemplateClassName )+import FFICXX.Generate.Type.Cabal ( AddCInc,AddCSrc,CabalName(..)+ , cabal_moduleprefix, cabal_pkgname+ , cabal_cheaderprefix, unCabalName+ )+import FFICXX.Generate.Type.Class ( Arg(..)+ , Class(..)+ , CPPTypes(..)+ , DaughterMap+ , Function(..)+ , TemplateAppInfo(..)+ , TemplateArgType(TArg_Class)+ , TemplateClass(..)+ , TemplateFunction(..)+ , TemplateMemberFunction(..)+ , TopLevel(..)+ , Types(..)+ , Variable(unVariable)+ , argsFromOpExp+ )+import FFICXX.Generate.Type.Config ( ModuleUnit(..)+ , ModuleUnitImports(..)+ , emptyModuleUnitImports+ , ModuleUnitMap(..)+ )+import FFICXX.Generate.Type.Module ( ClassImportHeader(..)+ , ClassModule(..)+ , PackageConfig(..)+ , TemplateClassImportHeader(..)+ , TemplateClassModule(..)+ , TopLevelImportHeader(..)+ )+++-- utility functions++getcabal = either tclass_cabal class_cabal++getparents = either (const []) (map Right . class_parents)++-- TODO: replace tclass_name with appropriate FFI name when supported.+getFFIName = either tclass_name ffiClassName+++getPkgName :: Either TemplateClass Class -> CabalName+getPkgName = cabal_pkgname . getcabal+++-- |+extractClassFromType :: Types -> [Either TemplateClass Class]+extractClassFromType Void = []+extractClassFromType SelfType = []+extractClassFromType (CT _ _) = []+extractClassFromType (CPT (CPTClass c) _) = [Right c]+extractClassFromType (CPT (CPTClassRef c) _) = [Right c]+extractClassFromType (CPT (CPTClassCopy c) _) = [Right c]+extractClassFromType (CPT (CPTClassMove c) _) = [Right c]+extractClassFromType (TemplateApp (TemplateAppInfo t ps _)) =+ Left t : (map Right $ mapMaybe (\case TArg_Class c -> Just c; _ -> Nothing) ps)+extractClassFromType (TemplateAppRef (TemplateAppInfo t ps _)) =+ Left t : (map Right $ mapMaybe (\case TArg_Class c -> Just c; _ -> Nothing) ps)+extractClassFromType (TemplateAppMove (TemplateAppInfo t ps _)) =+ Left t : (map Right $ mapMaybe (\case TArg_Class c -> Just c; _ -> Nothing) ps)+extractClassFromType (TemplateType t) = [Left t]+extractClassFromType (TemplateParam _) = []+extractClassFromType (TemplateParamPointer _) = []++classFromArg :: Arg -> [Either TemplateClass Class]+classFromArg = extractClassFromType . arg_type+++class_allparents :: Class -> [Class]+class_allparents c = let ps = class_parents c+ in if null ps+ then []+ else nub (ps <> (concatMap class_allparents ps))+++getClassModuleBase :: Class -> String+getClassModuleBase = (<.>) <$> (cabal_moduleprefix.class_cabal) <*> (fst.hsClassName)++getTClassModuleBase :: TemplateClass -> String+getTClassModuleBase = (<.>) <$> (cabal_moduleprefix.tclass_cabal) <*> (fst.hsTemplateClassName)+++-- | Daughter map not including itself+mkDaughterMap :: [Class] -> DaughterMap+mkDaughterMap = foldl mkDaughterMapWorker M.empty+ where mkDaughterMapWorker m c = let ps = map getClassModuleBase (class_allparents c)+ in foldl (addmeToYourDaughterList c) m ps+ addmeToYourDaughterList c m p = let f Nothing = Just [c]+ f (Just cs) = Just (c:cs)+ in M.alter f p m++++-- | Daughter Map including itself as a daughter+mkDaughterSelfMap :: [Class] -> DaughterMap+mkDaughterSelfMap = foldl' worker M.empty+ where worker m c = let ps = map getClassModuleBase (c:class_allparents c)+ in foldl (addToList c) m ps+ addToList c m p = let f Nothing = Just [c]+ f (Just cs) = Just (c:cs)+ in M.alter f p m++++-- | class dependency for a given function+data Dep4Func = Dep4Func { returnDependency :: [Either TemplateClass Class]+ , argumentDependency :: [Either TemplateClass Class] }+++-- |+extractClassDep :: Function -> Dep4Func+extractClassDep (Constructor args _) =+ Dep4Func [] (concatMap classFromArg args)+extractClassDep (Virtual ret _ args _) =+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+extractClassDep (NonVirtual ret _ args _) =+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+extractClassDep (Static ret _ args _) =+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+extractClassDep (Destructor _) =+ Dep4Func [] []++-- |+extractClassDepForTmplFun :: TemplateFunction -> Dep4Func+extractClassDepForTmplFun (TFun ret _ _ args) =+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+extractClassDepForTmplFun (TFunNew args _) =+ Dep4Func [] (concatMap classFromArg args)+extractClassDepForTmplFun TFunDelete =+ Dep4Func [] []+extractClassDepForTmplFun (TFunOp ret _ e) =+ Dep4Func (extractClassFromType ret) (concatMap classFromArg $ argsFromOpExp e)++-- |+extractClassDep4TmplMemberFun :: TemplateMemberFunction -> Dep4Func+extractClassDep4TmplMemberFun (TemplateMemberFunction {..}) =+ Dep4Func (extractClassFromType tmf_ret) (concatMap classFromArg tmf_args)++-- |+extractClassDepForTopLevel :: TopLevel -> Dep4Func+extractClassDepForTopLevel f =+ Dep4Func (extractClassFromType ret) (concatMap (extractClassFromType . arg_type) args)+ where ret = case f of+ TopLevelFunction {..} -> toplevelfunc_ret+ TopLevelVariable {..} -> toplevelvar_ret+ args = case f of+ TopLevelFunction {..} -> toplevelfunc_args+ TopLevelVariable {..} -> []+++-- TODO: Confirm the answer below is correct.+-- NOTE: Q: Why returnDependency only?+-- A: Difference between argument and return:+-- for a member function f,+-- we have (f :: (IA a, IB b) => a -> b -> IO C+-- return class is concrete and argument class is constraint.+mkModuleDepRaw :: Either TemplateClass Class -> [Either TemplateClass Class]+mkModuleDepRaw x@(Right c) =+ nub $+ filter (/= x) $+ concatMap (returnDependency . extractClassDep) (class_funcs c)+ ++ concatMap (returnDependency . extractClassDep4TmplMemberFun) (class_tmpl_funcs c)+mkModuleDepRaw x@(Left t) =+ (nub . filter (/= x) . concatMap (returnDependency.extractClassDepForTmplFun) . tclass_funcs) t++-- |+isNotInSamePackageWith+ :: Either TemplateClass Class+ -> Either TemplateClass Class+ -> Bool+isNotInSamePackageWith x y = (x /= y) && (getPkgName x /= getPkgName y)++-- x is in the sam+isInSamePackageButNotInheritedBy+ :: Either TemplateClass Class -- ^ y+ -> Either TemplateClass Class -- ^ x+ -> Bool+isInSamePackageButNotInheritedBy x y =+ x /= y && not (x `elem` getparents y) && (getPkgName x == getPkgName y)++-- TODO: Confirm the following answer+-- NOTE: Q: why returnDependency is not considered?+-- A: See explanation in mkModuleDepRaw+mkModuleDepHighNonSource :: Either TemplateClass Class -> [Either TemplateClass Class]+mkModuleDepHighNonSource y@(Right c) =+ let extclasses = filter (`isNotInSamePackageWith` y) $+ concatMap (argumentDependency.extractClassDep) (class_funcs c)+ ++ concatMap (argumentDependency.extractClassDep4TmplMemberFun) (class_tmpl_funcs c)+ parents = map Right (class_parents c)+ in nub (parents <> extclasses)+mkModuleDepHighNonSource y@(Left t) =+ let fs = tclass_funcs t+ extclasses = filter (`isNotInSamePackageWith` y) $+ concatMap (argumentDependency.extractClassDepForTmplFun) fs+ in nub extclasses++-- TODO: Confirm the following answer+-- NOTE: Q: why returnDependency is not considered?+-- A: See explanation in mkModuleDepRaw+mkModuleDepHighSource :: Either TemplateClass Class -> [Either TemplateClass Class]+mkModuleDepHighSource y@(Right c) =+ nub $+ filter (`isInSamePackageButNotInheritedBy` y) $+ concatMap (argumentDependency . extractClassDep) (class_funcs c)+ ++ concatMap (argumentDependency . extractClassDep4TmplMemberFun) (class_tmpl_funcs c)+mkModuleDepHighSource y@(Left t) =+ let fs = tclass_funcs t+ in nub $+ filter (`isInSamePackageButNotInheritedBy` y) $+ concatMap (argumentDependency . extractClassDepForTmplFun) fs++-- |+mkModuleDepCpp :: Either TemplateClass Class -> [Either TemplateClass Class]+mkModuleDepCpp y@(Right c) =+ let fs = class_funcs c+ vs = class_vars c+ tmfs = class_tmpl_funcs c+ in nub . filter (/= y) $+ concatMap (returnDependency.extractClassDep) fs+ <> concatMap (argumentDependency.extractClassDep) fs+ <> concatMap (classFromArg . unVariable) vs+ <> concatMap (returnDependency.extractClassDep4TmplMemberFun) tmfs+ <> concatMap (argumentDependency.extractClassDep4TmplMemberFun) tmfs+ <> getparents y+mkModuleDepCpp y@(Left t) =+ let fs = tclass_funcs t+ in nub . filter (/= y) $+ concatMap (returnDependency.extractClassDepForTmplFun) fs+ <> concatMap (argumentDependency.extractClassDepForTmplFun) fs+ <> getparents y++-- |+mkModuleDepFFI1 :: Either TemplateClass Class -> [Either TemplateClass Class]+mkModuleDepFFI1 (Right c) = let fs = class_funcs c+ vs = class_vars c+ tmfs = class_tmpl_funcs c+ in concatMap (returnDependency.extractClassDep) fs+ <> concatMap (argumentDependency.extractClassDep) fs+ <> concatMap (classFromArg . unVariable) vs+ <> concatMap (returnDependency.extractClassDep4TmplMemberFun) tmfs+ <> concatMap (argumentDependency.extractClassDep4TmplMemberFun) tmfs+mkModuleDepFFI1 (Left t) = let fs = tclass_funcs t+ in concatMap (returnDependency.extractClassDepForTmplFun) fs+ <> concatMap (argumentDependency.extractClassDepForTmplFun) fs++-- |+mkModuleDepFFI :: Either TemplateClass Class -> [Either TemplateClass Class]+mkModuleDepFFI y@(Right c) =+ let ps = map Right (class_allparents c)+ alldeps' = (concatMap mkModuleDepFFI1 ps) <> mkModuleDepFFI1 y+ in nub (filter (/= y) alldeps')+mkModuleDepFFI (Left _) = []++-- |+mkClassModule :: (ModuleUnit -> ModuleUnitImports)+ -> [(String,[String])]+ -> Class+ -> ClassModule+mkClassModule getImports extra c =+ ClassModule {+ cmModule = getClassModuleBase c+ , cmCIH = mkCIH getImports c+ , cmImportedModulesHighNonSource = highs_nonsource+ , cmImportedModulesRaw =raws+ , cmImportedModulesHighSource = highs_source+ , cmImportedModulesForFFI = ffis+ , cmExtraImport = extraimports+ }+ where highs_nonsource = mkModuleDepHighNonSource (Right c)+ raws = mkModuleDepRaw (Right c)+ highs_source = mkModuleDepHighSource (Right c)+ ffis = mkModuleDepFFI (Right c)+ extraimports = fromMaybe [] (lookup (class_name c) extra)++-- |+findModuleUnitImports :: ModuleUnitMap -> ModuleUnit -> ModuleUnitImports+findModuleUnitImports m u =+ fromMaybe emptyModuleUnitImports (HM.lookup u (unModuleUnitMap m))++-- |+mkTCM ::+ TemplateClassImportHeader+ -> TemplateClassModule+mkTCM tcih =+ let t = tcihTClass tcih+ in TCM (getTClassModuleBase t) tcih++-- |+mkPackageConfig+ :: (CabalName, ModuleUnit -> ModuleUnitImports) -- ^ (package name,getImports)+ -> ([Class],[TopLevel],[TemplateClassImportHeader],[(String,[String])])+ -> [AddCInc]+ -> [AddCSrc]+ -> PackageConfig+mkPackageConfig (pkgname,getImports) (cs,fs,ts,extra) acincs acsrcs =+ let ms = map (mkClassModule getImports extra) cs+ cmpfunc x y = class_name (cihClass x) == class_name (cihClass y)+ cihs = nubBy cmpfunc (map cmCIH ms)+ --+ tih = mkTIH pkgname getImports cihs fs+ tcms = map mkTCM ts+ tcihs = map tcmTCIH tcms+ in PkgConfig {+ pcfg_classModules = ms+ , pcfg_classImportHeaders = cihs+ , pcfg_topLevelImportHeader = tih+ , pcfg_templateClassModules = tcms+ , pcfg_templateClassImportHeaders = tcihs+ , pcfg_additional_c_incs = acincs+ , pcfg_additional_c_srcs = acsrcs+ }++-- TODO: change [String] to Set String+mkHSBOOTCandidateList :: [ClassModule] -> [String]+mkHSBOOTCandidateList ms =+ let+ -- get only class dependencies, not template classes.+ cs = rights (concatMap cmImportedModulesHighSource ms)+ in+ nub (map getClassModuleBase cs)++-- |+mkPkgHeaderFileName ::Class -> HeaderName+mkPkgHeaderFileName c =+ HdrName ( (cabal_cheaderprefix.class_cabal) c+ <> fst (hsClassName c)+ <.> "h"+ )++-- |+mkPkgCppFileName ::Class -> String+mkPkgCppFileName c =+ (cabal_cheaderprefix.class_cabal) c+ <> fst (hsClassName c)+ <.> "cpp"++-- |+mkPkgIncludeHeadersInH :: Class -> [HeaderName]+mkPkgIncludeHeadersInH c =+ let pkgname = (cabal_pkgname . class_cabal) c+ extclasses = filter ((/= pkgname) . getPkgName) . mkModuleDepCpp $ Right c+ extheaders = nub . map ((<>"Type.h") . unCabalName . getPkgName) $ extclasses+ in map mkPkgHeaderFileName (class_allparents c) <> map HdrName extheaders++-- |+mkPkgIncludeHeadersInCPP :: Class -> [HeaderName]+mkPkgIncludeHeadersInCPP = map mkPkgHeaderFileName . rights . mkModuleDepCpp . Right++-- |+mkCIH :: (ModuleUnit -> ModuleUnitImports) -- ^ (mk namespace and include headers)+ -> Class+ -> ClassImportHeader+mkCIH getImports c =+ ClassImportHeader {+ cihClass = c+ , cihSelfHeader = mkPkgHeaderFileName c+ , cihNamespace = (muimports_namespaces . getImports . MU_Class . class_name) c+ , cihSelfCpp = mkPkgCppFileName c+ , cihImportedClasses = mkModuleDepCpp (Right c)+ , cihIncludedHPkgHeadersInH = mkPkgIncludeHeadersInH c+ , cihIncludedHPkgHeadersInCPP = mkPkgIncludeHeadersInCPP c+ , cihIncludedCPkgHeaders = (muimports_headers . getImports . MU_Class . class_name) c+ }++-- | for top-level+mkTIH+ :: CabalName+ -> (ModuleUnit -> ModuleUnitImports)+ -> [ClassImportHeader]+ -> [TopLevel]+ -> TopLevelImportHeader+mkTIH pkgname getImports cihs fs =+ let tl_cs1 = concatMap (argumentDependency . extractClassDepForTopLevel) fs+ tl_cs2 = concatMap (returnDependency . extractClassDepForTopLevel) fs+ tl_cs = nubBy ((==) `on` either tclass_name ffiClassName) (tl_cs1 <> tl_cs2)+ -- NOTE: Select only class dependencies in the current package.+ -- TODO: This is clearly not a good impl. we need to look into this again+ -- after reconsidering multi-package generation.+ tl_cihs = catMaybes (foldr fn [] tl_cs)+ where+ fn c ys =+ let y = find (\x -> (ffiClassName . cihClass) x == getFFIName c) cihs+ in y:ys+ -- NOTE: The remaining class dependencies outside the current package+ extclasses = filter ((/= pkgname) . getPkgName) tl_cs+ extheaders = map HdrName $+ nub $+ map ((<>"Type.h") . unCabalName . getPkgName) extclasses++ in+ TopLevelImportHeader {+ tihHeaderFileName = unCabalName pkgname <> "TopLevel"+ , tihClassDep = tl_cihs+ , tihExtraClassDep = extclasses+ , tihFuncs = fs+ , tihNamespaces = muimports_namespaces (getImports MU_TopLevel)+ , tihExtraHeadersInH = extheaders+ , tihExtraHeadersInCPP = muimports_headers (getImports MU_TopLevel)+ }
+ src/FFICXX/Generate/Name.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE RecordWildCards #-}+module FFICXX.Generate.Name where++import Data.Char ( toLower )+import Data.Maybe ( fromMaybe, maybe )+import Data.Monoid ( (<>) )+--+import FFICXX.Generate.Type.Class ( Accessor(..)+ , Arg(..)+ , Class(..)+ , ClassAlias(caHaskellName,caFFIName)+ , Function(..)+ , TemplateArgType(..)+ , TemplateClass(..)+ , TemplateFunction(..)+ , TemplateMemberFunction(..)+ , TopLevel(..)+ , Variable(..)+ )+import FFICXX.Generate.Util ( firstLower, toLowers )++++hsFrontNameForTopLevel :: TopLevel -> String+hsFrontNameForTopLevel tfn =+ let (x:xs) = case tfn of+ TopLevelFunction {..} -> fromMaybe toplevelfunc_name toplevelfunc_alias+ TopLevelVariable {..} -> fromMaybe toplevelvar_name toplevelvar_alias+ in toLower x : xs+++typeclassName :: Class -> String+typeclassName c = 'I' : fst (hsClassName c)++typeclassNameT :: TemplateClass -> String+typeclassNameT c = 'I' : fst (hsTemplateClassName c)++++typeclassNameFromStr :: String -> String+typeclassNameFromStr = ('I':)++hsClassName :: Class -> (String, String) -- ^ High-level, 'Raw'-level+hsClassName c =+ let cname = maybe (class_name c) caHaskellName (class_alias c)+ in (cname, "Raw" <> cname)++hsClassNameForTArg :: TemplateArgType -> String+hsClassNameForTArg (TArg_Class c) = fst (hsClassName c)+hsClassNameForTArg (TArg_TypeParam p) = p+hsClassNameForTArg (TArg_Other s) = s++hsTemplateClassName :: TemplateClass -> (String, String) -- ^ High-level, 'Raw'-level+hsTemplateClassName t =+ let tname = tclass_name t+ in (tname, "Raw" <> tname)++existConstructorName :: Class -> String+existConstructorName c = 'E' : (fst.hsClassName) c+++ffiClassName :: Class -> String+ffiClassName c = maybe (class_name c) caFFIName (class_alias c)++hscFuncName :: Class -> Function -> String+hscFuncName c f = "c_"+ <> toLowers (ffiClassName c)+ <> "_"+ <> toLowers (aliasedFuncName c f)++hsFuncName :: Class -> Function -> String+hsFuncName c f = let (x:xs) = aliasedFuncName c f+ in (toLower x) : xs++aliasedFuncName :: Class -> Function -> String+aliasedFuncName c f =+ case f of+ Constructor _ a -> fromMaybe (constructorName c) a+ Virtual _ str _ a -> fromMaybe str a+ NonVirtual _ str _ a -> fromMaybe (nonvirtualName c str) a+ Static _ str _ a -> fromMaybe (nonvirtualName c str) a+ Destructor a -> fromMaybe destructorName a++-- |+hsTmplFuncName :: TemplateClass -> TemplateFunction -> String+hsTmplFuncName t f =+ case f of+ TFun {..} -> tfun_name+ TFunNew {..} -> fromMaybe ("new"<> tclass_name t) tfun_new_alias+ TFunDelete -> "delete" <> tclass_name t+ TFunOp {..} -> tfun_name++-- |+hsTmplFuncNameTH :: TemplateClass -> TemplateFunction -> String+hsTmplFuncNameTH t f = "t_" <> hsTmplFuncName t f+++hsTemplateMemberFunctionName :: Class -> TemplateMemberFunction -> String+hsTemplateMemberFunctionName c f = fromMaybe (nonvirtualName c (tmf_name f)) (tmf_alias f)+++hsTemplateMemberFunctionNameTH :: Class -> TemplateMemberFunction -> String+hsTemplateMemberFunctionNameTH c f = "t_" <> hsTemplateMemberFunctionName c f+++ffiTmplFuncName :: TemplateFunction -> String+ffiTmplFuncName f =+ case f of+ TFun {..} -> tfun_name+ TFunNew {..} -> fromMaybe "new" tfun_new_alias+ TFunDelete -> "delete"+ TFunOp {..} -> tfun_name++cppTmplFuncName :: TemplateFunction -> String+cppTmplFuncName f =+ case f of+ TFun {..} -> tfun_name+ TFunNew {..} -> "new"+ TFunDelete -> "delete"+ TFunOp {..} -> tfun_name++-- |+accessorName :: Class -> Variable -> Accessor -> String+accessorName c v a = nonvirtualName c (arg_name (unVariable v))+ <> "_"+ <> case a of+ Getter -> "get"+ Setter -> "set"++-- |+hscAccessorName :: Class -> Variable -> Accessor -> String+hscAccessorName c v a = "c_" <> toLowers (accessorName c v a)++-- |+tmplAccessorName :: Variable -> Accessor -> String+tmplAccessorName (Variable (Arg _ n)) a =+ n <> "_" <> case a of { Getter -> "get"; Setter -> "set" }++-- |+cppStaticName :: Class -> Function -> String+cppStaticName c f = class_name c <> "::" <> func_name f++-- |+cppFuncName :: Class -> Function -> String+cppFuncName c f = case f of+ Constructor _ _ -> "new"+ Virtual _ _ _ _ -> func_name f+ NonVirtual _ _ _ _-> func_name f+ Static _ _ _ _-> cppStaticName c f+ Destructor _ -> destructorName++constructorName :: Class -> String+constructorName c = "new" <> (fst.hsClassName) c++nonvirtualName :: Class -> String -> String+nonvirtualName c str = (firstLower.fst.hsClassName) c <> "_" <> str++destructorName :: String+destructorName = "delete"+
+ src/FFICXX/Generate/QQ/Verbatim.hs view
@@ -0,0 +1,13 @@+module FFICXX.Generate.QQ.Verbatim where++import Language.Haskell.TH.Quote+import Language.Haskell.TH.Lib++verbatim :: QuasiQuoter+verbatim = QuasiQuoter{ quoteExp = litE . stringL+ , quotePat = undefined+ , quoteType = undefined+ , quoteDec = undefined+ -- , quotePat = litP . stringP+ } +
+ src/FFICXX/Generate/Type/Annotate.hs view
@@ -0,0 +1,11 @@+module FFICXX.Generate.Type.Annotate where++import qualified Data.Map as M++data PkgType = PkgModule | PkgClass | PkgMethod + deriving (Show,Eq,Ord)++type AnnotateMap = M.Map (PkgType,String) String+++
+ src/FFICXX/Generate/Type/Cabal.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE DeriveGeneric #-}++module FFICXX.Generate.Type.Cabal where++import Data.Aeson (FromJSON(..),ToJSON(..)+ ,genericParseJSON,genericToJSON+ ,defaultOptions)+import Data.Aeson.Types (fieldLabelModifier)+import Data.Text (Text)+import GHC.Generics (Generic)++data AddCInc = AddCInc FilePath String++data AddCSrc = AddCSrc FilePath String++-- TODO: change String to Text+newtype CabalName = CabalName { unCabalName :: String }+ deriving (Show,Eq,Ord)+++data BuildType = Simple+ | Custom [CabalName] -- ^ dependencies++-- TODO: change String to Text+data Cabal =+ Cabal {+ cabal_pkgname :: CabalName+ , cabal_version :: String+ , cabal_cheaderprefix :: String+ , cabal_moduleprefix :: String+ , cabal_additional_c_incs :: [AddCInc]+ , cabal_additional_c_srcs :: [AddCSrc]+ , cabal_additional_pkgdeps :: [CabalName]+ , cabal_license :: Maybe String+ , cabal_licensefile :: Maybe String+ , cabal_extraincludedirs :: [FilePath]+ , cabal_extralibdirs :: [FilePath]+ , cabal_extrafiles :: [FilePath]+ , cabal_pkg_config_depends :: [String]+ , cabal_buildType :: BuildType+ }++data GeneratedCabalInfo =+ GeneratedCabalInfo {+ gci_pkgname :: Text+ , gci_version :: Text+ , gci_synopsis :: Text+ , gci_description :: Text+ , gci_homepage :: Text+ , gci_license :: Text+ , gci_licenseFile :: Text+ , gci_author :: Text+ , gci_maintainer :: Text+ , gci_category :: Text+ , gci_buildtype :: Text+ , gci_extraFiles :: [Text]+ , gci_csrcFiles :: [Text]+ , gci_sourcerepository :: Text+ , gci_cxxOptions :: [Text]+ , gci_pkgdeps :: [Text]+ , gci_exposedModules :: [Text]+ , gci_otherModules :: [Text]+ , gci_extraLibDirs :: [Text]+ , gci_extraLibraries :: [Text]+ , gci_extraIncludeDirs :: [Text]+ , gci_pkgconfigDepends :: [Text]+ , gci_includeFiles :: [Text]+ , gci_cppFiles :: [Text]+ }+ deriving (Show,Generic)++instance ToJSON GeneratedCabalInfo where+ toJSON = genericToJSON defaultOptions {fieldLabelModifier = drop 4}++instance FromJSON GeneratedCabalInfo where+ parseJSON = genericParseJSON defaultOptions {fieldLabelModifier = drop 4}
+ src/FFICXX/Generate/Type/Class.hs view
@@ -0,0 +1,341 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Type.Class where++import Data.List ( intercalate )+import qualified Data.Map as M+import Data.Monoid ( Monoid(..) )+import Data.Semigroup ( Semigroup(..), (<>) )+--+import FFICXX.Generate.Type.Cabal ( Cabal )+++-- | C types+data CTypes =+ CTBool+ | CTChar+ | CTClock+ | CTDouble+ | CTFile+ | CTFloat+ | CTFpos+ | CTInt+ | CTIntMax+ | CTIntPtr+ | CTJmpBuf+ | CTLLong+ | CTLong+ | CTPtrdiff+ | CTSChar+ | CTSUSeconds+ | CTShort+ | CTSigAtomic+ | CTSize+ | CTTime+ | CTUChar+ | CTUInt+ | CTUIntMax+ | CTUIntPtr+ | CTULLong+ | CTULong+ | CTUSeconds+ | CTUShort+ | CTWchar+ | CTInt8+ | CTInt16+ | CTInt32+ | CTInt64+ | CTUInt8+ | CTUInt16+ | CTUInt32+ | CTUInt64+ | CTVoidStar+ | CTString+ | CEnum CTypes String+ | CPointer CTypes+ | CRef CTypes+ deriving Show++-- | C++ types+data CPPTypes = CPTClass Class+ | CPTClassRef Class+ | CPTClassCopy Class+ | CPTClassMove Class+ deriving Show++-- | const flag+data IsConst = Const | NoConst+ deriving Show++-- | Argument type which can be used as an template argument like float+-- in vector<float>.+-- For now, this distinguishes Class and non-Class.+data TemplateArgType =+ TArg_Class Class+ | TArg_TypeParam String+ | TArg_Other String+ deriving Show++data TemplateAppInfo =+ TemplateAppInfo {+ tapp_tclass :: TemplateClass+ , tapp_tparams :: [TemplateArgType]+ , tapp_CppTypeForParam :: String -- TODO: remove this+ }+ deriving Show++-- | Supported C++ types.+data Types =+ Void+ | SelfType+ | CT CTypes IsConst+ | CPT CPPTypes IsConst+ | TemplateApp TemplateAppInfo -- ^ like vector<float>*+ | TemplateAppRef TemplateAppInfo -- ^ like vector<float>&+ | TemplateAppMove TemplateAppInfo -- ^ like unique_ptr<float> (using std::move)+ | TemplateType TemplateClass -- ^ template self? TODO: clarify this.+ | TemplateParam String+ | TemplateParamPointer String -- ^ this is A* with template<A>+ deriving Show++-------------++-- | Function argument, type and variable name.+data Arg =+ Arg {+ arg_type :: Types+ , arg_name :: String+ }+ deriving Show++-- | Regular member functions in a ordinary class+data Function =+ Constructor {+ func_args :: [Arg]+ , func_alias :: Maybe String+ }+ | Virtual {+ func_ret :: Types+ , func_name :: String+ , func_args :: [Arg]+ , func_alias :: Maybe String+ }+ | NonVirtual {+ func_ret :: Types+ , func_name :: String+ , func_args :: [Arg]+ , func_alias :: Maybe String+ }+ | Static {+ func_ret :: Types+ , func_name :: String+ , func_args :: [Arg]+ , func_alias :: Maybe String+ }+ | Destructor {+ func_alias :: Maybe String+ }+ deriving Show++-- | Member variable. Isomorphic to Arg+newtype Variable =+ Variable { unVariable :: Arg }+ deriving Show++-- | Member functions of a template class.+data TemplateMemberFunction =+ TemplateMemberFunction {+ tmf_params :: [String]+ , tmf_ret :: Types+ , tmf_name :: String+ , tmf_args :: [Arg]+ , tmf_alias :: Maybe String+ }+ deriving Show++-- | Function defined at top level like ordinary C functions,+-- i.e. no owning class.+data TopLevel =+ TopLevelFunction {+ toplevelfunc_ret :: Types+ , toplevelfunc_name :: String+ , toplevelfunc_args :: [Arg]+ , toplevelfunc_alias :: Maybe String+ }+ | TopLevelVariable {+ toplevelvar_ret :: Types+ , toplevelvar_name :: String+ , toplevelvar_alias :: Maybe String+ }+ deriving Show++isNewFunc :: Function -> Bool+isNewFunc (Constructor _ _) = True+isNewFunc _ = False++isDeleteFunc :: Function -> Bool+isDeleteFunc (Destructor _) = True+isDeleteFunc _ = False++isVirtualFunc :: Function -> Bool+isVirtualFunc (Destructor _) = True+isVirtualFunc (Virtual _ _ _ _) = True+isVirtualFunc _ = False++isNonVirtualFunc :: Function -> Bool+isNonVirtualFunc (NonVirtual _ _ _ _) = True+isNonVirtualFunc _ = False++++isStaticFunc :: Function -> Bool+isStaticFunc (Static _ _ _ _) = True+isStaticFunc _ = False++virtualFuncs :: [Function] -> [Function]+virtualFuncs = filter isVirtualFunc++constructorFuncs :: [Function] -> [Function]+constructorFuncs = filter isNewFunc++nonVirtualNotNewFuncs :: [Function] -> [Function]+nonVirtualNotNewFuncs =+ filter (\x -> (not.isVirtualFunc) x && (not.isNewFunc) x && (not.isDeleteFunc) x && (not.isStaticFunc) x )++staticFuncs :: [Function] -> [Function]+staticFuncs = filter isStaticFunc++--------++newtype ProtectedMethod = Protected { unProtected :: [String] }+ deriving (Semigroup, Monoid)++data ClassAlias = ClassAlias { caHaskellName :: String+ , caFFIName :: String+ }++-- TODO: partial record must be avoided.+data Class = Class {+ class_cabal :: Cabal+ , class_name :: String+ , class_parents :: [Class]+ , class_protected :: ProtectedMethod+ , class_alias :: Maybe ClassAlias+ , class_funcs :: [Function]+ , class_vars :: [Variable]+ , class_tmpl_funcs :: [TemplateMemberFunction]+ , class_has_proxy :: Bool+ }+ | AbstractClass {+ class_cabal :: Cabal+ , class_name :: String+ , class_parents :: [Class]+ , class_protected :: ProtectedMethod+ , class_alias :: Maybe ClassAlias+ , class_funcs :: [Function]+ , class_vars :: [Variable]+ , class_tmpl_funcs :: [TemplateMemberFunction]+ }++-- TODO: we had better not override standard definitions+instance Show Class where+ show x = show (class_name x)++-- TODO: we had better not override standard definitions+instance Eq Class where+ (==) x y = class_name x == class_name y++-- TODO: we had better not override standard definitions+instance Ord Class where+ compare x y = compare (class_name x) (class_name y)++data OpExp = OpStar -- ^ unary * (deRef) operator+ | OpFPPlus -- ^ unary prefix ++ operator+ -- | OpAdd Arg Arg+ -- | OpMul Arg Arg++data TemplateFunction =+ TFun {+ tfun_ret :: Types+ , tfun_name :: String+ , tfun_oname :: String+ , tfun_args :: [Arg]+ }+ | TFunNew {+ tfun_new_args :: [Arg]+ , tfun_new_alias :: Maybe String+ }+ | TFunDelete+ | TFunOp {+ tfun_ret :: Types+ , tfun_name :: String -- ^ haskell alias for the operator+ , tfun_opexp :: OpExp+ }++argsFromOpExp :: OpExp -> [Arg]+argsFromOpExp OpStar = []+argsFromOpExp OpFPPlus = []+-- argsFromOpExp (OpAdd x y) = [x,y]+-- argsFromOpExp (OpMul x y) = [x,y]++opSymbol :: OpExp -> String+opSymbol OpStar = "*"+opSymbol OpFPPlus = "++"+-- opSymbol (OpAdd _ _) = "+"+-- opSymbol (OpMul _ _) = "*"++-- TODO: Generalize this further.+-- | Positional string interpolation form.+-- For example, "std::map<K,V>::iterator" is FormNested "std::map" "iterator"].+data Form = FormSimple String+ | FormNested String String++data TemplateClass =+ TmplCls {+ tclass_cabal :: Cabal+ , tclass_name :: String+ , tclass_cxxform :: Form+ , tclass_params :: [String]+ , tclass_funcs :: [TemplateFunction]+ , tclass_vars :: [Variable]+ }++-- TODO: we had better not override standard definitions+instance Show TemplateClass where+ show x = show (tclass_name x <> " " <> intercalate " " (tclass_params x))++-- TODO: we had better not override standard definitions+instance Eq TemplateClass where+ (==) x y = tclass_name x == tclass_name y++-- TODO: we had better not override standard definitions+instance Ord TemplateClass where+ compare x y = compare (tclass_name x) (tclass_name y)+++data ClassGlobal = ClassGlobal+ { cgDaughterSelfMap :: DaughterMap+ , cgDaughterMap :: DaughterMap+ }++data Selfness = Self | NoSelf++++-- | Check abstract class+isAbstractClass :: Class -> Bool+isAbstractClass Class{} = False+isAbstractClass AbstractClass{} = True++-- | Check having Proxy+hasProxy :: Class -> Bool+hasProxy c@Class{} = class_has_proxy c+hasProxy AbstractClass{} = False++type DaughterMap = M.Map String [Class]++data Accessor = Getter | Setter+ deriving (Show, Eq)
+ src/FFICXX/Generate/Type/Config.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE DeriveGeneric #-}+module FFICXX.Generate.Type.Config where++import Data.Hashable ( Hashable(..) )+import Data.HashMap.Strict ( HashMap )+import GHC.Generics ( Generic )+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..), Namespace(..) )+++data ModuleUnit = MU_TopLevel + | MU_Class String+ deriving (Show,Eq,Generic)++instance Hashable ModuleUnit++data ModuleUnitImports =+ ModuleUnitImports {+ muimports_namespaces :: [Namespace]+ , muimports_headers :: [HeaderName]+ }+ deriving (Show)++emptyModuleUnitImports = ModuleUnitImports [] []++newtype ModuleUnitMap = ModuleUnitMap { unModuleUnitMap :: HashMap ModuleUnit ModuleUnitImports }++modImports ::+ String+ -> [String]+ -> [HeaderName]+ -> (ModuleUnit,ModuleUnitImports)+modImports n ns hs =+ ( MU_Class n+ , ModuleUnitImports {+ muimports_namespaces = map NS ns+ , muimports_headers = hs+ }+ )
+ src/FFICXX/Generate/Type/Module.hs view
@@ -0,0 +1,80 @@+module FFICXX.Generate.Type.Module where++import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..), Namespace(..) )+--+import FFICXX.Generate.Type.Cabal ( AddCInc, AddCSrc )+import FFICXX.Generate.Type.Class ( Class, TemplateClass, TopLevel )+++-- | C++ side+-- HPkg is generated C++ headers by fficxx, CPkg is original C++ headers+data ClassImportHeader =+ ClassImportHeader {+ cihClass :: Class+ , cihSelfHeader :: HeaderName -- ^ fficxx-side main header+ , cihNamespace :: [Namespace]+ , cihSelfCpp :: String+ , cihImportedClasses :: [Either TemplateClass Class] -- ^ Dependencies TODO: clarify this.+ , cihIncludedHPkgHeadersInH :: [HeaderName] -- TODO: Explain why we need to have these two+ , cihIncludedHPkgHeadersInCPP :: [HeaderName] -- separately.+ , cihIncludedCPkgHeaders :: [HeaderName] -- ^ C++-side headers+ } deriving (Show)+++-------------------------+-- Haskell side module --+-------------------------++data ClassModule =+ ClassModule {+ cmModule :: String+ , cmCIH :: ClassImportHeader+ , cmImportedModulesHighNonSource :: [Either TemplateClass Class]+ -- ^ imported modules that do not need source+ -- NOTE: source means the same cabal package.+ -- TODO: rename Source to something more clear.+ , cmImportedModulesRaw :: [Either TemplateClass Class]+ -- ^ imported modules for raw types.+ , cmImportedModulesHighSource :: [Either TemplateClass Class]+ -- ^ imported modules that need source+ , cmImportedModulesForFFI :: [Either TemplateClass Class]+ , cmExtraImport :: [String]+ } deriving (Show)+++data TemplateClassModule =+ TCM {+ tcmModule :: String+ , tcmTCIH :: TemplateClassImportHeader+ } deriving (Show)+++data TemplateClassImportHeader =+ TCIH {+ tcihTClass :: TemplateClass+ , tcihCxxHeaders :: [HeaderName] -- ^ C++-side headers+ } deriving (Show)++data TopLevelImportHeader =+ TopLevelImportHeader {+ tihHeaderFileName :: String+ , tihClassDep :: [ClassImportHeader]+ , tihExtraClassDep :: [Either TemplateClass Class]+ -- ^ Extra class dependencies outside current package.+ -- NOTE: we cannot fully construct ClassImportHeader for them.+ , tihFuncs :: [TopLevel]+ , tihNamespaces :: [Namespace]+ , tihExtraHeadersInH :: [HeaderName]+ , tihExtraHeadersInCPP :: [HeaderName]+ } deriving (Show)++data PackageConfig =+ PkgConfig {+ pcfg_classModules :: [ClassModule]+ , pcfg_classImportHeaders :: [ClassImportHeader]+ , pcfg_topLevelImportHeader :: TopLevelImportHeader+ , pcfg_templateClassModules :: [TemplateClassModule]+ , pcfg_templateClassImportHeaders :: [TemplateClassImportHeader]+ , pcfg_additional_c_incs :: [AddCInc]+ , pcfg_additional_c_srcs :: [AddCSrc]+ }
+ src/FFICXX/Generate/Type/PackageInterface.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++-- TODO: remove this module+module FFICXX.Generate.Type.PackageInterface where ++import Data.Hashable ( Hashable )+import qualified Data.HashMap.Strict as HM+--+import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+++newtype PackageName = PkgName String deriving (Hashable, Show, Eq, Ord)+newtype ClassName = ClsName String deriving (Hashable, Show, Eq, Ord)++type PackageInterface = HM.HashMap (PackageName, ClassName) HeaderName
+ src/FFICXX/Generate/Util.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE OverloadedStrings #-}++module FFICXX.Generate.Util where++import Data.Char +import Data.List+import Data.List.Split+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import Data.Text.Template+--++moduleDirFile :: String -> (String,String)+moduleDirFile mname = + let splitted = splitOn "." mname+ moddir = intercalate "/" (init splitted )+ modfile = (last splitted) <> ".hs" + in (moddir, modfile)++hline :: IO ()+hline = putStrLn "--------------------------------------------------------"++toUppers :: String -> String+toUppers = map toUpper++toLowers :: String -> String +toLowers = map toLower+++firstLower :: String -> String +firstLower [] = [] +firstLower (x:xs) = (toLower x) : xs ++conn :: String -> String -> String -> String +conn st x y = x <> st <> y ++connspace :: String -> String -> String+connspace = conn " " ++conncomma :: String -> String -> String+conncomma = conn ", " ++connBSlash :: String -> String -> String +connBSlash = conn "\\\n"++connSemicolonBSlash :: String -> String -> String+connSemicolonBSlash = conn "; \\\n"++connRet :: String -> String -> String+connRet = conn "\n"++connRet2 :: String -> String -> String +connRet2 = conn "\n\n"++connArrow :: String -> String -> String +connArrow = conn " -> " ++intercalateWith :: (String-> String -> String) -> (a->String) -> [a] -> String+intercalateWith f mapper x + | not (null x) = foldl1 f (map mapper x)+ | otherwise = "" +++intercalateWithM :: (Monad m) => (String -> String -> String) -> (a->m String) -> [a] -> m String +intercalateWithM f mapper x + | not (null x) = do ms <- mapM mapper x+ return (foldl1 f ms)+ | otherwise = return "" +++-- TODO: deprecate this and use contextT+context :: [(Text,String)] -> Context+context assocs x = maybe err (T.pack) . lookup x $ assocs+ where err = error $ "Could not find key: " <> (T.unpack x)++-- TODO: Rename this to context.+-- TODO: Proper error handling.+contextT :: [(Text,Text)] -> Context+contextT assocs x = fromMaybe err . lookup x $ assocs+ where err = error $ T.unpack ("Could not find key: " <> x)++subst :: Text -> Context -> String+subst t c = TL.unpack (substitute t c)
+ src/FFICXX/Generate/Util/HaskellSrcExts.hs view
@@ -0,0 +1,223 @@+{-# LANGUAGE CPP #-}++module FFICXX.Generate.Util.HaskellSrcExts where++import Data.Maybe (maybeToList)+import Data.List (foldl')+import Language.Haskell.Exts hiding (unit_tycon)+import qualified Language.Haskell.Exts (unit_tycon)+++unqual :: String -> QName ()+unqual = UnQual () . Ident ()++tycon :: String -> Type ()+tycon = TyCon () . unqual++tyapp :: Type () -> Type () -> Type ()+tyapp = TyApp ()++infixl 2 `tyapp`++tyfun :: Type () -> Type () -> Type ()+tyfun = TyFun ()++infixr 2 `tyfun`++tylist :: Type () -> Type ()+tylist = TyList ()++unit_tycon :: Type ()+unit_tycon = Language.Haskell.Exts.unit_tycon ()++conDecl :: String -> [Type ()] -> ConDecl ()+conDecl n ys = ConDecl () (Ident () n) ys++qualConDecl = QualConDecl ()++recDecl :: String -> [FieldDecl ()] -> ConDecl ()+recDecl n rs = RecDecl () (Ident () n) rs++app' :: String -> String -> Exp ()+app' x y = App () (mkVar x) (mkVar y)+++lit :: Literal () -> Exp ()+lit = Lit ()+++mkVar :: String -> Exp ()+mkVar = Var () . unqual++con :: String -> Exp ()+con = Con () . unqual++mkTVar :: String -> Type ()+mkTVar = TyVar () . Ident ()++mkPVar :: String -> Pat ()+mkPVar = PVar () . Ident ()++mkIVar :: String -> ImportSpec ()+mkIVar = IVar () . Ident ()++mkPVarSig :: String -> Type () -> Pat ()+mkPVarSig n typ = PatTypeSig () (mkPVar n) typ++pbind :: Pat () -> Exp () -> Maybe (Binds ()) -> Decl ()+pbind pat e = PatBind () pat (UnGuardedRhs () e)++pbind_ :: Pat () -> Exp () -> Decl ()+pbind_ p e = pbind p e Nothing++mkTBind :: String -> TyVarBind ()+mkTBind = UnkindedVar () . Ident ()++mkBind1 :: String -> [Pat ()] -> Exp () -> Maybe (Binds ()) -> Decl ()+mkBind1 n pat rhs mbinds =+ FunBind () [ Match () (Ident () n) pat (UnGuardedRhs () rhs) mbinds ]++mkFun :: String -> Type () -> [Pat ()] -> Exp () -> Maybe (Binds ()) -> [Decl ()]+mkFun fname typ pats rhs mbinds = [mkFunSig fname typ, mkBind1 fname pats rhs mbinds]++mkFunSig :: String -> Type () -> Decl ()+mkFunSig fname typ = TypeSig () [Ident () fname] typ++mkClass :: Context () -> String -> [TyVarBind ()] -> [ClassDecl ()] -> Decl ()+mkClass ctxt n tbinds cdecls = ClassDecl () (Just ctxt) (mkDeclHead n tbinds) [] (Just cdecls)+++dhead :: String -> DeclHead ()+dhead n = DHead () (Ident () n)++mkDeclHead :: String -> [TyVarBind ()] -> DeclHead ()+mkDeclHead n tbinds = foldl' (DHApp ()) (dhead n) tbinds++mkInstance :: Context () -> String -> [Type ()] -> [InstDecl ()] -> Decl ()+mkInstance ctxt n typs idecls = InstDecl () Nothing instrule (Just idecls)+ where instrule = IRule () Nothing (Just ctxt) insthead+ insthead = foldl' f (IHCon () (unqual n)) typs+ where f acc x = IHApp () acc (tyParen x)++mkData :: String -> [TyVarBind ()] -> [QualConDecl ()] -> Maybe (Deriving ()) -> Decl ()+#if MIN_VERSION_haskell_src_exts(1,20,0)+mkData n tbinds qdecls mderiv = DataDecl () (DataType ()) Nothing declhead qdecls (maybeToList mderiv)+#else+mkData n tbinds qdecls mderiv = DataDecl () (DataType ()) Nothing declhead qdecls mderiv+#endif+ where declhead = mkDeclHead n tbinds++mkNewtype :: String -> [TyVarBind ()] -> [QualConDecl ()] -> Maybe (Deriving ()) -> Decl ()+#if MIN_VERSION_haskell_src_exts(1,20,0)+mkNewtype n tbinds qdecls mderiv = DataDecl () (NewType ()) Nothing declhead qdecls (maybeToList mderiv)+#else+mkNewtype n tbinds qdecls mderiv = DataDecl () (NewType ()) Nothing declhead qdecls mderiv+#endif+ where declhead = mkDeclHead n tbinds++mkForImpCcall :: String -> String -> Type () -> Decl ()+mkForImpCcall quote n typ = ForImp () (CCall ()) (Just (PlaySafe () False)) (Just quote) (Ident () n) typ++mkModule :: String -> [ModulePragma ()] -> [ImportDecl ()] -> [Decl ()] -> Module ()+mkModule n pragmas idecls decls = Module () (Just mhead) pragmas idecls decls+ where mhead = ModuleHead () (ModuleName () n) Nothing Nothing++mkModuleE :: String -> [ModulePragma ()] -> [ExportSpec ()] -> [ImportDecl ()] -> [Decl ()] -> Module ()+mkModuleE n pragmas exps idecls decls = Module () (Just mhead) pragmas idecls decls+ where mhead = ModuleHead () (ModuleName () n) Nothing (Just eslist)+ eslist = ExportSpecList () exps++mkImport :: String -> ImportDecl ()+mkImport m = ImportDecl () (ModuleName () m) False False False Nothing Nothing Nothing++mkImportExp :: String -> [String] -> ImportDecl ()+mkImportExp m lst =+ ImportDecl () (ModuleName () m) False False False Nothing Nothing (Just islist)+ where islist = ImportSpecList () False (map mkIVar lst)+++mkImportSrc :: String -> ImportDecl ()+mkImportSrc m = ImportDecl () (ModuleName () m) False True False Nothing Nothing Nothing++lang :: [String] -> ModulePragma ()+lang ns = LanguagePragma () (map (Ident ()) ns)++dot :: Exp () -> Exp () -> Exp ()+x `dot` y = x `app` mkVar "." `app` y++tyForall = TyForall ()++tyParen = TyParen ()++tyPtr :: Type ()+tyPtr = tycon "Ptr"++tyForeignPtr :: Type ()+tyForeignPtr = tycon "ForeignPtr"++classA :: QName () -> [Type ()] -> Asst ()+#if MIN_VERSION_haskell_src_exts(1,22,0)+classA n = TypeA () . foldl' tyapp (TyCon () n)+#else+classA = ClassA ()+#endif++cxEmpty :: Context ()+cxEmpty = CxEmpty ()++cxTuple :: [Asst ()] -> Context ()+cxTuple = CxTuple ()++tySplice :: Splice () -> Type ()+tySplice = TySplice ()++parenSplice :: Exp () -> Splice ()+parenSplice = ParenSplice ()++bracketExp = BracketExp ()+typeBracket = TypeBracket ()+++#if MIN_VERSION_haskell_src_exts(1,20,0)+mkDeriving = Deriving () Nothing+#else+mkDeriving = Deriving ()+#endif++irule = IRule ()++ihcon = IHCon ()++evar = EVar ()+eabs = EAbs ()+ethingwith = EThingWith ()++ethingall q = ethingwith (EWildcard () 0) q []++emodule nm = EModuleContents () (ModuleName () nm)++nonamespace = NoNamespace ()++insType = InsType ()++insDecl = InsDecl ()++generator = Generator ()++qualifier = Qualifier ()++clsDecl = ClsDecl ()+++unkindedVar = UnkindedVar ()++op = QVarOp () . UnQual () . Symbol ()++inapp = InfixApp ()++if_ = If ()++urhs = UnGuardedRhs ()++-- case pattern match p -> e+match p e = Alt () p (urhs e) Nothing