Skip to content

Commit bb42cd4

Browse files
committed
allow submodules to have the same name as path components
1 parent 0a9b6f7 commit bb42cd4

File tree

5 files changed

+46
-23
lines changed

5 files changed

+46
-23
lines changed

inline-rust.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ library
4747
, ScopedTypeVariables
4848

4949
build-depends: base >=4.9 && <5.0
50-
, extra >=0.5
5150
, language-rust >=0.2.0
5251
, prettyprinter >=1.1
5352
, process >=1.4
@@ -82,6 +81,7 @@ test-suite spec
8281
, FunctionPointerTypes
8382
, PreludeTypes
8483
, AlgebraicDataTypes
84+
, Submodule
8585
, Submodule.Submodule
8686
build-depends: base
8787
, inline-rust

src/Language/Rust/Inline/Internal.hs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,15 @@ import Language.Rust.Inline.Context
3030
import Language.Haskell.TH
3131
import Language.Haskell.TH.Syntax
3232

33-
import Control.Monad ( when, forM, forM_ )
33+
import Control.Monad ( filterM, forM, forM_, when )
3434
import Data.Typeable ( Typeable )
3535
import Data.Monoid ( Endo(..) )
3636
import Data.Maybe ( fromMaybe )
3737
import Data.List ( nub, unfoldr )
38-
import Data.Char ( isAlpha, isAlphaNum, isUpperCase )
38+
import Data.Char ( isAlpha, isAlphaNum, isUpper )
3939

4040
import 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 )
4342
import System.Process ( spawnProcess, readProcess, waitForProcess )
4443
import System.Exit ( ExitCode(..) )
4544
import 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.
6463
initCodeBlocks :: Maybe [(String,String)] -- ^ dependencies, if crate root
65-
-> Q ()
64+
-> Q ()
6665
initCodeBlocks 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'.
8584
emitCodeBlock :: String -> Q [Dec]
8685
emitCodeBlock 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]
125124
extendContext 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

tests/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import PointerTypes
1616
import FunctionPointerTypes
1717
import PreludeTypes
1818
import AlgebraicDataTypes
19+
import Submodule
1920
import Submodule.Submodule
2021
import Data.Word
2122
import Test.Hspec
@@ -35,3 +36,4 @@ main = hspec $
3536
preludeTypes
3637
algebraicDataTypes
3738
submoduleTest
39+
subsubmoduleTest

tests/Submodule.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{-# LANGUAGE QuasiQuotes #-}
2+
{-# LANGUAGE TemplateHaskell #-}
3+
4+
module Submodule where
5+
6+
import Data.Int
7+
import Data.Word
8+
import Language.Rust.Inline
9+
import Test.Hspec
10+
11+
extendContext basic
12+
setCrateModule
13+
14+
submoduleTest :: Spec
15+
submoduleTest = describe "Submodules" $ it "Can link against submodules" $ [rust| i32 { 42 } |] `shouldBe` 42

tests/Submodule/Submodule.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ import Test.Hspec
1111
extendContext basic
1212
setCrateModule
1313

14-
submoduleTest :: Spec
15-
submoduleTest = describe "Submodules" $ it "Can link against submodules" $ [rust| i32 { 42 } |] `shouldBe` 42
14+
subsubmoduleTest :: Spec
15+
subsubmoduleTest = describe "Subsubmodules" $ it "Can link against subsubmodules" $ [rust| i32 { 42 } |] `shouldBe` 42

0 commit comments

Comments
 (0)