fficxx 0.6 → 0.7.0.0
raw patch · 27 files changed
+4949/−3663 lines, 27 filesdep +arraydep +dotgendep −eitherdep ~haskell-src-extsPVP ok
version bump matches the API change (PVP)
Dependencies added: array, dotgen
Dependencies removed: either
Dependency ranges changed: haskell-src-exts
API changes (from Hackage documentation)
- FFICXX.Generate.Code.HsFrontEnd: genImportForTopLevel :: TopLevel -> [ImportDecl ()]
- FFICXX.Generate.ContentMaker: buildInterfaceHSBOOT :: String -> Module ()
- FFICXX.Generate.Dependency: extractClassDepForTopLevel :: TopLevel -> Dep4Func
- FFICXX.Generate.Dependency: getClassModuleBase :: Class -> String
- FFICXX.Generate.Dependency: getTClassModuleBase :: TemplateClass -> String
- FFICXX.Generate.Dependency: mkHSBOOTCandidateList :: [ClassModule] -> [String]
- FFICXX.Generate.Dependency: mkModuleDepFFI :: Either TemplateClass Class -> [Either TemplateClass Class]
- FFICXX.Generate.Dependency: mkModuleDepFFI1 :: Either TemplateClass Class -> [Either TemplateClass Class]
- FFICXX.Generate.Dependency: mkModuleDepHighNonSource :: Either TemplateClass Class -> [Either TemplateClass Class]
- FFICXX.Generate.Dependency: mkModuleDepHighSource :: Either TemplateClass Class -> [Either TemplateClass Class]
- FFICXX.Generate.Dependency: mkModuleDepRaw :: Either TemplateClass Class -> [Either TemplateClass Class]
- FFICXX.Generate.Type.Module: [cmImportedModulesForFFI] :: ClassModule -> [Either TemplateClass Class]
- FFICXX.Generate.Type.Module: [cmImportedModulesHighNonSource] :: ClassModule -> [Either TemplateClass Class]
- FFICXX.Generate.Type.Module: [cmImportedModulesHighSource] :: ClassModule -> [Either TemplateClass Class]
- FFICXX.Generate.Type.Module: [cmImportedModulesRaw] :: ClassModule -> [Either TemplateClass Class]
+ FFICXX.Generate.Code.Cpp: genTLTmplFunCpp :: IsCPrimitive -> TLTemplate -> CMacro Identity
+ FFICXX.Generate.Code.Cpp: topLevelTemplateFunToDecl :: IsCPrimitive -> TLTemplate -> CFunDecl Identity
+ FFICXX.Generate.Code.Cpp: topLevelTemplateFunToDef :: IsCPrimitive -> TLTemplate -> CStatement Identity
+ FFICXX.Generate.Code.HsFrontEnd: genImportForTLOrdinary :: TLOrdinary -> [ImportDecl ()]
+ FFICXX.Generate.Code.HsFrontEnd: genImportForTLTemplate :: TLTemplate -> [ImportDecl ()]
+ FFICXX.Generate.Code.HsFrontEnd: mkImportWithDepCycles :: DepCycles -> String -> String -> ImportDecl ()
+ FFICXX.Generate.Code.HsTemplate: genTLTemplateImplementation :: TLTemplate -> [Decl ()]
+ FFICXX.Generate.Code.HsTemplate: genTLTemplateInstance :: TopLevelImportHeader -> TLTemplate -> [Decl ()]
+ FFICXX.Generate.Code.HsTemplate: genTLTemplateInterface :: TLTemplate -> [Decl ()]
+ FFICXX.Generate.Config: [sbcCxxOpts] :: SimpleBuilderConfig -> [String]
+ FFICXX.Generate.ContentMaker: buildInterfaceHsBoot :: DepCycles -> ClassModule -> Module ()
+ FFICXX.Generate.ContentMaker: buildTopLevelOrdinaryHs :: String -> ([ClassModule], [TemplateClassModule]) -> TopLevelImportHeader -> Module ()
+ FFICXX.Generate.ContentMaker: buildTopLevelTHHs :: String -> TopLevelImportHeader -> Module ()
+ FFICXX.Generate.ContentMaker: buildTopLevelTemplateHs :: String -> TopLevelImportHeader -> Module ()
+ FFICXX.Generate.Dependency: calculateDependency :: UClassSubmodule -> [UClassSubmodule]
+ FFICXX.Generate.Dependency: extractClassDepForTLOrdinary :: TLOrdinary -> Dep4Func
+ FFICXX.Generate.Dependency: extractClassDepForTLTemplate :: TLTemplate -> Dep4Func
+ FFICXX.Generate.Dependency: mkDepFFI :: Class -> [UClassSubmodule]
+ FFICXX.Generate.Dependency: mkTopLevelDep :: TopLevel -> [UClassSubmodule]
+ FFICXX.Generate.Dependency.Graph: constructDepGraph :: [UClass] -> [TopLevel] -> ([String], [(Int, [Int])])
+ FFICXX.Generate.Dependency.Graph: findDepCycles :: ([String], [(Int, [Int])]) -> DepCycles
+ FFICXX.Generate.Dependency.Graph: gatherHsBootSubmodules :: DepCycles -> [String]
+ FFICXX.Generate.Dependency.Graph: getCyclicDepSubmodules :: String -> DepCycles -> ([String], [String])
+ FFICXX.Generate.Dependency.Graph: locateInDepCycles :: (String, String) -> DepCycles -> Maybe (Int, Int)
+ FFICXX.Generate.Name: getClassModuleBase :: Class -> String
+ FFICXX.Generate.Name: getTClassModuleBase :: TemplateClass -> String
+ FFICXX.Generate.Name: subModuleName :: Either (TemplateClassSubmoduleType, TemplateClass) (ClassSubmoduleType, Class) -> String
+ FFICXX.Generate.Type.Class: TLOrdinary :: TLOrdinary -> TopLevel
+ FFICXX.Generate.Type.Class: TLTemplate :: TLTemplate -> TopLevel
+ FFICXX.Generate.Type.Class: TopLevelTemplateFunction :: [String] -> Types -> String -> String -> [Arg] -> TLTemplate
+ FFICXX.Generate.Type.Class: [topleveltfunc_args] :: TLTemplate -> [Arg]
+ FFICXX.Generate.Type.Class: [topleveltfunc_name] :: TLTemplate -> String
+ FFICXX.Generate.Type.Class: [topleveltfunc_oname] :: TLTemplate -> String
+ FFICXX.Generate.Type.Class: [topleveltfunc_params] :: TLTemplate -> [String]
+ FFICXX.Generate.Type.Class: [topleveltfunc_ret] :: TLTemplate -> Types
+ FFICXX.Generate.Type.Class: data TLOrdinary
+ FFICXX.Generate.Type.Class: data TLTemplate
+ FFICXX.Generate.Type.Class: filterTLOrdinary :: [TopLevel] -> [TLOrdinary]
+ FFICXX.Generate.Type.Class: filterTLTemplate :: [TopLevel] -> [TLTemplate]
+ FFICXX.Generate.Type.Class: instance GHC.Show.Show FFICXX.Generate.Type.Class.TLOrdinary
+ FFICXX.Generate.Type.Class: instance GHC.Show.Show FFICXX.Generate.Type.Class.TLTemplate
+ FFICXX.Generate.Type.Module: CSTCast :: ClassSubmoduleType
+ FFICXX.Generate.Type.Module: CSTFFI :: ClassSubmoduleType
+ FFICXX.Generate.Type.Module: CSTImplementation :: ClassSubmoduleType
+ FFICXX.Generate.Type.Module: CSTInterface :: ClassSubmoduleType
+ FFICXX.Generate.Type.Module: CSTRawType :: ClassSubmoduleType
+ FFICXX.Generate.Type.Module: TCSTTH :: TemplateClassSubmoduleType
+ FFICXX.Generate.Type.Module: TCSTTemplate :: TemplateClassSubmoduleType
+ FFICXX.Generate.Type.Module: [cmImportedSubmodulesForCast, cmImportedSubmodulesForImplementation] :: ClassModule -> [UClassSubmodule]
+ FFICXX.Generate.Type.Module: [cmImportedSubmodulesForFFI] :: ClassModule -> [UClassSubmodule]
+ FFICXX.Generate.Type.Module: [cmImportedSubmodulesForInterface] :: ClassModule -> [UClassSubmodule]
+ FFICXX.Generate.Type.Module: data ClassSubmoduleType
+ FFICXX.Generate.Type.Module: data TemplateClassSubmoduleType
+ FFICXX.Generate.Type.Module: instance GHC.Show.Show FFICXX.Generate.Type.Module.ClassSubmoduleType
+ FFICXX.Generate.Type.Module: instance GHC.Show.Show FFICXX.Generate.Type.Module.TemplateClassSubmoduleType
+ FFICXX.Generate.Type.Module: type DepCycles = [[(String, ([String], [String]))]]
+ FFICXX.Generate.Type.Module: type UClass = Either TemplateClass Class
+ FFICXX.Generate.Type.Module: type UClassSubmodule = Either (TemplateClassSubmoduleType, TemplateClass) (ClassSubmoduleType, Class)
+ FFICXX.Generate.Util: firstUpper :: String -> String
+ FFICXX.Generate.Util.DepGraph: drawDepGraph :: [UClass] -> [TopLevel] -> String
- FFICXX.Generate.Code.Cabal: buildCabalFile :: Cabal -> String -> PackageConfig -> [String] -> FilePath -> IO ()
+ FFICXX.Generate.Code.Cabal: buildCabalFile :: Cabal -> String -> PackageConfig -> [String] -> [String] -> FilePath -> IO ()
- FFICXX.Generate.Code.Cabal: buildJSONFile :: Cabal -> String -> PackageConfig -> [String] -> FilePath -> IO ()
+ FFICXX.Generate.Code.Cabal: buildJSONFile :: Cabal -> String -> PackageConfig -> [String] -> [String] -> FilePath -> IO ()
- FFICXX.Generate.Code.Cabal: genCabalInfo :: Cabal -> String -> PackageConfig -> [String] -> GeneratedCabalInfo
+ FFICXX.Generate.Code.Cabal: genCabalInfo :: Cabal -> String -> PackageConfig -> [String] -> [String] -> GeneratedCabalInfo
- FFICXX.Generate.Code.Cpp: genTopLevelCppDefinition :: TopLevel -> CStatement Identity
+ FFICXX.Generate.Code.Cpp: genTopLevelCppDefinition :: TLOrdinary -> CStatement Identity
- FFICXX.Generate.Code.Cpp: topLevelDecl :: TopLevel -> CFunDecl Identity
+ FFICXX.Generate.Code.Cpp: topLevelDecl :: TLOrdinary -> CFunDecl Identity
- FFICXX.Generate.Code.HsFFI: genTopLevelFFI :: TopLevelImportHeader -> TopLevel -> Decl ()
+ FFICXX.Generate.Code.HsFFI: genTopLevelFFI :: TopLevelImportHeader -> TLOrdinary -> Decl ()
- FFICXX.Generate.Code.HsFrontEnd: genHsFrontDecl :: Class -> Reader AnnotateMap (Decl ())
+ FFICXX.Generate.Code.HsFrontEnd: genHsFrontDecl :: Bool -> Class -> Reader AnnotateMap (Decl ())
- FFICXX.Generate.Code.HsFrontEnd: genImportInInterface :: ClassModule -> [ImportDecl ()]
+ FFICXX.Generate.Code.HsFrontEnd: genImportInInterface :: Bool -> DepCycles -> ClassModule -> [ImportDecl ()]
- FFICXX.Generate.Code.HsFrontEnd: genImportInTopLevel :: String -> ([ClassModule], [TemplateClassModule]) -> TopLevelImportHeader -> [ImportDecl ()]
+ FFICXX.Generate.Code.HsFrontEnd: genImportInTopLevel :: String -> ([ClassModule], [TemplateClassModule]) -> [ImportDecl ()]
- FFICXX.Generate.Code.HsFrontEnd: genTopLevelDef :: TopLevel -> [Decl ()]
+ FFICXX.Generate.Code.HsFrontEnd: genTopLevelDef :: TLOrdinary -> [Decl ()]
- FFICXX.Generate.Code.Primitive: tmplArgToCTypVar :: IsCPrimitive -> TemplateClass -> Arg -> (CType Identity, CName Identity)
+ FFICXX.Generate.Code.Primitive: tmplArgToCTypVar :: IsCPrimitive -> Arg -> (CType Identity, CName Identity)
- FFICXX.Generate.Config: SimpleBuilderConfig :: String -> ModuleUnitMap -> Cabal -> [Class] -> [TopLevel] -> [TemplateClassImportHeader] -> [String] -> [(String, [String])] -> [String] -> SimpleBuilderConfig
+ FFICXX.Generate.Config: SimpleBuilderConfig :: String -> ModuleUnitMap -> Cabal -> [Class] -> [TopLevel] -> [TemplateClassImportHeader] -> [String] -> [String] -> [(String, [String])] -> [String] -> SimpleBuilderConfig
- FFICXX.Generate.ContentMaker: buildInterfaceHs :: AnnotateMap -> ClassModule -> Module ()
+ FFICXX.Generate.ContentMaker: buildInterfaceHs :: AnnotateMap -> DepCycles -> ClassModule -> Module ()
- FFICXX.Generate.ContentMaker: buildTopLevelHs :: String -> ([ClassModule], [TemplateClassModule]) -> TopLevelImportHeader -> Module ()
+ FFICXX.Generate.ContentMaker: buildTopLevelHs :: String -> ([ClassModule], [TemplateClassModule]) -> Module ()
- FFICXX.Generate.Dependency: getparents :: Either b Class -> [Either a Class]
+ FFICXX.Generate.Dependency: getparents :: Either a Class -> [Either a Class]
- FFICXX.Generate.Type.Class: TopLevelFunction :: Types -> String -> [Arg] -> Maybe String -> TopLevel
+ FFICXX.Generate.Type.Class: TopLevelFunction :: Types -> String -> [Arg] -> Maybe String -> TLOrdinary
- FFICXX.Generate.Type.Class: TopLevelVariable :: Types -> String -> Maybe String -> TopLevel
+ FFICXX.Generate.Type.Class: TopLevelVariable :: Types -> String -> Maybe String -> TLOrdinary
- FFICXX.Generate.Type.Class: [toplevelfunc_alias] :: TopLevel -> Maybe String
+ FFICXX.Generate.Type.Class: [toplevelfunc_alias] :: TLOrdinary -> Maybe String
- FFICXX.Generate.Type.Class: [toplevelfunc_args] :: TopLevel -> [Arg]
+ FFICXX.Generate.Type.Class: [toplevelfunc_args] :: TLOrdinary -> [Arg]
- FFICXX.Generate.Type.Class: [toplevelfunc_name] :: TopLevel -> String
+ FFICXX.Generate.Type.Class: [toplevelfunc_name] :: TLOrdinary -> String
- FFICXX.Generate.Type.Class: [toplevelfunc_ret] :: TopLevel -> Types
+ FFICXX.Generate.Type.Class: [toplevelfunc_ret] :: TLOrdinary -> Types
- FFICXX.Generate.Type.Class: [toplevelvar_alias] :: TopLevel -> Maybe String
+ FFICXX.Generate.Type.Class: [toplevelvar_alias] :: TLOrdinary -> Maybe String
- FFICXX.Generate.Type.Class: [toplevelvar_name] :: TopLevel -> String
+ FFICXX.Generate.Type.Class: [toplevelvar_name] :: TLOrdinary -> String
- FFICXX.Generate.Type.Class: [toplevelvar_ret] :: TopLevel -> Types
+ FFICXX.Generate.Type.Class: [toplevelvar_ret] :: TLOrdinary -> Types
- 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: ClassModule :: String -> ClassImportHeader -> [UClassSubmodule] -> [UClassSubmodule] -> [UClassSubmodule] -> [String] -> ClassModule
Files
- ChangeLog.md +62/−0
- LICENSE +1/−1
- fficxx.cabal +12/−6
- src/FFICXX/Generate/Builder.hs +151/−118
- src/FFICXX/Generate/Code/Cabal.hs +189/−176
- src/FFICXX/Generate/Code/Cpp.hs +475/−400
- src/FFICXX/Generate/Code/HsCast.hs +29/−19
- src/FFICXX/Generate/Code/HsFFI.hs +71/−74
- src/FFICXX/Generate/Code/HsFrontEnd.hs +283/−201
- src/FFICXX/Generate/Code/HsProxy.hs +38/−28
- src/FFICXX/Generate/Code/HsTemplate.hs +588/−321
- src/FFICXX/Generate/Code/Primitive.hs +1064/−1000
- src/FFICXX/Generate/Config.hs +21/−21
- src/FFICXX/Generate/ContentMaker.hs +744/−526
- src/FFICXX/Generate/Dependency.hs +342/−285
- src/FFICXX/Generate/Dependency/Graph.hs +117/−0
- src/FFICXX/Generate/Name.hs +113/−72
- src/FFICXX/Generate/QQ/Verbatim.hs +18/−8
- src/FFICXX/Generate/Type/Annotate.hs +3/−6
- src/FFICXX/Generate/Type/Cabal.hs +58/−55
- src/FFICXX/Generate/Type/Class.hs +191/−168
- src/FFICXX/Generate/Type/Config.hs +22/−22
- src/FFICXX/Generate/Type/Module.hs +97/−64
- src/FFICXX/Generate/Type/PackageInterface.hs +5/−5
- src/FFICXX/Generate/Util.hs +46/−41
- src/FFICXX/Generate/Util/DepGraph.hs +36/−0
- src/FFICXX/Generate/Util/HaskellSrcExts.hs +173/−46
+ ChangeLog.md view
@@ -0,0 +1,62 @@+# Changelog for fficxx++## 0.7.0.0++- Show generated module dependency graph (#203)+- Fix incorrect hs-boot (#199)+- Simplify Nix script and support for multiple GHC versions in build (#196)+- aarch64-darwin support (#195)+- Implicit imports cleanup (#193)+- Upgrade to NixOS 21.11. (#192)+- CI action for ormolu formatting (#190)+- github action CI with nix build targets (#189)+- format all Haskell files by ormolu 0.0.3 (#180)+++## 0.6++- no more impure <nixpkgs> (#178)+- Duplicated template instances are safe (#176)+- Update for haskell-src-exts >= 1.22 (#174)+- change to_const/to_nonconst to from_X_to_Y (#172)+- std::map<k,v>::iterator is now supported. (#168)+- accessor for member variables of C++ template (#167)+- Support nested types inside template class (#163)+- Automatic dependency import in template class module (#162)+- cabal package generation and testing using hspec (#159)+- fficxx-test: stdcxx tests are rewritten as hspec tests (#158)+- multi-parameter template for function arguments and template member functions (#156)+- C++ multi-parameter template interfaced via fficxx! (#154)+- one class or template class per one haskell module! (#151)+- Inline C++ code generation for template member function (#149)+- Inline C++ code generation for std::function (#148)+- CDefinition. Unified newline treatment in Macro definition (#143)+- More ASTification with CMacroApp (#141)+- Declaration generation uses intermediate pseudo-AST representation (#140)+- Further towards intermediate reps for C++ code generation (#139)+- Further removing #include and using namespace (#138)+- Start C intermediate rep (#137)+- Convert (Types,String) to Arg (#134)+- no more stub.cc (#132)++## 0.5.1++## 0.5.0.1++## 0.5++## 0.4.1++## 0.4++## 0.3.1++## 0.3++## 0.2.1++## 0.2++## 0.1.0++## 0.1
LICENSE view
@@ -1,7 +1,7 @@ The following license covers this documentation, and the source code, except where otherwise indicated. -Copyright 2011-2019, Ian-Woo Kim. All rights reserved.+Copyright 2011-2022, 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:
fficxx.cabal view
@@ -1,14 +1,17 @@+Cabal-Version: 3.0 Name: fficxx-Version: 0.6+Version: 0.7.0.0 Synopsis: Automatic C++ binding generation Description: fficxx is an automatic haskell Foreign Function Interface (FFI) generator to C++.-License: BSD3+License: BSD-2-Clause License-file: LICENSE Author: Ian-Woo Kim Maintainer: Ian-Woo Kim <ianwookim@gmail.com> Build-Type: Simple+Tested-With: GHC == 9.0.2 || == 9.2.4 || == 9.4.2 Category: FFI Tools-Cabal-Version: >= 1.10+Extra-Source-Files:+ ChangeLog.md Source-repository head type: git@@ -16,21 +19,22 @@ Library hs-source-dirs: src- default-language: Haskell2010 + default-language: Haskell2010 Build-Depends: base == 4.* , aeson , aeson-pretty+ , array , bytestring , Cabal , containers , data-default , directory- , either+ , dotgen , errors , fficxx-runtime , filepath>1 , hashable- , haskell-src-exts >= 1.18+ , haskell-src-exts >= 1.22 , lens > 3 , mtl>2 , process@@ -54,9 +58,11 @@ FFICXX.Generate.Code.Primitive FFICXX.Generate.ContentMaker FFICXX.Generate.Dependency+ FFICXX.Generate.Dependency.Graph FFICXX.Generate.Name FFICXX.Generate.QQ.Verbatim FFICXX.Generate.Util+ FFICXX.Generate.Util.DepGraph FFICXX.Generate.Util.HaskellSrcExts FFICXX.Generate.Type.Annotate FFICXX.Generate.Type.Cabal
src/FFICXX/Generate/Builder.hs view
@@ -3,52 +3,56 @@ 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 )---+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 qualified Data.Text as T+import FFICXX.Generate.Code.Cabal (buildCabalFile, buildJSONFile)+import FFICXX.Generate.Config+ ( FFICXXConfig (..),+ SimpleBuilderConfig (..),+ )+import qualified FFICXX.Generate.ContentMaker as C+import FFICXX.Generate.Dependency+ ( findModuleUnitImports,+ mkPackageConfig,+ )+import FFICXX.Generate.Dependency.Graph+ ( constructDepGraph,+ findDepCycles,+ gatherHsBootSubmodules,+ )+import FFICXX.Generate.Type.Cabal+ ( AddCInc (..),+ AddCSrc (..),+ Cabal (..),+ CabalName (..),+ )+import FFICXX.Generate.Type.Class (hasProxy)+import FFICXX.Generate.Type.Module+ ( ClassImportHeader (..),+ ClassModule (..),+ PackageConfig (..),+ TemplateClassImportHeader (..),+ TemplateClassModule (..),+ TopLevelImportHeader (..),+ )+import FFICXX.Generate.Util (moduleDirFile)+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..))+import Language.Haskell.Exts.Pretty (prettyPrint)+import System.Directory+ ( copyFile,+ createDirectoryIfMissing,+ doesFileExist,+ )+import System.FilePath (splitExtension, (<.>), (</>))+import System.IO (IOMode (..), hPutStrLn, withFile)+import System.Process (readProcess) macrofy :: String -> String-macrofy = map ((\x->if x=='-' then '_' else x) . toUpper)-+macrofy = map ((\x -> if x == '-' then '_' else x) . toUpper) simpleBuilder :: FFICXXConfig -> SimpleBuilderConfig -> IO () simpleBuilder cfg sbc = do@@ -63,24 +67,35 @@ toplevelfunctions templates extralibs+ cxxopts extramods- staticFiles- = sbc+ staticFiles =+ sbc pkgname = cabal_pkgname cabal putStrLn ("Generating " <> unCabalName pkgname) let workingDir = fficxxconfig_workingDir cfg installDir = fficxxconfig_installBaseDir cfg- staticDir = fficxxconfig_staticFileDir cfg-+ staticDir = fficxxconfig_staticFileDir cfg pkgconfig@(PkgConfig mods cihs tih tcms _tcihs _ _) = mkPackageConfig (pkgname, findModuleUnitImports mumap)- (classes, toplevelfunctions,templates,extramods)+ (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"+ allClasses = fmap (Left . tcihTClass) templates ++ fmap Right classes+ depCycles =+ findDepCycles $+ constructDepGraph allClasses toplevelfunctions+ -- for now, put this function here+ -- This function is a little ad hoc, only for Interface.hs.+ -- But as of now, we support hs-boot for ordinary class only.+ mkHsBootCandidateList :: [ClassModule] -> [ClassModule]+ mkHsBootCandidateList ms =+ let hsbootSubmods = gatherHsBootSubmodules depCycles+ in filter (\c -> cmModule c <.> "Interface" `elem` hsbootSubmods) ms+ hsbootlst = mkHsBootCandidateList mods -- createDirectoryIfMissing True workingDir createDirectoryIfMissing True installDir@@ -88,114 +103,137 @@ createDirectoryIfMissing True (installDir </> "csrc") -- putStrLn "Copying static files"- mapM_ (\x->copyFileWithMD5Check (staticDir </> x) (installDir </> x)) staticFiles+ mapM_ (\x -> copyFileWithMD5Check (staticDir </> x) (installDir </> x)) staticFiles -- putStrLn "Generating Cabal file"- buildCabalFile cabal topLevelMod pkgconfig extralibs (workingDir</>cabalFileName)+ buildCabalFile cabal topLevelMod pkgconfig extralibs cxxopts (workingDir </> cabalFileName) -- putStrLn "Generating JSON file"- buildJSONFile cabal topLevelMod pkgconfig extralibs (workingDir</>jsonFileName)+ buildJSONFile cabal topLevelMod pkgconfig extralibs cxxopts (workingDir </> jsonFileName) -- putStrLn "Generating Header file"- let- gen :: FilePath -> String -> IO ()+ 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 (unCabalName pkgname <> "Type.h") (C.buildTypeDeclHeader (map cihClass cihs))+ for_ cihs $ \hdr ->+ gen+ (unHdrName (cihSelfHeader hdr))+ (C.buildDeclHeader (unCabalName pkgname) hdr) gen (tihHeaderFileName tih <.> "h")- (buildTopLevelHeader (unCabalName pkgname) tih)-+ (C.buildTopLevelHeader (unCabalName pkgname) tih) putStrLn "Generating Cpp file"- for_ cihs (\hdr -> gen (cihSelfCpp hdr) (buildDefMain hdr))- gen (tihHeaderFileName tih <.> "cpp") (buildTopLevelCppDef tih)+ for_ cihs (\hdr -> gen (cihSelfCpp hdr) (C.buildDefMain hdr))+ gen (tihHeaderFileName tih <.> "cpp") (C.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))+ for_ mods $ \m ->+ gen+ (cmModule m <.> "RawType" <.> "hs")+ (prettyPrint (C.buildRawTypeHs m)) -- putStrLn "Generating FFI.hsc"- for_ mods $ \m -> gen- (cmModule m <.> "FFI" <.> "hsc")- (prettyPrint (buildFFIHsc m))+ for_ mods $ \m ->+ gen+ (cmModule m <.> "FFI" <.> "hsc")+ (prettyPrint (C.buildFFIHsc m)) -- putStrLn "Generating Interface.hs"- for_ mods $ \m -> gen- (cmModule m <.> "Interface" <.> "hs")- (prettyPrint (buildInterfaceHs mempty m))+ for_ mods $ \m ->+ gen+ (cmModule m <.> "Interface" <.> "hs")+ (prettyPrint (C.buildInterfaceHs mempty depCycles m)) -- putStrLn "Generating Cast.hs"- for_ mods $ \m -> gen- (cmModule m <.> "Cast" <.> "hs")- (prettyPrint (buildCastHs m))+ for_ mods $ \m ->+ gen+ (cmModule m <.> "Cast" <.> "hs")+ (prettyPrint (C.buildCastHs m)) -- putStrLn "Generating Implementation.hs"- for_ mods $ \m -> gen- (cmModule m <.> "Implementation" <.> "hs")- (prettyPrint (buildImplementationHs mempty m))- --+ for_ mods $ \m ->+ gen+ (cmModule m <.> "Implementation" <.> "hs")+ (prettyPrint (C.buildImplementationHs mempty m))+ -- putStrLn "Generating Proxy.hs" for_ mods $ \m -> when (hasProxy . cihClass . cmCIH $ m) $- gen (cmModule m <.> "Proxy" <.> "hs") (prettyPrint (buildProxyHs m))+ gen (cmModule m <.> "Proxy" <.> "hs") (prettyPrint (C.buildProxyHs m)) -- putStrLn "Generating Template.hs"- for_ tcms $ \m -> gen- (tcmModule m <.> "Template" <.> "hs")- (prettyPrint (buildTemplateHs m))+ for_ tcms $ \m ->+ gen+ (tcmModule m <.> "Template" <.> "hs")+ (prettyPrint (C.buildTemplateHs m)) -- putStrLn "Generating TH.hs"- for_ tcms $ \m -> gen- (tcmModule m <.> "TH" <.> "hs")- (prettyPrint (buildTHHs m))-+ for_ tcms $ \m ->+ gen+ (tcmModule m <.> "TH" <.> "hs")+ (prettyPrint (C.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))+ -- This is a hack since haskell-src-exts always codegen () => instead of empty+ -- string for an empty context, which have different meanings in hs-boot file.+ -- Therefore, we get rid of them.+ let hsBootHackClearEmptyContexts = T.unpack . T.replace "() =>" "" . T.pack+ for_ hsbootlst $ \m -> do+ gen+ (cmModule m <.> "Interface" <.> "hs-boot")+ (hsBootHackClearEmptyContexts $ prettyPrint (C.buildInterfaceHsBoot depCycles m)) -- putStrLn "Generating Module summary file"- for_ mods $ \m -> gen- (cmModule m <.> "hs")- (prettyPrint (buildModuleHs m))+ for_ mods $ \m ->+ gen+ (cmModule m <.> "hs")+ (prettyPrint (C.buildModuleHs m)) --+ putStrLn "Generating Top-level Ordinary Module"+ gen (topLevelMod <.> "Ordinary" <.> "hs") (prettyPrint (C.buildTopLevelOrdinaryHs (topLevelMod <> ".Ordinary") (mods, tcms) tih))+ --+ putStrLn "Generating Top-level Template Module"+ gen+ (topLevelMod <.> "Template" <.> "hs")+ (prettyPrint (C.buildTopLevelTemplateHs (topLevelMod <> ".Template") tih))+ --+ putStrLn "Generating Top-level TH Module"+ gen+ (topLevelMod <.> "TH" <.> "hs")+ (prettyPrint (C.buildTopLevelTHHs (topLevelMod <> ".TH") tih))+ -- putStrLn "Generating Top-level Module"- gen (topLevelMod <.> "hs") (prettyPrint (buildTopLevelHs topLevelMod (mods,tcms) tih))+ gen+ (topLevelMod <.> "hs")+ (prettyPrint (C.buildTopLevelHs topLevelMod (mods, tcms))) -- putStrLn "Copying generated files to target directory" touch (workingDir </> "LICENSE")- copyFileWithMD5Check (workingDir </> cabalFileName) (installDir </> cabalFileName)- copyFileWithMD5Check (workingDir </> jsonFileName) (installDir </> jsonFileName)+ 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"-+ copyCppFiles workingDir (C.csrcDir installDir) (unCabalName pkgname) pkgconfig+ for_ mods (copyModule workingDir (C.srcDir installDir))+ for_ tcms (copyTemplateModule workingDir (C.srcDir installDir))+ putStrLn "Copying Ordinary"+ moduleFileCopy workingDir (C.srcDir installDir) $ topLevelMod <.> "Ordinary" <.> "hs"+ moduleFileCopy workingDir (C.srcDir installDir) $ topLevelMod <.> "Template" <.> "hs"+ moduleFileCopy workingDir (C.srcDir installDir) $ topLevelMod <.> "TH" <.> "hs"+ moduleFileCopy workingDir (C.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@@ -206,7 +244,6 @@ 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"@@ -217,32 +254,28 @@ >>= flip when (copyFileWithMD5Check (wdir </> tlhfile) (ddir </> tlhfile)) doesFileExist (wdir </> tlcppfile) >>= flip when (copyFileWithMD5Check (wdir </> tlcppfile) (ddir </> tlcppfile))- for_ cihs $ \header-> do+ 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+ let (fnamebody, fnameext) = splitExtension fname+ (mdir, mfile) = moduleDirFile fnamebody origfpath = wdir </> fname- (mfile',_mext') = splitExtension mfile+ (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@@ -254,8 +287,8 @@ moduleFileCopy wdir ddir $ modbase <> ".Implementation.hs" moduleFileCopy wdir ddir $ modbase <> ".Interface.hs-boot" when (hasProxy . cihClass . cmCIH $ m) $- moduleFileCopy wdir ddir $ modbase <> ".Proxy.hs"-+ moduleFileCopy wdir ddir $+ modbase <> ".Proxy.hs" copyTemplateModule :: FilePath -> FilePath -> TemplateClassModule -> IO () copyTemplateModule wdir ddir m = do
src/FFICXX/Generate/Code/Cabal.hs view
@@ -1,46 +1,49 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE RecordWildCards #-} module FFICXX.Generate.Code.Cabal where -import Data.Aeson.Encode.Pretty (encodePretty)+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 Data.List (intercalate, nub)+import Data.Text (Text)+import qualified Data.Text as T (intercalate, pack, replicate, unlines) 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 qualified Data.Text.Lazy as TL (toStrict)+import Data.Text.Template (substitute)+import FFICXX.Generate.Type.Cabal+ ( AddCInc (..),+ AddCSrc (..),+ BuildType (..),+ Cabal (..),+ CabalName (..),+ GeneratedCabalInfo (..),+ )+import FFICXX.Generate.Type.Class (hasProxy) import FFICXX.Generate.Type.Module--- import FFICXX.Generate.Type.PackageInterface-import FFICXX.Generate.Util-+ ( ClassImportHeader (..),+ ClassModule (..),+ PackageConfig (..),+ TemplateClassImportHeader,+ TemplateClassModule (..),+ TopLevelImportHeader (..),+ )+import FFICXX.Generate.Util (contextT)+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..))+import System.FilePath ((<.>), (</>)) 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 =+genCsrcFiles ::+ (TopLevelImportHeader, [ClassModule]) ->+ [AddCInc] ->+ [AddCSrc] ->+ [String]+genCsrcFiles (tih, cmods) acincs acsrcs = let selfheaders' = do x <- cmods let y = cmCIH x@@ -53,66 +56,71 @@ 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+ 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 =+genIncludeFiles ::+ -- | package name+ String ->+ ([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+ in (pkgname <> "Type.h") : includeFileStrs -- for library-genCppFiles :: (TopLevelImportHeader,[ClassModule])- -> [AddCSrc]- -> [String]-genCppFiles (tih,cmods) acsrcs =+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+ 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+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, summarymod <> ".Ordinary", summarymod <> ".Template", summarymod <> ".TH"]+ <> cmodstrs+ <> rawType+ <> ffi+ <> interface+ <> cast+ <> implementation+ <> proxy+ <> template+ <> th -- | generate other modules in cabal file genOtherModules :: [ClassModule] -> [String]@@ -120,19 +128,19 @@ -- | generate additional package dependencies. genPkgDeps :: [CabalName] -> [String]-genPkgDeps cs = [ "base > 4 && < 5"- , "fficxx >= 0.5"- , "fficxx-runtime >= 0.5"- , "template-haskell"- ]- ++ map unCabalName cs--+genPkgDeps cs =+ [ "base > 4 && < 5",+ "fficxx >= 0.7",+ "fficxx-runtime >= 0.7",+ "template-haskell"+ ]+ ++ map unCabalName cs -- | cabalTemplate :: Text cabalTemplate =- "Name: $pkgname\n\+ "Cabal-version: 3.0\n\+ \Name: $pkgname\n\ \Version: $version\n\ \Synopsis: $synopsis\n\ \Description: $description\n\@@ -142,9 +150,8 @@ \Author: $author\n\ \Maintainer: $maintainer\n\ \Category: $category\n\- \Tested-with: GHC >= 7.6\n\+ \Tested-with: GHC == 9.0.2 || == 9.2.4 || == 9.4.2 \n\ \$buildtype\n\- \cabal-version: >= 2\n\ \Extra-source-files:\n\ \$extraFiles\n\ \$csrcFiles\n\@@ -168,19 +175,20 @@ \ pkgconfig-depends: $pkgconfigDepends\n\ \ Install-includes:\n\ \$includeFiles\n\- \ C-sources:\n\+ \ Cxx-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 =+genCabalInfo ::+ Cabal ->+ String ->+ PackageConfig ->+ -- | extra libs+ [String] ->+ -- | cxx options+ [String] ->+ GeneratedCabalInfo+genCabalInfo cabal summarymodule pkgconfig extralibs cxxopts = let tih = pcfg_topLevelImportHeader pkgconfig classmodules = pcfg_classModules pkgconfig cih = pcfg_classImportHeaders pkgconfig@@ -189,95 +197,100 @@ 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- }-+ 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 = map T.pack cxxopts,+ 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)- ]-+ 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+buildCabalFile ::+ Cabal ->+ String ->+ PackageConfig ->+ -- | Extra libs+ [String] ->+ -- | cxx options+ [String] ->+ -- | Cabal file path+ FilePath ->+ IO ()+buildCabalFile cabal summarymodule pkgconfig extralibs cxxopts cabalfile = do+ let cinfo = genCabalInfo cabal summarymodule pkgconfig extralibs cxxopts 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+buildJSONFile ::+ Cabal ->+ String ->+ PackageConfig ->+ -- | Extra libs+ [String] ->+ -- | cxx options+ [String] ->+ -- | JSON file path+ FilePath ->+ IO ()+buildJSONFile cabal summarymodule pkgconfig extralibs cxxopts jsonfile = do+ let cinfo = genCabalInfo cabal summarymodule pkgconfig extralibs cxxopts BL.writeFile jsonfile (encodePretty cinfo)
src/FFICXX/Generate/Code/Cpp.hs view
@@ -1,67 +1,68 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}+{-# 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 Data.Char (toUpper)+import Data.Functor.Identity (Identity)+import Data.List (intercalate, intersperse) 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 )+ ( CFunSig (..),+ accessorCFunSig,+ argToCallCExp,+ argsToCTypVar,+ argsToCTypVarNoSelf,+ c2Cxx,+ cxx2C,+ genericFuncArgs,+ genericFuncRet,+ returnCType,+ tmplAccessorToTFun,+ tmplAllArgsToCTypVar,+ tmplAppTypeFromForm,+ tmplArgToCTypVar,+ tmplArgToCallCExp,+ tmplMemFuncArgToCTypVar,+ tmplMemFuncReturnCType,+ tmplReturnCType,+ )+import FFICXX.Generate.Name+ ( aliasedFuncName,+ cppFuncName,+ ffiClassName,+ ffiTmplFuncName,+ hsTemplateMemberFunctionName,+ )+import FFICXX.Generate.Type.Class+ ( Accessor (Getter, Setter),+ Arg (..),+ CPPTypes (..),+ CTypes (..),+ Class (..),+ Form (FormNested, FormSimple),+ Function (..),+ IsConst (Const, NoConst),+ Selfness (NoSelf, Self),+ TLOrdinary (..),+ TLTemplate (..),+ TemplateAppInfo (..),+ TemplateClass (..),+ TemplateFunction (..),+ TemplateMemberFunction (..),+ Types (..),+ Variable (..),+ argsFromOpExp,+ isDeleteFunc,+ isNewFunc,+ isStaticFunc,+ isVirtualFunc,+ opSymbol,+ virtualFuncs,+ )+import FFICXX.Generate.Type.Module (ClassImportHeader (..))+import FFICXX.Generate.Util (firstUpper, toUppers)+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import FFICXX.Runtime.TH (IsCPrimitive (CPrim, NonCPrim)) -- --@@ -76,73 +77,71 @@ 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))- ]+ [ 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"-+ classname_t = classname <> "_t"+ classname_p = classname <> "_p" genCppHeaderMacroType :: Class -> [R.CStatement Identity] genCppHeaderMacroType c =- [ R.Comment "Opaque type definition for $classname" ]+ [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+ 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+ 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+ 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-+ 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)+ 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-+ 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) =+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)]+ 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)]+ 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)]+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)] ---- ---- Definition@@ -152,78 +151,81 @@ genCppDefMacroVirtual :: Class -> R.CMacro Identity genCppDefMacroVirtual aclass =- let funcDefStr = intercalate "\n"- . map (R.renderCStmt . funcToDef aclass)- . virtualFuncs- . class_funcs- $ 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 ]+ 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+ 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 ]+ 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)+ 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+ 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+ 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- ]+ 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.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) =+genCppDefInstVirtual (p, c) = let macroname = map toUpper (ffiClassName p) <> "_DEF_VIRT"- in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)]+ 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)]+ 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)]+ in R.CMacroApp (R.sname macroname) [R.sname (ffiClassName c)] ----------------- @@ -237,198 +239,236 @@ -- TOP LEVEL FUNCTIONS -- ------------------------- -topLevelDecl :: TopLevel -> R.CFunDecl Identity+topLevelDecl :: TLOrdinary -> R.CFunDecl Identity topLevelDecl TopLevelFunction {..} = R.CFunDecl ret func args where- ret = returnCType toplevelfunc_ret+ 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+ ret = returnCType toplevelvar_ret func = R.sname ("TopLevel_" <> maybe toplevelvar_name id toplevelvar_alias) -genTopLevelCppDefinition :: TopLevel -> R.CStatement Identity+genTopLevelCppDefinition :: TLOrdinary -> 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+ 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+ in R.CDefinition Nothing decl body genTmplFunCpp ::- IsCPrimitive- -> TemplateClass- -> TemplateFunction- -> R.CMacro Identity+ 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 )))+ 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))) +genTLTmplFunCpp ::+ IsCPrimitive ->+ TLTemplate ->+ R.CMacro Identity+genTLTmplFunCpp b t@TopLevelTemplateFunction {..} =+ R.Define+ (R.sname macroname)+ (map R.sname ("callmod" : topleveltfunc_params))+ [ R.CExtern [R.CDeclaration decl],+ topLevelTemplateFunToDef b t,+ autoinst+ ]+ where+ nsuffix = intersperse (R.NamePart "_") $ map R.NamePart topleveltfunc_params+ suffix = case b of CPrim -> "_s"; NonCPrim -> ""+ macroname = firstUpper topleveltfunc_name <> "_instance" <> suffix+ decl = topLevelTemplateFunToDecl b t+ autoinst =+ R.CInit+ ( R.CVarDecl+ R.CTAuto+ (R.CName (R.NamePart "a_" : R.NamePart "callmod" : R.NamePart ("_TL_" <> topleveltfunc_name <> "_") : nsuffix))+ )+ (R.CVar (R.CName (R.NamePart ("TL_" <> topleveltfunc_name <> "_") : nsuffix)))+ genTmplVarCpp ::- IsCPrimitive- -> TemplateClass- -> Variable- -> [ R.CMacro Identity ]-genTmplVarCpp b t@TmplCls {..} var@(Variable (Arg {..})) =- [ gen var Getter, gen var Setter ]+ 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 -> "" }+ 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 )))- ]+ 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+ IsCPrimitive ->+ TemplateClass ->+ -- | (member functions, member accessors)+ ([TemplateFunction], [Variable]) ->+ 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]+ IsCPrimitive ->+ Types ->+ R.CExp Identity ->+ [R.CStatement Identity] returnCpp b ret caller = case ret of Void ->- [ R.CExpSA caller ]+ [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 ]+ [ 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 ]+ [R.CReturn $ R.CAddr caller] CT _ _ ->- [R.CReturn caller ]+ [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 ]+ [ 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'+ 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 ]+ [ 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'+ 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.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 ]- ]+ [R.CTSimple (R.sname (str <> "_t")), R.CTSimple (R.sname str)]+ [R.CNew (R.sname str) [caller]] ]- where str = ffiClassName c'+ 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.CNew (R.sname cpptype) [caller]),+ R.CReturn $ R.CTApp (R.sname "static_cast")- [ R.CTStar R.CTVoid ]- [ R.CVar (R.sname "r") ]+ [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.CNew (R.sname cpptype) [caller]),+ R.CReturn $ R.CTApp (R.sname "static_cast")- [ R.CTStar R.CTVoid ]- [ R.CVar (R.sname "r") ]+ [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.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") ]+ [ R.CTApp+ (R.sname "static_cast")+ [R.CTStar R.CTVoid]+ [R.CVar (R.sname "r")] ] ] TemplateType _ ->@@ -436,22 +476,22 @@ TemplateParam typ -> [ R.CReturn $ case b of- CPrim -> caller+ 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 ]+ [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+ 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 ]+ [R.CTSimple (R.CName [R.NamePart typ, R.NamePart "_t"]), R.CTSimple (R.sname typ)]+ [caller] ] -- Function Declaration and Definition@@ -459,98 +499,112 @@ funcToDecl :: Class -> Function -> R.CFunDecl Identity funcToDecl c func | isNewFunc func || isStaticFunc func =- let ret = returnCType (genericFuncRet 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+ args = argsToCTypVarNoSelf (genericFuncArgs func)+ in R.CFunDecl ret fname args | otherwise =- let ret = returnCType (genericFuncRet func)+ 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+ 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+ 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+ 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+ 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.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+ in R.CDefinition Nothing (funcToDecl c func) body -- template function declaration and definition - tmplFunToDecl ::- IsCPrimitive- -> TemplateClass- -> TemplateFunction- -> R.CFunDecl Identity+ 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+ 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 --- |+-- | top-level (bare) template function declaration+topLevelTemplateFunToDecl ::+ IsCPrimitive ->+ TLTemplate ->+ R.CFunDecl Identity+topLevelTemplateFunToDecl b (TopLevelTemplateFunction {..}) =+ let nsuffix = intersperse (R.NamePart "_") $ map R.NamePart topleveltfunc_params+ ret = tmplReturnCType b topleveltfunc_ret+ func = R.CName (R.NamePart ("TL_" <> topleveltfunc_name <> "_") : nsuffix)+ args = map (tmplArgToCTypVar b) topleveltfunc_args+ in R.CFunDecl ret func args++-- | function definition in a template class tmplFunToDef ::- IsCPrimitive- -> TemplateClass- -> TemplateFunction- -> R.CStatement Identity+ IsCPrimitive ->+ TemplateClass ->+ TemplateFunction ->+ R.CStatement Identity tmplFunToDef b t@TmplCls {..} f =- R.CDefinition (Just R.Inline) (tmplFunToDecl b t f) body+ R.CDefinition (Just R.Inline) (tmplFunToDecl b t f) body where typparams = map (R.CTSimple . R.sname) tclass_params body =@@ -569,72 +623,90 @@ (R.sname inner) typparams (map (tmplArgToCallCExp b) tfun_new_args)- in [ R.CReturn $ R.CTApp (R.sname "static_cast") [R.CTStar R.CTVoid] [caller] ]+ 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") ]+ [R.CTStar $ tmplAppTypeFromForm tclass_cxxform typparams]+ [R.CVar (R.sname "p")] ]- TFun {..} ->+ 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.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)+ ( R.CApp+ (R.CVar (R.sname tfun_oname))+ (map (tmplArgToCallCExp b) tfun_args) )- TFunOp {..} ->+ 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.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))+ ( R.CApp+ (R.CVar (R.sname ("operator" <> opSymbol tfun_opexp)))+ (map (tmplArgToCallCExp b) (argsFromOpExp tfun_opexp)) ) +-- | function definition in a template class+topLevelTemplateFunToDef ::+ IsCPrimitive ->+ TLTemplate ->+ R.CStatement Identity+topLevelTemplateFunToDef b t@TopLevelTemplateFunction {..} =+ R.CDefinition (Just R.Inline) (topLevelTemplateFunToDecl b t) body+ where+ typparams = map (R.CTSimple . R.sname) topleveltfunc_params+ body =+ returnCpp b (topleveltfunc_ret) $+ R.CTApp+ (R.sname topleveltfunc_oname)+ typparams+ (map (tmplArgToCallCExp b) topleveltfunc_args) +-- | tmplVarToDef ::- IsCPrimitive- -> TemplateClass- -> Variable- -> Accessor- -> R.CStatement Identity+ 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+ 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")))- ]+ 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@@ -644,39 +716,41 @@ 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"- )- ]+ 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+ in R.CFunDecl ret fname args accessorsToDecls :: [Variable] -> [R.CFunDecl Identity] accessorsToDecls vs =- concatMap (\v -> [accessorToDecl v Getter,accessorToDecl v Setter]) 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.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 ]-+ 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 @@ -687,25 +761,26 @@ 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+ 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+ 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))- )+ 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
@@ -1,37 +1,47 @@ 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)+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,+ tyPtr,+ tyapp,+ tycon,+ unqual,+ )+import Language.Haskell.Exts.Build (app)+import Language.Haskell.Exts.Syntax (Decl (..), InstDecl (..))+ ----- 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)+ [ 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 =+ | (not . isAbstractClass) c = let iname = typeclassName c- (_,rname) = hsClassName 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)+ 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)+ | (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
@@ -3,48 +3,47 @@ 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 Data.Maybe (fromMaybe, mapMaybe) 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 )-+ ( CFunSig (..),+ accessorCFunSig,+ genericFuncArgs,+ genericFuncRet,+ hsFFIFuncTyp,+ )+import FFICXX.Generate.Dependency+ ( class_allparents,+ )+import FFICXX.Generate.Name+ ( aliasedFuncName,+ ffiClassName,+ hscAccessorName,+ hscFuncName,+ subModuleName,+ )+import FFICXX.Generate.Type.Class+ ( Accessor (Getter, Setter),+ Arg (..),+ Class (..),+ Function (..),+ Selfness (NoSelf, Self),+ TLOrdinary (..),+ 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)+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..))+import Language.Haskell.Exts.Syntax (Decl (..), ImportDecl (..))+import System.FilePath ((<.>)) genHsFFI :: ClassImportHeader -> [Decl ()] genHsFFI header =@@ -56,56 +55,54 @@ -- 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+ 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+ 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 :: 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-+ 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")-+genImportInFFI = fmap (mkImport . subModuleName) . cmImportedSubmodulesForFFI ---------------------------- -- for top level function -- ---------------------------- -genTopLevelFFI :: TopLevelImportHeader -> TopLevel -> Decl ()+genTopLevelFFI :: TopLevelImportHeader -> TLOrdinary -> 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)+ 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
@@ -1,94 +1,168 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}+{-# 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 Control.Monad.Reader (Reader)+import Data.Either (lefts, rights)+import qualified Data.List as L+import FFICXX.Generate.Code.Primitive+ ( CFunSig (..),+ HsFunSig (..),+ accessorSignature,+ classConstraints,+ convertCpp2HS,+ extractArgRetTypes,+ functionSignature,+ hsFuncXformer,+ )+import FFICXX.Generate.Dependency+ ( argumentDependency,+ extractClassDepForTLOrdinary,+ extractClassDepForTLTemplate,+ returnDependency,+ )+import FFICXX.Generate.Dependency.Graph+ ( getCyclicDepSubmodules,+ locateInDepCycles,+ )+import FFICXX.Generate.Name+ ( accessorName,+ aliasedFuncName,+ getClassModuleBase,+ getTClassModuleBase,+ hsClassName,+ hsFrontNameForTopLevel,+ hsFuncName,+ hscAccessorName,+ hscFuncName,+ subModuleName,+ typeclassName,+ )+import FFICXX.Generate.Type.Annotate (AnnotateMap) import FFICXX.Generate.Type.Class-import FFICXX.Generate.Type.Annotate+ ( Accessor (..),+ Class (..),+ TLOrdinary (..),+ TLTemplate,+ TopLevel (TLOrdinary),+ Types (..),+ constructorFuncs,+ isAbstractClass,+ isNewFunc,+ isVirtualFunc,+ nonVirtualNotNewFuncs,+ staticFuncs,+ virtualFuncs,+ ) import FFICXX.Generate.Type.Module-import FFICXX.Generate.Util+ ( ClassModule (..),+ DepCycles,+ TemplateClassModule (..),+ )+import FFICXX.Generate.Util (toLowers) import FFICXX.Generate.Util.HaskellSrcExts-+ ( classA,+ clsDecl,+ con,+ conDecl,+ cxEmpty,+ cxTuple,+ eabs,+ ethingall,+ evar,+ ihcon,+ insDecl,+ insType,+ irule,+ mkBind1,+ mkClass,+ mkData,+ mkDeriving,+ mkFun,+ mkFunSig,+ mkImport,+ mkImportSrc,+ mkInstance,+ mkNewtype,+ mkPVar,+ mkPVarSig,+ mkTBind,+ mkTVar,+ mkVar,+ nonamespace,+ pbind,+ qualConDecl,+ tyForall,+ tyPtr,+ tyapp,+ tycon,+ tyfun,+ unkindedVar,+ unqual,+ )+import Language.Haskell.Exts.Build (app, letE, name, pApp)+import Language.Haskell.Exts.Syntax+ ( Context (CxTuple),+ Decl (..),+ ExportSpec (..),+ ImportDecl (..),+ )+import System.FilePath ((<.>)) -genHsFrontDecl :: Class -> Reader AnnotateMap (Decl ())-genHsFrontDecl c = do+genHsFrontDecl :: Bool -> Class -> Reader AnnotateMap (Decl ())+genHsFrontDecl isHsBoot 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+ -- for hs-boot, we only have instance head.+ cdecl' = mkClass (CxTuple () []) (typeclassName c) [mkTBind "a"] [] sigdecl f = mkFunSig (hsFuncName c f) (functionSignature c f) body = map (clsDecl . sigdecl) . virtualFuncs . class_funcs $ c- return cdecl+ if isHsBoot+ then return cdecl'+ else return cdecl ------------------- genHsFrontInst :: Class -> Class -> [Decl ()] genHsFrontInst parent child- | (not.isAbstractClass) 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))+ where+ rhs = app (mkVar (hsFuncXformer f)) (mkVar (hscFuncName child f)) body = map (insDecl . defn) . virtualFuncs . class_funcs $ parent- in [idecl]+ in [idecl] | otherwise = [] --- --------------------- -genHsFrontInstNew :: Class -- ^ only concrete class- -> Reader AnnotateMap [Decl ()]+genHsFrontInstNew ::+ -- | only concrete class+ 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.+ 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+ 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)+ in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing+ where+ nonvirtualFuncs = nonVirtualNotNewFuncs (class_funcs c) ----- @@ -96,7 +170,7 @@ 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+ in mkFun (aliasedFuncName c f) (functionSignature c f) [] rhs Nothing ----- @@ -104,106 +178,113 @@ 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---+ 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)+ [ 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"))-+ 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")-+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")-+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 :: TLOrdinary -> [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+ let fname = hsFrontNameForTopLevel (TLOrdinary 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-+ let fname = hsFrontNameForTopLevel (TLOrdinary 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 --@@ -211,31 +292,39 @@ 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)) ]+ 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)+ 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)-+ where+ fs = class_funcs c+ fns = map (aliasedFuncName c) (staticFuncs fs) ------------ -- Import --@@ -244,79 +333,72 @@ genExtraImport :: ClassModule -> [ImportDecl ()] genExtraImport cm = map mkImport (cmExtraImport cm) - genImportInModule :: Class -> [ImportDecl ()]-genImportInModule x = map (\y -> mkImport (getClassModuleBase x<.>y)) ["RawType","Interface","Implementation"]+genImportInModule x = map (\y -> mkImport (getClassModuleBase x <.> y)) ["RawType", "Interface", "Implementation"] +mkImportWithDepCycles :: DepCycles -> String -> String -> ImportDecl ()+mkImportWithDepCycles depCycles self imported =+ let mloc = locateInDepCycles (self, imported) depCycles+ in case mloc of+ Just (idxSelf, idxImported)+ | idxImported > idxSelf ->+ mkImportSrc imported+ _ -> mkImport imported -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")- )+genImportInInterface :: Bool -> DepCycles -> ClassModule -> [ImportDecl ()]+genImportInInterface isHsBoot depCycles m =+ let modSelf = cmModule m <.> "Interface"+ imported = cmImportedSubmodulesForInterface m+ (rdepsU, rdepsD) = getCyclicDepSubmodules modSelf depCycles+ in if isHsBoot+ then -- for hs-boot file, we ignore all module imports in the cycle.+ -- TODO: This is likely to be broken in more general cases.+ -- Keep improving this as hs-boot allows. + let imported' = fmap subModuleName imported L.\\ (rdepsU <> rdepsD)+ in fmap mkImport imported'+ else fmap (mkImportWithDepCycles depCycles modSelf . subModuleName) imported+ -- | genImportInCast :: ClassModule -> [ImportDecl ()]-genImportInCast m = [ mkImport (cmModule m <.> "RawType")- , mkImport (cmModule m <.> "Interface") ]+genImportInCast m =+ fmap (mkImport . subModuleName) $ cmImportedSubmodulesForCast m --- | 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+ fmap (mkImport . subModuleName) $ cmImportedSubmodulesForImplementation m +-- | generate import list for a given top-level ordinary function+-- currently this may generate duplicate import list.+-- TODO: eliminate duplicated imports.+-- TODO2: should be refactored out.+genImportForTLOrdinary :: TLOrdinary -> [ImportDecl ()]+genImportForTLOrdinary f =+ let dep4func = extractClassDepForTLOrdinary f+ ecs = returnDependency dep4func ++ argumentDependency dep4func+ cmods = L.nub $ map getClassModuleBase $ rights ecs+ tmods = L.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 a given top-level function+-- | generate import list for a given top-level template function -- currently this may generate duplicate import list. -- TODO: eliminate duplicated imports.-genImportForTopLevel :: TopLevel -> [ImportDecl ()]-genImportForTopLevel f =- let dep4func = extractClassDepForTopLevel f+-- TODO2: should be refactored out.+genImportForTLTemplate :: TLTemplate -> [ImportDecl ()]+genImportForTLTemplate f =+ let dep4func = extractClassDepForTLTemplate 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+ cmods = L.nub $ map getClassModuleBase $ rights ecs+ tmods = L.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-+ String ->+ ([ClassModule], [TemplateClassModule]) ->+ [ImportDecl ()]+genImportInTopLevel modname (mods, _tmods) =+ map (mkImport . cmModule) mods+ ++ map mkImport [modname <.> "Template", modname <.> "TH", modname <.> "Ordinary"]
src/FFICXX/Generate/Code/HsProxy.hs view
@@ -2,36 +2,46 @@ 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 Data.List as L (foldr1) ---import qualified FFICXX.Runtime.CodeGen.Cxx as R-import FFICXX.Generate.Util.HaskellSrcExts- ( con, inapp, mkFun, mkVar- , op, qualifier- , tyapp, tycon, tylist- ) +import FFICXX.Generate.Util.HaskellSrcExts+ ( con,+ inapp,+ mkFun,+ mkVar,+ op,+ qualifier,+ tyapp,+ tycon,+ tylist,+ )+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import Language.Haskell.Exts.Build (app, doE, listE, qualStmt, strE)+import Language.Haskell.Exts.Syntax (Decl (..)) 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 []+ 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
@@ -1,72 +1,112 @@-{-# LANGUAGE LambdaCase #-}+{-# 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 qualified Data.List as L (foldr1)+import FFICXX.Generate.Code.Cpp+ ( genTLTmplFunCpp,+ genTmplClassCpp,+ genTmplFunCpp,+ genTmplVarCpp,+ )+import FFICXX.Generate.Code.HsCast (castBody)+import FFICXX.Generate.Code.Primitive+ ( convertCpp2HS,+ convertCpp2HS4Tmpl,+ functionSignatureT,+ functionSignatureTMF,+ functionSignatureTT,+ tmplAccessorToTFun,+ )+import FFICXX.Generate.Dependency (calculateDependency)+import FFICXX.Generate.Name+ ( ffiTmplFuncName,+ hsTemplateClassName,+ hsTemplateMemberFunctionName,+ hsTemplateMemberFunctionNameTH,+ hsTmplFuncName,+ hsTmplFuncNameTH,+ subModuleName,+ tmplAccessorName,+ typeclassNameT,+ )+import FFICXX.Generate.Type.Class+ ( Accessor (Getter, Setter),+ Arg (..),+ Class (..),+ TLTemplate (..),+ TemplateClass (..),+ TemplateFunction (..),+ TemplateMemberFunction (..),+ Types (Void),+ Variable (..),+ )+import FFICXX.Generate.Type.Module+ ( ClassImportHeader (..),+ TemplateClassImportHeader (..),+ TemplateClassSubmoduleType (..),+ TopLevelImportHeader (..),+ )+import FFICXX.Generate.Util (firstUpper) 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- )-+ ( bracketExp,+ clsDecl,+ con,+ conDecl,+ cxEmpty,+ generator,+ inapp,+ insDecl,+ insType,+ match,+ mkBind1,+ mkClass,+ mkData,+ mkFun,+ mkFunSig,+ mkImport,+ mkInstance,+ mkNewtype,+ mkPVar,+ mkTBind,+ mkTVar,+ mkVar,+ op,+ parenSplice,+ pbind_,+ qualConDecl,+ qualifier,+ tyPtr,+ tySplice,+ tyapp,+ tycon,+ tyfun,+ tylist,+ typeBracket,+ )+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..))+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import FFICXX.Runtime.TH (IsCPrimitive (CPrim, NonCPrim))+import Language.Haskell.Exts.Build+ ( app,+ binds,+ caseE,+ doE,+ lamE,+ letE,+ letStmt,+ listE,+ name,+ pApp,+ pTuple,+ paren,+ qualStmt,+ strE,+ tuple,+ wildcard,+ )+import Language.Haskell.Exts.Syntax (Boxed (Boxed), Decl (..), ImportDecl (..), Type (TyTuple)) ------------------------------ -- Template member function --@@ -75,7 +115,7 @@ genTemplateMemberFunctions :: ClassImportHeader -> [Decl ()] genTemplateMemberFunctions cih = let c = cihClass cih- in concatMap (\f -> genTMFExp c f <> genTMFInstance cih f) (class_tmpl_funcs c)+ in concatMap (\f -> genTMFExp c f <> genTMFInstance cih f) (class_tmpl_funcs c) -- TODO: combine this with genTmplInstance genTMFExp :: Class -> TemplateMemberFunction -> [Decl ()]@@ -84,90 +124,104 @@ nh = hsTemplateMemberFunctionNameTH c f v = mkVar p = mkPVar- itps = zip ([1..]::[Int]) (tmf_params f)- tvars = map (\(i,_) -> "typ" ++ show i) itps+ 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") ]+ 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"])+ 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- ]+ 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+ 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"))+ 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" ) ]+ 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"])) ]+ 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"- ]- )- )+ (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+ 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"])+ [ 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"])+ [ 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")@@ -178,111 +232,98 @@ 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")- )+ fmap (mkImport . subModuleName) $ calculateDependency $ Left (TCSTTemplate, t0) -- | 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+ [ 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)- ]+ 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"]- )+ fmap (mkImport . subModuleName) $ calculateDependency $ Left (TCSTTH, t0) -- | genTmplImplementation :: TemplateClass -> [Decl ()] genTmplImplementation t =- concatMap gen (tclass_funcs t) ++ concatMap genV (tclass_vars 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+ 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") ]+ 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+ 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]+ ( 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 ()]+ TemplateClassImportHeader ->+ [Decl ()] genTmplInstance tcih =- mkFun- fname- sig- (p "isCprim" : zipWith (\x y -> pTuple [p x,p y]) qtvars pvars)- rhs- Nothing+ 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@@ -291,150 +332,376 @@ 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+ 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)+ 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+ 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]- )+ 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)+ 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"+ (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)- )- )- ]-+ 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 "")+ (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" ]- , 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)- ]+ 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+ 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"))+ [ 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"])+ [ 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")+ ] - 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")- ]+---------------+-- top-level --+---------------++-- |+genTLTemplateInterface :: TLTemplate -> [Decl ()]+genTLTemplateInterface t =+ [ mkClass cxEmpty (firstUpper (topleveltfunc_name t)) (map mkTBind tps) methods+ ]+ where+ tps = topleveltfunc_params t+ ctyp = convertCpp2HS Nothing (topleveltfunc_ret t)+ lst = map (convertCpp2HS Nothing . arg_type) (topleveltfunc_args t)+ sigdecl = mkFunSig (topleveltfunc_name t) $ foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])+ methods = [clsDecl sigdecl]++-- |+genTLTemplateImplementation :: TLTemplate -> [Decl ()]+genTLTemplateImplementation t =+ mkFun nh sig (tvars_p ++ [p "suffix"]) rhs (Just bstmts)+ where+ v = mkVar+ p = mkPVar+ itps = zip ([1 ..] :: [Int]) (topleveltfunc_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 = "TL"+ nh = "t_" <> topleveltfunc_name t+ nc = topleveltfunc_name t+ 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' =+ let e = error "genTLTemplateImplementation"+ spls = map (tySplice . parenSplice . mkVar) $ topleveltfunc_params t+ ctyp = convertCpp2HS4Tmpl e Nothing spls (topleveltfunc_ret t)+ lst = map (convertCpp2HS4Tmpl e Nothing spls . arg_type) (topleveltfunc_args t)+ in foldr1 tyfun (lst <> [tyapp (tycon "IO") ctyp])+ tassgns = map (\(i, tp) -> pbind_ (p tp) (v "pure" `app` (v ("typ" ++ show i)))) itps+ bstmts =+ binds+ [ mkBind1+ "tyf"+ [wildcard]+ ( letE+ tassgns+ (bracketExp (typeBracket sig'))+ )+ Nothing+ ]++genTLTemplateInstance ::+ TopLevelImportHeader ->+ TLTemplate ->+ [Decl ()]+genTLTemplateInstance tih t =+ mkFun+ fname+ sig+ (p "isCprim" : zipWith (\x y -> pTuple [p x, p y]) qtvars pvars)+ rhs+ Nothing+ where+ p = mkPVar+ v = mkVar+ tcname = firstUpper (topleveltfunc_name t)+ fname = "gen" <> tcname <> "InstanceFor"+ itps = zip ([1 ..] :: [Int]) (topleveltfunc_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")]+ -- 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)+ <> [genstmt "f" (1 :: Int)]+ <> [ 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)+ genstmt prefix n =+ generator+ (p (prefix <> show n))+ ( v "mkFunc" `app` strE (topleveltfunc_name t)+ `app` v ("t_" <> topleveltfunc_name t)+ `app` typs_v+ `app` v "suffix"+ )+ lststmt = [pbind_ (p "lst") (listE [v "f1"])]+ -- 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 (tcname <> "_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+ includeStatic =+ strE $+ concatMap+ (<> "\n")+ ( [R.renderCMacro (R.Include (HdrName "MacroPatternMatch.h"))]+ ++ map+ R.renderCMacro+ ( map R.Include (tihExtraHeadersInCPP tih)+ ++ [genTLTmplFunCpp CPrim t, genTLTmplFunCpp NonCPrim t]+ )+ )+ {-+ 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` (v "con" `app` strE tcname)+ `app` foldl1+ (\f x -> con "AppT" `app` f `app` x)+ (v "con" `app` strE tcname : map v tvars)+ `app` (v "lst")+ ]
src/FFICXX/Generate/Code/Primitive.hs view
@@ -1,1003 +1,1067 @@-{-# 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+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}++module FFICXX.Generate.Code.Primitive where++import Control.Monad.Trans.State (get, put, runState)+import Data.Functor.Identity (Identity)+import FFICXX.Generate.Name+ ( ffiClassName,+ hsClassName,+ hsClassNameForTArg,+ hsTemplateClassName,+ tmplAccessorName,+ typeclassName,+ typeclassNameFromStr,+ )+import FFICXX.Generate.Type.Class+ ( Accessor (Getter, Setter),+ Arg (..),+ CPPTypes (..),+ CTypes (..),+ Class (..),+ 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,+ tyPtr,+ tySplice,+ tyapp,+ tycon,+ tyfun,+ unit_tycon,+ unqual,+ )+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import FFICXX.Runtime.TH (IsCPrimitive (CPrim, NonCPrim))+import Language.Haskell.Exts.Syntax (Asst (..), Context, Type (..))++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 ->+ 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) 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 ::+ -- | self+ Type () ->+ Maybe Class ->+ -- | type paramemter splice+ [Type ()] ->+ 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 ::+ -- | class (Nothing for top-level function)+ Maybe Class ->+ -- | is virtual function?+ Bool ->+ -- | C type signature information for a given function -- (Args,Types) -- ^ (argument types, return type) of a given function+ CFunSig ->+ -- | Haskell type signature information for the function -- ([Type ()],[Asst ()]) -- ^ (types, class constraints)+ HsFunSig+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_
src/FFICXX/Generate/Config.hs view
@@ -1,26 +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 )-+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 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]+data SimpleBuilderConfig = SimpleBuilderConfig+ { sbcTopModule :: String,+ sbcModUnitMap :: ModuleUnitMap,+ sbcCabal :: Cabal,+ sbcClasses :: [Class],+ sbcTopLevels :: [TopLevel],+ sbcTemplates :: [TemplateClassImportHeader],+ sbcExtraLibs :: [String],+ sbcCxxOpts :: [String],+ sbcExtraDeps :: [(String, [String])],+ sbcStaticFiles :: [String] }
src/FFICXX/Generate/ContentMaker.hs view
@@ -3,529 +3,747 @@ 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)+import Control.Lens (at, (&), (.~))+import Control.Monad.Trans.Reader (runReader)+import Data.Either (rights)+import Data.Functor.Identity (Identity)+import Data.List (intercalate, nub)+import qualified Data.Map as M+import Data.Maybe (mapMaybe)+import FFICXX.Generate.Code.Cpp+ ( genAllCppHeaderInclude,+ genCppDefInstAccessor,+ genCppDefInstNonVirtual,+ genCppDefInstVirtual,+ genCppDefMacroAccessor,+ genCppDefMacroNonVirtual,+ genCppDefMacroTemplateMemberFunction,+ genCppDefMacroVirtual,+ genCppHeaderInstAccessor,+ genCppHeaderInstNonVirtual,+ genCppHeaderInstVirtual,+ genCppHeaderMacroAccessor,+ genCppHeaderMacroNonVirtual,+ genCppHeaderMacroType,+ genCppHeaderMacroVirtual,+ 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,+ genImportForTLOrdinary,+ genImportForTLTemplate,+ genImportInCast,+ genImportInImplementation,+ genImportInInterface,+ genImportInModule,+ genImportInTopLevel,+ genTopLevelDef,+ hsClassRawType,+ )+import FFICXX.Generate.Code.HsProxy (genProxyInstance)+import FFICXX.Generate.Code.HsTemplate+ ( genImportInTH,+ genImportInTemplate,+ genTLTemplateImplementation,+ genTLTemplateInstance,+ genTLTemplateInterface,+ genTemplateMemberFunctions,+ genTmplImplementation,+ genTmplInstance,+ genTmplInterface,+ )+import FFICXX.Generate.Dependency+ ( class_allparents,+ mkDaughterMap,+ mkDaughterSelfMap,+ )+import FFICXX.Generate.Name+ ( ffiClassName,+ hsClassName,+ hsFrontNameForTopLevel,+ )+import FFICXX.Generate.Type.Annotate (AnnotateMap)+import FFICXX.Generate.Type.Class+ ( Class (..),+ ClassGlobal (..),+ DaughterMap,+ ProtectedMethod (..),+ TopLevel (TLOrdinary, TLTemplate),+ filterTLOrdinary,+ filterTLTemplate,+ isAbstractClass,+ )+import FFICXX.Generate.Type.Module+ ( ClassImportHeader (..),+ ClassModule (..),+ DepCycles,+ TemplateClassImportHeader (..),+ TemplateClassModule (..),+ TopLevelImportHeader (..),+ )+import FFICXX.Generate.Type.PackageInterface+ ( ClassName (..),+ PackageInterface,+ PackageName (..),+ )+import FFICXX.Generate.Util (firstUpper)+import FFICXX.Generate.Util.HaskellSrcExts+ ( emodule,+ evar,+ lang,+ mkImport,+ mkModule,+ mkModuleE,+ unqual,+ )+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..))+import qualified FFICXX.Runtime.CodeGen.Cxx as R+import Language.Haskell.Exts.Syntax+ ( Decl (..),+ EWildcard (EWildcard),+ ExportSpec (EThingWith),+ Module (..),+ )+import System.FilePath ((<.>), (</>))++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 ::+ -- | C prefix+ String ->+ 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 ::+ -- | C prefix+ String ->+ 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) $ filterTLOrdinary (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) $+ filterTLOrdinary (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", "InterruptibleFFI"]]+ 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 ->+ DepCycles ->+ ClassModule ->+ Module ()+buildInterfaceHs amap depCycles 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 False depCycles m+ <> genExtraImport m+ ifaceBody =+ runReader (mapM (genHsFrontDecl False) classes) amap+ <> (concatMap genHsFrontUpcastClass . filter (not . isAbstractClass)) classes+ <> (concatMap genHsFrontDowncastClass . filter (not . isAbstractClass)) classes++-- |+buildInterfaceHsBoot :: DepCycles -> ClassModule -> Module ()+buildInterfaceHsBoot depCycles m =+ mkModule+ (cmModule m <.> "Interface")+ [ lang+ [ "EmptyDataDecls",+ "ExistentialQuantification",+ "FlexibleContexts",+ "FlexibleInstances",+ "ForeignFunctionInterface",+ "MultiParamTypeClasses",+ "ScopedTypeVariables",+ "TypeFamilies",+ "TypeSynonymInstances"+ ]+ ]+ hsbootImports+ hsbootBody+ where+ c = cihClass (cmCIH m)+ hsbootImports =+ [ mkImport "Data.Word",+ mkImport "Data.Int",+ mkImport "Foreign.C",+ mkImport "Foreign.Ptr",+ mkImport "FFICXX.Runtime.Cast"+ ]+ <> genImportInInterface True depCycles m+ <> genExtraImport m+ hsbootBody =+ runReader (mapM (genHsFrontDecl True) [c]) M.empty++-- |+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)++-- |+buildModuleHs :: ClassModule -> Module ()+buildModuleHs m = mkModuleE (cmModule m) [] (genExport c) (genImportInModule c) []+ where+ c = cihClass (cmCIH m)++-- |+buildTopLevelHs ::+ String ->+ ([ClassModule], [TemplateClassModule]) ->+ Module ()+buildTopLevelHs modname (mods, tmods) =+ mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody+ where+ pkgExtensions =+ [ lang+ [ "FlexibleContexts",+ "FlexibleInstances",+ "ForeignFunctionInterface",+ "InterruptibleFFI"+ ]+ ]+ pkgExports =+ map (emodule . cmModule) mods+ ++ map emodule [modname <.> "Ordinary", modname <.> "Template", modname <.> "TH"]+ pkgImports = genImportInTopLevel modname (mods, tmods)+ pkgBody = [] -- map (genTopLevelFFI tih) (filterTLOrdinary tfns)+ -- ++ concatMap genTopLevelDef (filterTLOrdinary tfns)++buildTopLevelOrdinaryHs ::+ String ->+ ([ClassModule], [TemplateClassModule]) ->+ TopLevelImportHeader ->+ Module ()+buildTopLevelOrdinaryHs modname (_mods, tmods) tih =+ mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody+ where+ tfns = tihFuncs tih+ pkgExtensions =+ [ lang+ [ "FlexibleContexts",+ "FlexibleInstances",+ "ForeignFunctionInterface",+ "InterruptibleFFI"+ ]+ ]+ pkgExports = map (evar . unqual . hsFrontNameForTopLevel . TLOrdinary) (filterTLOrdinary tfns)+ pkgImports =+ map mkImport ["Foreign.C", "Foreign.Ptr", "FFICXX.Runtime.Cast"]+ ++ map (\m -> mkImport (tcmModule m <.> "Template")) tmods+ ++ concatMap genImportForTLOrdinary (filterTLOrdinary tfns)+ pkgBody =+ map (genTopLevelFFI tih) (filterTLOrdinary tfns)+ ++ concatMap genTopLevelDef (filterTLOrdinary tfns)++-- |+buildTopLevelTemplateHs ::+ String ->+ TopLevelImportHeader ->+ Module ()+buildTopLevelTemplateHs modname tih =+ mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody+ where+ tfns = filterTLTemplate (tihFuncs tih)+ pkgExtensions =+ [ lang+ [ "EmptyDataDecls",+ "FlexibleInstances",+ "ForeignFunctionInterface",+ "InterruptibleFFI",+ "MultiParamTypeClasses",+ "TypeFamilies"+ ]+ ]+ pkgExports =+ map+ ( (\n -> EThingWith () (EWildcard () 1) n [])+ . unqual+ . firstUpper+ . hsFrontNameForTopLevel+ . TLTemplate+ )+ tfns+ pkgImports =+ [ mkImport "Foreign.C.Types",+ mkImport "Foreign.Ptr",+ mkImport "FFICXX.Runtime.Cast"+ ]+ ++ concatMap genImportForTLTemplate tfns+ pkgBody = concatMap genTLTemplateInterface tfns++-- |+buildTopLevelTHHs ::+ String ->+ TopLevelImportHeader ->+ Module ()+buildTopLevelTHHs modname tih =+ mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody+ where+ tfns = filterTLTemplate (tihFuncs tih)+ pkgExtensions =+ [ lang+ [ "FlexibleContexts",+ "FlexibleInstances",+ "ForeignFunctionInterface",+ "InterruptibleFFI",+ "TemplateHaskell"+ ]+ ]+ pkgExports =+ map+ ( evar+ . unqual+ . (\x -> "gen" <> x <> "InstanceFor")+ . firstUpper+ . hsFrontNameForTopLevel+ . TLTemplate+ )+ tfns+ pkgImports =+ [ 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"+ ]+ ++ concatMap genImportForTLTemplate tfns+ pkgBody =+ concatMap genTLTemplateImplementation tfns+ <> concatMap (genTLTemplateInstance tih) 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
@@ -1,5 +1,6 @@-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} module FFICXX.Generate.Dependency where @@ -19,50 +20,66 @@ -- 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 Data.Bifunctor (bimap)+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.List as L (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(..)- )-+import Data.Maybe (catMaybes, fromMaybe, mapMaybe)+import FFICXX.Generate.Name+ ( ffiClassName,+ getClassModuleBase,+ getTClassModuleBase,+ hsClassName,+ )+import FFICXX.Generate.Type.Cabal+ ( AddCInc,+ AddCSrc,+ CabalName (..),+ cabal_cheaderprefix,+ cabal_pkgname,+ unCabalName,+ )+import FFICXX.Generate.Type.Class+ ( Arg (..),+ CPPTypes (..),+ Class (..),+ DaughterMap,+ Function (..),+ TLOrdinary (..),+ TLTemplate (..),+ TemplateAppInfo (..),+ TemplateArgType (TArg_Class),+ TemplateClass (..),+ TemplateFunction (..),+ TemplateMemberFunction (..),+ TopLevel (..),+ Types (..),+ Variable (unVariable),+ argsFromOpExp,+ filterTLOrdinary,+ virtualFuncs,+ )+import FFICXX.Generate.Type.Config+ ( ModuleUnit (..),+ ModuleUnitImports (..),+ ModuleUnitMap (..),+ emptyModuleUnitImports,+ )+import FFICXX.Generate.Type.Module+ ( ClassImportHeader (..),+ ClassModule (..),+ ClassSubmoduleType (..),+ PackageConfig (..),+ TemplateClassImportHeader (..),+ TemplateClassModule (..),+ TemplateClassSubmoduleType (..),+ TopLevelImportHeader (..),+ UClassSubmodule,+ )+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..))+import System.FilePath ((<.>)) -- utility functions @@ -73,98 +90,91 @@ -- 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 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 _)) =+extractClassFromType (TemplateAppRef (TemplateAppInfo t ps _)) = Left t : (map Right $ mapMaybe (\case TArg_Class c -> Just c; _ -> Nothing) ps)-extractClassFromType (TemplateAppMove (TemplateAppInfo t 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 (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)-+class_allparents c =+ let ps = class_parents c+ in if null ps+ then []+ else L.nub (ps <> (concatMap class_allparents ps)) -- | 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--+ 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--+mkDaughterSelfMap = L.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] }-+data Dep4Func = Dep4Func+ { returnDependency :: [Either TemplateClass Class],+ argumentDependency :: [Either TemplateClass Class]+ } -- | extractClassDep :: Function -> Dep4Func-extractClassDep (Constructor args _) =- Dep4Func [] (concatMap classFromArg args)+extractClassDep (Constructor args _) =+ Dep4Func [] (concatMap classFromArg args) extractClassDep (Virtual ret _ args _) =- Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args) extractClassDep (NonVirtual ret _ args _) =- Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args) extractClassDep (Static ret _ args _) =- Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args) extractClassDep (Destructor _) =- Dep4Func [] []+ Dep4Func [] [] -- | extractClassDepForTmplFun :: TemplateFunction -> Dep4Func-extractClassDepForTmplFun (TFun ret _ _ args) =- Dep4Func (extractClassFromType ret) (concatMap classFromArg args)+extractClassDepForTmplFun (TFun ret _ _ args) =+ Dep4Func (extractClassFromType ret) (concatMap classFromArg args) extractClassDepForTmplFun (TFunNew args _) =- Dep4Func [] (concatMap classFromArg args)+ Dep4Func [] (concatMap classFromArg args) extractClassDepForTmplFun TFunDelete =- Dep4Func [] []-extractClassDepForTmplFun (TFunOp ret _ e) =- Dep4Func (extractClassFromType ret) (concatMap classFromArg $ argsFromOpExp e)+ Dep4Func [] []+extractClassDepForTmplFun (TFunOp ret _ e) =+ Dep4Func (extractClassFromType ret) (concatMap classFromArg $ argsFromOpExp e) -- | extractClassDep4TmplMemberFun :: TemplateMemberFunction -> Dep4Func@@ -172,140 +182,192 @@ 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 {..} -> []+extractClassDepForTLOrdinary :: TLOrdinary -> Dep4Func+extractClassDepForTLOrdinary 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 {} -> [] +-- |+extractClassDepForTLTemplate :: TLTemplate -> Dep4Func+extractClassDepForTLTemplate f =+ Dep4Func (extractClassFromType ret) (concatMap (extractClassFromType . arg_type) args)+ where+ ret = topleveltfunc_ret f+ args = topleveltfunc_args f --- TODO: Confirm the answer below is correct.--- NOTE: Q: Why returnDependency only?+mkDepFFI :: Class -> [UClassSubmodule]+mkDepFFI cls =+ let ps = map Right (class_allparents cls)+ alldeps' = concatMap go ps <> go (Right cls)+ depSelf = Right (CSTRawType, cls)+ in depSelf : (fmap (bimap (TCSTTemplate,) (CSTRawType,)) $ L.nub $ filter (/= Right cls) alldeps')+ where+ go (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+ go (Left t) =+ let fs = tclass_funcs t+ in concatMap (returnDependency . extractClassDepForTmplFun) fs+ <> concatMap (argumentDependency . extractClassDepForTmplFun) fs++-- For raws:+-- NOTE: Q: Why returnDependency for RawTypes? -- 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+calculateDependency :: UClassSubmodule -> [UClassSubmodule]+calculateDependency (Left (typ, tcl)) = raws <> inplaces+ where+ raws' =+ L.nub $+ filter (/= Left tcl) $+ concatMap (returnDependency . extractClassDepForTmplFun) $+ tclass_funcs tcl+ raws =+ case typ of+ TCSTTemplate ->+ fmap (bimap (TCSTTemplate,) (CSTRawType,)) raws'+ TCSTTH ->+ concatMap+ ( \case+ Left t -> [Left (TCSTTemplate, t)]+ Right c -> fmap (Right . (,c)) [CSTRawType, CSTCast, CSTInterface]+ )+ raws'+ inplaces =+ let fs = tclass_funcs tcl+ in fmap (bimap (TCSTTemplate,) (CSTInterface,)) $+ L.nub $+ filter (`isInSamePackageButNotInheritedBy` Left tcl) $+ concatMap (argumentDependency . extractClassDepForTmplFun) fs+calculateDependency (Right (CSTRawType, _)) = []+calculateDependency (Right (CSTFFI, cls)) = mkDepFFI cls+calculateDependency (Right (CSTInterface, cls)) =+ let retDepClasses =+ concatMap (returnDependency . extractClassDep) (virtualFuncs $ class_funcs cls)+ ++ concatMap (returnDependency . extractClassDep4TmplMemberFun) (class_tmpl_funcs cls)+ argDepClasses =+ concatMap (argumentDependency . extractClassDep) (virtualFuncs $ class_funcs cls)+ ++ concatMap (argumentDependency . extractClassDep4TmplMemberFun) (class_tmpl_funcs cls)+ rawSelf = Right (CSTRawType, cls)+ raws =+ fmap (bimap (TCSTTemplate,) (CSTRawType,)) $ L.nub $ filter (/= Right cls) retDepClasses+ exts =+ let extclasses =+ filter (`isNotInSamePackageWith` Right cls) argDepClasses+ parents = map Right (class_parents cls)+ in fmap (bimap (TCSTTemplate,) (CSTInterface,)) $ L.nub (parents <> extclasses)+ inplaces =+ fmap (bimap (TCSTTemplate,) (CSTInterface,)) $+ L.nub $+ filter (`isInSamePackageButNotInheritedBy` Right cls) $ argDepClasses+ in rawSelf : (raws ++ exts ++ inplaces)+calculateDependency (Right (CSTCast, cls)) = [Right (CSTRawType, cls), Right (CSTInterface, cls)]+calculateDependency (Right (CSTImplementation, cls)) =+ let depsSelf =+ [ Right (CSTRawType, cls),+ Right (CSTFFI, cls),+ Right (CSTInterface, cls),+ Right (CSTCast, cls)+ ]+ dsFFI = fmap (bimap snd snd) $ mkDepFFI cls+ dsParents = L.nub $ map Right $ class_allparents cls+ dsNonParents = filter (not . (flip elem dsParents)) dsFFI + deps =+ concatMap+ ( \case+ Left t -> [Left (TCSTTemplate, t)]+ Right c ->+ [ Right (CSTRawType, c),+ Right (CSTCast, c),+ Right (CSTInterface, c)+ ]+ )+ (dsNonParents <> dsParents)+ in depsSelf <> deps+ -- |-isNotInSamePackageWith- :: Either TemplateClass Class- -> Either TemplateClass Class- -> Bool+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 ::+ -- | y+ Either TemplateClass Class ->+ -- | x+ Either TemplateClass Class ->+ 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+ in L.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+ in L.nub . filter (/= y) $+ concatMap (returnDependency . extractClassDepForTmplFun) fs+ <> concatMap (argumentDependency . extractClassDepForTmplFun) fs+ <> getparents y --- |-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 _) = []+-- | Find module-level dependency per each toplevel function/template function.+mkTopLevelDep :: TopLevel -> [UClassSubmodule]+mkTopLevelDep (TLOrdinary f) =+ let dep4func = extractClassDepForTLOrdinary f+ allDeps = returnDependency dep4func ++ argumentDependency dep4func+ mkTags (Left tcl) = [Left (TCSTTemplate, tcl)]+ mkTags (Right cls) = fmap (Right . (,cls)) [CSTRawType, CSTCast, CSTInterface]+ in concatMap mkTags allDeps+mkTopLevelDep (TLTemplate f) =+ let dep4func = extractClassDepForTLTemplate f+ allDeps = returnDependency dep4func ++ argumentDependency dep4func+ mkTags (Left tcl) = [Left (TCSTTemplate, tcl)]+ mkTags (Right cls) = fmap (Right . (,cls)) [CSTRawType, CSTCast, CSTInterface]+ in concatMap mkTags allDeps -- |-mkClassModule :: (ModuleUnit -> ModuleUnitImports)- -> [(String,[String])]- -> Class- -> ClassModule+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+ ClassModule+ { cmModule = getClassModuleBase c,+ cmCIH = mkCIH getImports c,+ cmImportedSubmodulesForInterface = calculateDependency $ Right (CSTInterface, c),+ cmImportedSubmodulesForFFI = calculateDependency $ Right (CSTFFI, c),+ cmImportedSubmodulesForCast = calculateDependency $ Right (CSTCast, c),+ cmImportedSubmodulesForImplementation = calculateDependency $ Right (CSTImplementation, c),+ cmExtraImport = fromMaybe [] (lookup (class_name c) extra) }- 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@@ -314,121 +376,116 @@ -- | mkTCM ::- TemplateClassImportHeader- -> TemplateClassModule+ TemplateClassImportHeader ->+ TemplateClassModule mkTCM tcih = let t = tcihTClass tcih- in TCM (getTClassModuleBase t) 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 =+mkPackageConfig ::+ -- | (package name,getImports)+ (CabalName, ModuleUnit -> ModuleUnitImports) ->+ ([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)+ cihs = L.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)+ 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+ } -- |-mkPkgHeaderFileName ::Class -> HeaderName+mkPkgHeaderFileName :: Class -> HeaderName mkPkgHeaderFileName c =- HdrName ( (cabal_cheaderprefix.class_cabal) c- <> fst (hsClassName c)- <.> "h"- )+ HdrName+ ( (cabal_cheaderprefix . class_cabal) c+ <> fst (hsClassName c)+ <.> "h"+ ) -- |-mkPkgCppFileName ::Class -> String+mkPkgCppFileName :: Class -> String mkPkgCppFileName c =- (cabal_cheaderprefix.class_cabal) c- <> fst (hsClassName 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+ let pkgname = (cabal_pkgname . class_cabal) c+ extclasses = filter ((/= pkgname) . getPkgName) . mkModuleDepCpp $ Right c+ extheaders = L.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 ::+ -- | (mk namespace and include headers)+ (ModuleUnit -> ModuleUnitImports) ->+ 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- }+ 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 ::+ 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)+ let ofs = filterTLOrdinary fs+ tl_cs1 = concatMap (argumentDependency . extractClassDepForTLOrdinary) ofs+ tl_cs2 = concatMap (returnDependency . extractClassDepForTLOrdinary) ofs+ tl_cs = L.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+ where+ fn c ys =+ let y = L.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)- }+ extheaders =+ map HdrName $+ L.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/Dependency/Graph.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TupleSections #-}++module FFICXX.Generate.Dependency.Graph where++import Data.Array (listArray)+import qualified Data.Graph as G+import qualified Data.HashMap.Strict as HM+import qualified Data.List as L+import Data.Maybe (fromMaybe, mapMaybe)+import Data.Tree (flatten)+import Data.Tuple (swap)+import FFICXX.Generate.Dependency+ ( calculateDependency,+ mkTopLevelDep,+ )+import FFICXX.Generate.Name (subModuleName)+import FFICXX.Generate.Type.Class (TopLevel (..))+import FFICXX.Generate.Type.Module+ ( ClassSubmoduleType (..),+ DepCycles,+ TemplateClassSubmoduleType (..),+ UClass,+ UClassSubmodule,+ )++-- TODO: Introduce unique id per submodule.++-- | construct dependency graph+constructDepGraph ::+ -- | list of all classes, either template class or ordinary class.+ [UClass] ->+ -- | list of all top-level functions.+ [TopLevel] ->+ -- | (all submodules, [(submodule, submodule dependencies)])+ ([String], [(Int, [Int])])+constructDepGraph allClasses allTopLevels = (allSyms, depmap')+ where+ -- for classes/template classes+ mkDep :: UClass -> [(UClassSubmodule, [UClassSubmodule])]+ mkDep c =+ case c of+ Left tcl ->+ fmap+ (build . Left . (,tcl))+ [TCSTTemplate, TCSTTH]+ Right cls ->+ fmap+ (build . Right . (,cls))+ [CSTRawType, CSTFFI, CSTInterface, CSTCast, CSTImplementation]+ where+ build x = (x, calculateDependency x)++ dep2Name :: [(UClassSubmodule, [UClassSubmodule])] -> [(String, [String])]+ dep2Name = fmap (\(x, ys) -> (subModuleName x, fmap subModuleName ys))+ -- TopLevel+ topLevelDeps :: (String, [String])+ topLevelDeps =+ let deps =+ L.nub . L.sort $ concatMap (fmap subModuleName . mkTopLevelDep) allTopLevels+ in ("[TopLevel]", deps)++ depmapAllClasses = concatMap (dep2Name . mkDep) allClasses+ depmap = topLevelDeps : depmapAllClasses+ allSyms =+ L.nub . L.sort $+ fmap fst depmap ++ concatMap snd depmap+ allISyms :: [(Int, String)]+ allISyms = zip [0 ..] allSyms+ symRevMap = HM.fromList $ fmap swap allISyms+ replace (c, ds) = do+ i <- HM.lookup c symRevMap+ js <- traverse (\d -> HM.lookup d symRevMap) ds+ pure (i, js)+ depmap' = mapMaybe replace depmap++-- | find grouped dependency cycles+findDepCycles :: ([String], [(Int, [Int])]) -> DepCycles+findDepCycles (syms, deps) =+ let symMap = zip [0 ..] syms+ lookupSym i = fromMaybe "<NOTFOUND>" (L.lookup i symMap)+ n = length syms+ bounds = (0, n - 1)+ gr = listArray bounds $ fmap (\i -> fromMaybe [] (L.lookup i deps)) [0 .. n - 1]+ lookupSymAndRestrictDeps :: [Int] -> [(String, ([String], [String]))]+ lookupSymAndRestrictDeps cycl = fmap go cycl+ where+ go i =+ let sym = lookupSym i+ (rdepsU, rdepsL) =+ L.partition (< i) $ filter (`elem` cycl) $ fromMaybe [] (L.lookup i deps)+ (rdepsU', rdepsL') = (fmap lookupSym rdepsU, fmap lookupSym rdepsL)+ in (sym, (rdepsU', rdepsL'))+ cycleGroups =+ fmap lookupSymAndRestrictDeps $ filter (\xs -> length xs > 1) $ fmap flatten (G.scc gr)+ in cycleGroups++getCyclicDepSubmodules :: String -> DepCycles -> ([String], [String])+getCyclicDepSubmodules self depCycles = fromMaybe ([], []) $ do+ cycl <- L.find (\xs -> self `L.elem` fmap fst xs) depCycles+ L.lookup self cycl++-- | locate importing module and imported module in dependency cycles+locateInDepCycles :: (String, String) -> DepCycles -> Maybe (Int, Int)+locateInDepCycles (self, imported) depCycles = do+ cycl <- L.find (\xs -> self `L.elem` fmap fst xs) depCycles+ let cyclNoDeps = fmap fst cycl+ idxSelf <- self `L.elemIndex` cyclNoDeps+ idxImported <- imported `L.elemIndex` cyclNoDeps+ pure (idxSelf, idxImported)++gatherHsBootSubmodules :: DepCycles -> [String]+gatherHsBootSubmodules depCycles = do+ cycl <- depCycles+ (_, (_us, ds)) <- cycl+ d <- ds+ pure d
src/FFICXX/Generate/Name.hs view
@@ -1,33 +1,40 @@+{-# LANGUAGE NamedFieldPuns #-} {-# 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 )-+module FFICXX.Generate.Name where +import Data.Char (toLower)+import Data.Maybe (fromMaybe)+import FFICXX.Generate.Type.Cabal (cabal_moduleprefix)+import FFICXX.Generate.Type.Class+ ( Accessor (..),+ Arg (..),+ Class (..),+ ClassAlias (caFFIName, caHaskellName),+ Function (..),+ TLOrdinary (..),+ TLTemplate (..),+ TemplateArgType (..),+ TemplateClass (..),+ TemplateFunction (..),+ TemplateMemberFunction (..),+ TopLevel (..),+ Variable (..),+ )+import FFICXX.Generate.Type.Module+ ( ClassSubmoduleType (..),+ TemplateClassSubmoduleType (..),+ )+import FFICXX.Generate.Util (firstLower, toLowers)+import System.FilePath ((<.>)) 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-+ let (x : xs) = case tfn of+ TLOrdinary TopLevelFunction {..} -> fromMaybe toplevelfunc_name toplevelfunc_alias+ TLOrdinary TopLevelVariable {..} -> fromMaybe toplevelvar_name toplevelvar_alias+ TLTemplate TopLevelTemplateFunction {..} -> topleveltfunc_name+ in toLower x : xs typeclassName :: Class -> String typeclassName c = 'I' : fst (hsClassName c)@@ -35,97 +42,100 @@ typeclassNameT :: TemplateClass -> String typeclassNameT c = 'I' : fst (hsTemplateClassName c) -- typeclassNameFromStr :: String -> String-typeclassNameFromStr = ('I':)+typeclassNameFromStr = ('I' :) -hsClassName :: Class -> (String, String) -- ^ High-level, 'Raw'-level+hsClassName ::+ Class ->+ -- | High-level, 'Raw'-level+ (String, String) hsClassName c = let cname = maybe (class_name c) caHaskellName (class_alias c)- in (cname, "Raw" <> cname)+ 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 ::+ TemplateClass ->+ -- | High-level, 'Raw'-level+ (String, String) hsTemplateClassName t = let tname = tclass_name t- in (tname, "Raw" <> tname)+ in (tname, "Raw" <> tname) existConstructorName :: Class -> String-existConstructorName c = 'E' : (fst.hsClassName) c-+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)+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+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+ 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+ 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+ TFun {tfun_name} -> tfun_name+ TFunNew {tfun_new_alias} -> fromMaybe ("new" <> tclass_name t) tfun_new_alias+ TFunDelete -> "delete" <> tclass_name t+ TFunOp {tfun_name} -> 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+ TFun {tfun_name} -> tfun_name+ TFunNew {tfun_new_alias} -> fromMaybe "new" tfun_new_alias+ TFunDelete -> "delete"+ TFunOp {tfun_name} -> tfun_name cppTmplFuncName :: TemplateFunction -> String cppTmplFuncName f = case f of- TFun {..} -> tfun_name- TFunNew {..} -> "new"- TFunDelete -> "delete"- TFunOp {..} -> tfun_name+ TFun {tfun_name} -> tfun_name+ TFunNew {} -> "new"+ TFunDelete -> "delete"+ TFunOp {tfun_name} -> tfun_name -- | accessorName :: Class -> Variable -> Accessor -> String-accessorName c v a = nonvirtualName c (arg_name (unVariable v))- <> "_"- <> case a of- Getter -> "get"- Setter -> "set"+accessorName c v a =+ nonvirtualName c (arg_name (unVariable v))+ <> "_"+ <> case a of+ Getter -> "get"+ Setter -> "set" -- | hscAccessorName :: Class -> Variable -> Accessor -> String@@ -134,7 +144,7 @@ -- | tmplAccessorName :: Variable -> Accessor -> String tmplAccessorName (Variable (Arg _ n)) a =- n <> "_" <> case a of { Getter -> "get"; Setter -> "set" }+ n <> "_" <> case a of Getter -> "get"; Setter -> "set" -- | cppStaticName :: Class -> Function -> String@@ -142,19 +152,50 @@ -- | 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+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+constructorName c = "new" <> (fst . hsClassName) c nonvirtualName :: Class -> String -> String-nonvirtualName c str = (firstLower.fst.hsClassName) c <> "_" <> str+nonvirtualName c str = (firstLower . fst . hsClassName) c <> "_" <> str destructorName :: String destructorName = "delete" +--+-- Module base and Submodule names in ClassModule+--++getClassModuleBase :: Class -> String+getClassModuleBase = (<.>) <$> (cabal_moduleprefix . class_cabal) <*> (fst . hsClassName)++getTClassModuleBase :: TemplateClass -> String+getTClassModuleBase = (<.>) <$> (cabal_moduleprefix . tclass_cabal) <*> (fst . hsTemplateClassName)++subModuleName ::+ Either+ (TemplateClassSubmoduleType, TemplateClass)+ (ClassSubmoduleType, Class) ->+ String+subModuleName (Left (typ, tcl)) = modBase <.> submod+ where+ modBase = getTClassModuleBase tcl+ submod = case typ of+ TCSTTH -> "TH"+ TCSTTemplate -> "Template"+subModuleName (Right (typ, cls)) = modBase <.> submod+ where+ modBase = getClassModuleBase cls+ submod =+ case typ of+ CSTRawType -> "RawType"+ CSTInterface -> "Interface"+ CSTImplementation -> "Implementation"+ CSTFFI -> "FFI"+ CSTCast -> "Cast"
src/FFICXX/Generate/QQ/Verbatim.hs view
@@ -1,13 +1,23 @@ module FFICXX.Generate.QQ.Verbatim where -import Language.Haskell.TH.Quote import Language.Haskell.TH.Lib+ ( litE,+ stringL,+ )+import Language.Haskell.TH.Quote+ ( QuasiQuoter (..),+ quoteDec,+ quoteExp,+ quotePat,+ quoteType,+ ) verbatim :: QuasiQuoter-verbatim = QuasiQuoter{ quoteExp = litE . stringL- , quotePat = undefined- , quoteType = undefined- , quoteDec = undefined- -- , quotePat = litP . stringP- } -+verbatim =+ QuasiQuoter+ { quoteExp = litE . stringL,+ quotePat = undefined,+ quoteType = undefined,+ quoteDec = undefined+ -- , quotePat = litP . stringP+ }
src/FFICXX/Generate/Type/Annotate.hs view
@@ -2,10 +2,7 @@ import qualified Data.Map as M -data PkgType = PkgModule | PkgClass | PkgMethod - deriving (Show,Eq,Ord)--type AnnotateMap = M.Map (PkgType,String) String--+data PkgType = PkgModule | PkgClass | PkgMethod+ deriving (Show, Eq, Ord) +type AnnotateMap = M.Map (PkgType, String) String
src/FFICXX/Generate/Type/Cabal.hs view
@@ -2,72 +2,75 @@ module FFICXX.Generate.Type.Cabal where -import Data.Aeson (FromJSON(..),ToJSON(..)- ,genericParseJSON,genericToJSON- ,defaultOptions)+import Data.Aeson+ ( FromJSON (..),+ ToJSON (..),+ defaultOptions,+ genericParseJSON,+ genericToJSON,+ ) import Data.Aeson.Types (fieldLabelModifier)-import Data.Text (Text)-import GHC.Generics (Generic)+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)-+newtype CabalName = CabalName {unCabalName :: String}+ deriving (Show, Eq, Ord) -data BuildType = Simple- | Custom [CabalName] -- ^ dependencies+data BuildType+ = Simple+ | -- | dependencies+ Custom [CabalName] -- 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 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)+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}
src/FFICXX/Generate/Type/Class.hs view
@@ -1,21 +1,18 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-} {-# 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 )-+import Data.List (intercalate)+import qualified Data.Map as M+import Data.Maybe (mapMaybe)+import FFICXX.Generate.Type.Cabal (Cabal) -- | C types-data CTypes =- CTBool+data CTypes+ = CTBool | CTChar | CTClock | CTDouble@@ -57,121 +54,143 @@ | CEnum CTypes String | CPointer CTypes | CRef CTypes- deriving Show+ deriving (Show) -- | C++ types-data CPPTypes = CPTClass Class- | CPTClassRef Class- | CPTClassCopy Class- | CPTClassMove Class- deriving Show+data CPPTypes+ = CPTClass Class+ | CPTClassRef Class+ | CPTClassCopy Class+ | CPTClassMove Class+ deriving (Show) -- | const flag data IsConst = Const | NoConst- deriving Show+ 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+data TemplateArgType+ = TArg_Class Class | TArg_TypeParam String | TArg_Other String- deriving Show+ deriving (Show) -data TemplateAppInfo =- TemplateAppInfo {- tapp_tclass :: TemplateClass- , tapp_tparams :: [TemplateArgType]- , tapp_CppTypeForParam :: String -- TODO: remove this+data TemplateAppInfo = TemplateAppInfo+ { tapp_tclass :: TemplateClass,+ tapp_tparams :: [TemplateArgType],+ tapp_CppTypeForParam :: String -- TODO: remove this }- deriving Show+ deriving (Show) -- | Supported C++ types.-data Types =- Void+data Types+ = Void | SelfType- | CT CTypes IsConst+ | 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+ | -- | like vector<float>*+ TemplateApp TemplateAppInfo+ | -- | like vector<float>&+ TemplateAppRef TemplateAppInfo+ | -- | like unique_ptr<float> (using std::move)+ TemplateAppMove TemplateAppInfo+ | -- | template self? TODO: clarify this.+ TemplateType TemplateClass+ | TemplateParam String+ | -- | this is A* with template<A>+ TemplateParamPointer String+ deriving (Show) ------------- -- | Function argument, type and variable name.-data Arg =- Arg {- arg_type :: Types- , arg_name :: String+data Arg = Arg+ { arg_type :: Types,+ arg_name :: String }- deriving Show+ 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+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+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+data TemplateMemberFunction = TemplateMemberFunction+ { tmf_params :: [String],+ tmf_ret :: Types,+ tmf_name :: String,+ tmf_args :: [Arg],+ tmf_alias :: Maybe String }- deriving Show+ 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+data TopLevel+ = TLOrdinary TLOrdinary+ | TLTemplate TLTemplate+ deriving (Show) +filterTLOrdinary :: [TopLevel] -> [TLOrdinary]+filterTLOrdinary = mapMaybe (\case TLOrdinary f -> Just f; _ -> Nothing)++filterTLTemplate :: [TopLevel] -> [TLTemplate]+filterTLTemplate = mapMaybe (\case TLTemplate f -> Just f; _ -> Nothing)++data TLOrdinary+ = 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)++data TLTemplate = TopLevelTemplateFunction+ { topleveltfunc_params :: [String],+ topleveltfunc_ret :: Types,+ topleveltfunc_name :: String,+ topleveltfunc_oname :: String,+ topleveltfunc_args :: [Arg]+ }+ deriving (Show)+ isNewFunc :: Function -> Bool isNewFunc (Constructor _ _) = True isNewFunc _ = False@@ -181,15 +200,13 @@ isDeleteFunc _ = False isVirtualFunc :: Function -> Bool-isVirtualFunc (Destructor _) = True-isVirtualFunc (Virtual _ _ _ _) = True-isVirtualFunc _ = False+isVirtualFunc (Destructor _) = True+isVirtualFunc (Virtual _ _ _ _) = True+isVirtualFunc _ = False isNonVirtualFunc :: Function -> Bool isNonVirtualFunc (NonVirtual _ _ _ _) = True-isNonVirtualFunc _ = False--+isNonVirtualFunc _ = False isStaticFunc :: Function -> Bool isStaticFunc (Static _ _ _ _) = True@@ -203,42 +220,44 @@ nonVirtualNotNewFuncs :: [Function] -> [Function] nonVirtualNotNewFuncs =- filter (\x -> (not.isVirtualFunc) x && (not.isNewFunc) x && (not.isDeleteFunc) x && (not.isStaticFunc) x )+ 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)+newtype ProtectedMethod = Protected {unProtected :: [String]}+ deriving (Semigroup, Monoid) -data ClassAlias = ClassAlias { caHaskellName :: String- , caFFIName :: String- }+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]- }+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@@ -252,55 +271,62 @@ 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 OpExp+ = -- | unary * (deRef) operator+ OpStar+ | -- | unary prefix ++ operator+ -- | OpAdd Arg Arg+ -- | OpMul Arg Arg+ OpFPPlus -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- }+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- }+ | TFunOp+ { tfun_ret :: Types,+ -- | haskell alias for the operator+ tfun_name :: String,+ tfun_opexp :: OpExp+ } argsFromOpExp :: OpExp -> [Arg]-argsFromOpExp OpStar = []+argsFromOpExp OpStar = [] argsFromOpExp OpFPPlus = []+ -- argsFromOpExp (OpAdd x y) = [x,y] -- argsFromOpExp (OpMul x y) = [x,y] opSymbol :: OpExp -> String-opSymbol OpStar = "*"+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 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]+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@@ -315,27 +341,24 @@ instance Ord TemplateClass where compare x y = compare (tclass_name x) (tclass_name y) - data ClassGlobal = ClassGlobal- { cgDaughterSelfMap :: DaughterMap- , cgDaughterMap :: DaughterMap- }+ { cgDaughterSelfMap :: DaughterMap,+ cgDaughterMap :: DaughterMap+ } data Selfness = Self | NoSelf -- -- | Check abstract class isAbstractClass :: Class -> Bool-isAbstractClass Class{} = False-isAbstractClass AbstractClass{} = True+isAbstractClass Class {} = False+isAbstractClass AbstractClass {} = True -- | Check having Proxy hasProxy :: Class -> Bool-hasProxy c@Class{} = class_has_proxy c-hasProxy AbstractClass{} = False+hasProxy c@Class {} = class_has_proxy c+hasProxy AbstractClass {} = False type DaughterMap = M.Map String [Class] data Accessor = Getter | Setter- deriving (Show, Eq)+ deriving (Show, Eq)
src/FFICXX/Generate/Type/Config.hs view
@@ -1,39 +1,39 @@ {-# LANGUAGE DeriveGeneric #-}+ module FFICXX.Generate.Type.Config where -import Data.Hashable ( Hashable(..) )-import Data.HashMap.Strict ( HashMap )-import GHC.Generics ( Generic )+import Data.HashMap.Strict (HashMap)+import Data.Hashable (Hashable (..)) ---import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..), Namespace(..) )-+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..), Namespace (..))+import GHC.Generics (Generic) -data ModuleUnit = MU_TopLevel - | MU_Class String- deriving (Show,Eq,Generic)+data ModuleUnit+ = MU_TopLevel+ | MU_Class String+ deriving (Show, Eq, Generic) instance Hashable ModuleUnit -data ModuleUnitImports =- ModuleUnitImports {- muimports_namespaces :: [Namespace]- , muimports_headers :: [HeaderName]+data ModuleUnitImports = ModuleUnitImports+ { muimports_namespaces :: [Namespace],+ muimports_headers :: [HeaderName] } deriving (Show) emptyModuleUnitImports = ModuleUnitImports [] [] -newtype ModuleUnitMap = ModuleUnitMap { unModuleUnitMap :: HashMap ModuleUnit ModuleUnitImports }+newtype ModuleUnitMap = ModuleUnitMap {unModuleUnitMap :: HashMap ModuleUnit ModuleUnitImports} modImports ::- String- -> [String]- -> [HeaderName]- -> (ModuleUnit,ModuleUnitImports)+ String ->+ [String] ->+ [HeaderName] ->+ (ModuleUnit, ModuleUnitImports) modImports n ns hs =- ( MU_Class n- , ModuleUnitImports {- muimports_namespaces = map NS ns- , muimports_headers = hs- }+ ( MU_Class n,+ ModuleUnitImports+ { muimports_namespaces = map NS ns,+ muimports_headers = hs+ } )
src/FFICXX/Generate/Type/Module.hs view
@@ -1,80 +1,113 @@ 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 )-+import FFICXX.Generate.Type.Cabal (AddCInc, AddCSrc)+import FFICXX.Generate.Type.Class (Class, TemplateClass, TopLevel)+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..), Namespace (..)) --- | C++ side+--+-- Import/Header+-- -- 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)+data ClassImportHeader = ClassImportHeader+ { cihClass :: Class,+ -- | fficxx-side main header+ cihSelfHeader :: HeaderName,+ cihNamespace :: [Namespace],+ cihSelfCpp :: String,+ -- | Dependencies TODO: clarify this.+ cihImportedClasses :: [Either TemplateClass Class],+ cihIncludedHPkgHeadersInH :: [HeaderName], -- TODO: Explain why we need to have these two+ cihIncludedHPkgHeadersInCPP :: [HeaderName], -- separately. + -- | C++-side headers+ cihIncludedCPkgHeaders :: [HeaderName]+ }+ deriving (Show) ----------------------------- Haskell side module ----------------------------+--+-- Submodule+-- -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 ClassSubmoduleType+ = CSTRawType+ | CSTInterface+ | CSTImplementation+ | CSTFFI+ | CSTCast+ deriving (Show) +data TemplateClassSubmoduleType+ = TCSTTH+ | TCSTTemplate+ deriving (Show) -data TemplateClassModule =- TCM {- tcmModule :: String- , tcmTCIH :: TemplateClassImportHeader- } deriving (Show)+-- | UClass = Unified Class, either template class or ordinary class+type UClass = Either TemplateClass Class +type UClassSubmodule =+ Either (TemplateClassSubmoduleType, TemplateClass) (ClassSubmoduleType, Class) -data TemplateClassImportHeader =- TCIH {- tcihTClass :: TemplateClass- , tcihCxxHeaders :: [HeaderName] -- ^ C++-side headers- } deriving (Show)+-- | Dependency cycle information. Currently just a string+-- self, former, latter+type DepCycles = [[(String, ([String], [String]))]] -data TopLevelImportHeader =- TopLevelImportHeader {- tihHeaderFileName :: String- , tihClassDep :: [ClassImportHeader]- , tihExtraClassDep :: [Either TemplateClass Class]- -- ^ Extra class dependencies outside current package.+--+-- Module+--++data ClassModule = ClassModule+ { cmModule :: String,+ cmCIH :: ClassImportHeader,+ -- | imported submodules for Interface.hs+ cmImportedSubmodulesForInterface :: [UClassSubmodule],+ -- | imported submodules for FFI.hs+ cmImportedSubmodulesForFFI :: [UClassSubmodule],+ -- | imported submodules for Cast.hs+ cmImportedSubmodulesForCast,+ -- imported submodules for Implementation.hs+ cmImportedSubmodulesForImplementation ::+ [UClassSubmodule],+ cmExtraImport :: [String]+ }+ deriving (Show)++data TemplateClassModule = TCM+ { tcmModule :: String,+ tcmTCIH :: TemplateClassImportHeader+ }+ deriving (Show)++data TemplateClassImportHeader = TCIH+ { tcihTClass :: TemplateClass,+ -- | C++-side headers+ tcihCxxHeaders :: [HeaderName]+ }+ deriving (Show)++data TopLevelImportHeader = TopLevelImportHeader+ { tihHeaderFileName :: String,+ tihClassDep :: [ClassImportHeader],+ -- | Extra class dependencies outside current package. -- NOTE: we cannot fully construct ClassImportHeader for them.- , tihFuncs :: [TopLevel]- , tihNamespaces :: [Namespace]- , tihExtraHeadersInH :: [HeaderName]- , tihExtraHeadersInCPP :: [HeaderName]- } deriving (Show)+ tihExtraClassDep :: [Either TemplateClass Class],+ 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]+--+-- Package-level+--++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
@@ -1,15 +1,15 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} -- TODO: remove this module-module FFICXX.Generate.Type.PackageInterface where +module FFICXX.Generate.Type.PackageInterface where -import Data.Hashable ( Hashable ) import qualified Data.HashMap.Strict as HM+import Data.Hashable (Hashable) ---import FFICXX.Runtime.CodeGen.Cxx ( HeaderName(..) )+import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..)) +newtype PackageName = PkgName String deriving (Hashable, Show, Eq, Ord) -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 +type PackageInterface = HM.HashMap (PackageName, ClassName) HeaderName
src/FFICXX/Generate/Util.hs view
@@ -2,23 +2,24 @@ 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---+import Data.Char (toLower, toUpper)+import Data.List (intercalate)+import Data.List.Split (splitOn)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import Data.Text.Template+ ( Context,+ substitute,+ ) -moduleDirFile :: String -> (String,String)-moduleDirFile mname = +moduleDirFile :: String -> (String, String)+moduleDirFile mname = let splitted = splitOn "." mname- moddir = intercalate "/" (init splitted )- modfile = (last splitted) <> ".hs" - in (moddir, modfile)+ moddir = intercalate "/" (init splitted)+ modfile = (last splitted) <> ".hs"+ in (moddir, modfile) hline :: IO () hline = putStrLn "--------------------------------------------------------"@@ -26,24 +27,27 @@ toUppers :: String -> String toUppers = map toUpper -toLowers :: String -> String +toLowers :: String -> String toLowers = map toLower +firstLower :: String -> String+firstLower [] = []+firstLower (x : xs) = (toLower x) : xs -firstLower :: String -> String -firstLower [] = [] -firstLower (x:xs) = (toLower x) : xs +firstUpper :: String -> String+firstUpper [] = []+firstUpper (x : xs) = (toUpper x) : xs -conn :: String -> String -> String -> String -conn st x y = x <> st <> y +conn :: String -> String -> String -> String+conn st x y = x <> st <> y connspace :: String -> String -> String-connspace = conn " " +connspace = conn " " conncomma :: String -> String -> String-conncomma = conn ", " +conncomma = conn ", " -connBSlash :: String -> String -> String +connBSlash :: String -> String -> String connBSlash = conn "\\\n" connSemicolonBSlash :: String -> String -> String@@ -52,35 +56,36 @@ connRet :: String -> String -> String connRet = conn "\n" -connRet2 :: String -> String -> String +connRet2 :: String -> String -> String connRet2 = conn "\n\n" -connArrow :: String -> String -> String -connArrow = conn " -> " +connArrow :: String -> String -> String+connArrow = conn " -> " -intercalateWith :: (String-> String -> String) -> (a->String) -> [a] -> String-intercalateWith f mapper x +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 "" + | 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 :: [(Text, String)] -> Context context assocs x = maybe err (T.pack) . lookup x $ assocs- where err = error $ "Could not find key: " <> (T.unpack x)+ where+ err = error $ "Could not find key: " <> (T.unpack x) -- TODO: Rename this to context. -- TODO: Proper error handling.-contextT :: [(Text,Text)] -> Context+contextT :: [(Text, Text)] -> Context contextT assocs x = fromMaybe err . lookup x $ assocs- where err = error $ T.unpack ("Could not find key: " <> x)+ 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/DepGraph.hs view
@@ -0,0 +1,36 @@+module FFICXX.Generate.Util.DepGraph+ ( drawDepGraph,+ )+where++import Data.Foldable (for_)+import FFICXX.Generate.Dependency.Graph+ ( constructDepGraph,+ )+import FFICXX.Generate.Type.Class (TopLevel (..))+import FFICXX.Generate.Type.Module (UClass)+import Text.Dot (Dot, NodeId, attribute, node, showDot, (.->.))++src, box, diamond :: String -> Dot NodeId+src label = node $ [("shape", "none"), ("label", label)]+box label = node $ [("shape", "box"), ("style", "rounded"), ("label", label)]+diamond label = node $ [("shape", "diamond"), ("label", label), ("fontsize", "10")]++-- | Draw dependency graph of modules in graphviz dot format.+drawDepGraph ::+ -- | list of all classes, either template class or ordinary class.+ [UClass] ->+ -- | list of all top-level functions.+ [TopLevel] ->+ -- | dot string+ String+drawDepGraph allclasses allTopLevels =+ showDot $ do+ attribute ("size", "40,15")+ attribute ("rankdir", "LR")+ cs <- traverse box allSyms+ for_ depmap' $ \(i, js) ->+ for_ js $ \j ->+ (cs !! i) .->. (cs !! j)+ where+ (allSyms, depmap') = constructDepGraph allclasses allTopLevels
src/FFICXX/Generate/Util/HaskellSrcExts.hs view
@@ -1,14 +1,112 @@-{-# 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)-+import Data.List (foldl')+import Data.Maybe (maybeToList)+import Language.Haskell.Exts+ ( Alt (..),+ Asst (TypeA),+ Binds,+ Bracket (TypeBracket),+ CallConv (CCall),+ ClassDecl (ClsDecl),+ ConDecl+ ( ConDecl,+ RecDecl+ ),+ Context+ ( CxEmpty,+ CxTuple+ ),+ DataOrNew+ ( DataType,+ NewType+ ),+ Decl+ ( ClassDecl,+ DataDecl,+ ForImp,+ FunBind,+ InstDecl,+ PatBind,+ TypeSig+ ),+ DeclHead+ ( DHApp,+ DHead+ ),+ Deriving (..),+ EWildcard (..),+ Exp+ ( App,+ BracketExp,+ Con,+ If,+ InfixApp,+ Lit,+ Var+ ),+ ExportSpec+ ( EAbs,+ EModuleContents,+ EThingWith,+ EVar+ ),+ ExportSpecList (..),+ FieldDecl,+ ImportDecl (..),+ ImportSpec (IVar),+ ImportSpecList (..),+ InstDecl+ ( InsDecl,+ InsType+ ),+ InstHead+ ( IHApp,+ IHCon+ ),+ InstRule (IRule),+ Literal,+ Match (..),+ Module (..),+ ModuleHead (..),+ ModuleName (..),+ ModulePragma (LanguagePragma),+ Name+ ( Ident,+ Symbol+ ),+ Namespace (NoNamespace),+ Pat+ ( PVar,+ PatTypeSig+ ),+ QName (UnQual),+ QOp (QVarOp),+ QualConDecl (..),+ Rhs (UnGuardedRhs),+ Safety (PlayInterruptible),+ Splice (ParenSplice),+ Stmt+ ( Generator,+ Qualifier+ ),+ TyVarBind (UnkindedVar),+ Type+ ( TyApp,+ TyCon,+ TyForall,+ TyFun,+ TyList,+ TyParen,+ TySplice,+ TyVar+ ),+ app,+ unit_tycon,+ )+import Language.Haskell.Exts.Syntax (CName) -unqual :: String -> QName ()+unqual :: String -> QName () unqual = UnQual () . Ident () tycon :: String -> Type ()@@ -33,6 +131,11 @@ conDecl :: String -> [Type ()] -> ConDecl () conDecl n ys = ConDecl () (Ident () n) ys +qualConDecl ::+ Maybe [TyVarBind ()] ->+ Maybe (Context ()) ->+ ConDecl () ->+ QualConDecl () qualConDecl = QualConDecl () recDecl :: String -> [FieldDecl ()] -> ConDecl ()@@ -41,11 +144,9 @@ app' :: String -> String -> Exp () app' x y = App () (mkVar x) (mkVar y) - lit :: Literal () -> Exp () lit = Lit () - mkVar :: String -> Exp () mkVar = Var () . unqual @@ -75,7 +176,7 @@ mkBind1 :: String -> [Pat ()] -> Exp () -> Maybe (Binds ()) -> Decl () mkBind1 n pat rhs mbinds =- FunBind () [ Match () (Ident () n) pat (UnGuardedRhs () 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]@@ -84,8 +185,7 @@ 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)-+mkClass ctxt n tbinds cdecls = ClassDecl () (Just ctxt) (mkDeclHead n tbinds) [] (Just cdecls) dhead :: String -> DeclHead () dhead n = DHead () (Ident () n)@@ -95,37 +195,35 @@ 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)+ 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+mkData n tbinds qdecls mderiv = DataDecl () (DataType ()) Nothing declhead qdecls (maybeToList mderiv)+ 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+mkNewtype n tbinds qdecls mderiv = DataDecl () (NewType ()) Nothing declhead qdecls (maybeToList mderiv)+ where+ declhead = mkDeclHead n tbinds mkForImpCcall :: String -> String -> Type () -> Decl ()-mkForImpCcall quote n typ = ForImp () (CCall ()) (Just (PlaySafe () False)) (Just quote) (Ident () n) typ+mkForImpCcall quote n typ = ForImp () (CCall ()) (Just (PlayInterruptible ())) (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+ 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+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@@ -133,8 +231,8 @@ mkImportExp :: String -> [String] -> ImportDecl () mkImportExp m lst = ImportDecl () (ModuleName () m) False False False Nothing Nothing (Just islist)- where islist = ImportSpecList () False (map mkIVar lst)-+ where+ islist = ImportSpecList () False (map mkIVar lst) mkImportSrc :: String -> ImportDecl () mkImportSrc m = ImportDecl () (ModuleName () m) False True False Nothing Nothing Nothing@@ -145,8 +243,14 @@ dot :: Exp () -> Exp () -> Exp () x `dot` y = x `app` mkVar "." `app` y +tyForall ::+ Maybe [TyVarBind ()] ->+ Maybe (Context ()) ->+ Type () ->+ Type () tyForall = TyForall () +tyParen :: Type () -> Type () tyParen = TyParen () tyPtr :: Type ()@@ -156,11 +260,7 @@ 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 ()@@ -174,50 +274,77 @@ parenSplice :: Exp () -> Splice () parenSplice = ParenSplice () +bracketExp :: Bracket () -> Exp () bracketExp = BracketExp ()-typeBracket = TypeBracket () +typeBracket :: Type () -> Bracket ()+typeBracket = TypeBracket () -#if MIN_VERSION_haskell_src_exts(1,20,0)+mkDeriving :: [InstRule ()] -> Deriving () mkDeriving = Deriving () Nothing-#else-mkDeriving = Deriving ()-#endif +irule ::+ Maybe [TyVarBind ()] ->+ Maybe (Context ()) ->+ InstHead () ->+ InstRule () irule = IRule () +ihcon :: QName () -> InstHead () ihcon = IHCon () +evar :: QName () -> ExportSpec () evar = EVar ()++eabs :: Namespace () -> QName () -> ExportSpec () eabs = EAbs ()++ethingwith ::+ EWildcard () ->+ QName () ->+ [Language.Haskell.Exts.Syntax.CName ()] ->+ ExportSpec () ethingwith = EThingWith () +ethingall :: QName () -> ExportSpec () ethingall q = ethingwith (EWildcard () 0) q [] +emodule :: String -> ExportSpec () emodule nm = EModuleContents () (ModuleName () nm) +nonamespace :: Namespace () nonamespace = NoNamespace () +insType :: Type () -> Type () -> InstDecl () insType = InsType () +insDecl :: Decl () -> InstDecl () insDecl = InsDecl () +generator :: Pat () -> Exp () -> Stmt () generator = Generator () +qualifier :: Exp () -> Stmt () qualifier = Qualifier () +clsDecl :: Decl () -> ClassDecl () clsDecl = ClsDecl () -+unkindedVar :: Name () -> TyVarBind () unkindedVar = UnkindedVar () +op :: String -> QOp () op = QVarOp () . UnQual () . Symbol () +inapp :: Exp () -> QOp () -> Exp () -> Exp () inapp = InfixApp () +if_ :: Exp () -> Exp () -> Exp () -> Exp () if_ = If () +urhs :: Exp () -> Rhs () urhs = UnGuardedRhs () --- case pattern match p -> e+-- | case pattern match p -> e+match :: Pat () -> Exp () -> Alt () match p e = Alt () p (urhs e) Nothing