1{-# LANGUAGE OverloadedStrings #-}
2module Generate.JavaScript.Expression
15import qualified Data.IntMap as IntMap
16import qualified Data.List as List
18import qualified Data.Map as Map
19import qualified Data.Name as Name
20import qualified Data.Set as Set
21import qualified Data.Utf8 as Utf8
23import qualified AST.Canonical as Can
24import qualified AST.Optimized as Opt
25import qualified Data.Index as Index
26import qualified Elm.Compiler.Type as Type
27import qualified Elm.Compiler.Type.Extract as Extract
28import qualified Elm.Version as V
29import qualified Elm.ModuleName as ModuleName
30import qualified Elm.Package as Pkg
31import qualified Generate.JavaScript.Builder as JS
32import qualified Generate.JavaScript.Name as JsName
33import qualified Generate.Mode as Mode
34import qualified Json.Encode as Encode
35import qualified Optimize.DecisionTree as DT
36import qualified Reporting.Annotation as A
43generateJsExpr :: Mode.Mode -> Opt.Expr -> JS.Expr
44generateJsExpr mode expression =
45 codeToExpr (generate mode expression)
48generate :: Mode.Mode -> Opt.Expr -> Code
49generate mode expression =
58 JS.Call toChar [ JS.String (Utf8.toBuilder char) ]
61 JS.String (Utf8.toBuilder char)
64 JsExpr $ JS.String (Utf8.toBuilder string)
70 JsExpr $ JS.Float (Utf8.toBuilder float)
73 JsExpr $ JS.Ref (JsName.fromLocal name)
75 Opt.VarGlobal (Opt.Global home name) ->
76 JsExpr $ JS.Ref (JsName.fromGlobal home name)
78 Opt.VarEnum (Opt.Global home name) index ->
81 JsExpr $ JS.Ref (JsName.fromGlobal home name)
84 JsExpr $ JS.Int (Index.toMachine index)
86 Opt.VarBox (Opt.Global home name) ->
89 Mode.Dev _ -> JsName.fromGlobal home name
90 Mode.Prod _ -> JsName.fromGlobal ModuleName.basics Name.identity
92 Opt.VarCycle home name ->
93 JsExpr $ JS.Call (JS.Ref (JsName.fromCycle home name)) []
95 Opt.VarDebug name home region unhandledValueName ->
96 JsExpr $ generateDebug name home region unhandledValueName
98 Opt.VarKernel home name ->
99 JsExpr $ JS.Ref (JsName.fromKernel home name)
104 JsExpr $ JS.Ref (JsName.fromKernel Name.list "Nil")
109 (JS.Ref (JsName.fromKernel Name.list "fromArray"))
110 [ JS.Array $ map (generateJsExpr mode) entries
113 Opt.Function args body ->
114 generateFunction (map JsName.fromLocal args) (generate mode body)
116 Opt.Call func args ->
117 JsExpr $ generateCall mode func args
119 Opt.TailCall name args ->
120 JsBlock $ generateTailCall mode name args
122 Opt.If branches final ->
123 generateIf mode branches final
127 generateDef mode def : codeToStmtList (generate mode body)
129 Opt.Destruct (Opt.Destructor name path) body ->
131 pathDef = JS.Var (JsName.fromLocal name) (generatePath mode path)
133 JsBlock $ pathDef : codeToStmtList (generate mode body)
135 Opt.Case label root decider jumps ->
136 JsBlock $ generateCase mode label root decider jumps
138 Opt.Accessor field ->
139 JsExpr $ JS.Function Nothing [JsName.dollar]
141 JS.Access (JS.Ref JsName.dollar) (generateField mode field)
144 Opt.Access record field ->
145 JsExpr $ JS.Access (generateJsExpr mode record) (generateField mode field)
147 Opt.Update record fields ->
149 JS.Call (JS.Ref (JsName.fromKernel Name.utils "update"))
150 [ generateJsExpr mode record
151 , generateRecord mode fields
155 JsExpr $ generateRecord mode fields
160 JsExpr $ JS.Ref (JsName.fromKernel Name.utils "Tuple0")
165 Opt.Tuple a b maybeC ->
169 JS.Call (JS.Ref (JsName.fromKernel Name.utils "Tuple2"))
170 [ generateJsExpr mode a
171 , generateJsExpr mode b
175 JS.Call (JS.Ref (JsName.fromKernel Name.utils "Tuple3"))
176 [ generateJsExpr mode a
177 , generateJsExpr mode b
178 , generateJsExpr mode c
181 Opt.Shader src attributes uniforms ->
184 ( JsName.fromLocal field
185 , JS.String (JsName.toBuilder (generateField mode field))
188 toTranslationObject fields =
189 JS.Object (map toTranlation (Set.toList fields))
192 [ ( JsName.fromLocal "src", JS.String (Utf8.toBuilder src) )
193 , ( JsName.fromLocal "attributes", toTranslationObject attributes )
194 , ( JsName.fromLocal "uniforms", toTranslationObject uniforms )
207codeToExpr :: Code -> JS.Expr
213 JsBlock [ JS.Return expr ] ->
217 JS.Call (JS.Function Nothing [] stmts) []
220codeToStmtList :: Code -> [JS.Stmt]
223 JsExpr (JS.Call (JS.Function Nothing [] stmts) []) ->
233codeToStmt :: Code -> JS.Stmt
236 JsExpr (JS.Call (JS.Function Nothing [] stmts) []) ->
253{-# NOINLINE toChar #-}
256 JS.Ref (JsName.fromKernel Name.utils "chr")
263generateCtor :: Mode.Mode -> Opt.Global -> Index.ZeroBased -> Int -> Code
264generateCtor mode (Opt.Global home name) index arity =
267 Index.indexedMap (\i _ -> JsName.fromIndex i) [1 .. arity]
271 Mode.Dev _ -> JS.String (Name.toBuilder name)
272 Mode.Prod _ -> JS.Int (ctorToInt home name index)
274 generateFunction argNames $ JsExpr $ JS.Object $
275 (JsName.dollar, ctorTag) : map (\n -> (n, JS.Ref n)) argNames
278ctorToInt :: ModuleName.Canonical -> Name.Name -> Index.ZeroBased -> Int
279ctorToInt home name index =
280 if home == ModuleName.dict && name == "RBNode_elm_builtin" || name == "RBEmpty_elm_builtin" then
281 0 - Index.toHuman index
283 Index.toMachine index
290generateRecord :: Mode.Mode -> Map.Map Name.Name Opt.Expr -> JS.Expr
291generateRecord mode fields =
293 toPair (field, value) =
294 (generateField mode field, generateJsExpr mode value)
296 JS.Object (map toPair (Map.toList fields))
299generateField :: Mode.Mode -> Name.Name -> JsName.Name
300generateField mode name =
303 JsName.fromLocal name
314generateDebug :: Name.Name -> ModuleName.Canonical -> A.Region -> Maybe Name.Name -> JS.Expr
315generateDebug name (ModuleName.Canonical _ home) region unhandledValueName =
316 if name /= "todo" then
317 JS.Ref (JsName.fromGlobal ModuleName.debug name)
319 case unhandledValueName of
321 JS.Call (JS.Ref (JsName.fromKernel Name.debug "todo")) $
322 [ JS.String (Name.toBuilder home)
323 , regionToJsExpr region
327 JS.Call (JS.Ref (JsName.fromKernel Name.debug "todoCase")) $
328 [ JS.String (Name.toBuilder home)
329 , regionToJsExpr region
330 , JS.Ref (JsName.fromLocal valueName)
334regionToJsExpr :: A.Region -> JS.Expr
335regionToJsExpr (A.Region start end) =
337 [ ( JsName.fromLocal "start", positionToJsExpr start )
338 , ( JsName.fromLocal "end", positionToJsExpr end )
342positionToJsExpr :: A.Position -> JS.Expr
343positionToJsExpr (A.Position line column) =
345 [ ( JsName.fromLocal "line", JS.Int (fromIntegral line) )
346 , ( JsName.fromLocal "column", JS.Int (fromIntegral column) )
354generateFunction :: [JsName.Name] -> Code -> Code
355generateFunction args body =
356 case IntMap.lookup (length args) funcHelpers of
360 [ JS.Function Nothing args $
367 JsExpr $ JS.Function Nothing [arg] $
370 foldr addArg body args
373{-# NOINLINE funcHelpers #-}
374funcHelpers :: IntMap.IntMap JS.Expr
377 map (\n -> (n, JS.Ref (JsName.makeF n))) [2..9]
384generateCall :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
385generateCall mode func args =
387 Opt.VarGlobal global@(Opt.Global (ModuleName.Canonical pkg _) _) | pkg == Pkg.core ->
388 generateCoreCall mode global args
393 generateCallHelp mode func args
398 generateJsExpr mode arg
401 generateCallHelp mode func args
404 generateCallHelp mode func args
407generateCallHelp :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
408generateCallHelp mode func args =
410 (generateJsExpr mode func)
411 (map (generateJsExpr mode) args)
414generateGlobalCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
415generateGlobalCall home name args =
416 generateNormalCall (JS.Ref (JsName.fromGlobal home name)) args
419generateNormalCall :: JS.Expr -> [JS.Expr] -> JS.Expr
420generateNormalCall func args =
421 case IntMap.lookup (length args) callHelpers of
423 JS.Call helper (func:args)
426 List.foldl' (\f a -> JS.Call f [a]) func args
429{-# NOINLINE callHelpers #-}
430callHelpers :: IntMap.IntMap JS.Expr
433 map (\n -> (n, JS.Ref (JsName.makeA n))) [2..9]
440generateCoreCall :: Mode.Mode -> Opt.Global -> [Opt.Expr] -> JS.Expr
441generateCoreCall mode (Opt.Global home@(ModuleName.Canonical _ moduleName) name) args =
442 if moduleName == Name.basics then
443 generateBasicsCall mode home name args
445 else if moduleName == Name.bitwise then
446 generateBitwiseCall home name (map (generateJsExpr mode) args)
448 else if moduleName == Name.tuple then
449 generateTupleCall home name (map (generateJsExpr mode) args)
451 else if moduleName == Name.jsArray then
452 generateJsArrayCall home name (map (generateJsExpr mode) args)
455 generateGlobalCall home name (map (generateJsExpr mode) args)
458generateTupleCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
459generateTupleCall home name args =
463 "first" -> JS.Access value (JsName.fromLocal "a")
464 "second" -> JS.Access value (JsName.fromLocal "b")
465 _ -> generateGlobalCall home name args
468 generateGlobalCall home name args
471generateJsArrayCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
472generateJsArrayCall home name args =
474 [entry] | name == "singleton" -> JS.Array [entry]
475 [index, array] | name == "unsafeGet" -> JS.Index array index
476 _ -> generateGlobalCall home name args
479generateBitwiseCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
480generateBitwiseCall home name args =
484 "complement" -> JS.Prefix JS.PrefixComplement arg
485 _ -> generateGlobalCall home name args
489 "and" -> JS.Infix JS.OpBitwiseAnd left right
490 "or" -> JS.Infix JS.OpBitwiseOr left right
491 "xor" -> JS.Infix JS.OpBitwiseXor left right
492 "shiftLeftBy" -> JS.Infix JS.OpLShift right left
493 "shiftRightBy" -> JS.Infix JS.OpSpRShift right left
494 "shiftRightZfBy" -> JS.Infix JS.OpZfRShift right left
495 _ -> generateGlobalCall home name args
498 generateGlobalCall home name args
501generateBasicsCall :: Mode.Mode -> ModuleName.Canonical -> Name.Name -> [Opt.Expr] -> JS.Expr
502generateBasicsCall mode home name args =
505 let arg = generateJsExpr mode elmArg in
507 "not" -> JS.Prefix JS.PrefixNot arg
508 "negate" -> JS.Prefix JS.PrefixNegate arg
510 "truncate" -> JS.Infix JS.OpBitwiseOr arg (JS.Int 0)
511 _ -> generateGlobalCall home name [arg]
513 [elmLeft, elmRight] ->
515 -- NOTE: removed "composeL" and "composeR" because of this issue:
516 -- https://github.com/elm/compiler/issues/1722
517 "append" -> append mode elmLeft elmRight
518 "apL" -> generateJsExpr mode $ apply elmLeft elmRight
519 "apR" -> generateJsExpr mode $ apply elmRight elmLeft
522 left = generateJsExpr mode elmLeft
523 right = generateJsExpr mode elmRight
526 "add" -> JS.Infix JS.OpAdd left right
527 "sub" -> JS.Infix JS.OpSub left right
528 "mul" -> JS.Infix JS.OpMul left right
529 "fdiv" -> JS.Infix JS.OpDiv left right
530 "idiv" -> JS.Infix JS.OpBitwiseOr (JS.Infix JS.OpDiv left right) (JS.Int 0)
531 "eq" -> equal left right
532 "neq" -> notEqual left right
533 "lt" -> cmp JS.OpLt JS.OpLt 0 left right
534 "gt" -> cmp JS.OpGt JS.OpGt 0 left right
535 "le" -> cmp JS.OpLe JS.OpLt 1 left right
536 "ge" -> cmp JS.OpGe JS.OpGt (-1) left right
537 "or" -> JS.Infix JS.OpOr left right
538 "and" -> JS.Infix JS.OpAnd left right
539 "xor" -> JS.Infix JS.OpNe left right
540 "remainderBy" -> JS.Infix JS.OpMod right left
541 _ -> generateGlobalCall home name [left, right]
544 generateGlobalCall home name (map (generateJsExpr mode) args)
547equal :: JS.Expr -> JS.Expr -> JS.Expr
549 if isLiteral left || isLiteral right then
552 JS.Call (JS.Ref (JsName.fromKernel Name.utils "eq")) [left, right]
555notEqual :: JS.Expr -> JS.Expr -> JS.Expr
557 if isLiteral left || isLiteral right then
560 JS.Prefix JS.PrefixNot $
561 JS.Call (JS.Ref (JsName.fromKernel Name.utils "eq")) [left, right]
564cmp :: JS.InfixOp -> JS.InfixOp -> Int -> JS.Expr -> JS.Expr -> JS.Expr
565cmp idealOp backupOp backupInt left right =
566 if isLiteral left || isLiteral right then
567 JS.Infix idealOp left right
570 (JS.Call (JS.Ref (JsName.fromKernel Name.utils "cmp")) [left, right])
574isLiteral :: JS.Expr -> Bool
593apply :: Opt.Expr -> Opt.Expr -> Opt.Expr
596 Opt.Accessor field ->
597 Opt.Access value field
600 Opt.Call f (args ++ [value])
603 Opt.Call func [value]
606append :: Mode.Mode -> Opt.Expr -> Opt.Expr -> JS.Expr
607append mode left right =
608 let seqs = generateJsExpr mode left : toSeqs mode right in
609 if any isStringLiteral seqs then
610 foldr1 (JS.Infix JS.OpAdd) seqs
615jsAppend :: JS.Expr -> JS.Expr -> JS.Expr
617 JS.Call (JS.Ref (JsName.fromKernel Name.utils "ap")) [a, b]
620toSeqs :: Mode.Mode -> Opt.Expr -> [JS.Expr]
623 Opt.Call (Opt.VarGlobal (Opt.Global home "append")) [left, right]
624 | home == ModuleName.basics ->
625 generateJsExpr mode left : toSeqs mode right
628 [generateJsExpr mode expr]
631isStringLiteral :: JS.Expr -> Bool
632isStringLiteral expr =
642-- SIMPLIFY INFIX OPERATORS
645strictEq :: JS.Expr -> JS.Expr -> JS.Expr
649 JS.Prefix JS.PrefixNot right
652 if bool then right else JS.Prefix JS.PrefixNot right
657 JS.Prefix JS.PrefixNot left
660 if bool then left else JS.Prefix JS.PrefixNot left
663 JS.Infix JS.OpEq left right
666strictNEq :: JS.Expr -> JS.Expr -> JS.Expr
667strictNEq left right =
670 JS.Prefix JS.PrefixNot (JS.Prefix JS.PrefixNot right)
673 if bool then JS.Prefix JS.PrefixNot right else right
678 JS.Prefix JS.PrefixNot (JS.Prefix JS.PrefixNot left)
681 if bool then JS.Prefix JS.PrefixNot left else left
684 JS.Infix JS.OpNe left right
691-- TODO check if JS minifiers collapse unnecessary temporary variables
693generateTailCall :: Mode.Mode -> Name.Name -> [(Name.Name, Opt.Expr)] -> [JS.Stmt]
694generateTailCall mode name args =
696 toTempVars (argName, arg) =
697 ( JsName.makeTemp argName, generateJsExpr mode arg )
699 toRealVars (argName, _) =
701 JS.Assign (JS.LRef (JsName.fromLocal argName)) (JS.Ref (JsName.makeTemp argName))
703 JS.Vars (map toTempVars args)
704 : map toRealVars args
705 ++ [ JS.Continue (Just (JsName.fromLocal name)) ]
712generateDef :: Mode.Mode -> Opt.Def -> JS.Stmt
713generateDef mode def =
716 JS.Var (JsName.fromLocal name) (generateJsExpr mode body)
718 Opt.TailDef name argNames body ->
719 JS.Var (JsName.fromLocal name) (codeToExpr (generateTailDef mode name argNames body))
722generateTailDef :: Mode.Mode -> Name.Name -> [Name.Name] -> Opt.Expr -> Code
723generateTailDef mode name argNames body =
724 generateFunction (map JsName.fromLocal argNames) $ JsBlock $
725 [ JS.Labelled (JsName.fromLocal name) $
726 JS.While (JS.Bool True) $
727 codeToStmt $ generate mode body
735generatePath :: Mode.Mode -> Opt.Path -> JS.Expr
736generatePath mode path =
738 Opt.Index index subPath ->
739 JS.Access (generatePath mode subPath) (JsName.fromIndex index)
742 JS.Ref (JsName.fromLocal name)
744 Opt.Field field subPath ->
745 JS.Access (generatePath mode subPath) (generateField mode field)
750 JS.Access (generatePath mode subPath) (JsName.fromIndex Index.first)
753 generatePath mode subPath
760generateIf :: Mode.Mode -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> Code
761generateIf mode givenBranches givenFinal =
764 crushIfs givenBranches givenFinal
766 convertBranch (condition, expr) =
767 ( generateJsExpr mode condition
771 branchExprs = map convertBranch branches
772 finalCode = generate mode final
774 if isBlock finalCode || any (isBlock . snd) branchExprs then
775 JsBlock [ foldr addStmtIf (codeToStmt finalCode) branchExprs ]
777 JsExpr $ foldr addExprIf (codeToExpr finalCode) branchExprs
780addExprIf :: (JS.Expr, Code) -> JS.Expr -> JS.Expr
781addExprIf (condition, branch) final =
782 JS.If condition (codeToExpr branch) final
785addStmtIf :: (JS.Expr, Code) -> JS.Stmt -> JS.Stmt
786addStmtIf (condition, branch) final =
787 JS.IfStmt condition (codeToStmt branch) final
790isBlock :: Code -> Bool
797crushIfs :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
798crushIfs branches final =
799 crushIfsHelp [] branches final
803 :: [(Opt.Expr, Opt.Expr)]
804 -> [(Opt.Expr, Opt.Expr)]
806 -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
807crushIfsHelp visitedBranches unvisitedBranches final =
808 case unvisitedBranches of
811 Opt.If subBranches subFinal ->
812 crushIfsHelp visitedBranches subBranches subFinal
815 (reverse visitedBranches, final)
817 visiting : unvisited ->
818 crushIfsHelp (visiting : visitedBranches) unvisited final
825generateCase :: Mode.Mode -> Name.Name -> Name.Name -> Opt.Decider Opt.Choice -> [(Int, Opt.Expr)] -> [JS.Stmt]
826generateCase mode label root decider jumps =
827 foldr (goto mode label) (generateDecider mode label root decider) jumps
830goto :: Mode.Mode -> Name.Name -> (Int, Opt.Expr) -> [JS.Stmt] -> [JS.Stmt]
831goto mode label (index, branch) stmts =
835 (JsName.makeLabel label index)
836 (JS.While (JS.Bool True) (JS.Block stmts))
838 labeledDeciderStmt : codeToStmtList (generate mode branch)
841generateDecider :: Mode.Mode -> Name.Name -> Name.Name -> Opt.Decider Opt.Choice -> [JS.Stmt]
842generateDecider mode label root decisionTree =
844 Opt.Leaf (Opt.Inline branch) ->
845 codeToStmtList (generate mode branch)
847 Opt.Leaf (Opt.Jump index) ->
848 [ JS.Break (Just (JsName.makeLabel label index)) ]
850 Opt.Chain testChain success failure ->
852 (List.foldl1' (JS.Infix JS.OpAnd) (map (generateIfTest mode root) testChain))
853 (JS.Block $ generateDecider mode label root success)
854 (JS.Block $ generateDecider mode label root failure)
857 Opt.FanOut path edges fallback ->
859 (generateCaseTest mode root path (fst (head edges)))
861 (\edge cases -> generateCaseBranch mode label root edge : cases)
862 [ JS.Default (generateDecider mode label root fallback) ]
868generateIfTest :: Mode.Mode -> Name.Name -> (DT.Path, DT.Test) -> JS.Expr
869generateIfTest mode root (path, test) =
871 value = pathToJsExpr mode root path
874 DT.IsCtor home name index _ opts ->
878 Mode.Dev _ -> JS.Access value JsName.dollar
881 Can.Normal -> JS.Access value JsName.dollar
887 Mode.Dev _ -> JS.String (Name.toBuilder name)
888 Mode.Prod _ -> JS.Int (ctorToInt home name index)
894 JS.Prefix JS.PrefixNot value
897 strictEq value (JS.Int int)
900 strictEq (JS.String (Utf8.toBuilder char)) $
902 Mode.Dev _ -> JS.Call (JS.Access value (JsName.fromLocal "valueOf")) []
906 strictEq value (JS.String (Utf8.toBuilder string))
909 JS.Access value (JsName.fromLocal "b")
912 JS.Prefix JS.PrefixNot $
913 JS.Access value (JsName.fromLocal "b")
916 error "COMPILER BUG - there should never be tests on a tuple"
920generateCaseBranch :: Mode.Mode -> Name.Name -> Name.Name -> (DT.Test, Opt.Decider Opt.Choice) -> JS.Case
921generateCaseBranch mode label root (test, subTree) =
923 (generateCaseValue mode test)
924 (generateDecider mode label root subTree)
927generateCaseValue :: Mode.Mode -> DT.Test -> JS.Expr
928generateCaseValue mode test =
930 DT.IsCtor home name index _ _ ->
932 Mode.Dev _ -> JS.String (Name.toBuilder name)
933 Mode.Prod _ -> JS.Int (ctorToInt home name index)
939 JS.String (Utf8.toBuilder char)
942 JS.String (Utf8.toBuilder string)
945 error "COMPILER BUG - there should never be three tests on a boolean"
948 error "COMPILER BUG - there should never be three tests on a list"
951 error "COMPILER BUG - there should never be three tests on a list"
954 error "COMPILER BUG - there should never be three tests on a tuple"
957generateCaseTest :: Mode.Mode -> Name.Name -> DT.Path -> DT.Test -> JS.Expr
958generateCaseTest mode root path exampleTest =
960 value = pathToJsExpr mode root path
963 DT.IsCtor home name _ _ opts ->
964 if name == Name.bool && home == ModuleName.basics then
969 JS.Access value JsName.dollar
974 JS.Access value JsName.dollar
991 JS.Call (JS.Access value (JsName.fromLocal "valueOf")) []
997 error "COMPILER BUG - there should never be three tests on a list"
1000 error "COMPILER BUG - there should never be three tests on a list"
1003 error "COMPILER BUG - there should never be three tests on a list"
1006 error "COMPILER BUG - there should never be three tests on a list"
1013pathToJsExpr :: Mode.Mode -> Name.Name -> DT.Path -> JS.Expr
1014pathToJsExpr mode root path =
1016 DT.Index index subPath ->
1017 JS.Access (pathToJsExpr mode root subPath) (JsName.fromIndex index)
1022 JS.Access (pathToJsExpr mode root subPath) (JsName.fromIndex Index.first)
1025 pathToJsExpr mode root subPath
1028 JS.Ref (JsName.fromLocal root)
1035generateMain :: Mode.Mode -> ModuleName.Canonical -> Opt.Main -> JS.Expr
1036generateMain mode home main =
1039 JS.Ref (JsName.fromKernel Name.virtualDom "init")
1040 # JS.Ref (JsName.fromGlobal home "main")
1044 Opt.Dynamic msgType decoder ->
1045 JS.Ref (JsName.fromGlobal home "main")
1046 # generateJsExpr mode decoder
1047 # toDebugMetadata mode msgType
1050(#) :: JS.Expr -> JS.Expr -> JS.Expr
1055toDebugMetadata :: Mode.Mode -> Can.Type -> JS.Expr
1056toDebugMetadata mode msgType =
1064 Mode.Dev (Just interfaces) ->
1065 JS.Json $ Encode.object $
1066 [ ("versions", Encode.object [ ("elm", V.encode V.compiler) ])
1067 , ("types", Type.encodeMetadata (Extract.fromMsg interfaces msgType))
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