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.Module as Module
25import qualified Elm.Compiler.Objects as Obj
26import qualified Elm.Interface as I
27import qualified Elm.Name as N
28import qualified Elm.Package as Pkg
30import qualified Elm.Project.Json as Project
31import qualified Elm.Project.Summary as Summary
32import qualified File.Args as Args
33import qualified File.Crawl as Crawl
34import qualified File.IO as IO
35import qualified Generate.Functions as Functions
36import qualified Generate.Html as Html
37import qualified Generate.Nitpick as Nitpick
38import qualified Generate.JavaScript.Mode as Mode
39import qualified Reporting.Exit as Exit
40import qualified Reporting.Exit.Make as E
41import qualified Reporting.Task as Task
42import qualified Stuff.Paths as Paths
43import Terminal.Args (Parser(..))
50data Mode = Debug | Dev | Prod
53generate :: Mode -> Mode.Target -> Maybe Output -> Summary.Summary -> Crawl.Result -> Task.Task ()
54generate mode target maybeOutput summary graph@(Crawl.Graph args _ _ _ _) =
59 Args.Roots name names ->
60 do objectGraph <- organize summary graph
64 Debug -> return (Mode.debug target (error "TODO"))
65 Dev -> return (Mode.dev target)
67 do noDebugUses summary objectGraph
68 return (Mode.prod target objectGraph)
70 generateMonolith realMode maybeOutput summary objectGraph (name:names)
77generateMonolith :: Mode.Mode -> Maybe Output -> Summary.Summary -> Obj.Graph -> [Module.Raw] -> Task.Task ()
78generateMonolith mode maybeOutput (Summary.Summary _ project _ _ _) graph rootNames =
79 do let pkg = Project.getName project
80 let roots = map (Module.Canonical pkg) rootNames
81 case Obj.generate mode graph roots of
85 Obj.Some name _names builder ->
88 "(function(scope){\n'use strict';"
89 <> Functions.functions <> builder <> "}(this));"
94 IO.writeBuilder "elm.js" monolith
101 JavaScript maybeDir fileName ->
102 do path <- toWritablePath maybeDir fileName
103 IO.writeBuilder path monolith
106 putMVar mvar (Html.sandwich name monolith)
108 Html maybeDir fileName ->
109 do path <- toWritablePath maybeDir fileName
110 IO.writeBuilder path (Html.sandwich name monolith)
114-- GENERATE REPL MONOLITH
117generateReplFile :: Summary.Summary -> Crawl.Result -> I.Interface -> N.Name -> Task.Task FilePath
118generateReplFile summary@(Summary.Summary _ project _ _ _) graph iface name =
120 objectGraph <- organize summary graph
122 let home = Module.Canonical (Project.getName project) "Elm_Repl"
123 let builder = Obj.generateForRepl objectGraph iface home name
125 liftIO $ IO.writeBuilder (Paths.temp "js") $
126 replRecovery <> "(function(){\n'use strict';" <> Functions.functions <> builder <> "}());"
128 return (Paths.temp "js")
131replRecovery :: B.Builder
133 "process.on('uncaughtException', function(err) { process.stderr.write(err.toString()); process.exit(1); });"
140organize :: Summary.Summary -> Crawl.Result -> Task.Task Obj.Graph
141organize (Summary.Summary root _ _ _ deps) (Crawl.Graph _ locals _ _ _) =
142 do localObjs <- Obj.unions <$> traverse (loadModuleObj root) (Map.keys locals)
143 foreignObjs <- Obj.unions <$> traverse loadPackageObj (Map.toList deps)
144 return (Obj.union localObjs foreignObjs)
147loadModuleObj :: FilePath -> Module.Raw -> Task.Task Obj.Graph
148loadModuleObj root name =
149 IO.readBinary (Paths.elmo root name)
152loadPackageObj :: ( Pkg.Name, (Pkg.Version, deps) ) -> Task.Task Obj.Graph
153loadPackageObj ( name, (version,_) ) =
154 do dir <- Task.getPackageCacheDirFor name version
155 IO.readBinary (dir </> "objs.dat")
162noDebugUses :: Summary.Summary -> Obj.Graph -> Task.Task ()
163noDebugUses (Summary.Summary _ project _ _ _) graph =
164 case Nitpick.findDebugUses (Project.getName project) graph of
169 Task.throw (Exit.Make (E.CannotOptimizeDebugValues m ms))
172noDebugUsesInPackage :: Summary.Summary -> Crawl.Result -> Task.Task ()
173noDebugUsesInPackage summary graph =
174 noDebugUses summary =<< organize summary graph
183 | Html (Maybe FilePath) FilePath
184 | JavaScript (Maybe FilePath) FilePath
185 | HtmlBuilder (MVar B.Builder)
188toWritablePath :: Maybe FilePath -> FilePath -> IO FilePath
189toWritablePath maybeDir fileName =
195 do Dir.createDirectoryIfMissing True dir
196 return (dir </> fileName)
203output :: Parser Output
206 { _singular = "output file"
207 , _plural = "output files"
208 , _parser = parseOutput
209 , _suggest = \_ -> return []
210 , _examples = exampleOutput
214parseOutput :: String -> Maybe Output
216 if string == "/dev/null" || string == "NUL" || string == "$null" then
219 else if FP.takeExtension string == ".html" && length string > 5 then
220 splitOutput Html string
222 else if FP.takeExtension string == ".js" && length string > 3 then
223 splitOutput JavaScript string
229splitOutput :: (Maybe FilePath -> FilePath -> Output) -> String -> Maybe Output
230splitOutput toOutput string =
231 case FP.splitPath string of
236 Just $ toOutput Nothing name
239 Just $ toOutput (Just (FP.joinPath (init segments))) (last segments)
242exampleOutput :: String -> IO [String]
244 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