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.
This commit is contained in:
Joseph Savona
2022-12-08 07:35:14 -08:00
parent 4837e21de3
commit 21652a135b
90 changed files with 1589 additions and 778 deletions
-1
View File
@@ -51,7 +51,6 @@ class SSABuilder {
makeId(oldId: Identifier): Identifier {
return {
id: this.nextSsaId,
preSsaId: oldId.id,
name: oldId.name,
mutableRange: {
start: makeInstructionId(0),
-2
View File
@@ -298,8 +298,6 @@ export type MutableRange = {
* Represents a user-defined variable (has a name) or a temporary variable (no name).
*/
export type Identifier = {
// the original `id` value prior to entering SSA form
preSsaId: IdentifierId | null;
// unique value to distinguish a variable, since name is not guaranteed to exist or be unique
id: IdentifierId;
// null for temporaries. name is primarily used for debugging.
-2
View File
@@ -111,7 +111,6 @@ export default class HIRBuilder {
makeTemporary(): Identifier {
const id = this.nextIdentifierId;
return {
preSsaId: null,
id,
name: null,
mutableRange: { start: makeInstructionId(0), end: makeInstructionId(0) },
@@ -124,7 +123,6 @@ export default class HIRBuilder {
if (identifier == null) {
const id = this.nextIdentifierId;
identifier = {
preSsaId: null,
id,
name: node.name,
mutableRange: {
+145 -16
View File
@@ -1,24 +1,153 @@
import { HIRFunction } from "./HIR";
import { eachBlockOperand } from "./visitors";
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {
Effect,
GeneratedSource,
HIRFunction,
Identifier,
Instruction,
InstructionKind,
Phi,
} from "./HIR";
import { eachInstructionValueOperand, eachTerminalOperand } from "./visitors";
/**
* Removes SSA form by restoring each `Identifier.id` value to its pre-SSA value,
* and removing all phi nodes.
* Removes SSA form by creating unique variable declarations for the versions of each variables.
* - Versions of a variable that do not flow into a phi node are each assigned their own const variable
* declaration.
* - If multiple versions of a variable flow into some phi node, then all those versions are reassigned to
* the phi version. A single declaration is created at the same block scope as the phi, prior to any of the
* assignments.
*/
export default function leaveSSA(fn: HIRFunction) {
const ir = fn.body;
export function leaveSSA(fn: HIRFunction) {
// Maps identifiers that appear as a phi or phi operand to a single canonical identifier
// for all instances.
const variableMapping: Map<Identifier, Identifier> = new Map();
for (const param of fn.params) {
param.identifier.id = param.identifier.preSsaId ?? param.identifier.id;
}
for (const [, block] of fn.body.blocks) {
// Identifiers (from phis) that *may* need a new `let` declaration created. If the original
// variable declaration flows into the phi, then we can reuse its declaration - this is
// discovered during iteration of instructions.
const needsDeclaration: Set<Identifier> = new Set();
// Find any phi nodes which need a variable declaration in the current block
// This includes phis in fallthrough nodes, or blocks that form part of control flow
// such as for or while (and later if/switch).
const phis: Array<Phi> = [];
const terminal = block.terminal;
if (
(terminal.kind === "if" ||
terminal.kind === "switch" ||
terminal.kind === "while" ||
terminal.kind === "for") &&
terminal.fallthrough !== null
) {
const fallthrough = fn.body.blocks.get(terminal.fallthrough)!;
phis.push(...fallthrough.phis);
}
if (terminal.kind === "while" || terminal.kind === "for") {
const test = fn.body.blocks.get(terminal.test)!;
phis.push(...test.phis);
const loop = fn.body.blocks.get(terminal.loop)!;
phis.push(...loop.phis);
}
if (terminal.kind === "for") {
const update = fn.body.blocks.get(terminal.update)!;
phis.push(...update.phis);
}
// For each phi, determine a canonical identifier to use for versions of the variable
// that appear in the phi (as its output id and operands). If this is the first time
// we're seeing the phi id, then we may need to generate a new variable declaration
// Note that there can be multiple phi nodes for the same variable, we capture the
// outermost scope by visiting predecessor blocks first.
for (const phi of phis) {
let canonicalId = variableMapping.get(phi.id);
if (canonicalId === undefined) {
// Determine a new canonical id. We use the id/operand whose id is lowest,
// which ensures that _if_ the original variable declaration is one of the
// options we'll choose it and can reuse the declaration.
canonicalId = phi.id;
for (const [, operand] of phi.operands) {
if (operand.id < canonicalId.id) {
canonicalId = operand;
}
}
variableMapping.set(phi.id, canonicalId);
needsDeclaration.add(canonicalId);
}
// all versions of the variable need to be remapped to the canonical id
for (const [, operand] of phi.operands) {
variableMapping.set(operand, canonicalId);
}
}
// Visit instructions and rewrite identifiers based on the variable mapping
// updated above.
for (const instr of block.instructions) {
const { lvalue, value } = instr;
if (lvalue !== null) {
lvalue.place.identifier =
variableMapping.get(lvalue.place.identifier) ??
lvalue.place.identifier;
if (lvalue.place.memberPath === null) {
if (!variableMapping.has(lvalue.place.identifier)) {
// This variable does not flow into a phi, therefore there
// is no reassignment. Convert the declaration to a const.
lvalue.kind = InstructionKind.Const;
} else if (
variableMapping.get(lvalue.place.identifier) ===
lvalue.place.identifier
) {
// This is an existing declaration we can reuse as the canonical declaration for its
// phi. Note, the declaration must already be a `let` or else it would be invalid to
// reassign the variable in the first place.
needsDeclaration.delete(lvalue.place.identifier);
}
}
}
for (const operand of eachInstructionValueOperand(value)) {
operand.identifier =
variableMapping.get(operand.identifier) ?? operand.identifier;
}
}
for (const operand of eachTerminalOperand(terminal)) {
operand.identifier =
variableMapping.get(operand.identifier) ?? operand.identifier;
}
// Generate new let declarations for any remaining phi variables
for (const identifier of needsDeclaration) {
const instr: Instruction = {
// NOTE: reuse the terminal id since these lets must be scoped with the terminal anyway
// the only reason they exist is that there is a scope that will span the control flow.
id: block.terminal.id,
lvalue: {
place: {
kind: "Identifier",
memberPath: null,
identifier,
effect: Effect.Mutate,
loc: GeneratedSource,
},
kind: InstructionKind.Let,
},
value: {
kind: "Primitive",
value: undefined,
loc: GeneratedSource,
},
loc: GeneratedSource,
};
block.instructions.push(instr);
}
for (const [, block] of ir.blocks) {
block.phis.clear();
}
for (const [, block] of ir.blocks) {
for (const place of eachBlockOperand(block)) {
place.identifier.id = place.identifier.preSsaId ?? place.identifier.id;
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ import enterSSA from "../HIR/EnterSSA";
import { Environment } from "../HIR/HIRBuilder";
import { inferMutableRanges } from "../HIR/InferMutableLifetimes";
import inferReferenceEffects from "../HIR/InferReferenceEffects";
import leaveSSA from "../HIR/LeaveSSA";
import { leaveSSA } from "../HIR/LeaveSSA";
import codegen from "./Codegen";
import { HIRFunction } from "./HIR";
import { inferReactiveScopeDependencies } from "./InferReactiveScopeDependencies";
+6 -1
View File
@@ -128,7 +128,9 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
case "if": {
value = `[${terminal.id}] If (${printPlace(terminal.test)}) then:bb${
terminal.consequent
} else:bb${terminal.alternate}`;
} else:bb${terminal.alternate}${
terminal.fallthrough ? ` fallthrough=bb${terminal.fallthrough}` : ""
}`;
break;
}
case "throw": {
@@ -157,6 +159,9 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
output.push(` Default: bb${case_.block}`);
}
});
if (terminal.fallthrough) {
output.push(` Fallthrough: bb${terminal.fallthrough}`);
}
value = output;
break;
}
@@ -51,9 +51,9 @@ flowchart TB
```javascript
function f$0() {
let x$1 = 1;
x$1 = 2;
return x$1 + x$1 + x$1;
const x$4 = 1;
const x$5 = 2;
return x$5 + x$5 + x$5;
}
```
@@ -0,0 +1,91 @@
## Input
```javascript
function foo(a, b, c) {
let x = null;
label: {
if (a) {
x = b;
break label;
}
x = c;
}
return x;
}
```
## HIR
```
bb0:
[1] Let mutate x$8_@0 = null
[2] If (read a$5) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb0
[3] Reassign mutate x$9_@1[3:6] = read b$6
[4] Goto bb1
bb2:
predecessor blocks: bb0
[5] Reassign mutate x$10_@1[3:6] = read c$7
[6] Goto bb1
bb1:
predecessor blocks: bb3 bb2
x$11_@1[3:6]: phi(bb3: x$9_@1, bb2: x$10_@1)
[7] Return read x$11_@1
scope1 [3:6]:
- read b$6
- read a$5
- read c$7
```
### CFG
```mermaid
flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Let mutate x$8_@0 = null
"]
bb0_instrs --> bb0_terminal(["If (read a$5)"])
end
subgraph bb3
bb3_instrs["
[3] Reassign mutate x$9_@1[3:6] = read b$6
"]
bb3_instrs --> bb3_terminal(["Goto"])
end
subgraph bb2
bb2_instrs["
[5] Reassign mutate x$10_@1[3:6] = read c$7
"]
bb2_instrs --> bb2_terminal(["Goto"])
end
subgraph bb1
bb1_terminal(["Return read x$11_@1"])
end
%% Jumps
bb0_terminal -- "then" --> bb3
bb0_terminal -- "else" --> bb2
bb3_terminal --> bb1
bb2_terminal --> bb1
```
## Code
```javascript
function foo$0(a$5, b$6, c$7) {
const x$8 = null;
bb2: if (a$5) {
const x$9 = b$6;
}
const x$10 = c$7;
}
```
@@ -0,0 +1,11 @@
function foo(a, b, c) {
let x = null;
label: {
if (a) {
x = b;
break label;
}
x = c;
}
return x;
}
@@ -1,106 +0,0 @@
## Input
```javascript
function f(reader) {
const queue = [1, 2, 3];
let value = 0;
let sum = 0;
// BUG: we need to codegen the complex test expression
while ((value = queue.pop()) != null) {
sum += value;
}
return sum;
}
```
## HIR
```
bb0:
[1] Const mutate $11_@0 = 1
[2] Const mutate $12_@1 = 2
[3] Const mutate $13_@2 = 3
[4] Const mutate queue$14_@3[0:14] = Array [read $11_@0, read $12_@1, read $13_@2]
[5] Let mutate value$15_@4 = 0
[6] Let mutate sum$16_@3[0:14] = 0
[7] While test=bb1 loop=bb3 fallthrough=bb2
bb1:
predecessor blocks: bb0 bb3
sum$21_@3[0:14]: phi(bb0: sum$16_@3, bb3: sum$22_@3)
[8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
[9] Const mutate $19_@6 = null
[10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
[11] If (read $20_@7) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
[12] Reassign mutate sum$22_@3[0:14] = Binary read sum$21_@3 + read value$18_@3
[13] Goto(Continue) bb1
bb2:
predecessor blocks: bb1
[14] Return read sum$21_@3
scope7 [10:12]:
- read $19_@6
```
### CFG
```mermaid
flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Const mutate $11_@0 = 1
[2] Const mutate $12_@1 = 2
[3] Const mutate $13_@2 = 3
[4] Const mutate queue$14_@3[0:14] = Array [read $11_@0, read $12_@1, read $13_@2]
[5] Let mutate value$15_@4 = 0
[6] Let mutate sum$16_@3[0:14] = 0
"]
bb0_instrs --> bb0_terminal(["While"])
end
subgraph bb1
bb1_instrs["
[8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
[9] Const mutate $19_@6 = null
[10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
"]
bb1_instrs --> bb1_terminal(["If (read $20_@7)"])
end
subgraph bb3
bb3_instrs["
[12] Reassign mutate sum$22_@3[0:14] = Binary read sum$21_@3 + read value$18_@3
"]
bb3_instrs --> bb3_terminal(["Goto"])
end
subgraph bb2
bb2_terminal(["Return read sum$21_@3"])
end
%% Jumps
bb0_terminal -- "test" --> bb1
bb0_terminal -- "loop" --> bb3
bb0_terminal -- "fallthrough" --> bb2
bb1_terminal -- "then" --> bb3
bb1_terminal -- "else" --> bb2
bb3_terminal --> bb1
```
## Code
```javascript
function f$0(reader$1) {
const queue$2 = [1, 2, 3];
let value$6 = 0;
let sum$7 = 0;
bb2: while (((value$6 = queue$2.pop()), value$6 != null)) {
sum$7 = sum$7 + value$6;
}
return sum$7;
}
```
@@ -36,7 +36,7 @@ bb1:
a$12_@0[0:12]: phi(bb0: a$8_@0, bb3: a$15_@0)
b$14_@0[0:12]: phi(bb0: b$9_@0, bb3: b$17_@0)
c$16_@0[0:12]: phi(bb0: c$10_@0, bb3: c$18_@0)
[5] If (read cond$7) then:bb3 else:bb2
[5] If (read cond$7) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[6] Let mutate z$13_@0[0:12] = read a$12_@0
@@ -102,22 +102,22 @@ flowchart TB
## Code
```javascript
function foo$0(cond$1) {
let a$2 = {};
let b$3 = {};
let c$4 = {};
bb2: while (cond$1) {
let z$5 = a$2;
a$2 = b$3;
b$3 = c$4;
c$4 = z$5;
mutate$6(a$2, b$3);
function foo$0(cond$7) {
let a$8 = {};
let b$9 = {};
let c$10 = {};
bb2: while (cond$7) {
const z$13 = a$8;
a$8 = b$9;
b$9 = c$10;
c$10 = z$13;
mutate$6(a$8, b$9);
}
a$2;
b$3;
c$4;
return a$2;
a$8;
b$9;
c$10;
return a$8;
}
```
@@ -145,7 +145,7 @@ flowchart TB
## Code
```javascript
function mutate$0(x$1, y$2) {}
function mutate$0(x$3, y$4) {}
```
@@ -65,10 +65,10 @@ flowchart TB
```javascript
function f$0() {
let x$1 = 1;
x$1 = x$1 + 1;
x$1 = x$1 + 1;
x$1 = x$1 >>> 1;
const x$5 = 1;
const x$7 = x$5 + 1;
const x$9 = x$7 + 1;
const x$11 = x$9 >>> 1;
}
```
@@ -107,9 +107,9 @@ flowchart TB
## Code
```javascript
function g$0(a$1) {
a$1.c.b = a$1.b.c + 1;
a$1.c.b = a$1.b.c * 2;
function g$0(a$4) {
a$4.c.b = a$4.b.c + 1;
a$4.c.b = a$4.b.c * 2;
}
```
@@ -89,14 +89,14 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
const b$3 = {};
foo$4(a$2, b$3);
let _$5 = <div a={a$2}></div>;
function Component$0(props$9) {
const a$10 = [];
const b$11 = {};
foo$4(a$10, b$11);
const _$13 = <div a={a$10}></div>;
foo$4(b$3);
return <div a={a$2} b={b$3}></div>;
foo$4(b$11);
return <div a={a$10} b={b$11}></div>;
}
```
@@ -18,16 +18,16 @@ function foo(a, b, c) {
```
bb0:
[1] If (read a$4) then:bb3 else:bb1
[1] If (read a$4) then:bb3 else:bb1 fallthrough=bb1
bb3:
predecessor blocks: bb0
[2] While test=bb4 loop=bb6 fallthrough=bb1
bb4:
predecessor blocks: bb3 bb7
[3] If (read b$5) then:bb6 else:bb1
[3] If (read b$5) then:bb6 else:bb1 fallthrough=bb1
bb6:
predecessor blocks: bb4
[4] If (read c$6) then:bb1 else:bb7
[4] If (read c$6) then:bb1 else:bb7 fallthrough=bb7
bb7:
predecessor blocks: bb6
[5] Goto(Continue) bb4
@@ -78,10 +78,10 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
bb1: if (a$1) {
while (b$2) {
bb7: if (c$3) break;
function foo$0(a$4, b$5, c$6) {
bb1: if (a$4) {
while (b$5) {
bb7: if (c$6) break;
}
}
}
@@ -44,12 +44,12 @@ bb0:
[7] Goto bb1
bb1:
predecessor blocks: bb0 bb5 bb10
[8] If (read items$27_@0) then:bb3 else:bb2
[8] If (read items$27_@0) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[9] Const mutate $34_@6 = null
[10] Const mutate $36_@3[0:19] = Binary read item$10_@3 == read $34_@6
[11] If (read $36_@3) then:bb8 else:bb9
[11] If (read $36_@3) then:bb8 else:bb9 fallthrough=bb7
bb8:
predecessor blocks: bb3
[12] Const mutate $37_@3[0:19] = read $36_@3
@@ -61,7 +61,7 @@ bb9:
bb7:
predecessor blocks: bb8 bb9
$40_@3[0:19]: phi(bb8: $37_@3, bb9: $39_@3)
[16] If (read $40_@3) then:bb5 else:bb4
[16] If (read $40_@3) then:bb5 else:bb4 fallthrough=bb4
bb5:
predecessor blocks: bb7
[17] Goto(Continue) bb1
@@ -72,7 +72,7 @@ bb4:
[20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
[21] Call mutate renderedItems$29_@2.push(read $44_@8)
[22] Const mutate $49_@2[3:26] = Binary read renderedItems$29_@2.length >= read max$32_@5
[23] If (read $49_@2) then:bb2 else:bb10
[23] If (read $49_@2) then:bb2 else:bb10 fallthrough=bb10
bb10:
predecessor blocks: bb4
[24] Goto(Continue) bb1
@@ -187,12 +187,12 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const items$2 = props$1.items;
const maxItems$3 = props$1.maxItems;
const renderedItems$4 = [];
const seen$5 = new Set$6();
const max$7 = Math$8.max(0, maxItems$3);
function Component$0(props$26) {
const items$27 = props$26.items;
const maxItems$28 = props$26.maxItems;
const renderedItems$29 = [];
const seen$30 = new Set$6();
const max$32 = Math$8.max(0, maxItems$28);
}
```
@@ -80,7 +80,7 @@ function Component(props) {
bb0:
[1] Const mutate a_DEBUG$5_@0[1:7] = Array []
[2] Call mutate a_DEBUG$5_@0.push(read props$4.a)
[3] If (read props$4.b) then:bb2 else:bb1
[3] If (read props$4.b) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Const mutate $6_@1 = null
@@ -129,15 +129,15 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a_DEBUG$2 = [];
a_DEBUG$2.push(props$1.a);
bb1: if (props$1.b) {
function Component$0(props$4) {
const a_DEBUG$5 = [];
a_DEBUG$5.push(props$4.a);
bb1: if (props$4.b) {
return null;
}
a_DEBUG$2.push(props$1.d);
return a_DEBUG$2;
a_DEBUG$5.push(props$4.d);
return a_DEBUG$5;
}
```
@@ -147,7 +147,7 @@ function Component$0(props$1) {
bb0:
[1] Const mutate a$4_@0[1:7] = Array []
[2] Call mutate a$4_@0.push(read props$3.a)
[3] If (read props$3.b) then:bb2 else:bb1
[3] If (read props$3.b) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Call mutate a$4_@0.push(read props$3.c)
@@ -198,15 +198,15 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
a$2.push(props$1.a);
bb1: if (props$1.b) {
a$2.push(props$1.c);
function Component$0(props$3) {
const a$4 = [];
a$4.push(props$3.a);
bb1: if (props$3.b) {
a$4.push(props$3.c);
}
a$2.push(props$1.d);
return a$2;
a$4.push(props$3.d);
return a$4;
}
```
@@ -216,7 +216,7 @@ function Component$0(props$1) {
bb0:
[1] Const mutate a$5_@0[1:8] = Array []
[2] Call mutate a$5_@0.push(read props$4.a)
[3] If (read props$4.b) then:bb2 else:bb1
[3] If (read props$4.b) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Call mutate a$5_@0.push(read props$4.c)
@@ -268,16 +268,16 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
a$2.push(props$1.a);
bb1: if (props$1.b) {
a$2.push(props$1.c);
function Component$0(props$4) {
const a$5 = [];
a$5.push(props$4.a);
bb1: if (props$4.b) {
a$5.push(props$4.c);
return null;
}
a$2.push(props$1.d);
return a$2;
a$5.push(props$4.d);
return a$5;
}
```
@@ -287,7 +287,7 @@ function Component$0(props$1) {
bb0:
[1] Const mutate a$4_@0[1:7] = Array []
[2] Call mutate a$4_@0.push(read props$3.a)
[3] If (read props$3.b) then:bb2 else:bb1
[3] If (read props$3.b) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Call mutate a$4_@0.push(read props$3.c)
@@ -337,16 +337,16 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
a$2.push(props$1.a);
bb1: if (props$1.b) {
a$2.push(props$1.c);
return a$2;
function Component$0(props$3) {
const a$4 = [];
a$4.push(props$3.a);
bb1: if (props$3.b) {
a$4.push(props$3.c);
return a$4;
}
a$2.push(props$1.d);
return a$2;
a$4.push(props$3.d);
return a$4;
}
```
@@ -356,7 +356,7 @@ function Component$0(props$1) {
bb0:
[1] Const mutate a$4_@0[1:7] = Array []
[2] Call mutate a$4_@0.push(read props$3.a)
[3] If (read props$3.b) then:bb1 else:bb2
[3] If (read props$3.b) then:bb1 else:bb2 fallthrough=bb2
bb2:
predecessor blocks: bb0
[4] Call mutate a$4_@0.push(read props$3.c)
@@ -406,15 +406,15 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
a$2.push(props$1.a);
bb2: if (props$1.b) {
a$2.push(props$1.d);
return a$2;
function Component$0(props$3) {
const a$4 = [];
a$4.push(props$3.a);
bb2: if (props$3.b) {
a$4.push(props$3.d);
return a$4;
}
a$2.push(props$1.c);
a$4.push(props$3.c);
}
```
@@ -37,14 +37,14 @@ function mayMutate() {}
bb0:
[1] Const mutate a$7_@0[1:9] = Array []
[2] Const mutate b$8_@0[1:9] = Array []
[3] If (read b$8_@0) then:bb2 else:bb1
[3] If (read b$8_@0) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Call mutate a$7_@0.push(read props$6.p0)
[5] Goto bb1
bb1:
predecessor blocks: bb2 bb0
[6] If (read props$6.p1) then:bb4 else:bb3
[6] If (read props$6.p1) then:bb4 else:bb3 fallthrough=bb3
bb4:
predecessor blocks: bb1
[7] Call mutate b$8_@0.push(read props$6.p2)
@@ -109,18 +109,18 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
const b$3 = [];
bb1: if (b$3) {
a$2.push(props$1.p0);
function Component$0(props$6) {
const a$7 = [];
const b$8 = [];
bb1: if (b$8) {
a$7.push(props$6.p0);
}
bb3: if (props$1.p1) {
b$3.push(props$1.p2);
bb3: if (props$6.p1) {
b$8.push(props$6.p2);
}
return <Foo$4 a={a$2} b={b$3}></Foo$4>;
return <Foo$4 a={a$7} b={b$8}></Foo$4>;
}
```
@@ -131,14 +131,14 @@ bb0:
[1] Const mutate a$9_@0[0:10] = Array []
[2] Const mutate b$10_@0[0:10] = Array []
[3] Const mutate $11_@0[0:10] = Call mutate mayMutate$4_@0(mutate b$10_@0)
[4] If (read $11_@0) then:bb2 else:bb1
[4] If (read $11_@0) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Call mutate a$9_@0.push(read props$8.p0)
[6] Goto bb1
bb1:
predecessor blocks: bb2 bb0
[7] If (read props$8.p1) then:bb4 else:bb3
[7] If (read props$8.p1) then:bb4 else:bb3 fallthrough=bb3
bb4:
predecessor blocks: bb1
[8] Call mutate b$10_@0.push(read props$8.p2)
@@ -200,18 +200,18 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
const b$3 = [];
bb1: if (mayMutate$4(b$3)) {
a$2.push(props$1.p0);
function Component$0(props$8) {
const a$9 = [];
const b$10 = [];
bb1: if (mayMutate$4(b$10)) {
a$9.push(props$8.p0);
}
bb3: if (props$1.p1) {
b$3.push(props$1.p2);
bb3: if (props$8.p1) {
b$10.push(props$8.p2);
}
return <Foo$6 a={a$2} b={b$3}></Foo$6>;
return <Foo$6 a={a$9} b={b$10}></Foo$6>;
}
```
@@ -89,14 +89,14 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
const b$3 = {};
new Foo$4(a$2, b$3);
let _$5 = <div a={a$2}></div>;
function Component$0(props$9) {
const a$10 = [];
const b$11 = {};
new Foo$4(a$10, b$11);
const _$13 = <div a={a$10}></div>;
new Foo$4(b$3);
return <div a={a$2} b={b$3}></div>;
new Foo$4(b$11);
return <div a={a$10} b={b$11}></div>;
}
```
@@ -27,14 +27,14 @@ bb0:
[3] Const mutate $9_@1 = "div"
[4] JSX <read $9_@1>{freeze x$8_@0}</read $9_@1>
[5] Const mutate y$10_@2[5:12] = Array []
[6] If (read x$8_@0.length) then:bb2 else:bb1
[6] If (read x$8_@0.length) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[7] Call mutate y$10_@2.push(read x$8_@0)
[8] Goto bb1
bb1:
predecessor blocks: bb2 bb0
[9] If (read b$7) then:bb4 else:bb3
[9] If (read b$7) then:bb4 else:bb3 fallthrough=bb3
bb4:
predecessor blocks: bb1
[10] Call mutate y$10_@2.push(read b$7)
@@ -100,17 +100,17 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2) {
const x$3 = [];
x$3.push(a$1);
<div>{x$3}</div>;
const y$5 = [];
bb1: if (x$3.length) {
y$5.push(x$3);
function foo$0(a$6, b$7) {
const x$8 = [];
x$8.push(a$6);
<div>{x$8}</div>;
const y$10 = [];
bb1: if (x$8.length) {
y$10.push(x$8);
}
bb3: if (b$2) {
y$5.push(b$2);
bb3: if (b$7) {
y$10.push(b$7);
}
}
@@ -27,14 +27,14 @@ bb0:
[1] Const mutate items$9_@0[1:10] = Array [read z$8]
[2] Call mutate items$9_@0.push(read x$6)
[3] Const mutate items2$10_@1[3:7] = Array []
[4] If (read x$6) then:bb2 else:bb1
[4] If (read x$6) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Call mutate items2$10_@1.push(read y$7)
[6] Goto bb1
bb1:
predecessor blocks: bb2 bb0
[7] If (read y$7) then:bb4 else:bb3
[7] If (read y$7) then:bb4 else:bb3 fallthrough=bb3
bb4:
predecessor blocks: bb1
[8] Call mutate items$9_@0.push(read x$6)
@@ -97,19 +97,19 @@ flowchart TB
## Code
```javascript
function foo$0(x$1, y$2, z$3) {
const items$4 = [z$3];
items$4.push(x$1);
const items2$5 = [];
bb1: if (x$1) {
items2$5.push(y$2);
function foo$0(x$6, y$7, z$8) {
const items$9 = [z$8];
items$9.push(x$6);
const items2$10 = [];
bb1: if (x$6) {
items2$10.push(y$7);
}
bb3: if (y$2) {
items$4.push(x$1);
bb3: if (y$7) {
items$9.push(x$6);
}
return items2$5;
return items2$10;
}
```
@@ -0,0 +1,25 @@
## Input
```javascript
function f(reader) {
const queue = [1, 2, 3];
let value = 0;
let sum = 0;
// BUG: we need to codegen the complex test expression
while ((value = queue.pop()) != null) {
sum += value;
}
return sum;
}
```
## Error
```
TODO: Handle conversion of VariableDeclaration to expression
```
@@ -24,13 +24,13 @@ function foo(a, b, c) {
```
bb0:
[1] Let mutate x$10_@0[1:8] = Array []
[2] If (read a$7) then:bb2 else:bb1
[2] If (read a$7) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] If (read b$8) then:bb4 else:bb1
[3] If (read b$8) then:bb4 else:bb1 fallthrough=bb1
bb4:
predecessor blocks: bb2
[4] If (read c$9) then:bb6 else:bb1
[4] If (read c$9) then:bb6 else:bb1 fallthrough=bb1
bb6:
predecessor blocks: bb4
[5] Const mutate $11_@1 = 0
@@ -38,7 +38,7 @@ bb6:
[7] Goto bb1
bb1:
predecessor blocks: bb6 bb4 bb2 bb0
[8] If (read a$7.length) then:bb8 else:bb7
[8] If (read a$7.length) then:bb8 else:bb7 fallthrough=bb7
bb8:
predecessor blocks: bb1
[9] Return read a$7
@@ -105,18 +105,18 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
let x$4 = [];
bb1: if (a$1) {
if (b$2) {
if (c$3) {
x$4.push(0);
function foo$0(a$7, b$8, c$9) {
const x$10 = [];
bb1: if (a$7) {
if (b$8) {
if (c$9) {
x$10.push(0);
}
}
}
bb7: if (a$1.length) {
return a$1;
bb7: if (a$7.length) {
return a$7;
}
return null;
@@ -51,10 +51,10 @@ flowchart TB
```javascript
function Component$0() {
const a$1 = [];
const b$2 = a$1;
useFreeze$3(a$1);
foo$4(b$2);
const a$5 = [];
const b$6 = a$5;
useFreeze$3(a$5);
foo$4(b$6);
}
```
@@ -109,7 +109,7 @@ flowchart TB
## Code
```javascript
function foo$0(x$1) {}
function foo$0(x$2) {}
```
@@ -121,14 +121,14 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const x$2 = [];
const y$3 = useFreeze$4(x$2);
foo$5(y$3, x$2);
function Component$0(props$10) {
const x$11 = [];
const y$12 = useFreeze$4(x$11);
foo$5(y$12, x$11);
return (
<Component$0>
{x$2}
{y$3}
{x$11}
{y$12}
</Component$0>
);
}
@@ -50,11 +50,11 @@ flowchart TB
```javascript
function Component$0() {
const a$1 = [];
useFreeze$2(a$1);
useFreeze$2(a$1);
call$3(a$1);
return a$1;
const a$4 = [];
useFreeze$2(a$4);
useFreeze$2(a$4);
call$3(a$4);
return a$4;
}
```
@@ -82,7 +82,7 @@ flowchart TB
## Code
```javascript
function useFreeze$0(x$1) {}
function useFreeze$0(x$2) {}
```
## HIR
@@ -109,7 +109,7 @@ flowchart TB
## Code
```javascript
function call$0(x$1) {}
function call$0(x$2) {}
```
@@ -29,7 +29,7 @@ bb0:
[1] Const mutate cond$8_@0 = read props$7.cond
[2] Const mutate x$9_@1 = read props$7.x
[3] Let mutate a$10_@2 = undefined
[4] If (read cond$8_@0) then:bb2 else:bb3
[4] If (read cond$8_@0) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Reassign mutate a$11_@3[5:8] = read x$9_@1
@@ -99,20 +99,21 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const cond$2 = props$1.cond;
const x$3 = props$1.x;
let a$4 = undefined;
bb1: if (cond$2) {
a$4 = x$3;
function Component$0(props$7) {
const cond$8 = props$7.cond;
const x$9 = props$7.x;
const a$10 = undefined;
let a$11 = undefined;
bb1: if (cond$8) {
a$11 = x$9;
} else {
a$4 = [];
a$11 = [];
}
useFreeze$5(a$4);
useFreeze$5(a$4);
call$6(a$4);
return a$4;
useFreeze$5(a$11);
useFreeze$5(a$11);
call$6(a$11);
return a$11;
}
```
@@ -140,7 +141,7 @@ flowchart TB
## Code
```javascript
function useFreeze$0(x$1) {}
function useFreeze$0(x$2) {}
```
## HIR
@@ -167,7 +168,7 @@ flowchart TB
## Code
```javascript
function call$0(x$1) {}
function call$0(x$2) {}
```
@@ -147,7 +147,7 @@ function Foo$0() {}
bb0:
[1] Const mutate a$9_@0[0:7] = Call mutate compute$3_@0(read props$8.a)
[2] Const mutate b$10_@0[0:7] = Call mutate compute$3_@0(read props$8.b)
[3] If (read props$8.c) then:bb2 else:bb1
[3] If (read props$8.c) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Call mutate mutate$5_@0(mutate a$9_@0)
@@ -198,15 +198,15 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = compute$3(props$1.a);
const b$4 = compute$3(props$1.b);
bb1: if (props$1.c) {
mutate$5(a$2);
mutate$5(b$4);
function Component$0(props$8) {
const a$9 = compute$3(props$8.a);
const b$10 = compute$3(props$8.b);
bb1: if (props$8.c) {
mutate$5(a$9);
mutate$5(b$10);
}
return <Foo$6 a={a$2} b={b$4}></Foo$6>;
return <Foo$6 a={a$9} b={b$10}></Foo$6>;
}
```
@@ -58,10 +58,10 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = compute$3(props$1.a);
const b$4 = compute$3(props$1.b);
return <Foo$5 a={a$2} b={b$4}></Foo$5>;
function Component$0(props$7) {
const a$8 = compute$3(props$7.a);
const b$9 = compute$3(props$7.b);
return <Foo$5 a={a$8} b={b$9}></Foo$5>;
}
```
@@ -114,7 +114,7 @@ function Foo$0() {}
bb0:
[1] Const mutate a$9_@0[0:6] = Call mutate compute$3_@0(read props$8.a)
[2] Const mutate b$10_@0[0:6] = Call mutate compute$3_@0(read props$8.b)
[3] If (read props$8.c) then:bb2 else:bb1
[3] If (read props$8.c) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Call mutate foo$5_@0(mutate a$9_@0, mutate b$10_@0)
@@ -163,14 +163,14 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = compute$3(props$1.a);
const b$4 = compute$3(props$1.b);
bb1: if (props$1.c) {
foo$5(a$2, b$4);
function Component$0(props$8) {
const a$9 = compute$3(props$8.a);
const b$10 = compute$3(props$8.b);
bb1: if (props$8.c) {
foo$5(a$9, b$10);
}
return <Foo$6 a={a$2} b={b$4}></Foo$6>;
return <Foo$6 a={a$9} b={b$10}></Foo$6>;
}
```
@@ -60,11 +60,11 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = compute$3(props$1.a);
const b$4 = compute$3(props$1.b);
foo$5(a$2, b$4);
return <Foo$6 a={a$2} b={b$4}></Foo$6>;
function Component$0(props$8) {
const a$9 = compute$3(props$8.a);
const b$10 = compute$3(props$8.b);
foo$5(a$9, b$10);
return <Foo$6 a={a$9} b={b$10}></Foo$6>;
}
```
@@ -19,10 +19,10 @@ function foo(a, b, c) {
```
bb0:
[1] Let mutate y$8_@0[1:6] = Array []
[2] If (read a$5) then:bb3 else:bb1
[2] If (read a$5) then:bb3 else:bb1 fallthrough=bb1
bb3:
predecessor blocks: bb0
[3] If (read b$6) then:bb5 else:bb1
[3] If (read b$6) then:bb5 else:bb1 fallthrough=bb1
bb5:
predecessor blocks: bb3
[4] Call mutate y$8_@0.push(read c$7)
@@ -72,11 +72,11 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
let y$4 = [];
bb1: if (a$1) {
if (b$2) {
y$4.push(c$3);
function foo$0(a$5, b$6, c$7) {
const y$8 = [];
bb1: if (a$5) {
if (b$6) {
y$8.push(c$7);
}
}
}
@@ -76,10 +76,10 @@ flowchart TB
## Code
```javascript
function Foo$0(props$1) {
function Foo$0(props$13) {
return (
<>
Hello {props$1.greeting}
Hello {props$13.greeting}
{<div>{<>Text</>}</div>}
</>
);
@@ -24,7 +24,7 @@ function g() {}
```
bb0:
[1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
[2] If (read $5_@0) then:bb2 else:bb3
[2] If (read $5_@0) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Const mutate $6_@1[0:6] = Call mutate g$4_@1()
@@ -92,7 +92,7 @@ function And$0() {
```
bb0:
[1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
[2] If (read $5_@0) then:bb2 else:bb3
[2] If (read $5_@0) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Const mutate $6_@1[0:6] = read $5_@0
@@ -162,7 +162,7 @@ bb0:
[1] Const mutate $9_@0[0:2] = Call mutate f$2_@0()
[2] Const mutate $10_@1 = null
[3] Const mutate $11_@2 = Binary read $9_@0 != read $10_@1
[4] If (read $11_@2) then:bb2 else:bb3
[4] If (read $11_@2) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Const mutate $12_@3[0:8] = read $9_@0
@@ -221,7 +221,7 @@ flowchart TB
## Code
```javascript
function QuestionQuestion$0(props$1) {
function QuestionQuestion$0(props$8) {
bb1: if (f$2() != null) {
} else {
}
@@ -63,7 +63,7 @@ flowchart TB
## Code
```javascript
function mutate$0(x$1, y$2) {}
function mutate$0(x$3, y$4) {}
```
## HIR
@@ -90,7 +90,7 @@ flowchart TB
## Code
```javascript
function cond$0(x$1) {}
function cond$0(x$2) {}
```
## HIR
@@ -109,7 +109,7 @@ bb1:
c$22_@0[0:23]: phi(bb0: c$15_@0, bb4: c$25_@0)
d$24_@0[0:23]: phi(bb0: d$16_@0, bb4: d$26_@0)
[6] Const mutate $17_@1[6:8] = true
[7] If (read $17_@1) then:bb3 else:bb2
[7] If (read $17_@1) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[8] Let mutate z$19_@0[0:23] = read a$18_@0
@@ -119,7 +119,7 @@ bb3:
[12] Reassign mutate d$26_@0[0:23] = read z$19_@0
[13] Call mutate mutate$7_@0(mutate a$21_@0, mutate b$23_@0)
[14] Const mutate $29_@0[0:23] = Call mutate cond$8_@0(mutate a$21_@0)
[15] If (read $29_@0) then:bb2 else:bb4
[15] If (read $29_@0) then:bb2 else:bb4 fallthrough=bb4
bb4:
predecessor blocks: bb3
[16] Goto(Continue) bb1
@@ -129,16 +129,16 @@ bb2:
b$31_@0[0:23]: phi(bb3: b$23_@0, bb1: b$20_@0)
c$32_@0[0:23]: phi(bb3: c$25_@0, bb1: c$22_@0)
d$33_@0[0:23]: phi(bb3: d$26_@0, bb1: d$24_@0)
[17] If (read a$30_@0) then:bb7 else:bb7
[17] If (read a$30_@0) then:bb7 else:bb7 fallthrough=bb7
bb7:
predecessor blocks: bb2
[18] If (read b$31_@0) then:bb9 else:bb9
[18] If (read b$31_@0) then:bb9 else:bb9 fallthrough=bb9
bb9:
predecessor blocks: bb7
[19] If (read c$32_@0) then:bb11 else:bb11
[19] If (read c$32_@0) then:bb11 else:bb11 fallthrough=bb11
bb11:
predecessor blocks: bb9
[20] If (read d$33_@0) then:bb13 else:bb13
[20] If (read d$33_@0) then:bb13 else:bb13 fallthrough=bb13
bb13:
predecessor blocks: bb11
[21] Const mutate $34_@2 = null
@@ -225,35 +225,35 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
let a$2 = {};
let b$3 = {};
let c$4 = {};
let d$5 = {};
function Component$0(props$12) {
let a$18 = {};
let b$20 = {};
let c$22 = {};
let d$24 = {};
bb2: while (true) {
let z$6 = a$2;
a$2 = b$3;
b$3 = c$4;
c$4 = d$5;
d$5 = z$6;
mutate$7(a$2, b$3);
const z$19 = a$18;
a$18 = b$20;
b$20 = c$22;
c$22 = d$24;
d$24 = z$19;
mutate$7(a$18, b$20);
bb4: if (cond$8(a$2)) break;
bb4: if (cond$8(a$18)) break;
}
bb7: if (a$2) {
bb7: if (a$18) {
}
bb9: if (b$3) {
bb9: if (b$20) {
}
bb11: if (c$4) {
bb11: if (c$22) {
}
bb13: if (d$5) {
bb13: if (d$24) {
}
mutate$7(d$5, null);
mutate$7(d$24, null);
}
```
@@ -59,7 +59,7 @@ flowchart TB
## Code
```javascript
function mutate$0(x$1, y$2) {}
function mutate$0(x$3, y$4) {}
```
## HIR
@@ -73,19 +73,19 @@ bb0:
[5] Const mutate x$15_@1[0:15] = Object { }
[6] Reassign mutate x$15_@1.b[0:15] = read b$12_@1
[7] Const mutate y$16_@1[0:15] = Call mutate mutate$8_@1(mutate x$15_@1, mutate d$14_@1)
[8] If (read a$11_@0) then:bb1 else:bb1
[8] If (read a$11_@0) then:bb1 else:bb1 fallthrough=bb1
bb1:
predecessor blocks: bb0
[9] If (read b$12_@1) then:bb3 else:bb3
[9] If (read b$12_@1) then:bb3 else:bb3 fallthrough=bb3
bb3:
predecessor blocks: bb1
[10] If (read c$13_@2) then:bb5 else:bb5
[10] If (read c$13_@2) then:bb5 else:bb5 fallthrough=bb5
bb5:
predecessor blocks: bb3
[11] If (read d$14_@1) then:bb7 else:bb7
[11] If (read d$14_@1) then:bb7 else:bb7 fallthrough=bb7
bb7:
predecessor blocks: bb5
[12] If (read y$16_@1) then:bb9 else:bb9
[12] If (read y$16_@1) then:bb9 else:bb9 fallthrough=bb9
bb9:
predecessor blocks: bb7
[13] Const mutate $17_@3 = null
@@ -148,32 +148,32 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = {};
const b$3 = [a$2];
const c$4 = {};
const d$5 = {
c: c$4,
function Component$0(props$10) {
const a$11 = {};
const b$12 = [a$11];
const c$13 = {};
const d$14 = {
c: c$13,
};
const x$6 = {};
x$6.b = b$3;
const y$7 = mutate$8(x$6, d$5);
bb1: if (a$2) {
const x$15 = {};
x$15.b = b$12;
const y$16 = mutate$8(x$15, d$14);
bb1: if (a$11) {
}
bb3: if (b$3) {
bb3: if (b$12) {
}
bb5: if (c$4) {
bb5: if (c$13) {
}
bb7: if (d$5) {
bb7: if (d$14) {
}
bb9: if (y$7) {
bb9: if (y$16) {
}
mutate$8(x$6, null);
mutate$8(x$15, null);
}
```
@@ -100,27 +100,27 @@ bb0:
bb1:
predecessor blocks: bb0 bb4
[6] Const mutate $16_@2[6:8] = true
[7] If (read $16_@2) then:bb3 else:bb2
[7] If (read $16_@2) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[8] Call mutate mutate$6_@0(mutate a$12_@0, mutate b$13_@0)
[9] Const mutate $21_@0[0:18] = Call mutate cond$7_@0(mutate a$12_@0)
[10] If (read $21_@0) then:bb2 else:bb4
[10] If (read $21_@0) then:bb2 else:bb4 fallthrough=bb4
bb4:
predecessor blocks: bb3
[11] Goto(Continue) bb1
bb2:
predecessor blocks: bb3 bb1
[12] If (read a$12_@0) then:bb7 else:bb7
[12] If (read a$12_@0) then:bb7 else:bb7 fallthrough=bb7
bb7:
predecessor blocks: bb2
[13] If (read b$13_@0) then:bb9 else:bb9
[13] If (read b$13_@0) then:bb9 else:bb9 fallthrough=bb9
bb9:
predecessor blocks: bb7
[14] If (read c$14_@1) then:bb11 else:bb11
[14] If (read c$14_@1) then:bb11 else:bb11 fallthrough=bb11
bb11:
predecessor blocks: bb9
[15] If (read d$15_@0) then:bb13 else:bb13
[15] If (read d$15_@0) then:bb13 else:bb13 fallthrough=bb13
bb13:
predecessor blocks: bb11
[16] Const mutate $28_@3 = null
@@ -202,30 +202,30 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
let a$2 = {};
let b$3 = {};
let c$4 = {};
let d$5 = {};
function Component$0(props$11) {
const a$12 = {};
const b$13 = {};
const c$14 = {};
const d$15 = {};
bb2: while (true) {
mutate$6(a$2, b$3);
mutate$6(a$12, b$13);
bb4: if (cond$7(a$2)) break;
bb4: if (cond$7(a$12)) break;
}
bb7: if (a$2) {
bb7: if (a$12) {
}
bb9: if (b$3) {
bb9: if (b$13) {
}
bb11: if (c$4) {
bb11: if (c$14) {
}
bb13: if (d$5) {
bb13: if (d$15) {
}
mutate$6(d$5, null);
mutate$6(d$15, null);
}
```
@@ -21,7 +21,7 @@ function foo(a, b, c) {
bb0:
[1] Const mutate x$9_@0[1:6] = Array []
[2] Const mutate y$10_@0[1:6] = Array []
[3] If (read x$9_@0) then:bb1 else:bb1
[3] If (read x$9_@0) then:bb1 else:bb1 fallthrough=bb1
bb1:
predecessor blocks: bb0
[4] Call mutate y$10_@0.push(read a$6)
@@ -61,14 +61,14 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
const x$4 = [];
const y$5 = [];
bb1: if (x$4) {
function foo$0(a$6, b$7, c$8) {
const x$9 = [];
const y$10 = [];
bb1: if (x$9) {
}
y$5.push(a$1);
x$4.push(b$2);
y$10.push(a$6);
x$9.push(b$7);
}
```
@@ -47,11 +47,11 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2) {
let x$3 = [];
let y$4 = [];
x$3.push(a$1);
y$4.push(b$2);
function foo$0(a$5, b$6) {
const x$7 = [];
const y$8 = [];
x$7.push(a$5);
y$8.push(b$6);
}
```
@@ -47,11 +47,11 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2) {
let x$3 = [];
let y$4 = [];
y$4.push(b$2);
x$3.push(a$1);
function foo$0(a$5, b$6) {
const x$7 = [];
const y$8 = [];
y$8.push(b$6);
x$7.push(a$5);
}
```
@@ -22,11 +22,11 @@ function foo(a, b, c) {
```
bb0:
[1] Let mutate x$11_@0[1:11] = Array []
[2] If (read a$8) then:bb2 else:bb1
[2] If (read a$8) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Let mutate y$12_@1[3:7] = Array []
[4] If (read b$9) then:bb4 else:bb3
[4] If (read b$9) then:bb4 else:bb3 fallthrough=bb3
bb4:
predecessor blocks: bb2
[5] Call mutate y$12_@1.push(read c$10)
@@ -98,19 +98,19 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
let x$4 = [];
bb1: if (a$1) {
let y$5 = [];
function foo$0(a$8, b$9, c$10) {
const x$11 = [];
bb1: if (a$8) {
const y$12 = [];
bb3: if (b$2) {
y$5.push(c$3);
bb3: if (b$9) {
y$12.push(c$10);
}
x$4.push(<div>{y$5}</div>);
x$11.push(<div>{y$12}</div>);
}
return x$4;
return x$11;
}
```
@@ -22,7 +22,7 @@ bb0:
[3] While test=bb1 loop=bb3 fallthrough=bb2
bb1:
predecessor blocks: bb0 bb3
[4] If (read c$8) then:bb3 else:bb2
[4] If (read c$8) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[5] Call mutate y$10_@0.push(read b$7)
@@ -76,12 +76,12 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
let x$4 = [];
let y$5 = [];
bb2: while (c$3) {
y$5.push(b$2);
x$4.push(a$1);
function foo$0(a$6, b$7, c$8) {
const x$9 = [];
const y$10 = [];
bb2: while (c$8) {
y$10.push(b$7);
x$9.push(a$6);
}
}
@@ -22,11 +22,11 @@ function foo(a, b, c) {
```
bb0:
[1] Let mutate x$9_@0[1:9] = Array []
[2] If (read a$6) then:bb2 else:bb1
[2] If (read a$6) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Let mutate y$10_@0[1:9] = Array []
[4] If (read b$7) then:bb4 else:bb3
[4] If (read b$7) then:bb4 else:bb3 fallthrough=bb3
bb4:
predecessor blocks: bb2
[5] Call mutate y$10_@0.push(read c$8)
@@ -90,19 +90,19 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
let x$4 = [];
bb1: if (a$1) {
let y$5 = [];
function foo$0(a$6, b$7, c$8) {
const x$9 = [];
bb1: if (a$6) {
const y$10 = [];
bb3: if (b$2) {
y$5.push(c$3);
bb3: if (b$7) {
y$10.push(c$8);
}
x$4.push(y$5);
x$9.push(y$10);
}
return x$4;
return x$9;
}
```
@@ -57,13 +57,13 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const x$2 = {};
const y$3 = [];
x$2.y = y$3;
const child$4 = <Component$0 data={y$3}></Component$0>;
x$2.y.push(props$1.p0);
return <Component$0 data={x$2}>{child$4}</Component$0>;
function Component$0(props$6) {
const x$7 = {};
const y$8 = [];
x$7.y = y$8;
const child$9 = <Component$0 data={y$8}></Component$0>;
x$7.y.push(props$6.p0);
return <Component$0 data={x$7}>{child$9}</Component$0>;
}
```
@@ -51,12 +51,12 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = {};
let y$2 = [];
let z$3 = {};
y$2.push(z$3);
x$1.y = y$2;
return x$1;
const x$4 = {};
const y$5 = [];
const z$6 = {};
y$5.push(z$6);
x$4.y = y$5;
return x$4;
}
```
@@ -22,10 +22,10 @@ bb0:
[1] Let mutate x$10_@0[1:8] = Array []
[2] Const mutate $11_@1 = 1
[3] Const mutate $12_@2 = Binary read a$8.length === read $11_@1
[4] If (read $12_@2) then:bb2 else:bb1
[4] If (read $12_@2) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] If (read b$9) then:bb4 else:bb1
[5] If (read b$9) then:bb4 else:bb1 fallthrough=bb1
bb4:
predecessor blocks: bb2
[6] Call mutate x$10_@0.push(read b$9)
@@ -88,15 +88,15 @@ flowchart TB
## Code
```javascript
function f$0(a$1, b$2) {
let x$3 = [];
bb1: if (a$1.length === 1) {
if (b$2) {
x$3.push(b$2);
function f$0(a$8, b$9) {
const x$10 = [];
bb1: if (a$8.length === 1) {
if (b$9) {
x$10.push(b$9);
}
}
return <div>{x$3}</div>;
return <div>{x$10}</div>;
}
```
@@ -26,7 +26,7 @@ bb0:
[1] Let mutate x$7_@0[1:7] = Array []
[2] Call mutate x$7_@0.push(read props$6.p0)
[3] Let mutate y$8_@0[1:7] = read x$7_@0
[4] If (read props$6.p1) then:bb2 else:bb1
[4] If (read props$6.p1) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Reassign mutate x$9_@0[1:7] = Array []
@@ -88,18 +88,18 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
let x$2 = [];
x$2.push(props$1.p0);
let y$3 = x$2;
bb1: if (props$1.p1) {
x$2 = [];
function Component$0(props$6) {
let x$7 = [];
x$7.push(props$6.p0);
const y$8 = x$7;
bb1: if (props$6.p1) {
x$7 = [];
}
let _$4 = <Component$0 x={x$2}></Component$0>;
const _$12 = <Component$0 x={x$7}></Component$0>;
y$3.push(props$1.p2);
return <Component$0 x={x$2} y={y$3}></Component$0>;
y$8.push(props$6.p2);
return <Component$0 x={x$7} y={y$8}></Component$0>;
}
```
@@ -35,7 +35,7 @@ function foo(a, b, c) {
```
bb0:
[1] Let mutate x$16_@0[1:5] = Array []
[2] If (read a$13) then:bb2 else:bb1
[2] If (read a$13) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Call mutate x$16_@0.push(read a$13)
@@ -48,6 +48,7 @@ bb1:
[8] Switch (read b$14)
Case read $20_@3: bb5
Default: bb4
Fallthrough: bb3
bb5:
predecessor blocks: bb1
[9] Reassign mutate x$22_@4[9:14] = Array []
@@ -150,31 +151,32 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
let x$4 = [];
bb1: if (a$1) {
x$4.push(a$1);
function foo$0(a$13, b$14, c$15) {
const x$16 = [];
bb1: if (a$13) {
x$16.push(a$13);
}
let y$5 = <div>{x$4}</div>;
const y$19 = <div>{x$16}</div>;
let x$22 = undefined;
bb3: switch (b$2) {
bb3: switch (b$14) {
case 0: {
x$4 = [];
x$4.push(b$2);
x$22 = [];
x$22.push(b$14);
break bb3;
}
default: {
x$4 = [];
x$4.push(c$3);
x$22 = [];
x$22.push(c$15);
}
}
return (
<div>
{y$5}
{x$4}
{y$19}
{x$22}
</div>
);
}
@@ -66,15 +66,15 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
let x$2 = [];
x$2.push(props$1.p0);
let y$3 = x$2;
x$2 = [];
let _$4 = <Component$0 x={x$2}></Component$0>;
function Component$0(props$6) {
const x$7 = [];
x$7.push(props$6.p0);
const y$8 = x$7;
const x$9 = [];
const _$10 = <Component$0 x={x$9}></Component$0>;
y$3.push(props$1.p1);
return <Component$0 x={x$2} y={y$3}></Component$0>;
y$8.push(props$6.p1);
return <Component$0 x={x$9} y={y$8}></Component$0>;
}
```
@@ -37,7 +37,7 @@ function Component(props) {
```
bb0:
[1] Let mutate x$7_@0 = undefined
[2] If (read props$6.cond) then:bb2 else:bb10
[2] If (read props$6.cond) then:bb2 else:bb10 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Const mutate $8_@1 = 2
@@ -48,6 +48,7 @@ bb2:
Case read $9_@2: bb6
Case read $8_@1: bb4
Default: bb4
Fallthrough: bb1
bb8:
predecessor blocks: bb2
[7] Reassign mutate x$11_@4[7:17] = read props$6.v0
@@ -62,7 +63,7 @@ bb4:
[12] Goto bb1
bb10:
predecessor blocks: bb0
[13] If (read props$6.cond2) then:bb12 else:bb13
[13] If (read props$6.cond2) then:bb12 else:bb13 fallthrough=bb1
bb12:
predecessor blocks: bb10
[14] Reassign mutate x$14_@4[7:17] = read props$6.b
@@ -167,17 +168,18 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
let x$2 = undefined;
bb1: if (props$1.cond) {
switch (props$1.test) {
function Component$0(props$6) {
const x$7 = undefined;
let x$11 = undefined;
bb1: if (props$6.cond) {
switch (props$6.test) {
case 0: {
x$2 = props$1.v0;
x$11 = props$6.v0;
break bb1;
}
case 1: {
x$2 = props$1.v1;
x$11 = props$6.v1;
break bb1;
}
@@ -185,18 +187,18 @@ function Component$0(props$1) {
}
default: {
x$2 = props$1.v2;
x$11 = props$6.v2;
}
}
} else {
if (props$1.cond2) {
x$2 = props$1.b;
if (props$6.cond2) {
x$11 = props$6.b;
} else {
x$2 = props$1.c;
x$11 = props$6.c;
}
}
x$2;
x$11;
}
```
@@ -84,14 +84,14 @@ flowchart TB
```javascript
function foo$0() {
let a$1 = {};
let b$2 = {};
let c$3 = {};
a$1 = b$2;
b$2 = c$3;
c$3 = a$1;
mutate$4(a$1, b$2);
return c$3;
const a$5 = {};
const b$6 = {};
const c$7 = {};
const a$8 = b$6;
const b$9 = c$7;
const c$10 = a$8;
mutate$4(a$8, b$9);
return c$10;
}
```
@@ -15,7 +15,7 @@ function foo(x, y) {
```
bb0:
[1] If (read x$8) then:bb2 else:bb1
[1] If (read x$8) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[2] Const mutate $10_@0 = false
@@ -71,11 +71,11 @@ flowchart TB
## Code
```javascript
function foo$0(x$1, y$2) {
bb1: if (x$1) {
return foo$0(false, y$2);
function foo$0(x$8, y$9) {
bb1: if (x$8) {
return foo$0(false, y$9);
}
return [y$2 * 10];
return [y$9 * 10];
}
```
@@ -45,11 +45,11 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = 1;
const b$3 = 2;
const x$4 = [a$2, b$3];
return x$4;
function Component$0(props$5) {
const a$6 = 1;
const b$7 = 2;
const x$8 = [a$6, b$7];
return x$8;
}
```
@@ -53,7 +53,7 @@ bb0:
[2] Const mutate b$12_@0[0:10] = Object { }
[3] Call mutate foo$4_@0(mutate a$11_@0, mutate b$12_@0)
[4] Const mutate $13_@0[0:10] = Call mutate foo$4_@0()
[5] If (read $13_@0) then:bb2 else:bb1
[5] If (read $13_@0) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[6] Const mutate $14_@1 = "div"
@@ -113,16 +113,16 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
const b$3 = {};
foo$4(a$2, b$3);
function Component$0(props$10) {
const a$11 = [];
const b$12 = {};
foo$4(a$11, b$12);
bb1: if (foo$4()) {
let _$5 = <div a={a$2}></div>;
const _$15 = <div a={a$11}></div>;
}
foo$4(a$2, b$3);
return <div a={a$2} b={b$3}></div>;
foo$4(a$11, b$12);
return <div a={a$11} b={b$12}></div>;
}
```
@@ -89,14 +89,14 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
const b$3 = {};
foo$4(a$2, b$3);
let _$5 = <div a={a$2}></div>;
function Component$0(props$9) {
const a$10 = [];
const b$11 = {};
foo$4(a$10, b$11);
const _$13 = <div a={a$10}></div>;
foo$4(a$2, b$3);
return <div a={a$2} b={b$3}></div>;
foo$4(a$10, b$11);
return <div a={a$10} b={b$11}></div>;
}
```
@@ -25,7 +25,7 @@ bb0:
[2] Let mutate y$8_@1 = 2
[3] Const mutate $9_@2 = 2
[4] Const mutate $10_@3 = Binary read y$8_@1 === read $9_@2
[5] If (read $10_@3) then:bb2 else:bb1
[5] If (read $10_@3) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[6] Reassign mutate x$11_@0[1:14] = 3
@@ -35,7 +35,7 @@ bb1:
x$17_@0[1:14]: phi(bb2: x$11_@0, bb0: x$7_@0)
[8] Const mutate $12_@4 = 3
[9] Const mutate $14_@5 = Binary read y$8_@1 === read $12_@4
[10] If (read $14_@5) then:bb4 else:bb3
[10] If (read $14_@5) then:bb4 else:bb3 fallthrough=bb3
bb4:
predecessor blocks: bb1
[11] Reassign mutate x$15_@0[1:14] = 5
@@ -107,17 +107,19 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
let y$2 = 2;
bb1: if (y$2 === 2) {
x$1 = 3;
let x$7 = 1;
const y$8 = 2;
bb1: if (y$8 === 2) {
x$7 = 3;
}
bb3: if (y$2 === 3) {
x$1 = 5;
let x$15 = undefined;
bb3: if (y$8 === 3) {
x$15 = 5;
}
y$2 = x$1;
const y$18 = x$15;
}
```
@@ -22,7 +22,7 @@ bb0:
[2] Let mutate y$6_@1 = 2
[3] Const mutate $7_@2 = 2
[4] Const mutate $8_@3 = Binary read y$6_@1 === read $7_@2
[5] If (read $8_@3) then:bb2 else:bb1
[5] If (read $8_@3) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[6] Reassign mutate x$9_@0[1:9] = 3
@@ -75,13 +75,13 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
let y$2 = 2;
bb1: if (y$2 === 2) {
x$1 = 3;
let x$5 = 1;
const y$6 = 2;
bb1: if (y$6 === 2) {
x$5 = 3;
}
y$2 = x$1;
const y$11 = x$5;
}
```
@@ -23,11 +23,11 @@ bb0:
[2] Goto bb1
bb1:
predecessor blocks: bb0 bb4
[3] If (read items$5_@0) then:bb3 else:bb2
[3] If (read items$5_@0) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[4] Let mutate y$7_@1 = 0
[5] If (read cond$4) then:bb5 else:bb4
[5] If (read cond$4) then:bb5 else:bb4 fallthrough=bb4
bb5:
predecessor blocks: bb3
[6] Reassign mutate y$9_@2 = 1
@@ -88,8 +88,8 @@ flowchart TB
## Code
```javascript
function foo$0(cond$1) {
let items$2 = [];
function foo$0(cond$4) {
const items$5 = [];
}
```
@@ -27,7 +27,7 @@ bb1:
x$13_@0[0:13]: phi(bb3: x$7_@0, bb4: x$14_@0)
[5] Const mutate $9_@2 = 10
[6] Const mutate $11_@3[6:8] = Binary read i$8_@1 < read $9_@2
[7] If (read $11_@3) then:bb5 else:bb2
[7] If (read $11_@3) then:bb5 else:bb2 fallthrough=bb2
bb5:
predecessor blocks: bb1
[8] Const mutate $12_@4 = 1
@@ -103,12 +103,12 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
bb2: for (let i$2 = 0; i$2 < 10; update$3()) {
x$1 = x$1 + 1;
let x$7 = 1;
bb2: for (const i$8 = 0; i$8 < 10; update$3()) {
x$7 = x$7 + 1;
}
return x$1;
return x$7;
}
```
@@ -21,7 +21,7 @@ function foo() {
bb0:
[1] Let mutate x$5_@0 = 1
[2] Let mutate y$6_@1 = 2
[3] If (read y$6_@1) then:bb2 else:bb3
[3] If (read y$6_@1) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Let mutate z$7_@2 = Binary read x$5_@0 + read y$6_@1
@@ -81,12 +81,12 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
let y$2 = 2;
bb1: if (y$2) {
let z$3 = x$1 + y$2;
const x$5 = 1;
const y$6 = 2;
bb1: if (y$6) {
const z$7 = x$5 + y$6;
} else {
let z$4 = x$1;
const z$8 = x$5;
}
}
@@ -0,0 +1,195 @@
## Input
```javascript
function foo(a, b, c, d) {
let x = 0;
if (true) {
if (true) {
x = a;
} else {
x = b;
}
x;
} else {
if (true) {
x = c;
} else {
x = d;
}
x;
}
x;
}
```
## HIR
```
bb0:
[1] Let mutate x$13_@0 = 0
[2] Const mutate $14_@1 = true
[3] If (read $14_@1) then:bb2 else:bb6 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Const mutate $15_@2 = true
[5] If (read $15_@2) then:bb4 else:bb5 fallthrough=bb3
bb4:
predecessor blocks: bb2
[6] Reassign mutate x$16_@3[6:17] = read a$9
[7] Goto bb3
bb5:
predecessor blocks: bb2
[8] Reassign mutate x$17_@3[6:17] = read b$10
[9] Goto bb3
bb3:
predecessor blocks: bb4 bb5
x$18_@3[6:17]: phi(bb4: x$16_@3, bb5: x$17_@3)
[10] read x$18_@3
[11] Goto bb1
bb6:
predecessor blocks: bb0
[12] Const mutate $19_@4 = true
[13] If (read $19_@4) then:bb8 else:bb9 fallthrough=bb7
bb8:
predecessor blocks: bb6
[14] Reassign mutate x$20_@3[6:17] = read c$11
[15] Goto bb7
bb9:
predecessor blocks: bb6
[16] Reassign mutate x$21_@3[6:17] = read d$12
[17] Goto bb7
bb7:
predecessor blocks: bb8 bb9
x$22_@3[6:17]: phi(bb8: x$20_@3, bb9: x$21_@3)
[18] read x$22_@3
[19] Goto bb1
bb1:
predecessor blocks: bb3 bb7
x$23_@3[6:17]: phi(bb3: x$18_@3, bb7: x$22_@3)
[20] read x$23_@3
[21] Return
scope3 [6:17]:
- read a$9
- read b$10
- read $15_@2
- read c$11
- read d$12
```
### CFG
```mermaid
flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Let mutate x$13_@0 = 0
[2] Const mutate $14_@1 = true
"]
bb0_instrs --> bb0_terminal(["If (read $14_@1)"])
end
subgraph bb2
bb2_instrs["
[4] Const mutate $15_@2 = true
"]
bb2_instrs --> bb2_terminal(["If (read $15_@2)"])
end
subgraph bb4
bb4_instrs["
[6] Reassign mutate x$16_@3[6:17] = read a$9
"]
bb4_instrs --> bb4_terminal(["Goto"])
end
subgraph bb5
bb5_instrs["
[8] Reassign mutate x$17_@3[6:17] = read b$10
"]
bb5_instrs --> bb5_terminal(["Goto"])
end
subgraph bb3
bb3_instrs["
[10] read x$18_@3
"]
bb3_instrs --> bb3_terminal(["Goto"])
end
subgraph bb6
bb6_instrs["
[12] Const mutate $19_@4 = true
"]
bb6_instrs --> bb6_terminal(["If (read $19_@4)"])
end
subgraph bb8
bb8_instrs["
[14] Reassign mutate x$20_@3[6:17] = read c$11
"]
bb8_instrs --> bb8_terminal(["Goto"])
end
subgraph bb9
bb9_instrs["
[16] Reassign mutate x$21_@3[6:17] = read d$12
"]
bb9_instrs --> bb9_terminal(["Goto"])
end
subgraph bb7
bb7_instrs["
[18] read x$22_@3
"]
bb7_instrs --> bb7_terminal(["Goto"])
end
subgraph bb1
bb1_instrs["
[20] read x$23_@3
"]
bb1_instrs --> bb1_terminal(["Return"])
end
%% Jumps
bb0_terminal -- "then" --> bb2
bb0_terminal -- "else" --> bb6
bb0_terminal -- "fallthrough" --> bb1
bb2_terminal -- "then" --> bb4
bb2_terminal -- "else" --> bb5
bb2_terminal -- "fallthrough" --> bb3
bb4_terminal --> bb3
bb5_terminal --> bb3
bb3_terminal --> bb1
bb6_terminal -- "then" --> bb8
bb6_terminal -- "else" --> bb9
bb6_terminal -- "fallthrough" --> bb7
bb8_terminal --> bb7
bb9_terminal --> bb7
bb7_terminal --> bb1
```
## Code
```javascript
function foo$0(a$9, b$10, c$11, d$12) {
const x$13 = 0;
let x$18 = undefined;
bb1: if (true) {
bb3: if (true) {
x$18 = a$9;
} else {
x$18 = b$10;
}
x$18;
} else {
bb7: if (true) {
x$18 = c$11;
} else {
x$18 = d$12;
}
x$18;
}
x$18;
}
```
@@ -0,0 +1,19 @@
function foo(a, b, c, d) {
let x = 0;
if (true) {
if (true) {
x = a;
} else {
x = b;
}
x;
} else {
if (true) {
x = c;
} else {
x = d;
}
x;
}
x;
}
@@ -25,19 +25,19 @@ bb0:
[2] While test=bb1 loop=bb3 fallthrough=bb2
bb1:
predecessor blocks: bb0 bb5
[3] If (read a$6) then:bb3 else:bb2
[3] If (read a$6) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[4] While test=bb4 loop=bb6 fallthrough=bb5
bb4:
predecessor blocks: bb3 bb8
[5] If (read b$7) then:bb6 else:bb5
[5] If (read b$7) then:bb6 else:bb5 fallthrough=bb5
bb6:
predecessor blocks: bb4
[6] While test=bb7 loop=bb9 fallthrough=bb8
bb7:
predecessor blocks: bb6 bb9
[7] If (read c$8) then:bb9 else:bb8
[7] If (read c$8) then:bb9 else:bb8 fallthrough=bb8
bb9:
predecessor blocks: bb7
[8] Const mutate $13_@1 = 1
@@ -124,17 +124,17 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
let x$4 = 0;
bb2: while (a$1) {
bb5: while (b$2) {
bb8: while (c$3) {
x$4 + 1;
function foo$0(a$6, b$7, c$8) {
const x$9 = 0;
bb2: while (a$6) {
bb5: while (b$7) {
bb8: while (c$8) {
x$9 + 1;
}
}
}
return x$4;
return x$9;
}
```
@@ -0,0 +1,105 @@
## Input
```javascript
function foo(a, b, c, d, e) {
let x = null;
if (a) {
x = b;
} else {
if (c) {
x = d;
}
}
return x;
}
```
## HIR
```
bb0:
[1] Let mutate x$12_@0[1:8] = null
[2] If (read a$7) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Reassign mutate x$13_@0[1:8] = read b$8
[4] Goto bb1
bb3:
predecessor blocks: bb0
[5] If (read c$9) then:bb5 else:bb1 fallthrough=bb1
bb5:
predecessor blocks: bb3
[6] Reassign mutate x$14_@0[1:8] = read d$10
[7] Goto bb1
bb1:
predecessor blocks: bb2 bb5 bb3
x$15_@0[1:8]: phi(bb2: x$13_@0, bb5: x$14_@0, bb3: x$12_@0)
[8] Return read x$15_@0
scope0 [1:8]:
- read b$8
- read d$10
- read c$9
- read a$7
```
### CFG
```mermaid
flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Let mutate x$12_@0[1:8] = null
"]
bb0_instrs --> bb0_terminal(["If (read a$7)"])
end
subgraph bb2
bb2_instrs["
[3] Reassign mutate x$13_@0[1:8] = read b$8
"]
bb2_instrs --> bb2_terminal(["Goto"])
end
subgraph bb3
bb3_terminal(["If (read c$9)"])
end
subgraph bb5
bb5_instrs["
[6] Reassign mutate x$14_@0[1:8] = read d$10
"]
bb5_instrs --> bb5_terminal(["Goto"])
end
subgraph bb1
bb1_terminal(["Return read x$15_@0"])
end
%% Jumps
bb0_terminal -- "then" --> bb2
bb0_terminal -- "else" --> bb3
bb0_terminal -- "fallthrough" --> bb1
bb2_terminal --> bb1
bb3_terminal -- "then" --> bb5
bb3_terminal -- "else" --> bb1
bb5_terminal --> bb1
```
## Code
```javascript
function foo$0(a$7, b$8, c$9, d$10, e$11) {
let x$12 = null;
bb1: if (a$7) {
x$12 = b$8;
} else {
if (c$9) {
x$12 = d$10;
}
}
return x$12;
}
```
@@ -0,0 +1,11 @@
function foo(a, b, c, d, e) {
let x = null;
if (a) {
x = b;
} else {
if (c) {
x = d;
}
}
return x;
}
@@ -72,11 +72,11 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = [];
const b$3 = {};
let c$4 = new Foo$5(a$2, b$3);
return c$4;
function Component$0(props$6) {
const a$7 = [];
const b$8 = {};
const c$9 = new Foo$5(a$7, b$8);
return c$9;
}
```
@@ -26,7 +26,7 @@ bb0:
[2] Let mutate y$7_@0[1:10] = 2
[3] Const mutate $8_@2 = 1
[4] Const mutate $9_@3 = Binary read x$6_@0 > read $8_@2
[5] If (read $9_@3) then:bb2 else:bb3
[5] If (read $9_@3) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[6] Reassign mutate x$10_@0[1:10] = 2
@@ -91,19 +91,19 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
let y$2 = 2;
bb1: if (x$1 > 1) {
x$1 = 2;
let x$6 = 1;
let y$7 = 2;
bb1: if (x$6 > 1) {
x$6 = 2;
} else {
y$2 = 3;
y$7 = 3;
}
let t$5 = {
x: x$1,
y: y$2,
const t$14 = {
x: x$6,
y: y$7,
};
return t$5;
return t$14;
}
```
@@ -45,14 +45,14 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
const a$2 = 1;
const b$3 = 2;
const x$4 = {
a: a$2,
b: b$3,
function Component$0(props$5) {
const a$6 = 1;
const b$7 = 2;
const x$8 = {
a: a$6,
b: b$7,
};
return x$4;
return x$8;
}
```
@@ -47,12 +47,12 @@ flowchart TB
```javascript
function foo$0() {
const x$1 = [];
const y$2 = {
x: x$1,
const x$4 = [];
const y$5 = {
x: x$4,
};
y$2.x.push([]);
return y$2;
y$5.x.push([]);
return y$5;
}
```
@@ -44,10 +44,10 @@ flowchart TB
```javascript
function foo$0() {
const x$1 = [];
const y$2 = {};
y$2.x = x$1;
return y$2;
const x$3 = [];
const y$4 = {};
y$4.x = x$3;
return y$4;
}
```
@@ -0,0 +1,63 @@
## Input
```javascript
function foo(a, b, c) {
let x = 0;
x = a;
x = b;
x = c;
return x;
}
```
## HIR
```
bb0:
[1] Let mutate x$8_@0 = 0
[2] Reassign mutate x$9_@1 = read a$5
[3] Reassign mutate x$10_@2 = read b$6
[4] Reassign mutate x$11_@3 = read c$7
[5] Return read x$11_@3
scope1 [2:3]:
- read a$5
scope2 [3:4]:
- read b$6
scope3 [4:5]:
- read c$7
```
### CFG
```mermaid
flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Let mutate x$8_@0 = 0
[2] Reassign mutate x$9_@1 = read a$5
[3] Reassign mutate x$10_@2 = read b$6
[4] Reassign mutate x$11_@3 = read c$7
"]
bb0_instrs --> bb0_terminal(["Return read x$11_@3"])
end
%% Jumps
%% empty
```
## Code
```javascript
function foo$0(a$5, b$6, c$7) {
const x$8 = 0;
const x$9 = a$5;
const x$10 = b$6;
const x$11 = c$7;
return x$11;
}
```
@@ -0,0 +1,7 @@
function foo(a, b, c) {
let x = 0;
x = a;
x = b;
x = c;
return x;
}
@@ -20,7 +20,7 @@ bb0:
[1] Let mutate x$4_@0[1:7] = 1
[2] Const mutate $5_@1 = 1
[3] Const mutate $6_@2 = Binary read x$4_@0 === read $5_@1
[4] If (read $6_@2) then:bb2 else:bb1
[4] If (read $6_@2) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Reassign mutate x$7_@0[1:7] = 2
@@ -67,12 +67,12 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
bb1: if (x$1 === 1) {
x$1 = 2;
let x$4 = 1;
bb1: if (x$4 === 1) {
x$4 = 2;
}
return x$1;
return x$4;
}
```
@@ -49,7 +49,7 @@ function log$0() {}
```
bb0:
[1] Let mutate str$6_@0[1:8] = ""
[2] If (read cond$5) then:bb2 else:bb3
[2] If (read cond$5) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[3] Let mutate str$7_@1 = "other test"
@@ -110,16 +110,16 @@ flowchart TB
## Code
```javascript
function Foo$0(cond$1) {
let str$2 = "";
bb1: if (cond$1) {
let str$3 = "other test";
log$4(str$3);
function Foo$0(cond$5) {
let str$6 = "";
bb1: if (cond$5) {
const str$7 = "other test";
log$4(str$7);
} else {
str$2 = "fallthrough test";
str$6 = "fallthrough test";
}
log$4(str$2);
log$4(str$6);
}
```
@@ -0,0 +1,191 @@
## Input
```javascript
function foo(a, b, c, d) {
let x = 0;
if (true) {
if (true) {
x = a;
} else {
x = b;
}
x;
} else {
if (true) {
x = c;
} else {
x = d;
}
x;
}
// note: intentionally no phi here so that there are two distinct phis above
}
```
## HIR
```
bb0:
[1] Let mutate x$13_@0 = 0
[2] Const mutate $14_@1 = true
[3] If (read $14_@1) then:bb2 else:bb6 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Const mutate $15_@2 = true
[5] If (read $15_@2) then:bb4 else:bb5 fallthrough=bb3
bb4:
predecessor blocks: bb2
[6] Reassign mutate x$16_@3[6:9] = read a$9
[7] Goto bb3
bb5:
predecessor blocks: bb2
[8] Reassign mutate x$17_@3[6:9] = read b$10
[9] Goto bb3
bb3:
predecessor blocks: bb4 bb5
x$18_@3[6:9]: phi(bb4: x$16_@3, bb5: x$17_@3)
[10] read x$18_@3
[11] Goto bb1
bb6:
predecessor blocks: bb0
[12] Const mutate $19_@4 = true
[13] If (read $19_@4) then:bb8 else:bb9 fallthrough=bb7
bb8:
predecessor blocks: bb6
[14] Reassign mutate x$20_@5[14:17] = read c$11
[15] Goto bb7
bb9:
predecessor blocks: bb6
[16] Reassign mutate x$21_@5[14:17] = read d$12
[17] Goto bb7
bb7:
predecessor blocks: bb8 bb9
x$22_@5[14:17]: phi(bb8: x$20_@5, bb9: x$21_@5)
[18] read x$22_@5
[19] Goto bb1
bb1:
predecessor blocks: bb3 bb7
[20] Return
scope3 [6:9]:
- read a$9
- read b$10
scope5 [14:17]:
- read c$11
- read d$12
```
### CFG
```mermaid
flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Let mutate x$13_@0 = 0
[2] Const mutate $14_@1 = true
"]
bb0_instrs --> bb0_terminal(["If (read $14_@1)"])
end
subgraph bb2
bb2_instrs["
[4] Const mutate $15_@2 = true
"]
bb2_instrs --> bb2_terminal(["If (read $15_@2)"])
end
subgraph bb4
bb4_instrs["
[6] Reassign mutate x$16_@3[6:9] = read a$9
"]
bb4_instrs --> bb4_terminal(["Goto"])
end
subgraph bb5
bb5_instrs["
[8] Reassign mutate x$17_@3[6:9] = read b$10
"]
bb5_instrs --> bb5_terminal(["Goto"])
end
subgraph bb3
bb3_instrs["
[10] read x$18_@3
"]
bb3_instrs --> bb3_terminal(["Goto"])
end
subgraph bb6
bb6_instrs["
[12] Const mutate $19_@4 = true
"]
bb6_instrs --> bb6_terminal(["If (read $19_@4)"])
end
subgraph bb8
bb8_instrs["
[14] Reassign mutate x$20_@5[14:17] = read c$11
"]
bb8_instrs --> bb8_terminal(["Goto"])
end
subgraph bb9
bb9_instrs["
[16] Reassign mutate x$21_@5[14:17] = read d$12
"]
bb9_instrs --> bb9_terminal(["Goto"])
end
subgraph bb7
bb7_instrs["
[18] read x$22_@5
"]
bb7_instrs --> bb7_terminal(["Goto"])
end
subgraph bb1
bb1_terminal(["Return"])
end
%% Jumps
bb0_terminal -- "then" --> bb2
bb0_terminal -- "else" --> bb6
bb0_terminal -- "fallthrough" --> bb1
bb2_terminal -- "then" --> bb4
bb2_terminal -- "else" --> bb5
bb2_terminal -- "fallthrough" --> bb3
bb4_terminal --> bb3
bb5_terminal --> bb3
bb3_terminal --> bb1
bb6_terminal -- "then" --> bb8
bb6_terminal -- "else" --> bb9
bb6_terminal -- "fallthrough" --> bb7
bb8_terminal --> bb7
bb9_terminal --> bb7
bb7_terminal --> bb1
```
## Code
```javascript
function foo$0(a$9, b$10, c$11, d$12) {
const x$13 = 0;
bb1: if (true) {
let x$16 = undefined;
bb3: if (true) {
x$16 = a$9;
} else {
x$16 = b$10;
}
x$16;
} else {
let x$20 = undefined;
bb7: if (true) {
x$20 = c$11;
} else {
x$20 = d$12;
}
x$20;
}
}
```
@@ -0,0 +1,19 @@
function foo(a, b, c, d) {
let x = 0;
if (true) {
if (true) {
x = a;
} else {
x = b;
}
x;
} else {
if (true) {
x = c;
} else {
x = d;
}
x;
}
// note: intentionally no phi here so that there are two distinct phis above
}
@@ -23,7 +23,7 @@ bb0:
[1] Let mutate y$5_@0 = 2
[2] Const mutate $6_@1 = 1
[3] Const mutate $7_@2 = Binary read y$5_@0 > read $6_@1
[4] If (read $7_@2) then:bb2 else:bb3
[4] If (read $7_@2) then:bb2 else:bb3 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Reassign mutate y$8_@3[5:10] = 1
@@ -89,14 +89,15 @@ flowchart TB
```javascript
function foo$0() {
let y$1 = 2;
bb1: if (y$1 > 1) {
y$1 = 1;
const y$5 = 2;
let y$8 = undefined;
bb1: if (y$5 > 1) {
y$8 = 1;
} else {
y$1 = 2;
y$8 = 2;
}
let x$4 = y$1;
const x$11 = y$8;
}
```
@@ -40,8 +40,8 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
let y$2 = 2;
const x$3 = 1;
const y$4 = 2;
}
```
@@ -19,7 +19,7 @@ function foo() {
bb0:
[1] Let mutate x$4_@0 = 1
[2] Let mutate y$5_@1 = 2
[3] If (read y$5_@1) then:bb2 else:bb1
[3] If (read y$5_@1) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[4] Let mutate z$6_@2 = Binary read x$4_@0 + read y$5_@1
@@ -65,10 +65,10 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
let y$2 = 2;
bb1: if (y$2) {
let z$3 = x$1 + y$2;
const x$4 = 1;
const y$5 = 2;
bb1: if (y$5) {
const z$6 = x$4 + y$5;
}
}
@@ -37,6 +37,7 @@ bb0:
Case read $14_@4: bb5
Case read $12_@2: bb3
Default: bb2
Fallthrough: bb1
bb5:
predecessor blocks: bb0
[7] Const mutate $15_@5 = 1
@@ -130,24 +131,25 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
bb1: switch (x$1) {
case x$1 === 1: {
x$1 = x$1 + 1;
const x$10 = 1;
let x$16 = undefined;
bb1: switch (x$10) {
case x$10 === 1: {
x$16 = x$10 + 1;
break bb1;
}
case x$1 === 2: {
x$1 = x$1 + 2;
case x$10 === 2: {
x$16 = x$10 + 2;
break bb1;
}
default: {
x$1 = x$1 + 3;
x$16 = x$10 + 3;
}
}
let y$9 = x$1;
const y$22 = x$16;
}
```
@@ -19,7 +19,7 @@ bb0:
[1] Let mutate x$4_@0[1:7] = 1
[2] Const mutate $5_@1 = 1
[3] Const mutate $6_@2 = Binary read x$4_@0 === read $5_@1
[4] If (read $6_@2) then:bb2 else:bb1
[4] If (read $6_@2) then:bb2 else:bb1 fallthrough=bb1
bb2:
predecessor blocks: bb0
[5] Reassign mutate x$7_@0[1:7] = 2
@@ -66,12 +66,12 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
bb1: if (x$1 === 1) {
x$1 = 2;
let x$4 = 1;
bb1: if (x$4 === 1) {
x$4 = 2;
}
throw x$1;
throw x$4;
}
```
@@ -23,7 +23,7 @@ bb1:
predecessor blocks: bb0 bb3
[3] Const mutate $6_@1 = 10
[4] Const mutate $8_@2[4:6] = Binary read x$5_@0 < read $6_@1
[5] If (read $8_@2) then:bb3 else:bb2
[5] If (read $8_@2) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[6] Const mutate $9_@3 = 1
@@ -82,12 +82,12 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
bb2: while (x$1 < 10) {
x$1 + 1;
const x$5 = 1;
bb2: while (x$5 < 10) {
x$5 + 1;
}
return x$1;
return x$5;
}
```
@@ -24,7 +24,7 @@ bb1:
x$7_@0[0:9]: phi(bb0: x$5_@0, bb3: x$10_@0)
[3] Const mutate $6_@1 = 10
[4] Const mutate $8_@2[4:6] = Binary read x$7_@0 < read $6_@1
[5] If (read $8_@2) then:bb3 else:bb2
[5] If (read $8_@2) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[6] Const mutate $9_@3 = 1
@@ -80,12 +80,12 @@ flowchart TB
```javascript
function foo$0() {
let x$1 = 1;
bb2: while (x$1 < 10) {
x$1 = x$1 + 1;
let x$5 = 1;
bb2: while (x$5 < 10) {
x$5 = x$5 + 1;
}
return x$1;
return x$5;
}
```
@@ -42,6 +42,7 @@ bb0:
Case read $13_@2: bb6
Default: bb1
Case read $12_@1: bb2
Fallthrough: bb1
bb6:
predecessor blocks: bb0
[7] Call mutate x$10_@0.push(read props$9.p2)
@@ -121,17 +122,17 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
let x$2 = [];
let y$3 = undefined;
bb1: switch (props$1.p0) {
function Component$0(props$9) {
const x$10 = [];
let y$11 = undefined;
bb1: switch (props$9.p0) {
case 1: {
break bb1;
}
case true: {
x$2.push(props$1.p2);
y$3 = [];
x$10.push(props$9.p2);
y$11 = [];
break bb1;
}
@@ -140,13 +141,13 @@ function Component$0(props$1) {
}
case false: {
y$3 = x$2;
y$11 = x$10;
}
}
const child$7 = <Component$0 data={x$2}></Component$0>;
y$3.push(props$1.p4);
return <Component$0 data={y$3}>{child$7}</Component$0>;
const child$19 = <Component$0 data={x$10}></Component$0>;
y$11.push(props$9.p4);
return <Component$0 data={y$11}>{child$19}</Component$0>;
}
```
@@ -51,6 +51,7 @@ bb0:
Case read $12_@2: bb4
Case read $11_@1: bb3
Default: bb2
Fallthrough: bb1
bb10:
predecessor blocks: bb0
[9] Reassign mutate y$17_@7 = 0
@@ -159,15 +160,15 @@ flowchart TB
## Code
```javascript
function foo$0(x$1) {
let y$2 = undefined;
bb1: switch (x$1) {
function foo$0(x$9) {
const y$10 = undefined;
bb1: switch (x$9) {
case 0: {
y$2 = 0;
const y$17 = 0;
}
case 1: {
y$2 = 1;
const y$18 = 1;
break bb1;
}
@@ -176,20 +177,20 @@ function foo$0(x$1) {
}
case 3: {
y$2 = 3;
const y$19 = 3;
break bb1;
}
case 4: {
y$2 = 4;
const y$20 = 4;
}
case 5: {
y$2 = 5;
const y$21 = 5;
}
default: {
y$2 = 0;
const y$22 = 0;
}
}
}
@@ -36,6 +36,7 @@ bb0:
Case read $12_@2: bb4
Case read $11_@1: bb2
Default: bb1
Fallthrough: bb1
bb4:
predecessor blocks: bb0
[6] Call mutate x$9_@0.push(read props$8.p2)
@@ -116,24 +117,24 @@ flowchart TB
## Code
```javascript
function Component$0(props$1) {
let x$2 = [];
let y$3 = undefined;
bb1: switch (props$1.p0) {
function Component$0(props$8) {
const x$9 = [];
let y$10 = undefined;
bb1: switch (props$8.p0) {
case true: {
x$2.push(props$1.p2);
x$2.push(props$1.p3);
y$3 = [];
x$9.push(props$8.p2);
x$9.push(props$8.p3);
const y$13 = [];
}
case false: {
y$3 = x$2;
y$10 = x$9;
}
}
const child$6 = <Component$0 data={x$2}></Component$0>;
y$3.push(props$1.p4);
return <Component$0 data={y$3}>{child$6}</Component$0>;
const child$19 = <Component$0 data={x$9}></Component$0>;
y$10.push(props$8.p4);
return <Component$0 data={y$10}>{child$19}</Component$0>;
}
```
@@ -18,7 +18,7 @@ bb0:
[1] While test=bb1 loop=bb2 fallthrough=bb2
bb1:
predecessor blocks: bb0
[2] If (read a$3) then:bb2 else:bb2
[2] If (read a$3) then:bb2 else:bb2 fallthrough=bb2
bb2:
predecessor blocks: bb1
[3] Return read b$4
@@ -52,11 +52,11 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2) {
bb2: while (a$1) {
function foo$0(a$3, b$4) {
bb2: while (a$3) {
break;
}
return b$2;
return b$4;
}
```
@@ -22,10 +22,10 @@ bb0:
[1] While test=bb1 loop=bb3 fallthrough=bb2
bb1:
predecessor blocks: bb0 bb5 bb4
[2] If (read a$5) then:bb3 else:bb2
[2] If (read a$5) then:bb3 else:bb2 fallthrough=bb2
bb3:
predecessor blocks: bb1
[3] If (read b$6) then:bb5 else:bb4
[3] If (read b$6) then:bb5 else:bb4 fallthrough=bb4
bb5:
predecessor blocks: bb3
[4] Goto(Continue) bb1
@@ -86,15 +86,15 @@ flowchart TB
## Code
```javascript
function foo$0(a$1, b$2, c$3, d$4) {
bb2: while (a$1) {
bb4: if (b$2) {
function foo$0(a$5, b$6, c$7, d$8) {
bb2: while (a$5) {
bb4: if (b$6) {
continue;
}
c$3();
c$7();
}
d$4();
d$8();
}
```
+99 -61
View File
@@ -48,61 +48,58 @@ describe("React Forget (HIR version)", () => {
}
}
const ast = parser.parse(input, {
sourceFilename: file,
plugins: ["typescript", "jsx"],
});
let items: Array<[string, string, string]> = [];
traverse(ast, {
FunctionDeclaration: {
enter(nodePath) {
const { ir } = run(nodePath, {
eliminateRedundantPhi: true,
inferReferenceEffects: true,
inferMutableRanges: true,
inferReactiveScopeVariables: true,
inferReactiveScopes: true,
inferReactiveScopeDependencies: true,
leaveSSA: false,
codegen: false,
});
let items: Array<[string, string, string]> | null = null;
let error: Error | null = null;
try {
items = transform(input, file);
} catch (e) {
error = e;
}
let outputs: Array<string>;
// Print the HIR before leaving SSA.
const textHIR = printFunction(ir);
const visualization = visualizeHIRMermaid(ir);
const expectError = file.startsWith("error.");
if (expectError) {
if (error === null) {
throw new Error(
`Expected an error to be thrown for fixture: '${file}', remove the 'error.' prefix if an error is not expected.`
);
} else {
outputs = [formatErrorOutput(error)];
}
} else {
if (error !== null) {
console.error(error);
throw new Error(
`Expected fixture '${file}' to succeed but it failed with error: '${error.message}'. See console output for details.`
);
}
if (items === null || items.length === 0) {
throw new Error(`Expected at least one output for file '${file}'.`);
}
outputs = formatOutput(items);
}
return `
## Input
const { ast } = run(nodePath, {
eliminateRedundantPhi: true,
inferReferenceEffects: true,
inferMutableRanges: true,
inferReactiveScopeVariables: true,
inferReactiveScopes: true,
inferReactiveScopeDependencies: true,
leaveSSA: true,
codegen: true,
});
${wrapWithTripleBackticks(input, "javascript")}
invariant(
ast !== null,
"ast is null when codegen option is enabled"
);
const text = prettier.format(
generate(ast).code.replace("\n\n", "\n"),
{
semi: true,
parser: "babel-ts",
}
);
items.push([textHIR, text, visualization]);
},
},
});
invariant(
items.length > 0,
"Visitor failed, check that the input has a function"
);
const outputs = items.map(([hir, text, visualization]) => {
return `
${outputs.join("\n")}
`;
}
);
});
function formatErrorOutput(error: Error): string {
return `
## Error
${wrapWithTripleBackticks(error.message)}
`;
}
function formatOutput(items: Array<[string, string, string]>): Array<string> {
return items.map(([hir, text, visualization]) => {
return `
## HIR
${wrapWithTripleBackticks(hir)}
@@ -115,14 +112,55 @@ ${wrapWithTripleBackticks(visualization, "mermaid")}
${wrapWithTripleBackticks(text, "javascript")}
`.trim();
});
return `
## Input
});
}
${wrapWithTripleBackticks(input, "javascript")}
function transform(
text: string,
file: string
): Array<[string, string, string]> {
const items: Array<[string, string, string]> = [];
const ast = parser.parse(text, {
sourceFilename: file,
plugins: ["typescript", "jsx"],
});
traverse(ast, {
FunctionDeclaration: {
enter(nodePath) {
const { ir } = run(nodePath, {
eliminateRedundantPhi: true,
inferReferenceEffects: true,
inferMutableRanges: true,
inferReactiveScopeVariables: true,
inferReactiveScopes: true,
inferReactiveScopeDependencies: true,
leaveSSA: false,
codegen: false,
});
${outputs.join("\n")}
`;
}
);
});
// Print the HIR before leaving SSA.
const textHIR = printFunction(ir);
const visualization = visualizeHIRMermaid(ir);
const { ast } = run(nodePath, {
eliminateRedundantPhi: true,
inferReferenceEffects: true,
inferMutableRanges: true,
inferReactiveScopeVariables: true,
inferReactiveScopes: true,
inferReactiveScopeDependencies: true,
leaveSSA: true,
codegen: true,
});
invariant(ast !== null, "ast is null when codegen option is enabled");
const text = prettier.format(generate(ast).code.replace("\n\n", "\n"), {
semi: true,
parser: "babel-ts",
});
items.push([textHIR, text, visualization]);
},
},
});
return items;
}
+1 -1
View File
@@ -34,7 +34,7 @@ import { inferReactiveScopeDependencies } from "./HIR/InferReactiveScopeDependen
import { inferReactiveScopes } from "./HIR/InferReactiveScopes";
import { inferReactiveScopeVariables } from "./HIR/InferReactiveScopeVariables";
import inferReferenceEffects from "./HIR/InferReferenceEffects";
import leaveSSA from "./HIR/LeaveSSA";
import { leaveSSA } from "./HIR/LeaveSSA";
import printHIR from "./HIR/PrintHIR";
function parseFunctions(