@@ -41,8 +41,7 @@ import Control.Monad
41import Control.Monad.Error.Class (MonadError(..))
41import Control.Monad.Error.Class (MonadError(..))
42import Control.Monad.Reader
42import Control.Monad.Reader
43import Control.Monad.Writer
43import Control.Monad.Writer
44−
44+import Control.Monad.Supply.Class (fresh)
45−import System.FilePath ((</>))
47import Language.PureScript.AST as P
46import Language.PureScript.AST as P
48import Language.PureScript.Comments as P
47import Language.PureScript.Comments as P
@@ -144,11 +143,6 @@ data RebuildPolicy
144 -- | Always rebuild this module
143 -- | Always rebuild this module
145 | RebuildAlways deriving (Show, Eq, Ord)
144 | RebuildAlways deriving (Show, Eq, Ord)
147−-- Traverse (Either e) instance (base 4.7)
148−traverseEither :: Applicative f => (a -> f b) -> Either e a -> f (Either e b)
149−traverseEither _ (Left x) = pure (Left x)
150−traverseEither f (Right y) = Right <$> f y
153-- Compiles in "make" mode, compiling each module separately to a js files and an externs file
147-- Compiles in "make" mode, compiling each module separately to a js files and an externs file
@@ -156,67 +150,46 @@ traverseEither f (Right y) = Right <$> f y
156-- having to typecheck the module again.
150-- having to typecheck the module again.
158make :: forall m. (Functor m, Applicative m, Monad m, MonadMake m)
152make :: forall m. (Functor m, Applicative m, Monad m, MonadMake m)
159− => FilePath -> [(Either RebuildPolicy FilePath, Module)] -> [String] -> m Environment
153+ => (ModuleName -> m (Either RebuildPolicy (Maybe UTCTime)))
160−make outputDir ms prefix = do
154+ -> (ModuleName -> m (Maybe UTCTime))
155+ -> (ModuleName -> m (FilePath, String))
156+ -> (CoreFn.Module CoreFn.Ann -> String -> Environment -> Integer -> m ())
157+ -> [(Either RebuildPolicy FilePath, Module)]
159+make getInputTimestamp getOutputTimestamp readExterns codegen ms = do
161 noPrelude <- asks optionsNoPrelude
160 noPrelude <- asks optionsNoPrelude
162 unless noPrelude (checkPreludeIsDefined (map snd ms))
161 unless noPrelude (checkPreludeIsDefined (map snd ms))
163− let filePathMap = M.fromList (map (\(fp, Module _ mn _ _) -> (mn, fp)) ms)
165 (sorted, graph) <- sortModules $ map importPrim $ if noPrelude then map snd ms else map (importPrelude . snd) ms
162 (sorted, graph) <- sortModules $ map importPrim $ if noPrelude then map snd ms else map (importPrelude . snd) ms
167 mapM_ lint sorted
163 mapM_ lint sorted
169 toRebuild <- foldM (\s (Module _ moduleName' _ _) -> do
164 toRebuild <- foldM (\s (Module _ moduleName' _ _) -> do
170− let filePath = runModuleName moduleName'
165+ inputTimestamp <- getInputTimestamp moduleName'
171−
166+ outputTimestamp <- getOutputTimestamp moduleName'
172− jsFile = outputDir </> filePath </> "index.js"
173− externsFile = outputDir </> filePath </> "externs.purs"
174− inputFile = fromMaybe (error "Module has no filename in 'make'") $ M.lookup moduleName' filePathMap
176− jsTimestamp <- getTimestamp jsFile
177− externsTimestamp <- getTimestamp externsFile
178− inputTimestamp <- traverseEither getTimestamp inputFile
180− return $ case (inputTimestamp, jsTimestamp, externsTimestamp) of
167+ return $ case (inputTimestamp, outputTimestamp) of
181− (Right (Just t1), Just t2, Just t3) | t1 < min t2 t3 -> s
168+ (Right (Just t1), Just t2) | t1 < t2 -> s
182− (Left RebuildNever, Just _, Just _) -> s
169+ (Left RebuildNever, Just _) -> s
183 _ -> S.insert moduleName' s) S.empty sorted
170 _ -> S.insert moduleName' s) S.empty sorted
185 marked <- rebuildIfNecessary (reverseDependencies graph) toRebuild sorted
172 marked <- rebuildIfNecessary (reverseDependencies graph) toRebuild sorted
187 (desugared, nextVar) <- runSupplyT 0 $ zip (map fst marked) <$> desugar (map snd marked)
173 (desugared, nextVar) <- runSupplyT 0 $ zip (map fst marked) <$> desugar (map snd marked)
189 evalSupplyT nextVar $ go initEnvironment desugared
174 evalSupplyT nextVar $ go initEnvironment desugared
192 go :: Environment -> [(Bool, Module)] -> SupplyT m Environment
177 go :: Environment -> [(Bool, Module)] -> SupplyT m Environment
193 go env [] = return env
178 go env [] = return env
194 go env ((False, m) : ms') = do
179 go env ((False, m) : ms') = do
195 (_, env') <- lift . runCheck' env $ typeCheckModule Nothing m
180 (_, env') <- lift . runCheck' env $ typeCheckModule Nothing m
197 go env' ms'
181 go env' ms'
198 go env ((True, m@(Module coms moduleName' _ exps)) : ms') = do
182 go env ((True, m@(Module coms moduleName' _ exps)) : ms') = do
199− let filePath = runModuleName moduleName'
200− jsFile = outputDir </> filePath </> "index.js"
201− externsFile = outputDir </> filePath </> "externs.purs"
203 lift . progress $ "Compiling " ++ runModuleName moduleName'
184 lift . progress $ "Compiling " ++ runModuleName moduleName'
205 (Module _ _ elaborated _, env') <- lift . runCheck' env $ typeCheckModule Nothing m
185 (Module _ _ elaborated _, env') <- lift . runCheck' env $ typeCheckModule Nothing m
207 regrouped <- createBindingGroups moduleName' . collapseBindingGroups $ elaborated
186 regrouped <- createBindingGroups moduleName' . collapseBindingGroups $ elaborated
209 let mod' = Module coms moduleName' regrouped exps
187 let mod' = Module coms moduleName' regrouped exps
210 corefn = CoreFn.moduleToCoreFn env' mod'
188 corefn = CoreFn.moduleToCoreFn env' mod'
211 [renamed] = renameInModules [corefn]
189 [renamed] = renameInModules [corefn]
212−
190+ let exts = moduleToPs mod' env'
213− pjs <- prettyPrintJS <$> moduleToJs renamed Nothing
191+ nextVar <- fresh
214− let js = unlines $ map ("// " ++) prefix ++ [pjs]
192+ lift $ codegen renamed exts env' nextVar
215− let exts = unlines $ map ("-- " ++) prefix ++ [moduleToPs mod' env']
217− lift $ writeTextFile jsFile js
218− lift $ writeTextFile externsFile exts
220 go env' ms'
193 go env' ms'
222 rebuildIfNecessary :: M.Map ModuleName [ModuleName] -> S.Set ModuleName -> [Module] -> m [(Bool, Module)]
195 rebuildIfNecessary :: M.Map ModuleName [ModuleName] -> S.Set ModuleName -> [Module] -> m [(Bool, Module)]
@@ -226,12 +199,11 @@ make outputDir ms prefix = do
226 toRebuild' = toRebuild `S.union` S.fromList deps
199 toRebuild' = toRebuild `S.union` S.fromList deps
227 (:) (True, m) <$> rebuildIfNecessary graph toRebuild' ms'
200 (:) (True, m) <$> rebuildIfNecessary graph toRebuild' ms'
228 rebuildIfNecessary graph toRebuild (Module _ moduleName' _ _ : ms') = do
201 rebuildIfNecessary graph toRebuild (Module _ moduleName' _ _ : ms') = do
229− let externsFile = outputDir </> runModuleName moduleName' </> "externs.purs"
202+ (path, externs) <- readExterns moduleName'
230− externs <- readTextFile externsFile
231− externsModules <- fmap (map snd) . alterErrors $ P.parseModulesFromFiles id [(externsFile, externs)]
203+ externsModules <- fmap (map snd) . alterErrors $ P.parseModulesFromFiles id [(path, externs)]
232 case externsModules of
204 case externsModules of
233 [m'@(Module _ moduleName'' _ _)] | moduleName'' == moduleName' -> (:) (False, m') <$> rebuildIfNecessary graph toRebuild ms'
205 [m'@(Module _ moduleName'' _ _)] | moduleName'' == moduleName' -> (:) (False, m') <$> rebuildIfNecessary graph toRebuild ms'
234− _ -> throwError . errorMessage . InvalidExternsFile $ externsFile
206+ _ -> throwError . errorMessage . InvalidExternsFile $ path
236 alterErrors = flip catchError $ \(MultipleErrors errs) ->
208 alterErrors = flip catchError $ \(MultipleErrors errs) ->
237 throwError . MultipleErrors $ flip map errs $ \e -> case e of
209 throwError . MultipleErrors $ flip map errs $ \e -> case e of