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.Text.Encoding as Text
21import qualified AST.Canonical as Can
22import qualified AST.Optimized as Opt
23import qualified AST.Module.Name as ModuleName
24import qualified Data.Index as Index
25import qualified Elm.Compiler.Type as Type
26import qualified Elm.Compiler.Type.Extract as Extract
27import qualified Elm.Name as N
28import qualified Elm.Package as Pkg
29import qualified Elm.Compiler.Version as Version
30import qualified Generate.JavaScript.Builder as JS
31import qualified Generate.JavaScript.Mode as Mode
32import qualified Generate.JavaScript.Name as Name
33import qualified Json.Encode as Encode
34import qualified Optimize.DecisionTree as DT
35import qualified Reporting.Region as R
42generateJsExpr :: Mode.Mode -> Opt.Expr -> JS.Expr
43generateJsExpr mode expression =
44 codeToExpr (generate mode expression)
47generate :: Mode.Mode -> Opt.Expr -> Code
48generate mode expression =
57 JS.Call toChar [ JS.String (Text.encodeUtf8Builder char) ]
60 JS.String (Text.encodeUtf8Builder char)
63 JsExpr $ JS.String (Text.encodeUtf8Builder string)
69 JsExpr $ JS.Float float
72 JsExpr $ JS.Ref (Name.fromLocal name)
74 Opt.VarGlobal (Opt.Global home name) ->
75 JsExpr $ JS.Ref (Name.fromGlobal home name)
77 Opt.VarEnum (Opt.Global home name) index ->
80 JsExpr $ JS.Ref (Name.fromGlobal home name)
83 JsExpr $ JS.Int (Index.toMachine index)
85 Opt.VarBox (Opt.Global home name) ->
88 Mode.Dev _ _ -> Name.fromGlobal home name
89 Mode.Prod _ _ -> Name.fromGlobal ModuleName.basics N.identity
91 Opt.VarCycle home name ->
92 JsExpr $ JS.Call (JS.Ref (Name.fromCycle home name)) []
94 Opt.VarDebug name home region unhandledValueName ->
95 JsExpr $ generateDebug name home region unhandledValueName
97 Opt.VarKernel home name ->
98 JsExpr $ JS.Ref (Name.fromKernel home name)
103 JsExpr $ JS.Ref (Name.fromKernel N.list "Nil")
108 (JS.Ref (Name.fromKernel N.list "fromArray"))
109 [ JS.Array $ map (generateJsExpr mode) entries
112 Opt.Function args body ->
113 generateFunction (map Name.fromLocal args) (generate mode body)
115 Opt.Call func args ->
116 JsExpr $ generateCall mode func args
118 Opt.TailCall name args ->
119 JsBlock $ generateTailCall mode name args
121 Opt.If branches final ->
122 generateIf mode branches final
126 generateDef mode def : codeToStmtList (generate mode body)
128 Opt.Destruct (Opt.Destructor name path) body ->
130 pathExpr = generatePath mode path
131 pathDef = JS.Var [ (Name.fromLocal name, Just pathExpr) ]
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 [Name.dollar]
141 JS.Access (JS.Ref Name.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 (Name.fromKernel N.utils "update"))
150 [ generateJsExpr mode record
151 , generateRecord mode fields
155 JsExpr $ generateRecord mode fields
160 JsExpr $ JS.Ref (Name.fromKernel N.utils "Tuple0")
165 Opt.Tuple a b maybeC ->
169 JS.Call (JS.Ref (Name.fromKernel N.utils "Tuple2"))
170 [ generateJsExpr mode a
171 , generateJsExpr mode b
175 JS.Call (JS.Ref (Name.fromKernel N.utils "Tuple3"))
176 [ generateJsExpr mode a
177 , generateJsExpr mode b
178 , generateJsExpr mode c
182 let string = JS.String (Text.encodeUtf8Builder src) in
183 JsExpr $ JS.Object [ ( Name.fromLocal "src", string ) ]
195codeToExpr :: Code -> JS.Expr
201 JsBlock [ JS.Return (Just expr) ] ->
205 JS.Call (JS.Function Nothing [] stmts) []
208codeToStmtList :: Code -> [JS.Stmt]
211 JsExpr (JS.Call (JS.Function Nothing [] stmts) []) ->
215 [ JS.Return (Just expr) ]
221codeToStmt :: Code -> JS.Stmt
224 JsExpr (JS.Call (JS.Function Nothing [] stmts) []) ->
228 JS.Return (Just expr)
241{-# NOINLINE toChar #-}
244 JS.Ref (Name.fromKernel N.utils "chr")
251generateCtor :: Mode.Mode -> Opt.Global -> Index.ZeroBased -> Int -> Code
252generateCtor mode (Opt.Global home name) index arity =
255 Index.indexedMap (\i _ -> Name.fromIndex i) [1 .. arity]
259 Mode.Dev _ _ -> JS.String (N.toBuilder name)
260 Mode.Prod _ _ -> JS.Int (ctorToInt home name index)
262 generateFunction argNames $ JsExpr $ JS.Object $
263 (Name.dollar, ctorTag) : map (\n -> (n, JS.Ref n)) argNames
266ctorToInt :: ModuleName.Canonical -> N.Name -> Index.ZeroBased -> Int
267ctorToInt home name index =
268 if home == ModuleName.dict && name == "RBNode_elm_builtin" || name == "RBEmpty_elm_builtin" then
269 0 - Index.toHuman index
271 Index.toMachine index
278generateRecord :: Mode.Mode -> Map.Map N.Name Opt.Expr -> JS.Expr
279generateRecord mode fields =
281 toPair (field, value) =
282 (generateField mode field, generateJsExpr mode value)
284 JS.Object (map toPair (Map.toList fields))
287generateField :: Mode.Mode -> N.Name -> Name.Name
288generateField mode name =
293 Mode.Prod _ fields ->
302generateDebug :: N.Name -> ModuleName.Canonical -> R.Region -> Maybe N.Name -> JS.Expr
303generateDebug name (ModuleName.Canonical _ home) region unhandledValueName =
304 if name /= "todo" then
305 JS.Ref (Name.fromGlobal ModuleName.debug name)
307 case unhandledValueName of
309 JS.Call (JS.Ref (Name.fromKernel N.debug "todo")) $
310 [ JS.String (N.toBuilder home)
311 , regionToJsExpr region
315 JS.Call (JS.Ref (Name.fromKernel N.debug "todoCase")) $
316 [ JS.String (N.toBuilder home)
317 , regionToJsExpr region
318 , JS.Ref (Name.fromLocal valueName)
322regionToJsExpr :: R.Region -> JS.Expr
323regionToJsExpr (R.Region start end) =
325 [ ( Name.fromLocal "start", positionToJsExpr start )
326 , ( Name.fromLocal "end", positionToJsExpr end )
330positionToJsExpr :: R.Position -> JS.Expr
331positionToJsExpr (R.Position line column) =
333 [ ( Name.fromLocal "line", JS.Int line )
334 , ( Name.fromLocal "column", JS.Int column )
342generateFunction :: [Name.Name] -> Code -> Code
343generateFunction args body =
344 case IntMap.lookup (length args) funcHelpers of
348 [ JS.Function Nothing args $
355 JsExpr $ JS.Function Nothing [arg] $
358 foldr addArg body args
361{-# NOINLINE funcHelpers #-}
362funcHelpers :: IntMap.IntMap JS.Expr
365 map (\n -> (n, JS.Ref (Name.makeF n))) [2..9]
372generateCall :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
373generateCall mode func args =
375 Opt.VarGlobal global@(Opt.Global (ModuleName.Canonical pkg _) _) | pkg == Pkg.core ->
376 generateCoreCall mode global args
381 generateCallHelp mode func args
386 generateJsExpr mode arg
389 generateCallHelp mode func args
392 generateCallHelp mode func args
395generateCallHelp :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
396generateCallHelp mode func args =
398 (generateJsExpr mode func)
399 (map (generateJsExpr mode) args)
402generateGlobalCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
403generateGlobalCall home name args =
404 generateNormalCall (JS.Ref (Name.fromGlobal home name)) args
407generateNormalCall :: JS.Expr -> [JS.Expr] -> JS.Expr
408generateNormalCall func args =
409 case IntMap.lookup (length args) callHelpers of
411 JS.Call helper (func:args)
414 List.foldl' (\f a -> JS.Call f [a]) func args
417{-# NOINLINE callHelpers #-}
418callHelpers :: IntMap.IntMap JS.Expr
421 map (\n -> (n, JS.Ref (Name.makeA n))) [2..9]
428generateCoreCall :: Mode.Mode -> Opt.Global -> [Opt.Expr] -> JS.Expr
429generateCoreCall mode (Opt.Global home@(ModuleName.Canonical _ moduleName) name) args =
430 if moduleName == N.basics then
431 generateBasicsCall mode home name args
433 else if moduleName == N.bitwise then
434 generateBitwiseCall home name (map (generateJsExpr mode) args)
436 else if moduleName == N.tuple then
437 generateTupleCall home name (map (generateJsExpr mode) args)
439 else if moduleName == N.jsArray then
440 generateJsArrayCall home name (map (generateJsExpr mode) args)
443 generateGlobalCall home name (map (generateJsExpr mode) args)
446generateTupleCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
447generateTupleCall home name args =
451 "first" -> JS.Access value (Name.fromLocal "a")
452 "second" -> JS.Access value (Name.fromLocal "b")
453 _ -> generateGlobalCall home name args
456 generateGlobalCall home name args
459generateJsArrayCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
460generateJsArrayCall home name args =
462 [entry] | name == "singleton" -> JS.Array [entry]
463 [index, array] | name == "unsafeGet" -> JS.Index array index
464 _ -> generateGlobalCall home name args
467generateBitwiseCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
468generateBitwiseCall home name args =
472 "complement" -> JS.Prefix JS.PrefixBNot arg
473 _ -> generateGlobalCall home name args
477 "and" -> JS.Infix JS.OpBAnd left right
478 "or" -> JS.Infix JS.OpBOr left right
479 "xor" -> JS.Infix JS.OpBXor left right
480 "shiftLeftBy" -> JS.Infix JS.OpLShift right left
481 "shiftRightBy" -> JS.Infix JS.OpSpRShift right left
482 "shiftRightZfBy" -> JS.Infix JS.OpZfRShift right left
483 _ -> generateGlobalCall home name args
486 generateGlobalCall home name args
489generateBasicsCall :: Mode.Mode -> ModuleName.Canonical -> N.Name -> [Opt.Expr] -> JS.Expr
490generateBasicsCall mode home name args =
493 let arg = generateJsExpr mode elmArg in
495 "not" -> JS.Prefix JS.PrefixLNot arg
496 "negate" -> JS.Prefix JS.PrefixMinus arg
498 "truncate" -> JS.Infix JS.OpBOr arg (JS.Int 0)
499 _ -> generateGlobalCall home name [arg]
501 [elmLeft, elmRight] ->
503 "composeL" -> decomposeL mode elmLeft [elmRight]
504 "composeR" -> decomposeR mode [elmLeft] elmRight
505 "append" -> append mode elmLeft elmRight
506 "apL" -> generateJsExpr mode $ apply elmLeft elmRight
507 "apR" -> generateJsExpr mode $ apply elmRight elmLeft
510 left = generateJsExpr mode elmLeft
511 right = generateJsExpr mode elmRight
514 "add" -> JS.Infix JS.OpAdd left right
515 "sub" -> JS.Infix JS.OpSub left right
516 "mul" -> JS.Infix JS.OpMul left right
517 "fdiv" -> JS.Infix JS.OpDiv left right
518 "idiv" -> JS.Infix JS.OpBOr (JS.Infix JS.OpDiv left right) (JS.Int 0)
519 "eq" -> equal left right
520 "neq" -> notEqual left right
521 "lt" -> cmp JS.OpLT JS.OpLT 0 left right
522 "gt" -> cmp JS.OpGT JS.OpGT 0 left right
523 "le" -> cmp JS.OpLEq JS.OpLT 1 left right
524 "ge" -> cmp JS.OpGEq JS.OpGT (-1) left right
525 "or" -> JS.Infix JS.OpLOr left right
526 "and" -> JS.Infix JS.OpLAnd left right
527 "xor" -> JS.Infix JS.OpStrictNEq left right
528 "remainderBy" -> JS.Infix JS.OpMod right left
529 _ -> generateGlobalCall home name [left, right]
532 generateGlobalCall home name (map (generateJsExpr mode) args)
535equal :: JS.Expr -> JS.Expr -> JS.Expr
537 if isLiteral left || isLiteral right then
540 JS.Call (JS.Ref (Name.fromKernel N.utils "eq")) [left, right]
543notEqual :: JS.Expr -> JS.Expr -> JS.Expr
545 if isLiteral left || isLiteral right then
548 JS.Prefix JS.PrefixLNot $
549 JS.Call (JS.Ref (Name.fromKernel N.utils "eq")) [left, right]
552cmp :: JS.InfixOp -> JS.InfixOp -> Int -> JS.Expr -> JS.Expr -> JS.Expr
553cmp idealOp backupOp backupInt left right =
554 if isLiteral left || isLiteral right then
555 JS.Infix idealOp left right
558 (JS.Call (JS.Ref (Name.fromKernel N.utils "cmp")) [left, right])
562isLiteral :: JS.Expr -> Bool
581decomposeL :: Mode.Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
582decomposeL mode expr funcs =
584 Opt.Call (Opt.VarGlobal (Opt.Global home "composeL")) [left, func]
585 | home == ModuleName.basics ->
586 decomposeL mode left (func:funcs)
589 generateJsExpr mode $
590 Opt.Function [N.dollar] (foldr apply (Opt.VarLocal N.dollar) (expr:funcs))
593decomposeR :: Mode.Mode -> [Opt.Expr] -> Opt.Expr -> JS.Expr
594decomposeR mode funcs expr =
596 Opt.Call (Opt.VarGlobal (Opt.Global home "composeR")) [func, right]
597 | home == ModuleName.basics ->
598 decomposeR mode (func:funcs) right
601 generateJsExpr mode $
602 Opt.Function [N.dollar] (foldr apply (Opt.VarLocal N.dollar) (expr:funcs))
605apply :: Opt.Expr -> Opt.Expr -> Opt.Expr
608 Opt.Accessor field ->
609 Opt.Access value field
612 Opt.Call f (args ++ [value])
615 Opt.Call func [value]
618append :: Mode.Mode -> Opt.Expr -> Opt.Expr -> JS.Expr
619append mode left right =
620 let seqs = generateJsExpr mode left : toSeqs mode right in
621 if any isStringLiteral seqs then
622 foldr1 (JS.Infix JS.OpAdd) seqs
627jsAppend :: JS.Expr -> JS.Expr -> JS.Expr
629 JS.Call (JS.Ref (Name.fromKernel N.utils "ap")) [a, b]
632toSeqs :: Mode.Mode -> Opt.Expr -> [JS.Expr]
635 Opt.Call (Opt.VarGlobal (Opt.Global home "append")) [left, right]
636 | home == ModuleName.basics ->
637 generateJsExpr mode left : toSeqs mode right
640 [generateJsExpr mode expr]
643isStringLiteral :: JS.Expr -> Bool
644isStringLiteral expr =
654-- SIMPLIFY INFIX OPERATORS
657strictEq :: JS.Expr -> JS.Expr -> JS.Expr
661 JS.Prefix JS.PrefixLNot right
664 if bool then right else JS.Prefix JS.PrefixLNot right
669 JS.Prefix JS.PrefixLNot left
672 if bool then left else JS.Prefix JS.PrefixLNot left
675 JS.Infix JS.OpStrictEq left right
678strictNEq :: JS.Expr -> JS.Expr -> JS.Expr
679strictNEq left right =
685 if bool then JS.Prefix JS.PrefixLNot right else right
693 if bool then JS.Prefix JS.PrefixLNot left else left
696 JS.Infix JS.OpStrictNEq left right
703-- TODO check if JS minifiers collapse unnecessary temporary variables
705generateTailCall :: Mode.Mode -> N.Name -> [(N.Name, Opt.Expr)] -> [JS.Stmt]
706generateTailCall mode name args =
708 toTempVars (argName, arg) =
709 ( Name.makeTemp argName, Just (generateJsExpr mode arg) )
711 toRealVars (argName, _) =
713 JS.Assign (JS.LRef (Name.fromLocal argName)) (JS.Ref (Name.makeTemp argName))
715 JS.Var (map toTempVars args)
716 : map toRealVars args
717 ++ [ JS.Continue (Just (Name.fromLocal name)) ]
724generateDef :: Mode.Mode -> Opt.Def -> JS.Stmt
725generateDef mode def =
728 JS.Var [ (Name.fromLocal name, Just (generateJsExpr mode body)) ]
730 Opt.TailDef name argNames body ->
731 JS.Var [ (Name.fromLocal name, Just (codeToExpr (generateTailDef mode name argNames body))) ]
734generateTailDef :: Mode.Mode -> N.Name -> [N.Name] -> Opt.Expr -> Code
735generateTailDef mode name argNames body =
736 generateFunction (map Name.fromLocal argNames) $ JsBlock $
737 [ JS.Labelled (Name.fromLocal name) $
738 JS.While (JS.Bool True) $
739 codeToStmt $ generate mode body
747generatePath :: Mode.Mode -> Opt.Path -> JS.Expr
748generatePath mode path =
750 Opt.Index index subPath ->
751 JS.Access (generatePath mode subPath) (Name.fromIndex index)
754 JS.Ref (Name.fromLocal name)
756 Opt.Field field subPath ->
757 JS.Access (generatePath mode subPath) (generateField mode field)
762 JS.Access (generatePath mode subPath) (Name.fromIndex Index.first)
765 generatePath mode subPath
772generateIf :: Mode.Mode -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> Code
773generateIf mode givenBranches givenFinal =
776 crushIfs givenBranches givenFinal
778 convertBranch (condition, expr) =
779 ( generateJsExpr mode condition
783 branchExprs = map convertBranch branches
784 finalCode = generate mode final
786 if isBlock finalCode || any (isBlock . snd) branchExprs then
787 JsBlock [ foldr addStmtIf (codeToStmt finalCode) branchExprs ]
789 JsExpr $ foldr addExprIf (codeToExpr finalCode) branchExprs
792addExprIf :: (JS.Expr, Code) -> JS.Expr -> JS.Expr
793addExprIf (condition, branch) final =
794 JS.If condition (codeToExpr branch) final
797addStmtIf :: (JS.Expr, Code) -> JS.Stmt -> JS.Stmt
798addStmtIf (condition, branch) final =
799 JS.IfStmt condition (codeToStmt branch) final
802isBlock :: Code -> Bool
809crushIfs :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
810crushIfs branches final =
811 crushIfsHelp [] branches final
815 :: [(Opt.Expr, Opt.Expr)]
816 -> [(Opt.Expr, Opt.Expr)]
818 -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
819crushIfsHelp visitedBranches unvisitedBranches final =
820 case unvisitedBranches of
823 Opt.If subBranches subFinal ->
824 crushIfsHelp visitedBranches subBranches subFinal
827 (reverse visitedBranches, final)
829 visiting : unvisited ->
830 crushIfsHelp (visiting : visitedBranches) unvisited final
837generateCase :: Mode.Mode -> N.Name -> N.Name -> Opt.Decider Opt.Choice -> [(Int, Opt.Expr)] -> [JS.Stmt]
838generateCase mode label root decider jumps =
839 foldr (goto mode label) (generateDecider mode label root decider) jumps
842goto :: Mode.Mode -> N.Name -> (Int, Opt.Expr) -> [JS.Stmt] -> [JS.Stmt]
843goto mode label (index, branch) stmts =
847 (Name.makeLabel label index)
848 (JS.While (JS.Bool True) (JS.Block stmts))
850 labeledDeciderStmt : codeToStmtList (generate mode branch)
853generateDecider :: Mode.Mode -> N.Name -> N.Name -> Opt.Decider Opt.Choice -> [JS.Stmt]
854generateDecider mode label root decisionTree =
856 Opt.Leaf (Opt.Inline branch) ->
857 codeToStmtList (generate mode branch)
859 Opt.Leaf (Opt.Jump index) ->
860 [ JS.Break (Just (Name.makeLabel label index)) ]
862 Opt.Chain testChain success failure ->
864 (List.foldl1' (JS.Infix JS.OpLAnd) (map (generateIfTest mode root) testChain))
865 (JS.Block $ generateDecider mode label root success)
866 (JS.Block $ generateDecider mode label root failure)
869 Opt.FanOut path edges fallback ->
871 (generateCaseTest mode root path (fst (head edges)))
873 (\edge cases -> generateCaseBranch mode label root edge : cases)
874 [ JS.Default (generateDecider mode label root fallback) ]
880generateIfTest :: Mode.Mode -> N.Name -> (DT.Path, DT.Test) -> JS.Expr
881generateIfTest mode root (path, test) =
883 value = pathToJsExpr mode root path
886 DT.IsCtor home name index _ opts ->
890 Mode.Dev _ _ -> JS.Access value Name.dollar
893 Can.Normal -> JS.Access value Name.dollar
899 Mode.Dev _ _ -> JS.String (N.toBuilder name)
900 Mode.Prod _ _ -> JS.Int (ctorToInt home name index)
906 JS.Prefix JS.PrefixLNot value
909 strictEq value (JS.Int int)
912 strictEq (JS.String (Text.encodeUtf8Builder char)) $
914 Mode.Dev _ _ -> JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
915 Mode.Prod _ _ -> value
918 strictEq value (JS.String (Text.encodeUtf8Builder string))
921 JS.Access value (Name.fromLocal "b")
924 JS.Prefix JS.PrefixLNot $
925 JS.Access value (Name.fromLocal "b")
928 error "COMPILER BUG - there should never be tests on a tuple"
932generateCaseBranch :: Mode.Mode -> N.Name -> N.Name -> (DT.Test, Opt.Decider Opt.Choice) -> JS.Case
933generateCaseBranch mode label root (test, subTree) =
935 (generateCaseValue mode test)
936 (generateDecider mode label root subTree)
939generateCaseValue :: Mode.Mode -> DT.Test -> JS.Expr
940generateCaseValue mode test =
942 DT.IsCtor home name index _ _ ->
944 Mode.Dev _ _ -> JS.String (N.toBuilder name)
945 Mode.Prod _ _ -> JS.Int (ctorToInt home name index)
951 JS.String (Text.encodeUtf8Builder char)
954 JS.String (Text.encodeUtf8Builder string)
957 error "COMPILER BUG - there should never be three tests on a boolean"
960 error "COMPILER BUG - there should never be three tests on a list"
963 error "COMPILER BUG - there should never be three tests on a list"
966 error "COMPILER BUG - there should never be three tests on a tuple"
969generateCaseTest :: Mode.Mode -> N.Name -> DT.Path -> DT.Test -> JS.Expr
970generateCaseTest mode root path exampleTest =
972 value = pathToJsExpr mode root path
975 DT.IsCtor home name _ _ opts ->
976 if name == N.bool && home == ModuleName.basics then
981 JS.Access value Name.dollar
986 JS.Access value Name.dollar
1003 JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
1009 error "COMPILER BUG - there should never be three tests on a list"
1012 error "COMPILER BUG - there should never be three tests on a list"
1015 error "COMPILER BUG - there should never be three tests on a list"
1018 error "COMPILER BUG - there should never be three tests on a list"
1025pathToJsExpr :: Mode.Mode -> N.Name -> DT.Path -> JS.Expr
1026pathToJsExpr mode root path =
1028 DT.Index index subPath ->
1029 JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex index)
1034 JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex Index.first)
1037 pathToJsExpr mode root subPath
1040 JS.Ref (Name.fromLocal root)
1047generateMain :: Mode.Mode -> ModuleName.Canonical -> Opt.Main -> JS.Expr
1048generateMain mode home main =
1051 JS.Ref (Name.fromKernel N.virtualDom "init")
1052 # JS.Ref (Name.fromGlobal home "main")
1056 Opt.Dynamic msgType decoder ->
1057 JS.Ref (Name.fromGlobal home "main")
1058 # generateJsExpr mode decoder
1059 # toDebugMetadata mode msgType
1062(#) :: JS.Expr -> JS.Expr -> JS.Expr
1067toDebugMetadata :: Mode.Mode -> Can.Type -> JS.Expr
1068toDebugMetadata mode msgType =
1073 Mode.Dev _ Nothing ->
1076 Mode.Dev _ (Just interfaces) ->
1077 JS.Json $ Encode.object $
1078 [ ("versions", Encode.object [ ("elm", Pkg.encodeVersion Version.version) ])
1079 , ("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