1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
15import Control.Concurrent.MVar (MVar, putMVar)
16import Control.Monad.Trans (liftIO)
17import qualified Data.ByteString.Builder as B
18import qualified Data.Map as Map
19import Data.Monoid ((<>))
20import qualified System.Directory as Dir
21import qualified System.FilePath as FP
22import System.FilePath ((</>))
24import qualified Elm.Compiler as Compiler
25import qualified Elm.Compiler.Module as Module
26import qualified Elm.Compiler.Objects as Obj
27import qualified Elm.Interface as I
28import qualified Elm.Name as N
29import qualified Elm.Package as Pkg
31import qualified AST.Module.Name as ModuleName
32import qualified Elm.Project.Json as Project
33import qualified Elm.Project.Summary as Summary
34import qualified File.Args as Args
35import qualified File.Crawl as Crawl
36import qualified File.IO as IO
37import qualified Generate.Functions as Functions
38import qualified Generate.Html as Html
39import qualified Generate.Nitpick as Nitpick
40import qualified Generate.JavaScript.Mode as Mode
41import qualified Reporting.Exit as Exit
42import qualified Reporting.Exit.Make as E
43import qualified Reporting.Task as Task
44import qualified Stuff.Paths as Paths
45import Terminal.Args (Parser(..))
52data Mode = Debug | Dev | Prod
61 -> Map.Map Module.Raw Compiler.Artifacts
63generate mode target maybeOutput summary graph@(Crawl.Graph args _ _ _ _) artifacts =
68 Args.Roots name names ->
69 do objectGraph <- organize summary graph
74 return $ Mode.debug target (getInterfaces summary artifacts)
77 return $ Mode.dev target
80 do noDebugUses summary objectGraph
81 return $ Mode.prod target objectGraph
83 generateMonolith realMode maybeOutput summary objectGraph (name:names)
86getInterfaces :: Summary.Summary -> Map.Map Module.Raw Compiler.Artifacts -> I.Interfaces
87getInterfaces (Summary.Summary _ project _ interfaces _) artifacts =
89 pkg = Project.getName project
90 addArtifact home (Compiler.Artifacts elmi _ _) ifaces =
91 Map.insert (ModuleName.Canonical pkg home) elmi ifaces
93 Map.foldrWithKey addArtifact interfaces artifacts
107generateMonolith mode maybeOutput (Summary.Summary _ project _ _ _) graph rootNames =
108 do let pkg = Project.getName project
109 let roots = map (Module.Canonical pkg) rootNames
110 case Obj.generate mode graph roots of
114 Obj.Some name _names builder ->
117 "(function(scope){\n'use strict';"
118 <> Functions.functions <> builder <> "}(this));"
123 IO.writeBuilder "elm.js" monolith
130 JavaScript maybeDir fileName ->
131 do path <- toWritablePath maybeDir fileName
132 IO.writeBuilder path monolith
135 putMVar mvar (Html.sandwich name monolith)
137 Html maybeDir fileName ->
138 do path <- toWritablePath maybeDir fileName
139 IO.writeBuilder path (Html.sandwich name monolith)
143-- GENERATE REPL MONOLITH
146generateReplFile :: Summary.Summary -> Crawl.Result -> I.Interface -> N.Name -> Task.Task FilePath
147generateReplFile summary@(Summary.Summary _ project _ _ _) graph iface name =
149 objectGraph <- organize summary graph
151 let home = Module.Canonical (Project.getName project) "Elm_Repl"
152 let builder = Obj.generateForRepl True objectGraph iface home name
154 liftIO $ IO.writeBuilder (Paths.temp "js") $
155 replRecovery <> "(function(){\n'use strict';" <> Functions.functions <> builder <> "}());"
157 return (Paths.temp "js")
160replRecovery :: B.Builder
162 "process.on('uncaughtException', function(err) { process.stderr.write(err.toString()); process.exit(1); });"
169organize :: Summary.Summary -> Crawl.Result -> Task.Task Obj.Graph
170organize (Summary.Summary root _ _ _ deps) (Crawl.Graph _ locals _ _ _) =
171 do localObjs <- Obj.unions <$> traverse (loadModuleObj root) (Map.keys locals)
172 foreignObjs <- Obj.unions <$> traverse loadPackageObj (Map.toList deps)
173 return (Obj.union localObjs foreignObjs)
176loadModuleObj :: FilePath -> Module.Raw -> Task.Task Obj.Graph
177loadModuleObj root name =
178 IO.readBinary (Paths.elmo root name)
181loadPackageObj :: ( Pkg.Name, (Pkg.Version, deps) ) -> Task.Task Obj.Graph
182loadPackageObj ( name, (version,_) ) =
183 do dir <- Task.getPackageCacheDirFor name version
184 IO.readBinary (dir </> "objs.dat")
191noDebugUses :: Summary.Summary -> Obj.Graph -> Task.Task ()
192noDebugUses (Summary.Summary _ project _ _ _) graph =
193 case Nitpick.findDebugUses (Project.getName project) graph of
198 Task.throw (Exit.Make (E.CannotOptimizeDebugValues m ms))
201noDebugUsesInPackage :: Summary.Summary -> Crawl.Result -> Task.Task ()
202noDebugUsesInPackage summary graph =
203 noDebugUses summary =<< organize summary graph
212 | Html (Maybe FilePath) FilePath
213 | JavaScript (Maybe FilePath) FilePath
214 | HtmlBuilder (MVar B.Builder)
217toWritablePath :: Maybe FilePath -> FilePath -> IO FilePath
218toWritablePath maybeDir fileName =
224 do Dir.createDirectoryIfMissing True dir
225 return (dir </> fileName)
232output :: Parser Output
235 { _singular = "output file"
236 , _plural = "output files"
237 , _parser = parseOutput
238 , _suggest = \_ -> return []
239 , _examples = exampleOutput
243parseOutput :: String -> Maybe Output
245 if string == "/dev/null" || string == "NUL" || string == "$null" then
248 else if FP.takeExtension string == ".html" && length string > 5 then
249 splitOutput Html string
251 else if FP.takeExtension string == ".js" && length string > 3 then
252 splitOutput JavaScript string
258splitOutput :: (Maybe FilePath -> FilePath -> Output) -> String -> Maybe Output
259splitOutput toOutput string =
260 case FP.splitPath string of
265 Just $ toOutput Nothing name
268 Just $ toOutput (Just (FP.joinPath (init segments))) (last segments)
271exampleOutput :: String -> IO [String]
273 return [ "elm.js", "index.html", "/dev/null" ]
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list