@samitouri / QOS-React-2 / commits / ec345ca538

[wip][typer] Infer Array instance properties

--- TODO: add inference for TypedFunction to `InferReferenceEffects`

Mofei Zhang committed Mar 21, 2023 at 14:57 UTC ec345ca538704b25c66879025528e3b0dd1f96a2
13 files changed +252 -90
compiler/forget/src/HIR/ObjectShape.ts new
+134
@@ -0,0 +1,134 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +import invariant from "invariant";
8 +import { Effect } from "./HIR";
9 +import { BuiltInType, FunctionType, PrimitiveType } from "./Types";
10 +
11 +const PRIMITIVE_TYPE: PrimitiveType = {
12 + kind: "Primitive",
13 +};
14 +
15 +let nextAnonId = 0;
16 +// use strings since they are easily debuggable, even though `Symbol()`
17 +// might be more performant
18 +function createAnonId(): string {
19 + return `<generated_${nextAnonId++}>`;
20 +}
21 +
22 +function addFunction(
23 + registry: ShapeRegistry,
24 + properties: Iterable<[string, BuiltInType | null]>,
25 + fn: FunctionSignature
26 +): FunctionType {
27 + const shapeId = createAnonId();
28 + addShape(registry, shapeId, properties, fn);
29 + return {
30 + kind: "Function",
31 + shapeId,
32 + };
33 +}
34 +
35 +function addShape(
36 + registry: ShapeRegistry,
37 + id: string,
38 + properties: Iterable<[string, BuiltInType | null]>,
39 + functionType?: FunctionSignature
40 +): ObjectShape {
41 + const shape: ObjectShape = {
42 + properties: new Map(properties),
43 + functionType: functionType ?? null,
44 + };
45 +
46 + invariant(
47 + !registry.has(id),
48 + `[ObjectShape] Could not add shape to registry: name ${id} already exists.`
49 + );
50 + registry.set(id, shape);
51 + return shape;
52 +}
53 +
54 +// Param type not recorded since it currently does not affect inference.
55 +// Specifically, we currently do not:
56 +// - infer types based on their usage in argument position
57 +// - handle inference for overloaded / generic functions
58 +export type FunctionSignature = {
59 + positionalParams: Array<Effect>;
60 + restParam: Effect | null;
61 + returnType: BuiltInType | null;
62 + calleeEffect: Effect;
63 +};
64 +
65 +export type ObjectShape = {
66 + properties: Map<string, BuiltInType | null>;
67 + functionType: FunctionSignature | null;
68 +};
69 +
70 +export type ShapeRegistry = Map<string, ObjectShape>;
71 +
72 +/**
73 + * Shapes of built-in types
74 + */
75 +
76 +// The only "entrypoints" should be Globals and recursive lookups from properties / functions
77 +export const BUILTIN_SHAPES: ShapeRegistry = new Map();
78 +export const ArrayShapeId = "Array";
79 +export const ObjectShapeId = "Object";
80 +
81 +/* Built-in array shape */
82 +addShape(BUILTIN_SHAPES, ArrayShapeId, [
83 + [
84 + "at",
85 + addFunction(BUILTIN_SHAPES, [], {
86 + positionalParams: [Effect.Read],
87 + restParam: null,
88 + returnType: null,
89 + calleeEffect: Effect.Capture,
90 + }),
91 + ],
92 + [
93 + "concat",
94 + addFunction(BUILTIN_SHAPES, [], {
95 + positionalParams: [],
96 + restParam: Effect.Capture,
97 + returnType: {
98 + kind: "Object",
99 + shapeId: ArrayShapeId,
100 + },
101 + calleeEffect: Effect.Capture,
102 + }),
103 + ],
104 + ["length", PRIMITIVE_TYPE],
105 + [
106 + "push",
107 + addFunction(BUILTIN_SHAPES, [], {
108 + positionalParams: [],
109 + restParam: Effect.Capture,
110 + returnType: {
111 + kind: "Primitive",
112 + },
113 + calleeEffect: Effect.Store,
114 + }),
115 + ],
116 + // TODO: rest of Array properties
117 +]);
118 +
119 +/* Built-in Object shape */
120 +addShape(BUILTIN_SHAPES, ObjectShapeId, [
121 + [
122 + "toString",
123 + addFunction(BUILTIN_SHAPES, [], {
124 + positionalParams: [],
125 + restParam: null,
126 + returnType: {
127 + kind: "Primitive",
128 + },
129 + calleeEffect: Effect.Read,
130 + }),
131 + ],
132 + // TODO:
133 + // hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toLocaleString, valueOf
134 +]);
compiler/forget/src/HIR/PrintHIR.ts
+8 -1
@@ -566,7 +566,14 @@ function printScope(scope: ReactiveScope | null): string {
566
567 function printType(type: Type): string {
568 if (type.kind === "Type") return "";
569 - return `:T${type.kind}`;
569 + // TODO(mofeiZ): add debugName for generated ids
570 + if (type.kind === "Object" && type.shapeId != null) {
571 + return `:T${type.kind}<${type.shapeId}>`;
572 + } else if (type.kind === "Function" && type.shapeId != null) {
573 + return `:T${type.kind}<${type.shapeId}>`;
574 + } else {
575 + return `:T${type.kind}`;
576 + }
577 }
578
579 export function printSourceLocation(loc: SourceLocation): string {
compiler/forget/src/HIR/Types.ts
+25 -12
@@ -7,23 +7,36 @@
7 import invariant from "invariant";
8 import { Hook } from "./Hooks";
9
10 -export type Type =
11 - | PrimitiveType
12 - | HookType
13 - | FunctionType
14 - | ObjectType
15 - | PhiType
16 - | PolyType
17 - | TypeVar;
10 +export type BuiltInType = PrimitiveType | FunctionType | ObjectType;
11 +
12 +export type Type = BuiltInType | HookType | PhiType | PolyType | TypeVar;
13 export type PrimitiveType = { kind: "Primitive" };
19 -export type FunctionType = {
20 - kind: "Function";
21 -};
14 export type HookType = {
15 kind: "Hook";
16 definition: Hook;
17 };
26 -export type ObjectType = { kind: "Object" };
18 +
19 +/**
20 + * An {@link FunctionType} or {@link ObjectType} (also a JS object) may be associated with an
21 + * inferred "object shape", i.e. a known property (key -> Type) map. This is
22 + * subtly different from JS language semantics - `shape` represents both
23 + * OwnPropertyDescriptors and properties present in the prototype chain.
24 + *
25 + * In addition, a {@link FunctionType} may be associated with an inferred signature,
26 + *
27 + * If `shapeId` is present, it is a key into the global ShapeRegistry.
28 + */
29 +
30 +export type FunctionType = {
31 + kind: "Function";
32 + shapeId: string | null;
33 +};
34 +
35 +export type ObjectType = {
36 + kind: "Object";
37 + shapeId: string | null;
38 +};
39 +
40 export type TypeVar = {
41 kind: "Type";
42 id: TypeId;
compiler/forget/src/TypeInference/InferTypes.ts
+10 -2
@@ -9,6 +9,7 @@ import {
9 TypeId,
10 TypeVar,
11 } from "../HIR/HIR";
12 +import { ArrayShapeId, ObjectShapeId } from "../HIR/ObjectShape";
13 import { eachInstructionLValue, eachInstructionOperand } from "../HIR/visitors";
14
15 function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]): boolean {
@@ -150,7 +151,7 @@ function* generateInstructionTypes(
151 if (hook !== null) {
152 type = { kind: "Hook", definition: hook };
153 } else {
153 - type = { kind: "Function" };
154 + type = { kind: "Function", shapeId: null };
155 }
156 yield equation(value.callee.identifier.type, type);
157 break;
@@ -158,7 +159,14 @@ function* generateInstructionTypes(
159
160 case "ObjectExpression": {
161 invariant(left !== null, "invald object expression");
161 - yield equation(left, { kind: "Object" });
162 + yield equation(left, { kind: "Object", shapeId: ObjectShapeId });
163 + break;
164 + }
165 +
166 + case "ArrayExpression": {
167 + if (left) {
168 + yield equation(left, { kind: "Object", shapeId: ArrayShapeId });
169 + }
170 break;
171 }
172 }
compiler/forget/src/__tests__/fixtures/hir/simple-array.expect.md
+2 -2
@@ -25,7 +25,7 @@ bb0 (block):
25 [9] store $27 = StoreLocal Const mutate y$26 = capture $25
26 [10] mutate $28:TPrimitive = LoadLocal read x$21:TPrimitive
27 [11] mutate $29 = LoadLocal capture y$26
28 - [12] store $30 = Array [read $28:TPrimitive, capture $29]
29 - [13] Return freeze $30
28 + [12] store $30:TObject<Array> = Array [read $28:TPrimitive, capture $29]
29 + [13] Return freeze $30:TObject<Array>
30 ```
31
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/simple-object.expect.md
+2 -2
@@ -25,7 +25,7 @@ bb0 (block):
25 [9] store $27 = StoreLocal Const mutate y$26 = capture $25
26 [10] mutate $28:TPrimitive = LoadLocal read x$21:TPrimitive
27 [11] mutate $29 = LoadLocal capture y$26
28 - [12] store $30:TObject = Object { x: read $28:TPrimitive, y: capture $29 }
29 - [13] Return freeze $30:TObject
28 + [12] store $30:TObject<Object> = Object { x: read $28:TPrimitive, y: capture $29 }
29 + [13] Return freeze $30:TObject<Object>
30 ```
31
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction-with-mutation.expect.md
+7 -7
@@ -19,12 +19,12 @@ function foo(props) {
19
20 ```javascript
21 bb0 (block):
22 - [1] store $35[1:33] = Array []
23 - [2] store $37[2:33] = StoreLocal Let mutate x$36[2:33] = capture $35[1:33]
24 - [3] mutate $38[3:33] = LoadLocal capture x$36[2:33]
22 + [1] store $35[1:33]:TObject<Array> = Array []
23 + [2] store $37[2:33]:TObject<Array> = StoreLocal Let store x$36[2:33]:TObject<Array> = capture $35[1:33]:TObject<Array>
24 + [3] mutate $38[3:33]:TObject<Array> = LoadLocal capture x$36[2:33]:TObject<Array>
25 [4] mutate $39 = LoadLocal read props$34
26 [5] mutate $40 = PropertyLoad read $39.bar
27 - [6] mutate $41 = PropertyCall mutate $38[3:33].push(read $40)
27 + [6] mutate $41 = PropertyCall mutate $38[3:33]:TObject<Array>.push(read $40)
28 [7] Ternary test:bb2 fallthrough=bb1
29 bb2 (value):
30 predecessor blocks: bb0
@@ -33,9 +33,9 @@ bb2 (value):
33 [10] Branch (read $43) then:bb3 else:bb4
34 bb3 (value):
35 predecessor blocks: bb2
36 - [14] store $48[14:33] = Array []
37 - [15] store $49[15:33] = Array [capture $48[14:33]]
38 - [16] store $51[16:33] = Destructure Reassign [ mutate x$36[16:33] ] = capture $49[15:33]
36 + [14] store $48[14:33]:TObject<Array> = Array []
37 + [15] store $49[15:33]:TObject<Array> = Array [capture $48[14:33]:TObject<Array>]
38 + [16] store $51[16:33] = Destructure Reassign [ mutate x$36[16:33] ] = capture $49[15:33]:TObject<Array>
39 [17] mutate $52[17:33] = LoadLocal capture x$36[16:33]
40 [18] mutate $53 = LoadLocal read props$34
41 [19] mutate $54 = PropertyLoad read $53.foo
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction.expect.md
+7 -7
@@ -18,12 +18,12 @@ function foo(props) {
18
19 ```javascript
20 bb0 (block):
21 - [1] store $32[1:7] = Array []
22 - [2] store $34[2:7] = StoreLocal Let mutate x$33[2:7] = capture $32[1:7]
23 - [3] mutate $35[3:7] = LoadLocal capture x$33[2:7]
21 + [1] store $32[1:7]:TObject<Array> = Array []
22 + [2] store $34[2:7]:TObject<Array> = StoreLocal Let store x$33[2:7]:TObject<Array> = capture $32[1:7]:TObject<Array>
23 + [3] mutate $35[3:7]:TObject<Array> = LoadLocal capture x$33[2:7]:TObject<Array>
24 [4] mutate $36 = LoadLocal read props$31
25 [5] mutate $37 = PropertyLoad read $36.bar
26 - [6] mutate $38 = PropertyCall mutate $35[3:7].push(read $37)
26 + [6] mutate $38 = PropertyCall mutate $35[3:7]:TObject<Array>.push(read $37)
27 [7] Ternary test:bb2 fallthrough=bb1
28 bb2 (value):
29 predecessor blocks: bb0
@@ -32,9 +32,9 @@ bb2 (value):
32 [10] Branch (read $40) then:bb3 else:bb4
33 bb3 (value):
34 predecessor blocks: bb2
35 - [14] store $45[14:21] = Array []
36 - [15] store $46[15:21] = Array [capture $45[14:21]]
37 - [16] store $48[16:21] = Destructure Reassign [ mutate x$33[16:21] ] = capture $46[15:21]
35 + [14] store $45[14:21]:TObject<Array> = Array []
36 + [15] store $46[15:21]:TObject<Array> = Array [capture $45[14:21]:TObject<Array>]
37 + [16] store $48[16:21] = Destructure Reassign [ mutate x$33[16:21] ] = capture $46[15:21]:TObject<Array>
38 [17] mutate $49[17:21] = LoadLocal capture x$33[16:21]
39 [18] mutate $50 = LoadLocal read props$31
40 [19] mutate $51 = PropertyLoad read $50.foo
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-with-mutation.expect.md
+9 -9
@@ -17,12 +17,12 @@ function foo(props) {
17
18 ```javascript
19 bb0 (block):
20 - [1] store $33[1:31] = Array []
21 - [2] store $35[2:31] = StoreLocal Let mutate x$34[2:31] = capture $33[1:31]
22 - [3] mutate $36[3:31] = LoadLocal capture x$34[2:31]
20 + [1] store $33[1:31]:TObject<Array> = Array []
21 + [2] store $35[2:31]:TObject<Array> = StoreLocal Let store x$34[2:31]:TObject<Array> = capture $33[1:31]:TObject<Array>
22 + [3] mutate $36[3:31]:TObject<Array> = LoadLocal capture x$34[2:31]:TObject<Array>
23 [4] mutate $37 = LoadLocal read props$32
24 [5] mutate $38 = PropertyLoad read $37.bar
25 - [6] mutate $39 = PropertyCall mutate $36[3:31].push(read $38)
25 + [6] mutate $39 = PropertyCall mutate $36[3:31]:TObject<Array>.push(read $38)
26 [7] Ternary test:bb2 fallthrough=bb1
27 bb2 (value):
28 predecessor blocks: bb0
@@ -31,12 +31,12 @@ bb2 (value):
31 [10] Branch (read $41) then:bb3 else:bb4
32 bb3 (value):
33 predecessor blocks: bb2
34 - [13] store $45[13:31] = Array []
35 - [14] store $47[14:31] = StoreLocal Reassign mutate x$34[14:31] = capture $45[13:31]
36 - [15] mutate $48[15:31] = LoadLocal capture x$34[14:31]
34 + [13] store $45[13:31]:TObject<Array> = Array []
35 + [14] store $47[14:31]:TObject<Array> = StoreLocal Reassign store x$34[14:31]:TObject<Array> = capture $45[13:31]:TObject<Array>
36 + [15] mutate $48[15:31]:TObject<Array> = LoadLocal capture x$34[14:31]:TObject<Array>
37 [16] mutate $49 = LoadLocal read props$32
38 [17] mutate $50 = PropertyLoad read $49.foo
39 - [18] mutate $51[18:28] = PropertyCall mutate $48[15:31].push(read $50)
39 + [18] mutate $51[18:28] = PropertyCall mutate $48[15:31]:TObject<Array>.push(read $50)
40 [19] store $53[19:28] = StoreLocal Const mutate $52[7:28] = capture $51[18:28]
41 [20] Goto bb1
42 bb4 (value):
@@ -47,7 +47,7 @@ bb4 (value):
47 bb1 (block):
48 predecessor blocks: bb3 bb4
49 $59[7:28]:TPhi: phi(bb3: $52, bb4: $55)
50 - x$34[2:31]:TPhi: phi(bb3: x$34, bb4: x$34)
50 + x$34[2:31]:TObject<Array>: phi(bb3: x$34, bb4: x$34)
51 [24] store $58[24:28] = StoreLocal Const mutate _$57[24:28] = capture $52[7:28]
52 [25] mutate $60 = Global console
53 [26] mutate $61[26:28] = LoadLocal capture _$57[24:28]
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary.expect.md
+9 -9
@@ -16,12 +16,12 @@ function foo(props) {
16
17 ```javascript
18 bb0 (block):
19 - [1] store $30[1:7] = Array []
20 - [2] store $32[2:7] = StoreLocal Let mutate x$31[2:7] = capture $30[1:7]
21 - [3] mutate $33[3:7] = LoadLocal capture x$31[2:7]
19 + [1] store $30[1:7]:TObject<Array> = Array []
20 + [2] store $32[2:7]:TObject<Array> = StoreLocal Let store x$31[2:7]:TObject<Array> = capture $30[1:7]:TObject<Array>
21 + [3] mutate $33[3:7]:TObject<Array> = LoadLocal capture x$31[2:7]:TObject<Array>
22 [4] mutate $34 = LoadLocal read props$29
23 [5] mutate $35 = PropertyLoad read $34.bar
24 - [6] mutate $36 = PropertyCall mutate $33[3:7].push(read $35)
24 + [6] mutate $36 = PropertyCall mutate $33[3:7]:TObject<Array>.push(read $35)
25 [7] Ternary test:bb2 fallthrough=bb1
26 bb2 (value):
27 predecessor blocks: bb0
@@ -30,12 +30,12 @@ bb2 (value):
30 [10] Branch (read $38) then:bb3 else:bb4
31 bb3 (value):
32 predecessor blocks: bb2
33 - [13] store $42[13:19] = Array []
34 - [14] store $44[14:19] = StoreLocal Reassign mutate x$31[14:19] = capture $42[13:19]
35 - [15] mutate $45[15:19] = LoadLocal capture x$31[14:19]
33 + [13] store $42[13:19]:TObject<Array> = Array []
34 + [14] store $44[14:19]:TObject<Array> = StoreLocal Reassign store x$31[14:19]:TObject<Array> = capture $42[13:19]:TObject<Array>
35 + [15] mutate $45[15:19]:TObject<Array> = LoadLocal capture x$31[14:19]:TObject<Array>
36 [16] mutate $46 = LoadLocal read props$29
37 [17] mutate $47 = PropertyLoad read $46.foo
38 - [18] mutate $48[18:28] = PropertyCall mutate $45[15:19].push(read $47)
38 + [18] mutate $48[18:28] = PropertyCall mutate $45[15:19]:TObject<Array>.push(read $47)
39 [19] store $50[19:28] = StoreLocal Const mutate $49[7:28] = capture $48[18:28]
40 [20] Goto bb1
41 bb4 (value):
@@ -46,7 +46,7 @@ bb4 (value):
46 bb1 (block):
47 predecessor blocks: bb3 bb4
48 $56[7:28]:TPhi: phi(bb3: $49, bb4: $52)
49 - x$31:TPhi: phi(bb3: x$31, bb4: x$31)
49 + x$31:TObject<Array>: phi(bb3: x$31, bb4: x$31)
50 [24] store $55[24:28] = StoreLocal Const mutate _$54[24:28] = capture $49[7:28]
51 [25] mutate $57 = Global console
52 [26] mutate $58[26:28] = LoadLocal capture _$54[24:28]
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary-with-mutation.expect.md
+13 -13
@@ -19,12 +19,12 @@ function foo(props) {
19
20 ```javascript
21 bb0 (block):
22 - [1] store $40[1:7] = Array []
23 - [2] store $42[2:7] = StoreLocal Let mutate x$41[2:38] = capture $40[1:7]
24 - [3] mutate $43[3:7] = LoadLocal capture x$41[2:38]
22 + [1] store $40[1:7]:TObject<Array> = Array []
23 + [2] store $42[2:7]:TObject<Array> = StoreLocal Let store x$41[2:38]:TObject<Array> = capture $40[1:7]:TObject<Array>
24 + [3] mutate $43[3:7]:TObject<Array> = LoadLocal capture x$41[2:38]:TObject<Array>
25 [4] mutate $44 = LoadLocal read props$39
26 [5] mutate $45 = PropertyLoad read $44.bar
27 - [6] mutate $46 = PropertyCall mutate $43[3:7].push(read $45)
27 + [6] mutate $46 = PropertyCall mutate $43[3:7]:TObject<Array>.push(read $45)
28 [7] Ternary test:bb2 fallthrough=bb1
29 bb2 (value):
30 predecessor blocks: bb0
@@ -33,28 +33,28 @@ bb2 (value):
33 [10] Branch (read $48) then:bb3 else:bb4
34 bb3 (value):
35 predecessor blocks: bb2
36 - [13] store $52[13:38] = Array []
37 - [14] store $54[14:38] = StoreLocal Reassign mutate x$41[14:38] = capture $52[13:38]
38 - [15] mutate $55[15:38] = LoadLocal capture x$41[14:38]
36 + [13] store $52[13:38]:TObject<Array> = Array []
37 + [14] store $54[14:38]:TObject<Array> = StoreLocal Reassign store x$41[14:38]:TObject<Array> = capture $52[13:38]:TObject<Array>
38 + [15] mutate $55[15:38]:TObject<Array> = LoadLocal capture x$41[14:38]:TObject<Array>
39 [16] mutate $56 = LoadLocal read props$39
40 [17] mutate $57 = PropertyLoad read $56.foo
41 - [18] mutate $58[18:35] = PropertyCall mutate $55[15:38].push(read $57)
41 + [18] mutate $58[18:35] = PropertyCall mutate $55[15:38]:TObject<Array>.push(read $57)
42 [19] store $60[19:35] = StoreLocal Const mutate $59[7:35] = capture $58[18:35]
43 [20] Goto bb1
44 bb4 (value):
45 predecessor blocks: bb2
46 - [23] store $64[23:38] = Array []
47 - [24] store $66[24:38] = StoreLocal Reassign mutate x$41[24:38] = capture $64[23:38]
48 - [25] mutate $67[25:38] = LoadLocal capture x$41[24:38]
46 + [23] store $64[23:38]:TObject<Array> = Array []
47 + [24] store $66[24:38]:TObject<Array> = StoreLocal Reassign store x$41[24:38]:TObject<Array> = capture $64[23:38]:TObject<Array>
48 + [25] mutate $67[25:38]:TObject<Array> = LoadLocal capture x$41[24:38]:TObject<Array>
49 [26] mutate $68 = LoadLocal read props$39
50 [27] mutate $69 = PropertyLoad read $68.bar
51 - [28] mutate $70[28:35] = PropertyCall mutate $67[25:38].push(read $69)
51 + [28] mutate $70[28:35] = PropertyCall mutate $67[25:38]:TObject<Array>.push(read $69)
52 [29] store $72[29:35] = StoreLocal Const mutate $59[7:35] = capture $70[28:35]
53 [30] Goto bb1
54 bb1 (block):
55 predecessor blocks: bb3 bb4
56 $75[7:35]:TPhi: phi(bb3: $59, bb4: $71)
57 - x$41[14:38]:TPhi: phi(bb3: x$41, bb4: x$41)
57 + x$41[14:38]:TObject<Array>: phi(bb3: x$41, bb4: x$41)
58 [31] store $74[31:35] = StoreLocal Const mutate _$73[31:35] = capture $59[7:35]
59 [32] mutate $76 = Global console
60 [33] mutate $77[33:35] = LoadLocal capture _$73[31:35]
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary.expect.md
+13 -13
@@ -18,12 +18,12 @@ function foo(props) {
18
19 ```javascript
20 bb0 (block):
21 - [1] store $37[1:7] = Array []
22 - [2] store $39[2:7] = StoreLocal Let mutate x$38[2:7] = capture $37[1:7]
23 - [3] mutate $40[3:7] = LoadLocal capture x$38[2:7]
21 + [1] store $37[1:7]:TObject<Array> = Array []
22 + [2] store $39[2:7]:TObject<Array> = StoreLocal Let store x$38[2:7]:TObject<Array> = capture $37[1:7]:TObject<Array>
23 + [3] mutate $40[3:7]:TObject<Array> = LoadLocal capture x$38[2:7]:TObject<Array>
24 [4] mutate $41 = LoadLocal read props$36
25 [5] mutate $42 = PropertyLoad read $41.bar
26 - [6] mutate $43 = PropertyCall mutate $40[3:7].push(read $42)
26 + [6] mutate $43 = PropertyCall mutate $40[3:7]:TObject<Array>.push(read $42)
27 [7] Ternary test:bb2 fallthrough=bb1
28 bb2 (value):
29 predecessor blocks: bb0
@@ -32,28 +32,28 @@ bb2 (value):
32 [10] Branch (read $45) then:bb3 else:bb4
33 bb3 (value):
34 predecessor blocks: bb2
35 - [13] store $49[13:19] = Array []
36 - [14] store $51[14:19] = StoreLocal Reassign mutate x$38[14:19] = capture $49[13:19]
37 - [15] mutate $52[15:19] = LoadLocal capture x$38[14:19]
35 + [13] store $49[13:19]:TObject<Array> = Array []
36 + [14] store $51[14:19]:TObject<Array> = StoreLocal Reassign store x$38[14:19]:TObject<Array> = capture $49[13:19]:TObject<Array>
37 + [15] mutate $52[15:19]:TObject<Array> = LoadLocal capture x$38[14:19]:TObject<Array>
38 [16] mutate $53 = LoadLocal read props$36
39 [17] mutate $54 = PropertyLoad read $53.foo
40 - [18] mutate $55[18:35] = PropertyCall mutate $52[15:19].push(read $54)
40 + [18] mutate $55[18:35] = PropertyCall mutate $52[15:19]:TObject<Array>.push(read $54)
41 [19] store $57[19:35] = StoreLocal Const mutate $56[7:35] = capture $55[18:35]
42 [20] Goto bb1
43 bb4 (value):
44 predecessor blocks: bb2
45 - [23] store $61[23:29] = Array []
46 - [24] store $63[24:29] = StoreLocal Reassign mutate x$38[24:29] = capture $61[23:29]
47 - [25] mutate $64[25:29] = LoadLocal capture x$38[24:29]
45 + [23] store $61[23:29]:TObject<Array> = Array []
46 + [24] store $63[24:29]:TObject<Array> = StoreLocal Reassign store x$38[24:29]:TObject<Array> = capture $61[23:29]:TObject<Array>
47 + [25] mutate $64[25:29]:TObject<Array> = LoadLocal capture x$38[24:29]:TObject<Array>
48 [26] mutate $65 = LoadLocal read props$36
49 [27] mutate $66 = PropertyLoad read $65.bar
50 - [28] mutate $67[28:35] = PropertyCall mutate $64[25:29].push(read $66)
50 + [28] mutate $67[28:35] = PropertyCall mutate $64[25:29]:TObject<Array>.push(read $66)
51 [29] store $69[29:35] = StoreLocal Const mutate $56[7:35] = capture $67[28:35]
52 [30] Goto bb1
53 bb1 (block):
54 predecessor blocks: bb3 bb4
55 $72[7:35]:TPhi: phi(bb3: $56, bb4: $68)
56 - x$38:TPhi: phi(bb3: x$38, bb4: x$38)
56 + x$38:TObject<Array>: phi(bb3: x$38, bb4: x$38)
57 [31] store $71[31:35] = StoreLocal Const mutate _$70[31:35] = capture $56[7:35]
58 [32] mutate $73 = Global console
59 [33] mutate $74[33:35] = LoadLocal capture _$70[31:35]
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-with-mutation.expect.md
+13 -13
@@ -24,36 +24,36 @@ function foo(props) {
24
25 ```javascript
26 bb0 (block):
27 - [1] store $32[1:7] = Array []
28 - [2] store $34[2:7] = StoreLocal Let mutate x$33[2:31] = capture $32[1:7]
29 - [3] mutate $35[3:7] = LoadLocal capture x$33[2:31]
27 + [1] store $32[1:7]:TObject<Array> = Array []
28 + [2] store $34[2:7]:TObject<Array> = StoreLocal Let store x$33[2:31]:TObject<Array> = capture $32[1:7]:TObject<Array>
29 + [3] mutate $35[3:7]:TObject<Array> = LoadLocal capture x$33[2:31]:TObject<Array>
30 [4] mutate $36 = LoadLocal read props$31
31 [5] mutate $37 = PropertyLoad read $36.bar
32 - [6] mutate $38 = PropertyCall mutate $35[3:7].push(read $37)
32 + [6] mutate $38 = PropertyCall mutate $35[3:7]:TObject<Array>.push(read $37)
33 [7] mutate $39 = LoadLocal read props$31
34 [8] mutate $40 = PropertyLoad read $39.cond
35 [9] If (read $40) then:bb2 else:bb3 fallthrough=bb1
36 bb2 (block):
37 predecessor blocks: bb0
38 - [12] store $44[12:31] = Array []
39 - [13] store $46[13:31] = StoreLocal Reassign mutate x$33[13:31] = capture $44[12:31]
40 - [14] mutate $47[14:31] = LoadLocal capture x$33[13:31]
38 + [12] store $44[12:31]:TObject<Array> = Array []
39 + [13] store $46[13:31]:TObject<Array> = StoreLocal Reassign store x$33[13:31]:TObject<Array> = capture $44[12:31]:TObject<Array>
40 + [14] mutate $47[14:31]:TObject<Array> = LoadLocal capture x$33[13:31]:TObject<Array>
41 [15] mutate $48 = LoadLocal read props$31
42 [16] mutate $49 = PropertyLoad read $48.foo
43 - [17] mutate $50 = PropertyCall mutate $47[14:31].push(read $49)
43 + [17] mutate $50 = PropertyCall mutate $47[14:31]:TObject<Array>.push(read $49)
44 [18] Goto bb1
45 bb3 (block):
46 predecessor blocks: bb0
47 - [21] store $54[21:31] = Array []
48 - [22] store $56[22:31] = StoreLocal Reassign mutate x$33[22:31] = capture $54[21:31]
49 - [23] mutate $57[23:31] = LoadLocal capture x$33[22:31]
47 + [21] store $54[21:31]:TObject<Array> = Array []
48 + [22] store $56[22:31]:TObject<Array> = StoreLocal Reassign store x$33[22:31]:TObject<Array> = capture $54[21:31]:TObject<Array>
49 + [23] mutate $57[23:31]:TObject<Array> = LoadLocal capture x$33[22:31]:TObject<Array>
50 [24] mutate $58 = LoadLocal read props$31
51 [25] mutate $59 = PropertyLoad read $58.bar
52 - [26] mutate $60 = PropertyCall mutate $57[23:31].push(read $59)
52 + [26] mutate $60 = PropertyCall mutate $57[23:31]:TObject<Array>.push(read $59)
53 [27] Goto bb1
54 bb1 (block):
55 predecessor blocks: bb2 bb3
56 - x$33[13:31]:TPhi: phi(bb2: x$33, bb3: x$33)
56 + x$33[13:31]:TObject<Array>: phi(bb2: x$33, bb3: x$33)
57 [28] mutate $61:TFunction = Global mut
58 [29] mutate $62[29:31] = LoadLocal capture x$33[13:31]
59 [30] mutate $64 = Call read $61:TFunction(mutate $62[29:31])