mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[wip][typer] Infer Array instance properties
--- TODO: add inference for TypedFunction to `InferReferenceEffects`
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* 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 invariant from "invariant";
|
||||
import { Effect } from "./HIR";
|
||||
import { BuiltInType, FunctionType, PrimitiveType } from "./Types";
|
||||
|
||||
const PRIMITIVE_TYPE: PrimitiveType = {
|
||||
kind: "Primitive",
|
||||
};
|
||||
|
||||
let nextAnonId = 0;
|
||||
// use strings since they are easily debuggable, even though `Symbol()`
|
||||
// might be more performant
|
||||
function createAnonId(): string {
|
||||
return `<generated_${nextAnonId++}>`;
|
||||
}
|
||||
|
||||
function addFunction(
|
||||
registry: ShapeRegistry,
|
||||
properties: Iterable<[string, BuiltInType | null]>,
|
||||
fn: FunctionSignature
|
||||
): FunctionType {
|
||||
const shapeId = createAnonId();
|
||||
addShape(registry, shapeId, properties, fn);
|
||||
return {
|
||||
kind: "Function",
|
||||
shapeId,
|
||||
};
|
||||
}
|
||||
|
||||
function addShape(
|
||||
registry: ShapeRegistry,
|
||||
id: string,
|
||||
properties: Iterable<[string, BuiltInType | null]>,
|
||||
functionType?: FunctionSignature
|
||||
): ObjectShape {
|
||||
const shape: ObjectShape = {
|
||||
properties: new Map(properties),
|
||||
functionType: functionType ?? null,
|
||||
};
|
||||
|
||||
invariant(
|
||||
!registry.has(id),
|
||||
`[ObjectShape] Could not add shape to registry: name ${id} already exists.`
|
||||
);
|
||||
registry.set(id, shape);
|
||||
return shape;
|
||||
}
|
||||
|
||||
// Param type not recorded since it currently does not affect inference.
|
||||
// Specifically, we currently do not:
|
||||
// - infer types based on their usage in argument position
|
||||
// - handle inference for overloaded / generic functions
|
||||
export type FunctionSignature = {
|
||||
positionalParams: Array<Effect>;
|
||||
restParam: Effect | null;
|
||||
returnType: BuiltInType | null;
|
||||
calleeEffect: Effect;
|
||||
};
|
||||
|
||||
export type ObjectShape = {
|
||||
properties: Map<string, BuiltInType | null>;
|
||||
functionType: FunctionSignature | null;
|
||||
};
|
||||
|
||||
export type ShapeRegistry = Map<string, ObjectShape>;
|
||||
|
||||
/**
|
||||
* Shapes of built-in types
|
||||
*/
|
||||
|
||||
// The only "entrypoints" should be Globals and recursive lookups from properties / functions
|
||||
export const BUILTIN_SHAPES: ShapeRegistry = new Map();
|
||||
export const ArrayShapeId = "Array";
|
||||
export const ObjectShapeId = "Object";
|
||||
|
||||
/* Built-in array shape */
|
||||
addShape(BUILTIN_SHAPES, ArrayShapeId, [
|
||||
[
|
||||
"at",
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: null,
|
||||
calleeEffect: Effect.Capture,
|
||||
}),
|
||||
],
|
||||
[
|
||||
"concat",
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: Effect.Capture,
|
||||
returnType: {
|
||||
kind: "Object",
|
||||
shapeId: ArrayShapeId,
|
||||
},
|
||||
calleeEffect: Effect.Capture,
|
||||
}),
|
||||
],
|
||||
["length", PRIMITIVE_TYPE],
|
||||
[
|
||||
"push",
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: Effect.Capture,
|
||||
returnType: {
|
||||
kind: "Primitive",
|
||||
},
|
||||
calleeEffect: Effect.Store,
|
||||
}),
|
||||
],
|
||||
// TODO: rest of Array properties
|
||||
]);
|
||||
|
||||
/* Built-in Object shape */
|
||||
addShape(BUILTIN_SHAPES, ObjectShapeId, [
|
||||
[
|
||||
"toString",
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {
|
||||
kind: "Primitive",
|
||||
},
|
||||
calleeEffect: Effect.Read,
|
||||
}),
|
||||
],
|
||||
// TODO:
|
||||
// hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toLocaleString, valueOf
|
||||
]);
|
||||
@@ -566,7 +566,14 @@ function printScope(scope: ReactiveScope | null): string {
|
||||
|
||||
function printType(type: Type): string {
|
||||
if (type.kind === "Type") return "";
|
||||
return `:T${type.kind}`;
|
||||
// TODO(mofeiZ): add debugName for generated ids
|
||||
if (type.kind === "Object" && type.shapeId != null) {
|
||||
return `:T${type.kind}<${type.shapeId}>`;
|
||||
} else if (type.kind === "Function" && type.shapeId != null) {
|
||||
return `:T${type.kind}<${type.shapeId}>`;
|
||||
} else {
|
||||
return `:T${type.kind}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function printSourceLocation(loc: SourceLocation): string {
|
||||
|
||||
@@ -7,23 +7,36 @@
|
||||
import invariant from "invariant";
|
||||
import { Hook } from "./Hooks";
|
||||
|
||||
export type Type =
|
||||
| PrimitiveType
|
||||
| HookType
|
||||
| FunctionType
|
||||
| ObjectType
|
||||
| PhiType
|
||||
| PolyType
|
||||
| TypeVar;
|
||||
export type BuiltInType = PrimitiveType | FunctionType | ObjectType;
|
||||
|
||||
export type Type = BuiltInType | HookType | PhiType | PolyType | TypeVar;
|
||||
export type PrimitiveType = { kind: "Primitive" };
|
||||
export type FunctionType = {
|
||||
kind: "Function";
|
||||
};
|
||||
export type HookType = {
|
||||
kind: "Hook";
|
||||
definition: Hook;
|
||||
};
|
||||
export type ObjectType = { kind: "Object" };
|
||||
|
||||
/**
|
||||
* An {@link FunctionType} or {@link ObjectType} (also a JS object) may be associated with an
|
||||
* inferred "object shape", i.e. a known property (key -> Type) map. This is
|
||||
* subtly different from JS language semantics - `shape` represents both
|
||||
* OwnPropertyDescriptors and properties present in the prototype chain.
|
||||
*
|
||||
* In addition, a {@link FunctionType} may be associated with an inferred signature,
|
||||
*
|
||||
* If `shapeId` is present, it is a key into the global ShapeRegistry.
|
||||
*/
|
||||
|
||||
export type FunctionType = {
|
||||
kind: "Function";
|
||||
shapeId: string | null;
|
||||
};
|
||||
|
||||
export type ObjectType = {
|
||||
kind: "Object";
|
||||
shapeId: string | null;
|
||||
};
|
||||
|
||||
export type TypeVar = {
|
||||
kind: "Type";
|
||||
id: TypeId;
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
TypeId,
|
||||
TypeVar,
|
||||
} from "../HIR/HIR";
|
||||
import { ArrayShapeId, ObjectShapeId } from "../HIR/ObjectShape";
|
||||
import { eachInstructionLValue, eachInstructionOperand } from "../HIR/visitors";
|
||||
|
||||
function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]): boolean {
|
||||
@@ -150,7 +151,7 @@ function* generateInstructionTypes(
|
||||
if (hook !== null) {
|
||||
type = { kind: "Hook", definition: hook };
|
||||
} else {
|
||||
type = { kind: "Function" };
|
||||
type = { kind: "Function", shapeId: null };
|
||||
}
|
||||
yield equation(value.callee.identifier.type, type);
|
||||
break;
|
||||
@@ -158,7 +159,14 @@ function* generateInstructionTypes(
|
||||
|
||||
case "ObjectExpression": {
|
||||
invariant(left !== null, "invald object expression");
|
||||
yield equation(left, { kind: "Object" });
|
||||
yield equation(left, { kind: "Object", shapeId: ObjectShapeId });
|
||||
break;
|
||||
}
|
||||
|
||||
case "ArrayExpression": {
|
||||
if (left) {
|
||||
yield equation(left, { kind: "Object", shapeId: ArrayShapeId });
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ bb0 (block):
|
||||
[9] store $27 = StoreLocal Const mutate y$26 = capture $25
|
||||
[10] mutate $28:TPrimitive = LoadLocal read x$21:TPrimitive
|
||||
[11] mutate $29 = LoadLocal capture y$26
|
||||
[12] store $30 = Array [read $28:TPrimitive, capture $29]
|
||||
[13] Return freeze $30
|
||||
[12] store $30:TObject<Array> = Array [read $28:TPrimitive, capture $29]
|
||||
[13] Return freeze $30:TObject<Array>
|
||||
```
|
||||
|
||||
@@ -25,7 +25,7 @@ bb0 (block):
|
||||
[9] store $27 = StoreLocal Const mutate y$26 = capture $25
|
||||
[10] mutate $28:TPrimitive = LoadLocal read x$21:TPrimitive
|
||||
[11] mutate $29 = LoadLocal capture y$26
|
||||
[12] store $30:TObject = Object { x: read $28:TPrimitive, y: capture $29 }
|
||||
[13] Return freeze $30:TObject
|
||||
[12] store $30:TObject<Object> = Object { x: read $28:TPrimitive, y: capture $29 }
|
||||
[13] Return freeze $30:TObject<Object>
|
||||
```
|
||||
|
||||
+7
-7
@@ -19,12 +19,12 @@ function foo(props) {
|
||||
|
||||
```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]
|
||||
[1] store $35[1:33]:TObject<Array> = Array []
|
||||
[2] store $37[2:33]:TObject<Array> = StoreLocal Let store x$36[2:33]:TObject<Array> = capture $35[1:33]:TObject<Array>
|
||||
[3] mutate $38[3:33]:TObject<Array> = LoadLocal capture x$36[2:33]:TObject<Array>
|
||||
[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)
|
||||
[6] mutate $41 = PropertyCall mutate $38[3:33]:TObject<Array>.push(read $40)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
@@ -33,9 +33,9 @@ bb2 (value):
|
||||
[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]
|
||||
[14] store $48[14:33]:TObject<Array> = Array []
|
||||
[15] store $49[15:33]:TObject<Array> = Array [capture $48[14:33]:TObject<Array>]
|
||||
[16] store $51[16:33] = Destructure Reassign [ mutate x$36[16:33] ] = capture $49[15:33]:TObject<Array>
|
||||
[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
|
||||
|
||||
+7
-7
@@ -18,12 +18,12 @@ function foo(props) {
|
||||
|
||||
```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]
|
||||
[1] store $32[1:7]:TObject<Array> = Array []
|
||||
[2] store $34[2:7]:TObject<Array> = StoreLocal Let store x$33[2:7]:TObject<Array> = capture $32[1:7]:TObject<Array>
|
||||
[3] mutate $35[3:7]:TObject<Array> = LoadLocal capture x$33[2:7]:TObject<Array>
|
||||
[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)
|
||||
[6] mutate $38 = PropertyCall mutate $35[3:7]:TObject<Array>.push(read $37)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
@@ -32,9 +32,9 @@ bb2 (value):
|
||||
[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]
|
||||
[14] store $45[14:21]:TObject<Array> = Array []
|
||||
[15] store $46[15:21]:TObject<Array> = Array [capture $45[14:21]:TObject<Array>]
|
||||
[16] store $48[16:21] = Destructure Reassign [ mutate x$33[16:21] ] = capture $46[15:21]:TObject<Array>
|
||||
[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
|
||||
|
||||
+9
-9
@@ -17,12 +17,12 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $33[1:31] = Array []
|
||||
[2] store $35[2:31] = StoreLocal Let mutate x$34[2:31] = capture $33[1:31]
|
||||
[3] mutate $36[3:31] = LoadLocal capture x$34[2:31]
|
||||
[1] store $33[1:31]:TObject<Array> = Array []
|
||||
[2] store $35[2:31]:TObject<Array> = StoreLocal Let store x$34[2:31]:TObject<Array> = capture $33[1:31]:TObject<Array>
|
||||
[3] mutate $36[3:31]:TObject<Array> = LoadLocal capture x$34[2:31]:TObject<Array>
|
||||
[4] mutate $37 = LoadLocal read props$32
|
||||
[5] mutate $38 = PropertyLoad read $37.bar
|
||||
[6] mutate $39 = PropertyCall mutate $36[3:31].push(read $38)
|
||||
[6] mutate $39 = PropertyCall mutate $36[3:31]:TObject<Array>.push(read $38)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
@@ -31,12 +31,12 @@ bb2 (value):
|
||||
[10] Branch (read $41) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[13] store $45[13:31] = Array []
|
||||
[14] store $47[14:31] = StoreLocal Reassign mutate x$34[14:31] = capture $45[13:31]
|
||||
[15] mutate $48[15:31] = LoadLocal capture x$34[14:31]
|
||||
[13] store $45[13:31]:TObject<Array> = Array []
|
||||
[14] store $47[14:31]:TObject<Array> = StoreLocal Reassign store x$34[14:31]:TObject<Array> = capture $45[13:31]:TObject<Array>
|
||||
[15] mutate $48[15:31]:TObject<Array> = LoadLocal capture x$34[14:31]:TObject<Array>
|
||||
[16] mutate $49 = LoadLocal read props$32
|
||||
[17] mutate $50 = PropertyLoad read $49.foo
|
||||
[18] mutate $51[18:28] = PropertyCall mutate $48[15:31].push(read $50)
|
||||
[18] mutate $51[18:28] = PropertyCall mutate $48[15:31]:TObject<Array>.push(read $50)
|
||||
[19] store $53[19:28] = StoreLocal Const mutate $52[7:28] = capture $51[18:28]
|
||||
[20] Goto bb1
|
||||
bb4 (value):
|
||||
@@ -47,7 +47,7 @@ bb4 (value):
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$59[7:28]:TPhi: phi(bb3: $52, bb4: $55)
|
||||
x$34[2:31]:TPhi: phi(bb3: x$34, bb4: x$34)
|
||||
x$34[2:31]:TObject<Array>: phi(bb3: x$34, bb4: x$34)
|
||||
[24] store $58[24:28] = StoreLocal Const mutate _$57[24:28] = capture $52[7:28]
|
||||
[25] mutate $60 = Global console
|
||||
[26] mutate $61[26:28] = LoadLocal capture _$57[24:28]
|
||||
|
||||
@@ -16,12 +16,12 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $30[1:7] = Array []
|
||||
[2] store $32[2:7] = StoreLocal Let mutate x$31[2:7] = capture $30[1:7]
|
||||
[3] mutate $33[3:7] = LoadLocal capture x$31[2:7]
|
||||
[1] store $30[1:7]:TObject<Array> = Array []
|
||||
[2] store $32[2:7]:TObject<Array> = StoreLocal Let store x$31[2:7]:TObject<Array> = capture $30[1:7]:TObject<Array>
|
||||
[3] mutate $33[3:7]:TObject<Array> = LoadLocal capture x$31[2:7]:TObject<Array>
|
||||
[4] mutate $34 = LoadLocal read props$29
|
||||
[5] mutate $35 = PropertyLoad read $34.bar
|
||||
[6] mutate $36 = PropertyCall mutate $33[3:7].push(read $35)
|
||||
[6] mutate $36 = PropertyCall mutate $33[3:7]:TObject<Array>.push(read $35)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
@@ -30,12 +30,12 @@ bb2 (value):
|
||||
[10] Branch (read $38) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[13] store $42[13:19] = Array []
|
||||
[14] store $44[14:19] = StoreLocal Reassign mutate x$31[14:19] = capture $42[13:19]
|
||||
[15] mutate $45[15:19] = LoadLocal capture x$31[14:19]
|
||||
[13] store $42[13:19]:TObject<Array> = Array []
|
||||
[14] store $44[14:19]:TObject<Array> = StoreLocal Reassign store x$31[14:19]:TObject<Array> = capture $42[13:19]:TObject<Array>
|
||||
[15] mutate $45[15:19]:TObject<Array> = LoadLocal capture x$31[14:19]:TObject<Array>
|
||||
[16] mutate $46 = LoadLocal read props$29
|
||||
[17] mutate $47 = PropertyLoad read $46.foo
|
||||
[18] mutate $48[18:28] = PropertyCall mutate $45[15:19].push(read $47)
|
||||
[18] mutate $48[18:28] = PropertyCall mutate $45[15:19]:TObject<Array>.push(read $47)
|
||||
[19] store $50[19:28] = StoreLocal Const mutate $49[7:28] = capture $48[18:28]
|
||||
[20] Goto bb1
|
||||
bb4 (value):
|
||||
@@ -46,7 +46,7 @@ bb4 (value):
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$56[7:28]:TPhi: phi(bb3: $49, bb4: $52)
|
||||
x$31:TPhi: phi(bb3: x$31, bb4: x$31)
|
||||
x$31:TObject<Array>: phi(bb3: x$31, bb4: x$31)
|
||||
[24] store $55[24:28] = StoreLocal Const mutate _$54[24:28] = capture $49[7:28]
|
||||
[25] mutate $57 = Global console
|
||||
[26] mutate $58[26:28] = LoadLocal capture _$54[24:28]
|
||||
|
||||
+13
-13
@@ -19,12 +19,12 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $40[1:7] = Array []
|
||||
[2] store $42[2:7] = StoreLocal Let mutate x$41[2:38] = capture $40[1:7]
|
||||
[3] mutate $43[3:7] = LoadLocal capture x$41[2:38]
|
||||
[1] store $40[1:7]:TObject<Array> = Array []
|
||||
[2] store $42[2:7]:TObject<Array> = StoreLocal Let store x$41[2:38]:TObject<Array> = capture $40[1:7]:TObject<Array>
|
||||
[3] mutate $43[3:7]:TObject<Array> = LoadLocal capture x$41[2:38]:TObject<Array>
|
||||
[4] mutate $44 = LoadLocal read props$39
|
||||
[5] mutate $45 = PropertyLoad read $44.bar
|
||||
[6] mutate $46 = PropertyCall mutate $43[3:7].push(read $45)
|
||||
[6] mutate $46 = PropertyCall mutate $43[3:7]:TObject<Array>.push(read $45)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
@@ -33,28 +33,28 @@ bb2 (value):
|
||||
[10] Branch (read $48) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[13] store $52[13:38] = Array []
|
||||
[14] store $54[14:38] = StoreLocal Reassign mutate x$41[14:38] = capture $52[13:38]
|
||||
[15] mutate $55[15:38] = LoadLocal capture x$41[14:38]
|
||||
[13] store $52[13:38]:TObject<Array> = Array []
|
||||
[14] store $54[14:38]:TObject<Array> = StoreLocal Reassign store x$41[14:38]:TObject<Array> = capture $52[13:38]:TObject<Array>
|
||||
[15] mutate $55[15:38]:TObject<Array> = LoadLocal capture x$41[14:38]:TObject<Array>
|
||||
[16] mutate $56 = LoadLocal read props$39
|
||||
[17] mutate $57 = PropertyLoad read $56.foo
|
||||
[18] mutate $58[18:35] = PropertyCall mutate $55[15:38].push(read $57)
|
||||
[18] mutate $58[18:35] = PropertyCall mutate $55[15:38]:TObject<Array>.push(read $57)
|
||||
[19] store $60[19:35] = StoreLocal Const mutate $59[7:35] = capture $58[18:35]
|
||||
[20] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[23] store $64[23:38] = Array []
|
||||
[24] store $66[24:38] = StoreLocal Reassign mutate x$41[24:38] = capture $64[23:38]
|
||||
[25] mutate $67[25:38] = LoadLocal capture x$41[24:38]
|
||||
[23] store $64[23:38]:TObject<Array> = Array []
|
||||
[24] store $66[24:38]:TObject<Array> = StoreLocal Reassign store x$41[24:38]:TObject<Array> = capture $64[23:38]:TObject<Array>
|
||||
[25] mutate $67[25:38]:TObject<Array> = LoadLocal capture x$41[24:38]:TObject<Array>
|
||||
[26] mutate $68 = LoadLocal read props$39
|
||||
[27] mutate $69 = PropertyLoad read $68.bar
|
||||
[28] mutate $70[28:35] = PropertyCall mutate $67[25:38].push(read $69)
|
||||
[28] mutate $70[28:35] = PropertyCall mutate $67[25:38]:TObject<Array>.push(read $69)
|
||||
[29] store $72[29:35] = StoreLocal Const mutate $59[7:35] = capture $70[28:35]
|
||||
[30] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$75[7:35]:TPhi: phi(bb3: $59, bb4: $71)
|
||||
x$41[14:38]:TPhi: phi(bb3: x$41, bb4: x$41)
|
||||
x$41[14:38]:TObject<Array>: phi(bb3: x$41, bb4: x$41)
|
||||
[31] store $74[31:35] = StoreLocal Const mutate _$73[31:35] = capture $59[7:35]
|
||||
[32] mutate $76 = Global console
|
||||
[33] mutate $77[33:35] = LoadLocal capture _$73[31:35]
|
||||
|
||||
+13
-13
@@ -18,12 +18,12 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $37[1:7] = Array []
|
||||
[2] store $39[2:7] = StoreLocal Let mutate x$38[2:7] = capture $37[1:7]
|
||||
[3] mutate $40[3:7] = LoadLocal capture x$38[2:7]
|
||||
[1] store $37[1:7]:TObject<Array> = Array []
|
||||
[2] store $39[2:7]:TObject<Array> = StoreLocal Let store x$38[2:7]:TObject<Array> = capture $37[1:7]:TObject<Array>
|
||||
[3] mutate $40[3:7]:TObject<Array> = LoadLocal capture x$38[2:7]:TObject<Array>
|
||||
[4] mutate $41 = LoadLocal read props$36
|
||||
[5] mutate $42 = PropertyLoad read $41.bar
|
||||
[6] mutate $43 = PropertyCall mutate $40[3:7].push(read $42)
|
||||
[6] mutate $43 = PropertyCall mutate $40[3:7]:TObject<Array>.push(read $42)
|
||||
[7] Ternary test:bb2 fallthrough=bb1
|
||||
bb2 (value):
|
||||
predecessor blocks: bb0
|
||||
@@ -32,28 +32,28 @@ bb2 (value):
|
||||
[10] Branch (read $45) then:bb3 else:bb4
|
||||
bb3 (value):
|
||||
predecessor blocks: bb2
|
||||
[13] store $49[13:19] = Array []
|
||||
[14] store $51[14:19] = StoreLocal Reassign mutate x$38[14:19] = capture $49[13:19]
|
||||
[15] mutate $52[15:19] = LoadLocal capture x$38[14:19]
|
||||
[13] store $49[13:19]:TObject<Array> = Array []
|
||||
[14] store $51[14:19]:TObject<Array> = StoreLocal Reassign store x$38[14:19]:TObject<Array> = capture $49[13:19]:TObject<Array>
|
||||
[15] mutate $52[15:19]:TObject<Array> = LoadLocal capture x$38[14:19]:TObject<Array>
|
||||
[16] mutate $53 = LoadLocal read props$36
|
||||
[17] mutate $54 = PropertyLoad read $53.foo
|
||||
[18] mutate $55[18:35] = PropertyCall mutate $52[15:19].push(read $54)
|
||||
[18] mutate $55[18:35] = PropertyCall mutate $52[15:19]:TObject<Array>.push(read $54)
|
||||
[19] store $57[19:35] = StoreLocal Const mutate $56[7:35] = capture $55[18:35]
|
||||
[20] Goto bb1
|
||||
bb4 (value):
|
||||
predecessor blocks: bb2
|
||||
[23] store $61[23:29] = Array []
|
||||
[24] store $63[24:29] = StoreLocal Reassign mutate x$38[24:29] = capture $61[23:29]
|
||||
[25] mutate $64[25:29] = LoadLocal capture x$38[24:29]
|
||||
[23] store $61[23:29]:TObject<Array> = Array []
|
||||
[24] store $63[24:29]:TObject<Array> = StoreLocal Reassign store x$38[24:29]:TObject<Array> = capture $61[23:29]:TObject<Array>
|
||||
[25] mutate $64[25:29]:TObject<Array> = LoadLocal capture x$38[24:29]:TObject<Array>
|
||||
[26] mutate $65 = LoadLocal read props$36
|
||||
[27] mutate $66 = PropertyLoad read $65.bar
|
||||
[28] mutate $67[28:35] = PropertyCall mutate $64[25:29].push(read $66)
|
||||
[28] mutate $67[28:35] = PropertyCall mutate $64[25:29]:TObject<Array>.push(read $66)
|
||||
[29] store $69[29:35] = StoreLocal Const mutate $56[7:35] = capture $67[28:35]
|
||||
[30] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb3 bb4
|
||||
$72[7:35]:TPhi: phi(bb3: $56, bb4: $68)
|
||||
x$38:TPhi: phi(bb3: x$38, bb4: x$38)
|
||||
x$38:TObject<Array>: phi(bb3: x$38, bb4: x$38)
|
||||
[31] store $71[31:35] = StoreLocal Const mutate _$70[31:35] = capture $56[7:35]
|
||||
[32] mutate $73 = Global console
|
||||
[33] mutate $74[33:35] = LoadLocal capture _$70[31:35]
|
||||
|
||||
+13
-13
@@ -24,36 +24,36 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
bb0 (block):
|
||||
[1] store $32[1:7] = Array []
|
||||
[2] store $34[2:7] = StoreLocal Let mutate x$33[2:31] = capture $32[1:7]
|
||||
[3] mutate $35[3:7] = LoadLocal capture x$33[2:31]
|
||||
[1] store $32[1:7]:TObject<Array> = Array []
|
||||
[2] store $34[2:7]:TObject<Array> = StoreLocal Let store x$33[2:31]:TObject<Array> = capture $32[1:7]:TObject<Array>
|
||||
[3] mutate $35[3:7]:TObject<Array> = LoadLocal capture x$33[2:31]:TObject<Array>
|
||||
[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)
|
||||
[6] mutate $38 = PropertyCall mutate $35[3:7]:TObject<Array>.push(read $37)
|
||||
[7] mutate $39 = LoadLocal read props$31
|
||||
[8] mutate $40 = PropertyLoad read $39.cond
|
||||
[9] If (read $40) then:bb2 else:bb3 fallthrough=bb1
|
||||
bb2 (block):
|
||||
predecessor blocks: bb0
|
||||
[12] store $44[12:31] = Array []
|
||||
[13] store $46[13:31] = StoreLocal Reassign mutate x$33[13:31] = capture $44[12:31]
|
||||
[14] mutate $47[14:31] = LoadLocal capture x$33[13:31]
|
||||
[12] store $44[12:31]:TObject<Array> = Array []
|
||||
[13] store $46[13:31]:TObject<Array> = StoreLocal Reassign store x$33[13:31]:TObject<Array> = capture $44[12:31]:TObject<Array>
|
||||
[14] mutate $47[14:31]:TObject<Array> = LoadLocal capture x$33[13:31]:TObject<Array>
|
||||
[15] mutate $48 = LoadLocal read props$31
|
||||
[16] mutate $49 = PropertyLoad read $48.foo
|
||||
[17] mutate $50 = PropertyCall mutate $47[14:31].push(read $49)
|
||||
[17] mutate $50 = PropertyCall mutate $47[14:31]:TObject<Array>.push(read $49)
|
||||
[18] Goto bb1
|
||||
bb3 (block):
|
||||
predecessor blocks: bb0
|
||||
[21] store $54[21:31] = Array []
|
||||
[22] store $56[22:31] = StoreLocal Reassign mutate x$33[22:31] = capture $54[21:31]
|
||||
[23] mutate $57[23:31] = LoadLocal capture x$33[22:31]
|
||||
[21] store $54[21:31]:TObject<Array> = Array []
|
||||
[22] store $56[22:31]:TObject<Array> = StoreLocal Reassign store x$33[22:31]:TObject<Array> = capture $54[21:31]:TObject<Array>
|
||||
[23] mutate $57[23:31]:TObject<Array> = LoadLocal capture x$33[22:31]:TObject<Array>
|
||||
[24] mutate $58 = LoadLocal read props$31
|
||||
[25] mutate $59 = PropertyLoad read $58.bar
|
||||
[26] mutate $60 = PropertyCall mutate $57[23:31].push(read $59)
|
||||
[26] mutate $60 = PropertyCall mutate $57[23:31]:TObject<Array>.push(read $59)
|
||||
[27] Goto bb1
|
||||
bb1 (block):
|
||||
predecessor blocks: bb2 bb3
|
||||
x$33[13:31]:TPhi: phi(bb2: x$33, bb3: x$33)
|
||||
x$33[13:31]:TObject<Array>: phi(bb2: x$33, bb3: x$33)
|
||||
[28] mutate $61:TFunction = Global mut
|
||||
[29] mutate $62[29:31] = LoadLocal capture x$33[13:31]
|
||||
[30] mutate $64 = Call read $61:TFunction(mutate $62[29:31])
|
||||
|
||||
Reference in New Issue
Block a user