@@ -30,16 +30,15 @@ import Language.Rust.Inline.Context
3030import Language.Haskell.TH
3131import Language.Haskell.TH.Syntax
3232
33- import Control.Monad ( when , forM , forM_ )
33+ import Control.Monad ( filterM , forM , forM_ , when )
3434import Data.Typeable ( Typeable )
3535import Data.Monoid ( Endo (.. ) )
3636import Data.Maybe ( fromMaybe )
3737import Data.List ( nub , unfoldr )
38- import Data.Char ( isAlpha , isAlphaNum , isUpperCase )
38+ import Data.Char ( isAlpha , isAlphaNum , isUpper )
3939
4040import System.FilePath ( (</>) , (<.>) , takeBaseName , takeDirectory , takeExtension )
41- import System.Directory ( copyFile , removeFile , createDirectoryIfMissing )
42- import System.Directory.Extra ( listFilesRecursive , listDirectories , listFiles )
41+ import System.Directory ( copyFile , removeFile , createDirectoryIfMissing , listDirectory , doesDirectoryExist , doesFileExist )
4342import System.Process ( spawnProcess , readProcess , waitForProcess )
4443import System.Exit ( ExitCode (.. ) )
4544import System.Environment ( setEnv )
@@ -62,14 +61,14 @@ newtype FFINames = FFINames [String]
6261-- | Initialize the 'CodeBlocks' of the current module. Crash if it is already
6362-- intialized. This must be called exactly once.
6463initCodeBlocks :: Maybe [(String ,String )] -- ^ dependencies, if crate root
65- -> Q ()
64+ -> Q ()
6665initCodeBlocks dependenciesOpt = do
6766 -- check if there is already something there
6867 cb <- getQ
6968 case cb of
7069 Nothing -> pure ()
7170 Just (CodeBlocks _) -> fail " initCodeBlocks: CodeBlocks already initialized"
72-
71+
7372 -- add hooks for writing out files (and possibly compiling the project)
7473 let finalizer = case dependenciesOpt of
7574 Nothing -> fileFinalizer
@@ -84,7 +83,7 @@ initCodeBlocks dependenciesOpt = do
8483-- | Emit a raw 'String' of Rust code into the current 'ModuleState'.
8584emitCodeBlock :: String -> Q [Dec ]
8685emitCodeBlock code = do
87- Just (CodeBlocks cbs) <- getQ
86+ Just (CodeBlocks cbs) <- getQ
8887 putQ (CodeBlocks (cbs . showString code . showString " \n " ))
8988 pure []
9089
@@ -125,7 +124,7 @@ extendContext :: Q Context -> Q [Dec]
125124extendContext qExtension = do
126125 extension <- qExtension
127126 ctx <- getContext
128- putQ (ctx <> extension)
127+ putQ (ctx <> extension)
129128 pure []
130129
131130-- | Search in a 'Context' for the Haskell type corresponding to a Rust type.
@@ -156,16 +155,23 @@ cargoFinalizer extraArgs dependencies = do
156155 srcDir = pkgDir </> " src"
157156 crate = " quasiquote_" ++ pkg
158157
159- nameFiles <- filter ((" .ffinames" == ) . takeExtension) <$> runIO (listFilesRecursive srcDir)
158+ nameFiles <- fmap (srcDir </> ) . filter ((" .ffinames" == ) . takeExtension) <$> runIO (listDirectory srcDir)
160159
161160 let modDir dir = do
162- subdirs <- listDirectories dir
163- mapM_ modDir subdirs
164- srcs <- filter (\ file -> takeExtension file == " .rs" && isUpperCase (head $ takeBaseName file)) <$> listFiles dir
165- let modules = nub $ takeBaseName <$> (subdirs <> srcs)
166- writeFile (dir </> " mod.rs" ) . unlines . concat $ [ [" " , " pub mod " <> name <> " ;" , " pub use self::" <> name <> " ::*;" ]
161+ entries <- fmap (dir </> ) <$> listDirectory dir
162+ modDirs <- filterM doesDirectoryExist entries
163+ let modSrcs = filter (\ f -> takeExtension f == " .rs" && isUpper (head $ takeBaseName f)) entries
164+ mapM_ modDir modDirs
165+ let modules = nub $ takeBaseName <$> (modDirs <> modSrcs)
166+ writeFile (dir </> " mod.rs" ) . unlines . concat $ [ [" pub mod " <> name <> " ;" , " pub use self::" <> name <> " ::*;" , " " ]
167167 | name <- modules
168168 ]
169+ let currentModSrc = takeDirectory dir </> (takeBaseName dir <.> " rs" )
170+ currentModSrcExists <- doesFileExist currentModSrc
171+ when currentModSrcExists $ do
172+ currentModContents <- readFile currentModSrc
173+ removeFile currentModSrc
174+ appendFile (dir </> " mod.rs" ) currentModContents
169175
170176 runIO $ do
171177 modDir srcDir
@@ -216,13 +222,13 @@ cargoFinalizer extraArgs dependencies = do
216222 let cargoArgs = [ " build"
217223 , " --release"
218224 , " --manifest-path=" ++ cargoToml
219- ] ++ extraArgs
225+ ] ++ extraArgs
220226 msgFormat = [ " --message-format=json" ]
221227
222228 ec <- runIO $ spawnProcess " cargo" cargoArgs >>= waitForProcess
223229 when (ec /= ExitSuccess )
224230 (reportError rustcErrMsg)
225-
231+
226232 -- Run Cargo again to get the static library path
227233 jOuts <- runIO $ readProcess " cargo" (cargoArgs ++ msgFormat) " "
228234
@@ -263,12 +269,12 @@ fileFinalizer = do
263269
264270 let pkgDir = " .inline-rust" </> pkg
265271 srcDir = pkgDir </> " src"
266- thisFile = foldr1 (</>) mods
272+ modDir = foldr1 (</>) mods
267273
268274 -- Figure out what we are putting into this file
269275 Just cb <- getQ
270276 Just (Context (_,_,impls)) <- getQ
271- let code = showsCodeBlocks cb
277+ let code = showsCodeBlocks cb
272278 . showString " pub mod marshal {\n "
273279 . showString " #[allow(unused_imports)] use super::*;\n "
274280 . showString " pub trait MarshalInto<T> { fn marshal(self) -> T; }\n "
@@ -278,8 +284,8 @@ fileFinalizer = do
278284 $ " "
279285
280286 -- Write out the file
281- let filepath = srcDir </> thisFile <.> " rs"
282- let namesFile = srcDir </> thisFile <.> " ffinames"
287+ let filepath = srcDir </> modDir <.> " . rs"
288+ let namesFile = srcDir </> foldr1 (<.>) mods <.> " ffinames"
283289 Just (FFINames names) <- getQ
284290 runIO $ do
285291 createDirectoryIfMissing True $ takeDirectory filepath
0 commit comments