mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Support assignment expressions in value blocks
Enables support for assignment expressions in value blocks (which includes in loop init/test/update blocks). This was pretty straightforward, the main changes are: * During PropagateScopeDependencies, we currently record scope reassignments based on `Identifier` object identity. In the case where a variable is reassigned in multiple control-flow paths of a value block, however, there can be multiple object identities. So we now de-dupe reassignments based on identifier id. * MergeOverlappingScopes now treats value blocks as regular blocks, allowing it to correctly merge scopes from the value with other scopes from the outer block. Otherwise this is mostly just lots of tests. Note that there is an outstanding todo, which is that we currently error for ternaries and logicals whose value is unused (eg `cond ? (x = 1) : null`). I'll address that in a follow-up.
This commit is contained in:
@@ -24,6 +24,10 @@ module.exports = {
|
||||
// like invariant.
|
||||
"no-fallthrough": "off",
|
||||
|
||||
// Low-value: this fires even for declarations that capture references which wouldn't be as
|
||||
// obvious if the declaration was lifted to the parent root
|
||||
"no-inner-declarations": "off",
|
||||
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
|
||||
// Explicitly casting to/through any is sometimes required, often for error messages to
|
||||
|
||||
@@ -1198,17 +1198,6 @@ function lowerExpression(
|
||||
const expr = exprPath as NodePath<t.AssignmentExpression>;
|
||||
const operator = expr.node.operator;
|
||||
|
||||
if (builder.currentBlockKind() === "value") {
|
||||
// try lowering the RHS in case it also contains errors
|
||||
lowerExpressionToTemporary(builder, expr.get("right"));
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerExpression) Handle AssignmentExpression within a LogicalExpression or ConditionalExpression`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
nodePath: expr.parentPath,
|
||||
});
|
||||
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
|
||||
}
|
||||
|
||||
if (operator === "=") {
|
||||
const left = expr.get("left");
|
||||
return lowerAssignment(
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
Place,
|
||||
ReactiveBlock,
|
||||
ReactiveFunction,
|
||||
ReactiveInstruction,
|
||||
ReactiveScope,
|
||||
ScopeId,
|
||||
} from "../HIR";
|
||||
@@ -98,9 +99,6 @@ import { ReactiveFunctionVisitor, visitReactiveFunction } from "./visitors";
|
||||
*/
|
||||
export function mergeOverlappingReactiveScopes(fn: ReactiveFunction): void {
|
||||
const context = new Context();
|
||||
// context.enter(() => {
|
||||
// visitBlock(context, fn.body);
|
||||
// });
|
||||
visitReactiveFunction(fn, new Visitor(), context);
|
||||
context.complete();
|
||||
}
|
||||
@@ -120,6 +118,21 @@ class Visitor extends ReactiveFunctionVisitor<Context> {
|
||||
this.traverseBlock(block, state);
|
||||
});
|
||||
}
|
||||
override visitInstruction(
|
||||
instruction: ReactiveInstruction,
|
||||
state: Context
|
||||
): void {
|
||||
if (
|
||||
instruction.value.kind === "ConditionalExpression" ||
|
||||
instruction.value.kind === "LogicalExpression"
|
||||
) {
|
||||
state.enter(() => {
|
||||
super.visitInstruction(instruction, state);
|
||||
});
|
||||
} else {
|
||||
super.visitInstruction(instruction, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BlockScope {
|
||||
|
||||
@@ -317,7 +317,10 @@ class Context {
|
||||
this.currentScope != null &&
|
||||
place.identifier.scope != null &&
|
||||
declaration !== undefined &&
|
||||
declaration.scope !== place.identifier.scope
|
||||
declaration.scope !== place.identifier.scope &&
|
||||
!Array.from(this.currentScope.reassignments).some(
|
||||
(ident) => ident.id === place.identifier.id
|
||||
)
|
||||
) {
|
||||
this.currentScope.reassignments.add(place.identifier);
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function ternary(props) {
|
||||
let x = 0;
|
||||
const y = props.a ? (x = 1) : (x = 2);
|
||||
return x + y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function ternary(props) {
|
||||
let x = undefined;
|
||||
|
||||
const y = props.a ? ((x = 1), 1) : ((x = 2), 2);
|
||||
return x + y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @skip
|
||||
function ternary(props) {
|
||||
let x = 0;
|
||||
const y = props.a ? (x = 1) : (x = 2);
|
||||
|
||||
@@ -2,12 +2,26 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = 0;
|
||||
while (x > props.min && x < props.max) {
|
||||
x *= 2;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = 0;
|
||||
while (x > props.min && x < props.max) {
|
||||
x = x * 2;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @skip
|
||||
function foo(props) {
|
||||
let x = 0;
|
||||
while (x > props.min && x < props.max) {
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? (({ x } = { x: {} }), ([x] = [[]]), x.push(props.foo))
|
||||
: null;
|
||||
console.log(_);
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $35[1:33] = Array []
|
||||
[2] store $37[2:33] = StoreLocal Let mutate x$36[2:33] = capture $35[1:33]
|
||||
[3] mutate $38[3:33] = LoadLocal capture x$36[2:33]
|
||||
[4] mutate $39 = LoadLocal read props$34
|
||||
[5] mutate $40 = PropertyLoad read $39.bar
|
||||
[6] mutate $41 = PropertyCall mutate $38[3:33].push(read $40)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
[8] mutate $42 = LoadLocal read props$34
|
||||
[9] mutate $43 = PropertyLoad read $42.cond
|
||||
[10] Branch (read $43) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[14] store $48[14:33] = Array []
|
||||
[15] store $49[15:33] = Array [capture $48[14:33]]
|
||||
[16] store $51[16:33] = Destructure Reassign [ mutate x$36[16:33] ] = capture $49[15:33]
|
||||
[17] mutate $52[17:33] = LoadLocal capture x$36[16:33]
|
||||
[18] mutate $53 = LoadLocal read props$34
|
||||
[19] mutate $54 = PropertyLoad read $53.foo
|
||||
[20] mutate $55[20:30] = PropertyCall mutate $52[17:33].push(read $54)
|
||||
[21] store $57[21:30] = StoreLocal Const mutate $56[7:30] = capture $55[20:30]
|
||||
[22] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[23] mutate $58[23:30]:TPrimitive = null
|
||||
[24] store $60[24:30]:TPrimitive = StoreLocal Const mutate $56[7:30] = read $58[23:30]:TPrimitive
|
||||
[25] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$63[7:30]:TPhi: phi(bb3: $56, bb4: $59)
|
||||
x$36[2:33]:TPhi: phi(bb3: x$36, bb4: x$36)
|
||||
[26] store $62[26:30] = StoreLocal Const mutate _$61[26:30] = capture $56[7:30]
|
||||
[27] mutate $64 = Global console
|
||||
[28] mutate $65[28:30] = LoadLocal capture _$61[26:30]
|
||||
[29] mutate $66 = PropertyCall read $64.log(mutate $65[28:30])
|
||||
[30] mutate $67:TFunction = Global mut
|
||||
[31] mutate $68[31:33] = LoadLocal capture x$36[2:33]
|
||||
[32] mutate $70 = Call read $67:TFunction(mutate $68[31:33])
|
||||
[33] mutate $71 = LoadLocal capture x$36[2:33]
|
||||
[34] Return freeze $71
|
||||
```
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? (({ x } = { x: {} }), ([x] = [[]]), x.push(props.foo))
|
||||
: null;
|
||||
console.log(_);
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? (({ x } = { x: {} }), ([x] = [[]]), x.push(props.foo))
|
||||
: null;
|
||||
console.log(_);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $32[1:7] = Array []
|
||||
[2] store $34[2:7] = StoreLocal Let mutate x$33[2:7] = capture $32[1:7]
|
||||
[3] mutate $35[3:7] = LoadLocal capture x$33[2:7]
|
||||
[4] mutate $36 = LoadLocal read props$31
|
||||
[5] mutate $37 = PropertyLoad read $36.bar
|
||||
[6] mutate $38 = PropertyCall mutate $35[3:7].push(read $37)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
[8] mutate $39 = LoadLocal read props$31
|
||||
[9] mutate $40 = PropertyLoad read $39.cond
|
||||
[10] Branch (read $40) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[14] store $45[14:21] = Array []
|
||||
[15] store $46[15:21] = Array [capture $45[14:21]]
|
||||
[16] store $48[16:21] = Destructure Reassign [ mutate x$33[16:21] ] = capture $46[15:21]
|
||||
[17] mutate $49[17:21] = LoadLocal capture x$33[16:21]
|
||||
[18] mutate $50 = LoadLocal read props$31
|
||||
[19] mutate $51 = PropertyLoad read $50.foo
|
||||
[20] mutate $52[20:30] = PropertyCall mutate $49[17:21].push(read $51)
|
||||
[21] store $54[21:30] = StoreLocal Const mutate $53[7:30] = capture $52[20:30]
|
||||
[22] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[23] mutate $55[23:30]:TPrimitive = null
|
||||
[24] store $57[24:30]:TPrimitive = StoreLocal Const mutate $53[7:30] = read $55[23:30]:TPrimitive
|
||||
[25] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$60[7:30]:TPhi: phi(bb3: $53, bb4: $56)
|
||||
x$33:TPhi: phi(bb3: x$33, bb4: x$33)
|
||||
[26] store $59[26:30] = StoreLocal Const mutate _$58[26:30] = capture $53[7:30]
|
||||
[27] mutate $61 = Global console
|
||||
[28] mutate $62[28:30] = LoadLocal capture _$58[26:30]
|
||||
[29] mutate $63 = PropertyCall read $61.log(mutate $62[28:30])
|
||||
[30] mutate $64 = LoadLocal capture x$33
|
||||
[31] Return freeze $64
|
||||
```
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? (({ x } = { x: {} }), ([x] = [[]]), x.push(props.foo))
|
||||
: null;
|
||||
console.log(_);
|
||||
return x;
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;
|
||||
console.log(_);
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $35[1:33] = Array []
|
||||
[2] store $37[2:33] = StoreLocal Let mutate x$36[2:33] = capture $35[1:33]
|
||||
[3] mutate $38[3:33] = LoadLocal capture x$36[2:33]
|
||||
[4] mutate $39 = LoadLocal read props$34
|
||||
[5] mutate $40 = PropertyLoad read $39.bar
|
||||
[6] mutate $41 = PropertyCall mutate $38[3:33].push(read $40)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
[8] mutate $42 = LoadLocal read props$34
|
||||
[9] mutate $43 = PropertyLoad read $42.cond
|
||||
[10] Branch (read $43) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[14] store $48[14:33] = Array []
|
||||
[15] store $50[15:33] = StoreLocal Reassign mutate x$36[15:33] = capture $48[14:33]
|
||||
[17] mutate $52[17:33] = LoadLocal capture x$36[15:33]
|
||||
[18] mutate $53 = LoadLocal read props$34
|
||||
[19] mutate $54 = PropertyLoad read $53.foo
|
||||
[20] mutate $55[20:30] = PropertyCall mutate $52[17:33].push(read $54)
|
||||
[21] store $57[21:30] = StoreLocal Const mutate $56[7:30] = capture $55[20:30]
|
||||
[22] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[23] mutate $58[23:30]:TPrimitive = null
|
||||
[24] store $60[24:30]:TPrimitive = StoreLocal Const mutate $56[7:30] = read $58[23:30]:TPrimitive
|
||||
[25] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$63[7:30]:TPhi: phi(bb3: $56, bb4: $59)
|
||||
x$36[2:33]:TPhi: phi(bb3: x$36, bb4: x$36)
|
||||
[26] store $62[26:30] = StoreLocal Const mutate _$61[26:30] = capture $56[7:30]
|
||||
[27] mutate $64 = Global console
|
||||
[28] mutate $65[28:30] = LoadLocal capture _$61[26:30]
|
||||
[29] mutate $66 = PropertyCall read $64.log(mutate $65[28:30])
|
||||
[30] mutate $67:TFunction = Global mut
|
||||
[31] mutate $68[31:33] = LoadLocal capture x$36[2:33]
|
||||
[32] mutate $70 = Call read $67:TFunction(mutate $68[31:33])
|
||||
[33] mutate $71 = LoadLocal capture x$36[2:33]
|
||||
[34] Return freeze $71
|
||||
```
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;
|
||||
console.log(_);
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;
|
||||
console.log(_);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $32[1:7] = Array []
|
||||
[2] store $34[2:7] = StoreLocal Let mutate x$33[2:7] = capture $32[1:7]
|
||||
[3] mutate $35[3:7] = LoadLocal capture x$33[2:7]
|
||||
[4] mutate $36 = LoadLocal read props$31
|
||||
[5] mutate $37 = PropertyLoad read $36.bar
|
||||
[6] mutate $38 = PropertyCall mutate $35[3:7].push(read $37)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
[8] mutate $39 = LoadLocal read props$31
|
||||
[9] mutate $40 = PropertyLoad read $39.cond
|
||||
[10] Branch (read $40) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[14] store $45[14:21] = Array []
|
||||
[15] store $47[15:21] = StoreLocal Reassign mutate x$33[15:21] = capture $45[14:21]
|
||||
[17] mutate $49[17:21] = LoadLocal capture x$33[15:21]
|
||||
[18] mutate $50 = LoadLocal read props$31
|
||||
[19] mutate $51 = PropertyLoad read $50.foo
|
||||
[20] mutate $52[20:30] = PropertyCall mutate $49[17:21].push(read $51)
|
||||
[21] store $54[21:30] = StoreLocal Const mutate $53[7:30] = capture $52[20:30]
|
||||
[22] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[23] mutate $55[23:30]:TPrimitive = null
|
||||
[24] store $57[24:30]:TPrimitive = StoreLocal Const mutate $53[7:30] = read $55[23:30]:TPrimitive
|
||||
[25] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$60[7:30]:TPhi: phi(bb3: $53, bb4: $56)
|
||||
x$33:TPhi: phi(bb3: x$33, bb4: x$33)
|
||||
[26] store $59[26:30] = StoreLocal Const mutate _$58[26:30] = capture $53[7:30]
|
||||
[27] mutate $61 = Global console
|
||||
[28] mutate $62[28:30] = LoadLocal capture _$58[26:30]
|
||||
[29] mutate $63 = PropertyCall read $61.log(mutate $62[28:30])
|
||||
[30] mutate $64 = LoadLocal capture x$33
|
||||
[31] Return freeze $64
|
||||
```
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;
|
||||
console.log(_);
|
||||
return x;
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? ((x = {}), (x = []), x.push(props.foo))
|
||||
: ((x = []), (x = []), x.push(props.bar));
|
||||
console.log(_);
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $44[1:7] = Array []
|
||||
[2] store $46[2:7] = StoreLocal Let mutate x$45[2:42] = capture $44[1:7]
|
||||
[3] mutate $47[3:7] = LoadLocal capture x$45[2:42]
|
||||
[4] mutate $48 = LoadLocal read props$43
|
||||
[5] mutate $49 = PropertyLoad read $48.bar
|
||||
[6] mutate $50 = PropertyCall mutate $47[3:7].push(read $49)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
[8] mutate $51 = LoadLocal read props$43
|
||||
[9] mutate $52 = PropertyLoad read $51.cond
|
||||
[10] Branch (read $52) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[14] store $57[14:42] = Array []
|
||||
[15] store $59[15:42] = StoreLocal Reassign mutate x$45[15:42] = capture $57[14:42]
|
||||
[17] mutate $61[17:42] = LoadLocal capture x$45[15:42]
|
||||
[18] mutate $62 = LoadLocal read props$43
|
||||
[19] mutate $63 = PropertyLoad read $62.foo
|
||||
[20] mutate $64[20:39] = PropertyCall mutate $61[17:42].push(read $63)
|
||||
[21] store $66[21:39] = StoreLocal Const mutate $65[7:39] = capture $64[20:39]
|
||||
[22] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[26] store $71[26:42] = Array []
|
||||
[27] store $73[27:42] = StoreLocal Reassign mutate x$45[27:42] = capture $71[26:42]
|
||||
[29] mutate $75[29:42] = LoadLocal capture x$45[27:42]
|
||||
[30] mutate $76 = LoadLocal read props$43
|
||||
[31] mutate $77 = PropertyLoad read $76.bar
|
||||
[32] mutate $78[32:39] = PropertyCall mutate $75[29:42].push(read $77)
|
||||
[33] store $80[33:39] = StoreLocal Const mutate $65[7:39] = capture $78[32:39]
|
||||
[34] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$83[7:39]:TPhi: phi(bb3: $65, bb4: $79)
|
||||
x$45[15:42]:TPhi: phi(bb3: x$45, bb4: x$45)
|
||||
[35] store $82[35:39] = StoreLocal Const mutate _$81[35:39] = capture $65[7:39]
|
||||
[36] mutate $84 = Global console
|
||||
[37] mutate $85[37:39] = LoadLocal capture _$81[35:39]
|
||||
[38] mutate $86 = PropertyCall read $84.log(mutate $85[37:39])
|
||||
[39] mutate $87:TFunction = Global mut
|
||||
[40] mutate $88[40:42] = LoadLocal capture x$45[15:42]
|
||||
[41] mutate $90 = Call read $87:TFunction(mutate $88[40:42])
|
||||
[42] mutate $91 = LoadLocal capture x$45[15:42]
|
||||
[43] Return freeze $91
|
||||
```
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? ((x = {}), (x = []), x.push(props.foo))
|
||||
: ((x = []), (x = []), x.push(props.bar));
|
||||
console.log(_);
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? ((x = {}), (x = []), x.push(props.foo))
|
||||
: ((x = []), (x = []), x.push(props.bar));
|
||||
console.log(_);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $41[1:7] = Array []
|
||||
[2] store $43[2:7] = StoreLocal Let mutate x$42[2:7] = capture $41[1:7]
|
||||
[3] mutate $44[3:7] = LoadLocal capture x$42[2:7]
|
||||
[4] mutate $45 = LoadLocal read props$40
|
||||
[5] mutate $46 = PropertyLoad read $45.bar
|
||||
[6] mutate $47 = PropertyCall mutate $44[3:7].push(read $46)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
[8] mutate $48 = LoadLocal read props$40
|
||||
[9] mutate $49 = PropertyLoad read $48.cond
|
||||
[10] Branch (read $49) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[14] store $54[14:21] = Array []
|
||||
[15] store $56[15:21] = StoreLocal Reassign mutate x$42[15:21] = capture $54[14:21]
|
||||
[17] mutate $58[17:21] = LoadLocal capture x$42[15:21]
|
||||
[18] mutate $59 = LoadLocal read props$40
|
||||
[19] mutate $60 = PropertyLoad read $59.foo
|
||||
[20] mutate $61[20:39] = PropertyCall mutate $58[17:21].push(read $60)
|
||||
[21] store $63[21:39] = StoreLocal Const mutate $62[7:39] = capture $61[20:39]
|
||||
[22] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[26] store $68[26:33] = Array []
|
||||
[27] store $70[27:33] = StoreLocal Reassign mutate x$42[27:33] = capture $68[26:33]
|
||||
[29] mutate $72[29:33] = LoadLocal capture x$42[27:33]
|
||||
[30] mutate $73 = LoadLocal read props$40
|
||||
[31] mutate $74 = PropertyLoad read $73.bar
|
||||
[32] mutate $75[32:39] = PropertyCall mutate $72[29:33].push(read $74)
|
||||
[33] store $77[33:39] = StoreLocal Const mutate $62[7:39] = capture $75[32:39]
|
||||
[34] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$80[7:39]:TPhi: phi(bb3: $62, bb4: $76)
|
||||
x$42:TPhi: phi(bb3: x$42, bb4: x$42)
|
||||
[35] store $79[35:39] = StoreLocal Const mutate _$78[35:39] = capture $62[7:39]
|
||||
[36] mutate $81 = Global console
|
||||
[37] mutate $82[37:39] = LoadLocal capture _$78[35:39]
|
||||
[38] mutate $83 = PropertyCall read $81.log(mutate $82[37:39])
|
||||
[39] mutate $84 = LoadLocal capture x$42
|
||||
[40] Return freeze $84
|
||||
```
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
const _ = props.cond
|
||||
? ((x = {}), (x = []), x.push(props.foo))
|
||||
: ((x = []), (x = []), x.push(props.bar));
|
||||
console.log(_);
|
||||
return x;
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
if (props.cond) {
|
||||
x = {};
|
||||
x = [];
|
||||
x.push(props.foo);
|
||||
} else {
|
||||
x = [];
|
||||
x = [];
|
||||
x.push(props.bar);
|
||||
}
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $36[1:7] = Array []
|
||||
[2] store $38[2:7] = StoreLocal Let mutate x$37[2:35] = capture $36[1:7]
|
||||
[3] mutate $39[3:7] = LoadLocal capture x$37[2:35]
|
||||
[4] mutate $40 = LoadLocal read props$35
|
||||
[5] mutate $41 = PropertyLoad read $40.bar
|
||||
[6] mutate $42 = PropertyCall mutate $39[3:7].push(read $41)
|
||||
[7] mutate $43 = LoadLocal read props$35
|
||||
[8] mutate $44 = PropertyLoad read $43.cond
|
||||
[9] If (read $44) then:bb2 else:bb3 fallthrough=bb1
|
||||
bb2 (block):
|
||||
predecessor blocks: bb0
|
||||
[13] store $49[13:35] = Array []
|
||||
[14] store $51[14:35] = StoreLocal Reassign mutate x$37[14:35] = capture $49[13:35]
|
||||
[16] mutate $53[16:35] = LoadLocal capture x$37[14:35]
|
||||
[17] mutate $54 = LoadLocal read props$35
|
||||
[18] mutate $55 = PropertyLoad read $54.foo
|
||||
[19] mutate $56 = PropertyCall mutate $53[16:35].push(read $55)
|
||||
[20] Goto bb1
|
||||
bb3 (block):
|
||||
predecessor blocks: bb0
|
||||
[24] store $61[24:35] = Array []
|
||||
[25] store $63[25:35] = StoreLocal Reassign mutate x$37[25:35] = capture $61[24:35]
|
||||
[27] mutate $65[27:35] = LoadLocal capture x$37[25:35]
|
||||
[28] mutate $66 = LoadLocal read props$35
|
||||
[29] mutate $67 = PropertyLoad read $66.bar
|
||||
[30] mutate $68 = PropertyCall mutate $65[27:35].push(read $67)
|
||||
[31] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb2 bb3
|
||||
x$37[14:35]:TPhi: phi(bb2: x$37, bb3: x$37)
|
||||
[32] mutate $69:TFunction = Global mut
|
||||
[33] mutate $70[33:35] = LoadLocal capture x$37[14:35]
|
||||
[34] mutate $72 = Call read $69:TFunction(mutate $70[33:35])
|
||||
[35] mutate $73 = LoadLocal capture x$37[14:35]
|
||||
[36] Return freeze $73
|
||||
```
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
function foo(props) {
|
||||
let x = [];
|
||||
x.push(props.bar);
|
||||
if (props.cond) {
|
||||
x = {};
|
||||
x = [];
|
||||
x.push(props.foo);
|
||||
} else {
|
||||
x = [];
|
||||
x = [];
|
||||
x.push(props.bar);
|
||||
}
|
||||
mut(x);
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user