@@ -2,6 +2,7 @@
22module Generate.JavaScript.Expression
33 ( generate
44 , generateCtor
5+ , generateField
56 , generateTailDef
67 , generateMain
78 , Code
@@ -13,6 +14,7 @@ module Generate.JavaScript.Expression
1314
1415import qualified Data.IntMap as IntMap
1516import qualified Data.List as List
17+import Data.Map ((!))
1618import qualified Data.Map as Map
1719import qualified Data.Text.Encoding as Text
1820
@@ -22,11 +24,11 @@ import qualified AST.Module.Name as ModuleName
2224import qualified Data.Index as Index
2325import qualified Elm.Compiler.Type as Type
2426import qualified Elm.Compiler.Type.Extract as Extract
25−import qualified Elm.Interface as I
2627import qualified Elm.Name as N
2728import qualified Elm.Package as Pkg
2829import qualified Elm.Compiler.Version as Version
2930import qualified Generate.JavaScript.Builder as JS
31+import qualified Generate.JavaScript.Mode as Mode
3032import qualified Generate.JavaScript.Name as Name
3133import qualified Json.Encode as Encode
3234import qualified Optimize.DecisionTree as DT
@@ -34,22 +36,15 @@ import qualified Reporting.Region as R
3436
3537
3638
37−-- ENVIRONMENT
38−
39−
40−type Mode = Name.Mode
41−
42−
43−
4439-- EXPRESSIONS
4540
4641
47−generateJsExpr :: Mode -> Opt.Expr -> JS.Expr
42+generateJsExpr :: Mode.Mode -> Opt.Expr -> JS.Expr
4843generateJsExpr mode expression =
4944 codeToExpr (generate mode expression)
5045
5146
52−generate :: Mode -> Opt.Expr -> Code
47+generate :: Mode.Mode -> Opt.Expr -> Code
5348generate mode expression =
5449 case expression of
5550 Opt.Bool bool ->
@@ -58,10 +53,10 @@ generate mode expression =
5853 Opt.Chr char ->
5954 JsExpr $
6055 case mode of
61− Name.Dev _ _ ->
56+ Mode.Dev _ _ ->
6257 JS.Call toChar [ JS.String (Text.encodeUtf8Builder char) ]
6358
64− Name.Prod _ _ ->
59+ Mode.Prod _ _ ->
6560 JS.String (Text.encodeUtf8Builder char)
6661
6762 Opt.Str string ->
@@ -81,17 +76,17 @@ generate mode expression =
8176
8277 Opt.VarEnum (Opt.Global home name) index ->
8378 case mode of
84− Name.Dev _ _ ->
79+ Mode.Dev _ _ ->
8580 JsExpr $ JS.Ref (Name.fromGlobal home name)
8681
87− Name.Prod _ _ ->
82+ Mode.Prod _ _ ->
8883 JsExpr $ JS.Int (Index.toMachine index)
8984
9085 Opt.VarBox (Opt.Global home name) ->
9186 JsExpr $ JS.Ref $
9287 case mode of
93− Name.Dev _ _ -> Name.fromGlobal home name
94− Name.Prod _ _ -> Name.fromGlobal ModuleName.basics N.identity
88+ Mode.Dev _ _ -> Name.fromGlobal home name
89+ Mode.Prod _ _ -> Name.fromGlobal ModuleName.basics N.identity
9590
9691 Opt.VarCycle home name ->
9792 JsExpr $ JS.Call (JS.Ref (Name.fromCycle home name)) []
@@ -143,11 +138,11 @@ generate mode expression =
143138 Opt.Accessor field ->
144139 JsExpr $ JS.Function Nothing [Name.dollar]
145140 [ JS.Return $ Just $
146− JS.Access (JS.Ref Name.dollar) (Name.fromField mode field)
141+ JS.Access (JS.Ref Name.dollar) (generateField mode field)
147142 ]
148143
149144 Opt.Access record field ->
150− JsExpr $ JS.Access (generateJsExpr mode record) (Name.fromField mode field)
145+ JsExpr $ JS.Access (generateJsExpr mode record) (generateField mode field)
151146
152147 Opt.Update record fields ->
153148 JsExpr $
@@ -161,10 +156,10 @@ generate mode expression =
161156
162157 Opt.Unit ->
163158 case mode of
164− Name.Dev _ _ ->
159+ Mode.Dev _ _ ->
165160 JsExpr $ JS.Ref (Name.fromKernel N.utils "Tuple0")
166161
167− Name.Prod _ _ ->
162+ Mode.Prod _ _ ->
168163 JsExpr $ JS.Int 0
169164
170165 Opt.Tuple a b maybeC ->
@@ -253,7 +248,7 @@ toChar =
253248-- CTOR
254249
255250
256−generateCtor :: Mode -> N.Name -> Index.ZeroBased -> Int -> Code
251+generateCtor :: Mode.Mode -> N.Name -> Index.ZeroBased -> Int -> Code
257252generateCtor mode name index arity =
258253 let
259254 argNames =
@@ -261,8 +256,8 @@ generateCtor mode name index arity =
261256
262257 ctorTag =
263258 case mode of
264− Name.Dev _ _ -> JS.String (N.toBuilder name)
265− Name.Prod _ _ -> JS.Int (Index.toMachine index)
259+ Mode.Dev _ _ -> JS.String (N.toBuilder name)
260+ Mode.Prod _ _ -> JS.Int (Index.toMachine index)
266261 in
267262 generateFunction argNames $ JsExpr $ JS.Object $
268263 (Name.dollar, ctorTag) : map (\n -> (n, JS.Ref n)) argNames
@@ -272,15 +267,26 @@ generateCtor mode name index arity =
272267-- RECORDS
273268
274269
275−generateRecord :: Mode -> Map.Map N.Name Opt.Expr -> JS.Expr
270+generateRecord :: Mode.Mode -> Map.Map N.Name Opt.Expr -> JS.Expr
276271generateRecord mode fields =
277272 let
278273 toPair (field, value) =
279− (Name.fromField mode field, generateJsExpr mode value)
274+ (generateField mode field, generateJsExpr mode value)
280275 in
281276 JS.Object (map toPair (Map.toList fields))
282277
283278
279+generateField :: Mode.Mode -> N.Name -> Name.Name
280+generateField mode name =
281+ case mode of
282+ Mode.Dev _ _ ->
283+ Name.fromLocal name
284+
285+ Mode.Prod _ fields ->
286+ fields ! name
287+
288+
289+
284290
285291-- DEBUG
286292
@@ -355,7 +361,7 @@ funcHelpers =
355361-- CALLS
356362
357363
358−generateCall :: Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
364+generateCall :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
359365generateCall mode func args =
360366 case func of
361367 Opt.VarGlobal global@(Opt.Global (ModuleName.Canonical pkg _) _) | pkg == Pkg.core ->
@@ -363,10 +369,10 @@ generateCall mode func args =
363369
364370 Opt.VarBox _ ->
365371 case mode of
366− Name.Dev _ _ ->
372+ Mode.Dev _ _ ->
367373 generateCallHelp mode func args
368374
369− Name.Prod _ _ ->
375+ Mode.Prod _ _ ->
370376 case args of
371377 [arg] ->
372378 generateJsExpr mode arg
@@ -378,7 +384,7 @@ generateCall mode func args =
378384 generateCallHelp mode func args
379385
380386
381−generateCallHelp :: Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
387+generateCallHelp :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
382388generateCallHelp mode func args =
383389 generateNormalCall
384390 (generateJsExpr mode func)
@@ -411,7 +417,7 @@ callHelpers =
411417-- CORE CALLS
412418
413419
414−generateCoreCall :: Mode -> Opt.Global -> [Opt.Expr] -> JS.Expr
420+generateCoreCall :: Mode.Mode -> Opt.Global -> [Opt.Expr] -> JS.Expr
415421generateCoreCall mode (Opt.Global home@(ModuleName.Canonical _ moduleName) name) args =
416422 if moduleName == N.basics then
417423 generateBasicsCall mode home name args
@@ -472,7 +478,7 @@ generateBitwiseCall home name args =
472478 generateGlobalCall home name args
473479
474480
475−generateBasicsCall :: Mode -> ModuleName.Canonical -> N.Name -> [Opt.Expr] -> JS.Expr
481+generateBasicsCall :: Mode.Mode -> ModuleName.Canonical -> N.Name -> [Opt.Expr] -> JS.Expr
476482generateBasicsCall mode home name args =
477483 case args of
478484 [elmArg] ->
@@ -564,7 +570,7 @@ isLiteral expr =
564570 False
565571
566572
567−decomposeL :: Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
573+decomposeL :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
568574decomposeL mode expr funcs =
569575 case expr of
570576 Opt.Call (Opt.VarGlobal (Opt.Global home "composeL")) [left, func]
@@ -576,7 +582,7 @@ decomposeL mode expr funcs =
576582 Opt.Function [N.dollar] (foldr apply (Opt.VarLocal N.dollar) (expr:funcs))
577583
578584
579−decomposeR :: Mode -> [Opt.Expr] -> Opt.Expr -> JS.Expr
585+decomposeR :: Mode.Mode -> [Opt.Expr] -> Opt.Expr -> JS.Expr
580586decomposeR mode funcs expr =
581587 case expr of
582588 Opt.Call (Opt.VarGlobal (Opt.Global home "composeR")) [func, right]
@@ -601,7 +607,7 @@ apply func value =
601607 Opt.Call func [value]
602608
603609
604−append :: Mode -> Opt.Expr -> Opt.Expr -> JS.Expr
610+append :: Mode.Mode -> Opt.Expr -> Opt.Expr -> JS.Expr
605611append mode left right =
606612 let seqs = generateJsExpr mode left : toSeqs mode right in
607613 if any isStringLiteral seqs then
@@ -615,7 +621,7 @@ jsAppend a b =
615621 JS.Call (JS.Ref (Name.fromKernel N.utils "ap")) [a, b]
616622
617623
618−toSeqs :: Mode -> Opt.Expr -> [JS.Expr]
624+toSeqs :: Mode.Mode -> Opt.Expr -> [JS.Expr]
619625toSeqs mode expr =
620626 case expr of
621627 Opt.Call (Opt.VarGlobal (Opt.Global home "append")) [left, right]
@@ -688,7 +694,7 @@ strictNEq left right =
688694
689695-- TODO check if JS minifiers collapse unnecessary temporary variables
690696--
691−generateTailCall :: Mode -> N.Name -> [(N.Name, Opt.Expr)] -> [JS.Stmt]
697+generateTailCall :: Mode.Mode -> N.Name -> [(N.Name, Opt.Expr)] -> [JS.Stmt]
692698generateTailCall mode name args =
693699 let
694700 toTempVars (argName, arg) =
@@ -707,7 +713,7 @@ generateTailCall mode name args =
707713-- DEFINITIONS
708714
709715
710−generateDef :: Mode -> Opt.Def -> JS.Stmt
716+generateDef :: Mode.Mode -> Opt.Def -> JS.Stmt
711717generateDef mode def =
712718 case def of
713719 Opt.Def name body ->
@@ -717,7 +723,7 @@ generateDef mode def =
717723 JS.Var [ (Name.fromLocal name, Just (codeToExpr (generateTailDef mode name argNames body))) ]
718724
719725
720−generateTailDef :: Mode -> N.Name -> [N.Name] -> Opt.Expr -> Code
726+generateTailDef :: Mode.Mode -> N.Name -> [N.Name] -> Opt.Expr -> Code
721727generateTailDef mode name argNames body =
722728 generateFunction (map Name.fromLocal argNames) $ JsBlock $
723729 [ JS.Labelled (Name.fromLocal name) $
@@ -730,7 +736,7 @@ generateTailDef mode name argNames body =
730736-- PATHS
731737
732738
733−generatePath :: Mode -> Opt.Path -> JS.Expr
739+generatePath :: Mode.Mode -> Opt.Path -> JS.Expr
734740generatePath mode path =
735741 case path of
736742 Opt.Index index subPath ->
@@ -740,14 +746,14 @@ generatePath mode path =
740746 JS.Ref (Name.fromLocal name)
741747
742748 Opt.Field field subPath ->
743− JS.Access (generatePath mode subPath) (Name.fromField mode field)
749+ JS.Access (generatePath mode subPath) (generateField mode field)
744750
745751 Opt.Unbox subPath ->
746752 case mode of
747− Name.Dev _ _ ->
753+ Mode.Dev _ _ ->
748754 JS.Access (generatePath mode subPath) (Name.fromIndex Index.first)
749755
750− Name.Prod _ _ ->
756+ Mode.Prod _ _ ->
751757 generatePath mode subPath
752758
753759
@@ -755,7 +761,7 @@ generatePath mode path =
755761-- GENERATE IFS
756762
757763
758−generateIf :: Mode -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> Code
764+generateIf :: Mode.Mode -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> Code
759765generateIf mode givenBranches givenFinal =
760766 let
761767 (branches, final) =
@@ -820,12 +826,12 @@ crushIfsHelp visitedBranches unvisitedBranches final =
820826-- CASE EXPRESSIONS
821827
822828
823−generateCase :: Mode -> N.Name -> N.Name -> Opt.Decider Opt.Choice -> [(Int, Opt.Expr)] -> [JS.Stmt]
829+generateCase :: Mode.Mode -> N.Name -> N.Name -> Opt.Decider Opt.Choice -> [(Int, Opt.Expr)] -> [JS.Stmt]
824830generateCase mode label root decider jumps =
825831 foldr (goto mode label) (generateDecider mode label root decider) jumps
826832
827833
828−goto :: Mode -> N.Name -> (Int, Opt.Expr) -> [JS.Stmt] -> [JS.Stmt]
834+goto :: Mode.Mode -> N.Name -> (Int, Opt.Expr) -> [JS.Stmt] -> [JS.Stmt]
829835goto mode label (index, branch) stmts =
830836 let
831837 labeledDeciderStmt =
@@ -836,7 +842,7 @@ goto mode label (index, branch) stmts =
836842 labeledDeciderStmt : codeToStmtList (generate mode branch)
837843
838844
839−generateDecider :: Mode -> N.Name -> N.Name -> Opt.Decider Opt.Choice -> [JS.Stmt]
845+generateDecider :: Mode.Mode -> N.Name -> N.Name -> Opt.Decider Opt.Choice -> [JS.Stmt]
840846generateDecider mode label root decisionTree =
841847 case decisionTree of
842848 Opt.Leaf (Opt.Inline branch) ->
@@ -863,7 +869,7 @@ generateDecider mode label root decisionTree =
863869 ]
864870
865871
866−generateIfTest :: Mode -> N.Name -> (DT.Path, DT.Test) -> JS.Expr
872+generateIfTest :: Mode.Mode -> N.Name -> (DT.Path, DT.Test) -> JS.Expr
867873generateIfTest mode root (path, test) =
868874 let
869875 value = pathToJsExpr mode root path
@@ -872,8 +878,8 @@ generateIfTest mode root (path, test) =
872878 DT.IsCtor name index _ _ ->
873879 strictEq (JS.Access value Name.dollar) $
874880 case mode of
875− Name.Dev _ _ -> JS.String (N.toBuilder name)
876− Name.Prod _ _ -> JS.Int (Index.toMachine index)
881+ Mode.Dev _ _ -> JS.String (N.toBuilder name)
882+ Mode.Prod _ _ -> JS.Int (Index.toMachine index)
877883
878884 DT.IsInt int ->
879885 strictEq value (JS.Int int)
@@ -881,8 +887,8 @@ generateIfTest mode root (path, test) =
881887 DT.IsChr char ->
882888 strictEq (JS.String (Text.encodeUtf8Builder char)) $
883889 case mode of
884− Name.Dev _ _ -> JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
885− Name.Prod _ _ -> value
890+ Mode.Dev _ _ -> JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
891+ Mode.Prod _ _ -> value
886892
887893 DT.IsStr string ->
888894 strictEq value (JS.String (Text.encodeUtf8Builder string))
@@ -899,20 +905,20 @@ generateIfTest mode root (path, test) =
899905
900906
901907
902−generateCaseBranch :: Mode -> N.Name -> N.Name -> (DT.Test, Opt.Decider Opt.Choice) -> JS.Case
908+generateCaseBranch :: Mode.Mode -> N.Name -> N.Name -> (DT.Test, Opt.Decider Opt.Choice) -> JS.Case
903909generateCaseBranch mode label root (test, subTree) =
904910 JS.Case
905911 (generateCaseValue mode test)
906912 (generateDecider mode label root subTree)
907913
908914
909−generateCaseValue :: Mode -> DT.Test -> JS.Expr
915+generateCaseValue :: Mode.Mode -> DT.Test -> JS.Expr
910916generateCaseValue mode test =
911917 case test of
912918 DT.IsCtor name index _ _ ->
913919 case mode of
914− Name.Dev _ _ -> JS.String (N.toBuilder name)
915− Name.Prod _ _ -> JS.Int (Index.toMachine index)
920+ Mode.Dev _ _ -> JS.String (N.toBuilder name)
921+ Mode.Prod _ _ -> JS.Int (Index.toMachine index)
916922
917923 DT.IsInt int ->
918924 JS.Int int
@@ -933,7 +939,7 @@ generateCaseValue mode test =
933939 error "COMPILER BUG - there should never be three tests on a tuple"
934940
935941
936−generateCaseTest :: Mode -> N.Name -> DT.Path -> DT.Test -> JS.Expr
942+generateCaseTest :: Mode.Mode -> N.Name -> DT.Path -> DT.Test -> JS.Expr
937943generateCaseTest mode root path exampleTest =
938944 let
939945 value = pathToJsExpr mode root path
@@ -941,10 +947,10 @@ generateCaseTest mode root path exampleTest =
941947 case exampleTest of
942948 DT.IsCtor _ _ _ opts ->
943949 case mode of
944− Name.Dev _ _ ->
950+ Mode.Dev _ _ ->
945951 JS.Access value Name.dollar
946952
947− Name.Prod _ _ ->
953+ Mode.Prod _ _ ->
948954 case opts of
949955 Can.Normal ->
950956 JS.Access value Name.dollar
@@ -963,10 +969,10 @@ generateCaseTest mode root path exampleTest =
963969
964970 DT.IsChr _ ->
965971 case mode of
966− Name.Dev _ _ ->
972+ Mode.Dev _ _ ->
967973 JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
968974
969− Name.Prod _ _ ->
975+ Mode.Prod _ _ ->
970976 value
971977
972978 DT.IsCons ->
@@ -983,7 +989,7 @@ generateCaseTest mode root path exampleTest =
983989-- PATTERN PATHS
984990
985991
986−pathToJsExpr :: Mode -> N.Name -> DT.Path -> JS.Expr
992+pathToJsExpr :: Mode.Mode -> N.Name -> DT.Path -> JS.Expr
987993pathToJsExpr mode root path =
988994 case path of
989995 DT.Index index subPath ->
@@ -991,10 +997,10 @@ pathToJsExpr mode root path =
991997
992998 DT.Unbox subPath ->
993999 case mode of
994− Name.Dev _ _ ->
1000+ Mode.Dev _ _ ->
9951001 JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex Index.first)
9961002
997− Name.Prod _ _ ->
1003+ Mode.Prod _ _ ->
9981004 pathToJsExpr mode root subPath
9991005
10001006 DT.Empty ->
@@ -1005,8 +1011,8 @@ pathToJsExpr mode root path =
10051011-- GENERATE MAIN
10061012
10071013
1008−generateMain :: Mode -> I.Interfaces -> ModuleName.Canonical -> Opt.Main -> JS.Expr
1009−generateMain mode interfaces home main =
1014+generateMain :: Mode.Mode -> ModuleName.Canonical -> Opt.Main -> JS.Expr
1015+generateMain mode home main =
10101016 case main of
10111017 Opt.Static ->
10121018 JS.Ref (Name.fromKernel N.virtualDom "init")
@@ -1017,7 +1023,7 @@ generateMain mode interfaces home main =
10171023 Opt.Dynamic msgType decoder ->
10181024 JS.Ref (Name.fromGlobal home "main")
10191025 # generateJsExpr mode decoder
1020− # toDebugMetadata mode interfaces msgType
1026+ # toDebugMetadata mode msgType
10211027
10221028
10231029(#) :: JS.Expr -> JS.Expr -> JS.Expr
@@ -1025,19 +1031,17 @@ generateMain mode interfaces home main =
10251031 JS.Call func [arg]
10261032
10271033
1028−toDebugMetadata :: Mode -> I.Interfaces -> Can.Type -> JS.Expr
1029−toDebugMetadata mode interfaces msgType =
1034+toDebugMetadata :: Mode.Mode -> Can.Type -> JS.Expr
1035+toDebugMetadata mode msgType =
10301036 case mode of
1031− Name.Prod _ _ ->
1037+ Mode.Prod _ _ ->
10321038 JS.Int 0
10331039
1034− Name.Dev _ debugger ->
1035− case debugger of
1036− Name.DebuggerOff ->
1037− JS.Int 0
1040+ Mode.Dev _ Nothing ->
1041+ JS.Int 0
10381042
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− ]
1043+ Mode.Dev _ (Just interfaces) ->
1044+ JS.Json $ Encode.object $
1045+ [ ("versions", Encode.object [ ("elm", Pkg.encodeVersion Version.version) ])
1046+ , ("types", Type.encodeMetadata (Extract.fromMsg interfaces msgType))
1047+ ]