@@ -76,6 +76,20 @@ generate mode expression =
76 Opt.VarGlobal (Opt.Global home name) ->
76 Opt.VarGlobal (Opt.Global home name) ->
77 JsExpr $ JS.Ref (Name.fromGlobal home name)
77 JsExpr $ JS.Ref (Name.fromGlobal home name)
79+ Opt.VarEnum (Opt.Global home name) index ->
82+ JsExpr $ JS.Ref (Name.fromGlobal home name)
85+ JsExpr $ JS.Int (Index.toMachine index)
87+ Opt.VarBox (Opt.Global home name) ->
90+ Name.Debug _ -> Name.fromGlobal home name
91+ Name.Prod _ _ -> Name.fromGlobal ModuleName.basics N.identity
79 Opt.VarCycle home name ->
93 Opt.VarCycle home name ->
80 JsExpr $ JS.Call (JS.Ref (Name.fromCycle home name)) []
94 JsExpr $ JS.Call (JS.Ref (Name.fromCycle home name)) []
@@ -108,12 +122,16 @@ generate mode expression =
108 JsBlock $
122 JsBlock $
109 generateDef mode def : codeToStmtList (generate mode body)
123 generateDef mode def : codeToStmtList (generate mode body)
125+ Opt.Destruct (Opt.Destructor name path) body ->
127+ pathExpr = generatePath mode path
128+ pathDef = JS.Var [ (Name.fromLocal name, Just pathExpr) ]
130+ JsBlock $ pathDef : codeToStmtList (generate mode body)
111 Opt.Case label root decider jumps ->
132 Opt.Case label root decider jumps ->
112 JsBlock $ generateCase mode label root decider jumps
133 JsBlock $ generateCase mode label root decider jumps
114− Opt.Index expr index ->
115− JsExpr $ JS.Access (generateJsExpr mode expr) (Name.fromInt index)
117 Opt.Accessor field ->
135 Opt.Accessor field ->
118 JsExpr $ JS.Function Nothing [Name.dollar]
136 JsExpr $ JS.Function Nothing [Name.dollar]
119 [ JS.Return $ Just $
137 [ JS.Return $ Just $
@@ -134,7 +152,12 @@ generate mode expression =
134 JsExpr $ generateRecord mode fields
152 JsExpr $ generateRecord mode fields
136 Opt.Unit ->
154 Opt.Unit ->
137− JsExpr $ JS.Ref (Name.fromKernel N.utils "Tuple0")
157+ JsExpr $ JS.Ref (Name.fromKernel N.utils "Tuple0")
139 Opt.Tuple a b maybeC ->
162 Opt.Tuple a b maybeC ->
@@ -216,21 +239,19 @@ toChar =
219−generateCtor :: Mode -> N.Name -> Index.ZeroBased -> Int -> ([Name.Name], Code)
242+generateCtor :: Mode -> N.Name -> Index.ZeroBased -> Int -> Code
220generateCtor mode name index arity =
243generateCtor mode name index arity =
222− argNames = map Name.fromInt [1 .. arity]
245+ argNames =
223− argFields = map (\n -> (n, JS.Ref n)) argNames
246+ Index.indexedMap (\i _ -> Name.fromIndex i) [1 .. arity]
226 case mode of
249 case mode of
228− ( Name.dollar, JS.String (N.toBuilder name) )
250+ Name.Debug _ -> JS.String (N.toBuilder name)
230− Name.Prod _ _ ->
251+ Name.Prod _ _ -> JS.Int (Index.toMachine index)
231− ( Name.dollar, JS.Int (Index.toZeroBased index) )
233− ( argNames, JsExpr (JS.Object (tag:argFields)) )
253+ generateFunction argNames $ JsExpr $ JS.Object $
254+ (Name.dollar, ctorTag) : map (\n -> (n, JS.Ref n)) argNames
@@ -334,14 +355,32 @@ generateCall mode func args =
334 Opt.VarGlobal global@(Opt.Global (ModuleName.Canonical pkg _) _) | pkg == Pkg.core ->
355 Opt.VarGlobal global@(Opt.Global (ModuleName.Canonical pkg _) _) | pkg == Pkg.core ->
335 generateCoreCall mode global args
356 generateCoreCall mode global args
361+ generateCallHelp mode func args
366+ generateJsExpr mode arg
369+ generateCallHelp mode func args
338− generateNormalCall
372+ generateCallHelp mode func args
339− (generateJsExpr mode func)
340− (map (generateJsExpr mode) args)
375+generateCallHelp :: Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
376+generateCallHelp mode func args =
378+ (generateJsExpr mode func)
379+ (map (generateJsExpr mode) args)
343−generateNormalCall' :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
382+generateGlobalCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
344−generateNormalCall' home name args =
383+generateGlobalCall home name args =
345 generateNormalCall (JS.Ref (Name.fromGlobal home name)) args
384 generateNormalCall (JS.Ref (Name.fromGlobal home name)) args
@@ -385,8 +424,11 @@ generateCoreCall mode (Opt.Global home@(ModuleName.Canonical _ moduleName) name)
385 else if moduleName == N.tuple then
424 else if moduleName == N.tuple then
386 generateTupleCall home name (map (generateJsExpr mode) args)
425 generateTupleCall home name (map (generateJsExpr mode) args)
427+ else if moduleName == N.jsArray then
428+ generateJsArrayCall home name (map (generateJsExpr mode) args)
389− generateNormalCall' home name (map (generateJsExpr mode) args)
431+ generateGlobalCall home name (map (generateJsExpr mode) args)
392generateTupleCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
434generateTupleCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
@@ -396,10 +438,18 @@ generateTupleCall home name args =
396 case name of
438 case name of
397 "first" -> JS.Access value (Name.fromLocal "a")
439 "first" -> JS.Access value (Name.fromLocal "a")
398 "second" -> JS.Access value (Name.fromLocal "b")
440 "second" -> JS.Access value (Name.fromLocal "b")
399− _ -> generateNormalCall' home name args
441+ _ -> generateGlobalCall home name args
402− generateNormalCall' home name args
444+ generateGlobalCall home name args
447+generateJsArrayCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
448+generateJsArrayCall home name args =
450+ [entry] | name == "singleton" -> JS.Array [entry]
451+ [index, array] | name == "unsafeGet" -> JS.Index array index
452+ _ -> generateGlobalCall home name args
405generateBitwiseCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
455generateBitwiseCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
@@ -408,7 +458,7 @@ generateBitwiseCall home name args =
409 case name of
459 case name of
410 "complement" -> JS.Prefix JS.PrefixBNot arg
460 "complement" -> JS.Prefix JS.PrefixBNot arg
411− _ -> generateNormalCall' home name args
461+ _ -> generateGlobalCall home name args
413 [left,right] ->
463 [left,right] ->
414 case name of
464 case name of
@@ -418,10 +468,10 @@ generateBitwiseCall home name args =
418 "shiftLeftBy" -> JS.Infix JS.OpLShift right left
468 "shiftLeftBy" -> JS.Infix JS.OpLShift right left
419 "shiftRightBy" -> JS.Infix JS.OpSpRShift right left
469 "shiftRightBy" -> JS.Infix JS.OpSpRShift right left
420 "shiftRightZfBy" -> JS.Infix JS.OpZfRShift right left
470 "shiftRightZfBy" -> JS.Infix JS.OpZfRShift right left
421− _ -> generateNormalCall' home name args
471+ _ -> generateGlobalCall home name args
424− generateNormalCall' home name args
474+ generateGlobalCall home name args
427generateBasicsCall :: Mode -> ModuleName.Canonical -> N.Name -> [Opt.Expr] -> JS.Expr
477generateBasicsCall :: Mode -> ModuleName.Canonical -> N.Name -> [Opt.Expr] -> JS.Expr
@@ -433,7 +483,7 @@ generateBasicsCall mode home name args =
433 "not" -> JS.Prefix JS.PrefixLNot arg
483 "not" -> JS.Prefix JS.PrefixLNot arg
434 "toFloat" -> arg
484 "toFloat" -> arg
435 "truncate" -> JS.Infix JS.OpBOr arg (JS.Int 0)
485 "truncate" -> JS.Infix JS.OpBOr arg (JS.Int 0)
436− _ -> generateNormalCall' home name [arg]
486+ _ -> generateGlobalCall home name [arg]
438 [elmLeft, elmRight] ->
488 [elmLeft, elmRight] ->
439 case name of
489 case name of
@@ -462,10 +512,10 @@ generateBasicsCall mode home name args =
462 "or" -> JS.Infix JS.OpLOr left right
512 "or" -> JS.Infix JS.OpLOr left right
463 "and" -> JS.Infix JS.OpLAnd left right
513 "and" -> JS.Infix JS.OpLAnd left right
464 "xor" -> JS.Infix JS.OpStrictNEq left right
514 "xor" -> JS.Infix JS.OpStrictNEq left right
465− _ -> generateNormalCall' home name [left, right]
515+ _ -> generateGlobalCall home name [left, right]
468− generateNormalCall' home name (map (generateJsExpr mode) args)
518+ generateGlobalCall home name (map (generateJsExpr mode) args)
471equal :: JS.Expr -> JS.Expr -> JS.Expr
521equal :: JS.Expr -> JS.Expr -> JS.Expr
@@ -676,6 +726,31 @@ generateDef mode def =
732+generatePath :: Mode -> Opt.Path -> JS.Expr
733+generatePath mode path =
735+ Opt.Index index subPath ->
736+ JS.Access (generatePath mode subPath) (Name.fromIndex index)
739+ JS.Ref (Name.fromLocal name)
741+ Opt.Field field subPath ->
742+ JS.Access (generatePath mode subPath) (Name.fromField mode field)
744+ Opt.Unbox subPath ->
747+ JS.Access (generatePath mode subPath) (Name.fromIndex Index.first)
750+ generatePath mode subPath
679-- GENERATE IFS
754-- GENERATE IFS
@@ -770,45 +845,69 @@ generateDecider mode label root decisionTree =
770 [ JS.Break (Just (Name.makeLabel label index)) ]
845 [ JS.Break (Just (Name.makeLabel label index)) ]
772 Opt.Chain testChain success failure ->
847 Opt.Chain testChain success failure ->
774− makeTest (path, test) =
776− (pathToTestableExpr mode root path test)
777− (testToExpr mode test)
779 [ JS.IfStmt
848 [ JS.IfStmt
780− (List.foldl1' (JS.Infix JS.OpLAnd) (map makeTest testChain))
849+ (List.foldl1' (JS.Infix JS.OpLAnd) (map (generateIfTest mode root) testChain))
781 (JS.Block $ generateDecider mode label root success)
850 (JS.Block $ generateDecider mode label root success)
782 (JS.Block $ generateDecider mode label root failure)
851 (JS.Block $ generateDecider mode label root failure)
785 Opt.FanOut path edges fallback ->
854 Opt.FanOut path edges fallback ->
786 [ JS.Switch
855 [ JS.Switch
787− (pathToTestableExpr mode root path (fst (head edges)))
856+ (generateCaseTest mode root path (fst (head edges)))
789− (addCase mode label root)
858+ (\edge cases -> generateCaseBranch mode label root edge : cases)
790 [ JS.Default (generateDecider mode label root fallback) ]
859 [ JS.Default (generateDecider mode label root fallback) ]
796−addCase :: Mode -> N.Name -> N.Name -> (DT.Test, Opt.Decider Opt.Choice) -> [JS.Case] -> [JS.Case]
865+generateIfTest :: Mode -> N.Name -> (DT.Path, DT.Test) -> JS.Expr
797−addCase mode label root (test, subTree) cases =
866+generateIfTest mode root (path, test) =
798− let stmts = generateDecider mode label root subTree in
867+ let
799− JS.Case (testToExpr mode test) stmts : cases
868+ value = pathToJsExpr mode root path
871+ DT.IsCtor name index _ _ ->
872+ strictEq (JS.Access value Name.dollar) $
874+ Name.Debug _ -> JS.String (N.toBuilder name)
875+ Name.Prod _ _ -> JS.Int (Index.toMachine index)
878+ strictEq value (JS.Int int)
881+ strictEq (JS.String (Text.encodeUtf8Builder char)) $
883+ Name.Debug _ -> JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
884+ Name.Prod _ _ -> value
887+ strictEq value (JS.String (Text.encodeUtf8Builder string))
890+ JS.Access value (Name.fromLocal "b")
893+ JS.Prefix JS.PrefixLNot $
894+ JS.Access value (Name.fromLocal "b")
897+generateCaseBranch :: Mode -> N.Name -> N.Name -> (DT.Test, Opt.Decider Opt.Choice) -> JS.Case
898+generateCaseBranch mode label root (test, subTree) =
900+ (generateCaseValue mode test)
901+ (generateDecider mode label root subTree)
802−testToExpr :: Mode -> DT.Test -> JS.Expr
904+generateCaseValue :: Mode -> DT.Test -> JS.Expr
803−testToExpr mode test =
905+generateCaseValue mode test =
804 case test of
906 case test of
805− DT.IsCtor _ tag index ->
907+ DT.IsCtor name index _ _ ->
806 case mode of
908 case mode of
808− JS.String (N.toBuilder tag)
909+ Name.Debug _ -> JS.String (N.toBuilder name)
811− JS.Int (Index.toZeroBased index)
910+ Name.Prod _ _ -> JS.Int (Index.toMachine index)
813 DT.IsInt int ->
912 DT.IsInt int ->
814 JS.Int int
913 JS.Int int
@@ -819,46 +918,76 @@ testToExpr mode test =
819 DT.IsStr string ->
918 DT.IsStr string ->
820 JS.String (Text.encodeUtf8Builder string)
919 JS.String (Text.encodeUtf8Builder string)
922+ error "COMPILER BUG - there should never be three tests on a list"
925+ error "COMPILER BUG - there should never be three tests on a list"
823−pathToTestableExpr :: Mode -> N.Name -> DT.Path -> DT.Test -> JS.Expr
928+generateCaseTest :: Mode -> N.Name -> DT.Path -> DT.Test -> JS.Expr
824−pathToTestableExpr mode root path exampleTest =
929+generateCaseTest mode root path exampleTest =
827− pathToJsExpr mode (JS.Ref (Name.fromLocal root)) path
931+ value = pathToJsExpr mode root path
829 case exampleTest of
933 case exampleTest of
830− DT.IsCtor _ _ _ ->
934+ DT.IsCtor _ _ _ opts ->
831− JS.Access expr Name.dollar
937+ JS.Access value Name.dollar
942+ JS.Access value Name.dollar
833 DT.IsInt _ ->
950 DT.IsInt _ ->
836 DT.IsStr _ ->
953 DT.IsStr _ ->
839 DT.IsChr _ ->
956 DT.IsChr _ ->
840 case mode of
957 case mode of
841 Name.Debug _ ->
958 Name.Debug _ ->
842− JS.Call (JS.Access expr (Name.fromLocal "valueOf")) []
959+ JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
844 Name.Prod _ _ ->
961 Name.Prod _ _ ->
965+ error "COMPILER BUG - there should never be three tests on a list"
968+ error "COMPILER BUG - there should never be three tests on a list"
848−pathToJsExpr :: Mode -> JS.Expr -> DT.Path -> JS.Expr
975+pathToJsExpr :: Mode -> N.Name -> DT.Path -> JS.Expr
849−pathToJsExpr mode expr path =
976+pathToJsExpr mode root path =
850 case path of
977 case path of
851− DT.Index index subpath ->
978+ DT.Index index subPath ->
852− pathToJsExpr mode (JS.Access expr (Name.fromInt index)) subpath
979+ JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex index)
854− DT.Field field subpath ->
981+ DT.Unbox subPath ->
855− pathToJsExpr mode (JS.Access expr (Name.fromField mode field)) subpath
982+ case mode of
984+ JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex Index.first)
857− DT.Empty ->
986+ Name.Prod _ _ ->
858− expr
987+ pathToJsExpr mode root subPath
860− DT.Alias ->
989+ DT.Empty ->
861− expr
990+ JS.Ref (Name.fromLocal root)