on master help sign in
Add back --debug flag, only generate debugger in that case
commit6585f1faffb213a03d1fb0ed84d1486d99513a43 authorEvan Czaplicki <evancz@users.noreply.github.com> dateSun 8 Apr 2018, 14:22 (9 years ago) parenta36152c
10 files changed+171−97
builder/src/File/Args.hs+2−1 builder/src/Generate/Output.hs+3−1 builder/src/Reporting/Exit.hs+19−49 builder/src/Reporting/Exit/Make.hs+75 compiler/src/Generate/JavaScript.hs+11−8 compiler/src/Generate/JavaScript/Expression.hs+23−18 compiler/src/Generate/JavaScript/Name.hs+9−3 elm.cabal+1 ui/terminal/src/Main.hs+1 ui/terminal/src/Make.hs+27−17
builder/src/File/Args.hs+2−1
@@ -11,6 +11,7 @@ import qualified Elm.Compiler.Module as Module
1111import qualified Elm.Project.Json as Project
1212import qualified Elm.Project.Summary as Summary
1313import qualified Reporting.Exit as Exit
14+import qualified Reporting.Exit.Make as E
1415import qualified Reporting.Task as Task
1516
1617
@@ -36,4 +37,4 @@ fromSummary (Summary.Summary _ project _ _ _) =
3637 return $ Pkg (Project.getExposed info)
3738
3839 Project.App _ ->
39− Task.throw Exit.CannotMakeNothing
40+ Task.throw (Exit.Make E.CannotMakeNothing)
builder/src/Generate/Output.hs+3−1
@@ -34,6 +34,7 @@ import qualified Generate.Functions as Functions
3434import qualified Generate.Html as Html
3535import qualified Generate.Nitpick as Nitpick
3636import qualified Reporting.Exit as Exit
37+import qualified Reporting.Exit.Make as E
3738import qualified Reporting.Task as Task
3839import qualified Stuff.Paths as Paths
3940import Terminal.Args (Parser(..), suggestFiles)
@@ -61,6 +62,7 @@ generate options summary graph@(Crawl.Graph args _ _ _ _) =
6162 do objectGraph <- organize summary graph
6263
6364 case _mode options of
65+ Obj.Debug -> return ()
6466 Obj.Dev -> return ()
6567 Obj.Prod -> noDebugUses summary objectGraph
6668
@@ -163,7 +165,7 @@ noDebugUses (Summary.Summary _ project _ _ _) graph =
163165 return ()
164166
165167 m:ms ->
166− Task.throw (Exit.CannotOptimizeDebug m ms)
168+ Task.throw (Exit.Make (E.CannotOptimizeDebugValues m ms))
167169
168170
169171noDebugUsesInPackage :: Summary.Summary -> Crawl.Result -> Task.Task ()
builder/src/Reporting/Exit.hs+19−49
@@ -21,6 +21,7 @@ import qualified Reporting.Exit.Deps as Deps
2121import qualified Reporting.Exit.Diff as Diff
2222import qualified Reporting.Exit.Help as Help
2323import qualified Reporting.Exit.Http as Http
24+import qualified Reporting.Exit.Make as Make
2425import qualified Reporting.Exit.Publish as Publish
2526
2627
@@ -37,13 +38,12 @@ data Exit
3738 | Cycle [Module.Raw] -- TODO write docs to help with this scenario
3839 | Deps Deps.Exit
3940 | Diff Diff.Exit
41+ | Make Make.Exit
4042 | Publish Publish.Exit
4143 | BadHttp String Http.Exit
4244
4345 -- misc
4446 | NoSolution [Pkg.Name]
45− | CannotMakeNothing
46− | CannotOptimizeDebug Module.Raw [Module.Raw]
4747
4848
4949
@@ -86,17 +86,17 @@ toReport exit =
8686 "Whatever your scenario, I hope you have a lovely time using Elm!"
8787 ]
8888
89− Assets assetError ->
90− Asset.toReport assetError
89+ Assets assetExit ->
90+ Asset.toReport assetExit
9191
92− Bump bumpError ->
93− Bump.toReport bumpError
92+ Bump bumpExit ->
93+ Bump.toReport bumpExit
9494
9595 Compile e es ->
9696 Help.compilerReport e es
9797
98− Crawl crawlError ->
99− Crawl.toReport crawlError
98+ Crawl crawlExit ->
99+ Crawl.toReport crawlExit
100100
101101 Cycle names ->
102102 Help.report "IMPORT CYCLE" Nothing
@@ -107,17 +107,20 @@ toReport exit =
107107 ++ D.makeLink "import-cycles"
108108 ]
109109
110− Deps depsError ->
111− Deps.toReport depsError
110+ Deps depsExit ->
111+ Deps.toReport depsExit
112112
113− Diff commandsError ->
114− Diff.toReport commandsError
113+ Diff commandsExit ->
114+ Diff.toReport commandsExit
115115
116− Publish publishError ->
117− Publish.toReport publishError
116+ Make makeExit ->
117+ Make.toReport makeExit
118118
119− BadHttp url httpError ->
120− Http.toReport url httpError
119+ Publish publishExit ->
120+ Publish.toReport publishExit
121+
122+ BadHttp url httpExit ->
123+ Http.toReport url httpExit
121124
122125 NoSolution badPackages ->
123126 case badPackages of
@@ -148,36 +151,3 @@ toReport exit =
148151 \ goals, etc. They face obstacles outside of their technical work you will never\
149152 \ know about, so please assume the best and try to be patient and supportive!"
150153 ]
151−
152− CannotMakeNothing ->
153− Help.report "NO INPUT" Nothing
154− "What should I make though? I need more information, like:"
155− [ D.vcat
156− [ D.indent 4 $ D.green "elm make MyThing.elm"
157− , D.indent 4 $ D.green "elm make This.elm That.elm"
158− ]
159− , D.reflow
160− "However many files you give, I will create one JS file out of them."
161− ]
162−
163− CannotOptimizeDebug m ms ->
164− Help.report "DEBUG REMNANTS" Nothing
165− "There are uses of the `Debug` module in the following modules:"
166− [ D.indent 4 $ D.red $ D.vcat $ map (D.fromString . Module.nameToString) (m:ms)
167− , D.reflow "But the --optimize flag only works if all `Debug` functions are removed!"
168− , D.toSimpleNote $
169− "The issue is that --optimize strips out info needed by `Debug` functions.\
170− \ Here are two examples:"
171− , D.indent 4 $ D.reflow $
172− "(1) It shortens record field names. This makes the generated JavaScript is\
173− \ smaller, but `Debug.toString` cannot know the real field names anymore."
174− , D.indent 4 $ D.reflow $
175− "(2) Values like `type Height = Height Float` are unboxed. This reduces\
176− \ allocation, but it also means that `Debug.toString` cannot tell if it is\
177− \ looking at a `Height` or `Float` value."
178− , D.reflow $
179− "There are a few other cases like that, and it will be much worse once we start\
180− \ inlining code. That optimization could move `Debug.log` and `Debug.todo` calls,\
181− \ resulting in unpredictable behavior. I hope that clarifies why this restriction\
182− \ exists!"
183− ]
builder/src/Reporting/Exit/Make.hsnew file+75
@@ -0,0 +1,75 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Reporting.Exit.Make
3+ ( Exit(..)
4+ , toReport
5+ )
6+ where
7+
8+
9+import qualified Elm.Compiler.Module as Module
10+import qualified Reporting.Doc as D
11+import qualified Reporting.Exit.Help as Help
12+
13+
14+
15+-- EXITS
16+
17+
18+data Exit
19+ = CannotMakeNothing
20+ | CannotOptimizeDebugValues Module.Raw [Module.Raw]
21+ | CannotOptimizeAndDebug
22+
23+
24+
25+-- TO REPORT
26+
27+
28+toReport :: Exit -> Help.Report
29+toReport exit =
30+ case exit of
31+ CannotMakeNothing ->
32+ Help.report "NO INPUT" Nothing
33+ "What should I make though? I need more information, like:"
34+ [ D.vcat
35+ [ D.indent 4 $ D.green "elm make MyThing.elm"
36+ , D.indent 4 $ D.green "elm make This.elm That.elm"
37+ ]
38+ , D.reflow
39+ "However many files you give, I will create one JS file out of them."
40+ ]
41+
42+ CannotOptimizeDebugValues m ms ->
43+ Help.report "DEBUG REMNANTS" Nothing
44+ "There are uses of the `Debug` module in the following modules:"
45+ [ D.indent 4 $ D.red $ D.vcat $ map (D.fromString . Module.nameToString) (m:ms)
46+ , D.reflow "But the --optimize flag only works if all `Debug` functions are removed!"
47+ , D.toSimpleNote $
48+ "The issue is that --optimize strips out info needed by `Debug` functions.\
49+ \ Here are two examples:"
50+ , D.indent 4 $ D.reflow $
51+ "(1) It shortens record field names. This makes the generated JavaScript is\
52+ \ smaller, but `Debug.toString` cannot know the real field names anymore."
53+ , D.indent 4 $ D.reflow $
54+ "(2) Values like `type Height = Height Float` are unboxed. This reduces\
55+ \ allocation, but it also means that `Debug.toString` cannot tell if it is\
56+ \ looking at a `Height` or `Float` value."
57+ , D.reflow $
58+ "There are a few other cases like that, and it will be much worse once we start\
59+ \ inlining code. That optimization could move `Debug.log` and `Debug.todo` calls,\
60+ \ resulting in unpredictable behavior. I hope that clarifies why this restriction\
61+ \ exists!"
62+ ]
63+
64+ CannotOptimizeAndDebug ->
65+ Help.docReport "CLASHING FLAGS" Nothing
66+ ( D.fillSep
67+ ["I","cannot","compile","with",D.red "--optimize","and"
68+ ,D.red "--debug","at","the","same","time."
69+ ]
70+ )
71+ [ D.reflow
72+ "I need to take away information to optimize things, and I need to\
73+ \ add information to add the debugger. It is impossible to do both\
74+ \ at once, so pick just one of those flags."
75+ ]
compiler/src/Generate/JavaScript.hs+11−8
@@ -36,7 +36,7 @@ import qualified Reporting.Doc as D
3636-- GENERATE MAINS
3737
3838
39−data Mode = Dev | Prod
39+data Mode = Prod | Dev | Debug
4040
4141
4242data Output
@@ -71,8 +71,11 @@ addMain mode graph home _ state =
7171toRealMode :: Mode -> Name.Target -> Map.Map N.Name Int -> Name.Mode
7272toRealMode mode target fields =
7373 case mode of
74+ Debug ->
75+ Name.Dev target Name.DebuggerOn
76+
7477 Dev ->
75− Name.Dev target
78+ Name.Dev target Name.DebuggerOff
7679
7780 Prod ->
7881 Name.Prod target (Name.shortenFieldNames fields)
@@ -85,7 +88,7 @@ toRealMode mode target fields =
8588generateForRepl :: Opt.Graph -> I.Interface -> ModuleName.Canonical -> N.Name -> B.Builder
8689generateForRepl (Opt.Graph _ graph _) iface home name =
8790 let
88− mode = Name.Dev Name.Server
91+ mode = Name.Dev Name.Server Name.DebuggerOff
8992 debugState = addGlobal mode graph emptyState (Opt.Global ModuleName.debug "toString")
9093 evalState = addGlobal mode graph debugState (Opt.Global home name)
9194 in
@@ -238,7 +241,7 @@ generateCycle mode (Opt.Global home _) cycle =
238241 Name.Prod _ _ ->
239242 block
240243
241− Name.Dev _ ->
244+ Name.Dev _ _ ->
242245 JS.Try block Name.dollar $ JS.Throw $ JS.String $
243246 "The following top-level definitions are causing infinite recursion:\\n"
244247 <> drawCycle (map fst cycle)
@@ -310,7 +313,7 @@ addChunk mode builder chunk =
310313
311314 Opt.Debug ->
312315 case mode of
313− Name.Dev _ ->
316+ Name.Dev _ _ ->
314317 builder
315318
316319 Name.Prod _ _ ->
@@ -318,7 +321,7 @@ addChunk mode builder chunk =
318321
319322 Opt.Prod ->
320323 case mode of
321− Name.Dev _ ->
324+ Name.Dev _ _ ->
322325 "_UNUSED" <> builder
323326
324327 Name.Prod _ _ ->
@@ -334,7 +337,7 @@ generateEnum mode (Opt.Global home name) ctorName index =
334337 let
335338 definition =
336339 case mode of
337− Name.Dev _ ->
340+ Name.Dev _ _ ->
338341 Expr.codeToExpr (Expr.generateCtor mode ctorName index 0)
339342
340343 Name.Prod _ _ ->
@@ -352,7 +355,7 @@ generateBox mode (Opt.Global home name) ctorName =
352355 let
353356 definition =
354357 case mode of
355− Name.Dev _ ->
358+ Name.Dev _ _ ->
356359 Expr.codeToExpr (Expr.generateCtor mode ctorName Index.first 1)
357360
358361 Name.Prod _ _ ->
compiler/src/Generate/JavaScript/Expression.hs+23−18
@@ -58,7 +58,7 @@ generate mode expression =
5858 Opt.Chr char ->
5959 JsExpr $
6060 case mode of
61− Name.Dev _ ->
61+ Name.Dev _ _ ->
6262 JS.Call toChar [ JS.String (Text.encodeUtf8Builder char) ]
6363
6464 Name.Prod _ _ ->
@@ -81,7 +81,7 @@ generate mode expression =
8181
8282 Opt.VarEnum (Opt.Global home name) index ->
8383 case mode of
84− Name.Dev _ ->
84+ Name.Dev _ _ ->
8585 JsExpr $ JS.Ref (Name.fromGlobal home name)
8686
8787 Name.Prod _ _ ->
@@ -90,7 +90,7 @@ generate mode expression =
9090 Opt.VarBox (Opt.Global home name) ->
9191 JsExpr $ JS.Ref $
9292 case mode of
93− Name.Dev _ -> Name.fromGlobal home name
93+ Name.Dev _ _ -> Name.fromGlobal home name
9494 Name.Prod _ _ -> Name.fromGlobal ModuleName.basics N.identity
9595
9696 Opt.VarCycle home name ->
@@ -161,7 +161,7 @@ generate mode expression =
161161
162162 Opt.Unit ->
163163 case mode of
164− Name.Dev _ ->
164+ Name.Dev _ _ ->
165165 JsExpr $ JS.Ref (Name.fromKernel N.utils "Tuple0")
166166
167167 Name.Prod _ _ ->
@@ -261,7 +261,7 @@ generateCtor mode name index arity =
261261
262262 ctorTag =
263263 case mode of
264− Name.Dev _ -> JS.String (N.toBuilder name)
264+ Name.Dev _ _ -> JS.String (N.toBuilder name)
265265 Name.Prod _ _ -> JS.Int (Index.toMachine index)
266266 in
267267 generateFunction argNames $ JsExpr $ JS.Object $
@@ -363,7 +363,7 @@ generateCall mode func args =
363363
364364 Opt.VarBox _ ->
365365 case mode of
366− Name.Dev _ ->
366+ Name.Dev _ _ ->
367367 generateCallHelp mode func args
368368
369369 Name.Prod _ _ ->
@@ -744,7 +744,7 @@ generatePath mode path =
744744
745745 Opt.Unbox subPath ->
746746 case mode of
747− Name.Dev _ ->
747+ Name.Dev _ _ ->
748748 JS.Access (generatePath mode subPath) (Name.fromIndex Index.first)
749749
750750 Name.Prod _ _ ->
@@ -872,7 +872,7 @@ generateIfTest mode root (path, test) =
872872 DT.IsCtor name index _ _ ->
873873 strictEq (JS.Access value Name.dollar) $
874874 case mode of
875− Name.Dev _ -> JS.String (N.toBuilder name)
875+ Name.Dev _ _ -> JS.String (N.toBuilder name)
876876 Name.Prod _ _ -> JS.Int (Index.toMachine index)
877877
878878 DT.IsInt int ->
@@ -881,7 +881,7 @@ generateIfTest mode root (path, test) =
881881 DT.IsChr char ->
882882 strictEq (JS.String (Text.encodeUtf8Builder char)) $
883883 case mode of
884− Name.Dev _ -> JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
884+ Name.Dev _ _ -> JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
885885 Name.Prod _ _ -> value
886886
887887 DT.IsStr string ->
@@ -911,7 +911,7 @@ generateCaseValue mode test =
911911 case test of
912912 DT.IsCtor name index _ _ ->
913913 case mode of
914− Name.Dev _ -> JS.String (N.toBuilder name)
914+ Name.Dev _ _ -> JS.String (N.toBuilder name)
915915 Name.Prod _ _ -> JS.Int (Index.toMachine index)
916916
917917 DT.IsInt int ->
@@ -941,7 +941,7 @@ generateCaseTest mode root path exampleTest =
941941 case exampleTest of
942942 DT.IsCtor _ _ _ opts ->
943943 case mode of
944− Name.Dev _ ->
944+ Name.Dev _ _ ->
945945 JS.Access value Name.dollar
946946
947947 Name.Prod _ _ ->
@@ -963,7 +963,7 @@ generateCaseTest mode root path exampleTest =
963963
964964 DT.IsChr _ ->
965965 case mode of
966− Name.Dev _ ->
966+ Name.Dev _ _ ->
967967 JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
968968
969969 Name.Prod _ _ ->
@@ -991,7 +991,7 @@ pathToJsExpr mode root path =
991991
992992 DT.Unbox subPath ->
993993 case mode of
994− Name.Dev _ ->
994+ Name.Dev _ _ ->
995995 JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex Index.first)
996996
997997 Name.Prod _ _ ->
@@ -1031,8 +1031,13 @@ toDebugMetadata mode interfaces msgType =
10311031 Name.Prod _ _ ->
10321032 JS.Int 0
10331033
1034− Name.Dev _ ->
1035− JS.Json $ Encode.object $
1036− [ ("versions", Encode.object [ ("elm", Pkg.encodeVersion Version.version) ])
1037− , ("types", Type.encodeMetadata (Extract.fromMsg interfaces msgType))
1038− ]
1034+ Name.Dev _ debugger ->
1035+ case debugger of
1036+ Name.DebuggerOff ->
1037+ JS.Int 0
1038+
1039+ Name.DebuggerOn ->
1040+ JS.Json $ Encode.object $
1041+ [ ("versions", Encode.object [ ("elm", Pkg.encodeVersion Version.version) ])
1042+ , ("types", Type.encodeMetadata (Extract.fromMsg interfaces msgType))
1043+ ]
compiler/src/Generate/JavaScript/Name.hs+9−3
@@ -4,6 +4,7 @@ module Generate.JavaScript.Name
44 ( Name
55 , Mode(..)
66 , Target(..)
7+ , Debugger(..)
78 , isServer
89 , toBuilder
910 , fromIndex
@@ -53,13 +54,18 @@ newtype Name =
5354
5455
5556data Mode
56− = Dev Target
57+ = Dev Target Debugger
5758 | Prod Target ShortFieldNames
5859
5960
6061data Target = Client | Server
6162
6263
64+data Debugger
65+ = DebuggerOn
66+ | DebuggerOff
67+
68+
6369type ShortFieldNames =
6470 Map.Map N.Name Name
6571
@@ -67,7 +73,7 @@ type ShortFieldNames =
6773isServer :: Mode -> Bool
6874isServer mode =
6975 case mode of
70− Dev target -> isServerHelp target
76+ Dev target _ -> isServerHelp target
7177 Prod target _ -> isServerHelp target
7278
7379
@@ -124,7 +130,7 @@ fromKernel home name =
124130fromField :: Mode -> N.Name -> Name
125131fromField mode name =
126132 case mode of
127− Dev _ ->
133+ Dev _ _ ->
128134 Name (N.toBuilder name)
129135
130136 Prod _ fields ->
elm.cabal+1
@@ -117,6 +117,7 @@ Executable elm
117117 Reporting.Exit.Diff,
118118 Reporting.Exit.Help,
119119 Reporting.Exit.Http,
120+ Reporting.Exit.Make,
120121 Reporting.Exit.Publish,
121122 Reporting.Progress,
122123 Reporting.Progress.Bar,
ui/terminal/src/Main.hs+1
@@ -173,6 +173,7 @@ make =
173173
174174 makeFlags =
175175 flags Make.Flags
176+ |-- onOff "debug" "Turn on the time-travelling debugger. It allows you to rewind and replay events. The events can be imported/exported into a file, which makes for very precise bug reports!"
176177 |-- onOff "optimize" "Turn on optimizations to make code smaller and faster. For example, the compiler renames record fields to be as short as possible and unboxes values to reduce allocation."
177178 |-- flag "output" Output.output "Specify the name of the resulting JS file. For example --output=assets/elm.js to generate the JS at assets/elm.js or --output=/dev/null to generate no output at all!"
178179 |-- flag "report" Make.reportType "You can say --report=json to get error messages as JSON. This is only really useful if you are an editor plugin. Humans should avoid it!"
ui/terminal/src/Make.hs+27−17
@@ -14,7 +14,10 @@ import qualified System.FilePath as FP
1414import qualified Elm.Compiler.Objects as Obj
1515import qualified Elm.Project as Project
1616import qualified Generate.Output as Output
17+import qualified Reporting.Exit as Exit
18+import qualified Reporting.Exit.Make as E
1719import qualified Reporting.Task as Task
20+import qualified Reporting.Progress as Progress
1821import qualified Reporting.Progress.Json as Json
1922import qualified Reporting.Progress.Terminal as Terminal
2023import Terminal.Args (Parser(..), suggestFiles)
@@ -26,7 +29,8 @@ import Terminal.Args (Parser(..), suggestFiles)
2629
2730data Flags =
2831 Flags
29− { _optimize :: Bool
32+ { _debug :: Bool
33+ , _optimize :: Bool
3034 , _output :: Maybe Output.Output
3135 , _report :: Maybe ReportType
3236 , _docs :: Maybe FilePath
@@ -34,23 +38,29 @@ data Flags =
3438
3539
3640run :: [FilePath] -> Flags -> IO ()
37−run paths (Flags optimize output report docs) =
38− let
39− mode =
40− if optimize then Obj.Prod else Obj.Dev
41−
42− outputOptions =
43− Output.Options mode Obj.Client output
44−
45− makeReporter =
46− case report of
47− Nothing -> Terminal.create
48− Just Json -> return Json.reporter
49− in
50− do reporter <- makeReporter
41+run paths (Flags debug optimize output report docs) =
42+ do reporter <- toReporter report
5143 void $ Task.run reporter $
52− do summary <- Project.getRoot
53− Project.compile outputOptions docs summary paths
44+ do mode <- toMode debug optimize
45+ summary <- Project.getRoot
46+ let options = Output.Options mode Obj.Client output
47+ Project.compile options docs summary paths
48+
49+
50+toMode :: Bool -> Bool -> Task.Task Obj.Mode
51+toMode debug optimize =
52+ case (debug, optimize) of
53+ (True , True ) -> Task.throw $ Exit.Make E.CannotOptimizeAndDebug
54+ (False, True ) -> return Obj.Prod
55+ (False, False) -> return Obj.Dev
56+ (True , False) -> return Obj.Debug
57+
58+
59+toReporter :: Maybe ReportType -> IO Progress.Reporter
60+toReporter report =
61+ case report of
62+ Nothing -> Terminal.create
63+ Just Json -> return Json.reporter
5464
5565
5666