@samitouri / QOS-React-2 / commits / 99181160d5

[hir] implement assignment expressions

Implements assignment expressions with operators other than `=` (such as `+=`) by lowering to an assignment. I think this isn't fully correct for something like `a.b.c += 1`, but it seems like there's more gaps in object accesses.

Jan Kassens committed Nov 14, 2022 at 10:58 UTC 99181160d56ac573b7dc5cfb7291dfb3634c94db
3 files changed +158 -3
compiler/forget/src/HIR/BuildHIR.ts
+40 -3
@@ -901,13 +901,50 @@ function lowerExpression(
901 case "AssignmentExpression": {
902 const expr = exprPath as NodePath<t.AssignmentExpression>;
903 const left = lowerLVal(builder, expr.get("left"));
904 - const right = lowerExpression(builder, expr.get("right"));
904 const operator = expr.node.operator;
906 - todoInvariant(operator === "=", "todo: support non-simple assignment");
905 +
906 + if (operator === "=") {
907 + const right = lowerExpression(builder, expr.get("right"));
908 + builder.push({
909 + id: 0,
910 + lvalue: { place: left, kind: InstructionKind.Reassign },
911 + value: right,
912 + loc: exprLoc,
913 + });
914 + return left;
915 + }
916 +
917 + const operators: { [key: string]: t.BinaryExpression["operator"] } = {
918 + "+=": "+",
919 + "-=": "-",
920 + "/=": "/",
921 + "%=": "%",
922 + "*=": "*",
923 + "**=": "**",
924 + "&=": "&",
925 + "|=": "|",
926 + ">>=": ">>",
927 + ">>>=": ">>>",
928 + "<<=": "<<",
929 + "^=": "^",
930 + };
931 + const binaryOperator = operators[operator];
932 + invariant(
933 + binaryOperator != null,
934 + `Unhandled assignment operator '${operator}'`
935 + );
936 +
937 + const right = lowerExpressionToPlace(builder, expr.get("right"));
938 builder.push({
939 id: 0,
940 lvalue: { place: left, kind: InstructionKind.Reassign },
910 - value: right,
941 + value: {
942 + kind: "BinaryExpression",
943 + operator: binaryOperator,
944 + left,
945 + right,
946 + loc: exprLoc,
947 + },
948 loc: exprLoc,
949 });
950 return left;
compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md new
+107
@@ -0,0 +1,107 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function f() {
6 + let x = 1;
7 + x = x + 1;
8 + x += 1;
9 + x >>>= 1;
10 +}
11 +
12 +function g(a) {
13 + a.b.c = a.b.c + 1;
14 + a.b.c *= 2;
15 +}
16 +
17 +```
18 +
19 +## HIR
20 +
21 +```
22 +bb0:
23 + [1] Let mutate x$5 = 1
24 + [2] Const mutate $6 = 1
25 + [3] Reassign mutate x$7 = Binary read x$5 + read $6
26 + [4] Const mutate $8 = 1
27 + [5] Reassign mutate x$9 = Binary read x$7 + read $8
28 + [6] Const mutate $10 = 1
29 + [7] Reassign mutate x$11 = Binary read x$9 >>> read $10
30 + Return
31 +```
32 +
33 +### CFG
34 +
35 +```mermaid
36 +flowchart TB
37 + %% Basic Blocks
38 + subgraph bb0
39 + bb0_instrs["
40 + [1] Let mutate x$5 = 1
41 + [2] Const mutate $6 = 1
42 + [3] Reassign mutate x$7 = Binary read x$5 + read $6
43 + [4] Const mutate $8 = 1
44 + [5] Reassign mutate x$9 = Binary read x$7 + read $8
45 + [6] Const mutate $10 = 1
46 + [7] Reassign mutate x$11 = Binary read x$9 >>> read $10
47 + "]
48 + bb0_instrs --> bb0_terminal(["Return"])
49 + end
50 +
51 + %% Jumps
52 + %% empty
53 +```
54 +
55 +## Code
56 +
57 +```javascript
58 +function f$0() {
59 + let x$5 = 1;
60 + x$7 = x$5 + 1;
61 + x$9 = x$7 + 1;
62 + x$11 = x$9 >>> 1;
63 + return;
64 +}
65 +
66 +```
67 +## HIR
68 +
69 +```
70 +bb0:
71 + [1] Const mutate $5 = 1
72 + [2] Reassign mutate a$4.b.c[0:4] = Binary read a$4.b.c + read $5
73 + [3] Const mutate $6 = 2
74 + [4] Reassign mutate a$4.b.c[0:4] = Binary read a$4.b.c * read $6
75 + Return
76 +```
77 +
78 +### CFG
79 +
80 +```mermaid
81 +flowchart TB
82 + %% Basic Blocks
83 + subgraph bb0
84 + bb0_instrs["
85 + [1] Const mutate $5 = 1
86 + [2] Reassign mutate a$4.b.c[0:4] = Binary read a$4.b.c + read $5
87 + [3] Const mutate $6 = 2
88 + [4] Reassign mutate a$4.b.c[0:4] = Binary read a$4.b.c * read $6
89 + "]
90 + bb0_instrs --> bb0_terminal(["Return"])
91 + end
92 +
93 + %% Jumps
94 + %% empty
95 +```
96 +
97 +## Code
98 +
99 +```javascript
100 +function g$0(a$4) {
101 + a$4 = a$4.b.c + 1;
102 + a$4 = a$4.b.c * 2;
103 + return;
104 +}
105 +
106 +```
107 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/assignment-variations.js new
+11
@@ -0,0 +1,11 @@
1 +function f() {
2 + let x = 1;
3 + x = x + 1;
4 + x += 1;
5 + x >>>= 1;
6 +}
7 +
8 +function g(a) {
9 + a.b.c = a.b.c + 1;
10 + a.b.c *= 2;
11 +}