From 487786f7d4a858cc0dda55e38d10436fad412bc5 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Thu, 2 Mar 2023 14:19:17 -0800 Subject: [PATCH] StoreLocal instruction Adds a new `StoreLocal = ` instruction which stores into . With this change, Instruction.lvalue is _always_ a `const` temporary, and never a named identifier (there's a new validation pass to assert this). StoreLocal is the only way to declare or update a named identifier: the instructionKind property says whether it's a const/let declaration or a reassignment. Naturally a _lot_ of passes had to be updated to make this work, but the existing Effect.Store variant that @gsathya added made this overall straightforward. Note that as of this PR several passes still have code to handle the possibility of an instruction lvalue being something other than a temporary. When we clean that up in a follow-up, there will be a lot less of the duplication that appears here. For example, CodegenReactiveFunction has two places to handle variable declarations in this PR. However, one of them is to handle lvalues, which should now _always_ be temporaries and never emit a regular variable declaration. Similarly, several passes have to build up a table of identifier -> identifier (because of LoadLocal). Longer-term, we should update the Place abstraction so that it directly specifies the instruction which created that temporary, so we can look it up on demand instead of needing an extra mapping. --- compiler/forget/src/CompilerPipeline.ts | 3 + compiler/forget/src/HIR/BuildHIR.ts | 184 +++++++++++------- compiler/forget/src/HIR/HIR.ts | 6 + compiler/forget/src/HIR/PrintHIR.ts | 20 ++ .../src/HIR/ValidateConsistentIdentifiers.ts | 69 +++++++ compiler/forget/src/HIR/visitors.ts | 10 + compiler/forget/src/Inference/InferAlias.ts | 24 +-- .../src/Inference/InferAliasForStores.ts | 3 + .../src/Inference/InferMutableLifetimes.ts | 11 +- .../src/Inference/InferReferenceEffects.ts | 19 +- .../src/Optimization/ConstantPropagation.ts | 8 + .../src/Optimization/DeadCodeElimination.ts | 11 +- .../ReactiveScopes/CodegenReactiveFunction.ts | 71 +++++-- .../InferReactiveIdentifiers.ts | 71 ++++--- .../InferReactiveScopeVariables.ts | 28 ++- .../PropagateScopeDependencies.ts | 59 +++--- compiler/forget/src/SSA/EnterSSA.ts | 11 +- compiler/forget/src/SSA/LeaveSSA.ts | 115 ++++++++--- .../forget/src/TypeInference/InferTypes.ts | 9 + ..._bug.capturing-func-simple-alias.expect.md | 9 +- .../hir/alias-nested-member-path.expect.md | 9 +- .../hir/allocating-primitive-as-dep.expect.md | 59 +++--- .../hir/array-access-assignment.expect.md | 19 +- .../hir/assignment-in-nested-if.expect.md | 8 +- .../hir/assignment-variations.expect.md | 3 +- .../fixtures/hir/bug_object-pattern.expect.md | 9 +- .../hir/capture-func-passed-to-jsx.expect.md | 36 ++-- .../hir/capturing-arrow-function-1.expect.md | 18 +- .../hir/capturing-func-mutate-2.expect.md | 9 +- .../hir/capturing-func-mutate-3.expect.md | 27 +-- .../hir/capturing-func-mutate.expect.md | 9 +- .../hir/capturing-function-1.expect.md | 18 +- ...turing-function-member-expr-call.expect.md | 37 ++-- .../capturing-function-within-block.expect.md | 18 +- .../hir/capturing-member-expr.expect.md | 18 +- .../capturing-nested-member-call.expect.md | 18 +- ...ested-member-expr-in-nested-func.expect.md | 18 +- .../capturing-nested-member-expr.expect.md | 18 +- ...pturing-variable-in-nested-block.expect.md | 18 +- ...ring-variable-in-nested-function.expect.md | 18 +- .../fixtures/hir/component.expect.md | 41 ++-- .../fixtures/hir/concise-arrow-expr.expect.md | 31 +-- .../fixtures/hir/controlled-input.expect.md | 25 +-- .../hir/destructure-capture-global.expect.md | 9 +- .../fixtures/hir/for-logical.expect.md | 4 +- .../fixtures/hir/frozen-after-alias.expect.md | 9 +- .../fixtures/hir/hook-call.expect.md | 19 +- .../hir/hooks-freeze-arguments.expect.md | 9 +- ...reeze-possibly-mutable-arguments.expect.md | 8 +- .../fixtures/hir/independent.expect.md | 28 +-- .../hir/method-call-computed.expect.md | 27 +-- .../hir/method-call-fn-call.expect.md | 18 +- .../fixtures/hir/method-call.expect.md | 18 +- .../hir/mutable-liverange-loop.expect.md | 9 +- .../obj-literal-cached-in-if-else.expect.md | 16 +- ...mutated-after-if-else-with-alias.expect.md | 3 +- .../hir/obj-mutated-after-if-else.expect.md | 3 +- ...-after-nested-if-else-with-alias.expect.md | 3 +- .../hir/object-pattern-params.expect.md | 34 ++-- .../fixtures/hir/primitive-as-dep.expect.md | 49 ++--- .../hir/prop-capturing-function-1.expect.md | 18 +- .../hir/reassignment-conditional.expect.md | 18 +- .../reassignment-separate-scopes.expect.md | 19 +- .../fixtures/hir/reassignment.expect.md | 18 +- .../reduce-reactive-deps-cond-scope.expect.md | 9 +- ...s-dep-and-redeclare-maybe-frozen.expect.md | 19 +- ...me-variable-as-dep-and-redeclare.expect.md | 28 +-- .../fixtures/hir/simple-function-1.expect.md | 9 +- .../fixtures/hir/simple-scope.expect.md | 9 +- .../hir/ssa-arrayexpression.expect.md | 9 +- .../fixtures/hir/ssa-newexpression.expect.md | 9 +- .../hir/ssa-non-empty-initializer.expect.md | 9 +- .../hir/ssa-objectexpression-phi.expect.md | 9 +- .../hir/ssa-objectexpression.expect.md | 9 +- .../hir/ssa-property-alias-if.expect.md | 18 +- ...-property-alias-mutate-inside-if.expect.md | 9 +- .../fixtures/hir/ssa-property.expect.md | 9 +- .../hir/switch-non-final-default.expect.md | 27 +-- .../__tests__/fixtures/hir/switch.expect.md | 19 +- .../hir/tagged-template-literal.expect.md | 9 +- .../__tests__/fixtures/hir/timers.expect.md | 46 ++--- .../hir/type-binary-operator.expect.md | 18 +- .../fixtures/hir/type-field-load.expect.md | 9 +- .../type-test-field-load-binary-op.expect.md | 9 +- .../hir/type-test-field-store.expect.md | 9 +- .../hir/type-test-polymorphic.expect.md | 18 +- .../type-test-return-type-inference.expect.md | 27 +-- .../fixtures/hir/unary-expr.expect.md | 19 +- .../fixtures/hir/useMemo-simple.expect.md | 31 +-- compiler/forget/yarn.lock | 71 +++++-- 90 files changed, 1259 insertions(+), 772 deletions(-) create mode 100644 compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts diff --git a/compiler/forget/src/CompilerPipeline.ts b/compiler/forget/src/CompilerPipeline.ts index 8865b82c59..50ed36278f 100644 --- a/compiler/forget/src/CompilerPipeline.ts +++ b/compiler/forget/src/CompilerPipeline.ts @@ -13,6 +13,7 @@ import { ReactiveFunction, } from "./HIR"; import { EnvironmentOptions, mergeOptions } from "./HIR/Environment"; +import { validateConsistentIdentifiers } from "./HIR/ValidateConsistentIdentifiers"; import { analyseFunctions, dropMemoCalls, @@ -60,6 +61,8 @@ export function* run( enterSSA(hir); yield log({ kind: "hir", name: "SSA", value: hir }); + validateConsistentIdentifiers(hir); + eliminateRedundantPhi(hir); yield log({ kind: "hir", name: "EliminateRedundantPhi", value: hir }); diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 66f202d6a6..025974703d 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -110,7 +110,7 @@ export function lower( param.node.loc ?? GeneratedSource, InstructionKind.Let, param, - { kind: "LoadLocal", place, loc: place.loc } + place ); } else { builder.errors.push({ @@ -590,7 +590,7 @@ function lowerStatement( } case "VariableDeclaration": { const stmt = stmtPath as NodePath; - const nodeKind: string = stmt.node.kind; + const nodeKind: t.VariableDeclaration["kind"] = stmt.node.kind; if (nodeKind === "var") { builder.errors.push({ reason: `(BuildHIR::lowerStatement) Handle ${nodeKind} kinds in VariableDeclaration`, @@ -604,15 +604,24 @@ function lowerStatement( for (const declaration of stmt.get("declarations")) { const id = declaration.get("id"); const init = declaration.get("init"); - let value: InstructionValue; + let value: Place; if (init.node != null) { - value = lowerExpression(builder, init as NodePath); + value = lowerExpressionToTemporary( + builder, + init as NodePath + ); } else { - value = { - kind: "Primitive", - value: undefined, - loc: id.node.loc ?? GeneratedSource, - }; + value = buildTemporaryPlace(builder, id.node.loc ?? GeneratedSource); + builder.push({ + id: makeInstructionId(0), + lvalue: { place: { ...value }, kind: InstructionKind.Const }, + value: { + kind: "Primitive", + value: undefined, + loc: id.node.loc ?? GeneratedSource, + }, + loc: value.loc, + }); } lowerAssignment( builder, @@ -1177,7 +1186,7 @@ function lowerExpression( left.node.loc ?? GeneratedSource, InstructionKind.Reassign, left, - lowerExpression(builder, expr.get("right")) + lowerExpressionToTemporary(builder, expr.get("right")) ); } @@ -1209,21 +1218,41 @@ function lowerExpression( switch (leftNode.type) { case "Identifier": { const leftExpr = left as NodePath; - const place = lowerIdentifier(builder, leftExpr); + const identifier = lowerIdentifier(builder, leftExpr); + const leftPlace = lowerExpressionToTemporary(builder, leftExpr); const right = lowerExpressionToTemporary(builder, expr.get("right")); + const binaryPlace = buildTemporaryPlace(builder, exprLoc); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...place }, kind: InstructionKind.Reassign }, + lvalue: { + place: { ...binaryPlace }, + kind: InstructionKind.Const, + }, value: { kind: "BinaryExpression", operator: binaryOperator, - left: { ...place }, + left: leftPlace, right, loc: exprLoc, }, loc: exprLoc, }); - return { kind: "LoadLocal", place, loc: exprLoc }; + const result = buildTemporaryPlace(builder, exprLoc); + builder.push({ + id: makeInstructionId(0), + lvalue: { place: { ...result }, kind: InstructionKind.Const }, + value: { + kind: "StoreLocal", + lvalue: { + place: { ...identifier }, + kind: InstructionKind.Reassign, + }, + value: { ...binaryPlace }, + loc: exprLoc, + }, + loc: exprLoc, + }); + return { kind: "LoadLocal", place: identifier, loc: exprLoc }; } case "MemberExpression": { // a.b.c += @@ -1546,13 +1575,13 @@ function lowerExpression( }); return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc }; } - const temp = buildTemporaryPlace( + const primitiveTemp = buildTemporaryPlace( builder, expr.node.loc ?? GeneratedSource ); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...temp }, kind: InstructionKind.Const }, + lvalue: { place: { ...primitiveTemp }, kind: InstructionKind.Const }, value: { kind: "Primitive", value: 1, @@ -1560,18 +1589,39 @@ function lowerExpression( }, loc: expr.node.loc ?? GeneratedSource, }); + const temp = buildTemporaryPlace( + builder, + expr.node.loc ?? GeneratedSource + ); const identifier = lowerIdentifier( builder, argument as NodePath ); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...identifier }, kind: InstructionKind.Reassign }, + lvalue: { place: { ...temp }, kind: InstructionKind.Const }, value: { kind: "BinaryExpression", operator: expr.node.operator === "++" ? "+" : "-", left: { ...identifier }, - right: { ...temp }, + right: { ...primitiveTemp }, + loc: exprLoc, + }, + loc: exprLoc, + }); + builder.push({ + id: makeInstructionId(0), + lvalue: { + place: buildTemporaryPlace(builder, exprLoc), + kind: InstructionKind.Const, + }, + value: { + kind: "StoreLocal", + lvalue: { + place: { ...identifier }, + kind: InstructionKind.Reassign, + }, + value: { ...temp }, loc: exprLoc, }, loc: exprLoc, @@ -1883,7 +1933,7 @@ function lowerAssignment( loc: SourceLocation, kind: InstructionKind, lvaluePath: NodePath, - value: InstructionValue + value: Place ): InstructionValue { const lvalueNode = lvaluePath.node; switch (lvalueNode.type) { @@ -1913,6 +1963,7 @@ function lowerAssignment( }; } + const temporary = buildTemporaryPlace(builder, loc); const place: Place = { kind: "Identifier", identifier: identifier, @@ -1921,28 +1972,24 @@ function lowerAssignment( }; builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...place }, kind }, - value, + lvalue: { place: { ...temporary }, kind }, + value: { + kind: "StoreLocal", + lvalue: { + place: { ...place }, + kind, + }, + value, + loc, + }, loc, }); - return { kind: "LoadLocal", place, loc: place.loc }; + return { kind: "LoadLocal", place, loc: temporary.loc }; } case "MemberExpression": { const lvalue = lvaluePath as NodePath; const property = lvalue.get("property"); const object = lowerExpressionToTemporary(builder, lvalue.get("object")); - let valuePlace: Place; - if (value.kind === "LoadLocal") { - valuePlace = value.place; - } else { - valuePlace = buildTemporaryPlace(builder, loc); - builder.push({ - id: makeInstructionId(0), - lvalue: { place: { ...valuePlace }, kind: InstructionKind.Const }, - value, - loc, - }); - } if (!lvalue.node.computed) { if (!property.isIdentifier()) { builder.errors.push({ @@ -1956,7 +2003,7 @@ function lowerAssignment( kind: "PropertyStore", object, property: property.node.name, - value: valuePlace, + value, loc, }; } else { @@ -1974,20 +2021,13 @@ function lowerAssignment( kind: "ComputedStore", object, property: propertyPlace, - value: valuePlace, + value, loc, }; } } case "ArrayPattern": { const lvalue = lvaluePath as NodePath; - const arrayPlace = buildTemporaryPlace(builder, loc); - builder.push({ - id: makeInstructionId(0), - lvalue: { place: { ...arrayPlace }, kind: InstructionKind.Const }, - value, - loc, - }); const elements = lvalue.get("elements"); let hasError = false; for (let i = 0; i < elements.length; i++) { @@ -2018,27 +2058,32 @@ function lowerAssignment( }, loc: element.node.loc ?? GeneratedSource, }); - const value: InstructionValue = { - kind: "ComputedLoad", + const propertyPlace = buildTemporaryPlace(builder, property.loc); + builder.push({ + id: makeInstructionId(0), + lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const }, + value: { + kind: "ComputedLoad", + loc, + object: { ...value }, + property, + }, loc, - object: { ...arrayPlace }, - property, - }; - lowerAssignment(builder, loc, kind, element as NodePath, value); + }); + lowerAssignment( + builder, + loc, + kind, + element as NodePath, + propertyPlace + ); } return hasError ? { kind: "UnsupportedNode", node: lvalueNode, loc } - : { kind: "LoadLocal", place: arrayPlace, loc: arrayPlace.loc }; + : { kind: "LoadLocal", place: value, loc: value.loc }; } case "ObjectPattern": { const lvalue = lvaluePath as NodePath; - const objectPlace = buildTemporaryPlace(builder, loc); - builder.push({ - id: makeInstructionId(0), - lvalue: { place: { ...objectPlace }, kind }, - value, - loc, - }); const properties = lvalue.get("properties"); let hasError = false; for (let i = 0; i < properties.length; i++) { @@ -2072,18 +2117,27 @@ function lowerAssignment( hasError = true; continue; } - const value: InstructionValue = { - kind: "PropertyLoad", + const propertyPlace = buildTemporaryPlace( + builder, + property.node.loc ?? GeneratedSource + ); + builder.push({ + id: makeInstructionId(0), + lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const }, + value: { + kind: "PropertyLoad", + loc, + object: { ...value }, + property: key.node.name, + optional: false, // Key of ObjectPattern (evaluation of LVal) cannot be optional. + }, loc, - object: { ...objectPlace }, - property: key.node.name, - optional: false, // Key of ObjectPattern (evaluation of LVal) cannot be optional. - }; - lowerAssignment(builder, loc, kind, element, value); + }); + lowerAssignment(builder, loc, kind, element, propertyPlace); } return hasError ? { kind: "UnsupportedNode", node: lvalueNode, loc } - : { kind: "LoadLocal", place: objectPlace, loc: objectPlace.loc }; + : { kind: "LoadLocal", place: value, loc: value.loc }; } default: { builder.errors.push({ diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 0db41d1b74..767fda771b 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -418,6 +418,12 @@ export type InstructionValue = place: Place; loc: SourceLocation; } + | { + kind: "StoreLocal"; + lvalue: LValue; + value: Place; + loc: SourceLocation; + } | { kind: "Primitive"; value: number | boolean | string | null | undefined; diff --git a/compiler/forget/src/HIR/PrintHIR.ts b/compiler/forget/src/HIR/PrintHIR.ts index 1168dc5e22..8efb151920 100644 --- a/compiler/forget/src/HIR/PrintHIR.ts +++ b/compiler/forget/src/HIR/PrintHIR.ts @@ -315,6 +315,12 @@ export function printInstructionValue(instrValue: ReactiveValue): string { value = `LoadLocal ${printPlace(instrValue.place)}`; break; } + case "StoreLocal": { + value = `StoreLocal ${instrValue.lvalue.kind} ${printPlace( + instrValue.lvalue.place + )} = ${printPlace(instrValue.value)}`; + break; + } case "PropertyLoad": { value = `PropertyLoad ${printPlace(instrValue.object)}.${ instrValue.property @@ -412,6 +418,20 @@ function isMutable(range: MutableRange): boolean { } function printMutableRange(identifier: Identifier): string { + invariant( + (identifier.mutableRange.start === 0 && + identifier.mutableRange.end === 0) || + identifier.mutableRange.end > identifier.mutableRange.start, + "Identifier mutableRange was invalid: [%s:%s]", + identifier.mutableRange.start, + identifier.mutableRange.end + ); + if (identifier.scope !== null) { + invariant( + identifier.scope.range.end > identifier.scope.range.start, + "Identifier scope mutableRange was invalid" + ); + } const range = identifier.scope !== null ? identifier.scope.range diff --git a/compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts b/compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts new file mode 100644 index 0000000000..0ad9988a51 --- /dev/null +++ b/compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts @@ -0,0 +1,69 @@ +/** + * 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 { CompilerError } from "../CompilerError"; +import { + GeneratedSource, + HIRFunction, + Identifier, + IdentifierId, + SourceLocation, +} from "./HIR"; +import { eachInstructionValueOperand, eachTerminalOperand } from "./visitors"; + +/** + * Validation pass to check that there is a 1:1 mapping between Identifier objects and IdentifierIds, + * ie there can only be one Identifier instance per IdentifierId. + */ +export function validateConsistentIdentifiers(fn: HIRFunction): void { + const identifiers: Identifiers = new Map(); + for (const [, block] of fn.body.blocks) { + for (const phi of block.phis) { + validate(identifiers, phi.id); + for (const [, operand] of phi.operands) { + validate(identifiers, operand); + } + } + for (const instr of block.instructions) { + if (instr.lvalue.place.identifier.name !== null) { + CompilerError.invariant( + `Expected all lvalues to be temporaries, found '${instr.lvalue.place.identifier.name}'`, + instr.lvalue.place.loc + ); + } + validate( + identifiers, + instr.lvalue.place.identifier, + instr.lvalue.place.loc + ); + for (const operand of eachInstructionValueOperand(instr.value)) { + validate(identifiers, operand.identifier, operand.loc); + } + } + for (const operand of eachTerminalOperand(block.terminal)) { + validate(identifiers, operand.identifier, operand.loc); + } + } +} + +type Identifiers = Map; + +function validate( + identifiers: Identifiers, + identifier: Identifier, + loc: SourceLocation | null = null +): void { + const previous = identifiers.get(identifier.id); + if (previous === undefined) { + identifiers.set(identifier.id, identifier); + } else if (identifier !== previous) { + CompilerError.invariant( + `Duplicate identifier for id ${identifier.id}`, + loc ?? GeneratedSource + ); + } +} diff --git a/compiler/forget/src/HIR/visitors.ts b/compiler/forget/src/HIR/visitors.ts index 2da106e5e3..85285b60d5 100644 --- a/compiler/forget/src/HIR/visitors.ts +++ b/compiler/forget/src/HIR/visitors.ts @@ -52,6 +52,11 @@ export function* eachInstructionValueOperand( yield instrValue.place; break; } + case "StoreLocal": { + yield instrValue.lvalue.place; + yield instrValue.value; + break; + } case "PropertyLoad": { yield instrValue.object; break; @@ -181,6 +186,11 @@ export function mapInstructionOperands( instrValue.place = fn(instrValue.place); break; } + case "StoreLocal": { + instrValue.lvalue.place = fn(instrValue.lvalue.place); + instrValue.value = fn(instrValue.value); + break; + } case "NewExpression": case "CallExpression": { instrValue.callee = fn(instrValue.callee); diff --git a/compiler/forget/src/Inference/InferAlias.ts b/compiler/forget/src/Inference/InferAlias.ts index 1bd5df17a6..e4f057fca5 100644 --- a/compiler/forget/src/Inference/InferAlias.ts +++ b/compiler/forget/src/Inference/InferAlias.ts @@ -3,33 +3,24 @@ import { Identifier, Instruction, isPrimitiveType, - LValue, Place, } from "../HIR/HIR"; import DisjointSet from "../Utils/DisjointSet"; export type AliasSet = Set; -class AliasAnalyser { - aliases = new DisjointSet(); - - alias(lvalue: LValue, alias: Place) { - this.aliases.union([lvalue.place.identifier, alias.identifier]); - } -} - export function inferAliases(func: HIRFunction): DisjointSet { - const analyser = new AliasAnalyser(); + const aliases = new DisjointSet(); for (const [_, block] of func.body.blocks) { for (const instr of block.instructions) { - inferInstr(instr, analyser); + inferInstr(instr, aliases); } } - return analyser.aliases; + return aliases; } -function inferInstr(instr: Instruction, state: AliasAnalyser) { +function inferInstr(instr: Instruction, aliases: DisjointSet) { const { lvalue, value: instrValue } = instr; let alias: Place | null = null; switch (instrValue.kind) { @@ -40,6 +31,11 @@ function inferInstr(instr: Instruction, state: AliasAnalyser) { alias = instrValue.place; break; } + case "StoreLocal": { + // aliases.union([instrValue.place.identifier, instrValue.value.identifier]); + alias = instrValue.value; + break; + } case "ComputedLoad": case "PropertyLoad": { alias = instrValue.object; @@ -53,5 +49,5 @@ function inferInstr(instr: Instruction, state: AliasAnalyser) { return; } - state.alias(lvalue, alias); + aliases.union([lvalue.place.identifier, alias.identifier]); } diff --git a/compiler/forget/src/Inference/InferAliasForStores.ts b/compiler/forget/src/Inference/InferAliasForStores.ts index c36b11ee58..79c40bcb73 100644 --- a/compiler/forget/src/Inference/InferAliasForStores.ts +++ b/compiler/forget/src/Inference/InferAliasForStores.ts @@ -24,6 +24,9 @@ export function inferAliasForStores( if (lvalue.place.effect !== Effect.Store) { continue; } + if (value.kind === "StoreLocal") { + maybeAlias(aliases, value.lvalue.place, value.value, instr.id); + } for (const operand of eachInstructionValueOperand(value)) { if ( operand.effect === Effect.Capture || diff --git a/compiler/forget/src/Inference/InferMutableLifetimes.ts b/compiler/forget/src/Inference/InferMutableLifetimes.ts index 52a6dacc95..f7373a51e6 100644 --- a/compiler/forget/src/Inference/InferMutableLifetimes.ts +++ b/compiler/forget/src/Inference/InferMutableLifetimes.ts @@ -118,8 +118,15 @@ export function inferMutableLifetimes( } for (const instr of block.instructions) { - for (const input of eachInstructionOperand(instr)) { - inferPlace(input, instr, inferMutableRangeForStores); + if (instr.value.kind === "StoreLocal") { + inferPlace(instr.value.value, instr, inferMutableRangeForStores); + instr.value.lvalue.place.identifier.mutableRange.start = instr.id; + instr.value.lvalue.place.identifier.mutableRange.end = + makeInstructionId(instr.id + 1); + } else { + for (const input of eachInstructionOperand(instr)) { + inferPlace(input, instr, inferMutableRangeForStores); + } } const lvalueId = instr.lvalue.place.identifier; diff --git a/compiler/forget/src/Inference/InferReferenceEffects.ts b/compiler/forget/src/Inference/InferReferenceEffects.ts index f886ba318b..785883e99d 100644 --- a/compiler/forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/forget/src/Inference/InferReferenceEffects.ts @@ -307,9 +307,9 @@ class InferenceState { } case Effect.Capture: { if ( + valueKind === ValueKind.Immutable || valueKind === ValueKind.Frozen || - valueKind === ValueKind.MaybeFrozen || - valueKind === ValueKind.Immutable + valueKind === ValueKind.MaybeFrozen ) { effect = Effect.Read; } else { @@ -790,6 +790,21 @@ function inferBlock( state.alias(lvalue.place, instrValue.place); continue; } + case "StoreLocal": { + const effect = + state.isDefined(instrValue.lvalue.place) && + state.kind(instrValue.lvalue.place) === ValueKind.Context + ? Effect.Mutate + : Effect.Capture; + state.reference(instrValue.value, effect); + + const lvalue = instr.lvalue; + state.alias(lvalue.place, instrValue.value); + lvalue.place.effect = Effect.Store; + state.alias(instrValue.lvalue.place, instrValue.value); + instrValue.lvalue.place.effect = Effect.Store; + continue; + } default: { assertExhaustive(instrValue, "Unexpected instruction kind"); } diff --git a/compiler/forget/src/Optimization/ConstantPropagation.ts b/compiler/forget/src/Optimization/ConstantPropagation.ts index 77a5504c5d..6a7ca792f0 100644 --- a/compiler/forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/forget/src/Optimization/ConstantPropagation.ts @@ -313,6 +313,14 @@ function evaluateInstruction( case "LoadLocal": { return read(constants, value.place); } + case "StoreLocal": { + const placeValue = read(constants, value.value); + if (placeValue !== null) { + constants.set(value.lvalue.place.identifier.id, placeValue); + } + // NOTE: always return null to avoid replacing the StoreLocal with its value + return null; + } default: { // TODO: handle more cases return null; diff --git a/compiler/forget/src/Optimization/DeadCodeElimination.ts b/compiler/forget/src/Optimization/DeadCodeElimination.ts index 42ddc812a8..4036a6c1cc 100644 --- a/compiler/forget/src/Optimization/DeadCodeElimination.ts +++ b/compiler/forget/src/Optimization/DeadCodeElimination.ts @@ -40,7 +40,7 @@ export function deadCodeElimination(fn: HIRFunction): void { const instr = block.instructions[i]!; if ( !used.has(instr.lvalue.place.identifier) && - pruneableValue(instr.value) && + pruneableValue(instr.value, used) && // Can't prune the last value of a value block, that's its value! !(block.kind !== "block" && i === block.instructions.length - 1) ) { @@ -76,8 +76,15 @@ export function deadCodeElimination(fn: HIRFunction): void { * Returns true if it is safe to prune an instruction with the given value. * Functions which may have side- */ -function pruneableValue(value: InstructionValue): boolean { +function pruneableValue( + value: InstructionValue, + used: Set +): boolean { switch (value.kind) { + case "StoreLocal": { + // Stores are pruneable only if the identifier being stored to is never read later + return !used.has(value.lvalue.place.identifier); + } case "CallExpression": case "ComputedCall": case "ComputedStore": diff --git a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts index bbb2a72867..daae03b26b 100644 --- a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -99,11 +99,7 @@ function codegenBlock(cx: Context, block: ReactiveBlock): t.BlockStatement { for (const item of block) { switch (item.kind) { case "instruction": { - const statement = codegenInstructionNullable( - cx, - item.instruction, - codegenInstructionValue(cx, item.instruction.value) - ); + const statement = codegenInstructionNullable(cx, item.instruction); if (statement !== null) { statements.push(statement); } @@ -359,23 +355,47 @@ function codegenTerminal( function codegenInstructionNullable( cx: Context, - instr: ReactiveInstruction, - value: t.Expression + instr: ReactiveInstruction ): t.Statement | null { let statement; - if (instr.lvalue !== null && cx.hasDeclared(instr.lvalue.place.identifier)) { - statement = codegenInstruction( - cx, - { - ...instr, - lvalue: { - ...instr.lvalue, - kind: InstructionKind.Reassign, - }, - }, - value - ); + if (instr.value.kind === "StoreLocal") { + const kind = cx.hasDeclared(instr.value.lvalue.place.identifier) + ? InstructionKind.Reassign + : instr.value.lvalue.kind; + const value = codegenPlace(cx, instr.value.value); + switch (kind) { + case InstructionKind.Const: { + return createVariableDeclaration(instr.loc, "const", [ + t.variableDeclarator( + convertIdentifier(instr.value.lvalue.place.identifier), + value + ), + ]); + } + case InstructionKind.Let: { + return createVariableDeclaration(instr.loc, "let", [ + t.variableDeclarator( + convertIdentifier(instr.value.lvalue.place.identifier), + value + ), + ]); + } + case InstructionKind.Reassign: { + return createExpressionStatement( + instr.loc, + t.assignmentExpression( + "=", + convertIdentifier(instr.value.lvalue.place.identifier), + value + ) + ); + } + default: { + assertExhaustive(kind, `Unexpected instruction kind '${kind}'`); + } + } } else { + const value = codegenInstructionValue(cx, instr.value); statement = codegenInstruction(cx, instr, value); } if (statement.type === "EmptyStatement") { @@ -473,7 +493,10 @@ function codegenInstruction( cx.temp.set(instr.lvalue.place.identifier.id, value); return t.emptyStatement(); } else { - switch (instr.lvalue.kind) { + const kind = cx.hasDeclared(instr.lvalue.place.identifier) + ? InstructionKind.Reassign + : instr.lvalue.kind; + switch (kind) { case InstructionKind.Const: { return createVariableDeclaration(instr.loc, "const", [ t.variableDeclarator(codegenLVal(instr.lvalue), value), @@ -492,7 +515,7 @@ function codegenInstruction( } default: { assertExhaustive( - instr.lvalue.kind, + kind, `Unexpected instruction kind '${instr.lvalue.kind}'` ); } @@ -704,6 +727,12 @@ function codegenInstructionValue( value = codegenPlace(cx, instrValue.place); break; } + case "StoreLocal": { + CompilerError.invariant( + `Unexpected StoreLocal in codegenInstructionValue`, + instrValue.loc + ); + } case "FunctionExpression": { value = instrValue.expr; break; diff --git a/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts b/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts index b51e11a1f8..f886032234 100644 --- a/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts +++ b/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts @@ -21,27 +21,34 @@ import { } from "./visitors"; type IdentifierReactivity = Map; -class Visitor extends ReactiveFunctionVisitor { - override visitInstruction( - instr: ReactiveInstruction, - reactivityMap: IdentifierReactivity - ) { - this.traverseInstruction(instr, reactivityMap); + +class State { + reactivityMap: IdentifierReactivity = new Map(); + temporaries: Map = new Map(); +} + +class Visitor extends ReactiveFunctionVisitor { + override visitInstruction(instr: ReactiveInstruction, state: State) { + this.traverseInstruction(instr, state); const lval = instr.lvalue; if (lval == null) { return; } const { value } = instr; - let hasReactiveInput = reactivityMap.get(lval.place.identifier.id) === true; - if (!hasReactiveInput && value.kind !== "LoadGlobal") { - for (const operand of eachReactiveValueOperand(value)) { - // We currently treat free variables (from module or global scope) as - // non-reactive. We may later want type information about specific - // free variables, or a toggle `treatFreeVarsAsReactive`. - if (reactivityMap.get(operand.identifier.id)) { - hasReactiveInput = true; - break; - } + let hasReactiveInput = false; + // Globals are currently treated as non-reactive this happens implicitly because LoadGlobal + // has no operands which can be registered as reactive. + // Consider adding an option to declare whether a given global can be reactive or not, or + // a more general "treat all globals as reactive" flag. + for (const operand of eachReactiveValueOperand(value)) { + if (operand.effect === Effect.Store) { + continue; + } + const resolvedId: IdentifierId = + state.temporaries.get(operand.identifier.id) ?? operand.identifier.id; + if (state.reactivityMap.get(resolvedId)) { + hasReactiveInput = true; + break; } } if ( @@ -56,7 +63,7 @@ class Visitor extends ReactiveFunctionVisitor { // allow treating safe hooks as non-reactive. hasReactiveInput = true; } - reactivityMap.set(lval.place.identifier.id, hasReactiveInput); + state.reactivityMap.set(lval.place.identifier.id, hasReactiveInput); if (hasReactiveInput) { // all mutating effects must also be marked as reactive @@ -65,12 +72,10 @@ class Visitor extends ReactiveFunctionVisitor { case Effect.Capture: case Effect.Store: case Effect.Mutate: { - // Explicitly compare to `false` here, since absence from the - // map indicates a free variable - // todo [@mofeiZ] add knowledge about free variables - if (reactivityMap.get(operand.identifier.id) === false) { - reactivityMap.set(operand.identifier.id, true); - } + const resolvedId: IdentifierId = + state.temporaries.get(operand.identifier.id) ?? + operand.identifier.id; + state.reactivityMap.set(resolvedId, true); break; } case Effect.Freeze: @@ -90,6 +95,14 @@ class Visitor extends ReactiveFunctionVisitor { } } } + if (instr.lvalue !== null) { + if (instr.value.kind === "LoadLocal") { + state.temporaries.set( + instr.lvalue.place.identifier.id, + instr.value.place.identifier.id + ); + } + } } } /** @@ -134,18 +147,14 @@ export function inferReactiveIdentifiers( fn: ReactiveFunction ): Set { const visitor = new Visitor(); - const reactivityMap: IdentifierReactivity = new Map(); + const state = new State(); for (const param of fn.params) { - reactivityMap.set(param.identifier.id, true); + state.reactivityMap.set(param.identifier.id, true); } - let size: number; - do { - size = reactivityMap.size; - visitReactiveFunction(fn, visitor, reactivityMap); - } while (reactivityMap.size > size); + visitReactiveFunction(fn, visitor, state); const result = new Set(); - reactivityMap.forEach((isReactive, id) => { + state.reactivityMap.forEach((isReactive, id) => { if (isReactive) result.add(id); }); return result; diff --git a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts index 5f686ad438..bbee09a376 100644 --- a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts +++ b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts @@ -102,14 +102,29 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void { if (range.end > range.start + 1 || mayAllocate(instr.value)) { operands.push(instr.lvalue!.place.identifier); } - for (const operand of eachInstructionOperand(instr)) { + if (instr.value.kind === "StoreLocal") { if ( - isMutable(instr, operand) && - // exclude global variables from being added to scopes, we can't recreate them! - // TODO: improve handling of module-scoped variables and globals - operand.identifier.mutableRange.start > 0 + instr.value.lvalue.place.identifier.mutableRange.end > + instr.value.lvalue.place.identifier.mutableRange.start + 1 ) { - operands.push(operand.identifier); + operands.push(instr.value.lvalue.place.identifier); + } + if ( + isMutable(instr, instr.value.value) && + instr.value.value.identifier.mutableRange.start > 0 + ) { + operands.push(instr.value.value.identifier); + } + } else { + for (const operand of eachInstructionOperand(instr)) { + if ( + isMutable(instr, operand) && + // exclude global variables from being added to scopes, we can't recreate them! + // TODO: improve handling of module-scoped variables and globals + operand.identifier.mutableRange.start > 0 + ) { + operands.push(operand.identifier); + } } } if (operands.length !== 0) { @@ -168,6 +183,7 @@ function isMutable({ id }: Instruction, place: Place): boolean { function mayAllocate(value: InstructionValue): boolean { switch (value.kind) { + case "StoreLocal": case "LoadGlobal": case "TypeCastExpression": case "BinaryExpression": diff --git a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts index 0c81b7fdff..813b65c7d2 100644 --- a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts +++ b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts @@ -522,18 +522,15 @@ class Context { * Record a variable that is declared in some other scope and that is being reassigned in the * current one as a {@link ReactiveScope.reassignments} */ - visitReassignment(lvalue: LValue): void { - if (lvalue.kind !== InstructionKind.Reassign) { - return; - } - const declaration = this.#declarations.get(lvalue.place.identifier.id); + visitReassignment(place: Place): void { + const declaration = this.#declarations.get(place.identifier.id); if ( this.currentScope != null && - lvalue.place.identifier.scope != null && + place.identifier.scope != null && declaration !== undefined && - declaration.scope !== lvalue.place.identifier.scope + declaration.scope !== place.identifier.scope ) { - this.currentScope.reassignments.add(lvalue.place.identifier); + this.currentScope.reassignments.add(place.identifier); } } } @@ -570,21 +567,21 @@ function visit(context: Context, block: ReactiveBlock): void { break; } case "for": { - visitReactiveValue(context, terminal.init); - visitReactiveValue(context, terminal.test); + visitReactiveValue(context, terminal.id, terminal.init); + visitReactiveValue(context, terminal.id, terminal.test); context.enterConditional(() => { - visitReactiveValue(context, terminal.update); + visitReactiveValue(context, terminal.id, terminal.update); visit(context, terminal.loop); }); break; } case "do-while": { visit(context, terminal.loop); - visitReactiveValue(context, terminal.test); + visitReactiveValue(context, terminal.id, terminal.test); break; } case "while": { - visitReactiveValue(context, terminal.test); + visitReactiveValue(context, terminal.id, terminal.test); context.enterConditional(() => { visit(context, terminal.loop); }); @@ -642,22 +639,25 @@ function visit(context: Context, block: ReactiveBlock): void { } } -function visitReactiveValue(context: Context, value: ReactiveValue): void { +function visitReactiveValue( + context: Context, + id: InstructionId, + value: ReactiveValue +): void { switch (value.kind) { case "LogicalExpression": { - visitReactiveValue(context, value.left); - + visitReactiveValue(context, id, value.left); context.enterConditional(() => { - visitReactiveValue(context, value.right); + visitReactiveValue(context, id, value.right); }); break; } case "ConditionalExpression": { - visitReactiveValue(context, value.test); + visitReactiveValue(context, id, value.test); context.enterConditional(() => { - visitReactiveValue(context, value.consequent); - visitReactiveValue(context, value.alternate); + visitReactiveValue(context, id, value.consequent); + visitReactiveValue(context, id, value.alternate); }); break; } @@ -665,7 +665,7 @@ function visitReactiveValue(context: Context, value: ReactiveValue): void { for (const instr of value.instructions) { visitInstruction(context, instr); } - visitInstructionValue(context, value.value, null); + visitInstructionValue(context, id, value.value, null); break; } default: { @@ -678,6 +678,7 @@ function visitReactiveValue(context: Context, value: ReactiveValue): void { function visitInstructionValue( context: Context, + id: InstructionId, value: ReactiveValue, lvalue: LValue | null ): void { @@ -696,20 +697,26 @@ function visitInstructionValue( } else { context.visitProperty(value.object, value.property); } + } else if (value.kind === "StoreLocal") { + context.visitOperand(value.value); + if (value.lvalue.kind === InstructionKind.Reassign) { + context.visitReassignment(value.lvalue.place); + } + context.declare(value.lvalue.place.identifier, { + id, + scope: context.currentScope, + }); } else { - visitReactiveValue(context, value); + visitReactiveValue(context, id, value); } } function visitInstruction(context: Context, instr: ReactiveInstruction): void { const { lvalue } = instr; - visitInstructionValue(context, instr.value, lvalue); + visitInstructionValue(context, instr.id, instr.value, lvalue); if (lvalue == null) { return; } - if (lvalue.kind === InstructionKind.Reassign) { - context.visitReassignment(lvalue); - } context.declare(lvalue.place.identifier, { id: instr.id, scope: context.currentScope, diff --git a/compiler/forget/src/SSA/EnterSSA.ts b/compiler/forget/src/SSA/EnterSSA.ts index 89a2ce8b67..02a16508af 100644 --- a/compiler/forget/src/SSA/EnterSSA.ts +++ b/compiler/forget/src/SSA/EnterSSA.ts @@ -212,7 +212,16 @@ export default function enterSSA(func: HIRFunction): void { } for (const instr of block.instructions) { - mapInstructionOperands(instr, (place) => builder.getPlace(place)); + if (instr.value.kind === "StoreLocal") { + const oldPlace = instr.value.lvalue.place; + const newPlace = builder.definePlace(oldPlace); + instr.lvalue.kind = InstructionKind.Const; + instr.value.lvalue.place = newPlace; + + instr.value.value = builder.getPlace(instr.value.value); + } else { + mapInstructionOperands(instr, (place) => builder.getPlace(place)); + } const oldPlace = instr.lvalue.place; const newPlace = builder.definePlace(oldPlace); diff --git a/compiler/forget/src/SSA/LeaveSSA.ts b/compiler/forget/src/SSA/LeaveSSA.ts index 1104ca6007..223c60664b 100644 --- a/compiler/forget/src/SSA/LeaveSSA.ts +++ b/compiler/forget/src/SSA/LeaveSSA.ts @@ -110,7 +110,7 @@ export function leaveSSA(fn: HIRFunction): void { for (const instr of block.instructions) { // Iterate the instructions and perform any rewrites as well as promoting SSA variables to // `let` or `reassign` where possible. - const { lvalue } = instr; + const { lvalue, value } = instr; if ( lvalue.kind === InstructionKind.Const && rewrites.has(lvalue.place.identifier) @@ -122,16 +122,30 @@ export function leaveSSA(fn: HIRFunction): void { rewrites.get(lvalue.place.identifier) === lvalue.place.identifier ? InstructionKind.Let : InstructionKind.Reassign; - } else if (lvalue.place.identifier.name != null) { - const originalLVal = declarations.get(lvalue.place.identifier.name); + } else if ( + value.kind === "StoreLocal" && + value.lvalue.place.identifier.name != null + ) { + const originalLVal = declarations.get( + value.lvalue.place.identifier.name + ); if (originalLVal === undefined) { - declarations.set(lvalue.place.identifier.name, lvalue); + declarations.set(value.lvalue.place.identifier.name, value.lvalue); + value.lvalue.kind = InstructionKind.Const; } else { // This is an instance of the original id, so we need to promote the original declaration // to a `let` and the current lval to a `reassign` originalLVal.kind = InstructionKind.Let; - lvalue.kind = InstructionKind.Reassign; } + } else if ( + value.kind === "StoreLocal" && + rewrites.has(value.lvalue.place.identifier) + ) { + value.lvalue.kind = + rewrites.get(value.lvalue.place.identifier) === + value.lvalue.place.identifier + ? InstructionKind.Let + : InstructionKind.Reassign; } rewritePlace(lvalue.place, rewrites, declarations); for (const operand of eachInstructionValueOperand(instr.value)) { @@ -223,6 +237,58 @@ export function leaveSSA(fn: HIRFunction): void { ); const declaration = declarations.get(phi.id.name); if (declaration === undefined) { + let initValue: Place; + if (initOperand === null) { + initValue = { + effect: Effect.Read, + kind: "Identifier", + loc: GeneratedSource, + identifier: { + id: fn.env.nextIdentifierId, + name: null, + mutableRange: { + // TODO: this is technically the wrong start range; we do this because the instruction to create the + // undefined and the instruction to store it to the identifier share an InstructionId, which makes + // this value otherwise appear mutable when stored. All that matters is that the range end prior + // to the StoreLocal's instruction id, so we decrement by one. + start: makeInstructionId(block.terminal.id - 1), + end: makeInstructionId(block.terminal.id), + }, + scope: null, + type: { kind: "Primitive" }, + }, + }; + block.instructions.push({ + id: block.terminal.id, + lvalue: { + place: { ...initValue, effect: Effect.Mutate }, + kind: InstructionKind.Const, + }, + value: { + kind: "Primitive", + // TODO: consider leaving the variable uninitialized rather than explicitly undefined. + value: undefined, + loc: GeneratedSource, + }, + loc: GeneratedSource, + }); + } else { + initValue = { + kind: "Identifier", + identifier: initOperand, + effect: Effect.Capture, + loc: GeneratedSource, + }; + } + const lvalue: LValue = { + place: { + kind: "Identifier", + identifier: phi.id, + effect: Effect.Mutate, + loc: GeneratedSource, + }, + kind: InstructionKind.Let, + }; const instr: Instruction = { // NOTE: reuse the terminal id since these lets must be scoped with the terminal anyway. // the mutable range of this canonical id must by definition span from the binding (before @@ -231,34 +297,31 @@ export function leaveSSA(fn: HIRFunction): void { lvalue: { place: { kind: "Identifier", - identifier: phi.id, + identifier: { + id: fn.env.nextIdentifierId, + mutableRange: { + start: block.terminal.id, + end: makeInstructionId(block.terminal.id + 1), + }, + name: null, + scope: null, + type: phi.id.type, + }, effect: Effect.Mutate, loc: GeneratedSource, }, - kind: InstructionKind.Let, + kind: InstructionKind.Const, + }, + value: { + kind: "StoreLocal", + lvalue, + value: initValue, + loc: GeneratedSource, }, - value: - initOperand !== null - ? { - kind: "LoadLocal", - place: { - kind: "Identifier", - identifier: initOperand, - effect: Effect.Read, - loc: GeneratedSource, - }, - loc: GeneratedSource, - } - : { - kind: "Primitive", - // TODO: consider leaving the variable uninitialized rather than explicitly undefined. - value: undefined, - loc: GeneratedSource, - }, loc: GeneratedSource, }; block.instructions.push(instr); - declarations.set(phi.id.name, instr.lvalue); + declarations.set(phi.id.name, lvalue); phi.id.mutableRange.start = terminal.id; if (!isPhiMutatedAfterCreation) { phi.id.mutableRange.end = makeInstructionId(terminal.id + 1); diff --git a/compiler/forget/src/TypeInference/InferTypes.ts b/compiler/forget/src/TypeInference/InferTypes.ts index d7670911dc..1d52f7e21a 100644 --- a/compiler/forget/src/TypeInference/InferTypes.ts +++ b/compiler/forget/src/TypeInference/InferTypes.ts @@ -112,6 +112,15 @@ function* generateInstructionTypes( break; } + case "StoreLocal": { + yield equation(left, value.value.identifier.type); + yield equation( + value.lvalue.place.identifier.type, + value.value.identifier.type + ); + break; + } + case "BinaryExpression": { if (isPrimitiveBinaryOp(value.operator)) { yield equation(value.left.identifier.type, { kind: "Primitive" }); diff --git a/compiler/forget/src/__tests__/fixtures/hir/_bug.capturing-func-simple-alias.expect.md b/compiler/forget/src/__tests__/fixtures/hir/_bug.capturing-func-simple-alias.expect.md index 8de657bb48..5ff013bf3d 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/_bug.capturing-func-simple-alias.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/_bug.capturing-func-simple-alias.expect.md @@ -20,14 +20,15 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(2); const c_0 = $[0] !== a; - let x; + let t0; if (c_0) { - x = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = x; + $[1] = t0; } else { - x = $[1]; + t0 = $[1]; } + const x = t0; (function () { y = x; diff --git a/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md index 63f754b2c9..88c854c57f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md @@ -18,13 +18,14 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(3); - let z; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - z = []; - $[0] = z; + t0 = []; + $[0] = t0; } else { - z = $[0]; + t0 = $[0]; } + const z = t0; let y; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { y = {}; diff --git a/compiler/forget/src/__tests__/fixtures/hir/allocating-primitive-as-dep.expect.md b/compiler/forget/src/__tests__/fixtures/hir/allocating-primitive-as-dep.expect.md index e6031161e4..4d64b373f8 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/allocating-primitive-as-dep.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/allocating-primitive-as-dep.expect.md @@ -41,63 +41,68 @@ function AllocatingPrimitiveAsDep(props) { } const t1 = t0.b + 1; const c_2 = $[2] !== t1; - let y; + let t2; if (c_2) { - y = foo(t1); + t2 = foo(t1); $[2] = t1; - $[3] = y; + $[3] = t2; } else { - y = $[3]; + t2 = $[3]; } + const y = t2; return y; } function PrimitiveAsDepNested(props) { - const $ = React.unstable_useMemoCache(10); + const $ = React.unstable_useMemoCache(11); const c_0 = $[0] !== props.b; const c_1 = $[1] !== props.a; let x; + let y; if (c_0 || c_1) { x = {}; mutate(x); - const c_3 = $[3] !== props.b; + const c_4 = $[4] !== props.b; let t0; - if (c_3) { + if (c_4) { t0 = bar(props.b); - $[3] = props.b; - $[4] = t0; + $[4] = props.b; + $[5] = t0; } else { - t0 = $[4]; + t0 = $[5]; } const t1 = t0 + 1; - const c_5 = $[5] !== t1; - let y; - if (c_5) { - y = foo(t1); - $[5] = t1; - $[6] = y; + const c_6 = $[6] !== t1; + let t2; + if (c_6) { + t2 = foo(t1); + $[6] = t1; + $[7] = t2; } else { - y = $[6]; + t2 = $[7]; } + y = t2; mutate(x, props.a); $[0] = props.b; $[1] = props.a; $[2] = x; + $[3] = y; } else { x = $[2]; + y = $[3]; } - const c_7 = $[7] !== x; - const c_8 = $[8] !== y; - let t2; - if (c_7 || c_8) { - t2 = [x, y]; - $[7] = x; - $[8] = y; - $[9] = t2; + const c_8 = $[8] !== x; + const c_9 = $[9] !== y; + let t3; + if (c_8 || c_9) { + t3 = [x, y]; + $[8] = x; + $[9] = y; + $[10] = t3; } else { - t2 = $[9]; + t3 = $[10]; } - return t2; + return t3; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/array-access-assignment.expect.md b/compiler/forget/src/__tests__/fixtures/hir/array-access-assignment.expect.md index ceac7b26cb..1e0cd1f8ef 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/array-access-assignment.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/array-access-assignment.expect.md @@ -26,14 +26,15 @@ function foo(a, b, c) { if (c_0 || c_1 || c_2) { x = [a]; const c_5 = $[5] !== b; - let y; + let t0; if (c_5) { - y = [null, b]; + t0 = [null, b]; $[5] = b; - $[6] = y; + $[6] = t0; } else { - y = $[6]; + t0 = $[6]; } + const y = t0; z = [[], [], [c]]; x[0] = y[1]; z[0][0] = x[0]; @@ -48,16 +49,16 @@ function foo(a, b, c) { } const c_7 = $[7] !== x; const c_8 = $[8] !== z; - let t0; + let t1; if (c_7 || c_8) { - t0 = [x, z]; + t1 = [x, z]; $[7] = x; $[8] = z; - $[9] = t0; + $[9] = t1; } else { - t0 = $[9]; + t1 = $[9]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/assignment-in-nested-if.expect.md b/compiler/forget/src/__tests__/fixtures/hir/assignment-in-nested-if.expect.md index 4f1f37ae5c..5ee3cdac92 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/assignment-in-nested-if.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/assignment-in-nested-if.expect.md @@ -24,12 +24,14 @@ function useBar(props) { let z = undefined; if (props.a) { if (props.b) { + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - z = baz(); - $[0] = z; + t0 = baz(); + $[0] = t0; } else { - z = $[0]; + t0 = $[0]; } + z = t0; } } return z; diff --git a/compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md b/compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md index 1d31fd3a44..466df3ea3b 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md @@ -16,8 +16,7 @@ function f() { ```javascript function f() { - let x = 3; - x = x >>> 1; + const x = 3 >>> 1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/bug_object-pattern.expect.md b/compiler/forget/src/__tests__/fixtures/hir/bug_object-pattern.expect.md index 1573ca3811..649298ccc0 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/bug_object-pattern.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/bug_object-pattern.expect.md @@ -17,14 +17,15 @@ function component(t) { const $ = React.unstable_useMemoCache(2); const a = t.a; const c_0 = $[0] !== a; - let y; + let t0; if (c_0) { - y = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = y; + $[1] = t0; } else { - y = $[1]; + t0 = $[1]; } + const y = t0; return y; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capture-func-passed-to-jsx.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capture-func-passed-to-jsx.expect.md index 16570e78f8..deb506ce66 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capture-func-passed-to-jsx.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capture-func-passed-to-jsx.expect.md @@ -22,46 +22,50 @@ function component(a, b) { function component(a, b) { const $ = React.unstable_useMemoCache(9); const c_0 = $[0] !== b; - let y; + let t0; if (c_0) { - y = { b: b }; + t0 = { b: b }; $[0] = b; - $[1] = y; + $[1] = t0; } else { - y = $[1]; + t0 = $[1]; } + const y = t0; const c_2 = $[2] !== a; - let z; + let t1; if (c_2) { - z = { a: a }; + t1 = { a: a }; $[2] = a; - $[3] = z; + $[3] = t1; } else { - z = $[3]; + t1 = $[3]; } + const z = t1; const c_4 = $[4] !== z.a; const c_5 = $[5] !== y.b; - let x; + let t2; if (c_4 || c_5) { - x = function () { + t2 = function () { z.a = 2; y.b; }; $[4] = z.a; $[5] = y.b; - $[6] = x; + $[6] = t2; } else { - x = $[6]; + t2 = $[6]; } + const x = t2; const c_7 = $[7] !== x; - let t; + let t3; if (c_7) { - t = ; + t3 = ; $[7] = x; - $[8] = t; + $[8] = t3; } else { - t = $[8]; + t3 = $[8]; } + const t = t3; mutate(x); return t; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-arrow-function-1.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-arrow-function-1.expect.md index 13ad4c6c84..c11c944dbf 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-arrow-function-1.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-arrow-function-1.expect.md @@ -18,25 +18,27 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(4); const c_0 = $[0] !== a; - let z; + let t0; if (c_0) { - z = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = z; + $[1] = t0; } else { - z = $[1]; + t0 = $[1]; } + const z = t0; const c_2 = $[2] !== z; - let x; + let t1; if (c_2) { - x = () => { + t1 = () => { z; }; $[2] = z; - $[3] = x; + $[3] = t1; } else { - x = $[3]; + t1 = $[3]; } + const x = t1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-2.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-2.expect.md index f9b87ad5f7..55339e98d2 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-2.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-2.expect.md @@ -21,14 +21,15 @@ function component(a, b) { function component(a, b) { const $ = React.unstable_useMemoCache(5); const c_0 = $[0] !== b; - let y; + let t0; if (c_0) { - y = { b: b }; + t0 = { b: b }; $[0] = b; - $[1] = y; + $[1] = t0; } else { - y = $[1]; + t0 = $[1]; } + const y = t0; const c_2 = $[2] !== a; const c_3 = $[3] !== y.b; let x; diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-3.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-3.expect.md index 3f31743d4d..1fdf0b7eb0 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-3.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-3.expect.md @@ -20,37 +20,40 @@ function component(a, b) { function component(a, b) { const $ = React.unstable_useMemoCache(7); const c_0 = $[0] !== b; - let y; + let t0; if (c_0) { - y = { b: b }; + t0 = { b: b }; $[0] = b; - $[1] = y; + $[1] = t0; } else { - y = $[1]; + t0 = $[1]; } + const y = t0; const c_2 = $[2] !== a; - let z; + let t1; if (c_2) { - z = { a: a }; + t1 = { a: a }; $[2] = a; - $[3] = z; + $[3] = t1; } else { - z = $[3]; + t1 = $[3]; } + const z = t1; const c_4 = $[4] !== z.a; const c_5 = $[5] !== y.b; - let x; + let t2; if (c_4 || c_5) { - x = function () { + t2 = function () { z.a = 2; y.b; }; $[4] = z.a; $[5] = y.b; - $[6] = x; + $[6] = t2; } else { - x = $[6]; + t2 = $[6]; } + const x = t2; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate.expect.md index 665bd61a88..555b7635c1 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate.expect.md @@ -26,14 +26,15 @@ function component(a, b) { if (c_0 || c_1) { const z = { a: a }; const c_3 = $[3] !== b; - let y; + let t0; if (c_3) { - y = { b: b }; + t0 = { b: b }; $[3] = b; - $[4] = y; + $[4] = t0; } else { - y = $[4]; + t0 = $[4]; } + const y = t0; x = function () { z.a = 2; y.b; diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-1.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-1.expect.md index 640f1805d7..1ba76cd11a 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-1.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-1.expect.md @@ -18,25 +18,27 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(4); const c_0 = $[0] !== a; - let z; + let t0; if (c_0) { - z = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = z; + $[1] = t0; } else { - z = $[1]; + t0 = $[1]; } + const z = t0; const c_2 = $[2] !== z; - let x; + let t1; if (c_2) { - x = function () { + t1 = function () { z; }; $[2] = z; - $[3] = x; + $[3] = t1; } else { - x = $[3]; + t1 = $[3]; } + const x = t1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-member-expr-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-member-expr-call.expect.md index 73a1740d14..cd11bc3c6e 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-member-expr-call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-member-expr-call.expect.md @@ -19,44 +19,45 @@ function component({ mutator }) { ## Code ```javascript -function component(t23) { +function component(t28) { const $ = React.unstable_useMemoCache(7); - const t0 = t23; - const mutator = t0.mutator; + const mutator = t28.mutator; const c_0 = $[0] !== mutator; - let poke; + let t0; if (c_0) { - poke = () => { + t0 = () => { mutator.poke(); }; $[0] = mutator; - $[1] = poke; + $[1] = t0; } else { - poke = $[1]; + t0 = $[1]; } - const c_2 = $[2] !== t0.mutator.user; - let hide; + const poke = t0; + const c_2 = $[2] !== mutator.user; + let t1; if (c_2) { - hide = () => { + t1 = () => { mutator.user.hide(); }; - $[2] = t0.mutator.user; - $[3] = hide; + $[2] = mutator.user; + $[3] = t1; } else { - hide = $[3]; + t1 = $[3]; } + const hide = t1; const c_4 = $[4] !== poke; const c_5 = $[5] !== hide; - let t1; + let t2; if (c_4 || c_5) { - t1 = ; + t2 = ; $[4] = poke; $[5] = hide; - $[6] = t1; + $[6] = t2; } else { - t1 = $[6]; + t2 = $[6]; } - return t1; + return t2; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md index ebdfd83a0e..b6ecc41614 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md @@ -21,25 +21,27 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(4); const c_0 = $[0] !== a; - let z; + let t0; if (c_0) { - z = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = z; + $[1] = t0; } else { - z = $[1]; + t0 = $[1]; } + const z = t0; const c_2 = $[2] !== z; - let x; + let t1; if (c_2) { - x = function () { + t1 = function () { z; }; $[2] = z; - $[3] = x; + $[3] = t1; } else { - x = $[3]; + t1 = $[3]; } + const x = t1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-member-expr.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-member-expr.expect.md index 7ec2f87fd4..9eb8a5cc1c 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-member-expr.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-member-expr.expect.md @@ -18,25 +18,27 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(4); const c_0 = $[0] !== a; - let z; + let t0; if (c_0) { - z = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = z; + $[1] = t0; } else { - z = $[1]; + t0 = $[1]; } + const z = t0; const c_2 = $[2] !== z.a; - let x; + let t1; if (c_2) { - x = function () { + t1 = function () { z.a; }; $[2] = z.a; - $[3] = x; + $[3] = t1; } else { - x = $[3]; + t1 = $[3]; } + const x = t1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-call.expect.md index 9e1667151f..16583f4ac3 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-call.expect.md @@ -27,25 +27,27 @@ function component(a) { t0 = $[1]; } const c_2 = $[2] !== t0; - let z; + let t1; if (c_2) { - z = { a: t0 }; + t1 = { a: t0 }; $[2] = t0; - $[3] = z; + $[3] = t1; } else { - z = $[3]; + t1 = $[3]; } + const z = t1; const c_4 = $[4] !== z.a; - let x; + let t2; if (c_4) { - x = function () { + t2 = function () { z.a.a(); }; $[4] = z.a; - $[5] = x; + $[5] = t2; } else { - x = $[5]; + t2 = $[5]; } + const x = t2; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr-in-nested-func.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr-in-nested-func.expect.md index 33ac90a195..74a8575667 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr-in-nested-func.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr-in-nested-func.expect.md @@ -29,27 +29,29 @@ function component(a) { t0 = $[1]; } const c_2 = $[2] !== t0; - let z; + let t1; if (c_2) { - z = { a: t0 }; + t1 = { a: t0 }; $[2] = t0; - $[3] = z; + $[3] = t1; } else { - z = $[3]; + t1 = $[3]; } + const z = t1; const c_4 = $[4] !== z.a.a; - let x; + let t2; if (c_4) { - x = function () { + t2 = function () { (function () { z.a.a; })(); }; $[4] = z.a.a; - $[5] = x; + $[5] = t2; } else { - x = $[5]; + t2 = $[5]; } + const x = t2; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr.expect.md index 8895ecd944..0ff028550d 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr.expect.md @@ -27,25 +27,27 @@ function component(a) { t0 = $[1]; } const c_2 = $[2] !== t0; - let z; + let t1; if (c_2) { - z = { a: t0 }; + t1 = { a: t0 }; $[2] = t0; - $[3] = z; + $[3] = t1; } else { - z = $[3]; + t1 = $[3]; } + const z = t1; const c_4 = $[4] !== z.a.a; - let x; + let t2; if (c_4) { - x = function () { + t2 = function () { z.a.a; }; $[4] = z.a.a; - $[5] = x; + $[5] = t2; } else { - x = $[5]; + t2 = $[5]; } + const x = t2; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-block.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-block.expect.md index fcbd205f5c..a49d9ace8b 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-block.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-block.expect.md @@ -20,27 +20,29 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(4); const c_0 = $[0] !== a; - let z; + let t0; if (c_0) { - z = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = z; + $[1] = t0; } else { - z = $[1]; + t0 = $[1]; } + const z = t0; const c_2 = $[2] !== z; - let x; + let t1; if (c_2) { - x = function () { + t1 = function () { { z; } }; $[2] = z; - $[3] = x; + $[3] = t1; } else { - x = $[3]; + t1 = $[3]; } + const x = t1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-function.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-function.expect.md index dde6984aed..fdee9711a3 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-function.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-function.expect.md @@ -20,27 +20,29 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(4); const c_0 = $[0] !== a; - let z; + let t0; if (c_0) { - z = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = z; + $[1] = t0; } else { - z = $[1]; + t0 = $[1]; } + const z = t0; const c_2 = $[2] !== z; - let x; + let t1; if (c_2) { - x = function () { + t1 = function () { (function () { z; })(); }; $[2] = z; - $[3] = x; + $[3] = t1; } else { - x = $[3]; + t1 = $[3]; } + const x = t1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/component.expect.md b/compiler/forget/src/__tests__/fixtures/hir/component.expect.md index e1f3544fc4..0acc2fedb3 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/component.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/component.expect.md @@ -45,14 +45,15 @@ function Component(props) { renderedItems = []; const seen = new Set(); const c_3 = $[3] !== maxItems; - let max; + let t0; if (c_3) { - max = Math.max(0, maxItems); + t0 = Math.max(0, maxItems); $[3] = maxItems; - $[4] = max; + $[4] = t0; } else { - max = $[4]; + t0 = $[4]; } + const max = t0; for (let i = 0; i < items.length; i = i + 1, i) { const item = items.at(i); if (item == null || seen.has(item)) { @@ -74,31 +75,31 @@ function Component(props) { const count = renderedItems.length; const c_5 = $[5] !== count; - let t0; - if (c_5) { - t0 =

{count} Items

; - $[5] = count; - $[6] = t0; - } else { - t0 = $[6]; - } - const c_7 = $[7] !== t0; - const c_8 = $[8] !== renderedItems; let t1; + if (c_5) { + t1 =

{count} Items

; + $[5] = count; + $[6] = t1; + } else { + t1 = $[6]; + } + const c_7 = $[7] !== t1; + const c_8 = $[8] !== renderedItems; + let t2; if (c_7 || c_8) { - t1 = ( + t2 = (
- {t0} + {t1} {renderedItems}
); - $[7] = t0; + $[7] = t1; $[8] = renderedItems; - $[9] = t1; + $[9] = t2; } else { - t1 = $[9]; + t2 = $[9]; } - return t1; + return t2; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md b/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md index b0e1da977a..e43709ed22 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md @@ -17,24 +17,25 @@ function component() { const $ = React.unstable_useMemoCache(4); const setX = useState(0)[1]; const c_0 = $[0] !== setX; - let handler; - if (c_0) { - handler = (v) => setX(v); - $[0] = setX; - $[1] = handler; - } else { - handler = $[1]; - } - const c_2 = $[2] !== handler; let t0; - if (c_2) { - t0 = ; - $[2] = handler; - $[3] = t0; + if (c_0) { + t0 = (v) => setX(v); + $[0] = setX; + $[1] = t0; } else { - t0 = $[3]; + t0 = $[1]; } - return t0; + const handler = t0; + const c_2 = $[2] !== handler; + let t1; + if (c_2) { + t1 = ; + $[2] = handler; + $[3] = t1; + } else { + t1 = $[3]; + } + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/controlled-input.expect.md b/compiler/forget/src/__tests__/fixtures/hir/controlled-input.expect.md index 614f9b65d4..1e18384a2c 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/controlled-input.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/controlled-input.expect.md @@ -15,30 +15,31 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(5); - const t1 = useState(0); - const x = t1[0]; - const setX = t1[1]; + const t2 = useState(0); + const x = t2[0]; + const setX = t2[1]; const c_0 = $[0] !== setX; - let handler; + let t0; if (c_0) { - handler = (event) => setX(event.target.value); + t0 = (event) => setX(event.target.value); $[0] = setX; - $[1] = handler; + $[1] = t0; } else { - handler = $[1]; + t0 = $[1]; } + const handler = t0; const c_2 = $[2] !== handler; const c_3 = $[3] !== x; - let t0; + let t1; if (c_2 || c_3) { - t0 = ; + t1 = ; $[2] = handler; $[3] = x; - $[4] = t0; + $[4] = t1; } else { - t0 = $[4]; + t1 = $[4]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/destructure-capture-global.expect.md b/compiler/forget/src/__tests__/fixtures/hir/destructure-capture-global.expect.md index 9f0d022a43..94d5c7c989 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/destructure-capture-global.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/destructure-capture-global.expect.md @@ -17,14 +17,15 @@ let someGlobal = {}; function component(a) { const $ = React.unstable_useMemoCache(2); const c_0 = $[0] !== a; - let x; + let t0; if (c_0) { - x = { a: a, someGlobal: someGlobal }; + t0 = { a: a, someGlobal: someGlobal }; $[0] = a; - $[1] = x; + $[1] = t0; } else { - x = $[1]; + t0 = $[1]; } + const x = t0; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md b/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md index fa80e50243..8a47de3f23 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md @@ -32,9 +32,9 @@ function foo(props) { for ( let x = 0; x > props.min && x < props.max; - x = x$0 + (props.cond ? props.increment : 2), x + x = x + (props.cond ? props.increment : 2), x ) { - const x$0 = x * 2; + x = x * 2; } return y; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md b/compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md index fc8e3c68fd..e3716fd0d4 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md @@ -20,13 +20,14 @@ function foo(x) {} ```javascript function Component() { const $ = React.unstable_useMemoCache(1); - let a; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - a = []; - $[0] = a; + t0 = []; + $[0] = t0; } else { - a = $[0]; + t0 = $[0]; } + const a = t0; const b = a; useFreeze(a); foo(b); diff --git a/compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md index 58beec82e3..4ecc4cc7fa 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md @@ -27,30 +27,31 @@ function foo() {} function Component(props) { const $ = React.unstable_useMemoCache(3); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = []; - $[0] = x; + t0 = []; + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } + const x = t0; const y = useFreeze(x); foo(y, x); const c_1 = $[1] !== y; - let t0; + let t1; if (c_1) { - t0 = ( + t1 = ( {x} {y} ); $[1] = y; - $[2] = t0; + $[2] = t1; } else { - t0 = $[2]; + t1 = $[2]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md index 5309f9b52d..041d0e374f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md @@ -20,13 +20,14 @@ function call(x) {} ```javascript function Component() { const $ = React.unstable_useMemoCache(1); - let a; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - a = []; - $[0] = a; + t0 = []; + $[0] = t0; } else { - a = $[0]; + t0 = $[0]; } + const a = t0; useFreeze(a); useFreeze(a); call(a); diff --git a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md index feec1ee910..77dbdb1337 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md @@ -33,12 +33,14 @@ function Component(props) { if (cond) { a = x; } else { + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - a = []; - $[0] = a; + t0 = []; + $[0] = t0; } else { - a = $[0]; + t0 = $[0]; } + a = t0; } useFreeze(a); diff --git a/compiler/forget/src/__tests__/fixtures/hir/independent.expect.md b/compiler/forget/src/__tests__/fixtures/hir/independent.expect.md index 48cbfb3ba1..9a344bd0d9 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/independent.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/independent.expect.md @@ -40,35 +40,37 @@ function Foo() {} function Component(props) { const $ = React.unstable_useMemoCache(7); const c_0 = $[0] !== props.a; - let a; + let t0; if (c_0) { - a = compute(props.a); + t0 = compute(props.a); $[0] = props.a; - $[1] = a; + $[1] = t0; } else { - a = $[1]; + t0 = $[1]; } + const a = t0; const c_2 = $[2] !== props.b; - let b; + let t1; if (c_2) { - b = compute(props.b); + t1 = compute(props.b); $[2] = props.b; - $[3] = b; + $[3] = t1; } else { - b = $[3]; + t1 = $[3]; } + const b = t1; const c_4 = $[4] !== a; const c_5 = $[5] !== b; - let t0; + let t2; if (c_4 || c_5) { - t0 = ; + t2 = ; $[4] = a; $[5] = b; - $[6] = t0; + $[6] = t2; } else { - t0 = $[6]; + t2 = $[6]; } - return t0; + return t2; } function compute() {} diff --git a/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md b/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md index a051c52c9a..1350a34241 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md @@ -24,36 +24,39 @@ function foo(a, b, c) { function foo(a, b, c) { const $ = React.unstable_useMemoCache(8); const c_0 = $[0] !== a; - let x; + let t0; if (c_0) { - x = makeObject(a); + t0 = makeObject(a); $[0] = a; - $[1] = x; + $[1] = t0; } else { - x = $[1]; + t0 = $[1]; } + const x = t0; const c_2 = $[2] !== a; - let y; + let t1; if (c_2) { - y = makeObject(a); + t1 = makeObject(a); $[2] = a; - $[3] = y; + $[3] = t1; } else { - y = $[3]; + t1 = $[3]; } + const y = t1; const c_4 = $[4] !== x; const c_5 = $[5] !== y.method; const c_6 = $[6] !== b; - let z; + let t2; if (c_4 || c_5 || c_6) { - z = x[y.method](b); + t2 = x[y.method](b); $[4] = x; $[5] = y.method; $[6] = b; - $[7] = z; + $[7] = t2; } else { - z = $[7]; + t2 = $[7]; } + const z = t2; return z; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md index 50758f51f9..110ced0ca0 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md @@ -21,29 +21,31 @@ function foo(a, b, c) { function foo(a, b, c) { const $ = React.unstable_useMemoCache(6); const c_0 = $[0] !== a; - let x; + let t0; if (c_0) { - x = makeObject(a); + t0 = makeObject(a); $[0] = a; - $[1] = x; + $[1] = t0; } else { - x = $[1]; + t0 = $[1]; } + const x = t0; const method = x.method; const c_2 = $[2] !== method; const c_3 = $[3] !== x; const c_4 = $[4] !== b; - let y; + let t1; if (c_2 || c_3 || c_4) { - y = method.call(x, b); + t1 = method.call(x, b); $[2] = method; $[3] = x; $[4] = b; - $[5] = y; + $[5] = t1; } else { - y = $[5]; + t1 = $[5]; } + const y = t1; return y; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md index ec2c29a0fc..ea898b3969 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md @@ -20,25 +20,27 @@ function foo(a, b, c) { function foo(a, b, c) { const $ = React.unstable_useMemoCache(5); const c_0 = $[0] !== a; - let x; + let t0; if (c_0) { - x = makeObject(a); + t0 = makeObject(a); $[0] = a; - $[1] = x; + $[1] = t0; } else { - x = $[1]; + t0 = $[1]; } + const x = t0; const c_2 = $[2] !== x; const c_3 = $[3] !== b; - let y; + let t1; if (c_2 || c_3) { - y = x.foo(b); + t1 = x.foo(b); $[2] = x; $[3] = b; - $[4] = y; + $[4] = t1; } else { - y = $[4]; + t1 = $[4]; } + const y = t1; return y; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md b/compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md index 844e1391e7..465e44b685 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md @@ -44,13 +44,14 @@ function Component(props) { const $ = React.unstable_useMemoCache(1); const a = {}; const b = {}; - let c; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - c = {}; - $[0] = c; + t0 = {}; + $[0] = t0; } else { - c = $[0]; + t0 = $[0]; } + const c = t0; const d = {}; while (true) { mutate(a, b); diff --git a/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md b/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md index c552f392d3..9a1877dcd6 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md @@ -23,22 +23,26 @@ function foo(a, b, c, d) { let x = undefined; if (someVal) { const c_0 = $[0] !== b; + let t0; if (c_0) { - x = { b: b }; + t0 = { b: b }; $[0] = b; - $[1] = x; + $[1] = t0; } else { - x = $[1]; + t0 = $[1]; } + x = t0; } else { const c_2 = $[2] !== c; + let t1; if (c_2) { - x = { c: c }; + t1 = { c: c }; $[2] = c; - $[3] = x; + $[3] = t1; } else { - x = $[3]; + t1 = $[3]; } + x = t1; } return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else-with-alias.expect.md b/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else-with-alias.expect.md index 2a43eb71fb..e14877c15d 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else-with-alias.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else-with-alias.expect.md @@ -23,10 +23,11 @@ function foo(a, b, c, d) { ```javascript function foo(a, b, c, d) { const $ = React.unstable_useMemoCache(2); + someObj(); const c_0 = $[0] !== a; let x; if (c_0) { - x = someObj(); + x = undefined; if (a) { const y = someObj(); const z = y; diff --git a/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else.expect.md b/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else.expect.md index 161b3b01ea..f9e81d1ba9 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else.expect.md @@ -21,10 +21,11 @@ function foo(a, b, c, d) { ```javascript function foo(a, b, c, d) { const $ = React.unstable_useMemoCache(2); + someObj(); const c_0 = $[0] !== a; let x; if (c_0) { - x = someObj(); + x = undefined; if (a) { x = someObj(); } else { diff --git a/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-nested-if-else-with-alias.expect.md b/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-nested-if-else-with-alias.expect.md index 504a45b0b6..9dd095f521 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-nested-if-else-with-alias.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-nested-if-else-with-alias.expect.md @@ -29,11 +29,12 @@ function foo(a, b, c, d) { ```javascript function foo(a, b, c, d) { const $ = React.unstable_useMemoCache(3); + someObj(); const c_0 = $[0] !== a; const c_1 = $[1] !== b; let x; if (c_0 || c_1) { - x = someObj(); + x = undefined; if (a) { let z = undefined; if (b) { diff --git a/compiler/forget/src/__tests__/fixtures/hir/object-pattern-params.expect.md b/compiler/forget/src/__tests__/fixtures/hir/object-pattern-params.expect.md index c0a8ec7d70..09d63d71ff 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/object-pattern-params.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/object-pattern-params.expect.md @@ -13,40 +13,42 @@ function component({ a, b }) { ## Code ```javascript -function component(t12) { +function component(t19) { const $ = React.unstable_useMemoCache(7); - const a = t12.a; - const b = t12.b; + const a = t19.a; + const b = t19.b; const c_0 = $[0] !== a; - let y; + let t0; if (c_0) { - y = { a: a }; + t0 = { a: a }; $[0] = a; - $[1] = y; + $[1] = t0; } else { - y = $[1]; + t0 = $[1]; } + const y = t0; const c_2 = $[2] !== b; - let z; + let t1; if (c_2) { - z = { b: b }; + t1 = { b: b }; $[2] = b; - $[3] = z; + $[3] = t1; } else { - z = $[3]; + t1 = $[3]; } + const z = t1; const c_4 = $[4] !== y; const c_5 = $[5] !== z; - let t0; + let t2; if (c_4 || c_5) { - t0 = { y: y, z: z }; + t2 = { y: y, z: z }; $[4] = y; $[5] = z; - $[6] = t0; + $[6] = t2; } else { - t0 = $[6]; + t2 = $[6]; } - return t0; + return t2; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/primitive-as-dep.expect.md b/compiler/forget/src/__tests__/fixtures/hir/primitive-as-dep.expect.md index d7066d71a9..7db41c5a0f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/primitive-as-dep.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/primitive-as-dep.expect.md @@ -34,54 +34,59 @@ function PrimitiveAsDep(props) { const $ = React.unstable_useMemoCache(2); const t0 = props.b + 1; const c_0 = $[0] !== t0; - let y; + let t1; if (c_0) { - y = foo(t0); + t1 = foo(t0); $[0] = t0; - $[1] = y; + $[1] = t1; } else { - y = $[1]; + t1 = $[1]; } + const y = t1; return y; } function PrimitiveAsDepNested(props) { - const $ = React.unstable_useMemoCache(8); + const $ = React.unstable_useMemoCache(9); const c_0 = $[0] !== props.b; const c_1 = $[1] !== props.a; let x; + let y; if (c_0 || c_1) { x = {}; mutate(x); const t0 = props.b + 1; - const c_3 = $[3] !== t0; - let y; - if (c_3) { - y = foo(t0); - $[3] = t0; - $[4] = y; + const c_4 = $[4] !== t0; + let t1; + if (c_4) { + t1 = foo(t0); + $[4] = t0; + $[5] = t1; } else { - y = $[4]; + t1 = $[5]; } + y = t1; mutate(x, props.a); $[0] = props.b; $[1] = props.a; $[2] = x; + $[3] = y; } else { x = $[2]; + y = $[3]; } - const c_5 = $[5] !== x; - const c_6 = $[6] !== y; - let t1; - if (c_5 || c_6) { - t1 = [x, y]; - $[5] = x; - $[6] = y; - $[7] = t1; + const c_6 = $[6] !== x; + const c_7 = $[7] !== y; + let t2; + if (c_6 || c_7) { + t2 = [x, y]; + $[6] = x; + $[7] = y; + $[8] = t2; } else { - t1 = $[7]; + t2 = $[8]; } - return t1; + return t2; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/prop-capturing-function-1.expect.md b/compiler/forget/src/__tests__/fixtures/hir/prop-capturing-function-1.expect.md index b1280d73f9..7dcbede9de 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/prop-capturing-function-1.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/prop-capturing-function-1.expect.md @@ -19,26 +19,28 @@ function component(a, b) { const $ = React.unstable_useMemoCache(5); const c_0 = $[0] !== a; const c_1 = $[1] !== b; - let z; + let t0; if (c_0 || c_1) { - z = { a: a, b: b }; + t0 = { a: a, b: b }; $[0] = a; $[1] = b; - $[2] = z; + $[2] = t0; } else { - z = $[2]; + t0 = $[2]; } + const z = t0; const c_3 = $[3] !== z; - let x; + let t1; if (c_3) { - x = function () { + t1 = function () { z; }; $[3] = z; - $[4] = x; + $[4] = t1; } else { - x = $[4]; + t1 = $[4]; } + const x = t1; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md index e9514dd4a5..c7552085ba 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md @@ -36,27 +36,29 @@ function Component(props) { } const y = x; if (props.p1) { + let t0; if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - x = []; - $[2] = x; + t0 = []; + $[2] = t0; } else { - x = $[2]; + t0 = $[2]; } + x = t0; } y.push(props.p2); const c_3 = $[3] !== x; const c_4 = $[4] !== y; - let t0; + let t1; if (c_3 || c_4) { - t0 = ; + t1 = ; $[3] = x; $[4] = y; - $[5] = t0; + $[5] = t1; } else { - t0 = $[5]; + t1 = $[5]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md index 0e4381c6f9..79d36dd99e 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md @@ -48,14 +48,15 @@ function foo(a, b, c) { x = $[1]; } const c_2 = $[2] !== x; - let y; + let t0; if (c_2) { - y =
{x}
; + t0 =
{x}
; $[2] = x; - $[3] = y; + $[3] = t0; } else { - y = $[3]; + t0 = $[3]; } + const y = t0; bb3: switch (b) { case 0: { const c_4 = $[4] !== b; @@ -83,9 +84,9 @@ function foo(a, b, c) { } const c_8 = $[8] !== y; const c_9 = $[9] !== x; - let t0; + let t1; if (c_8 || c_9) { - t0 = ( + t1 = (
{y} {x} @@ -93,11 +94,11 @@ function foo(a, b, c) { ); $[8] = y; $[9] = x; - $[10] = t0; + $[10] = t1; } else { - t0 = $[10]; + t1 = $[10]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md index f3d722749e..0b3212b74d 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md @@ -30,12 +30,14 @@ function Component(props) { x = []; x.push(props.p0); y = x; + let t0; if ($[4] === Symbol.for("react.memo_cache_sentinel")) { - x = []; - $[4] = x; + t0 = []; + $[4] = t0; } else { - x = $[4]; + t0 = $[4]; } + x = t0; y.push(props.p1); $[0] = props.p0; @@ -48,16 +50,16 @@ function Component(props) { } const c_5 = $[5] !== x; const c_6 = $[6] !== y; - let t0; + let t1; if (c_5 || c_6) { - t0 = ; + t1 = ; $[5] = x; $[6] = y; - $[7] = t0; + $[7] = t1; } else { - t0 = $[7]; + t1 = $[7]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/reduce-reactive-deps-cond-scope.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reduce-reactive-deps-cond-scope.expect.md index 8cea94f8b8..bbeca80f3a 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reduce-reactive-deps-cond-scope.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reduce-reactive-deps-cond-scope.expect.md @@ -60,14 +60,15 @@ function TestReactiveDepsInCondScope(props) { x = {}; if (foo) { const c_2 = $[2] !== props.a.b; - let tmp; + let t0; if (c_2) { - tmp = bar(props.a.b); + t0 = bar(props.a.b); $[2] = props.a.b; - $[3] = tmp; + $[3] = t0; } else { - tmp = $[3]; + t0 = $[3]; } + const tmp = t0; x.a = tmp; } $[0] = props; diff --git a/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare-maybe-frozen.expect.md b/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare-maybe-frozen.expect.md index 4ba3d1f238..c4f6052007 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare-maybe-frozen.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare-maybe-frozen.expect.md @@ -89,9 +89,9 @@ function foo(props) { } const c_10 = $[10] !== x; const c_11 = $[11] !== y; - let content; + let t1; if (c_10 || c_11) { - content = ( + t1 = (
{x} {y} @@ -99,15 +99,16 @@ function foo(props) { ); $[10] = x; $[11] = y; - $[12] = content; + $[12] = t1; } else { - content = $[12]; + t1 = $[12]; } + const content = t1; const c_13 = $[13] !== header; const c_14 = $[14] !== content; - let t1; + let t2; if (c_13 || c_14) { - t1 = ( + t2 = ( <> {header} {content} @@ -115,11 +116,11 @@ function foo(props) { ); $[13] = header; $[14] = content; - $[15] = t1; + $[15] = t2; } else { - t1 = $[15]; + t2 = $[15]; } - return t1; + return t2; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare.expect.md b/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare.expect.md index 35f80c5340..dc4c090b37 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare.expect.md @@ -58,14 +58,15 @@ function foo(props) { x = $[1]; } const c_2 = $[2] !== x; - let header; + let t0; if (c_2) { - header =
{x}
; + t0 =
{x}
; $[2] = x; - $[3] = header; + $[3] = t0; } else { - header = $[3]; + t0 = $[3]; } + const header = t0; const c_4 = $[4] !== x; const c_5 = $[5] !== props.b; const c_6 = $[6] !== props.c; @@ -86,9 +87,9 @@ function foo(props) { } const c_9 = $[9] !== x; const c_10 = $[10] !== y; - let content; + let t1; if (c_9 || c_10) { - content = ( + t1 = (
{x} {y} @@ -96,15 +97,16 @@ function foo(props) { ); $[9] = x; $[10] = y; - $[11] = content; + $[11] = t1; } else { - content = $[11]; + t1 = $[11]; } + const content = t1; const c_12 = $[12] !== header; const c_13 = $[13] !== content; - let t0; + let t2; if (c_12 || c_13) { - t0 = ( + t2 = ( <> {header} {content} @@ -112,11 +114,11 @@ function foo(props) { ); $[12] = header; $[13] = content; - $[14] = t0; + $[14] = t2; } else { - t0 = $[14]; + t2 = $[14]; } - return t0; + return t2; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/simple-function-1.expect.md b/compiler/forget/src/__tests__/fixtures/hir/simple-function-1.expect.md index 2711e32bce..e7be6f7969 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/simple-function-1.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/simple-function-1.expect.md @@ -16,15 +16,16 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(1); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = function (a) { + t0 = function (a) { a.foo(); }; - $[0] = x; + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } + const x = t0; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/simple-scope.expect.md b/compiler/forget/src/__tests__/fixtures/hir/simple-scope.expect.md index 63e9e6427a..b934e57fd9 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/simple-scope.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/simple-scope.expect.md @@ -15,14 +15,15 @@ function foo(a) { function foo(a) { const $ = React.unstable_useMemoCache(2); const c_0 = $[0] !== a.b; - let x; + let t0; if (c_0) { - x = [a.b]; + t0 = [a.b]; $[0] = a.b; - $[1] = x; + $[1] = t0; } else { - x = $[1]; + t0 = $[1]; } + const x = t0; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-arrayexpression.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-arrayexpression.expect.md index fc50027b02..770afae39d 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-arrayexpression.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-arrayexpression.expect.md @@ -16,13 +16,14 @@ function Component(props) { ```javascript function Component(props) { const $ = React.unstable_useMemoCache(1); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = [1, 2]; - $[0] = x; + t0 = [1, 2]; + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } + const x = t0; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-newexpression.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-newexpression.expect.md index 71ee1c3284..91a2f48e2d 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-newexpression.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-newexpression.expect.md @@ -20,15 +20,16 @@ function Foo() {} function Component(props) { const $ = React.unstable_useMemoCache(1); - let c; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { const a = []; const b = {}; - c = new Foo(a, b); - $[0] = c; + t0 = new Foo(a, b); + $[0] = t0; } else { - c = $[0]; + t0 = $[0]; } + const c = t0; return c; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-non-empty-initializer.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-non-empty-initializer.expect.md index 26de88456a..4c98edcb97 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-non-empty-initializer.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-non-empty-initializer.expect.md @@ -19,13 +19,14 @@ function foo(a, b) { ```javascript function foo(a, b) { const $ = React.unstable_useMemoCache(1); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = []; - $[0] = x; + t0 = []; + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } + let x = t0; if (a) { x = 1; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md index 1168b7d192..9ac9eb5a89 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md @@ -26,13 +26,14 @@ function foo() { const x = 1; const y = 3; - let t; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - t = { x: x, y: y }; - $[0] = t; + t0 = { x: x, y: y }; + $[0] = t0; } else { - t = $[0]; + t0 = $[0]; } + const t = t0; return t; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression.expect.md index 7d3b670978..ac74ec2403 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression.expect.md @@ -16,13 +16,14 @@ function Component(props) { ```javascript function Component(props) { const $ = React.unstable_useMemoCache(1); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = { a: 1, b: 2 }; - $[0] = x; + t0 = { a: 1, b: 2 }; + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } + const x = t0; return x; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-if.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-if.expect.md index be7c9291e6..c022fa68dc 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-if.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-if.expect.md @@ -26,22 +26,24 @@ function foo(a) { if (c_0) { x = {}; if (a) { - let y; + let t0; if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - y = {}; - $[2] = y; + t0 = {}; + $[2] = t0; } else { - y = $[2]; + t0 = $[2]; } + const y = t0; x.y = y; } else { - let z; + let t1; if ($[3] === Symbol.for("react.memo_cache_sentinel")) { - z = {}; - $[3] = z; + t1 = {}; + $[3] = t1; } else { - z = $[3]; + t1 = $[3]; } + const z = t1; x.z = z; } $[0] = a; diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate-inside-if.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate-inside-if.expect.md index bf4d8496b3..536dccae86 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate-inside-if.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate-inside-if.expect.md @@ -32,13 +32,14 @@ function foo(a) { mutate(y); } else { - let z; + let t0; if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - z = {}; - $[2] = z; + t0 = {}; + $[2] = t0; } else { - z = $[2]; + t0 = $[2]; } + const z = t0; x.z = z; } $[0] = a; diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md index 7ce4f48830..38e4ce493b 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md @@ -16,13 +16,14 @@ function foo() { ```javascript function foo() { const $ = React.unstable_useMemoCache(2); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = []; - $[0] = x; + t0 = []; + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } + const x = t0; let y; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { y = {}; diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md index edc2f43429..617fbc88fb 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md @@ -45,12 +45,14 @@ function Component(props) { } case true: { x.push(props.p2); + let t0; if ($[3] === Symbol.for("react.memo_cache_sentinel")) { - y = []; - $[3] = y; + t0 = []; + $[3] = t0; } else { - y = $[3]; + t0 = $[3]; } + y = t0; break bb1; } default: { @@ -68,27 +70,28 @@ function Component(props) { y = $[2]; } const c_4 = $[4] !== x; - let child; + let t1; if (c_4) { - child = ; + t1 = ; $[4] = x; - $[5] = child; + $[5] = t1; } else { - child = $[5]; + t1 = $[5]; } + const child = t1; y.push(props.p4); const c_6 = $[6] !== y; const c_7 = $[7] !== child; - let t0; + let t2; if (c_6 || c_7) { - t0 = {child}; + t2 = {child}; $[6] = y; $[7] = child; - $[8] = t0; + $[8] = t2; } else { - t0 = $[8]; + t2 = $[8]; } - return t0; + return t2; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md index 7f1b6fd659..1ab3f13f01 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md @@ -51,27 +51,28 @@ function Component(props) { y = $[2]; } const c_3 = $[3] !== x; - let child; + let t0; if (c_3) { - child = ; + t0 = ; $[3] = x; - $[4] = child; + $[4] = t0; } else { - child = $[4]; + t0 = $[4]; } + const child = t0; y.push(props.p4); const c_5 = $[5] !== y; const c_6 = $[6] !== child; - let t0; + let t1; if (c_5 || c_6) { - t0 = {child}; + t1 = {child}; $[5] = y; $[6] = child; - $[7] = t0; + $[7] = t1; } else { - t0 = $[7]; + t1 = $[7]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/tagged-template-literal.expect.md b/compiler/forget/src/__tests__/fixtures/hir/tagged-template-literal.expect.md index 34b5d25fbb..6a58dca5dc 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/tagged-template-literal.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/tagged-template-literal.expect.md @@ -26,9 +26,9 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(1); - let t; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - t = graphql` + t0 = graphql` fragment List_viewer on Viewer @argumentDefinitions( count: { @@ -40,10 +40,11 @@ function component() { ) `; - $[0] = t; + $[0] = t0; } else { - t = $[0]; + t0 = $[0]; } + const t = t0; return t; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/timers.expect.md b/compiler/forget/src/__tests__/fixtures/hir/timers.expect.md index fcaa487b20..414007af95 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/timers.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/timers.expect.md @@ -20,40 +20,42 @@ function Component(props) { ```javascript function Component(props) { const $ = React.unstable_useMemoCache(4); - let start; - if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - start = performance.now(); - $[0] = start; - } else { - start = $[0]; - } - let now; - if ($[1] === Symbol.for("react.memo_cache_sentinel")) { - now = Date.now(); - $[1] = now; - } else { - now = $[1]; - } let t0; - if ($[2] === Symbol.for("react.memo_cache_sentinel")) { + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { t0 = performance.now(); - $[2] = t0; + $[0] = t0; } else { - t0 = $[2]; + t0 = $[0]; } - const time = t0 - start; + const start = t0; let t1; + if ($[1] === Symbol.for("react.memo_cache_sentinel")) { + t1 = Date.now(); + $[1] = t1; + } else { + t1 = $[1]; + } + const now = t1; + let t2; + if ($[2] === Symbol.for("react.memo_cache_sentinel")) { + t2 = performance.now(); + $[2] = t2; + } else { + t2 = $[2]; + } + const time = t2 - start; + let t3; if ($[3] === Symbol.for("react.memo_cache_sentinel")) { - t1 = ( + t3 = (
rendering took {time} at {now}
); - $[3] = t1; + $[3] = t3; } else { - t1 = $[3]; + t3 = $[3]; } - return t1; + return t3; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-binary-operator.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-binary-operator.expect.md index ee6bbd378d..087ff35c9a 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-binary-operator.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-binary-operator.expect.md @@ -17,20 +17,22 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(2); - let a; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - a = some(); - $[0] = a; + t0 = some(); + $[0] = t0; } else { - a = $[0]; + t0 = $[0]; } - let b; + const a = t0; + let t1; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { - b = someOther(); - $[1] = b; + t1 = someOther(); + $[1] = t1; } else { - b = $[1]; + t1 = $[1]; } + const b = t1; if (a > b) { } } diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md index 5283cf0d4d..42357dd2b2 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md @@ -15,13 +15,14 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(1); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = { t: 1 }; - $[0] = x; + t0 = { t: 1 }; + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } + const x = t0; const p = x.t; return p; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md index 746b9035b5..bd346cd04f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md @@ -35,13 +35,14 @@ function component() { } else { t1 = $[1]; } - let x; + let t2; if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - x = { u: t0, v: t1 }; - $[2] = x; + t2 = { u: t0, v: t1 }; + $[2] = t2; } else { - x = $[2]; + t2 = $[2]; } + const x = t2; const u = x.u; const v = x.v; if (u > v) { diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md index 542effbdf7..62636834cf 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md @@ -20,13 +20,14 @@ function component() { let x; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { x = {}; - let q; + let t0; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { - q = {}; - $[1] = q; + t0 = {}; + $[1] = t0; } else { - q = $[1]; + t0 = $[1]; } + const q = t0; x.t = q; $[0] = x; } else { diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md index 7673f82d17..dabcaf399a 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md @@ -24,20 +24,22 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(3); - let p; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - p = makePrimitive(); - $[0] = p; + t0 = makePrimitive(); + $[0] = t0; } else { - p = $[0]; + t0 = $[0]; } - let o; + const p = t0; + let t1; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { - o = {}; - $[1] = o; + t1 = {}; + $[1] = t1; } else { - o = $[1]; + t1 = $[1]; } + const o = t1; let x; if ($[2] === Symbol.for("react.memo_cache_sentinel")) { x = {}; diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-return-type-inference.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-return-type-inference.expect.md index 024902953f..0a4b769a0f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-return-type-inference.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-return-type-inference.expect.md @@ -20,29 +20,32 @@ function component() { ```javascript function component() { const $ = React.unstable_useMemoCache(3); - let x; + let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = foo(); - $[0] = x; + t0 = foo(); + $[0] = t0; } else { - x = $[0]; + t0 = $[0]; } - let y; + const x = t0; + let t1; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { - y = foo(); - $[1] = y; + t1 = foo(); + $[1] = t1; } else { - y = $[1]; + t1 = $[1]; } + const y = t1; if (x > y) { } - let z_0; + let t2; if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - z_0 = foo(); - $[2] = z_0; + t2 = foo(); + $[2] = t2; } else { - z_0 = $[2]; + t2 = $[2]; } + const z_0 = t2; return z_0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/unary-expr.expect.md b/compiler/forget/src/__tests__/fixtures/hir/unary-expr.expect.md index 47beec00f0..d67398abb8 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/unary-expr.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/unary-expr.expect.md @@ -22,14 +22,15 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(10); const c_0 = $[0] !== a; - let t; + let t0; if (c_0) { - t = { t: a }; + t0 = { t: a }; $[0] = a; - $[1] = t; + $[1] = t0; } else { - t = $[1]; + t0 = $[1]; } + const t = t0; const z = +t.t; const q = -t.t; const p = void t.t; @@ -44,9 +45,9 @@ function component(a) { const c_6 = $[6] !== m; const c_7 = $[7] !== e; const c_8 = $[8] !== f; - let t0; + let t1; if (c_2 || c_3 || c_4 || c_5 || c_6 || c_7 || c_8) { - t0 = { z: z, p: p, q: q, n: n, m: m, e: e, f: f }; + t1 = { z: z, p: p, q: q, n: n, m: m, e: e, f: f }; $[2] = z; $[3] = p; $[4] = q; @@ -54,11 +55,11 @@ function component(a) { $[6] = m; $[7] = e; $[8] = f; - $[9] = t0; + $[9] = t1; } else { - t0 = $[9]; + t1 = $[9]; } - return t0; + return t1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/useMemo-simple.expect.md b/compiler/forget/src/__tests__/fixtures/hir/useMemo-simple.expect.md index bcf90184da..ef1baed8c5 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/useMemo-simple.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/useMemo-simple.expect.md @@ -15,24 +15,25 @@ function component(a) { function component(a) { const $ = React.unstable_useMemoCache(4); const c_0 = $[0] !== a; - let x; - if (c_0) { - x = (() => [a])(); - $[0] = a; - $[1] = x; - } else { - x = $[1]; - } - const c_2 = $[2] !== x; let t0; - if (c_2) { - t0 = ; - $[2] = x; - $[3] = t0; + if (c_0) { + t0 = (() => [a])(); + $[0] = a; + $[1] = t0; } else { - t0 = $[3]; + t0 = $[1]; } - return t0; + const x = t0; + const c_2 = $[2] !== x; + let t1; + if (c_2) { + t1 = ; + $[2] = x; + $[3] = t1; + } else { + t1 = $[3]; + } + return t1; } ``` diff --git a/compiler/forget/yarn.lock b/compiler/forget/yarn.lock index afa3019a65..62d377b5f2 100644 --- a/compiler/forget/yarn.lock +++ b/compiler/forget/yarn.lock @@ -83,13 +83,14 @@ "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" -"@babel/generator@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" - integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== +"@babel/generator@^7.21.1": + version "7.21.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" + integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.21.0" "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.18.6": @@ -135,6 +136,14 @@ "@babel/template" "^7.18.10" "@babel/types" "^7.19.0" +"@babel/helper-function-name@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== + dependencies: + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" + "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" @@ -260,10 +269,10 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.3.tgz#8dd36d17c53ff347f9e55c328710321b49479a9a" integrity sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ== -"@babel/parser@^7.20.13": - version "7.20.13" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.13.tgz#ddf1eb5a813588d2fb1692b70c6fce75b945c088" - integrity sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw== +"@babel/parser@^7.20.7", "@babel/parser@^7.21.2": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" + integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -459,6 +468,15 @@ "@babel/parser" "^7.18.10" "@babel/types" "^7.18.10" +"@babel/template@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@babel/template@^7.3.3": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" @@ -484,18 +502,18 @@ lodash "^4.17.10" "@babel/traverse@^7.19.1": - version "7.20.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473" - integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ== + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75" + integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" + "@babel/generator" "^7.21.1" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" + "@babel/helper-function-name" "^7.21.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.13" - "@babel/types" "^7.20.7" + "@babel/parser" "^7.21.2" + "@babel/types" "^7.21.2" debug "^4.1.0" globals "^11.1.0" @@ -543,6 +561,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.21.0", "@babel/types@^7.21.2": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" + integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -831,7 +858,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== @@ -841,7 +868,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== @@ -862,6 +889,14 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.17": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"