@@ -76,6 +76,20 @@ generate mode expression =
7676 Opt.VarGlobal (Opt.Global home name) ->
7777 JsExpr $ JS.Ref (Name.fromGlobal home name)
7878
79+ Opt.VarEnum (Opt.Global home name) index ->
80+ case mode of
81+ Name.Debug _ ->
82+ JsExpr $ JS.Ref (Name.fromGlobal home name)
83+
84+ Name.Prod _ _ ->
85+ JsExpr $ JS.Int (Index.toMachine index)
86+
87+ Opt.VarBox (Opt.Global home name) ->
88+ JsExpr $ JS.Ref $
89+ case mode of
90+ Name.Debug _ -> Name.fromGlobal home name
91+ Name.Prod _ _ -> Name.fromGlobal ModuleName.basics N.identity
92+
7993 Opt.VarCycle home name ->
8094 JsExpr $ JS.Call (JS.Ref (Name.fromCycle home name)) []
8195
@@ -108,12 +122,16 @@ generate mode expression =
108122 JsBlock $
109123 generateDef mode def : codeToStmtList (generate mode body)
110124
125+ Opt.Destruct (Opt.Destructor name path) body ->
126+ let
127+ pathExpr = generatePath mode path
128+ pathDef = JS.Var [ (Name.fromLocal name, Just pathExpr) ]
129+ in
130+ JsBlock $ pathDef : codeToStmtList (generate mode body)
131+
111132 Opt.Case label root decider jumps ->
112133 JsBlock $ generateCase mode label root decider jumps
113134
114− Opt.Index expr index ->
115− JsExpr $ JS.Access (generateJsExpr mode expr) (Name.fromInt index)
116−
117135 Opt.Accessor field ->
118136 JsExpr $ JS.Function Nothing [Name.dollar]
119137 [ JS.Return $ Just $
@@ -134,7 +152,12 @@ generate mode expression =
134152 JsExpr $ generateRecord mode fields
135153
136154 Opt.Unit ->
137− JsExpr $ JS.Ref (Name.fromKernel N.utils "Tuple0")
155+ case mode of
156+ Name.Debug _ ->
157+ JsExpr $ JS.Ref (Name.fromKernel N.utils "Tuple0")
158+
159+ Name.Prod _ _ ->
160+ JsExpr $ JS.Int 0
138161
139162 Opt.Tuple a b maybeC ->
140163 JsExpr $
@@ -216,21 +239,19 @@ toChar =
216239-- CTOR
217240
218241
219−generateCtor :: Mode -> N.Name -> Index.ZeroBased -> Int -> ([Name.Name], Code)
242+generateCtor :: Mode -> N.Name -> Index.ZeroBased -> Int -> Code
220243generateCtor mode name index arity =
221244 let
222− argNames = map Name.fromInt [1 .. arity]
223− argFields = map (\n -> (n, JS.Ref n)) argNames
245+ argNames =
246+ Index.indexedMap (\i _ -> Name.fromIndex i) [1 .. arity]
224247
225− tag =
248+ ctorTag =
226249 case mode of
227− Name.Debug _ ->
228− ( Name.dollar, JS.String (N.toBuilder name) )
229−
230− Name.Prod _ _ ->
231− ( Name.dollar, JS.Int (Index.toZeroBased index) )
250+ Name.Debug _ -> JS.String (N.toBuilder name)
251+ Name.Prod _ _ -> JS.Int (Index.toMachine index)
232252 in
233− ( argNames, JsExpr (JS.Object (tag:argFields)) )
253+ generateFunction argNames $ JsExpr $ JS.Object $
254+ (Name.dollar, ctorTag) : map (\n -> (n, JS.Ref n)) argNames
234255
235256
236257
@@ -334,14 +355,32 @@ generateCall mode func args =
334355 Opt.VarGlobal global@(Opt.Global (ModuleName.Canonical pkg _) _) | pkg == Pkg.core ->
335356 generateCoreCall mode global args
336357
358+ Opt.VarBox _ ->
359+ case mode of
360+ Name.Debug _ ->
361+ generateCallHelp mode func args
362+
363+ Name.Prod _ _ ->
364+ case args of
365+ [arg] ->
366+ generateJsExpr mode arg
367+
368+ _ ->
369+ generateCallHelp mode func args
370+
337371 _ ->
338− generateNormalCall
339− (generateJsExpr mode func)
340− (map (generateJsExpr mode) args)
372+ generateCallHelp mode func args
341373
342374
343−generateNormalCall' :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
344−generateNormalCall' home name args =
375+generateCallHelp :: Mode -> Opt.Expr -> [Opt.Expr] -> JS.Expr
376+generateCallHelp mode func args =
377+ generateNormalCall
378+ (generateJsExpr mode func)
379+ (map (generateJsExpr mode) args)
380+
381+
382+generateGlobalCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
383+generateGlobalCall home name args =
345384 generateNormalCall (JS.Ref (Name.fromGlobal home name)) args
346385
347386
@@ -385,8 +424,11 @@ generateCoreCall mode (Opt.Global home@(ModuleName.Canonical _ moduleName) name)
385424 else if moduleName == N.tuple then
386425 generateTupleCall home name (map (generateJsExpr mode) args)
387426
427+ else if moduleName == N.jsArray then
428+ generateJsArrayCall home name (map (generateJsExpr mode) args)
429+
388430 else
389− generateNormalCall' home name (map (generateJsExpr mode) args)
431+ generateGlobalCall home name (map (generateJsExpr mode) args)
390432
391433
392434generateTupleCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
@@ -396,10 +438,18 @@ generateTupleCall home name args =
396438 case name of
397439 "first" -> JS.Access value (Name.fromLocal "a")
398440 "second" -> JS.Access value (Name.fromLocal "b")
399− _ -> generateNormalCall' home name args
441+ _ -> generateGlobalCall home name args
400442
401443 _ ->
402− generateNormalCall' home name args
444+ generateGlobalCall home name args
445+
446+
447+generateJsArrayCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
448+generateJsArrayCall home name args =
449+ case args of
450+ [entry] | name == "singleton" -> JS.Array [entry]
451+ [index, array] | name == "unsafeGet" -> JS.Index array index
452+ _ -> generateGlobalCall home name args
403453
404454
405455generateBitwiseCall :: ModuleName.Canonical -> N.Name -> [JS.Expr] -> JS.Expr
@@ -408,7 +458,7 @@ generateBitwiseCall home name args =
408458 [arg] ->
409459 case name of
410460 "complement" -> JS.Prefix JS.PrefixBNot arg
411− _ -> generateNormalCall' home name args
461+ _ -> generateGlobalCall home name args
412462
413463 [left,right] ->
414464 case name of
@@ -418,10 +468,10 @@ generateBitwiseCall home name args =
418468 "shiftLeftBy" -> JS.Infix JS.OpLShift right left
419469 "shiftRightBy" -> JS.Infix JS.OpSpRShift right left
420470 "shiftRightZfBy" -> JS.Infix JS.OpZfRShift right left
421− _ -> generateNormalCall' home name args
471+ _ -> generateGlobalCall home name args
422472
423473 _ ->
424− generateNormalCall' home name args
474+ generateGlobalCall home name args
425475
426476
427477generateBasicsCall :: Mode -> ModuleName.Canonical -> N.Name -> [Opt.Expr] -> JS.Expr
@@ -433,7 +483,7 @@ generateBasicsCall mode home name args =
433483 "not" -> JS.Prefix JS.PrefixLNot arg
434484 "toFloat" -> arg
435485 "truncate" -> JS.Infix JS.OpBOr arg (JS.Int 0)
436− _ -> generateNormalCall' home name [arg]
486+ _ -> generateGlobalCall home name [arg]
437487
438488 [elmLeft, elmRight] ->
439489 case name of
@@ -462,10 +512,10 @@ generateBasicsCall mode home name args =
462512 "or" -> JS.Infix JS.OpLOr left right
463513 "and" -> JS.Infix JS.OpLAnd left right
464514 "xor" -> JS.Infix JS.OpStrictNEq left right
465− _ -> generateNormalCall' home name [left, right]
515+ _ -> generateGlobalCall home name [left, right]
466516
467517 _ ->
468− generateNormalCall' home name (map (generateJsExpr mode) args)
518+ generateGlobalCall home name (map (generateJsExpr mode) args)
469519
470520
471521equal :: JS.Expr -> JS.Expr -> JS.Expr
@@ -676,6 +726,31 @@ generateDef mode def =
676726
677727
678728
729+-- PATHS
730+
731+
732+generatePath :: Mode -> Opt.Path -> JS.Expr
733+generatePath mode path =
734+ case path of
735+ Opt.Index index subPath ->
736+ JS.Access (generatePath mode subPath) (Name.fromIndex index)
737+
738+ Opt.Root name ->
739+ JS.Ref (Name.fromLocal name)
740+
741+ Opt.Field field subPath ->
742+ JS.Access (generatePath mode subPath) (Name.fromField mode field)
743+
744+ Opt.Unbox subPath ->
745+ case mode of
746+ Name.Debug _ ->
747+ JS.Access (generatePath mode subPath) (Name.fromIndex Index.first)
748+
749+ Name.Prod _ _ ->
750+ generatePath mode subPath
751+
752+
753+
679754-- GENERATE IFS
680755
681756
@@ -770,45 +845,69 @@ generateDecider mode label root decisionTree =
770845 [ JS.Break (Just (Name.makeLabel label index)) ]
771846
772847 Opt.Chain testChain success failure ->
773− let
774− makeTest (path, test) =
775− strictEq
776− (pathToTestableExpr mode root path test)
777− (testToExpr mode test)
778− in
779848 [ JS.IfStmt
780− (List.foldl1' (JS.Infix JS.OpLAnd) (map makeTest testChain))
849+ (List.foldl1' (JS.Infix JS.OpLAnd) (map (generateIfTest mode root) testChain))
781850 (JS.Block $ generateDecider mode label root success)
782851 (JS.Block $ generateDecider mode label root failure)
783852 ]
784853
785854 Opt.FanOut path edges fallback ->
786855 [ JS.Switch
787− (pathToTestableExpr mode root path (fst (head edges)))
856+ (generateCaseTest mode root path (fst (head edges)))
788857 ( foldr
789− (addCase mode label root)
858+ (\edge cases -> generateCaseBranch mode label root edge : cases)
790859 [ JS.Default (generateDecider mode label root fallback) ]
791860 edges
792861 )
793862 ]
794863
795864
796−addCase :: Mode -> N.Name -> N.Name -> (DT.Test, Opt.Decider Opt.Choice) -> [JS.Case] -> [JS.Case]
797−addCase mode label root (test, subTree) cases =
798− let stmts = generateDecider mode label root subTree in
799− JS.Case (testToExpr mode test) stmts : cases
865+generateIfTest :: Mode -> N.Name -> (DT.Path, DT.Test) -> JS.Expr
866+generateIfTest mode root (path, test) =
867+ let
868+ value = pathToJsExpr mode root path
869+ in
870+ case test of
871+ DT.IsCtor name index _ _ ->
872+ strictEq (JS.Access value Name.dollar) $
873+ case mode of
874+ Name.Debug _ -> JS.String (N.toBuilder name)
875+ Name.Prod _ _ -> JS.Int (Index.toMachine index)
876+
877+ DT.IsInt int ->
878+ strictEq value (JS.Int int)
800879
880+ DT.IsChr char ->
881+ strictEq (JS.String (Text.encodeUtf8Builder char)) $
882+ case mode of
883+ Name.Debug _ -> JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
884+ Name.Prod _ _ -> value
801885
802−testToExpr :: Mode -> DT.Test -> JS.Expr
803−testToExpr mode test =
886+ DT.IsStr string ->
887+ strictEq value (JS.String (Text.encodeUtf8Builder string))
888+
889+ DT.IsCons ->
890+ JS.Access value (Name.fromLocal "b")
891+
892+ DT.IsNil ->
893+ JS.Prefix JS.PrefixLNot $
894+ JS.Access value (Name.fromLocal "b")
895+
896+
897+generateCaseBranch :: Mode -> N.Name -> N.Name -> (DT.Test, Opt.Decider Opt.Choice) -> JS.Case
898+generateCaseBranch mode label root (test, subTree) =
899+ JS.Case
900+ (generateCaseValue mode test)
901+ (generateDecider mode label root subTree)
902+
903+
904+generateCaseValue :: Mode -> DT.Test -> JS.Expr
905+generateCaseValue mode test =
804906 case test of
805− DT.IsCtor _ tag index ->
907+ DT.IsCtor name index _ _ ->
806908 case mode of
807− Name.Debug _ ->
808− JS.String (N.toBuilder tag)
809−
810− Name.Prod _ _ ->
811− JS.Int (Index.toZeroBased index)
909+ Name.Debug _ -> JS.String (N.toBuilder name)
910+ Name.Prod _ _ -> JS.Int (Index.toMachine index)
812911
813912 DT.IsInt int ->
814913 JS.Int int
@@ -819,46 +918,76 @@ testToExpr mode test =
819918 DT.IsStr string ->
820919 JS.String (Text.encodeUtf8Builder string)
821920
921+ DT.IsCons ->
922+ error "COMPILER BUG - there should never be three tests on a list"
822923
823−pathToTestableExpr :: Mode -> N.Name -> DT.Path -> DT.Test -> JS.Expr
824−pathToTestableExpr mode root path exampleTest =
924+ DT.IsNil ->
925+ error "COMPILER BUG - there should never be three tests on a list"
926+
927+
928+generateCaseTest :: Mode -> N.Name -> DT.Path -> DT.Test -> JS.Expr
929+generateCaseTest mode root path exampleTest =
825930 let
826− expr =
827− pathToJsExpr mode (JS.Ref (Name.fromLocal root)) path
931+ value = pathToJsExpr mode root path
828932 in
829933 case exampleTest of
830− DT.IsCtor _ _ _ ->
831− JS.Access expr Name.dollar
934+ DT.IsCtor _ _ _ opts ->
935+ case mode of
936+ Name.Debug _ ->
937+ JS.Access value Name.dollar
938+
939+ Name.Prod _ _ ->
940+ case opts of
941+ Can.Normal ->
942+ JS.Access value Name.dollar
943+
944+ Can.Enum ->
945+ value
946+
947+ Can.Unbox ->
948+ value
832949
833950 DT.IsInt _ ->
834− expr
951+ value
835952
836953 DT.IsStr _ ->
837− expr
954+ value
838955
839956 DT.IsChr _ ->
840957 case mode of
841958 Name.Debug _ ->
842− JS.Call (JS.Access expr (Name.fromLocal "valueOf")) []
959+ JS.Call (JS.Access value (Name.fromLocal "valueOf")) []
843960
844961 Name.Prod _ _ ->
845− expr
962+ value
846963
964+ DT.IsCons ->
965+ error "COMPILER BUG - there should never be three tests on a list"
847966
848−pathToJsExpr :: Mode -> JS.Expr -> DT.Path -> JS.Expr
849−pathToJsExpr mode expr path =
967+ DT.IsNil ->
968+ error "COMPILER BUG - there should never be three tests on a list"
969+
970+
971+
972+-- PATTERN PATHS
973+
974+
975+pathToJsExpr :: Mode -> N.Name -> DT.Path -> JS.Expr
976+pathToJsExpr mode root path =
850977 case path of
851− DT.Index index subpath ->
852− pathToJsExpr mode (JS.Access expr (Name.fromInt index)) subpath
978+ DT.Index index subPath ->
979+ JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex index)
853980
854− DT.Field field subpath ->
855− pathToJsExpr mode (JS.Access expr (Name.fromField mode field)) subpath
981+ DT.Unbox subPath ->
982+ case mode of
983+ Name.Debug _ ->
984+ JS.Access (pathToJsExpr mode root subPath) (Name.fromIndex Index.first)
856985
857− DT.Empty ->
858− expr
986+ Name.Prod _ _ ->
987+ pathToJsExpr mode root subPath
859988
860− DT.Alias ->
861− expr
989+ DT.Empty ->
990+ JS.Ref (Name.fromLocal root)
862991
863992
864993