on master help sign in
Provide fewer JS features with Gen/JS/Builder

Require that all `var` statements have definitions and remove some operators that are not used in code gen.

commit90fc53010eea06951cf7c2a1125718055ede20fc authorEvan Czaplicki <evancz@users.noreply.github.com> dateThu 30 May 2019, 10:59 (7 years ago) parentefc3d09
3 files changed+122−147
compiler/src/Generate/JavaScript.hs+24−35 compiler/src/Generate/JavaScript/Builder.hs+61−74 compiler/src/Generate/JavaScript/Expression.hs+37−38
compiler/src/Generate/JavaScript.hs+24−35
@@ -225,7 +225,7 @@ addKernel (State revKernels revBuilders seen) kernel =
225225
226226var :: Opt.Global -> Expr.Code -> JS.Stmt
227227var (Opt.Global home name) code =
228− JS.Var [ (JsName.fromGlobal home name, Just (Expr.codeToExpr code)) ]
228+ JS.Var (JsName.fromGlobal home name) (Expr.codeToExpr code)
229229
230230
231231isDebugger :: Opt.Global -> Bool
@@ -265,10 +265,10 @@ generateCycleFunc :: Mode.Mode -> ModuleName.Canonical -> Opt.Def -> JS.Stmt
265265generateCycleFunc mode home def =
266266 case def of
267267 Opt.Def name expr ->
268− JS.Var [ (JsName.fromGlobal home name, Just (Expr.codeToExpr (Expr.generate mode expr))) ]
268+ JS.Var (JsName.fromGlobal home name) (Expr.codeToExpr (Expr.generate mode expr))
269269
270270 Opt.TailDef name args expr ->
271− JS.Var [ (JsName.fromGlobal home name, Just (Expr.codeToExpr (Expr.generateTailDef mode name args expr))) ]
271+ JS.Var (JsName.fromGlobal home name) (Expr.codeToExpr (Expr.generateTailDef mode name args expr))
272272
273273
274274generateSafeCycle :: Mode.Mode -> ModuleName.Canonical -> (Name.Name, Opt.Expr) -> JS.Stmt
@@ -284,7 +284,7 @@ generateRealCycle home (name, _) =
284284 realName = JsName.fromGlobal home name
285285 in
286286 JS.Block
287− [ JS.Var [ ( realName, Just (JS.Call (JS.Ref safeName) []) ) ]
287+ [ JS.Var realName (JS.Call (JS.Ref safeName) [])
288288 , JS.ExprStmt $ JS.Assign (JS.LRef safeName) $
289289 JS.Function Nothing [] [ JS.Return (Just (JS.Ref realName)) ]
290290 ]
@@ -354,16 +354,13 @@ addChunk mode chunk builder =
354354
355355generateEnum :: Mode.Mode -> Opt.Global -> Index.ZeroBased -> JS.Stmt
356356generateEnum mode global@(Opt.Global home name) index =
357− let
358− definition =
359− case mode of
360− Mode.Dev _ ->
361− Expr.codeToExpr (Expr.generateCtor mode global index 0)
357+ JS.Var (JsName.fromGlobal home name) $
358+ case mode of
359+ Mode.Dev _ ->
360+ Expr.codeToExpr (Expr.generateCtor mode global index 0)
362361
363− Mode.Prod _ ->
364− JS.Int (Index.toMachine index)
365− in
366− JS.Var [ (JsName.fromGlobal home name, Just definition) ]
362+ Mode.Prod _ ->
363+ JS.Int (Index.toMachine index)
367364
368365
369366
@@ -372,16 +369,13 @@ generateEnum mode global@(Opt.Global home name) index =
372369
373370generateBox :: Mode.Mode -> Opt.Global -> JS.Stmt
374371generateBox mode global@(Opt.Global home name) =
375− let
376− definition =
377− case mode of
378− Mode.Dev _ ->
379− Expr.codeToExpr (Expr.generateCtor mode global Index.first 1)
372+ JS.Var (JsName.fromGlobal home name) $
373+ case mode of
374+ Mode.Dev _ ->
375+ Expr.codeToExpr (Expr.generateCtor mode global Index.first 1)
380376
381− Mode.Prod _ ->
382− JS.Ref (JsName.fromGlobal ModuleName.basics Name.identity)
383− in
384− JS.Var [ (JsName.fromGlobal home name, Just definition) ]
377+ Mode.Prod _ ->
378+ JS.Ref (JsName.fromGlobal ModuleName.basics Name.identity)
385379
386380
387381{-# NOINLINE identity #-}
@@ -396,14 +390,11 @@ identity =
396390
397391generatePort :: Mode.Mode -> Opt.Global -> Name.Name -> Opt.Expr -> JS.Stmt
398392generatePort mode (Opt.Global home name) makePort converter =
399− let
400− definition =
401− JS.Call (JS.Ref (JsName.fromKernel Name.platform makePort))
402− [ JS.String (Name.toBuilder name)
403− , Expr.codeToExpr (Expr.generate mode converter)
404− ]
405− in
406− JS.Var [ (JsName.fromGlobal home name, Just definition) ]
393+ JS.Var (JsName.fromGlobal home name) $
394+ JS.Call (JS.Ref (JsName.fromKernel Name.platform makePort))
395+ [ JS.String (Name.toBuilder name)
396+ , Expr.codeToExpr (Expr.generate mode converter)
397+ ]
407398
408399
409400
@@ -431,11 +422,9 @@ generateManager mode graph (Opt.Global home@(ModuleName.Canonical _ moduleName)
431422
432423generateLeaf :: ModuleName.Canonical -> Name.Name -> JS.Stmt
433424generateLeaf home@(ModuleName.Canonical _ moduleName) name =
434− let
435− definition =
436− JS.Call leaf [ JS.String (Name.toBuilder moduleName) ]
437− in
438− JS.Var [ (JsName.fromGlobal home name, Just definition) ]
425+ JS.Var (JsName.fromGlobal home name) $
426+ JS.Call leaf [ JS.String (Name.toBuilder moduleName) ]
427+
439428
440429
441430{-# NOINLINE leaf #-}
compiler/src/Generate/JavaScript/Builder.hs+61−74
@@ -37,13 +37,13 @@ data Expr
3737 | Array [Expr]
3838 | Object [(Name, Expr)]
3939 | Ref Name
40− | Access Expr Name -- ^ @foo.bar@, spec 11.2.1
41− | Index Expr Expr -- ^ @foo[bar]@, spec 11.2.1
40+ | Access Expr Name -- foo.bar
41+ | Index Expr Expr -- foo[bar]
4242 | Prefix PrefixOp Expr
4343 | Infix InfixOp Expr Expr
4444 | If Expr Expr Expr
4545 | Assign LValue Expr
46− | Call Expr [Expr] -- ^ @f(x,y,z)@, spec 11.2.3
46+ | Call Expr [Expr]
4747 | Function (Maybe Name) [Name] [Stmt]
4848
4949
@@ -58,20 +58,21 @@ data LValue
5858
5959
6060data Stmt
61− = Block [Stmt] -- {stmts}
62− | EmptyStmt -- ;
63− | ExprStmt Expr -- expr;
64− | IfStmt Expr Stmt Stmt -- if (e) stmt1 else stmt2
65− | Switch Expr [Case] -- switch (e) clauses
66− | While Expr Stmt -- while (e) do stmt
67− | Break (Maybe Name) -- break lab;
68− | Continue (Maybe Name) -- continue lab;
69− | Labelled Name Stmt -- lab: stmt
70− | Try Stmt Name Stmt -- try stmt catch (x) stmt
71− | Throw Expr -- throw expr;
72− | Return (Maybe Expr) -- return expr;
73− | Var [(Name, Maybe Expr)] -- var x, y=42;
74− | FunctionStmt Name [Name] [Stmt] -- function f(x, y, z) {...}
61+ = Block [Stmt]
62+ | EmptyStmt
63+ | ExprStmt Expr
64+ | IfStmt Expr Stmt Stmt
65+ | Switch Expr [Case]
66+ | While Expr Stmt
67+ | Break (Maybe Name)
68+ | Continue (Maybe Name)
69+ | Labelled Name Stmt
70+ | Try Stmt Name Stmt
71+ | Throw Expr
72+ | Return (Maybe Expr)
73+ | Var Name Expr
74+ | Vars [(Name, Expr)]
75+ | FunctionStmt Name [Name] [Stmt]
7576
7677
7778data Case
@@ -84,37 +85,31 @@ data Case
8485
8586
8687data InfixOp
87− = OpLT -- <
88− | OpLEq -- <=
89− | OpGT -- >
90− | OpGEq -- >=
91− | OpIn -- in
92− | OpInstanceof -- instanceof
93− | OpEq -- ==
94− | OpNEq -- !=
95− | OpStrictEq -- ===
96− | OpStrictNEq -- !==
97− | OpLAnd -- &&
98− | OpLOr -- ||
88+ = OpAdd -- +
89+ | OpSub -- -
9990 | OpMul -- *
10091 | OpDiv -- /
10192 | OpMod -- %
102− | OpSub -- -
103− | OpLShift -- <<
104− | OpSpRShift -- >>
105− | OpZfRShift -- >>>
106− | OpBAnd -- &
107− | OpBXor -- ^
108− | OpBOr -- |
109− | OpAdd -- +
93+ | OpEq -- ===
94+ | OpNe -- !==
95+ | OpLt -- <
96+ | OpLe -- <=
97+ | OpGt -- >
98+ | OpGe -- >=
99+ | OpAnd -- &&
100+ | OpOr -- ||
101+ | OpBitwiseAnd -- &
102+ | OpBitwiseXor -- ^
103+ | OpBitwiseOr -- |
104+ | OpLShift -- <<
105+ | OpSpRShift -- >>
106+ | OpZfRShift -- >>>
110107
111108
112109data PrefixOp
113− = PrefixLNot -- !
114− | PrefixBNot -- ~
115− | PrefixPlus -- +
116− | PrefixMinus -- -
117− | PrefixTypeof -- typeof
110+ = PrefixNot -- !
111+ | PrefixNegate -- -
112+ | PrefixComplement -- ~
118113
119114
120115
@@ -230,10 +225,13 @@ fromStmt indent statement =
230225 Return (Just expr) ->
231226 indent <> "return " <> snd (fromExpr indent Whatever expr) <> ";\n"
232227
233− Var [] ->
228+ Var name expr ->
229+ indent <> "var " <> Name.toBuilder name <> " = " <> snd (fromExpr indent Whatever expr) <> ";\n"
230+
231+ Vars [] ->
234232 mempty
235233
236− Var vars ->
234+ Vars vars ->
237235 indent <> "var " <> commaNewlineSep indent (map (varToBuilder indent) vars) <> ";\n"
238236
239237 FunctionStmt name args stmts ->
@@ -264,14 +262,9 @@ fromClause indent clause =
264262-- VAR DECLS
265263
266264
267−varToBuilder :: Builder -> (Name, Maybe Expr) -> Builder
268−varToBuilder indent (name, maybeExpr) =
269− case maybeExpr of
270− Nothing ->
271− Name.toBuilder name
272−
273− Just expr ->
274− Name.toBuilder name <> " = " <> snd (fromExpr indent Whatever expr)
265+varToBuilder :: Builder -> (Name, Expr) -> Builder
266+varToBuilder indent (name, expr) =
267+ Name.toBuilder name <> " = " <> snd (fromExpr indent Whatever expr)
275268
276269
277270
@@ -505,36 +498,30 @@ makeBracketed indent expr bracketedExpr =
505498fromPrefix :: PrefixOp -> Builder
506499fromPrefix op =
507500 case op of
508− PrefixLNot -> "!"
509− PrefixBNot -> "~"
510− PrefixPlus -> "+"
511− PrefixMinus -> "-"
512− PrefixTypeof -> "typeof "
501+ PrefixNot -> "!"
502+ PrefixNegate -> "-"
503+ PrefixComplement -> "~"
513504
514505
515506fromInfix :: InfixOp -> Builder
516507fromInfix op =
517508 case op of
518− OpLT -> " < "
519− OpLEq -> " <= "
520− OpGT -> " > "
521− OpGEq -> " >= "
522− OpIn -> " in "
523− OpInstanceof -> " instanceof "
524− OpEq -> " == "
525− OpNEq -> " != "
526− OpStrictEq -> " === "
527− OpStrictNEq -> " !== "
528− OpLAnd -> " && "
529− OpLOr -> " || "
509+ OpAdd -> " + "
510+ OpSub -> " - "
530511 OpMul -> " * "
531512 OpDiv -> " / "
532513 OpMod -> " % "
533− OpSub -> " - "
514+ OpEq -> " === "
515+ OpNe -> " !== "
516+ OpLt -> " < "
517+ OpLe -> " <= "
518+ OpGt -> " > "
519+ OpGe -> " >= "
520+ OpAnd -> " && "
521+ OpOr -> " || "
522+ OpBitwiseAnd -> " & "
523+ OpBitwiseXor -> " ^ "
524+ OpBitwiseOr -> " | "
534525 OpLShift -> " << "
535526 OpSpRShift -> " >> "
536527 OpZfRShift -> " >>> "
537− OpBAnd -> " & "
538− OpBXor -> " ^ "
539− OpBOr -> " | "
540− OpAdd -> " + "
compiler/src/Generate/JavaScript/Expression.hs+37−38
@@ -128,8 +128,7 @@ generate mode expression =
128128
129129 Opt.Destruct (Opt.Destructor name path) body ->
130130 let
131− pathExpr = generatePath mode path
132− pathDef = JS.Var [ (JsName.fromLocal name, Just pathExpr) ]
131+ pathDef = JS.Var (JsName.fromLocal name) (generatePath mode path)
133132 in
134133 JsBlock $ pathDef : codeToStmtList (generate mode body)
135134
@@ -482,17 +481,17 @@ generateBitwiseCall home name args =
482481 case args of
483482 [arg] ->
484483 case name of
485− "complement" -> JS.Prefix JS.PrefixBNot arg
484+ "complement" -> JS.Prefix JS.PrefixComplement arg
486485 _ -> generateGlobalCall home name args
487486
488487 [left,right] ->
489488 case name of
490− "and" -> JS.Infix JS.OpBAnd left right
491− "or" -> JS.Infix JS.OpBOr left right
492− "xor" -> JS.Infix JS.OpBXor left right
493− "shiftLeftBy" -> JS.Infix JS.OpLShift right left
494− "shiftRightBy" -> JS.Infix JS.OpSpRShift right left
495− "shiftRightZfBy" -> JS.Infix JS.OpZfRShift right left
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
496495 _ -> generateGlobalCall home name args
497496
498497 _ ->
@@ -505,10 +504,10 @@ generateBasicsCall mode home name args =
505504 [elmArg] ->
506505 let arg = generateJsExpr mode elmArg in
507506 case name of
508− "not" -> JS.Prefix JS.PrefixLNot arg
509− "negate" -> JS.Prefix JS.PrefixMinus arg
507+ "not" -> JS.Prefix JS.PrefixNot arg
508+ "negate" -> JS.Prefix JS.PrefixNegate arg
510509 "toFloat" -> arg
511− "truncate" -> JS.Infix JS.OpBOr arg (JS.Int 0)
510+ "truncate" -> JS.Infix JS.OpBitwiseOr arg (JS.Int 0)
512511 _ -> generateGlobalCall home name [arg]
513512
514513 [elmLeft, elmRight] ->
@@ -528,16 +527,16 @@ generateBasicsCall mode home name args =
528527 "sub" -> JS.Infix JS.OpSub left right
529528 "mul" -> JS.Infix JS.OpMul left right
530529 "fdiv" -> JS.Infix JS.OpDiv left right
531− "idiv" -> JS.Infix JS.OpBOr (JS.Infix JS.OpDiv left right) (JS.Int 0)
530+ "idiv" -> JS.Infix JS.OpBitwiseOr (JS.Infix JS.OpDiv left right) (JS.Int 0)
532531 "eq" -> equal left right
533532 "neq" -> notEqual left right
534− "lt" -> cmp JS.OpLT JS.OpLT 0 left right
535− "gt" -> cmp JS.OpGT JS.OpGT 0 left right
536− "le" -> cmp JS.OpLEq JS.OpLT 1 left right
537− "ge" -> cmp JS.OpGEq JS.OpGT (-1) left right
538− "or" -> JS.Infix JS.OpLOr left right
539− "and" -> JS.Infix JS.OpLAnd left right
540− "xor" -> JS.Infix JS.OpStrictNEq 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
541540 "remainderBy" -> JS.Infix JS.OpMod right left
542541 _ -> generateGlobalCall home name [left, right]
543542
@@ -558,7 +557,7 @@ notEqual left right =
558557 if isLiteral left || isLiteral right then
559558 strictNEq left right
560559 else
561− JS.Prefix JS.PrefixLNot $
560+ JS.Prefix JS.PrefixNot $
562561 JS.Call (JS.Ref (JsName.fromKernel Name.utils "eq")) [left, right]
563562
564563
@@ -647,42 +646,42 @@ strictEq :: JS.Expr -> JS.Expr -> JS.Expr
647646strictEq left right =
648647 case left of
649648 JS.Int 0 ->
650− JS.Prefix JS.PrefixLNot right
649+ JS.Prefix JS.PrefixNot right
651650
652651 JS.Bool bool ->
653− if bool then right else JS.Prefix JS.PrefixLNot right
652+ if bool then right else JS.Prefix JS.PrefixNot right
654653
655654 _ ->
656655 case right of
657656 JS.Int 0 ->
658− JS.Prefix JS.PrefixLNot left
657+ JS.Prefix JS.PrefixNot left
659658
660659 JS.Bool bool ->
661− if bool then left else JS.Prefix JS.PrefixLNot left
660+ if bool then left else JS.Prefix JS.PrefixNot left
662661
663662 _ ->
664− JS.Infix JS.OpStrictEq left right
663+ JS.Infix JS.OpEq left right
665664
666665
667666strictNEq :: JS.Expr -> JS.Expr -> JS.Expr
668667strictNEq left right =
669668 case left of
670669 JS.Int 0 ->
671− JS.Prefix JS.PrefixLNot (JS.Prefix JS.PrefixLNot right)
670+ JS.Prefix JS.PrefixNot (JS.Prefix JS.PrefixNot right)
672671
673672 JS.Bool bool ->
674− if bool then JS.Prefix JS.PrefixLNot right else right
673+ if bool then JS.Prefix JS.PrefixNot right else right
675674
676675 _ ->
677676 case right of
678677 JS.Int 0 ->
679− JS.Prefix JS.PrefixLNot (JS.Prefix JS.PrefixLNot left)
678+ JS.Prefix JS.PrefixNot (JS.Prefix JS.PrefixNot left)
680679
681680 JS.Bool bool ->
682− if bool then JS.Prefix JS.PrefixLNot left else left
681+ if bool then JS.Prefix JS.PrefixNot left else left
683682
684683 _ ->
685− JS.Infix JS.OpStrictNEq left right
684+ JS.Infix JS.OpNe left right
686685
687686
688687
@@ -695,13 +694,13 @@ generateTailCall :: Mode.Mode -> Name.Name -> [(Name.Name, Opt.Expr)] -> [JS.Stm
695694generateTailCall mode name args =
696695 let
697696 toTempVars (argName, arg) =
698− ( JsName.makeTemp argName, Just (generateJsExpr mode arg) )
697+ ( JsName.makeTemp argName, generateJsExpr mode arg )
699698
700699 toRealVars (argName, _) =
701700 JS.ExprStmt $
702701 JS.Assign (JS.LRef (JsName.fromLocal argName)) (JS.Ref (JsName.makeTemp argName))
703702 in
704− JS.Var (map toTempVars args)
703+ JS.Vars (map toTempVars args)
705704 : map toRealVars args
706705 ++ [ JS.Continue (Just (JsName.fromLocal name)) ]
707706
@@ -714,10 +713,10 @@ generateDef :: Mode.Mode -> Opt.Def -> JS.Stmt
714713generateDef mode def =
715714 case def of
716715 Opt.Def name body ->
717− JS.Var [ (JsName.fromLocal name, Just (generateJsExpr mode body)) ]
716+ JS.Var (JsName.fromLocal name) (generateJsExpr mode body)
718717
719718 Opt.TailDef name argNames body ->
720− JS.Var [ (JsName.fromLocal name, Just (codeToExpr (generateTailDef mode name argNames body))) ]
719+ JS.Var (JsName.fromLocal name) (codeToExpr (generateTailDef mode name argNames body))
721720
722721
723722generateTailDef :: Mode.Mode -> Name.Name -> [Name.Name] -> Opt.Expr -> Code
@@ -850,7 +849,7 @@ generateDecider mode label root decisionTree =
850849
851850 Opt.Chain testChain success failure ->
852851 [ JS.IfStmt
853− (List.foldl1' (JS.Infix JS.OpLAnd) (map (generateIfTest mode root) testChain))
852+ (List.foldl1' (JS.Infix JS.OpAnd) (map (generateIfTest mode root) testChain))
854853 (JS.Block $ generateDecider mode label root success)
855854 (JS.Block $ generateDecider mode label root failure)
856855 ]
@@ -892,7 +891,7 @@ generateIfTest mode root (path, test) =
892891 value
893892
894893 DT.IsBool False ->
895− JS.Prefix JS.PrefixLNot value
894+ JS.Prefix JS.PrefixNot value
896895
897896 DT.IsInt int ->
898897 strictEq value (JS.Int int)
@@ -910,7 +909,7 @@ generateIfTest mode root (path, test) =
910909 JS.Access value (JsName.fromLocal "b")
911910
912911 DT.IsNil ->
913− JS.Prefix JS.PrefixLNot $
912+ JS.Prefix JS.PrefixNot $
914913 JS.Access value (JsName.fromLocal "b")
915914
916915 DT.IsTuple ->