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 AST.Utils.Shader as Shader
26import qualified Data.Index as Index
27import qualified Elm.Compiler.Type as Type
28import qualified Elm.Compiler.Type.Extract as Extract
29import qualified Elm.Version as V
30import qualified Elm.ModuleName as ModuleName
31import qualified Elm.Package as Pkg
32import qualified Generate.JavaScript.Builder as JS
33import qualified Generate.JavaScript.Name as JsName
34import qualified Generate.Mode as Mode
35import qualified Json.Encode as Encode
36import Json.Encode ((==>))
37import qualified Optimize.DecisionTree as DT
38import qualified Reporting.Annotation as A
45generateJsExpr :: Mode.Mode -> Opt.Expr -> JS.Expr
46generateJsExpr mode expression =
47 codeToExpr (generate mode expression)
50generate :: Mode.Mode -> Opt.Expr -> Code
51generate mode expression =
60 JS.Call toChar [ JS.String (Utf8.toBuilder char) ]
63 JS.String (Utf8.toBuilder char)
66 JsExpr $ JS.String (Utf8.toBuilder string)
72 JsExpr $ JS.Float (Utf8.toBuilder float)
75 JsExpr $ JS.Ref (JsName.fromLocal name)
77 Opt.VarGlobal (Opt.Global home name) ->
78 JsExpr $ JS.Ref (JsName.fromGlobal home name)
80 Opt.VarEnum (Opt.Global home name) index ->
83 JsExpr $ JS.Ref (JsName.fromGlobal home name)
86 JsExpr $ JS.Int (Index.toMachine index)
88 Opt.VarBox (Opt.Global home name) ->
91 Mode.Dev _ -> JsName.fromGlobal home name
92 Mode.Prod _ -> JsName.fromGlobal ModuleName.basics Name.identity
94 Opt.VarCycle home name ->
95 JsExpr $ JS.Call (JS.Ref (JsName.fromCycle home name)) []
97 Opt.VarDebug name home region unhandledValueName ->
98 JsExpr $ generateDebug name home region unhandledValueName
100 Opt.VarKernel home name ->
101 JsExpr $ JS.Ref (JsName.fromKernel home name)
106 JsExpr $ JS.Ref (JsName.fromKernel Name.list "Nil")
111 (JS.Ref (JsName.fromKernel Name.list "fromArray"))
112 [ JS.Array $ map (generateJsExpr mode) entries
115 Opt.Function args body ->
116 generateFunction (map JsName.fromLocal args) (generate mode body)
118 Opt.Call func args ->
119 JsExpr $ generateCall mode func args
121 Opt.TailCall name args ->
122 JsBlock $ generateTailCall mode name args
124 Opt.If branches final ->
125 generateIf mode branches final
129 generateDef mode def : codeToStmtList (generate mode body)
131 Opt.Destruct (Opt.Destructor name path) body ->
133 pathDef = JS.Var (JsName.fromLocal name) (generatePath mode path)
135 JsBlock $ pathDef : codeToStmtList (generate mode body)
137 Opt.Case label root decider jumps ->
138 JsBlock $ generateCase mode label root decider jumps
140 Opt.Accessor field ->
141 JsExpr $ JS.Function Nothing [JsName.dollar]
143 JS.Access (JS.Ref JsName.dollar) (generateField mode field)
146 Opt.Access record field ->
147 JsExpr $ JS.Access (generateJsExpr mode record) (generateField mode field)
149 Opt.Update record fields ->
151 JS.Call (JS.Ref (JsName.fromKernel Name.utils "update"))
152 [ generateJsExpr mode record
153 , generateRecord mode fields
157 JsExpr $ generateRecord mode fields
162 JsExpr $ JS.Ref (JsName.fromKernel Name.utils "Tuple0")
167 Opt.Tuple a b maybeC ->
171 JS.Call (JS.Ref (JsName.fromKernel Name.utils "Tuple2"))
172 [ generateJsExpr mode a
173 , generateJsExpr mode b
177 JS.Call (JS.Ref (JsName.fromKernel Name.utils "Tuple3"))
178 [ generateJsExpr mode a
179 , generateJsExpr mode b
180 , generateJsExpr mode c
183 Opt.Shader src attributes uniforms ->
186 ( JsName.fromLocal field
187 , JS.String (JsName.toBuilder (generateField mode field))
190 toTranslationObject fields =
191 JS.Object (map toTranlation (Set.toList fields))
194 [ ( JsName.fromLocal "src", JS.String (Shader.toJsStringBuilder src) )
195 , ( JsName.fromLocal "attributes", toTranslationObject attributes )
196 , ( JsName.fromLocal "uniforms", toTranslationObject uniforms )
209codeToExpr :: Code -> JS.Expr
215 JsBlock [ JS.Return expr ] ->
219 JS.Call (JS.Function Nothing [] stmts) []
222codeToStmtList :: Code -> [JS.Stmt]
225 JsExpr (JS.Call (JS.Function Nothing [] stmts) []) ->
235codeToStmt :: Code -> JS.Stmt
238 JsExpr (JS.Call (JS.Function Nothing [] stmts) []) ->
255{-# NOINLINE toChar #-}
258 JS.Ref (JsName.fromKernel Name.utils "chr")
265generateCtor :: Mode.Mode -> Opt.Global -> Index.ZeroBased -> Int -> Code
266generateCtor mode (Opt.Global home name) index arity =
269 Index.indexedMap (\i _ -> JsName.fromIndex i) [1 .. arity]
273 Mode.Dev _ -> JS.String (Name.toBuilder name)
274 Mode.Prod _ -> JS.Int (ctorToInt home name index)
276 generateFunction argNames $ JsExpr $ JS.Object $
277 (JsName.dollar, ctorTag) : map (\n -> (n, JS.Ref n)) argNames
280ctorToInt :: ModuleName.Canonical -> Name.Name -> Index.ZeroBased -> Int
281ctorToInt home name index =
282 if home == ModuleName.dict && name == "RBNode_elm_builtin" || name == "RBEmpty_elm_builtin" then
283 0 - Index.toHuman index
285 Index.toMachine index
292generateRecord :: Mode.Mode -> Map.Map Name.Name Opt.Expr -> JS.Expr
293generateRecord mode fields =
295 toPair (field, value) =
296 (generateField mode field, generateJsExpr mode value)
298 JS.Object (map toPair (Map.toList fields))
301generateField :: Mode.Mode -> Name.Name -> JsName.Name
302generateField mode name =
305 JsName.fromLocal name
316generateDebug :: Name.Name -> ModuleName.Canonical -> A.Region -> Maybe Name.Name -> JS.Expr
317generateDebug name (ModuleName.Canonical _ home) region unhandledValueName =
318 if name /= "todo" then
319 JS.Ref (JsName.fromGlobal ModuleName.debug name)
321 case unhandledValueName of
323 JS.Call (JS.Ref (JsName.fromKernel Name.debug "todo")) $
324 [ JS.String (Name.toBuilder home)
325 , regionToJsExpr region
329 JS.Call (JS.Ref (JsName.fromKernel Name.debug "todoCase")) $
330 [ JS.String (Name.toBuilder home)
331 , regionToJsExpr region
332 , JS.Ref (JsName.fromLocal valueName)
336regionToJsExpr :: A.Region -> JS.Expr
337regionToJsExpr (A.Region start end) =
339 [ ( JsName.fromLocal "start", positionToJsExpr start )
340 , ( JsName.fromLocal "end", positionToJsExpr end )
344positionToJsExpr :: A.Position -> JS.Expr
345positionToJsExpr (A.Position line column) =
347 [ ( JsName.fromLocal "line", JS.Int (fromIntegral line) )
348 , ( JsName.fromLocal "column", JS.Int (fromIntegral column) )
356generateFunction :: [JsName.Name] -> Code -> Code
357generateFunction args body =
358 case IntMap.lookup (length args) funcHelpers of
362 [ JS.Function Nothing args $
369 JsExpr $ JS.Function Nothing [arg] $
372 foldr addArg body args
375{-# NOINLINE funcHelpers #-}
376funcHelpers :: IntMap.IntMap JS.Expr
379 map (\n -> (n, JS.Ref (JsName.makeF n))) [2..9]
386generateCall :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
387generateCall mode func args =
389 Opt.VarGlobal global@(Opt.Global (ModuleName.Canonical pkg _) _) | pkg == Pkg.core ->
390 generateCoreCall mode global args
395 generateCallHelp mode func args
400 generateJsExpr mode arg
403 generateCallHelp mode func args
406 generateCallHelp mode func args
409generateCallHelp :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
410generateCallHelp mode func args =
412 (generateJsExpr mode func)
413 (map (generateJsExpr mode) args)
416generateGlobalCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
417generateGlobalCall home name args =
418 generateNormalCall (JS.Ref (JsName.fromGlobal home name)) args
421generateNormalCall :: JS.Expr -> [JS.Expr] -> JS.Expr
422generateNormalCall func args =
423 case IntMap.lookup (length args) callHelpers of
425 JS.Call helper (func:args)
428 List.foldl' (\f a -> JS.Call f [a]) func args
431{-# NOINLINE callHelpers #-}
432callHelpers :: IntMap.IntMap JS.Expr
435 map (\n -> (n, JS.Ref (JsName.makeA n))) [2..9]
442generateCoreCall :: Mode.Mode -> Opt.Global -> [Opt.Expr] -> JS.Expr
443generateCoreCall mode (Opt.Global home@(ModuleName.Canonical _ moduleName) name) args =
444 if moduleName == Name.basics then
445 generateBasicsCall mode home name args
447 else if moduleName == Name.bitwise then
448 generateBitwiseCall home name (map (generateJsExpr mode) args)
450 else if moduleName == Name.tuple then
451 generateTupleCall home name (map (generateJsExpr mode) args)
453 else if moduleName == Name.jsArray then
454 generateJsArrayCall home name (map (generateJsExpr mode) args)
457 generateGlobalCall home name (map (generateJsExpr mode) args)
460generateTupleCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
461generateTupleCall home name args =
465 "first" -> JS.Access value (JsName.fromLocal "a")
466 "second" -> JS.Access value (JsName.fromLocal "b")
467 _ -> generateGlobalCall home name args
470 generateGlobalCall home name args
473generateJsArrayCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
474generateJsArrayCall home name args =
476 [entry] | name == "singleton" -> JS.Array [entry]
477 [index, array] | name == "unsafeGet" -> JS.Index array index
478 _ -> generateGlobalCall home name args
481generateBitwiseCall :: ModuleName.Canonical -> Name.Name -> [JS.Expr] -> JS.Expr
482generateBitwiseCall home name args =
486 "complement" -> JS.Prefix JS.PrefixComplement arg
487 _ -> generateGlobalCall home name args
491 "and" -> JS.Infix JS.OpBitwiseAnd left right
492 "or" -> JS.Infix JS.OpBitwiseOr left right
493 "xor" -> JS.Infix JS.OpBitwiseXor left right
494 "shiftLeftBy" -> JS.Infix JS.OpLShift right left
495 "shiftRightBy" -> JS.Infix JS.OpSpRShift right left
496 "shiftRightZfBy" -> JS.Infix JS.OpZfRShift right left
497 _ -> generateGlobalCall home name args
500 generateGlobalCall home name args
503generateBasicsCall :: Mode.Mode -> ModuleName.Canonical -> Name.Name -> [Opt.Expr] -> JS.Expr
504generateBasicsCall mode home name args =
507 let arg = generateJsExpr mode elmArg in
509 "not" -> JS.Prefix JS.PrefixNot arg
510 "negate" -> JS.Prefix JS.PrefixNegate arg
512 "truncate" -> JS.Infix JS.OpBitwiseOr arg (JS.Int 0)
513 _ -> generateGlobalCall home name [arg]
515 [elmLeft, elmRight] ->
517 -- NOTE: removed "composeL" and "composeR" because of this issue:
518 -- https://github.com/elm/compiler/issues/1722
519 "append" -> append mode elmLeft elmRight
520 "apL" -> generateJsExpr mode $ apply elmLeft elmRight
521 "apR" -> generateJsExpr mode $ apply elmRight elmLeft
524 left = generateJsExpr mode elmLeft
525 right = generateJsExpr mode elmRight
528 "add" -> JS.Infix JS.OpAdd left right
529 "sub" -> JS.Infix JS.OpSub left right
530 "mul" -> JS.Infix JS.OpMul left right
531 "fdiv" -> JS.Infix JS.OpDiv left right
532 "idiv" -> JS.Infix JS.OpBitwiseOr (JS.Infix JS.OpDiv left right) (JS.Int 0)
533 "eq" -> equal left right
534 "neq" -> notEqual left right
535 "lt" -> cmp JS.OpLt JS.OpLt 0 left right
536 "gt" -> cmp JS.OpGt JS.OpGt 0 left right
537 "le" -> cmp JS.OpLe JS.OpLt 1 left right
538 "ge" -> cmp JS.OpGe JS.OpGt (-1) left right
539 "or" -> JS.Infix JS.OpOr left right
540 "and" -> JS.Infix JS.OpAnd left right
541 "xor" -> JS.Infix JS.OpNe left right
542 "remainderBy" -> JS.Infix JS.OpMod right left
543 _ -> generateGlobalCall home name [left, right]
546 generateGlobalCall home name (map (generateJsExpr mode) args)
549equal :: JS.Expr -> JS.Expr -> JS.Expr
551 if isLiteral left || isLiteral right then
554 JS.Call (JS.Ref (JsName.fromKernel Name.utils "eq")) [left, right]
557notEqual :: JS.Expr -> JS.Expr -> JS.Expr
559 if isLiteral left || isLiteral right then
562 JS.Prefix JS.PrefixNot $
563 JS.Call (JS.Ref (JsName.fromKernel Name.utils "eq")) [left, right]
566cmp :: JS.InfixOp -> JS.InfixOp -> Int -> JS.Expr -> JS.Expr -> JS.Expr
567cmp idealOp backupOp backupInt left right =
568 if isLiteral left || isLiteral right then
569 JS.Infix idealOp left right
572 (JS.Call (JS.Ref (JsName.fromKernel Name.utils "cmp")) [left, right])
576isLiteral :: JS.Expr -> Bool
595apply :: Opt.Expr -> Opt.Expr -> Opt.Expr
598 Opt.Accessor field ->
599 Opt.Access value field
602 Opt.Call f (args ++ [value])
605 Opt.Call func [value]
608append :: Mode.Mode -> Opt.Expr -> Opt.Expr -> JS.Expr
609append mode left right =
610 let seqs = generateJsExpr mode left : toSeqs mode right in
611 if any isStringLiteral seqs then
612 foldr1 (JS.Infix JS.OpAdd) seqs
617jsAppend :: JS.Expr -> JS.Expr -> JS.Expr
619 JS.Call (JS.Ref (JsName.fromKernel Name.utils "ap")) [a, b]
622toSeqs :: Mode.Mode -> Opt.Expr -> [JS.Expr]
625 Opt.Call (Opt.VarGlobal (Opt.Global home "append")) [left, right]
626 | home == ModuleName.basics ->
627 generateJsExpr mode left : toSeqs mode right
630 [generateJsExpr mode expr]
633isStringLiteral :: JS.Expr -> Bool
634isStringLiteral expr =
644-- SIMPLIFY INFIX OPERATORS
647strictEq :: JS.Expr -> JS.Expr -> JS.Expr
651 JS.Prefix JS.PrefixNot right
654 if bool then right else JS.Prefix JS.PrefixNot right
659 JS.Prefix JS.PrefixNot left
662 if bool then left else JS.Prefix JS.PrefixNot left
665 JS.Infix JS.OpEq left right
668strictNEq :: JS.Expr -> JS.Expr -> JS.Expr
669strictNEq left right =
672 JS.Prefix JS.PrefixNot (JS.Prefix JS.PrefixNot right)
675 if bool then JS.Prefix JS.PrefixNot right else right
680 JS.Prefix JS.PrefixNot (JS.Prefix JS.PrefixNot left)
683 if bool then JS.Prefix JS.PrefixNot left else left
686 JS.Infix JS.OpNe left right
693-- TODO check if JS minifiers collapse unnecessary temporary variables
695generateTailCall :: Mode.Mode -> Name.Name -> [(Name.Name, Opt.Expr)] -> [JS.Stmt]
696generateTailCall mode name args =
698 toTempVars (argName, arg) =
699 ( JsName.makeTemp argName, generateJsExpr mode arg )
701 toRealVars (argName, _) =
703 JS.Assign (JS.LRef (JsName.fromLocal argName)) (JS.Ref (JsName.makeTemp argName))
705 JS.Vars (map toTempVars args)
706 : map toRealVars args
707 ++ [ JS.Continue (Just (JsName.fromLocal name)) ]
714generateDef :: Mode.Mode -> Opt.Def -> JS.Stmt
715generateDef mode def =
718 JS.Var (JsName.fromLocal name) (generateJsExpr mode body)
720 Opt.TailDef name argNames body ->
721 JS.Var (JsName.fromLocal name) (codeToExpr (generateTailDef mode name argNames body))
724generateTailDef :: Mode.Mode -> Name.Name -> [Name.Name] -> Opt.Expr -> Code
725generateTailDef mode name argNames body =
726 generateFunction (map JsName.fromLocal argNames) $ JsBlock $
727 [ JS.Labelled (JsName.fromLocal name) $
728 JS.While (JS.Bool True) $
729 codeToStmt $ generate mode body
737generatePath :: Mode.Mode -> Opt.Path -> JS.Expr
738generatePath mode path =
740 Opt.Index index subPath ->
741 JS.Access (generatePath mode subPath) (JsName.fromIndex index)
744 JS.Ref (JsName.fromLocal name)
746 Opt.Field field subPath ->
747 JS.Access (generatePath mode subPath) (generateField mode field)
752 JS.Access (generatePath mode subPath) (JsName.fromIndex Index.first)
755 generatePath mode subPath
762generateIf :: Mode.Mode -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> Code
763generateIf mode givenBranches givenFinal =
766 crushIfs givenBranches givenFinal
768 convertBranch (condition, expr) =
769 ( generateJsExpr mode condition
773 branchExprs = map convertBranch branches
774 finalCode = generate mode final
776 if isBlock finalCode || any (isBlock . snd) branchExprs then
777 JsBlock [ foldr addStmtIf (codeToStmt finalCode) branchExprs ]
779 JsExpr $ foldr addExprIf (codeToExpr finalCode) branchExprs
782addExprIf :: (JS.Expr, Code) -> JS.Expr -> JS.Expr
783addExprIf (condition, branch) final =
784 JS.If condition (codeToExpr branch) final
787addStmtIf :: (JS.Expr, Code) -> JS.Stmt -> JS.Stmt
788addStmtIf (condition, branch) final =
789 JS.IfStmt condition (codeToStmt branch) final
792isBlock :: Code -> Bool
799crushIfs :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
800crushIfs branches final =
801 crushIfsHelp [] branches final
805 :: [(Opt.Expr, Opt.Expr)]
806 -> [(Opt.Expr, Opt.Expr)]
808 -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
809crushIfsHelp visitedBranches unvisitedBranches final =
810 case unvisitedBranches of
813 Opt.If subBranches subFinal ->
814 crushIfsHelp visitedBranches subBranches subFinal
817 (reverse visitedBranches, final)
819 visiting : unvisited ->
820 crushIfsHelp (visiting : visitedBranches) unvisited final
827generateCase :: Mode.Mode -> Name.Name -> Name.Name -> Opt.Decider Opt.Choice -> [(Int, Opt.Expr)] -> [JS.Stmt]
828generateCase mode label root decider jumps =
829 foldr (goto mode label) (generateDecider mode label root decider) jumps
832goto :: Mode.Mode -> Name.Name -> (Int, Opt.Expr) -> [JS.Stmt] -> [JS.Stmt]
833goto mode label (index, branch) stmts =
837 (JsName.makeLabel label index)
838 (JS.While (JS.Bool True) (JS.Block stmts))
840 labeledDeciderStmt : codeToStmtList (generate mode branch)
843generateDecider :: Mode.Mode -> Name.Name -> Name.Name -> Opt.Decider Opt.Choice -> [JS.Stmt]
844generateDecider mode label root decisionTree =
846 Opt.Leaf (Opt.Inline branch) ->
847 codeToStmtList (generate mode branch)
849 Opt.Leaf (Opt.Jump index) ->
850 [ JS.Break (Just (JsName.makeLabel label index)) ]
852 Opt.Chain testChain success failure ->
854 (List.foldl1' (JS.Infix JS.OpAnd) (map (generateIfTest mode root) testChain))
855 (JS.Block $ generateDecider mode label root success)
856 (JS.Block $ generateDecider mode label root failure)
859 Opt.FanOut path edges fallback ->
861 (generateCaseTest mode root path (fst (head edges)))
863 (\edge cases -> generateCaseBranch mode label root edge : cases)
864 [ JS.Default (generateDecider mode label root fallback) ]
870generateIfTest :: Mode.Mode -> Name.Name -> (DT.Path, DT.Test) -> JS.Expr
871generateIfTest mode root (path, test) =
873 value = pathToJsExpr mode root path
876 DT.IsCtor home name index _ opts ->
880 Mode.Dev _ -> JS.Access value JsName.dollar
883 Can.Normal -> JS.Access value JsName.dollar
889 Mode.Dev _ -> JS.String (Name.toBuilder name)
890 Mode.Prod _ -> JS.Int (ctorToInt home name index)
896 JS.Prefix JS.PrefixNot value
899 strictEq value (JS.Int int)
902 strictEq (JS.String (Utf8.toBuilder char)) $
904 Mode.Dev _ -> JS.Call (JS.Access value (JsName.fromLocal "valueOf")) []
908 strictEq value (JS.String (Utf8.toBuilder string))
911 JS.Access value (JsName.fromLocal "b")
914 JS.Prefix JS.PrefixNot $
915 JS.Access value (JsName.fromLocal "b")
918 error "COMPILER BUG - there should never be tests on a tuple"
922generateCaseBranch :: Mode.Mode -> Name.Name -> Name.Name -> (DT.Test, Opt.Decider Opt.Choice) -> JS.Case
923generateCaseBranch mode label root (test, subTree) =
925 (generateCaseValue mode test)
926 (generateDecider mode label root subTree)
929generateCaseValue :: Mode.Mode -> DT.Test -> JS.Expr
930generateCaseValue mode test =
932 DT.IsCtor home name index _ _ ->
934 Mode.Dev _ -> JS.String (Name.toBuilder name)
935 Mode.Prod _ -> JS.Int (ctorToInt home name index)
941 JS.String (Utf8.toBuilder char)
944 JS.String (Utf8.toBuilder string)
947 error "COMPILER BUG - there should never be three tests on a boolean"
950 error "COMPILER BUG - there should never be three tests on a list"
953 error "COMPILER BUG - there should never be three tests on a list"
956 error "COMPILER BUG - there should never be three tests on a tuple"
959generateCaseTest :: Mode.Mode -> Name.Name -> DT.Path -> DT.Test -> JS.Expr
960generateCaseTest mode root path exampleTest =
962 value = pathToJsExpr mode root path
965 DT.IsCtor home name _ _ opts ->
966 if name == Name.bool && home == ModuleName.basics then
971 JS.Access value JsName.dollar
976 JS.Access value JsName.dollar
993 JS.Call (JS.Access value (JsName.fromLocal "valueOf")) []
999 error "COMPILER BUG - there should never be three tests on a list"
1002 error "COMPILER BUG - there should never be three tests on a list"
1005 error "COMPILER BUG - there should never be three tests on a list"
1008 error "COMPILER BUG - there should never be three tests on a list"
1015pathToJsExpr :: Mode.Mode -> Name.Name -> DT.Path -> JS.Expr
1016pathToJsExpr mode root path =
1018 DT.Index index subPath ->
1019 JS.Access (pathToJsExpr mode root subPath) (JsName.fromIndex index)
1024 JS.Access (pathToJsExpr mode root subPath) (JsName.fromIndex Index.first)
1027 pathToJsExpr mode root subPath
1030 JS.Ref (JsName.fromLocal root)
1037generateMain :: Mode.Mode -> ModuleName.Canonical -> Opt.Main -> JS.Expr
1038generateMain mode home main =
1041 JS.Ref (JsName.fromKernel Name.virtualDom "init")
1042 # JS.Ref (JsName.fromGlobal home "main")
1046 Opt.Dynamic msgType decoder ->
1047 JS.Ref (JsName.fromGlobal home "main")
1048 # generateJsExpr mode decoder
1049 # toDebugMetadata mode msgType
1052(#) :: JS.Expr -> JS.Expr -> JS.Expr
1057toDebugMetadata :: Mode.Mode -> Can.Type -> JS.Expr
1058toDebugMetadata mode msgType =
1066 Mode.Dev (Just interfaces) ->
1067 JS.Json $ Encode.object $
1068 [ "versions" ==> Encode.object [ "elm" ==> V.encode V.compiler ]
1069 , "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