@@ -24,6 +24,8 @@ module Language.PureScript
24 , compile'
24 , compile'
25 , RebuildPolicy(..)
25 , RebuildPolicy(..)
26 , MakeActions(..)
26 , MakeActions(..)
@@ -46,7 +48,7 @@ import Control.Monad.Supply.Class (fresh)
47import Language.PureScript.AST as P
49import Language.PureScript.AST as P
48import Language.PureScript.Comments as P
50import Language.PureScript.Comments as P
49−import Language.PureScript.CodeGen
51+import Language.PureScript.CodeGen.Externs (moduleToPs)
50import Language.PureScript.DeadCodeElimination as P
52import Language.PureScript.DeadCodeElimination as P
51import Language.PureScript.Environment as P
53import Language.PureScript.Environment as P
52import Language.PureScript.Errors as P
54import Language.PureScript.Errors as P
@@ -87,11 +89,11 @@ import qualified Paths_purescript as Paths
87-- * Pretty-print the generated Javascript
89-- * Pretty-print the generated Javascript
89compile :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m, MonadReader (Options Compile) m)
91compile :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m, MonadReader (Options Compile) m)
90− => [Module] -> m ([CoreFn.Module CoreFn.Ann], String, Environment, Integer)
92+ => [Module] -> m ([CoreFn.Module CoreFn.Ann], Environment, SupplyVar, Externs)
91compile = compile' initEnvironment
93compile = compile' initEnvironment
93compile' :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m, MonadReader (Options Compile) m)
95compile' :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m, MonadReader (Options Compile) m)
94− => Environment -> [Module] -> m ([CoreFn.Module CoreFn.Ann], String, Environment, Integer)
96+ => Environment -> [Module] -> m ([CoreFn.Module CoreFn.Ann], Environment, SupplyVar, Externs)
95compile' env ms = do
97compile' env ms = do
96 noPrelude <- asks optionsNoPrelude
98 noPrelude <- asks optionsNoPrelude
97 unless noPrelude (checkPreludeIsDefined ms)
99 unless noPrelude (checkPreludeIsDefined ms)
@@ -108,40 +110,48 @@ compile' env ms = do
108 renamed = renameInModules elim
110 renamed = renameInModules elim
109 codeGenModuleNames = moduleNameFromString `map` codeGenModules additional
111 codeGenModuleNames = moduleNameFromString `map` codeGenModules additional
110 modulesToCodeGen = if null codeGenModuleNames then renamed else filter (\(CoreFn.Module _ mn _ _ _ _) -> mn `elem` codeGenModuleNames) renamed
112 modulesToCodeGen = if null codeGenModuleNames then renamed else filter (\(CoreFn.Module _ mn _ _ _ _) -> mn `elem` codeGenModuleNames) renamed
111− let exts = intercalate "\n" . map (`moduleToPs` env') $ regrouped
113+ exts = intercalate "\n" . map (`moduleToPs` env') $ regrouped
112− return (modulesToCodeGen, exts, env', nextVar)
114+ return (modulesToCodeGen, env', nextVar, exts)
115−-- A type class which collects the IO actions we need to be able to run in "make" mode
117+-- Actions that require implementations when running in "make" mode.
117−--class (MonadReader (P.Options P.Make) m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => MonadMake m where
119−-- -- Get a file timestamp
121−-- getTimestamp :: FilePath -> m (Maybe UTCTime)
124−-- -- Read a file as a string
126−-- readTextFile :: FilePath -> m String
129−-- -- Write a text file
131−-- writeTextFile :: FilePath -> String -> m ()
134−-- -- Respond to a progress update
136−-- progress :: String -> m ()
138−data MakeActions m = MakeActions
119+data MakeActions m = MakeActions {
121+ -- Get the timestamp for the input file(s) for a module. If there are multiple
122+ -- files (.purs and foreign files, for example) the timestamp should be for
123+ -- the most recently modified file.
139− { getInputTimestamp :: ModuleName -> m (Either RebuildPolicy (Maybe UTCTime))
125+ getInputTimestamp :: ModuleName -> m (Either RebuildPolicy (Maybe UTCTime))
127+ -- Get the timestamp for the output files for a module. This should be the
128+ -- timestamp for the oldest modified file, or Nothing if any of the required
129+ -- output files are missing.
140− , getOutputTimestamp :: ModuleName -> m (Maybe UTCTime)
131+ , getOutputTimestamp :: ModuleName -> m (Maybe UTCTime)
133+ -- Read the externs file for a module as a string and also return the actual
134+ -- path for the file.
141− , readExterns :: ModuleName -> m (FilePath, String)
135+ , readExterns :: ModuleName -> m (FilePath, String)
137+ -- Run the code generator for the module and write any required output files.
142− , codegen :: CoreFn.Module CoreFn.Ann -> String -> Environment -> Integer -> m ()
139+ , codegen :: CoreFn.Module CoreFn.Ann -> Environment -> SupplyVar -> Externs -> m ()
143− , progress :: String -> m ()
140+ -- |
144− }
141+ -- Respond to a progress update.
143+ , progress :: String -> m ()
147+-- Generated code for an externs file.
149+type Externs = String
152+-- A value to be used in the Supply monad.
154+type SupplyVar = Integer
147-- Determines when to rebuild a module
157-- Determines when to rebuild a module
@@ -186,16 +196,15 @@ make MakeActions{..} ms = do
186 (_, env') <- lift . runCheck' env $ typeCheckModule Nothing m
196 (_, env') <- lift . runCheck' env $ typeCheckModule Nothing m
187 go env' ms'
197 go env' ms'
188 go env ((True, m@(Module coms moduleName' _ exps)) : ms') = do
198 go env ((True, m@(Module coms moduleName' _ exps)) : ms') = do
190 lift $ progress $ "Compiling " ++ runModuleName moduleName'
199 lift $ progress $ "Compiling " ++ runModuleName moduleName'
191 (Module _ _ elaborated _, env') <- lift . runCheck' env $ typeCheckModule Nothing m
200 (Module _ _ elaborated _, env') <- lift . runCheck' env $ typeCheckModule Nothing m
192 regrouped <- createBindingGroups moduleName' . collapseBindingGroups $ elaborated
201 regrouped <- createBindingGroups moduleName' . collapseBindingGroups $ elaborated
193 let mod' = Module coms moduleName' regrouped exps
202 let mod' = Module coms moduleName' regrouped exps
194 corefn = CoreFn.moduleToCoreFn env' mod'
203 corefn = CoreFn.moduleToCoreFn env' mod'
195 [renamed] = renameInModules [corefn]
204 [renamed] = renameInModules [corefn]
196− let exts = moduleToPs mod' env'
205+ exts = moduleToPs mod' env'
197 nextVar <- fresh
206 nextVar <- fresh
198− lift $ codegen renamed exts env' nextVar
207+ lift $ codegen renamed env' nextVar exts
199 go env' ms'
208 go env' ms'
201 rebuildIfNecessary :: M.Map ModuleName [ModuleName] -> S.Set ModuleName -> [Module] -> m [(Bool, Module)]
210 rebuildIfNecessary :: M.Map ModuleName [ModuleName] -> S.Set ModuleName -> [Module] -> m [(Bool, Module)]