diff --git a/compiler/forget/src/HIR/Environment.ts b/compiler/forget/src/HIR/Environment.ts index b8806ee80d..487900d013 100644 --- a/compiler/forget/src/HIR/Environment.ts +++ b/compiler/forget/src/HIR/Environment.ts @@ -1,7 +1,17 @@ +import invariant from "invariant"; import { log } from "../Utils/logger"; import { DEFAULT_GLOBALS, Global } from "./Globals"; -import { Effect, IdentifierId, makeIdentifierId, ValueKind } from "./HIR"; +import { + BuiltInType, + Effect, + FunctionType, + IdentifierId, + makeIdentifierId, + Type, + ValueKind, +} from "./HIR"; import { BUILTIN_HOOKS, Hook } from "./Hooks"; +import { BUILTIN_SHAPES, FunctionSignature } from "./ObjectShape"; const HOOK_PATTERN = /^_?use/; @@ -64,4 +74,32 @@ export class Environment { valueKind: ValueKind.Mutable, }; } + + getPropertyType(receiver: Type, property: string): BuiltInType | null { + if (receiver.kind === "Object" || receiver.kind === "Function") { + const { shapeId } = receiver; + if (shapeId !== null) { + const shape = BUILTIN_SHAPES.get(shapeId); + invariant( + shape !== undefined, + `[HIR] Forget internal error: cannot resolve shape ${shapeId}` + ); + return shape.properties.get(property) ?? null; + } + } + return null; + } + + getFunctionSignature(type: FunctionType): FunctionSignature | null { + const { shapeId } = type; + if (shapeId !== null) { + const shape = BUILTIN_SHAPES.get(shapeId); + invariant( + shape !== undefined, + `[HIR] Forget internal error: cannot resolve shape ${shapeId}` + ); + return shape.functionType; + } + return null; + } } diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 6e4bb101aa..9a1e1e374d 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -445,6 +445,9 @@ export type Phi = { * may be different for ComputedCalls * - {@link PropertyCall.property} remains an rval (i.e. never promoted to a * named identifier). We currently rely on this for codegen. + * + * Type inference does not currently guarantee that {@link PropertyCall.property} + * is a FunctionType. */ type PropertyCall = { kind: "PropertyCall"; diff --git a/compiler/forget/src/HIR/PrintHIR.ts b/compiler/forget/src/HIR/PrintHIR.ts index 65821ed1ab..9139f7e885 100644 --- a/compiler/forget/src/HIR/PrintHIR.ts +++ b/compiler/forget/src/HIR/PrintHIR.ts @@ -269,9 +269,9 @@ export function printInstructionValue(instrValue: ReactiveValue): string { break; } case "PropertyCall": { - value = `PropertyCall ${printPlace(instrValue.receiver)}.${ + value = `PropertyCall ${printPlace(instrValue.receiver)}.${printPlace( instrValue.property - }(${instrValue.args.map((arg) => printPattern(arg)).join(", ")})`; + )}(${instrValue.args.map((arg) => printPattern(arg)).join(", ")})`; break; } case "ComputedCall": { diff --git a/compiler/forget/src/TypeInference/InferTypes.ts b/compiler/forget/src/TypeInference/InferTypes.ts index 72b977a4e9..6c3563fa0f 100644 --- a/compiler/forget/src/TypeInference/InferTypes.ts +++ b/compiler/forget/src/TypeInference/InferTypes.ts @@ -4,6 +4,7 @@ import { Environment } from "../HIR"; import { HIRFunction, Instruction, + makeType, Type, typeEquals, TypeId, @@ -37,7 +38,7 @@ function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]): boolean { } export default function (func: HIRFunction): void { - const unifier = new Unifier(); + const unifier = new Unifier(func.env); for (const e of generate(func)) { unifier.unify(e.left, e.right); } @@ -62,12 +63,25 @@ function apply(func: HIRFunction, unifier: Unifier): void { } } -type TypeEquation = { - left: Type; - right: Type; +type FunctionCallType = { + kind: "FunctionCall"; + returnType: TypeVar; }; -function equation(left: Type, right: Type): TypeEquation { +type PolyType = + | { + kind: "Property"; + object: Type; + propertyName: string; + } + | FunctionCallType; + +type TypeEquation = { + left: Type; + right: Type | PolyType; +}; + +function equation(left: Type, right: Type | PolyType): TypeEquation { return { left, right, @@ -169,14 +183,67 @@ function* generateInstructionTypes( } break; } + + case "PropertyLoad": { + if (left) { + yield equation(left, { + kind: "Property", + object: value.object.identifier.type, + propertyName: value.property, + }); + } + break; + } + + case "PropertyCall": { + const returnType = makeType(); + yield equation(value.property.identifier.type, { + kind: "FunctionCall", + returnType, + }); + if (left) { + yield equation(left, returnType); + } + } } } type Substitution = Map; class Unifier { substitutions: Substitution = new Map(); + env: Environment; + + constructor(env: Environment) { + this.env = env; + } + + unifyFunctionCall(tA: Type, tB: FunctionCallType): void { + const propertyType = this.get(tA); + if (propertyType.kind === "Function") { + const fn = this.env.getFunctionSignature(propertyType); + const returnType = fn?.returnType ?? null; + if (returnType !== null) { + this.unify(tB.returnType, returnType); + } + } + } + + unify(tA: Type, tB: Type | PolyType): void { + if (tB.kind === "Property") { + const objectType = this.get(tB.object); + const propertyType = this.env.getPropertyType( + objectType, + tB.propertyName + ); + if (propertyType !== null) { + this.unify(tA, propertyType); + } + return; + } else if (tB.kind === "FunctionCall") { + this.unifyFunctionCall(tA, tB); + return; + } - unify(tA: Type, tB: Type): void { if (typeEquals(tA, tB)) { return; } diff --git a/compiler/forget/src/__tests__/fixtures/compiler/array-properties.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/array-properties.expect.md new file mode 100644 index 0000000000..2c4bc324b0 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/array-properties.expect.md @@ -0,0 +1,50 @@ + +## Input + +```javascript +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.length; + const y = a.push; + return { a, x, y, z: a.concat }; +} + +``` + +## Code + +```javascript +function Component(props) { + const $ = React.unstable_useMemoCache(7); + const c_0 = $[0] !== props.a; + const c_1 = $[1] !== props.b; + let t0; + if (c_0 || c_1) { + t0 = [props.a, props.b, "hello"]; + $[0] = props.a; + $[1] = props.b; + $[2] = t0; + } else { + t0 = $[2]; + } + const a = t0; + const x = a.length; + const y = a.push; + const c_3 = $[3] !== a; + const c_4 = $[4] !== x; + const c_5 = $[5] !== y; + let t1; + if (c_3 || c_4 || c_5) { + t1 = { a, x, y, z: a.concat }; + $[3] = a; + $[4] = x; + $[5] = y; + $[6] = t1; + } else { + t1 = $[6]; + } + return t1; +} + +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/compiler/array-properties.js b/compiler/forget/src/__tests__/fixtures/compiler/array-properties.js new file mode 100644 index 0000000000..8d314feb33 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/array-properties.js @@ -0,0 +1,6 @@ +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.length; + const y = a.push; + return { a, x, y, z: a.concat }; +} diff --git a/compiler/forget/src/__tests__/fixtures/compiler/array-property-call.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/array-property-call.expect.md new file mode 100644 index 0000000000..8f897264d4 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/array-property-call.expect.md @@ -0,0 +1,59 @@ + +## Input + +```javascript +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.push(42); + const y = a.at(props.c); + + return { a, x, y }; +} + +``` + +## Code + +```javascript +function Component(props) { + const $ = React.unstable_useMemoCache(10); + const c_0 = $[0] !== props.a; + const c_1 = $[1] !== props.b; + const c_2 = $[2] !== props.c; + let t0; + let a; + let x; + if (c_0 || c_1 || c_2) { + a = [props.a, props.b, "hello"]; + x = a.push(42); + t0 = a.at(props.c); + $[0] = props.a; + $[1] = props.b; + $[2] = props.c; + $[3] = t0; + $[4] = a; + $[5] = x; + } else { + t0 = $[3]; + a = $[4]; + x = $[5]; + } + const y = t0; + const c_6 = $[6] !== a; + const c_7 = $[7] !== x; + const c_8 = $[8] !== y; + let t1; + if (c_6 || c_7 || c_8) { + t1 = { a, x, y }; + $[6] = a; + $[7] = x; + $[8] = y; + $[9] = t1; + } else { + t1 = $[9]; + } + return t1; +} + +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/compiler/array-property-call.js b/compiler/forget/src/__tests__/fixtures/compiler/array-property-call.js new file mode 100644 index 0000000000..3356a23cd6 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/array-property-call.js @@ -0,0 +1,7 @@ +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.push(42); + const y = a.at(props.c); + + return { a, x, y }; +} diff --git a/compiler/forget/src/__tests__/fixtures/hir/array-properties.expect.md b/compiler/forget/src/__tests__/fixtures/hir/array-properties.expect.md new file mode 100644 index 0000000000..975aabd471 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/array-properties.expect.md @@ -0,0 +1,39 @@ + +## Input + +```javascript +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.length; + const y = a.push; + return { a, x, y, z: a.concat }; +} + +``` + +## HIR + +```javascript +bb0 (block): + [1] mutate $25 = LoadLocal read props$24 + [2] mutate $26 = PropertyLoad read $25.a + [3] mutate $27 = LoadLocal read props$24 + [4] mutate $28 = PropertyLoad read $27.b + [5] mutate $29:TPrimitive = "hello" + [6] store $30:TObject = Array [read $26, read $28, read $29:TPrimitive] + [7] store $32:TObject = StoreLocal Const store a$31:TObject = capture $30:TObject + [8] mutate $33:TObject = LoadLocal capture a$31:TObject + [9] mutate $34:TPrimitive = PropertyLoad read $33:TObject.length + [10] store $36:TPrimitive = StoreLocal Const mutate x$35:TPrimitive = capture $34:TPrimitive + [11] mutate $37:TObject = LoadLocal capture a$31:TObject + [12] mutate $38:TFunction<> = PropertyLoad read $37:TObject.push + [13] store $40:TFunction<> = StoreLocal Const mutate y$39:TFunction<> = capture $38:TFunction<> + [14] mutate $41:TObject = LoadLocal capture a$31:TObject + [15] mutate $42:TPrimitive = LoadLocal capture x$35:TPrimitive + [16] mutate $43:TFunction<> = LoadLocal capture y$39:TFunction<> + [17] mutate $44:TObject = LoadLocal capture a$31:TObject + [18] mutate $45:TFunction<> = PropertyLoad read $44:TObject.concat + [19] store $46:TObject = Object { a: capture $41:TObject, x: capture $42:TPrimitive, y: capture $43:TFunction<>, z: capture $45:TFunction<> } + [20] Return freeze $46:TObject +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/array-properties.js b/compiler/forget/src/__tests__/fixtures/hir/array-properties.js new file mode 100644 index 0000000000..8d314feb33 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/array-properties.js @@ -0,0 +1,6 @@ +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.length; + const y = a.push; + return { a, x, y, z: a.concat }; +} diff --git a/compiler/forget/src/__tests__/fixtures/hir/array-property-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/array-property-call.expect.md new file mode 100644 index 0000000000..bad8635364 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/array-property-call.expect.md @@ -0,0 +1,43 @@ + +## Input + +```javascript +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.push(42); + const y = a.at(props.c); + + return { a, x, y }; +} + +``` + +## HIR + +```javascript +bb0 (block): + [1] mutate $28 = LoadLocal read props$27 + [2] mutate $29 = PropertyLoad read $28.a + [3] mutate $30 = LoadLocal read props$27 + [4] mutate $31 = PropertyLoad read $30.b + [5] mutate $32:TPrimitive = "hello" + [6] store $33[6:18]:TObject = Array [read $29, read $31, read $32:TPrimitive] + [7] store $35[7:18]:TObject = StoreLocal Const store a$34[7:18]:TObject = capture $33[6:18]:TObject + [8] mutate $36[8:18]:TObject = LoadLocal capture a$34[7:18]:TObject + [9] mutate $37:TPrimitive = 42 + [10] mutate $38[10:18]:TFunction<> = PropertyLoad read $36[8:18]:TObject.push + [11] mutate $39:TPrimitive = PropertyCall mutate $36[8:18]:TObject.read $38[10:18]:TFunction<>(read $37:TPrimitive) + [12] store $41:TPrimitive = StoreLocal Const mutate x$40:TPrimitive = capture $39:TPrimitive + [13] mutate $42[13:18]:TObject = LoadLocal capture a$34[7:18]:TObject + [14] mutate $43 = LoadLocal read props$27 + [15] mutate $44 = PropertyLoad read $43.c + [16] mutate $45[16:18]:TFunction<> = PropertyLoad read $42[13:18]:TObject.at + [17] mutate $46 = PropertyCall mutate $42[13:18]:TObject.read $45[16:18]:TFunction<>(read $44) + [18] store $48 = StoreLocal Const mutate y$47 = capture $46 + [19] mutate $49:TObject = LoadLocal capture a$34[7:18]:TObject + [20] mutate $50:TPrimitive = LoadLocal capture x$40:TPrimitive + [21] mutate $51 = LoadLocal capture y$47 + [22] store $52:TObject = Object { a: capture $49:TObject, x: capture $50:TPrimitive, y: capture $51 } + [23] Return freeze $52:TObject +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/array-property-call.js b/compiler/forget/src/__tests__/fixtures/hir/array-property-call.js new file mode 100644 index 0000000000..3356a23cd6 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/array-property-call.js @@ -0,0 +1,7 @@ +function Component(props) { + const a = [props.a, props.b, "hello"]; + const x = a.push(42); + const y = a.at(props.c); + + return { a, x, y }; +} diff --git a/compiler/forget/src/__tests__/fixtures/hir/infer-call-array-length.expect.md b/compiler/forget/src/__tests__/fixtures/hir/infer-call-array-length.expect.md new file mode 100644 index 0000000000..7506aac791 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/infer-call-array-length.expect.md @@ -0,0 +1,26 @@ + +## Input + +```javascript +function Component() { + let x = []; + let y = x.length(); + return y; +} + +``` + +## HIR + +```javascript +bb0 (block): + [1] store $10[1:6]:TObject = Array [] + [2] store $12[2:6]:TObject = StoreLocal Const store x$11[2:6]:TObject = capture $10[1:6]:TObject + [3] mutate $13[3:6]:TObject = LoadLocal capture x$11[2:6]:TObject + [4] mutate $14[4:6]:TPrimitive = PropertyLoad read $13[3:6]:TObject.length + [5] mutate $15 = PropertyCall mutate $13[3:6]:TObject.read $14[4:6]:TPrimitive() + [6] store $17 = StoreLocal Const mutate y$16 = capture $15 + [7] mutate $18 = LoadLocal capture y$16 + [8] Return freeze $18 +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/infer-call-array-length.js b/compiler/forget/src/__tests__/fixtures/hir/infer-call-array-length.js new file mode 100644 index 0000000000..6aa8841509 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/infer-call-array-length.js @@ -0,0 +1,5 @@ +function Component() { + let x = []; + let y = x.length(); + return y; +} diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction-with-mutation.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction-with-mutation.expect.md index 12a39cb391..9fd4956180 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction-with-mutation.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction-with-mutation.expect.md @@ -24,8 +24,8 @@ bb0 (block): [3] mutate $41[3:36]:TObject = LoadLocal capture x$39[2:36]:TObject [4] mutate $42 = LoadLocal read props$37 [5] mutate $43 = PropertyLoad read $42.bar - [6] mutate $44[6:36] = PropertyLoad read $41[3:36]:TObject.push - [7] mutate $45 = PropertyCall mutate $41[3:36]:TObject.[object Object](read $43) + [6] mutate $44[6:36]:TFunction<> = PropertyLoad read $41[3:36]:TObject.push + [7] mutate $45:TPrimitive = PropertyCall mutate $41[3:36]:TObject.read $44[6:36]:TFunction<>(read $43) [8] Ternary test:bb2 fallthrough=bb1 bb2 (value): predecessor blocks: bb0 @@ -41,7 +41,7 @@ bb3 (value): [19] mutate $57 = LoadLocal read props$37 [20] mutate $58 = PropertyLoad read $57.foo [21] mutate $59[21:36] = PropertyLoad read $56[18:36].push - [22] mutate $60[22:33] = PropertyCall mutate $56[18:36].[object Object](read $58) + [22] mutate $60[22:33] = PropertyCall mutate $56[18:36].read $59[21:36](read $58) [23] store $62[23:33] = StoreLocal Const mutate $61[8:33] = capture $60[22:33] [24] Goto bb1 bb4 (value): @@ -57,7 +57,7 @@ bb1 (block): [29] mutate $69 = Global console [30] mutate $70[30:33] = LoadLocal capture _$66[28:33] [31] mutate $71 = PropertyLoad read $69.log - [32] mutate $72 = PropertyCall read $69.[object Object](mutate $70[30:33]) + [32] mutate $72 = PropertyCall read $69.read $71(mutate $70[30:33]) [33] mutate $73:TFunction = Global mut [34] mutate $74[34:36] = LoadLocal capture x$39[2:36] [35] mutate $76 = Call read $73:TFunction(mutate $74[34:36]) diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction.expect.md index 8b65c73c61..b143a7e0af 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-destruction.expect.md @@ -23,8 +23,8 @@ bb0 (block): [3] mutate $38[3:8]:TObject = LoadLocal capture x$36[2:8]:TObject [4] mutate $39 = LoadLocal read props$34 [5] mutate $40 = PropertyLoad read $39.bar - [6] mutate $41[6:8] = PropertyLoad read $38[3:8]:TObject.push - [7] mutate $42 = PropertyCall mutate $38[3:8]:TObject.[object Object](read $40) + [6] mutate $41[6:8]:TFunction<> = PropertyLoad read $38[3:8]:TObject.push + [7] mutate $42:TPrimitive = PropertyCall mutate $38[3:8]:TObject.read $41[6:8]:TFunction<>(read $40) [8] Ternary test:bb2 fallthrough=bb1 bb2 (value): predecessor blocks: bb0 @@ -40,7 +40,7 @@ bb3 (value): [19] mutate $54 = LoadLocal read props$34 [20] mutate $55 = PropertyLoad read $54.foo [21] mutate $56[21:23] = PropertyLoad read $53[18:23].push - [22] mutate $57[22:33] = PropertyCall mutate $53[18:23].[object Object](read $55) + [22] mutate $57[22:33] = PropertyCall mutate $53[18:23].read $56[21:23](read $55) [23] store $59[23:33] = StoreLocal Const mutate $58[8:33] = capture $57[22:33] [24] Goto bb1 bb4 (value): @@ -56,7 +56,7 @@ bb1 (block): [29] mutate $66 = Global console [30] mutate $67[30:33] = LoadLocal capture _$63[28:33] [31] mutate $68 = PropertyLoad read $66.log - [32] mutate $69 = PropertyCall read $66.[object Object](mutate $67[30:33]) + [32] mutate $69 = PropertyCall read $66.read $68(mutate $67[30:33]) [33] mutate $70 = LoadLocal capture x$36 [34] Return freeze $70 ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-with-mutation.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-with-mutation.expect.md index a94dc61094..d6ebe2504c 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-with-mutation.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary-with-mutation.expect.md @@ -22,8 +22,8 @@ bb0 (block): [3] mutate $39[3:34]:TObject = LoadLocal capture x$37[2:34]:TObject [4] mutate $40 = LoadLocal read props$35 [5] mutate $41 = PropertyLoad read $40.bar - [6] mutate $42[6:34] = PropertyLoad read $39[3:34]:TObject.push - [7] mutate $43 = PropertyCall mutate $39[3:34]:TObject.[object Object](read $41) + [6] mutate $42[6:34]:TFunction<> = PropertyLoad read $39[3:34]:TObject.push + [7] mutate $43:TPrimitive = PropertyCall mutate $39[3:34]:TObject.read $42[6:34]:TFunction<>(read $41) [8] Ternary test:bb2 fallthrough=bb1 bb2 (value): predecessor blocks: bb0 @@ -37,24 +37,24 @@ bb3 (value): [16] mutate $52[16:34]:TObject = LoadLocal capture x$37[15:34]:TObject [17] mutate $53 = LoadLocal read props$35 [18] mutate $54 = PropertyLoad read $53.foo - [19] mutate $55[19:34] = PropertyLoad read $52[16:34]:TObject.push - [20] mutate $56[20:31] = PropertyCall mutate $52[16:34]:TObject.[object Object](read $54) - [21] store $58[21:31] = StoreLocal Const mutate $57[8:31] = capture $56[20:31] + [19] mutate $55[19:34]:TFunction<> = PropertyLoad read $52[16:34]:TObject.push + [20] mutate $56[20:31]:TPrimitive = PropertyCall mutate $52[16:34]:TObject.read $55[19:34]:TFunction<>(read $54) + [21] store $58[21:31]:TPrimitive = StoreLocal Const mutate $57[8:31]:TPrimitive = capture $56[20:31]:TPrimitive [22] Goto bb1 bb4 (value): predecessor blocks: bb2 [23] mutate $59[23:31]:TPrimitive = null - [24] store $61[24:31]:TPrimitive = StoreLocal Const mutate $57[8:31] = read $59[23:31]:TPrimitive + [24] store $61[24:31]:TPrimitive = StoreLocal Const mutate $57[8:31]:TPrimitive = read $59[23:31]:TPrimitive [25] Goto bb1 bb1 (block): predecessor blocks: bb3 bb4 - $64[8:31]:TPhi: phi(bb3: $57, bb4: $60) + $64[8:31]:TPrimitive: phi(bb3: $57, bb4: $60) x$37[2:34]:TObject: phi(bb3: x$37, bb4: x$37) - [26] store $63[26:31] = StoreLocal Const mutate _$62[26:31] = capture $57[8:31] + [26] store $63[26:31] = StoreLocal Const mutate _$62[26:31] = capture $57[8:31]:TPrimitive [27] mutate $65 = Global console [28] mutate $66[28:31] = LoadLocal capture _$62[26:31] [29] mutate $67 = PropertyLoad read $65.log - [30] mutate $68 = PropertyCall read $65.[object Object](mutate $66[28:31]) + [30] mutate $68 = PropertyCall read $65.read $67(mutate $66[28:31]) [31] mutate $69:TFunction = Global mut [32] mutate $70[32:34] = LoadLocal capture x$37[2:34] [33] mutate $72 = Call read $69:TFunction(mutate $70[32:34]) diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary.expect.md index 9673cf7507..b4b9d37e8e 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-ternary.expect.md @@ -21,8 +21,8 @@ bb0 (block): [3] mutate $36[3:8]:TObject = LoadLocal capture x$34[2:8]:TObject [4] mutate $37 = LoadLocal read props$32 [5] mutate $38 = PropertyLoad read $37.bar - [6] mutate $39[6:8] = PropertyLoad read $36[3:8]:TObject.push - [7] mutate $40 = PropertyCall mutate $36[3:8]:TObject.[object Object](read $38) + [6] mutate $39[6:8]:TFunction<> = PropertyLoad read $36[3:8]:TObject.push + [7] mutate $40:TPrimitive = PropertyCall mutate $36[3:8]:TObject.read $39[6:8]:TFunction<>(read $38) [8] Ternary test:bb2 fallthrough=bb1 bb2 (value): predecessor blocks: bb0 @@ -36,24 +36,24 @@ bb3 (value): [16] mutate $49[16:21]:TObject = LoadLocal capture x$34[15:21]:TObject [17] mutate $50 = LoadLocal read props$32 [18] mutate $51 = PropertyLoad read $50.foo - [19] mutate $52[19:21] = PropertyLoad read $49[16:21]:TObject.push - [20] mutate $53[20:31] = PropertyCall mutate $49[16:21]:TObject.[object Object](read $51) - [21] store $55[21:31] = StoreLocal Const mutate $54[8:31] = capture $53[20:31] + [19] mutate $52[19:21]:TFunction<> = PropertyLoad read $49[16:21]:TObject.push + [20] mutate $53[20:31]:TPrimitive = PropertyCall mutate $49[16:21]:TObject.read $52[19:21]:TFunction<>(read $51) + [21] store $55[21:31]:TPrimitive = StoreLocal Const mutate $54[8:31]:TPrimitive = capture $53[20:31]:TPrimitive [22] Goto bb1 bb4 (value): predecessor blocks: bb2 [23] mutate $56[23:31]:TPrimitive = null - [24] store $58[24:31]:TPrimitive = StoreLocal Const mutate $54[8:31] = read $56[23:31]:TPrimitive + [24] store $58[24:31]:TPrimitive = StoreLocal Const mutate $54[8:31]:TPrimitive = read $56[23:31]:TPrimitive [25] Goto bb1 bb1 (block): predecessor blocks: bb3 bb4 - $61[8:31]:TPhi: phi(bb3: $54, bb4: $57) + $61[8:31]:TPrimitive: phi(bb3: $54, bb4: $57) x$34:TObject: phi(bb3: x$34, bb4: x$34) - [26] store $60[26:31] = StoreLocal Const mutate _$59[26:31] = capture $54[8:31] + [26] store $60[26:31] = StoreLocal Const mutate _$59[26:31] = capture $54[8:31]:TPrimitive [27] mutate $62 = Global console [28] mutate $63[28:31] = LoadLocal capture _$59[26:31] [29] mutate $64 = PropertyLoad read $62.log - [30] mutate $65 = PropertyCall read $62.[object Object](mutate $63[28:31]) + [30] mutate $65 = PropertyCall read $62.read $64(mutate $63[28:31]) [31] mutate $66 = LoadLocal capture x$34 [32] Return freeze $66 ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary-with-mutation.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary-with-mutation.expect.md index 935b927313..7ed9278fa3 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary-with-mutation.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary-with-mutation.expect.md @@ -24,8 +24,8 @@ bb0 (block): [3] mutate $47[3:8]:TObject = LoadLocal capture x$45[2:42]:TObject [4] mutate $48 = LoadLocal read props$43 [5] mutate $49 = PropertyLoad read $48.bar - [6] mutate $50[6:8] = PropertyLoad read $47[3:8]:TObject.push - [7] mutate $51 = PropertyCall mutate $47[3:8]:TObject.[object Object](read $49) + [6] mutate $50[6:8]:TFunction<> = PropertyLoad read $47[3:8]:TObject.push + [7] mutate $51:TPrimitive = PropertyCall mutate $47[3:8]:TObject.read $50[6:8]:TFunction<>(read $49) [8] Ternary test:bb2 fallthrough=bb1 bb2 (value): predecessor blocks: bb0 @@ -39,9 +39,9 @@ bb3 (value): [16] mutate $60[16:42]:TObject = LoadLocal capture x$45[15:42]:TObject [17] mutate $61 = LoadLocal read props$43 [18] mutate $62 = PropertyLoad read $61.foo - [19] mutate $63[19:42] = PropertyLoad read $60[16:42]:TObject.push - [20] mutate $64[20:39] = PropertyCall mutate $60[16:42]:TObject.[object Object](read $62) - [21] store $66[21:39] = StoreLocal Const mutate $65[8:39] = capture $64[20:39] + [19] mutate $63[19:42]:TFunction<> = PropertyLoad read $60[16:42]:TObject.push + [20] mutate $64[20:39]:TPrimitive = PropertyCall mutate $60[16:42]:TObject.read $63[19:42]:TFunction<>(read $62) + [21] store $66[21:39]:TPrimitive = StoreLocal Const mutate $65[8:39]:TPrimitive = capture $64[20:39]:TPrimitive [22] Goto bb1 bb4 (value): predecessor blocks: bb2 @@ -50,19 +50,19 @@ bb4 (value): [27] mutate $73[27:42]:TObject = LoadLocal capture x$45[26:42]:TObject [28] mutate $74 = LoadLocal read props$43 [29] mutate $75 = PropertyLoad read $74.bar - [30] mutate $76[30:42] = PropertyLoad read $73[27:42]:TObject.push - [31] mutate $77[31:39] = PropertyCall mutate $73[27:42]:TObject.[object Object](read $75) - [32] store $79[32:39] = StoreLocal Const mutate $65[8:39] = capture $77[31:39] + [30] mutate $76[30:42]:TFunction<> = PropertyLoad read $73[27:42]:TObject.push + [31] mutate $77[31:39]:TPrimitive = PropertyCall mutate $73[27:42]:TObject.read $76[30:42]:TFunction<>(read $75) + [32] store $79[32:39]:TPrimitive = StoreLocal Const mutate $65[8:39]:TPrimitive = capture $77[31:39]:TPrimitive [33] Goto bb1 bb1 (block): predecessor blocks: bb3 bb4 - $82[8:39]:TPhi: phi(bb3: $65, bb4: $78) + $82[8:39]:TPrimitive: phi(bb3: $65, bb4: $78) x$45[15:42]:TObject: phi(bb3: x$45, bb4: x$45) - [34] store $81[34:39] = StoreLocal Const mutate _$80[34:39] = capture $65[8:39] + [34] store $81[34:39] = StoreLocal Const mutate _$80[34:39] = capture $65[8:39]:TPrimitive [35] mutate $83 = Global console [36] mutate $84[36:39] = LoadLocal capture _$80[34:39] [37] mutate $85 = PropertyLoad read $83.log - [38] mutate $86 = PropertyCall read $83.[object Object](mutate $84[36:39]) + [38] mutate $86 = PropertyCall read $83.read $85(mutate $84[36: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]) diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary.expect.md index 1ce2d98123..5562e58710 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-ternary.expect.md @@ -23,8 +23,8 @@ bb0 (block): [3] mutate $44[3:8]:TObject = LoadLocal capture x$42[2:8]:TObject [4] mutate $45 = LoadLocal read props$40 [5] mutate $46 = PropertyLoad read $45.bar - [6] mutate $47[6:8] = PropertyLoad read $44[3:8]:TObject.push - [7] mutate $48 = PropertyCall mutate $44[3:8]:TObject.[object Object](read $46) + [6] mutate $47[6:8]:TFunction<> = PropertyLoad read $44[3:8]:TObject.push + [7] mutate $48:TPrimitive = PropertyCall mutate $44[3:8]:TObject.read $47[6:8]:TFunction<>(read $46) [8] Ternary test:bb2 fallthrough=bb1 bb2 (value): predecessor blocks: bb0 @@ -38,9 +38,9 @@ bb3 (value): [16] mutate $57[16:21]:TObject = LoadLocal capture x$42[15:21]:TObject [17] mutate $58 = LoadLocal read props$40 [18] mutate $59 = PropertyLoad read $58.foo - [19] mutate $60[19:21] = PropertyLoad read $57[16:21]:TObject.push - [20] mutate $61[20:39] = PropertyCall mutate $57[16:21]:TObject.[object Object](read $59) - [21] store $63[21:39] = StoreLocal Const mutate $62[8:39] = capture $61[20:39] + [19] mutate $60[19:21]:TFunction<> = PropertyLoad read $57[16:21]:TObject.push + [20] mutate $61[20:39]:TPrimitive = PropertyCall mutate $57[16:21]:TObject.read $60[19:21]:TFunction<>(read $59) + [21] store $63[21:39]:TPrimitive = StoreLocal Const mutate $62[8:39]:TPrimitive = capture $61[20:39]:TPrimitive [22] Goto bb1 bb4 (value): predecessor blocks: bb2 @@ -49,19 +49,19 @@ bb4 (value): [27] mutate $70[27:32]:TObject = LoadLocal capture x$42[26:32]:TObject [28] mutate $71 = LoadLocal read props$40 [29] mutate $72 = PropertyLoad read $71.bar - [30] mutate $73[30:32] = PropertyLoad read $70[27:32]:TObject.push - [31] mutate $74[31:39] = PropertyCall mutate $70[27:32]:TObject.[object Object](read $72) - [32] store $76[32:39] = StoreLocal Const mutate $62[8:39] = capture $74[31:39] + [30] mutate $73[30:32]:TFunction<> = PropertyLoad read $70[27:32]:TObject.push + [31] mutate $74[31:39]:TPrimitive = PropertyCall mutate $70[27:32]:TObject.read $73[30:32]:TFunction<>(read $72) + [32] store $76[32:39]:TPrimitive = StoreLocal Const mutate $62[8:39]:TPrimitive = capture $74[31:39]:TPrimitive [33] Goto bb1 bb1 (block): predecessor blocks: bb3 bb4 - $79[8:39]:TPhi: phi(bb3: $62, bb4: $75) + $79[8:39]:TPrimitive: phi(bb3: $62, bb4: $75) x$42:TObject: phi(bb3: x$42, bb4: x$42) - [34] store $78[34:39] = StoreLocal Const mutate _$77[34:39] = capture $62[8:39] + [34] store $78[34:39] = StoreLocal Const mutate _$77[34:39] = capture $62[8:39]:TPrimitive [35] mutate $80 = Global console [36] mutate $81[36:39] = LoadLocal capture _$77[34:39] [37] mutate $82 = PropertyLoad read $80.log - [38] mutate $83 = PropertyCall read $80.[object Object](mutate $81[36:39]) + [38] mutate $83 = PropertyCall read $80.read $82(mutate $81[36:39]) [39] mutate $84 = LoadLocal capture x$42 [40] Return freeze $84 ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-with-mutation.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-with-mutation.expect.md index 54d561135c..625e980712 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-with-mutation.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming-unconditional-with-mutation.expect.md @@ -29,8 +29,8 @@ bb0 (block): [3] mutate $38[3:8]:TObject = LoadLocal capture x$36[2:34]:TObject [4] mutate $39 = LoadLocal read props$34 [5] mutate $40 = PropertyLoad read $39.bar - [6] mutate $41[6:8] = PropertyLoad read $38[3:8]:TObject.push - [7] mutate $42 = PropertyCall mutate $38[3:8]:TObject.[object Object](read $40) + [6] mutate $41[6:8]:TFunction<> = PropertyLoad read $38[3:8]:TObject.push + [7] mutate $42:TPrimitive = PropertyCall mutate $38[3:8]:TObject.read $41[6:8]:TFunction<>(read $40) [8] mutate $43 = LoadLocal read props$34 [9] mutate $44 = PropertyLoad read $43.cond [10] If (read $44) then:bb2 else:bb3 fallthrough=bb1 @@ -41,8 +41,8 @@ bb2 (block): [15] mutate $51[15:34]:TObject = LoadLocal capture x$36[14:34]:TObject [16] mutate $52 = LoadLocal read props$34 [17] mutate $53 = PropertyLoad read $52.foo - [18] mutate $54[18:34] = PropertyLoad read $51[15:34]:TObject.push - [19] mutate $55 = PropertyCall mutate $51[15:34]:TObject.[object Object](read $53) + [18] mutate $54[18:34]:TFunction<> = PropertyLoad read $51[15:34]:TObject.push + [19] mutate $55:TPrimitive = PropertyCall mutate $51[15:34]:TObject.read $54[18:34]:TFunction<>(read $53) [20] Goto bb1 bb3 (block): predecessor blocks: bb0 @@ -51,8 +51,8 @@ bb3 (block): [25] mutate $62[25:34]:TObject = LoadLocal capture x$36[24:34]:TObject [26] mutate $63 = LoadLocal read props$34 [27] mutate $64 = PropertyLoad read $63.bar - [28] mutate $65[28:34] = PropertyLoad read $62[25:34]:TObject.push - [29] mutate $66 = PropertyCall mutate $62[25:34]:TObject.[object Object](read $64) + [28] mutate $65[28:34]:TFunction<> = PropertyLoad read $62[25:34]:TObject.push + [29] mutate $66:TPrimitive = PropertyCall mutate $62[25:34]:TObject.read $65[28:34]:TFunction<>(read $64) [30] Goto bb1 bb1 (block): predecessor blocks: bb2 bb3