@@ -27,14 +27,15 @@ import qualified Language.PureScript as P
2727
2828import Data.Char (isSpace)
2929import Data.Function (on)
30−import Data.List (sort, stripPrefix, intercalate, groupBy, sortBy, partition)
30+import Data.List (sort, stripPrefix, intercalate, groupBy, sortBy)
3131import Data.Maybe (mapMaybe)
3232import Data.Time.Clock (UTCTime())
33+import Data.Tuple (swap)
3334
3435import qualified Data.Map as M
3536
3637import Control.Monad
37−import Control.Arrow ((>>>))
38+import Control.Arrow ((***), (>>>))
3839
3940import Control.Monad.Reader
4041import Control.Monad.Writer.Strict
@@ -57,7 +58,7 @@ main = hspec spec
5758spec :: Spec
5859spec = do
5960
60− (supportExterns, supportForeigns, passingTestCases, failingTestCases) <- runIO $ do
61+ (supportExterns, passingTestCases, failingTestCases) <- runIO $ do
6162 cwd <- getCurrentDirectory
6263 let passing = cwd </> "examples" </> "passing"
6364 let failing = cwd </> "examples" </> "failing"
@@ -66,49 +67,40 @@ spec = do
6667 passingFiles <- getTestFiles passing <$> testGlob passing
6768 failingFiles <- getTestFiles failing <$> testGlob failing
6869 supportPurs <- supportFiles "purs"
69− supportForeigns <- loadForeigns =<< supportFiles "js"
7070 supportPursFiles <- readInput supportPurs
7171 supportExterns <- runExceptT $ do
7272 modules <- ExceptT . return $ P.parseModulesFromFiles id supportPursFiles
73− externs <- ExceptT . runTest $ P.make (makeActions supportForeigns) (map snd modules)
73+ foreigns <- inferForeignModules modules
74+ externs <- ExceptT . runTest $ P.make (makeActions foreigns) (map snd modules)
7475 return (zip (map snd modules) externs)
7576 case supportExterns of
7677 Left errs -> fail (P.prettyPrintMultipleErrors False errs)
77− Right externs -> return (externs, supportForeigns, passingFiles, failingFiles)
78+ Right externs -> return (externs, passingFiles, failingFiles)
7879
7980 context ("Passing examples") $ do
80− forM_ passingTestCases $ \(testPurs, testJS) ->
81− it ("'" <> takeFileName (getTestMain testPurs) <> "' should compile and run without error") $ do
82− testForeigns <- loadForeigns testJS
83− assertCompiles supportExterns testPurs (supportForeigns <> testForeigns)
81+ forM_ passingTestCases $ \testPurs ->
82+ it ("'" <> takeFileName (getTestMain testPurs) <> "' should compile and run without error") $
83+ assertCompiles supportExterns testPurs
8484
8585 context ("Failing examples") $ do
86− forM_ failingTestCases $ \(testPurs, testJS) -> do
86+ forM_ failingTestCases $ \testPurs -> do
8787 let mainPath = getTestMain testPurs
8888 expectedFailures <- runIO $ getShouldFailWith mainPath
89− it ("'" <> takeFileName mainPath <> "' should fail with '" <> intercalate "', '" expectedFailures <> "'") $ do
90− testForeigns <- loadForeigns testJS
91− assertDoesNotCompile supportExterns testPurs (supportForeigns <> testForeigns) expectedFailures
89+ it ("'" <> takeFileName mainPath <> "' should fail with '" <> intercalate "', '" expectedFailures <> "'") $
90+ assertDoesNotCompile supportExterns testPurs expectedFailures
9291
9392 where
9493
9594 -- A glob for all purs and js files within a test directory
9695 testGlob :: FilePath -> IO [FilePath]
97− testGlob dir = join . fst <$> Glob.globDir (map Glob.compile ["**/*.purs", "**/*.js"]) dir
98−
99− -- Loads foreign modules from source files
100− loadForeigns :: [FilePath] -> IO (M.Map P.ModuleName FilePath)
101− loadForeigns paths = do
102− files <- forM paths (\f -> (f,) <$> readUTF8File f)
103− Right (foreigns, _) <- runExceptT $ runWriterT $ P.parseForeignModulesFromFiles files
104− return foreigns
96+ testGlob = Glob.globDir1 (Glob.compile "**/*.purs")
10597
10698 -- Groups the test files so that a top-level file can have dependencies in a
10799 -- subdirectory of the same name. The inner tuple contains a list of the
108100 -- .purs files and the .js files for the test case.
109− getTestFiles :: FilePath -> [FilePath] -> [([FilePath], [FilePath])]
101+ getTestFiles :: FilePath -> [FilePath] -> [[FilePath]]
110102 getTestFiles baseDir
111− = map (partition ((== ".purs") . takeExtensions))
103+ = map (filter ((== ".purs") . takeExtensions))
112104 . map (map (baseDir </>))
113105 . groupBy ((==) `on` extractPrefix)
114106 . sortBy (compare `on` extractPrefix)
@@ -137,6 +129,15 @@ spec = do
137129 where
138130 extractFailWiths = lines >>> mapMaybe (stripPrefix "-- @shouldFailWith ") >>> map trim
139131
132+inferForeignModules
133+ :: MonadIO m
134+ => [(FilePath, P.Module)]
135+ -> m (M.Map P.ModuleName FilePath)
136+inferForeignModules = P.inferForeignModules . fromList
137+ where
138+ fromList :: [(FilePath, P.Module)] -> M.Map P.ModuleName (Either P.RebuildPolicy FilePath)
139+ fromList = M.fromList . map ((P.getModuleName *** Right) . swap)
140+
140141trim :: String -> String
141142trim = dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse
142143
@@ -175,12 +176,12 @@ runTest = fmap fst . P.runMake P.defaultOptions
175176compile
176177 :: [(P.Module, P.ExternsFile)]
177178 -> [FilePath]
178− -> M.Map P.ModuleName FilePath
179179 -> ([P.Module] -> IO ())
180180 -> IO (Either P.MultipleErrors [P.ExternsFile])
181−compile supportExterns inputFiles foreigns check = silence $ runTest $ do
181+compile supportExterns inputFiles check = silence $ runTest $ do
182182 fs <- liftIO $ readInput inputFiles
183183 ms <- P.parseModulesFromFiles id fs
184+ foreigns <- inferForeignModules ms
184185 liftIO (check (map snd ms))
185186 let actions = makeActions foreigns
186187 case ms of
@@ -190,22 +191,20 @@ compile supportExterns inputFiles foreigns check = silence $ runTest $ do
190191assert
191192 :: [(P.Module, P.ExternsFile)]
192193 -> [FilePath]
193− -> M.Map P.ModuleName FilePath
194194 -> ([P.Module] -> IO ())
195195 -> (Either P.MultipleErrors [P.ExternsFile] -> IO (Maybe String))
196196 -> Expectation
197−assert supportExterns inputFiles foreigns check f = do
198− e <- compile supportExterns inputFiles foreigns check
197+assert supportExterns inputFiles check f = do
198+ e <- compile supportExterns inputFiles check
199199 maybeErr <- f e
200200 maybe (return ()) expectationFailure maybeErr
201201
202202assertCompiles
203203 :: [(P.Module, P.ExternsFile)]
204204 -> [FilePath]
205− -> M.Map P.ModuleName FilePath
206205 -> Expectation
207−assertCompiles supportExterns inputFiles foreigns =
208− assert supportExterns inputFiles foreigns checkMain $ \e ->
206+assertCompiles supportExterns inputFiles = do
207+ assert supportExterns inputFiles checkMain $ \e ->
209208 case e of
210209 Left errs -> return . Just . P.prettyPrintMultipleErrors False $ errs
211210 Right _ -> do
@@ -228,11 +227,10 @@ assertCompiles supportExterns inputFiles foreigns =
228227assertDoesNotCompile
229228 :: [(P.Module, P.ExternsFile)]
230229 -> [FilePath]
231− -> M.Map P.ModuleName FilePath
232230 -> [String]
233231 -> Expectation
234−assertDoesNotCompile supportExterns inputFiles foreigns shouldFailWith =
235− assert supportExterns inputFiles foreigns noPreCheck $ \e ->
232+assertDoesNotCompile supportExterns inputFiles shouldFailWith = do
233+ assert supportExterns inputFiles noPreCheck $ \e ->
236234 case e of
237235 Left errs ->
238236 return $ if null shouldFailWith