@samitouri / QOS-React-2 / commits / 21652a135b

Improved LeaveSSA pass

## Problem The previous version of LeaveSSA used a very simple approach in which identifiers stored their pre-ssa id, and LeaveSSA restored this id back. The upside of this approach is that it's very simple and trivially correct (assuming no reordering of code). The downside is that after running LeaveSSA we lose all information about which versions of variable declarations are distinct, and which might merge together in a phi. That information is really useful for scope analysis! Consider this input (variables are numbered as they would be in SSA form): ```javascript function foo(a, b, c) { let x$1 = null; if (a) { x$2 = b; } else { x$3 = c; } x$4 = phi(x$2, x$3); return x$4; ``` The current LeaveSSA assigns all 4 variables back to `x$1`, with a single let declaration at `let x$1 = null`. However, from a reactive scopes perspective, there are really just 2 versions of x: the initial x$1 (defined and never used) and then x$2, x$3, and x$4, which have to be merged into a single scope because they are part of a phi. In other words, we can't independently compute x$2, x$3, or x$4 - if any of their inputs changes, we have to redo all the computation. However, the existing structure makes it difficult to figure out the correct starting point for this scope — there is no initial `let` declaration that we can refer to. Instead, we can represent the program as follows after LeaveSSA, and then use this form for scope analysis: ```javascript function foo(a, b, c) { const x$1 = null; // NOTE: rewritten to const let x$2; // synthesized declaration to allow later reassignment if (a) { x$2 = b; } else { x$2 = c; } return x$2; ``` Note that there are only 2 versions of x, and we have synthesized a variable declaration for x$2 at the appropriate scope. Our scope analysis can then determine that the range of x$2 is from the declaration to the end of the if. ## Approach This pass does two main rewrites: * For variables that do *not* appear as a phi id or operand, it rewrites the declaration to be `const`. You can see this above for x$1. * For variables that *do* appear as a phi or operand, it synthesizes a new `let` binding at the appropriate scope (ie, in the appropriate block), and updates all other operands from the phi to use the same id for the variable. You can see this above for x$2, x$3, and x$4. Note that the let binding is generated at the narrowest scope possible. In this example, we generate distinct let bindings for the other if and else branches: ```javascript function foo(a, b, c) { let x = null; if (a) { // we generate a `let x$2` here if (b) { x = 0; // becomes x$2 } else { x = 1; // becomes x$2 } x // becomes x$2 } else { // we generate a `let x$3` here if (c) { x = 2; // becomes x$3 } else { x = 3; // becomes x$3 } x; // becomes x$3 } } ``` Because the different x values from the outer if/else can never join in a phi, we can treat them as independent variables and (re)compute them independently. The algorithm works by iterating in reverse-postorder, and looking ahead at fallthrough blocks to find phi nodes that may need a let declaration (see above example of where these are generated). It also tracks variables which _don't_ participate in a phi so that it can rewrite their declarations to `const`. ## TODO This PR does *not* yet work for cases where there is unconditional assignment within a `while` test condition. That would technically create a distinct version of the variable that shadows the value for the loop, and you can't have variable declarations in a while test condition. That case already doesn't work, though, so i'm punting on it for now until we figure out a bit more around "value" blocks. We have some good options, like desugaring to a `for(;;)` and manually implementing the while semantics in that case.

Joseph Savona committed Dec 8, 2022 at 07:35 UTC 21652a135b6bd1cb87dbcc2480aaf0886e056d63
90 files changed +1596 -785
compiler/forget/src/HIR/EnterSSA.ts
-1
@@ -51,7 +51,6 @@ class SSABuilder {
51 makeId(oldId: Identifier): Identifier {
52 return {
53 id: this.nextSsaId,
54 - preSsaId: oldId.id,
54 name: oldId.name,
55 mutableRange: {
56 start: makeInstructionId(0),
compiler/forget/src/HIR/HIR.ts
-2
@@ -298,8 +298,6 @@ export type MutableRange = {
298 * Represents a user-defined variable (has a name) or a temporary variable (no name).
299 */
300 export type Identifier = {
301 - // the original `id` value prior to entering SSA form
302 - preSsaId: IdentifierId | null;
301 // unique value to distinguish a variable, since name is not guaranteed to exist or be unique
302 id: IdentifierId;
303 // null for temporaries. name is primarily used for debugging.
compiler/forget/src/HIR/HIRBuilder.ts
-2
@@ -111,7 +111,6 @@ export default class HIRBuilder {
111 makeTemporary(): Identifier {
112 const id = this.nextIdentifierId;
113 return {
114 - preSsaId: null,
114 id,
115 name: null,
116 mutableRange: { start: makeInstructionId(0), end: makeInstructionId(0) },
@@ -124,7 +123,6 @@ export default class HIRBuilder {
123 if (identifier == null) {
124 const id = this.nextIdentifierId;
125 identifier = {
127 - preSsaId: null,
126 id,
127 name: node.name,
128 mutableRange: {
compiler/forget/src/HIR/LeaveSSA.ts
+144 -15
@@ -1,24 +1,153 @@
1 -import { HIRFunction } from "./HIR";
2 -import { eachBlockOperand } from "./visitors";
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +
8 +import {
9 + Effect,
10 + GeneratedSource,
11 + HIRFunction,
12 + Identifier,
13 + Instruction,
14 + InstructionKind,
15 + Phi,
16 +} from "./HIR";
17 +import { eachInstructionValueOperand, eachTerminalOperand } from "./visitors";
18
19 /**
5 - * Removes SSA form by restoring each `Identifier.id` value to its pre-SSA value,
6 - * and removing all phi nodes.
20 + * Removes SSA form by creating unique variable declarations for the versions of each variables.
21 + * - Versions of a variable that do not flow into a phi node are each assigned their own const variable
22 + * declaration.
23 + * - If multiple versions of a variable flow into some phi node, then all those versions are reassigned to
24 + * the phi version. A single declaration is created at the same block scope as the phi, prior to any of the
25 + * assignments.
26 */
8 -export default function leaveSSA(fn: HIRFunction) {
9 - const ir = fn.body;
27 +export function leaveSSA(fn: HIRFunction) {
28 + // Maps identifiers that appear as a phi or phi operand to a single canonical identifier
29 + // for all instances.
30 + const variableMapping: Map<Identifier, Identifier> = new Map();
31
11 - for (const param of fn.params) {
12 - param.identifier.id = param.identifier.preSsaId ?? param.identifier.id;
13 - }
32 + for (const [, block] of fn.body.blocks) {
33 + // Identifiers (from phis) that *may* need a new `let` declaration created. If the original
34 + // variable declaration flows into the phi, then we can reuse its declaration - this is
35 + // discovered during iteration of instructions.
36 + const needsDeclaration: Set<Identifier> = new Set();
37
15 - for (const [, block] of ir.blocks) {
16 - block.phis.clear();
17 - }
38 + // Find any phi nodes which need a variable declaration in the current block
39 + // This includes phis in fallthrough nodes, or blocks that form part of control flow
40 + // such as for or while (and later if/switch).
41 + const phis: Array<Phi> = [];
42 + const terminal = block.terminal;
43 + if (
44 + (terminal.kind === "if" ||
45 + terminal.kind === "switch" ||
46 + terminal.kind === "while" ||
47 + terminal.kind === "for") &&
48 + terminal.fallthrough !== null
49 + ) {
50 + const fallthrough = fn.body.blocks.get(terminal.fallthrough)!;
51 + phis.push(...fallthrough.phis);
52 + }
53 + if (terminal.kind === "while" || terminal.kind === "for") {
54 + const test = fn.body.blocks.get(terminal.test)!;
55 + phis.push(...test.phis);
56 + const loop = fn.body.blocks.get(terminal.loop)!;
57 + phis.push(...loop.phis);
58 + }
59 + if (terminal.kind === "for") {
60 + const update = fn.body.blocks.get(terminal.update)!;
61 + phis.push(...update.phis);
62 + }
63
19 - for (const [, block] of ir.blocks) {
20 - for (const place of eachBlockOperand(block)) {
21 - place.identifier.id = place.identifier.preSsaId ?? place.identifier.id;
64 + // For each phi, determine a canonical identifier to use for versions of the variable
65 + // that appear in the phi (as its output id and operands). If this is the first time
66 + // we're seeing the phi id, then we may need to generate a new variable declaration
67 + // Note that there can be multiple phi nodes for the same variable, we capture the
68 + // outermost scope by visiting predecessor blocks first.
69 + for (const phi of phis) {
70 + let canonicalId = variableMapping.get(phi.id);
71 + if (canonicalId === undefined) {
72 + // Determine a new canonical id. We use the id/operand whose id is lowest,
73 + // which ensures that _if_ the original variable declaration is one of the
74 + // options we'll choose it and can reuse the declaration.
75 + canonicalId = phi.id;
76 + for (const [, operand] of phi.operands) {
77 + if (operand.id < canonicalId.id) {
78 + canonicalId = operand;
79 + }
80 + }
81 + variableMapping.set(phi.id, canonicalId);
82 + needsDeclaration.add(canonicalId);
83 + }
84 + // all versions of the variable need to be remapped to the canonical id
85 + for (const [, operand] of phi.operands) {
86 + variableMapping.set(operand, canonicalId);
87 + }
88 }
89 +
90 + // Visit instructions and rewrite identifiers based on the variable mapping
91 + // updated above.
92 + for (const instr of block.instructions) {
93 + const { lvalue, value } = instr;
94 + if (lvalue !== null) {
95 + lvalue.place.identifier =
96 + variableMapping.get(lvalue.place.identifier) ??
97 + lvalue.place.identifier;
98 + if (lvalue.place.memberPath === null) {
99 + if (!variableMapping.has(lvalue.place.identifier)) {
100 + // This variable does not flow into a phi, therefore there
101 + // is no reassignment. Convert the declaration to a const.
102 + lvalue.kind = InstructionKind.Const;
103 + } else if (
104 + variableMapping.get(lvalue.place.identifier) ===
105 + lvalue.place.identifier
106 + ) {
107 + // This is an existing declaration we can reuse as the canonical declaration for its
108 + // phi. Note, the declaration must already be a `let` or else it would be invalid to
109 + // reassign the variable in the first place.
110 + needsDeclaration.delete(lvalue.place.identifier);
111 + }
112 + }
113 + }
114 + for (const operand of eachInstructionValueOperand(value)) {
115 + operand.identifier =
116 + variableMapping.get(operand.identifier) ?? operand.identifier;
117 + }
118 + }
119 +
120 + for (const operand of eachTerminalOperand(terminal)) {
121 + operand.identifier =
122 + variableMapping.get(operand.identifier) ?? operand.identifier;
123 + }
124 +
125 + // Generate new let declarations for any remaining phi variables
126 + for (const identifier of needsDeclaration) {
127 + const instr: Instruction = {
128 + // NOTE: reuse the terminal id since these lets must be scoped with the terminal anyway
129 + // the only reason they exist is that there is a scope that will span the control flow.
130 + id: block.terminal.id,
131 + lvalue: {
132 + place: {
133 + kind: "Identifier",
134 + memberPath: null,
135 + identifier,
136 + effect: Effect.Mutate,
137 + loc: GeneratedSource,
138 + },
139 + kind: InstructionKind.Let,
140 + },
141 + value: {
142 + kind: "Primitive",
143 + value: undefined,
144 + loc: GeneratedSource,
145 + },
146 + loc: GeneratedSource,
147 + };
148 + block.instructions.push(instr);
149 + }
150 +
151 + block.phis.clear();
152 }
153 }
compiler/forget/src/HIR/Pipeline.ts
+1 -1
@@ -12,7 +12,7 @@ import enterSSA from "../HIR/EnterSSA";
12 import { Environment } from "../HIR/HIRBuilder";
13 import { inferMutableRanges } from "../HIR/InferMutableLifetimes";
14 import inferReferenceEffects from "../HIR/InferReferenceEffects";
15 -import leaveSSA from "../HIR/LeaveSSA";
15 +import { leaveSSA } from "../HIR/LeaveSSA";
16 import codegen from "./Codegen";
17 import { HIRFunction } from "./HIR";
18 import { inferReactiveScopeDependencies } from "./InferReactiveScopeDependencies";
compiler/forget/src/HIR/PrintHIR.ts
+6 -1
@@ -128,7 +128,9 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
128 case "if": {
129 value = `[${terminal.id}] If (${printPlace(terminal.test)}) then:bb${
130 terminal.consequent
131 - } else:bb${terminal.alternate}`;
131 + } else:bb${terminal.alternate}${
132 + terminal.fallthrough ? ` fallthrough=bb${terminal.fallthrough}` : ""
133 + }`;
134 break;
135 }
136 case "throw": {
@@ -157,6 +159,9 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
159 output.push(` Default: bb${case_.block}`);
160 }
161 });
162 + if (terminal.fallthrough) {
163 + output.push(` Fallthrough: bb${terminal.fallthrough}`);
164 + }
165 value = output;
166 break;
167 }
compiler/forget/src/__tests__/fixtures/hir/_bug_expression-with-assignment.expect.md
+3 -3
@@ -51,9 +51,9 @@ flowchart TB
51
52 ```javascript
53 function f$0() {
54 - let x$1 = 1;
55 - x$1 = 2;
56 - return x$1 + x$1 + x$1;
54 + const x$4 = 1;
55 + const x$5 = 2;
56 + return x$5 + x$5 + x$5;
57 }
58
59 ```
compiler/forget/src/__tests__/fixtures/hir/_bug_inverted-if-else.expect.md new
+91
@@ -0,0 +1,91 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo(a, b, c) {
6 + let x = null;
7 + label: {
8 + if (a) {
9 + x = b;
10 + break label;
11 + }
12 + x = c;
13 + }
14 + return x;
15 +}
16 +
17 +```
18 +
19 +## HIR
20 +
21 +```
22 +bb0:
23 + [1] Let mutate x$8_@0 = null
24 + [2] If (read a$5) then:bb3 else:bb2 fallthrough=bb2
25 +bb3:
26 + predecessor blocks: bb0
27 + [3] Reassign mutate x$9_@1[3:6] = read b$6
28 + [4] Goto bb1
29 +bb2:
30 + predecessor blocks: bb0
31 + [5] Reassign mutate x$10_@1[3:6] = read c$7
32 + [6] Goto bb1
33 +bb1:
34 + predecessor blocks: bb3 bb2
35 + x$11_@1[3:6]: phi(bb3: x$9_@1, bb2: x$10_@1)
36 + [7] Return read x$11_@1
37 +scope1 [3:6]:
38 + - read b$6
39 + - read a$5
40 + - read c$7
41 +```
42 +
43 +### CFG
44 +
45 +```mermaid
46 +flowchart TB
47 + %% Basic Blocks
48 + subgraph bb0
49 + bb0_instrs["
50 + [1] Let mutate x$8_@0 = null
51 + "]
52 + bb0_instrs --> bb0_terminal(["If (read a$5)"])
53 + end
54 + subgraph bb3
55 + bb3_instrs["
56 + [3] Reassign mutate x$9_@1[3:6] = read b$6
57 + "]
58 + bb3_instrs --> bb3_terminal(["Goto"])
59 + end
60 + subgraph bb2
61 + bb2_instrs["
62 + [5] Reassign mutate x$10_@1[3:6] = read c$7
63 + "]
64 + bb2_instrs --> bb2_terminal(["Goto"])
65 + end
66 + subgraph bb1
67 + bb1_terminal(["Return read x$11_@1"])
68 + end
69 +
70 + %% Jumps
71 + bb0_terminal -- "then" --> bb3
72 + bb0_terminal -- "else" --> bb2
73 + bb3_terminal --> bb1
74 + bb2_terminal --> bb1
75 +
76 +```
77 +
78 +## Code
79 +
80 +```javascript
81 +function foo$0(a$5, b$6, c$7) {
82 + const x$8 = null;
83 + bb2: if (a$5) {
84 + const x$9 = b$6;
85 + }
86 +
87 + const x$10 = c$7;
88 +}
89 +
90 +```
91 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/_bug_inverted-if-else.js new
+11
@@ -0,0 +1,11 @@
1 +function foo(a, b, c) {
2 + let x = null;
3 + label: {
4 + if (a) {
5 + x = b;
6 + break label;
7 + }
8 + x = c;
9 + }
10 + return x;
11 +}
compiler/forget/src/__tests__/fixtures/hir/_bug_while-with-assignment.expect.md deleted
-106
@@ -1,106 +0,0 @@
1 -
2 -## Input
3 -
4 -```javascript
5 -function f(reader) {
6 - const queue = [1, 2, 3];
7 - let value = 0;
8 - let sum = 0;
9 - // BUG: we need to codegen the complex test expression
10 - while ((value = queue.pop()) != null) {
11 - sum += value;
12 - }
13 - return sum;
14 -}
15 -
16 -```
17 -
18 -## HIR
19 -
20 -```
21 -bb0:
22 - [1] Const mutate $11_@0 = 1
23 - [2] Const mutate $12_@1 = 2
24 - [3] Const mutate $13_@2 = 3
25 - [4] Const mutate queue$14_@3[0:14] = Array [read $11_@0, read $12_@1, read $13_@2]
26 - [5] Let mutate value$15_@4 = 0
27 - [6] Let mutate sum$16_@3[0:14] = 0
28 - [7] While test=bb1 loop=bb3 fallthrough=bb2
29 -bb1:
30 - predecessor blocks: bb0 bb3
31 - sum$21_@3[0:14]: phi(bb0: sum$16_@3, bb3: sum$22_@3)
32 - [8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
33 - [9] Const mutate $19_@6 = null
34 - [10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
35 - [11] If (read $20_@7) then:bb3 else:bb2
36 -bb3:
37 - predecessor blocks: bb1
38 - [12] Reassign mutate sum$22_@3[0:14] = Binary read sum$21_@3 + read value$18_@3
39 - [13] Goto(Continue) bb1
40 -bb2:
41 - predecessor blocks: bb1
42 - [14] Return read sum$21_@3
43 -scope7 [10:12]:
44 - - read $19_@6
45 -```
46 -
47 -### CFG
48 -
49 -```mermaid
50 -flowchart TB
51 - %% Basic Blocks
52 - subgraph bb0
53 - bb0_instrs["
54 - [1] Const mutate $11_@0 = 1
55 - [2] Const mutate $12_@1 = 2
56 - [3] Const mutate $13_@2 = 3
57 - [4] Const mutate queue$14_@3[0:14] = Array [read $11_@0, read $12_@1, read $13_@2]
58 - [5] Let mutate value$15_@4 = 0
59 - [6] Let mutate sum$16_@3[0:14] = 0
60 - "]
61 - bb0_instrs --> bb0_terminal(["While"])
62 - end
63 - subgraph bb1
64 - bb1_instrs["
65 - [8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
66 - [9] Const mutate $19_@6 = null
67 - [10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
68 - "]
69 - bb1_instrs --> bb1_terminal(["If (read $20_@7)"])
70 - end
71 - subgraph bb3
72 - bb3_instrs["
73 - [12] Reassign mutate sum$22_@3[0:14] = Binary read sum$21_@3 + read value$18_@3
74 - "]
75 - bb3_instrs --> bb3_terminal(["Goto"])
76 - end
77 - subgraph bb2
78 - bb2_terminal(["Return read sum$21_@3"])
79 - end
80 -
81 - %% Jumps
82 - bb0_terminal -- "test" --> bb1
83 - bb0_terminal -- "loop" --> bb3
84 - bb0_terminal -- "fallthrough" --> bb2
85 - bb1_terminal -- "then" --> bb3
86 - bb1_terminal -- "else" --> bb2
87 - bb3_terminal --> bb1
88 -
89 -```
90 -
91 -## Code
92 -
93 -```javascript
94 -function f$0(reader$1) {
95 - const queue$2 = [1, 2, 3];
96 - let value$6 = 0;
97 - let sum$7 = 0;
98 - bb2: while (((value$6 = queue$2.pop()), value$6 != null)) {
99 - sum$7 = sum$7 + value$6;
100 - }
101 -
102 - return sum$7;
103 -}
104 -
105 -```
106 -
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/alias-while.expect.md
+16 -16
@@ -36,7 +36,7 @@ bb1:
36 a$12_@0[0:12]: phi(bb0: a$8_@0, bb3: a$15_@0)
37 b$14_@0[0:12]: phi(bb0: b$9_@0, bb3: b$17_@0)
38 c$16_@0[0:12]: phi(bb0: c$10_@0, bb3: c$18_@0)
39 - [5] If (read cond$7) then:bb3 else:bb2
39 + [5] If (read cond$7) then:bb3 else:bb2 fallthrough=bb2
40 bb3:
41 predecessor blocks: bb1
42 [6] Let mutate z$13_@0[0:12] = read a$12_@0
@@ -102,22 +102,22 @@ flowchart TB
102 ## Code
103
104 ```javascript
105 -function foo$0(cond$1) {
106 - let a$2 = {};
107 - let b$3 = {};
108 - let c$4 = {};
109 - bb2: while (cond$1) {
110 - let z$5 = a$2;
111 - a$2 = b$3;
112 - b$3 = c$4;
113 - c$4 = z$5;
114 - mutate$6(a$2, b$3);
105 +function foo$0(cond$7) {
106 + let a$8 = {};
107 + let b$9 = {};
108 + let c$10 = {};
109 + bb2: while (cond$7) {
110 + const z$13 = a$8;
111 + a$8 = b$9;
112 + b$9 = c$10;
113 + c$10 = z$13;
114 + mutate$6(a$8, b$9);
115 }
116
117 - a$2;
118 - b$3;
119 - c$4;
120 - return a$2;
117 + a$8;
118 + b$9;
119 + c$10;
120 + return a$8;
121 }
122
123 ```
@@ -145,7 +145,7 @@ flowchart TB
145 ## Code
146
147 ```javascript
148 -function mutate$0(x$1, y$2) {}
148 +function mutate$0(x$3, y$4) {}
149
150 ```
151
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md
+7 -7
@@ -65,10 +65,10 @@ flowchart TB
65
66 ```javascript
67 function f$0() {
68 - let x$1 = 1;
69 - x$1 = x$1 + 1;
70 - x$1 = x$1 + 1;
71 - x$1 = x$1 >>> 1;
68 + const x$5 = 1;
69 + const x$7 = x$5 + 1;
70 + const x$9 = x$7 + 1;
71 + const x$11 = x$9 >>> 1;
72 }
73
74 ```
@@ -107,9 +107,9 @@ flowchart TB
107 ## Code
108
109 ```javascript
110 -function g$0(a$1) {
111 - a$1.c.b = a$1.b.c + 1;
112 - a$1.c.b = a$1.b.c * 2;
110 +function g$0(a$4) {
111 + a$4.c.b = a$4.b.c + 1;
112 + a$4.c.b = a$4.b.c * 2;
113 }
114
115 ```
compiler/forget/src/__tests__/fixtures/hir/call.expect.md
+8 -8
@@ -89,14 +89,14 @@ flowchart TB
89 ## Code
90
91 ```javascript
92 -function Component$0(props$1) {
93 - const a$2 = [];
94 - const b$3 = {};
95 - foo$4(a$2, b$3);
96 - let _$5 = <div a={a$2}></div>;
97 -
98 - foo$4(b$3);
99 - return <div a={a$2} b={b$3}></div>;
92 +function Component$0(props$9) {
93 + const a$10 = [];
94 + const b$11 = {};
95 + foo$4(a$10, b$11);
96 + const _$13 = <div a={a$10}></div>;
97 +
98 + foo$4(b$11);
99 + return <div a={a$10} b={b$11}></div>;
100 }
101
102 ```
compiler/forget/src/__tests__/fixtures/hir/complex-while.expect.md
+7 -7
@@ -18,16 +18,16 @@ function foo(a, b, c) {
18
19 ```
20 bb0:
21 - [1] If (read a$4) then:bb3 else:bb1
21 + [1] If (read a$4) then:bb3 else:bb1 fallthrough=bb1
22 bb3:
23 predecessor blocks: bb0
24 [2] While test=bb4 loop=bb6 fallthrough=bb1
25 bb4:
26 predecessor blocks: bb3 bb7
27 - [3] If (read b$5) then:bb6 else:bb1
27 + [3] If (read b$5) then:bb6 else:bb1 fallthrough=bb1
28 bb6:
29 predecessor blocks: bb4
30 - [4] If (read c$6) then:bb1 else:bb7
30 + [4] If (read c$6) then:bb1 else:bb7 fallthrough=bb7
31 bb7:
32 predecessor blocks: bb6
33 [5] Goto(Continue) bb4
@@ -78,10 +78,10 @@ flowchart TB
78 ## Code
79
80 ```javascript
81 -function foo$0(a$1, b$2, c$3) {
82 - bb1: if (a$1) {
83 - while (b$2) {
84 - bb7: if (c$3) break;
81 +function foo$0(a$4, b$5, c$6) {
82 + bb1: if (a$4) {
83 + while (b$5) {
84 + bb7: if (c$6) break;
85 }
86 }
87 }
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+10 -10
@@ -44,12 +44,12 @@ bb0:
44 [7] Goto bb1
45 bb1:
46 predecessor blocks: bb0 bb5 bb10
47 - [8] If (read items$27_@0) then:bb3 else:bb2
47 + [8] If (read items$27_@0) then:bb3 else:bb2 fallthrough=bb2
48 bb3:
49 predecessor blocks: bb1
50 [9] Const mutate $34_@6 = null
51 [10] Const mutate $36_@3[0:19] = Binary read item$10_@3 == read $34_@6
52 - [11] If (read $36_@3) then:bb8 else:bb9
52 + [11] If (read $36_@3) then:bb8 else:bb9 fallthrough=bb7
53 bb8:
54 predecessor blocks: bb3
55 [12] Const mutate $37_@3[0:19] = read $36_@3
@@ -61,7 +61,7 @@ bb9:
61 bb7:
62 predecessor blocks: bb8 bb9
63 $40_@3[0:19]: phi(bb8: $37_@3, bb9: $39_@3)
64 - [16] If (read $40_@3) then:bb5 else:bb4
64 + [16] If (read $40_@3) then:bb5 else:bb4 fallthrough=bb4
65 bb5:
66 predecessor blocks: bb7
67 [17] Goto(Continue) bb1
@@ -72,7 +72,7 @@ bb4:
72 [20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
73 [21] Call mutate renderedItems$29_@2.push(read $44_@8)
74 [22] Const mutate $49_@2[3:26] = Binary read renderedItems$29_@2.length >= read max$32_@5
75 - [23] If (read $49_@2) then:bb2 else:bb10
75 + [23] If (read $49_@2) then:bb2 else:bb10 fallthrough=bb10
76 bb10:
77 predecessor blocks: bb4
78 [24] Goto(Continue) bb1
@@ -187,12 +187,12 @@ flowchart TB
187 ## Code
188
189 ```javascript
190 -function Component$0(props$1) {
191 - const items$2 = props$1.items;
192 - const maxItems$3 = props$1.maxItems;
193 - const renderedItems$4 = [];
194 - const seen$5 = new Set$6();
195 - const max$7 = Math$8.max(0, maxItems$3);
190 +function Component$0(props$26) {
191 + const items$27 = props$26.items;
192 + const maxItems$28 = props$26.maxItems;
193 + const renderedItems$29 = [];
194 + const seen$30 = new Set$6();
195 + const max$32 = Math$8.max(0, maxItems$28);
196 }
197
198 ```
compiler/forget/src/__tests__/fixtures/hir/conditional-break.expect.md
+40 -40
@@ -80,7 +80,7 @@ function Component(props) {
80 bb0:
81 [1] Const mutate a_DEBUG$5_@0[1:7] = Array []
82 [2] Call mutate a_DEBUG$5_@0.push(read props$4.a)
83 - [3] If (read props$4.b) then:bb2 else:bb1
83 + [3] If (read props$4.b) then:bb2 else:bb1 fallthrough=bb1
84 bb2:
85 predecessor blocks: bb0
86 [4] Const mutate $6_@1 = null
@@ -129,15 +129,15 @@ flowchart TB
129 ## Code
130
131 ```javascript
132 -function Component$0(props$1) {
133 - const a_DEBUG$2 = [];
134 - a_DEBUG$2.push(props$1.a);
135 - bb1: if (props$1.b) {
132 +function Component$0(props$4) {
133 + const a_DEBUG$5 = [];
134 + a_DEBUG$5.push(props$4.a);
135 + bb1: if (props$4.b) {
136 return null;
137 }
138
139 - a_DEBUG$2.push(props$1.d);
140 - return a_DEBUG$2;
139 + a_DEBUG$5.push(props$4.d);
140 + return a_DEBUG$5;
141 }
142
143 ```
@@ -147,7 +147,7 @@ function Component$0(props$1) {
147 bb0:
148 [1] Const mutate a$4_@0[1:7] = Array []
149 [2] Call mutate a$4_@0.push(read props$3.a)
150 - [3] If (read props$3.b) then:bb2 else:bb1
150 + [3] If (read props$3.b) then:bb2 else:bb1 fallthrough=bb1
151 bb2:
152 predecessor blocks: bb0
153 [4] Call mutate a$4_@0.push(read props$3.c)
@@ -198,15 +198,15 @@ flowchart TB
198 ## Code
199
200 ```javascript
201 -function Component$0(props$1) {
202 - const a$2 = [];
203 - a$2.push(props$1.a);
204 - bb1: if (props$1.b) {
205 - a$2.push(props$1.c);
201 +function Component$0(props$3) {
202 + const a$4 = [];
203 + a$4.push(props$3.a);
204 + bb1: if (props$3.b) {
205 + a$4.push(props$3.c);
206 }
207
208 - a$2.push(props$1.d);
209 - return a$2;
208 + a$4.push(props$3.d);
209 + return a$4;
210 }
211
212 ```
@@ -216,7 +216,7 @@ function Component$0(props$1) {
216 bb0:
217 [1] Const mutate a$5_@0[1:8] = Array []
218 [2] Call mutate a$5_@0.push(read props$4.a)
219 - [3] If (read props$4.b) then:bb2 else:bb1
219 + [3] If (read props$4.b) then:bb2 else:bb1 fallthrough=bb1
220 bb2:
221 predecessor blocks: bb0
222 [4] Call mutate a$5_@0.push(read props$4.c)
@@ -268,16 +268,16 @@ flowchart TB
268 ## Code
269
270 ```javascript
271 -function Component$0(props$1) {
272 - const a$2 = [];
273 - a$2.push(props$1.a);
274 - bb1: if (props$1.b) {
275 - a$2.push(props$1.c);
271 +function Component$0(props$4) {
272 + const a$5 = [];
273 + a$5.push(props$4.a);
274 + bb1: if (props$4.b) {
275 + a$5.push(props$4.c);
276 return null;
277 }
278
279 - a$2.push(props$1.d);
280 - return a$2;
279 + a$5.push(props$4.d);
280 + return a$5;
281 }
282
283 ```
@@ -287,7 +287,7 @@ function Component$0(props$1) {
287 bb0:
288 [1] Const mutate a$4_@0[1:7] = Array []
289 [2] Call mutate a$4_@0.push(read props$3.a)
290 - [3] If (read props$3.b) then:bb2 else:bb1
290 + [3] If (read props$3.b) then:bb2 else:bb1 fallthrough=bb1
291 bb2:
292 predecessor blocks: bb0
293 [4] Call mutate a$4_@0.push(read props$3.c)
@@ -337,16 +337,16 @@ flowchart TB
337 ## Code
338
339 ```javascript
340 -function Component$0(props$1) {
341 - const a$2 = [];
342 - a$2.push(props$1.a);
343 - bb1: if (props$1.b) {
344 - a$2.push(props$1.c);
345 - return a$2;
340 +function Component$0(props$3) {
341 + const a$4 = [];
342 + a$4.push(props$3.a);
343 + bb1: if (props$3.b) {
344 + a$4.push(props$3.c);
345 + return a$4;
346 }
347
348 - a$2.push(props$1.d);
349 - return a$2;
348 + a$4.push(props$3.d);
349 + return a$4;
350 }
351
352 ```
@@ -356,7 +356,7 @@ function Component$0(props$1) {
356 bb0:
357 [1] Const mutate a$4_@0[1:7] = Array []
358 [2] Call mutate a$4_@0.push(read props$3.a)
359 - [3] If (read props$3.b) then:bb1 else:bb2
359 + [3] If (read props$3.b) then:bb1 else:bb2 fallthrough=bb2
360 bb2:
361 predecessor blocks: bb0
362 [4] Call mutate a$4_@0.push(read props$3.c)
@@ -406,15 +406,15 @@ flowchart TB
406 ## Code
407
408 ```javascript
409 -function Component$0(props$1) {
410 - const a$2 = [];
411 - a$2.push(props$1.a);
412 - bb2: if (props$1.b) {
413 - a$2.push(props$1.d);
414 - return a$2;
409 +function Component$0(props$3) {
410 + const a$4 = [];
411 + a$4.push(props$3.a);
412 + bb2: if (props$3.b) {
413 + a$4.push(props$3.d);
414 + return a$4;
415 }
416
417 - a$2.push(props$1.c);
417 + a$4.push(props$3.c);
418 }
419
420 ```
compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md
+20 -20
@@ -37,14 +37,14 @@ function mayMutate() {}
37 bb0:
38 [1] Const mutate a$7_@0[1:9] = Array []
39 [2] Const mutate b$8_@0[1:9] = Array []
40 - [3] If (read b$8_@0) then:bb2 else:bb1
40 + [3] If (read b$8_@0) then:bb2 else:bb1 fallthrough=bb1
41 bb2:
42 predecessor blocks: bb0
43 [4] Call mutate a$7_@0.push(read props$6.p0)
44 [5] Goto bb1
45 bb1:
46 predecessor blocks: bb2 bb0
47 - [6] If (read props$6.p1) then:bb4 else:bb3
47 + [6] If (read props$6.p1) then:bb4 else:bb3 fallthrough=bb3
48 bb4:
49 predecessor blocks: bb1
50 [7] Call mutate b$8_@0.push(read props$6.p2)
@@ -109,18 +109,18 @@ flowchart TB
109 ## Code
110
111 ```javascript
112 -function Component$0(props$1) {
113 - const a$2 = [];
114 - const b$3 = [];
115 - bb1: if (b$3) {
116 - a$2.push(props$1.p0);
112 +function Component$0(props$6) {
113 + const a$7 = [];
114 + const b$8 = [];
115 + bb1: if (b$8) {
116 + a$7.push(props$6.p0);
117 }
118
119 - bb3: if (props$1.p1) {
120 - b$3.push(props$1.p2);
119 + bb3: if (props$6.p1) {
120 + b$8.push(props$6.p2);
121 }
122
123 - return <Foo$4 a={a$2} b={b$3}></Foo$4>;
123 + return <Foo$4 a={a$7} b={b$8}></Foo$4>;
124 }
125
126 ```
@@ -131,14 +131,14 @@ bb0:
131 [1] Const mutate a$9_@0[0:10] = Array []
132 [2] Const mutate b$10_@0[0:10] = Array []
133 [3] Const mutate $11_@0[0:10] = Call mutate mayMutate$4_@0(mutate b$10_@0)
134 - [4] If (read $11_@0) then:bb2 else:bb1
134 + [4] If (read $11_@0) then:bb2 else:bb1 fallthrough=bb1
135 bb2:
136 predecessor blocks: bb0
137 [5] Call mutate a$9_@0.push(read props$8.p0)
138 [6] Goto bb1
139 bb1:
140 predecessor blocks: bb2 bb0
141 - [7] If (read props$8.p1) then:bb4 else:bb3
141 + [7] If (read props$8.p1) then:bb4 else:bb3 fallthrough=bb3
142 bb4:
143 predecessor blocks: bb1
144 [8] Call mutate b$10_@0.push(read props$8.p2)
@@ -200,18 +200,18 @@ flowchart TB
200 ## Code
201
202 ```javascript
203 -function Component$0(props$1) {
204 - const a$2 = [];
205 - const b$3 = [];
206 - bb1: if (mayMutate$4(b$3)) {
207 - a$2.push(props$1.p0);
203 +function Component$0(props$8) {
204 + const a$9 = [];
205 + const b$10 = [];
206 + bb1: if (mayMutate$4(b$10)) {
207 + a$9.push(props$8.p0);
208 }
209
210 - bb3: if (props$1.p1) {
211 - b$3.push(props$1.p2);
210 + bb3: if (props$8.p1) {
211 + b$10.push(props$8.p2);
212 }
213
214 - return <Foo$6 a={a$2} b={b$3}></Foo$6>;
214 + return <Foo$6 a={a$9} b={b$10}></Foo$6>;
215 }
216
217 ```
compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md
+8 -8
@@ -89,14 +89,14 @@ flowchart TB
89 ## Code
90
91 ```javascript
92 -function Component$0(props$1) {
93 - const a$2 = [];
94 - const b$3 = {};
95 - new Foo$4(a$2, b$3);
96 - let _$5 = <div a={a$2}></div>;
97 -
98 - new Foo$4(b$3);
99 - return <div a={a$2} b={b$3}></div>;
92 +function Component$0(props$9) {
93 + const a$10 = [];
94 + const b$11 = {};
95 + new Foo$4(a$10, b$11);
96 + const _$13 = <div a={a$10}></div>;
97 +
98 + new Foo$4(b$11);
99 + return <div a={a$10} b={b$11}></div>;
100 }
101
102 ```
compiler/forget/src/__tests__/fixtures/hir/dependencies-outputs.expect.md
+11 -11
@@ -27,14 +27,14 @@ bb0:
27 [3] Const mutate $9_@1 = "div"
28 [4] JSX <read $9_@1>{freeze x$8_@0}</read $9_@1>
29 [5] Const mutate y$10_@2[5:12] = Array []
30 - [6] If (read x$8_@0.length) then:bb2 else:bb1
30 + [6] If (read x$8_@0.length) then:bb2 else:bb1 fallthrough=bb1
31 bb2:
32 predecessor blocks: bb0
33 [7] Call mutate y$10_@2.push(read x$8_@0)
34 [8] Goto bb1
35 bb1:
36 predecessor blocks: bb2 bb0
37 - [9] If (read b$7) then:bb4 else:bb3
37 + [9] If (read b$7) then:bb4 else:bb3 fallthrough=bb3
38 bb4:
39 predecessor blocks: bb1
40 [10] Call mutate y$10_@2.push(read b$7)
@@ -100,17 +100,17 @@ flowchart TB
100 ## Code
101
102 ```javascript
103 -function foo$0(a$1, b$2) {
104 - const x$3 = [];
105 - x$3.push(a$1);
106 - <div>{x$3}</div>;
107 - const y$5 = [];
108 - bb1: if (x$3.length) {
109 - y$5.push(x$3);
103 +function foo$0(a$6, b$7) {
104 + const x$8 = [];
105 + x$8.push(a$6);
106 + <div>{x$8}</div>;
107 + const y$10 = [];
108 + bb1: if (x$8.length) {
109 + y$10.push(x$8);
110 }
111
112 - bb3: if (b$2) {
113 - y$5.push(b$2);
112 + bb3: if (b$7) {
113 + y$10.push(b$7);
114 }
115 }
116
compiler/forget/src/__tests__/fixtures/hir/dependencies.expect.md
+11 -11
@@ -27,14 +27,14 @@ bb0:
27 [1] Const mutate items$9_@0[1:10] = Array [read z$8]
28 [2] Call mutate items$9_@0.push(read x$6)
29 [3] Const mutate items2$10_@1[3:7] = Array []
30 - [4] If (read x$6) then:bb2 else:bb1
30 + [4] If (read x$6) then:bb2 else:bb1 fallthrough=bb1
31 bb2:
32 predecessor blocks: bb0
33 [5] Call mutate items2$10_@1.push(read y$7)
34 [6] Goto bb1
35 bb1:
36 predecessor blocks: bb2 bb0
37 - [7] If (read y$7) then:bb4 else:bb3
37 + [7] If (read y$7) then:bb4 else:bb3 fallthrough=bb3
38 bb4:
39 predecessor blocks: bb1
40 [8] Call mutate items$9_@0.push(read x$6)
@@ -97,19 +97,19 @@ flowchart TB
97 ## Code
98
99 ```javascript
100 -function foo$0(x$1, y$2, z$3) {
101 - const items$4 = [z$3];
102 - items$4.push(x$1);
103 - const items2$5 = [];
104 - bb1: if (x$1) {
105 - items2$5.push(y$2);
100 +function foo$0(x$6, y$7, z$8) {
101 + const items$9 = [z$8];
102 + items$9.push(x$6);
103 + const items2$10 = [];
104 + bb1: if (x$6) {
105 + items2$10.push(y$7);
106 }
107
108 - bb3: if (y$2) {
109 - items$4.push(x$1);
108 + bb3: if (y$7) {
109 + items$9.push(x$6);
110 }
111
112 - return items2$5;
112 + return items2$10;
113 }
114
115 ```
compiler/forget/src/__tests__/fixtures/hir/error.while-with-assignment-in-test.expect.md new
+25
@@ -0,0 +1,25 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function f(reader) {
6 + const queue = [1, 2, 3];
7 + let value = 0;
8 + let sum = 0;
9 + // BUG: we need to codegen the complex test expression
10 + while ((value = queue.pop()) != null) {
11 + sum += value;
12 + }
13 + return sum;
14 +}
15 +
16 +```
17 +
18 +
19 +## Error
20 +
21 +```
22 +TODO: Handle conversion of VariableDeclaration to expression
23 +```
24 +
25 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/error.while-with-assignment-in-test.js renamed
compiler/forget/src/__tests__/fixtures/hir/extend-scopes-if.expect.md
+12 -12
@@ -24,13 +24,13 @@ function foo(a, b, c) {
24 ```
25 bb0:
26 [1] Let mutate x$10_@0[1:8] = Array []
27 - [2] If (read a$7) then:bb2 else:bb1
27 + [2] If (read a$7) then:bb2 else:bb1 fallthrough=bb1
28 bb2:
29 predecessor blocks: bb0
30 - [3] If (read b$8) then:bb4 else:bb1
30 + [3] If (read b$8) then:bb4 else:bb1 fallthrough=bb1
31 bb4:
32 predecessor blocks: bb2
33 - [4] If (read c$9) then:bb6 else:bb1
33 + [4] If (read c$9) then:bb6 else:bb1 fallthrough=bb1
34 bb6:
35 predecessor blocks: bb4
36 [5] Const mutate $11_@1 = 0
@@ -38,7 +38,7 @@ bb6:
38 [7] Goto bb1
39 bb1:
40 predecessor blocks: bb6 bb4 bb2 bb0
41 - [8] If (read a$7.length) then:bb8 else:bb7
41 + [8] If (read a$7.length) then:bb8 else:bb7 fallthrough=bb7
42 bb8:
43 predecessor blocks: bb1
44 [9] Return read a$7
@@ -105,18 +105,18 @@ flowchart TB
105 ## Code
106
107 ```javascript
108 -function foo$0(a$1, b$2, c$3) {
109 - let x$4 = [];
110 - bb1: if (a$1) {
111 - if (b$2) {
112 - if (c$3) {
113 - x$4.push(0);
108 +function foo$0(a$7, b$8, c$9) {
109 + const x$10 = [];
110 + bb1: if (a$7) {
111 + if (b$8) {
112 + if (c$9) {
113 + x$10.push(0);
114 }
115 }
116 }
117
118 - bb7: if (a$1.length) {
119 - return a$1;
118 + bb7: if (a$7.length) {
119 + return a$7;
120 }
121
122 return null;
compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md
+5 -5
@@ -51,10 +51,10 @@ flowchart TB
51
52 ```javascript
53 function Component$0() {
54 - const a$1 = [];
55 - const b$2 = a$1;
56 - useFreeze$3(a$1);
57 - foo$4(b$2);
54 + const a$5 = [];
55 + const b$6 = a$5;
56 + useFreeze$3(a$5);
57 + foo$4(b$6);
58 }
59
60 ```
@@ -109,7 +109,7 @@ flowchart TB
109 ## Code
110
111 ```javascript
112 -function foo$0(x$1) {}
112 +function foo$0(x$2) {}
113
114 ```
115
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md
+6 -6
@@ -121,14 +121,14 @@ flowchart TB
121 ## Code
122
123 ```javascript
124 -function Component$0(props$1) {
125 - const x$2 = [];
126 - const y$3 = useFreeze$4(x$2);
127 - foo$5(y$3, x$2);
124 +function Component$0(props$10) {
125 + const x$11 = [];
126 + const y$12 = useFreeze$4(x$11);
127 + foo$5(y$12, x$11);
128 return (
129 <Component$0>
130 - {x$2}
131 - {y$3}
130 + {x$11}
131 + {y$12}
132 </Component$0>
133 );
134 }
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md
+7 -7
@@ -50,11 +50,11 @@ flowchart TB
50
51 ```javascript
52 function Component$0() {
53 - const a$1 = [];
54 - useFreeze$2(a$1);
55 - useFreeze$2(a$1);
56 - call$3(a$1);
57 - return a$1;
53 + const a$4 = [];
54 + useFreeze$2(a$4);
55 + useFreeze$2(a$4);
56 + call$3(a$4);
57 + return a$4;
58 }
59
60 ```
@@ -82,7 +82,7 @@ flowchart TB
82 ## Code
83
84 ```javascript
85 -function useFreeze$0(x$1) {}
85 +function useFreeze$0(x$2) {}
86
87 ```
88 ## HIR
@@ -109,7 +109,7 @@ flowchart TB
109 ## Code
110
111 ```javascript
112 -function call$0(x$1) {}
112 +function call$0(x$2) {}
113
114 ```
115
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+15 -14
@@ -29,7 +29,7 @@ bb0:
29 [1] Const mutate cond$8_@0 = read props$7.cond
30 [2] Const mutate x$9_@1 = read props$7.x
31 [3] Let mutate a$10_@2 = undefined
32 - [4] If (read cond$8_@0) then:bb2 else:bb3
32 + [4] If (read cond$8_@0) then:bb2 else:bb3 fallthrough=bb1
33 bb2:
34 predecessor blocks: bb0
35 [5] Reassign mutate a$11_@3[5:8] = read x$9_@1
@@ -99,20 +99,21 @@ flowchart TB
99 ## Code
100
101 ```javascript
102 -function Component$0(props$1) {
103 - const cond$2 = props$1.cond;
104 - const x$3 = props$1.x;
105 - let a$4 = undefined;
106 - bb1: if (cond$2) {
107 - a$4 = x$3;
102 +function Component$0(props$7) {
103 + const cond$8 = props$7.cond;
104 + const x$9 = props$7.x;
105 + const a$10 = undefined;
106 + let a$11 = undefined;
107 + bb1: if (cond$8) {
108 + a$11 = x$9;
109 } else {
109 - a$4 = [];
110 + a$11 = [];
111 }
112
112 - useFreeze$5(a$4);
113 - useFreeze$5(a$4);
114 - call$6(a$4);
115 - return a$4;
113 + useFreeze$5(a$11);
114 + useFreeze$5(a$11);
115 + call$6(a$11);
116 + return a$11;
117 }
118
119 ```
@@ -140,7 +141,7 @@ flowchart TB
141 ## Code
142
143 ```javascript
143 -function useFreeze$0(x$1) {}
144 +function useFreeze$0(x$2) {}
145
146 ```
147 ## HIR
@@ -167,7 +168,7 @@ flowchart TB
168 ## Code
169
170 ```javascript
170 -function call$0(x$1) {}
171 +function call$0(x$2) {}
172
173 ```
174
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md
+8 -8
@@ -147,7 +147,7 @@ function Foo$0() {}
147 bb0:
148 [1] Const mutate a$9_@0[0:7] = Call mutate compute$3_@0(read props$8.a)
149 [2] Const mutate b$10_@0[0:7] = Call mutate compute$3_@0(read props$8.b)
150 - [3] If (read props$8.c) then:bb2 else:bb1
150 + [3] If (read props$8.c) then:bb2 else:bb1 fallthrough=bb1
151 bb2:
152 predecessor blocks: bb0
153 [4] Call mutate mutate$5_@0(mutate a$9_@0)
@@ -198,15 +198,15 @@ flowchart TB
198 ## Code
199
200 ```javascript
201 -function Component$0(props$1) {
202 - const a$2 = compute$3(props$1.a);
203 - const b$4 = compute$3(props$1.b);
204 - bb1: if (props$1.c) {
205 - mutate$5(a$2);
206 - mutate$5(b$4);
201 +function Component$0(props$8) {
202 + const a$9 = compute$3(props$8.a);
203 + const b$10 = compute$3(props$8.b);
204 + bb1: if (props$8.c) {
205 + mutate$5(a$9);
206 + mutate$5(b$10);
207 }
208
209 - return <Foo$6 a={a$2} b={b$4}></Foo$6>;
209 + return <Foo$6 a={a$9} b={b$10}></Foo$6>;
210 }
211
212 ```
compiler/forget/src/__tests__/fixtures/hir/independent.expect.md
+4 -4
@@ -58,10 +58,10 @@ flowchart TB
58 ## Code
59
60 ```javascript
61 -function Component$0(props$1) {
62 - const a$2 = compute$3(props$1.a);
63 - const b$4 = compute$3(props$1.b);
64 - return <Foo$5 a={a$2} b={b$4}></Foo$5>;
61 +function Component$0(props$7) {
62 + const a$8 = compute$3(props$7.a);
63 + const b$9 = compute$3(props$7.b);
64 + return <Foo$5 a={a$8} b={b$9}></Foo$5>;
65 }
66
67 ```
compiler/forget/src/__tests__/fixtures/hir/interdependent-across-if.expect.md
+7 -7
@@ -114,7 +114,7 @@ function Foo$0() {}
114 bb0:
115 [1] Const mutate a$9_@0[0:6] = Call mutate compute$3_@0(read props$8.a)
116 [2] Const mutate b$10_@0[0:6] = Call mutate compute$3_@0(read props$8.b)
117 - [3] If (read props$8.c) then:bb2 else:bb1
117 + [3] If (read props$8.c) then:bb2 else:bb1 fallthrough=bb1
118 bb2:
119 predecessor blocks: bb0
120 [4] Call mutate foo$5_@0(mutate a$9_@0, mutate b$10_@0)
@@ -163,14 +163,14 @@ flowchart TB
163 ## Code
164
165 ```javascript
166 -function Component$0(props$1) {
167 - const a$2 = compute$3(props$1.a);
168 - const b$4 = compute$3(props$1.b);
169 - bb1: if (props$1.c) {
170 - foo$5(a$2, b$4);
166 +function Component$0(props$8) {
167 + const a$9 = compute$3(props$8.a);
168 + const b$10 = compute$3(props$8.b);
169 + bb1: if (props$8.c) {
170 + foo$5(a$9, b$10);
171 }
172
173 - return <Foo$6 a={a$2} b={b$4}></Foo$6>;
173 + return <Foo$6 a={a$9} b={b$10}></Foo$6>;
174 }
175
176 ```
compiler/forget/src/__tests__/fixtures/hir/interdependent.expect.md
+5 -5
@@ -60,11 +60,11 @@ flowchart TB
60 ## Code
61
62 ```javascript
63 -function Component$0(props$1) {
64 - const a$2 = compute$3(props$1.a);
65 - const b$4 = compute$3(props$1.b);
66 - foo$5(a$2, b$4);
67 - return <Foo$6 a={a$2} b={b$4}></Foo$6>;
63 +function Component$0(props$8) {
64 + const a$9 = compute$3(props$8.a);
65 + const b$10 = compute$3(props$8.b);
66 + foo$5(a$9, b$10);
67 + return <Foo$6 a={a$9} b={b$10}></Foo$6>;
68 }
69
70 ```
compiler/forget/src/__tests__/fixtures/hir/inverted-if.expect.md
+7 -7
@@ -19,10 +19,10 @@ function foo(a, b, c) {
19 ```
20 bb0:
21 [1] Let mutate y$8_@0[1:6] = Array []
22 - [2] If (read a$5) then:bb3 else:bb1
22 + [2] If (read a$5) then:bb3 else:bb1 fallthrough=bb1
23 bb3:
24 predecessor blocks: bb0
25 - [3] If (read b$6) then:bb5 else:bb1
25 + [3] If (read b$6) then:bb5 else:bb1 fallthrough=bb1
26 bb5:
27 predecessor blocks: bb3
28 [4] Call mutate y$8_@0.push(read c$7)
@@ -72,11 +72,11 @@ flowchart TB
72 ## Code
73
74 ```javascript
75 -function foo$0(a$1, b$2, c$3) {
76 - let y$4 = [];
77 - bb1: if (a$1) {
78 - if (b$2) {
79 - y$4.push(c$3);
75 +function foo$0(a$5, b$6, c$7) {
76 + const y$8 = [];
77 + bb1: if (a$5) {
78 + if (b$6) {
79 + y$8.push(c$7);
80 }
81 }
82 }
compiler/forget/src/__tests__/fixtures/hir/jsx-fragment.expect.md
+2 -2
@@ -76,10 +76,10 @@ flowchart TB
76 ## Code
77
78 ```javascript
79 -function Foo$0(props$1) {
79 +function Foo$0(props$13) {
80 return (
81 <>
82 - Hello {props$1.greeting}
82 + Hello {props$13.greeting}
83 {<div>{<>Text</>}</div>}
84 </>
85 );
compiler/forget/src/__tests__/fixtures/hir/logical-expression.expect.md
+4 -4
@@ -24,7 +24,7 @@ function g() {}
24 ```
25 bb0:
26 [1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
27 - [2] If (read $5_@0) then:bb2 else:bb3
27 + [2] If (read $5_@0) then:bb2 else:bb3 fallthrough=bb1
28 bb2:
29 predecessor blocks: bb0
30 [3] Const mutate $6_@1[0:6] = Call mutate g$4_@1()
@@ -92,7 +92,7 @@ function And$0() {
92 ```
93 bb0:
94 [1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
95 - [2] If (read $5_@0) then:bb2 else:bb3
95 + [2] If (read $5_@0) then:bb2 else:bb3 fallthrough=bb1
96 bb2:
97 predecessor blocks: bb0
98 [3] Const mutate $6_@1[0:6] = read $5_@0
@@ -162,7 +162,7 @@ bb0:
162 [1] Const mutate $9_@0[0:2] = Call mutate f$2_@0()
163 [2] Const mutate $10_@1 = null
164 [3] Const mutate $11_@2 = Binary read $9_@0 != read $10_@1
165 - [4] If (read $11_@2) then:bb2 else:bb3
165 + [4] If (read $11_@2) then:bb2 else:bb3 fallthrough=bb1
166 bb2:
167 predecessor blocks: bb0
168 [5] Const mutate $12_@3[0:8] = read $9_@0
@@ -221,7 +221,7 @@ flowchart TB
221 ## Code
222
223 ```javascript
224 -function QuestionQuestion$0(props$1) {
224 +function QuestionQuestion$0(props$8) {
225 bb1: if (f$2() != null) {
226 } else {
227 }
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+26 -26
@@ -63,7 +63,7 @@ flowchart TB
63 ## Code
64
65 ```javascript
66 -function mutate$0(x$1, y$2) {}
66 +function mutate$0(x$3, y$4) {}
67
68 ```
69 ## HIR
@@ -90,7 +90,7 @@ flowchart TB
90 ## Code
91
92 ```javascript
93 -function cond$0(x$1) {}
93 +function cond$0(x$2) {}
94
95 ```
96 ## HIR
@@ -109,7 +109,7 @@ bb1:
109 c$22_@0[0:23]: phi(bb0: c$15_@0, bb4: c$25_@0)
110 d$24_@0[0:23]: phi(bb0: d$16_@0, bb4: d$26_@0)
111 [6] Const mutate $17_@1[6:8] = true
112 - [7] If (read $17_@1) then:bb3 else:bb2
112 + [7] If (read $17_@1) then:bb3 else:bb2 fallthrough=bb2
113 bb3:
114 predecessor blocks: bb1
115 [8] Let mutate z$19_@0[0:23] = read a$18_@0
@@ -119,7 +119,7 @@ bb3:
119 [12] Reassign mutate d$26_@0[0:23] = read z$19_@0
120 [13] Call mutate mutate$7_@0(mutate a$21_@0, mutate b$23_@0)
121 [14] Const mutate $29_@0[0:23] = Call mutate cond$8_@0(mutate a$21_@0)
122 - [15] If (read $29_@0) then:bb2 else:bb4
122 + [15] If (read $29_@0) then:bb2 else:bb4 fallthrough=bb4
123 bb4:
124 predecessor blocks: bb3
125 [16] Goto(Continue) bb1
@@ -129,16 +129,16 @@ bb2:
129 b$31_@0[0:23]: phi(bb3: b$23_@0, bb1: b$20_@0)
130 c$32_@0[0:23]: phi(bb3: c$25_@0, bb1: c$22_@0)
131 d$33_@0[0:23]: phi(bb3: d$26_@0, bb1: d$24_@0)
132 - [17] If (read a$30_@0) then:bb7 else:bb7
132 + [17] If (read a$30_@0) then:bb7 else:bb7 fallthrough=bb7
133 bb7:
134 predecessor blocks: bb2
135 - [18] If (read b$31_@0) then:bb9 else:bb9
135 + [18] If (read b$31_@0) then:bb9 else:bb9 fallthrough=bb9
136 bb9:
137 predecessor blocks: bb7
138 - [19] If (read c$32_@0) then:bb11 else:bb11
138 + [19] If (read c$32_@0) then:bb11 else:bb11 fallthrough=bb11
139 bb11:
140 predecessor blocks: bb9
141 - [20] If (read d$33_@0) then:bb13 else:bb13
141 + [20] If (read d$33_@0) then:bb13 else:bb13 fallthrough=bb13
142 bb13:
143 predecessor blocks: bb11
144 [21] Const mutate $34_@2 = null
@@ -225,35 +225,35 @@ flowchart TB
225 ## Code
226
227 ```javascript
228 -function Component$0(props$1) {
229 - let a$2 = {};
230 - let b$3 = {};
231 - let c$4 = {};
232 - let d$5 = {};
228 +function Component$0(props$12) {
229 + let a$18 = {};
230 + let b$20 = {};
231 + let c$22 = {};
232 + let d$24 = {};
233 bb2: while (true) {
234 - let z$6 = a$2;
235 - a$2 = b$3;
236 - b$3 = c$4;
237 - c$4 = d$5;
238 - d$5 = z$6;
239 - mutate$7(a$2, b$3);
240 -
241 - bb4: if (cond$8(a$2)) break;
234 + const z$19 = a$18;
235 + a$18 = b$20;
236 + b$20 = c$22;
237 + c$22 = d$24;
238 + d$24 = z$19;
239 + mutate$7(a$18, b$20);
240 +
241 + bb4: if (cond$8(a$18)) break;
242 }
243
244 - bb7: if (a$2) {
244 + bb7: if (a$18) {
245 }
246
247 - bb9: if (b$3) {
247 + bb9: if (b$20) {
248 }
249
250 - bb11: if (c$4) {
250 + bb11: if (c$22) {
251 }
252
253 - bb13: if (d$5) {
253 + bb13: if (d$24) {
254 }
255
256 - mutate$7(d$5, null);
256 + mutate$7(d$24, null);
257 }
258
259 ```
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-with-aliasing.expect.md
+21 -21
@@ -59,7 +59,7 @@ flowchart TB
59 ## Code
60
61 ```javascript
62 -function mutate$0(x$1, y$2) {}
62 +function mutate$0(x$3, y$4) {}
63
64 ```
65 ## HIR
@@ -73,19 +73,19 @@ bb0:
73 [5] Const mutate x$15_@1[0:15] = Object { }
74 [6] Reassign mutate x$15_@1.b[0:15] = read b$12_@1
75 [7] Const mutate y$16_@1[0:15] = Call mutate mutate$8_@1(mutate x$15_@1, mutate d$14_@1)
76 - [8] If (read a$11_@0) then:bb1 else:bb1
76 + [8] If (read a$11_@0) then:bb1 else:bb1 fallthrough=bb1
77 bb1:
78 predecessor blocks: bb0
79 - [9] If (read b$12_@1) then:bb3 else:bb3
79 + [9] If (read b$12_@1) then:bb3 else:bb3 fallthrough=bb3
80 bb3:
81 predecessor blocks: bb1
82 - [10] If (read c$13_@2) then:bb5 else:bb5
82 + [10] If (read c$13_@2) then:bb5 else:bb5 fallthrough=bb5
83 bb5:
84 predecessor blocks: bb3
85 - [11] If (read d$14_@1) then:bb7 else:bb7
85 + [11] If (read d$14_@1) then:bb7 else:bb7 fallthrough=bb7
86 bb7:
87 predecessor blocks: bb5
88 - [12] If (read y$16_@1) then:bb9 else:bb9
88 + [12] If (read y$16_@1) then:bb9 else:bb9 fallthrough=bb9
89 bb9:
90 predecessor blocks: bb7
91 [13] Const mutate $17_@3 = null
@@ -148,32 +148,32 @@ flowchart TB
148 ## Code
149
150 ```javascript
151 -function Component$0(props$1) {
152 - const a$2 = {};
153 - const b$3 = [a$2];
154 - const c$4 = {};
155 - const d$5 = {
156 - c: c$4,
151 +function Component$0(props$10) {
152 + const a$11 = {};
153 + const b$12 = [a$11];
154 + const c$13 = {};
155 + const d$14 = {
156 + c: c$13,
157 };
158 - const x$6 = {};
159 - x$6.b = b$3;
160 - const y$7 = mutate$8(x$6, d$5);
161 - bb1: if (a$2) {
158 + const x$15 = {};
159 + x$15.b = b$12;
160 + const y$16 = mutate$8(x$15, d$14);
161 + bb1: if (a$11) {
162 }
163
164 - bb3: if (b$3) {
164 + bb3: if (b$12) {
165 }
166
167 - bb5: if (c$4) {
167 + bb5: if (c$13) {
168 }
169
170 - bb7: if (d$5) {
170 + bb7: if (d$14) {
171 }
172
173 - bb9: if (y$7) {
173 + bb9: if (y$16) {
174 }
175
176 - mutate$8(x$6, null);
176 + mutate$8(x$15, null);
177 }
178
179 ```
compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md
+18 -18
@@ -100,27 +100,27 @@ bb0:
100 bb1:
101 predecessor blocks: bb0 bb4
102 [6] Const mutate $16_@2[6:8] = true
103 - [7] If (read $16_@2) then:bb3 else:bb2
103 + [7] If (read $16_@2) then:bb3 else:bb2 fallthrough=bb2
104 bb3:
105 predecessor blocks: bb1
106 [8] Call mutate mutate$6_@0(mutate a$12_@0, mutate b$13_@0)
107 [9] Const mutate $21_@0[0:18] = Call mutate cond$7_@0(mutate a$12_@0)
108 - [10] If (read $21_@0) then:bb2 else:bb4
108 + [10] If (read $21_@0) then:bb2 else:bb4 fallthrough=bb4
109 bb4:
110 predecessor blocks: bb3
111 [11] Goto(Continue) bb1
112 bb2:
113 predecessor blocks: bb3 bb1
114 - [12] If (read a$12_@0) then:bb7 else:bb7
114 + [12] If (read a$12_@0) then:bb7 else:bb7 fallthrough=bb7
115 bb7:
116 predecessor blocks: bb2
117 - [13] If (read b$13_@0) then:bb9 else:bb9
117 + [13] If (read b$13_@0) then:bb9 else:bb9 fallthrough=bb9
118 bb9:
119 predecessor blocks: bb7
120 - [14] If (read c$14_@1) then:bb11 else:bb11
120 + [14] If (read c$14_@1) then:bb11 else:bb11 fallthrough=bb11
121 bb11:
122 predecessor blocks: bb9
123 - [15] If (read d$15_@0) then:bb13 else:bb13
123 + [15] If (read d$15_@0) then:bb13 else:bb13 fallthrough=bb13
124 bb13:
125 predecessor blocks: bb11
126 [16] Const mutate $28_@3 = null
@@ -202,30 +202,30 @@ flowchart TB
202 ## Code
203
204 ```javascript
205 -function Component$0(props$1) {
206 - let a$2 = {};
207 - let b$3 = {};
208 - let c$4 = {};
209 - let d$5 = {};
205 +function Component$0(props$11) {
206 + const a$12 = {};
207 + const b$13 = {};
208 + const c$14 = {};
209 + const d$15 = {};
210 bb2: while (true) {
211 - mutate$6(a$2, b$3);
211 + mutate$6(a$12, b$13);
212
213 - bb4: if (cond$7(a$2)) break;
213 + bb4: if (cond$7(a$12)) break;
214 }
215
216 - bb7: if (a$2) {
216 + bb7: if (a$12) {
217 }
218
219 - bb9: if (b$3) {
219 + bb9: if (b$13) {
220 }
221
222 - bb11: if (c$4) {
222 + bb11: if (c$14) {
223 }
224
225 - bb13: if (d$5) {
225 + bb13: if (d$15) {
226 }
227
228 - mutate$6(d$5, null);
228 + mutate$6(d$15, null);
229 }
230
231 ```
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-interleaved-by-terminal.expect.md
+7 -7
@@ -21,7 +21,7 @@ function foo(a, b, c) {
21 bb0:
22 [1] Const mutate x$9_@0[1:6] = Array []
23 [2] Const mutate y$10_@0[1:6] = Array []
24 - [3] If (read x$9_@0) then:bb1 else:bb1
24 + [3] If (read x$9_@0) then:bb1 else:bb1 fallthrough=bb1
25 bb1:
26 predecessor blocks: bb0
27 [4] Call mutate y$10_@0.push(read a$6)
@@ -61,14 +61,14 @@ flowchart TB
61 ## Code
62
63 ```javascript
64 -function foo$0(a$1, b$2, c$3) {
65 - const x$4 = [];
66 - const y$5 = [];
67 - bb1: if (x$4) {
64 +function foo$0(a$6, b$7, c$8) {
65 + const x$9 = [];
66 + const y$10 = [];
67 + bb1: if (x$9) {
68 }
69
70 - y$5.push(a$1);
71 - x$4.push(b$2);
70 + y$10.push(a$6);
71 + x$9.push(b$7);
72 }
73
74 ```
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-interleaved.expect.md
+5 -5
@@ -47,11 +47,11 @@ flowchart TB
47 ## Code
48
49 ```javascript
50 -function foo$0(a$1, b$2) {
51 - let x$3 = [];
52 - let y$4 = [];
53 - x$3.push(a$1);
54 - y$4.push(b$2);
50 +function foo$0(a$5, b$6) {
51 + const x$7 = [];
52 + const y$8 = [];
53 + x$7.push(a$5);
54 + y$8.push(b$6);
55 }
56
57 ```
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-shadowed.expect.md
+5 -5
@@ -47,11 +47,11 @@ flowchart TB
47 ## Code
48
49 ```javascript
50 -function foo$0(a$1, b$2) {
51 - let x$3 = [];
52 - let y$4 = [];
53 - y$4.push(b$2);
54 - x$3.push(a$1);
50 +function foo$0(a$5, b$6) {
51 + const x$7 = [];
52 + const y$8 = [];
53 + y$8.push(b$6);
54 + x$7.push(a$5);
55 }
56
57 ```
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-shadowing-within-block.expect.md
+10 -10
@@ -22,11 +22,11 @@ function foo(a, b, c) {
22 ```
23 bb0:
24 [1] Let mutate x$11_@0[1:11] = Array []
25 - [2] If (read a$8) then:bb2 else:bb1
25 + [2] If (read a$8) then:bb2 else:bb1 fallthrough=bb1
26 bb2:
27 predecessor blocks: bb0
28 [3] Let mutate y$12_@1[3:7] = Array []
29 - [4] If (read b$9) then:bb4 else:bb3
29 + [4] If (read b$9) then:bb4 else:bb3 fallthrough=bb3
30 bb4:
31 predecessor blocks: bb2
32 [5] Call mutate y$12_@1.push(read c$10)
@@ -98,19 +98,19 @@ flowchart TB
98 ## Code
99
100 ```javascript
101 -function foo$0(a$1, b$2, c$3) {
102 - let x$4 = [];
103 - bb1: if (a$1) {
104 - let y$5 = [];
101 +function foo$0(a$8, b$9, c$10) {
102 + const x$11 = [];
103 + bb1: if (a$8) {
104 + const y$12 = [];
105
106 - bb3: if (b$2) {
107 - y$5.push(c$3);
106 + bb3: if (b$9) {
107 + y$12.push(c$10);
108 }
109
110 - x$4.push(<div>{y$5}</div>);
110 + x$11.push(<div>{y$12}</div>);
111 }
112
113 - return x$4;
113 + return x$11;
114 }
115
116 ```
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-while.expect.md
+7 -7
@@ -22,7 +22,7 @@ bb0:
22 [3] While test=bb1 loop=bb3 fallthrough=bb2
23 bb1:
24 predecessor blocks: bb0 bb3
25 - [4] If (read c$8) then:bb3 else:bb2
25 + [4] If (read c$8) then:bb3 else:bb2 fallthrough=bb2
26 bb3:
27 predecessor blocks: bb1
28 [5] Call mutate y$10_@0.push(read b$7)
@@ -76,12 +76,12 @@ flowchart TB
76 ## Code
77
78 ```javascript
79 -function foo$0(a$1, b$2, c$3) {
80 - let x$4 = [];
81 - let y$5 = [];
82 - bb2: while (c$3) {
83 - y$5.push(b$2);
84 - x$4.push(a$1);
79 +function foo$0(a$6, b$7, c$8) {
80 + const x$9 = [];
81 + const y$10 = [];
82 + bb2: while (c$8) {
83 + y$10.push(b$7);
84 + x$9.push(a$6);
85 }
86 }
87
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-within-block.expect.md
+10 -10
@@ -22,11 +22,11 @@ function foo(a, b, c) {
22 ```
23 bb0:
24 [1] Let mutate x$9_@0[1:9] = Array []
25 - [2] If (read a$6) then:bb2 else:bb1
25 + [2] If (read a$6) then:bb2 else:bb1 fallthrough=bb1
26 bb2:
27 predecessor blocks: bb0
28 [3] Let mutate y$10_@0[1:9] = Array []
29 - [4] If (read b$7) then:bb4 else:bb3
29 + [4] If (read b$7) then:bb4 else:bb3 fallthrough=bb3
30 bb4:
31 predecessor blocks: bb2
32 [5] Call mutate y$10_@0.push(read c$8)
@@ -90,19 +90,19 @@ flowchart TB
90 ## Code
91
92 ```javascript
93 -function foo$0(a$1, b$2, c$3) {
94 - let x$4 = [];
95 - bb1: if (a$1) {
96 - let y$5 = [];
93 +function foo$0(a$6, b$7, c$8) {
94 + const x$9 = [];
95 + bb1: if (a$6) {
96 + const y$10 = [];
97
98 - bb3: if (b$2) {
99 - y$5.push(c$3);
98 + bb3: if (b$7) {
99 + y$10.push(c$8);
100 }
101
102 - x$4.push(y$5);
102 + x$9.push(y$10);
103 }
104
105 - return x$4;
105 + return x$9;
106 }
107
108 ```
compiler/forget/src/__tests__/fixtures/hir/property-assignment.expect.md
+7 -7
@@ -57,13 +57,13 @@ flowchart TB
57 ## Code
58
59 ```javascript
60 -function Component$0(props$1) {
61 - const x$2 = {};
62 - const y$3 = [];
63 - x$2.y = y$3;
64 - const child$4 = <Component$0 data={y$3}></Component$0>;
65 - x$2.y.push(props$1.p0);
66 - return <Component$0 data={x$2}>{child$4}</Component$0>;
60 +function Component$0(props$6) {
61 + const x$7 = {};
62 + const y$8 = [];
63 + x$7.y = y$8;
64 + const child$9 = <Component$0 data={y$8}></Component$0>;
65 + x$7.y.push(props$6.p0);
66 + return <Component$0 data={x$7}>{child$9}</Component$0>;
67 }
68
69 ```
compiler/forget/src/__tests__/fixtures/hir/reactive-scope-grouping.expect.md
+6 -6
@@ -51,12 +51,12 @@ flowchart TB
51
52 ```javascript
53 function foo$0() {
54 - let x$1 = {};
55 - let y$2 = [];
56 - let z$3 = {};
57 - y$2.push(z$3);
58 - x$1.y = y$2;
59 - return x$1;
54 + const x$4 = {};
55 + const y$5 = [];
56 + const z$6 = {};
57 + y$5.push(z$6);
58 + x$4.y = y$5;
59 + return x$4;
60 }
61
62 ```
compiler/forget/src/__tests__/fixtures/hir/reactive-scopes.expect.md
+8 -8
@@ -22,10 +22,10 @@ bb0:
22 [1] Let mutate x$10_@0[1:8] = Array []
23 [2] Const mutate $11_@1 = 1
24 [3] Const mutate $12_@2 = Binary read a$8.length === read $11_@1
25 - [4] If (read $12_@2) then:bb2 else:bb1
25 + [4] If (read $12_@2) then:bb2 else:bb1 fallthrough=bb1
26 bb2:
27 predecessor blocks: bb0
28 - [5] If (read b$9) then:bb4 else:bb1
28 + [5] If (read b$9) then:bb4 else:bb1 fallthrough=bb1
29 bb4:
30 predecessor blocks: bb2
31 [6] Call mutate x$10_@0.push(read b$9)
@@ -88,15 +88,15 @@ flowchart TB
88 ## Code
89
90 ```javascript
91 -function f$0(a$1, b$2) {
92 - let x$3 = [];
93 - bb1: if (a$1.length === 1) {
94 - if (b$2) {
95 - x$3.push(b$2);
91 +function f$0(a$8, b$9) {
92 + const x$10 = [];
93 + bb1: if (a$8.length === 1) {
94 + if (b$9) {
95 + x$10.push(b$9);
96 }
97 }
98
99 - return <div>{x$3}</div>;
99 + return <div>{x$10}</div>;
100 }
101
102 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+10 -10
@@ -26,7 +26,7 @@ bb0:
26 [1] Let mutate x$7_@0[1:7] = Array []
27 [2] Call mutate x$7_@0.push(read props$6.p0)
28 [3] Let mutate y$8_@0[1:7] = read x$7_@0
29 - [4] If (read props$6.p1) then:bb2 else:bb1
29 + [4] If (read props$6.p1) then:bb2 else:bb1 fallthrough=bb1
30 bb2:
31 predecessor blocks: bb0
32 [5] Reassign mutate x$9_@0[1:7] = Array []
@@ -88,18 +88,18 @@ flowchart TB
88 ## Code
89
90 ```javascript
91 -function Component$0(props$1) {
92 - let x$2 = [];
93 - x$2.push(props$1.p0);
94 - let y$3 = x$2;
95 - bb1: if (props$1.p1) {
96 - x$2 = [];
91 +function Component$0(props$6) {
92 + let x$7 = [];
93 + x$7.push(props$6.p0);
94 + const y$8 = x$7;
95 + bb1: if (props$6.p1) {
96 + x$7 = [];
97 }
98
99 - let _$4 = <Component$0 x={x$2}></Component$0>;
99 + const _$12 = <Component$0 x={x$7}></Component$0>;
100
101 - y$3.push(props$1.p2);
102 - return <Component$0 x={x$2} y={y$3}></Component$0>;
101 + y$8.push(props$6.p2);
102 + return <Component$0 x={x$7} y={y$8}></Component$0>;
103 }
104
105 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md
+15 -13
@@ -35,7 +35,7 @@ function foo(a, b, c) {
35 ```
36 bb0:
37 [1] Let mutate x$16_@0[1:5] = Array []
38 - [2] If (read a$13) then:bb2 else:bb1
38 + [2] If (read a$13) then:bb2 else:bb1 fallthrough=bb1
39 bb2:
40 predecessor blocks: bb0
41 [3] Call mutate x$16_@0.push(read a$13)
@@ -48,6 +48,7 @@ bb1:
48 [8] Switch (read b$14)
49 Case read $20_@3: bb5
50 Default: bb4
51 + Fallthrough: bb3
52 bb5:
53 predecessor blocks: bb1
54 [9] Reassign mutate x$22_@4[9:14] = Array []
@@ -150,31 +151,32 @@ flowchart TB
151 ## Code
152
153 ```javascript
153 -function foo$0(a$1, b$2, c$3) {
154 - let x$4 = [];
155 - bb1: if (a$1) {
156 - x$4.push(a$1);
154 +function foo$0(a$13, b$14, c$15) {
155 + const x$16 = [];
156 + bb1: if (a$13) {
157 + x$16.push(a$13);
158 }
159
159 - let y$5 = <div>{x$4}</div>;
160 + const y$19 = <div>{x$16}</div>;
161 + let x$22 = undefined;
162
161 - bb3: switch (b$2) {
163 + bb3: switch (b$14) {
164 case 0: {
163 - x$4 = [];
164 - x$4.push(b$2);
165 + x$22 = [];
166 + x$22.push(b$14);
167 break bb3;
168 }
169
170 default: {
169 - x$4 = [];
170 - x$4.push(c$3);
171 + x$22 = [];
172 + x$22.push(c$15);
173 }
174 }
175
176 return (
177 <div>
176 - {y$5}
177 - {x$4}
178 + {y$19}
179 + {x$22}
180 </div>
181 );
182 }
compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md
+8 -8
@@ -66,15 +66,15 @@ flowchart TB
66 ## Code
67
68 ```javascript
69 -function Component$0(props$1) {
70 - let x$2 = [];
71 - x$2.push(props$1.p0);
72 - let y$3 = x$2;
73 - x$2 = [];
74 - let _$4 = <Component$0 x={x$2}></Component$0>;
69 +function Component$0(props$6) {
70 + const x$7 = [];
71 + x$7.push(props$6.p0);
72 + const y$8 = x$7;
73 + const x$9 = [];
74 + const _$10 = <Component$0 x={x$9}></Component$0>;
75
76 - y$3.push(props$1.p1);
77 - return <Component$0 x={x$2} y={y$3}></Component$0>;
76 + y$8.push(props$6.p1);
77 + return <Component$0 x={x$9} y={y$8}></Component$0>;
78 }
79
80 ```
compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md
+15 -13
@@ -37,7 +37,7 @@ function Component(props) {
37 ```
38 bb0:
39 [1] Let mutate x$7_@0 = undefined
40 - [2] If (read props$6.cond) then:bb2 else:bb10
40 + [2] If (read props$6.cond) then:bb2 else:bb10 fallthrough=bb1
41 bb2:
42 predecessor blocks: bb0
43 [3] Const mutate $8_@1 = 2
@@ -48,6 +48,7 @@ bb2:
48 Case read $9_@2: bb6
49 Case read $8_@1: bb4
50 Default: bb4
51 + Fallthrough: bb1
52 bb8:
53 predecessor blocks: bb2
54 [7] Reassign mutate x$11_@4[7:17] = read props$6.v0
@@ -62,7 +63,7 @@ bb4:
63 [12] Goto bb1
64 bb10:
65 predecessor blocks: bb0
65 - [13] If (read props$6.cond2) then:bb12 else:bb13
66 + [13] If (read props$6.cond2) then:bb12 else:bb13 fallthrough=bb1
67 bb12:
68 predecessor blocks: bb10
69 [14] Reassign mutate x$14_@4[7:17] = read props$6.b
@@ -167,17 +168,18 @@ flowchart TB
168 ## Code
169
170 ```javascript
170 -function Component$0(props$1) {
171 - let x$2 = undefined;
172 - bb1: if (props$1.cond) {
173 - switch (props$1.test) {
171 +function Component$0(props$6) {
172 + const x$7 = undefined;
173 + let x$11 = undefined;
174 + bb1: if (props$6.cond) {
175 + switch (props$6.test) {
176 case 0: {
175 - x$2 = props$1.v0;
177 + x$11 = props$6.v0;
178 break bb1;
179 }
180
181 case 1: {
180 - x$2 = props$1.v1;
182 + x$11 = props$6.v1;
183 break bb1;
184 }
185
@@ -185,18 +187,18 @@ function Component$0(props$1) {
187 }
188
189 default: {
188 - x$2 = props$1.v2;
190 + x$11 = props$6.v2;
191 }
192 }
193 } else {
192 - if (props$1.cond2) {
193 - x$2 = props$1.b;
194 + if (props$6.cond2) {
195 + x$11 = props$6.b;
196 } else {
195 - x$2 = props$1.c;
197 + x$11 = props$6.c;
198 }
199 }
200
199 - x$2;
201 + x$11;
202 }
203
204 ```
compiler/forget/src/__tests__/fixtures/hir/simple-alias.expect.md
+8 -8
@@ -84,14 +84,14 @@ flowchart TB
84
85 ```javascript
86 function foo$0() {
87 - let a$1 = {};
88 - let b$2 = {};
89 - let c$3 = {};
90 - a$1 = b$2;
91 - b$2 = c$3;
92 - c$3 = a$1;
93 - mutate$4(a$1, b$2);
94 - return c$3;
87 + const a$5 = {};
88 + const b$6 = {};
89 + const c$7 = {};
90 + const a$8 = b$6;
91 + const b$9 = c$7;
92 + const c$10 = a$8;
93 + mutate$4(a$8, b$9);
94 + return c$10;
95 }
96
97 ```
compiler/forget/src/__tests__/fixtures/hir/simple.expect.md
+5 -5
@@ -15,7 +15,7 @@ function foo(x, y) {
15
16 ```
17 bb0:
18 - [1] If (read x$8) then:bb2 else:bb1
18 + [1] If (read x$8) then:bb2 else:bb1 fallthrough=bb1
19 bb2:
20 predecessor blocks: bb0
21 [2] Const mutate $10_@0 = false
@@ -71,11 +71,11 @@ flowchart TB
71 ## Code
72
73 ```javascript
74 -function foo$0(x$1, y$2) {
75 - bb1: if (x$1) {
76 - return foo$0(false, y$2);
74 +function foo$0(x$8, y$9) {
75 + bb1: if (x$8) {
76 + return foo$0(false, y$9);
77 }
78 - return [y$2 * 10];
78 + return [y$9 * 10];
79 }
80
81 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-arrayexpression.expect.md
+5 -5
@@ -45,11 +45,11 @@ flowchart TB
45 ## Code
46
47 ```javascript
48 -function Component$0(props$1) {
49 - const a$2 = 1;
50 - const b$3 = 2;
51 - const x$4 = [a$2, b$3];
52 - return x$4;
48 +function Component$0(props$5) {
49 + const a$6 = 1;
50 + const b$7 = 2;
51 + const x$8 = [a$6, b$7];
52 + return x$8;
53 }
54
55 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx-2.expect.md
+8 -8
@@ -53,7 +53,7 @@ bb0:
53 [2] Const mutate b$12_@0[0:10] = Object { }
54 [3] Call mutate foo$4_@0(mutate a$11_@0, mutate b$12_@0)
55 [4] Const mutate $13_@0[0:10] = Call mutate foo$4_@0()
56 - [5] If (read $13_@0) then:bb2 else:bb1
56 + [5] If (read $13_@0) then:bb2 else:bb1 fallthrough=bb1
57 bb2:
58 predecessor blocks: bb0
59 [6] Const mutate $14_@1 = "div"
@@ -113,16 +113,16 @@ flowchart TB
113 ## Code
114
115 ```javascript
116 -function Component$0(props$1) {
117 - const a$2 = [];
118 - const b$3 = {};
119 - foo$4(a$2, b$3);
116 +function Component$0(props$10) {
117 + const a$11 = [];
118 + const b$12 = {};
119 + foo$4(a$11, b$12);
120 bb1: if (foo$4()) {
121 - let _$5 = <div a={a$2}></div>;
121 + const _$15 = <div a={a$11}></div>;
122 }
123
124 - foo$4(a$2, b$3);
125 - return <div a={a$2} b={b$3}></div>;
124 + foo$4(a$11, b$12);
125 + return <div a={a$11} b={b$12}></div>;
126 }
127
128 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx.expect.md
+8 -8
@@ -89,14 +89,14 @@ flowchart TB
89 ## Code
90
91 ```javascript
92 -function Component$0(props$1) {
93 - const a$2 = [];
94 - const b$3 = {};
95 - foo$4(a$2, b$3);
96 - let _$5 = <div a={a$2}></div>;
97 -
98 - foo$4(a$2, b$3);
99 - return <div a={a$2} b={b$3}></div>;
92 +function Component$0(props$9) {
93 + const a$10 = [];
94 + const b$11 = {};
95 + foo$4(a$10, b$11);
96 + const _$13 = <div a={a$10}></div>;
97 +
98 + foo$4(a$10, b$11);
99 + return <div a={a$10} b={b$11}></div>;
100 }
101
102 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-multiple-if.expect.md
+11 -9
@@ -25,7 +25,7 @@ bb0:
25 [2] Let mutate y$8_@1 = 2
26 [3] Const mutate $9_@2 = 2
27 [4] Const mutate $10_@3 = Binary read y$8_@1 === read $9_@2
28 - [5] If (read $10_@3) then:bb2 else:bb1
28 + [5] If (read $10_@3) then:bb2 else:bb1 fallthrough=bb1
29 bb2:
30 predecessor blocks: bb0
31 [6] Reassign mutate x$11_@0[1:14] = 3
@@ -35,7 +35,7 @@ bb1:
35 x$17_@0[1:14]: phi(bb2: x$11_@0, bb0: x$7_@0)
36 [8] Const mutate $12_@4 = 3
37 [9] Const mutate $14_@5 = Binary read y$8_@1 === read $12_@4
38 - [10] If (read $14_@5) then:bb4 else:bb3
38 + [10] If (read $14_@5) then:bb4 else:bb3 fallthrough=bb3
39 bb4:
40 predecessor blocks: bb1
41 [11] Reassign mutate x$15_@0[1:14] = 5
@@ -107,17 +107,19 @@ flowchart TB
107
108 ```javascript
109 function foo$0() {
110 - let x$1 = 1;
111 - let y$2 = 2;
112 - bb1: if (y$2 === 2) {
113 - x$1 = 3;
110 + let x$7 = 1;
111 + const y$8 = 2;
112 + bb1: if (y$8 === 2) {
113 + x$7 = 3;
114 }
115
116 - bb3: if (y$2 === 3) {
117 - x$1 = 5;
116 + let x$15 = undefined;
117 +
118 + bb3: if (y$8 === 3) {
119 + x$15 = 5;
120 }
121
120 - y$2 = x$1;
122 + const y$18 = x$15;
123 }
124
125 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-single-if.expect.md
+6 -6
@@ -22,7 +22,7 @@ bb0:
22 [2] Let mutate y$6_@1 = 2
23 [3] Const mutate $7_@2 = 2
24 [4] Const mutate $8_@3 = Binary read y$6_@1 === read $7_@2
25 - [5] If (read $8_@3) then:bb2 else:bb1
25 + [5] If (read $8_@3) then:bb2 else:bb1 fallthrough=bb1
26 bb2:
27 predecessor blocks: bb0
28 [6] Reassign mutate x$9_@0[1:9] = 3
@@ -75,13 +75,13 @@ flowchart TB
75
76 ```javascript
77 function foo$0() {
78 - let x$1 = 1;
79 - let y$2 = 2;
80 - bb1: if (y$2 === 2) {
81 - x$1 = 3;
78 + let x$5 = 1;
79 + const y$6 = 2;
80 + bb1: if (y$6 === 2) {
81 + x$5 = 3;
82 }
83
84 - y$2 = x$1;
84 + const y$11 = x$5;
85 }
86
87 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-for-of.expect.md
+4 -4
@@ -23,11 +23,11 @@ bb0:
23 [2] Goto bb1
24 bb1:
25 predecessor blocks: bb0 bb4
26 - [3] If (read items$5_@0) then:bb3 else:bb2
26 + [3] If (read items$5_@0) then:bb3 else:bb2 fallthrough=bb2
27 bb3:
28 predecessor blocks: bb1
29 [4] Let mutate y$7_@1 = 0
30 - [5] If (read cond$4) then:bb5 else:bb4
30 + [5] If (read cond$4) then:bb5 else:bb4 fallthrough=bb4
31 bb5:
32 predecessor blocks: bb3
33 [6] Reassign mutate y$9_@2 = 1
@@ -88,8 +88,8 @@ flowchart TB
88 ## Code
89
90 ```javascript
91 -function foo$0(cond$1) {
92 - let items$2 = [];
91 +function foo$0(cond$4) {
92 + const items$5 = [];
93 }
94
95 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-for.expect.md
+5 -5
@@ -27,7 +27,7 @@ bb1:
27 x$13_@0[0:13]: phi(bb3: x$7_@0, bb4: x$14_@0)
28 [5] Const mutate $9_@2 = 10
29 [6] Const mutate $11_@3[6:8] = Binary read i$8_@1 < read $9_@2
30 - [7] If (read $11_@3) then:bb5 else:bb2
30 + [7] If (read $11_@3) then:bb5 else:bb2 fallthrough=bb2
31 bb5:
32 predecessor blocks: bb1
33 [8] Const mutate $12_@4 = 1
@@ -103,12 +103,12 @@ flowchart TB
103
104 ```javascript
105 function foo$0() {
106 - let x$1 = 1;
107 - bb2: for (let i$2 = 0; i$2 < 10; update$3()) {
108 - x$1 = x$1 + 1;
106 + let x$7 = 1;
107 + bb2: for (const i$8 = 0; i$8 < 10; update$3()) {
108 + x$7 = x$7 + 1;
109 }
110
111 - return x$1;
111 + return x$7;
112 }
113
114 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-if-else.expect.md
+6 -6
@@ -21,7 +21,7 @@ function foo() {
21 bb0:
22 [1] Let mutate x$5_@0 = 1
23 [2] Let mutate y$6_@1 = 2
24 - [3] If (read y$6_@1) then:bb2 else:bb3
24 + [3] If (read y$6_@1) then:bb2 else:bb3 fallthrough=bb1
25 bb2:
26 predecessor blocks: bb0
27 [4] Let mutate z$7_@2 = Binary read x$5_@0 + read y$6_@1
@@ -81,12 +81,12 @@ flowchart TB
81
82 ```javascript
83 function foo$0() {
84 - let x$1 = 1;
85 - let y$2 = 2;
86 - bb1: if (y$2) {
87 - let z$3 = x$1 + y$2;
84 + const x$5 = 1;
85 + const y$6 = 2;
86 + bb1: if (y$6) {
87 + const z$7 = x$5 + y$6;
88 } else {
89 - let z$4 = x$1;
89 + const z$8 = x$5;
90 }
91 }
92
compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.expect.md new
+195
@@ -0,0 +1,195 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo(a, b, c, d) {
6 + let x = 0;
7 + if (true) {
8 + if (true) {
9 + x = a;
10 + } else {
11 + x = b;
12 + }
13 + x;
14 + } else {
15 + if (true) {
16 + x = c;
17 + } else {
18 + x = d;
19 + }
20 + x;
21 + }
22 + x;
23 +}
24 +
25 +```
26 +
27 +## HIR
28 +
29 +```
30 +bb0:
31 + [1] Let mutate x$13_@0 = 0
32 + [2] Const mutate $14_@1 = true
33 + [3] If (read $14_@1) then:bb2 else:bb6 fallthrough=bb1
34 +bb2:
35 + predecessor blocks: bb0
36 + [4] Const mutate $15_@2 = true
37 + [5] If (read $15_@2) then:bb4 else:bb5 fallthrough=bb3
38 +bb4:
39 + predecessor blocks: bb2
40 + [6] Reassign mutate x$16_@3[6:17] = read a$9
41 + [7] Goto bb3
42 +bb5:
43 + predecessor blocks: bb2
44 + [8] Reassign mutate x$17_@3[6:17] = read b$10
45 + [9] Goto bb3
46 +bb3:
47 + predecessor blocks: bb4 bb5
48 + x$18_@3[6:17]: phi(bb4: x$16_@3, bb5: x$17_@3)
49 + [10] read x$18_@3
50 + [11] Goto bb1
51 +bb6:
52 + predecessor blocks: bb0
53 + [12] Const mutate $19_@4 = true
54 + [13] If (read $19_@4) then:bb8 else:bb9 fallthrough=bb7
55 +bb8:
56 + predecessor blocks: bb6
57 + [14] Reassign mutate x$20_@3[6:17] = read c$11
58 + [15] Goto bb7
59 +bb9:
60 + predecessor blocks: bb6
61 + [16] Reassign mutate x$21_@3[6:17] = read d$12
62 + [17] Goto bb7
63 +bb7:
64 + predecessor blocks: bb8 bb9
65 + x$22_@3[6:17]: phi(bb8: x$20_@3, bb9: x$21_@3)
66 + [18] read x$22_@3
67 + [19] Goto bb1
68 +bb1:
69 + predecessor blocks: bb3 bb7
70 + x$23_@3[6:17]: phi(bb3: x$18_@3, bb7: x$22_@3)
71 + [20] read x$23_@3
72 + [21] Return
73 +scope3 [6:17]:
74 + - read a$9
75 + - read b$10
76 + - read $15_@2
77 + - read c$11
78 + - read d$12
79 +```
80 +
81 +### CFG
82 +
83 +```mermaid
84 +flowchart TB
85 + %% Basic Blocks
86 + subgraph bb0
87 + bb0_instrs["
88 + [1] Let mutate x$13_@0 = 0
89 + [2] Const mutate $14_@1 = true
90 + "]
91 + bb0_instrs --> bb0_terminal(["If (read $14_@1)"])
92 + end
93 + subgraph bb2
94 + bb2_instrs["
95 + [4] Const mutate $15_@2 = true
96 + "]
97 + bb2_instrs --> bb2_terminal(["If (read $15_@2)"])
98 + end
99 + subgraph bb4
100 + bb4_instrs["
101 + [6] Reassign mutate x$16_@3[6:17] = read a$9
102 + "]
103 + bb4_instrs --> bb4_terminal(["Goto"])
104 + end
105 + subgraph bb5
106 + bb5_instrs["
107 + [8] Reassign mutate x$17_@3[6:17] = read b$10
108 + "]
109 + bb5_instrs --> bb5_terminal(["Goto"])
110 + end
111 + subgraph bb3
112 + bb3_instrs["
113 + [10] read x$18_@3
114 + "]
115 + bb3_instrs --> bb3_terminal(["Goto"])
116 + end
117 + subgraph bb6
118 + bb6_instrs["
119 + [12] Const mutate $19_@4 = true
120 + "]
121 + bb6_instrs --> bb6_terminal(["If (read $19_@4)"])
122 + end
123 + subgraph bb8
124 + bb8_instrs["
125 + [14] Reassign mutate x$20_@3[6:17] = read c$11
126 + "]
127 + bb8_instrs --> bb8_terminal(["Goto"])
128 + end
129 + subgraph bb9
130 + bb9_instrs["
131 + [16] Reassign mutate x$21_@3[6:17] = read d$12
132 + "]
133 + bb9_instrs --> bb9_terminal(["Goto"])
134 + end
135 + subgraph bb7
136 + bb7_instrs["
137 + [18] read x$22_@3
138 + "]
139 + bb7_instrs --> bb7_terminal(["Goto"])
140 + end
141 + subgraph bb1
142 + bb1_instrs["
143 + [20] read x$23_@3
144 + "]
145 + bb1_instrs --> bb1_terminal(["Return"])
146 + end
147 +
148 + %% Jumps
149 + bb0_terminal -- "then" --> bb2
150 + bb0_terminal -- "else" --> bb6
151 + bb0_terminal -- "fallthrough" --> bb1
152 + bb2_terminal -- "then" --> bb4
153 + bb2_terminal -- "else" --> bb5
154 + bb2_terminal -- "fallthrough" --> bb3
155 + bb4_terminal --> bb3
156 + bb5_terminal --> bb3
157 + bb3_terminal --> bb1
158 + bb6_terminal -- "then" --> bb8
159 + bb6_terminal -- "else" --> bb9
160 + bb6_terminal -- "fallthrough" --> bb7
161 + bb8_terminal --> bb7
162 + bb9_terminal --> bb7
163 + bb7_terminal --> bb1
164 +
165 +```
166 +
167 +## Code
168 +
169 +```javascript
170 +function foo$0(a$9, b$10, c$11, d$12) {
171 + const x$13 = 0;
172 + let x$18 = undefined;
173 + bb1: if (true) {
174 + bb3: if (true) {
175 + x$18 = a$9;
176 + } else {
177 + x$18 = b$10;
178 + }
179 +
180 + x$18;
181 + } else {
182 + bb7: if (true) {
183 + x$18 = c$11;
184 + } else {
185 + x$18 = d$12;
186 + }
187 +
188 + x$18;
189 + }
190 +
191 + x$18;
192 +}
193 +
194 +```
195 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.js new
+19
@@ -0,0 +1,19 @@
1 +function foo(a, b, c, d) {
2 + let x = 0;
3 + if (true) {
4 + if (true) {
5 + x = a;
6 + } else {
7 + x = b;
8 + }
9 + x;
10 + } else {
11 + if (true) {
12 + x = c;
13 + } else {
14 + x = d;
15 + }
16 + x;
17 + }
18 + x;
19 +}
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-loops-no-reassign.expect.md
+10 -10
@@ -25,19 +25,19 @@ bb0:
25 [2] While test=bb1 loop=bb3 fallthrough=bb2
26 bb1:
27 predecessor blocks: bb0 bb5
28 - [3] If (read a$6) then:bb3 else:bb2
28 + [3] If (read a$6) then:bb3 else:bb2 fallthrough=bb2
29 bb3:
30 predecessor blocks: bb1
31 [4] While test=bb4 loop=bb6 fallthrough=bb5
32 bb4:
33 predecessor blocks: bb3 bb8
34 - [5] If (read b$7) then:bb6 else:bb5
34 + [5] If (read b$7) then:bb6 else:bb5 fallthrough=bb5
35 bb6:
36 predecessor blocks: bb4
37 [6] While test=bb7 loop=bb9 fallthrough=bb8
38 bb7:
39 predecessor blocks: bb6 bb9
40 - [7] If (read c$8) then:bb9 else:bb8
40 + [7] If (read c$8) then:bb9 else:bb8 fallthrough=bb8
41 bb9:
42 predecessor blocks: bb7
43 [8] Const mutate $13_@1 = 1
@@ -124,17 +124,17 @@ flowchart TB
124 ## Code
125
126 ```javascript
127 -function foo$0(a$1, b$2, c$3) {
128 - let x$4 = 0;
129 - bb2: while (a$1) {
130 - bb5: while (b$2) {
131 - bb8: while (c$3) {
132 - x$4 + 1;
127 +function foo$0(a$6, b$7, c$8) {
128 + const x$9 = 0;
129 + bb2: while (a$6) {
130 + bb5: while (b$7) {
131 + bb8: while (c$8) {
132 + x$9 + 1;
133 }
134 }
135 }
136
137 - return x$4;
137 + return x$9;
138 }
139
140 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md new
+105
@@ -0,0 +1,105 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo(a, b, c, d, e) {
6 + let x = null;
7 + if (a) {
8 + x = b;
9 + } else {
10 + if (c) {
11 + x = d;
12 + }
13 + }
14 + return x;
15 +}
16 +
17 +```
18 +
19 +## HIR
20 +
21 +```
22 +bb0:
23 + [1] Let mutate x$12_@0[1:8] = null
24 + [2] If (read a$7) then:bb2 else:bb3 fallthrough=bb1
25 +bb2:
26 + predecessor blocks: bb0
27 + [3] Reassign mutate x$13_@0[1:8] = read b$8
28 + [4] Goto bb1
29 +bb3:
30 + predecessor blocks: bb0
31 + [5] If (read c$9) then:bb5 else:bb1 fallthrough=bb1
32 +bb5:
33 + predecessor blocks: bb3
34 + [6] Reassign mutate x$14_@0[1:8] = read d$10
35 + [7] Goto bb1
36 +bb1:
37 + predecessor blocks: bb2 bb5 bb3
38 + x$15_@0[1:8]: phi(bb2: x$13_@0, bb5: x$14_@0, bb3: x$12_@0)
39 + [8] Return read x$15_@0
40 +scope0 [1:8]:
41 + - read b$8
42 + - read d$10
43 + - read c$9
44 + - read a$7
45 +```
46 +
47 +### CFG
48 +
49 +```mermaid
50 +flowchart TB
51 + %% Basic Blocks
52 + subgraph bb0
53 + bb0_instrs["
54 + [1] Let mutate x$12_@0[1:8] = null
55 + "]
56 + bb0_instrs --> bb0_terminal(["If (read a$7)"])
57 + end
58 + subgraph bb2
59 + bb2_instrs["
60 + [3] Reassign mutate x$13_@0[1:8] = read b$8
61 + "]
62 + bb2_instrs --> bb2_terminal(["Goto"])
63 + end
64 + subgraph bb3
65 + bb3_terminal(["If (read c$9)"])
66 + end
67 + subgraph bb5
68 + bb5_instrs["
69 + [6] Reassign mutate x$14_@0[1:8] = read d$10
70 + "]
71 + bb5_instrs --> bb5_terminal(["Goto"])
72 + end
73 + subgraph bb1
74 + bb1_terminal(["Return read x$15_@0"])
75 + end
76 +
77 + %% Jumps
78 + bb0_terminal -- "then" --> bb2
79 + bb0_terminal -- "else" --> bb3
80 + bb0_terminal -- "fallthrough" --> bb1
81 + bb2_terminal --> bb1
82 + bb3_terminal -- "then" --> bb5
83 + bb3_terminal -- "else" --> bb1
84 + bb5_terminal --> bb1
85 +
86 +```
87 +
88 +## Code
89 +
90 +```javascript
91 +function foo$0(a$7, b$8, c$9, d$10, e$11) {
92 + let x$12 = null;
93 + bb1: if (a$7) {
94 + x$12 = b$8;
95 + } else {
96 + if (c$9) {
97 + x$12 = d$10;
98 + }
99 + }
100 +
101 + return x$12;
102 +}
103 +
104 +```
105 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.js new
+11
@@ -0,0 +1,11 @@
1 +function foo(a, b, c, d, e) {
2 + let x = null;
3 + if (a) {
4 + x = b;
5 + } else {
6 + if (c) {
7 + x = d;
8 + }
9 + }
10 + return x;
11 +}
compiler/forget/src/__tests__/fixtures/hir/ssa-newexpression.expect.md
+5 -5
@@ -72,11 +72,11 @@ flowchart TB
72 ## Code
73
74 ```javascript
75 -function Component$0(props$1) {
76 - const a$2 = [];
77 - const b$3 = {};
78 - let c$4 = new Foo$5(a$2, b$3);
79 - return c$4;
75 +function Component$0(props$6) {
76 + const a$7 = [];
77 + const b$8 = {};
78 + const c$9 = new Foo$5(a$7, b$8);
79 + return c$9;
80 }
81
82 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md
+10 -10
@@ -26,7 +26,7 @@ bb0:
26 [2] Let mutate y$7_@0[1:10] = 2
27 [3] Const mutate $8_@2 = 1
28 [4] Const mutate $9_@3 = Binary read x$6_@0 > read $8_@2
29 - [5] If (read $9_@3) then:bb2 else:bb3
29 + [5] If (read $9_@3) then:bb2 else:bb3 fallthrough=bb1
30 bb2:
31 predecessor blocks: bb0
32 [6] Reassign mutate x$10_@0[1:10] = 2
@@ -91,19 +91,19 @@ flowchart TB
91
92 ```javascript
93 function foo$0() {
94 - let x$1 = 1;
95 - let y$2 = 2;
96 - bb1: if (x$1 > 1) {
97 - x$1 = 2;
94 + let x$6 = 1;
95 + let y$7 = 2;
96 + bb1: if (x$6 > 1) {
97 + x$6 = 2;
98 } else {
99 - y$2 = 3;
99 + y$7 = 3;
100 }
101
102 - let t$5 = {
103 - x: x$1,
104 - y: y$2,
102 + const t$14 = {
103 + x: x$6,
104 + y: y$7,
105 };
106 - return t$5;
106 + return t$14;
107 }
108
109 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression.expect.md
+7 -7
@@ -45,14 +45,14 @@ flowchart TB
45 ## Code
46
47 ```javascript
48 -function Component$0(props$1) {
49 - const a$2 = 1;
50 - const b$3 = 2;
51 - const x$4 = {
52 - a: a$2,
53 - b: b$3,
48 +function Component$0(props$5) {
49 + const a$6 = 1;
50 + const b$7 = 2;
51 + const x$8 = {
52 + a: a$6,
53 + b: b$7,
54 };
55 - return x$4;
55 + return x$8;
56 }
57
58 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-property-call.expect.md
+5 -5
@@ -47,12 +47,12 @@ flowchart TB
47
48 ```javascript
49 function foo$0() {
50 - const x$1 = [];
51 - const y$2 = {
52 - x: x$1,
50 + const x$4 = [];
51 + const y$5 = {
52 + x: x$4,
53 };
54 - y$2.x.push([]);
55 - return y$2;
54 + y$5.x.push([]);
55 + return y$5;
56 }
57
58 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md
+4 -4
@@ -44,10 +44,10 @@ flowchart TB
44
45 ```javascript
46 function foo$0() {
47 - const x$1 = [];
48 - const y$2 = {};
49 - y$2.x = x$1;
50 - return y$2;
47 + const x$3 = [];
48 + const y$4 = {};
49 + y$4.x = x$3;
50 + return y$4;
51 }
52
53 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-reassign.expect.md new
+63
@@ -0,0 +1,63 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo(a, b, c) {
6 + let x = 0;
7 + x = a;
8 + x = b;
9 + x = c;
10 + return x;
11 +}
12 +
13 +```
14 +
15 +## HIR
16 +
17 +```
18 +bb0:
19 + [1] Let mutate x$8_@0 = 0
20 + [2] Reassign mutate x$9_@1 = read a$5
21 + [3] Reassign mutate x$10_@2 = read b$6
22 + [4] Reassign mutate x$11_@3 = read c$7
23 + [5] Return read x$11_@3
24 +scope1 [2:3]:
25 + - read a$5
26 +scope2 [3:4]:
27 + - read b$6
28 +scope3 [4:5]:
29 + - read c$7
30 +```
31 +
32 +### CFG
33 +
34 +```mermaid
35 +flowchart TB
36 + %% Basic Blocks
37 + subgraph bb0
38 + bb0_instrs["
39 + [1] Let mutate x$8_@0 = 0
40 + [2] Reassign mutate x$9_@1 = read a$5
41 + [3] Reassign mutate x$10_@2 = read b$6
42 + [4] Reassign mutate x$11_@3 = read c$7
43 + "]
44 + bb0_instrs --> bb0_terminal(["Return read x$11_@3"])
45 + end
46 +
47 + %% Jumps
48 + %% empty
49 +```
50 +
51 +## Code
52 +
53 +```javascript
54 +function foo$0(a$5, b$6, c$7) {
55 + const x$8 = 0;
56 + const x$9 = a$5;
57 + const x$10 = b$6;
58 + const x$11 = c$7;
59 + return x$11;
60 +}
61 +
62 +```
63 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/ssa-reassign.js new
+7
@@ -0,0 +1,7 @@
1 +function foo(a, b, c) {
2 + let x = 0;
3 + x = a;
4 + x = b;
5 + x = c;
6 + return x;
7 +}
compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md
+5 -5
@@ -20,7 +20,7 @@ bb0:
20 [1] Let mutate x$4_@0[1:7] = 1
21 [2] Const mutate $5_@1 = 1
22 [3] Const mutate $6_@2 = Binary read x$4_@0 === read $5_@1
23 - [4] If (read $6_@2) then:bb2 else:bb1
23 + [4] If (read $6_@2) then:bb2 else:bb1 fallthrough=bb1
24 bb2:
25 predecessor blocks: bb0
26 [5] Reassign mutate x$7_@0[1:7] = 2
@@ -67,12 +67,12 @@ flowchart TB
67
68 ```javascript
69 function foo$0() {
70 - let x$1 = 1;
71 - bb1: if (x$1 === 1) {
72 - x$1 = 2;
70 + let x$4 = 1;
71 + bb1: if (x$4 === 1) {
72 + x$4 = 2;
73 }
74
75 - return x$1;
75 + return x$4;
76 }
77
78 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md
+8 -8
@@ -49,7 +49,7 @@ function log$0() {}
49 ```
50 bb0:
51 [1] Let mutate str$6_@0[1:8] = ""
52 - [2] If (read cond$5) then:bb2 else:bb3
52 + [2] If (read cond$5) then:bb2 else:bb3 fallthrough=bb1
53 bb2:
54 predecessor blocks: bb0
55 [3] Let mutate str$7_@1 = "other test"
@@ -110,16 +110,16 @@ flowchart TB
110 ## Code
111
112 ```javascript
113 -function Foo$0(cond$1) {
114 - let str$2 = "";
115 - bb1: if (cond$1) {
116 - let str$3 = "other test";
117 - log$4(str$3);
113 +function Foo$0(cond$5) {
114 + let str$6 = "";
115 + bb1: if (cond$5) {
116 + const str$7 = "other test";
117 + log$4(str$7);
118 } else {
119 - str$2 = "fallthrough test";
119 + str$6 = "fallthrough test";
120 }
121
122 - log$4(str$2);
122 + log$4(str$6);
123 }
124
125 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-sibling-phis.expect.md new
+191
@@ -0,0 +1,191 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo(a, b, c, d) {
6 + let x = 0;
7 + if (true) {
8 + if (true) {
9 + x = a;
10 + } else {
11 + x = b;
12 + }
13 + x;
14 + } else {
15 + if (true) {
16 + x = c;
17 + } else {
18 + x = d;
19 + }
20 + x;
21 + }
22 + // note: intentionally no phi here so that there are two distinct phis above
23 +}
24 +
25 +```
26 +
27 +## HIR
28 +
29 +```
30 +bb0:
31 + [1] Let mutate x$13_@0 = 0
32 + [2] Const mutate $14_@1 = true
33 + [3] If (read $14_@1) then:bb2 else:bb6 fallthrough=bb1
34 +bb2:
35 + predecessor blocks: bb0
36 + [4] Const mutate $15_@2 = true
37 + [5] If (read $15_@2) then:bb4 else:bb5 fallthrough=bb3
38 +bb4:
39 + predecessor blocks: bb2
40 + [6] Reassign mutate x$16_@3[6:9] = read a$9
41 + [7] Goto bb3
42 +bb5:
43 + predecessor blocks: bb2
44 + [8] Reassign mutate x$17_@3[6:9] = read b$10
45 + [9] Goto bb3
46 +bb3:
47 + predecessor blocks: bb4 bb5
48 + x$18_@3[6:9]: phi(bb4: x$16_@3, bb5: x$17_@3)
49 + [10] read x$18_@3
50 + [11] Goto bb1
51 +bb6:
52 + predecessor blocks: bb0
53 + [12] Const mutate $19_@4 = true
54 + [13] If (read $19_@4) then:bb8 else:bb9 fallthrough=bb7
55 +bb8:
56 + predecessor blocks: bb6
57 + [14] Reassign mutate x$20_@5[14:17] = read c$11
58 + [15] Goto bb7
59 +bb9:
60 + predecessor blocks: bb6
61 + [16] Reassign mutate x$21_@5[14:17] = read d$12
62 + [17] Goto bb7
63 +bb7:
64 + predecessor blocks: bb8 bb9
65 + x$22_@5[14:17]: phi(bb8: x$20_@5, bb9: x$21_@5)
66 + [18] read x$22_@5
67 + [19] Goto bb1
68 +bb1:
69 + predecessor blocks: bb3 bb7
70 + [20] Return
71 +scope3 [6:9]:
72 + - read a$9
73 + - read b$10
74 +scope5 [14:17]:
75 + - read c$11
76 + - read d$12
77 +```
78 +
79 +### CFG
80 +
81 +```mermaid
82 +flowchart TB
83 + %% Basic Blocks
84 + subgraph bb0
85 + bb0_instrs["
86 + [1] Let mutate x$13_@0 = 0
87 + [2] Const mutate $14_@1 = true
88 + "]
89 + bb0_instrs --> bb0_terminal(["If (read $14_@1)"])
90 + end
91 + subgraph bb2
92 + bb2_instrs["
93 + [4] Const mutate $15_@2 = true
94 + "]
95 + bb2_instrs --> bb2_terminal(["If (read $15_@2)"])
96 + end
97 + subgraph bb4
98 + bb4_instrs["
99 + [6] Reassign mutate x$16_@3[6:9] = read a$9
100 + "]
101 + bb4_instrs --> bb4_terminal(["Goto"])
102 + end
103 + subgraph bb5
104 + bb5_instrs["
105 + [8] Reassign mutate x$17_@3[6:9] = read b$10
106 + "]
107 + bb5_instrs --> bb5_terminal(["Goto"])
108 + end
109 + subgraph bb3
110 + bb3_instrs["
111 + [10] read x$18_@3
112 + "]
113 + bb3_instrs --> bb3_terminal(["Goto"])
114 + end
115 + subgraph bb6
116 + bb6_instrs["
117 + [12] Const mutate $19_@4 = true
118 + "]
119 + bb6_instrs --> bb6_terminal(["If (read $19_@4)"])
120 + end
121 + subgraph bb8
122 + bb8_instrs["
123 + [14] Reassign mutate x$20_@5[14:17] = read c$11
124 + "]
125 + bb8_instrs --> bb8_terminal(["Goto"])
126 + end
127 + subgraph bb9
128 + bb9_instrs["
129 + [16] Reassign mutate x$21_@5[14:17] = read d$12
130 + "]
131 + bb9_instrs --> bb9_terminal(["Goto"])
132 + end
133 + subgraph bb7
134 + bb7_instrs["
135 + [18] read x$22_@5
136 + "]
137 + bb7_instrs --> bb7_terminal(["Goto"])
138 + end
139 + subgraph bb1
140 + bb1_terminal(["Return"])
141 + end
142 +
143 + %% Jumps
144 + bb0_terminal -- "then" --> bb2
145 + bb0_terminal -- "else" --> bb6
146 + bb0_terminal -- "fallthrough" --> bb1
147 + bb2_terminal -- "then" --> bb4
148 + bb2_terminal -- "else" --> bb5
149 + bb2_terminal -- "fallthrough" --> bb3
150 + bb4_terminal --> bb3
151 + bb5_terminal --> bb3
152 + bb3_terminal --> bb1
153 + bb6_terminal -- "then" --> bb8
154 + bb6_terminal -- "else" --> bb9
155 + bb6_terminal -- "fallthrough" --> bb7
156 + bb8_terminal --> bb7
157 + bb9_terminal --> bb7
158 + bb7_terminal --> bb1
159 +
160 +```
161 +
162 +## Code
163 +
164 +```javascript
165 +function foo$0(a$9, b$10, c$11, d$12) {
166 + const x$13 = 0;
167 + bb1: if (true) {
168 + let x$16 = undefined;
169 +
170 + bb3: if (true) {
171 + x$16 = a$9;
172 + } else {
173 + x$16 = b$10;
174 + }
175 +
176 + x$16;
177 + } else {
178 + let x$20 = undefined;
179 +
180 + bb7: if (true) {
181 + x$20 = c$11;
182 + } else {
183 + x$20 = d$12;
184 + }
185 +
186 + x$20;
187 + }
188 +}
189 +
190 +```
191 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/ssa-sibling-phis.js new
+19
@@ -0,0 +1,19 @@
1 +function foo(a, b, c, d) {
2 + let x = 0;
3 + if (true) {
4 + if (true) {
5 + x = a;
6 + } else {
7 + x = b;
8 + }
9 + x;
10 + } else {
11 + if (true) {
12 + x = c;
13 + } else {
14 + x = d;
15 + }
16 + x;
17 + }
18 + // note: intentionally no phi here so that there are two distinct phis above
19 +}
compiler/forget/src/__tests__/fixtures/hir/ssa-simple-phi.expect.md
+7 -6
@@ -23,7 +23,7 @@ bb0:
23 [1] Let mutate y$5_@0 = 2
24 [2] Const mutate $6_@1 = 1
25 [3] Const mutate $7_@2 = Binary read y$5_@0 > read $6_@1
26 - [4] If (read $7_@2) then:bb2 else:bb3
26 + [4] If (read $7_@2) then:bb2 else:bb3 fallthrough=bb1
27 bb2:
28 predecessor blocks: bb0
29 [5] Reassign mutate y$8_@3[5:10] = 1
@@ -89,14 +89,15 @@ flowchart TB
89
90 ```javascript
91 function foo$0() {
92 - let y$1 = 2;
93 - bb1: if (y$1 > 1) {
94 - y$1 = 1;
92 + const y$5 = 2;
93 + let y$8 = undefined;
94 + bb1: if (y$5 > 1) {
95 + y$8 = 1;
96 } else {
96 - y$1 = 2;
97 + y$8 = 2;
98 }
99
99 - let x$4 = y$1;
100 + const x$11 = y$8;
101 }
102
103 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-simple.expect.md
+2 -2
@@ -40,8 +40,8 @@ flowchart TB
40
41 ```javascript
42 function foo$0() {
43 - let x$1 = 1;
44 - let y$2 = 2;
43 + const x$3 = 1;
44 + const y$4 = 2;
45 }
46
47 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-single-if.expect.md
+5 -5
@@ -19,7 +19,7 @@ function foo() {
19 bb0:
20 [1] Let mutate x$4_@0 = 1
21 [2] Let mutate y$5_@1 = 2
22 - [3] If (read y$5_@1) then:bb2 else:bb1
22 + [3] If (read y$5_@1) then:bb2 else:bb1 fallthrough=bb1
23 bb2:
24 predecessor blocks: bb0
25 [4] Let mutate z$6_@2 = Binary read x$4_@0 + read y$5_@1
@@ -65,10 +65,10 @@ flowchart TB
65
66 ```javascript
67 function foo$0() {
68 - let x$1 = 1;
69 - let y$2 = 2;
70 - bb1: if (y$2) {
71 - let z$3 = x$1 + y$2;
68 + const x$4 = 1;
69 + const y$5 = 2;
70 + bb1: if (y$5) {
71 + const z$6 = x$4 + y$5;
72 }
73 }
74
compiler/forget/src/__tests__/fixtures/hir/ssa-switch.expect.md
+10 -8
@@ -37,6 +37,7 @@ bb0:
37 Case read $14_@4: bb5
38 Case read $12_@2: bb3
39 Default: bb2
40 + Fallthrough: bb1
41 bb5:
42 predecessor blocks: bb0
43 [7] Const mutate $15_@5 = 1
@@ -130,24 +131,25 @@ flowchart TB
131
132 ```javascript
133 function foo$0() {
133 - let x$1 = 1;
134 - bb1: switch (x$1) {
135 - case x$1 === 1: {
136 - x$1 = x$1 + 1;
134 + const x$10 = 1;
135 + let x$16 = undefined;
136 + bb1: switch (x$10) {
137 + case x$10 === 1: {
138 + x$16 = x$10 + 1;
139 break bb1;
140 }
141
140 - case x$1 === 2: {
141 - x$1 = x$1 + 2;
142 + case x$10 === 2: {
143 + x$16 = x$10 + 2;
144 break bb1;
145 }
146
147 default: {
146 - x$1 = x$1 + 3;
148 + x$16 = x$10 + 3;
149 }
150 }
151
150 - let y$9 = x$1;
152 + const y$22 = x$16;
153 }
154
155 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md
+5 -5
@@ -19,7 +19,7 @@ bb0:
19 [1] Let mutate x$4_@0[1:7] = 1
20 [2] Const mutate $5_@1 = 1
21 [3] Const mutate $6_@2 = Binary read x$4_@0 === read $5_@1
22 - [4] If (read $6_@2) then:bb2 else:bb1
22 + [4] If (read $6_@2) then:bb2 else:bb1 fallthrough=bb1
23 bb2:
24 predecessor blocks: bb0
25 [5] Reassign mutate x$7_@0[1:7] = 2
@@ -66,12 +66,12 @@ flowchart TB
66
67 ```javascript
68 function foo$0() {
69 - let x$1 = 1;
70 - bb1: if (x$1 === 1) {
71 - x$1 = 2;
69 + let x$4 = 1;
70 + bb1: if (x$4 === 1) {
71 + x$4 = 2;
72 }
73
74 - throw x$1;
74 + throw x$4;
75 }
76
77 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-while-no-reassign.expect.md
+5 -5
@@ -23,7 +23,7 @@ bb1:
23 predecessor blocks: bb0 bb3
24 [3] Const mutate $6_@1 = 10
25 [4] Const mutate $8_@2[4:6] = Binary read x$5_@0 < read $6_@1
26 - [5] If (read $8_@2) then:bb3 else:bb2
26 + [5] If (read $8_@2) then:bb3 else:bb2 fallthrough=bb2
27 bb3:
28 predecessor blocks: bb1
29 [6] Const mutate $9_@3 = 1
@@ -82,12 +82,12 @@ flowchart TB
82
83 ```javascript
84 function foo$0() {
85 - let x$1 = 1;
86 - bb2: while (x$1 < 10) {
87 - x$1 + 1;
85 + const x$5 = 1;
86 + bb2: while (x$5 < 10) {
87 + x$5 + 1;
88 }
89
90 - return x$1;
90 + return x$5;
91 }
92
93 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-while.expect.md
+5 -5
@@ -24,7 +24,7 @@ bb1:
24 x$7_@0[0:9]: phi(bb0: x$5_@0, bb3: x$10_@0)
25 [3] Const mutate $6_@1 = 10
26 [4] Const mutate $8_@2[4:6] = Binary read x$7_@0 < read $6_@1
27 - [5] If (read $8_@2) then:bb3 else:bb2
27 + [5] If (read $8_@2) then:bb3 else:bb2 fallthrough=bb2
28 bb3:
29 predecessor blocks: bb1
30 [6] Const mutate $9_@3 = 1
@@ -80,12 +80,12 @@ flowchart TB
80
81 ```javascript
82 function foo$0() {
83 - let x$1 = 1;
84 - bb2: while (x$1 < 10) {
85 - x$1 = x$1 + 1;
83 + let x$5 = 1;
84 + bb2: while (x$5 < 10) {
85 + x$5 = x$5 + 1;
86 }
87
88 - return x$1;
88 + return x$5;
89 }
90
91 ```
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+11 -10
@@ -42,6 +42,7 @@ bb0:
42 Case read $13_@2: bb6
43 Default: bb1
44 Case read $12_@1: bb2
45 + Fallthrough: bb1
46 bb6:
47 predecessor blocks: bb0
48 [7] Call mutate x$10_@0.push(read props$9.p2)
@@ -121,17 +122,17 @@ flowchart TB
122 ## Code
123
124 ```javascript
124 -function Component$0(props$1) {
125 - let x$2 = [];
126 - let y$3 = undefined;
127 - bb1: switch (props$1.p0) {
125 +function Component$0(props$9) {
126 + const x$10 = [];
127 + let y$11 = undefined;
128 + bb1: switch (props$9.p0) {
129 case 1: {
130 break bb1;
131 }
132
133 case true: {
133 - x$2.push(props$1.p2);
134 - y$3 = [];
134 + x$10.push(props$9.p2);
135 + y$11 = [];
136 break bb1;
137 }
138
@@ -140,13 +141,13 @@ function Component$0(props$1) {
141 }
142
143 case false: {
143 - y$3 = x$2;
144 + y$11 = x$10;
145 }
146 }
147
147 - const child$7 = <Component$0 data={x$2}></Component$0>;
148 - y$3.push(props$1.p4);
149 - return <Component$0 data={y$3}>{child$7}</Component$0>;
148 + const child$19 = <Component$0 data={x$10}></Component$0>;
149 + y$11.push(props$9.p4);
150 + return <Component$0 data={y$11}>{child$19}</Component$0>;
151 }
152
153 ```
compiler/forget/src/__tests__/fixtures/hir/switch-with-fallthrough.expect.md
+10 -9
@@ -51,6 +51,7 @@ bb0:
51 Case read $12_@2: bb4
52 Case read $11_@1: bb3
53 Default: bb2
54 + Fallthrough: bb1
55 bb10:
56 predecessor blocks: bb0
57 [9] Reassign mutate y$17_@7 = 0
@@ -159,15 +160,15 @@ flowchart TB
160 ## Code
161
162 ```javascript
162 -function foo$0(x$1) {
163 - let y$2 = undefined;
164 - bb1: switch (x$1) {
163 +function foo$0(x$9) {
164 + const y$10 = undefined;
165 + bb1: switch (x$9) {
166 case 0: {
166 - y$2 = 0;
167 + const y$17 = 0;
168 }
169
170 case 1: {
170 - y$2 = 1;
171 + const y$18 = 1;
172 break bb1;
173 }
174
@@ -176,20 +177,20 @@ function foo$0(x$1) {
177 }
178
179 case 3: {
179 - y$2 = 3;
180 + const y$19 = 3;
181 break bb1;
182 }
183
184 case 4: {
184 - y$2 = 4;
185 + const y$20 = 4;
186 }
187
188 case 5: {
188 - y$2 = 5;
189 + const y$21 = 5;
190 }
191
192 default: {
192 - y$2 = 0;
193 + const y$22 = 0;
194 }
195 }
196 }
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+12 -11
@@ -36,6 +36,7 @@ bb0:
36 Case read $12_@2: bb4
37 Case read $11_@1: bb2
38 Default: bb1
39 + Fallthrough: bb1
40 bb4:
41 predecessor blocks: bb0
42 [6] Call mutate x$9_@0.push(read props$8.p2)
@@ -116,24 +117,24 @@ flowchart TB
117 ## Code
118
119 ```javascript
119 -function Component$0(props$1) {
120 - let x$2 = [];
121 - let y$3 = undefined;
122 - bb1: switch (props$1.p0) {
120 +function Component$0(props$8) {
121 + const x$9 = [];
122 + let y$10 = undefined;
123 + bb1: switch (props$8.p0) {
124 case true: {
124 - x$2.push(props$1.p2);
125 - x$2.push(props$1.p3);
126 - y$3 = [];
125 + x$9.push(props$8.p2);
126 + x$9.push(props$8.p3);
127 + const y$13 = [];
128 }
129
130 case false: {
130 - y$3 = x$2;
131 + y$10 = x$9;
132 }
133 }
134
134 - const child$6 = <Component$0 data={x$2}></Component$0>;
135 - y$3.push(props$1.p4);
136 - return <Component$0 data={y$3}>{child$6}</Component$0>;
135 + const child$19 = <Component$0 data={x$9}></Component$0>;
136 + y$10.push(props$8.p4);
137 + return <Component$0 data={y$10}>{child$19}</Component$0>;
138 }
139
140 ```
compiler/forget/src/__tests__/fixtures/hir/while-break.expect.md
+4 -4
@@ -18,7 +18,7 @@ bb0:
18 [1] While test=bb1 loop=bb2 fallthrough=bb2
19 bb1:
20 predecessor blocks: bb0
21 - [2] If (read a$3) then:bb2 else:bb2
21 + [2] If (read a$3) then:bb2 else:bb2 fallthrough=bb2
22 bb2:
23 predecessor blocks: bb1
24 [3] Return read b$4
@@ -52,11 +52,11 @@ flowchart TB
52 ## Code
53
54 ```javascript
55 -function foo$0(a$1, b$2) {
56 - bb2: while (a$1) {
55 +function foo$0(a$3, b$4) {
56 + bb2: while (a$3) {
57 break;
58 }
59 - return b$2;
59 + return b$4;
60 }
61
62 ```
compiler/forget/src/__tests__/fixtures/hir/while-conditional-continue.expect.md
+7 -7
@@ -22,10 +22,10 @@ bb0:
22 [1] While test=bb1 loop=bb3 fallthrough=bb2
23 bb1:
24 predecessor blocks: bb0 bb5 bb4
25 - [2] If (read a$5) then:bb3 else:bb2
25 + [2] If (read a$5) then:bb3 else:bb2 fallthrough=bb2
26 bb3:
27 predecessor blocks: bb1
28 - [3] If (read b$6) then:bb5 else:bb4
28 + [3] If (read b$6) then:bb5 else:bb4 fallthrough=bb4
29 bb5:
30 predecessor blocks: bb3
31 [4] Goto(Continue) bb1
@@ -86,15 +86,15 @@ flowchart TB
86 ## Code
87
88 ```javascript
89 -function foo$0(a$1, b$2, c$3, d$4) {
90 - bb2: while (a$1) {
91 - bb4: if (b$2) {
89 +function foo$0(a$5, b$6, c$7, d$8) {
90 + bb2: while (a$5) {
91 + bb4: if (b$6) {
92 continue;
93 }
94 - c$3();
94 + c$7();
95 }
96
97 - d$4();
97 + d$8();
98 }
99
100 ```
compiler/forget/src/__tests__/hir-test.ts
+103 -65
@@ -48,61 +48,58 @@ describe("React Forget (HIR version)", () => {
48 }
49 }
50
51 - const ast = parser.parse(input, {
52 - sourceFilename: file,
53 - plugins: ["typescript", "jsx"],
54 - });
55 - let items: Array<[string, string, string]> = [];
56 - traverse(ast, {
57 - FunctionDeclaration: {
58 - enter(nodePath) {
59 - const { ir } = run(nodePath, {
60 - eliminateRedundantPhi: true,
61 - inferReferenceEffects: true,
62 - inferMutableRanges: true,
63 - inferReactiveScopeVariables: true,
64 - inferReactiveScopes: true,
65 - inferReactiveScopeDependencies: true,
66 - leaveSSA: false,
67 - codegen: false,
68 - });
69 -
70 - // Print the HIR before leaving SSA.
71 - const textHIR = printFunction(ir);
72 - const visualization = visualizeHIRMermaid(ir);
73 -
74 - const { ast } = run(nodePath, {
75 - eliminateRedundantPhi: true,
76 - inferReferenceEffects: true,
77 - inferMutableRanges: true,
78 - inferReactiveScopeVariables: true,
79 - inferReactiveScopes: true,
80 - inferReactiveScopeDependencies: true,
81 - leaveSSA: true,
82 - codegen: true,
83 - });
84 -
85 - invariant(
86 - ast !== null,
87 - "ast is null when codegen option is enabled"
88 - );
89 - const text = prettier.format(
90 - generate(ast).code.replace("\n\n", "\n"),
91 - {
92 - semi: true,
93 - parser: "babel-ts",
94 - }
95 - );
96 - items.push([textHIR, text, visualization]);
97 - },
98 - },
99 - });
100 - invariant(
101 - items.length > 0,
102 - "Visitor failed, check that the input has a function"
103 - );
104 - const outputs = items.map(([hir, text, visualization]) => {
105 - return `
51 + let items: Array<[string, string, string]> | null = null;
52 + let error: Error | null = null;
53 + try {
54 + items = transform(input, file);
55 + } catch (e) {
56 + error = e;
57 + }
58 + let outputs: Array<string>;
59 +
60 + const expectError = file.startsWith("error.");
61 + if (expectError) {
62 + if (error === null) {
63 + throw new Error(
64 + `Expected an error to be thrown for fixture: '${file}', remove the 'error.' prefix if an error is not expected.`
65 + );
66 + } else {
67 + outputs = [formatErrorOutput(error)];
68 + }
69 + } else {
70 + if (error !== null) {
71 + console.error(error);
72 + throw new Error(
73 + `Expected fixture '${file}' to succeed but it failed with error: '${error.message}'. See console output for details.`
74 + );
75 + }
76 + if (items === null || items.length === 0) {
77 + throw new Error(`Expected at least one output for file '${file}'.`);
78 + }
79 + outputs = formatOutput(items);
80 + }
81 + return `
82 +## Input
83 +
84 +${wrapWithTripleBackticks(input, "javascript")}
85 +
86 +${outputs.join("\n")}
87 + `;
88 + }
89 + );
90 +});
91 +
92 +function formatErrorOutput(error: Error): string {
93 + return `
94 +## Error
95 +
96 +${wrapWithTripleBackticks(error.message)}
97 + `;
98 +}
99 +
100 +function formatOutput(items: Array<[string, string, string]>): Array<string> {
101 + return items.map(([hir, text, visualization]) => {
102 + return `
103 ## HIR
104
105 ${wrapWithTripleBackticks(hir)}
@@ -115,14 +112,55 @@ ${wrapWithTripleBackticks(visualization, "mermaid")}
112
113 ${wrapWithTripleBackticks(text, "javascript")}
114 `.trim();
118 - });
119 - return `
120 -## Input
121 -
122 -${wrapWithTripleBackticks(input, "javascript")}
115 + });
116 +}
117
124 -${outputs.join("\n")}
125 - `;
126 - }
127 - );
128 -});
118 +function transform(
119 + text: string,
120 + file: string
121 +): Array<[string, string, string]> {
122 + const items: Array<[string, string, string]> = [];
123 + const ast = parser.parse(text, {
124 + sourceFilename: file,
125 + plugins: ["typescript", "jsx"],
126 + });
127 + traverse(ast, {
128 + FunctionDeclaration: {
129 + enter(nodePath) {
130 + const { ir } = run(nodePath, {
131 + eliminateRedundantPhi: true,
132 + inferReferenceEffects: true,
133 + inferMutableRanges: true,
134 + inferReactiveScopeVariables: true,
135 + inferReactiveScopes: true,
136 + inferReactiveScopeDependencies: true,
137 + leaveSSA: false,
138 + codegen: false,
139 + });
140 +
141 + // Print the HIR before leaving SSA.
142 + const textHIR = printFunction(ir);
143 + const visualization = visualizeHIRMermaid(ir);
144 +
145 + const { ast } = run(nodePath, {
146 + eliminateRedundantPhi: true,
147 + inferReferenceEffects: true,
148 + inferMutableRanges: true,
149 + inferReactiveScopeVariables: true,
150 + inferReactiveScopes: true,
151 + inferReactiveScopeDependencies: true,
152 + leaveSSA: true,
153 + codegen: true,
154 + });
155 +
156 + invariant(ast !== null, "ast is null when codegen option is enabled");
157 + const text = prettier.format(generate(ast).code.replace("\n\n", "\n"), {
158 + semi: true,
159 + parser: "babel-ts",
160 + });
161 + items.push([textHIR, text, visualization]);
162 + },
163 + },
164 + });
165 + return items;
166 +}
compiler/forget/src/index.ts
+1 -1
@@ -34,7 +34,7 @@ import { inferReactiveScopeDependencies } from "./HIR/InferReactiveScopeDependen
34 import { inferReactiveScopes } from "./HIR/InferReactiveScopes";
35 import { inferReactiveScopeVariables } from "./HIR/InferReactiveScopeVariables";
36 import inferReferenceEffects from "./HIR/InferReferenceEffects";
37 -import leaveSSA from "./HIR/LeaveSSA";
37 +import { leaveSSA } from "./HIR/LeaveSSA";
38 import printHIR from "./HIR/PrintHIR";
39
40 function parseFunctions(