diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 025974703d..bc323517ed 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -614,7 +614,7 @@ function lowerStatement( value = buildTemporaryPlace(builder, id.node.loc ?? GeneratedSource); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...value }, kind: InstructionKind.Const }, + lvalue: { ...value }, value: { kind: "Primitive", value: undefined, @@ -647,7 +647,7 @@ function lowerStatement( ); builder.push({ id: makeInstructionId(0), - lvalue: { kind: InstructionKind.Const, place }, + lvalue: place, value, loc: stmt.node.loc ?? GeneratedSource, }); @@ -746,13 +746,10 @@ function lowerStatement( }); builder.push({ id: makeInstructionId(0), - lvalue: { - place: buildTemporaryPlace( - builder, - stmtPath.node.loc ?? GeneratedSource - ), - kind: InstructionKind.Const, - }, + lvalue: buildTemporaryPlace( + builder, + stmtPath.node.loc ?? GeneratedSource + ), loc: stmtPath.node.loc ?? GeneratedSource, value: { kind: "UnsupportedNode", @@ -1043,7 +1040,7 @@ function lowerExpression( const consequentBlock = builder.enter("value", (_blockId) => { builder.push({ id: makeInstructionId(0), - lvalue: { kind: InstructionKind.Reassign, place: { ...place } }, + lvalue: { ...place }, value: lowerExpression(builder, expr.get("consequent")), loc: exprLoc, }); @@ -1058,7 +1055,7 @@ function lowerExpression( const alternateBlock = builder.enter("value", (_blockId) => { builder.push({ id: makeInstructionId(0), - lvalue: { kind: InstructionKind.Reassign, place: { ...place } }, + lvalue: { ...place }, value: lowerExpression(builder, expr.get("alternate")), loc: exprLoc, }); @@ -1106,7 +1103,7 @@ function lowerExpression( const consequent = builder.enter("value", () => { builder.push({ id: makeInstructionId(0), - lvalue: { kind: InstructionKind.Reassign, place: { ...place } }, + lvalue: { ...place }, value: { kind: "LoadLocal", place: { ...leftPlace }, @@ -1124,7 +1121,7 @@ function lowerExpression( const alternate = builder.enter("value", () => { builder.push({ id: makeInstructionId(0), - lvalue: { kind: InstructionKind.Reassign, place: { ...place } }, + lvalue: { ...place }, value: lowerExpression(builder, expr.get("right")), loc: exprLoc, }); @@ -1148,7 +1145,7 @@ function lowerExpression( ); builder.push({ id: makeInstructionId(0), - lvalue: { kind: InstructionKind.Reassign, place: { ...leftPlace } }, + lvalue: { ...leftPlace }, value: lowerExpression(builder, expr.get("left")), loc: exprLoc, }); @@ -1225,8 +1222,7 @@ function lowerExpression( builder.push({ id: makeInstructionId(0), lvalue: { - place: { ...binaryPlace }, - kind: InstructionKind.Const, + ...binaryPlace, }, value: { kind: "BinaryExpression", @@ -1240,7 +1236,7 @@ function lowerExpression( const result = buildTemporaryPlace(builder, exprLoc); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...result }, kind: InstructionKind.Const }, + lvalue: { ...result }, value: { kind: "StoreLocal", lvalue: { @@ -1270,8 +1266,7 @@ function lowerExpression( builder.push({ id: makeInstructionId(0), lvalue: { - place: { ...previousValuePlace }, - kind: InstructionKind.Const, + ...previousValuePlace, }, value, loc: leftExpr.node.loc ?? GeneratedSource, @@ -1281,8 +1276,7 @@ function lowerExpression( builder.push({ id: makeInstructionId(0), lvalue: { - place: { ...newValuePlace }, - kind: InstructionKind.Const, + ...newValuePlace, }, value: { kind: "BinaryExpression", @@ -1332,7 +1326,7 @@ function lowerExpression( const place: Place = buildTemporaryPlace(builder, exprLoc); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...place }, kind: InstructionKind.Const }, + lvalue: { ...place }, value, loc: exprLoc, }); @@ -1581,7 +1575,7 @@ function lowerExpression( ); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...primitiveTemp }, kind: InstructionKind.Const }, + lvalue: { ...primitiveTemp }, value: { kind: "Primitive", value: 1, @@ -1599,7 +1593,7 @@ function lowerExpression( ); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...temp }, kind: InstructionKind.Const }, + lvalue: { ...temp }, value: { kind: "BinaryExpression", operator: expr.node.operator === "++" ? "+" : "-", @@ -1611,16 +1605,10 @@ function lowerExpression( }); builder.push({ id: makeInstructionId(0), - lvalue: { - place: buildTemporaryPlace(builder, exprLoc), - kind: InstructionKind.Const, - }, + lvalue: buildTemporaryPlace(builder, exprLoc), value: { kind: "StoreLocal", - lvalue: { - place: { ...identifier }, - kind: InstructionKind.Reassign, - }, + lvalue: { place: { ...identifier }, kind: InstructionKind.Reassign }, value: { ...temp }, loc: exprLoc, }, @@ -1723,7 +1711,7 @@ function lowerJsxElementName( loc: exprLoc, }, loc: exprLoc, - lvalue: { place: { ...place }, kind: InstructionKind.Const }, + lvalue: { ...place }, }); return { ...place }; } @@ -1740,9 +1728,9 @@ function lowerJsxElementName( loc: exprLoc, }, loc: exprLoc, - lvalue: { place, kind: InstructionKind.Const }, + lvalue: { ...place }, }); - return { ...place }; + return place; } } @@ -1777,7 +1765,7 @@ function lowerJsxElement( loc: exprLoc, }, loc: exprLoc, - lvalue: { place: { ...place }, kind: InstructionKind.Const }, + lvalue: { ...place }, }); return { ...place }; } @@ -1792,7 +1780,7 @@ function lowerJsxElement( loc: exprLoc, }, loc: exprLoc, - lvalue: { place: { ...place }, kind: InstructionKind.Const }, + lvalue: { ...place }, }); return place; } else { @@ -1812,7 +1800,7 @@ function lowerJsxElement( loc: exprLoc, }, loc: exprLoc, - lvalue: { place: { ...place }, kind: InstructionKind.Const }, + lvalue: { ...place }, }); return place; } @@ -1832,7 +1820,7 @@ function lowerExpressionToTemporary( id: makeInstructionId(0), value: value, loc: exprLoc, - lvalue: { place: { ...place }, kind: InstructionKind.Const }, + lvalue: { ...place }, }); return place; } @@ -1851,7 +1839,7 @@ function lowerExpressionToPlace( id: makeInstructionId(0), value: value, loc: exprLoc, - lvalue: { place: { ...place }, kind: InstructionKind.Const }, + lvalue: { ...place }, }); return place; } @@ -1869,10 +1857,7 @@ function lowerExpressionToVoid( id: makeInstructionId(0), value: instr, loc: exprLoc, - lvalue: { - place: buildTemporaryPlace(builder, exprLoc), - kind: InstructionKind.Const, - }, + lvalue: buildTemporaryPlace(builder, exprLoc), }); } @@ -1899,10 +1884,7 @@ function lowerIdentifier( id: makeInstructionId(0), value, loc: place.loc, - lvalue: { - place: { ...place }, - kind: InstructionKind.Const, - }, + lvalue: { ...place }, }); return place; } @@ -1972,13 +1954,10 @@ function lowerAssignment( }; builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...temporary }, kind }, + lvalue: { ...temporary }, value: { kind: "StoreLocal", - lvalue: { - place: { ...place }, - kind, - }, + lvalue: { place: { ...place }, kind }, value, loc, }, @@ -2050,7 +2029,7 @@ function lowerAssignment( ); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...property }, kind: InstructionKind.Const }, + lvalue: { ...property }, value: { kind: "Primitive", value: i, @@ -2061,7 +2040,7 @@ function lowerAssignment( const propertyPlace = buildTemporaryPlace(builder, property.loc); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const }, + lvalue: { ...propertyPlace }, value: { kind: "ComputedLoad", loc, @@ -2123,7 +2102,7 @@ function lowerAssignment( ); builder.push({ id: makeInstructionId(0), - lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const }, + lvalue: { ...propertyPlace }, value: { kind: "PropertyLoad", loc, diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 767fda771b..f88b5c23f1 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -81,7 +81,7 @@ export type ReactiveTerminalStatement< export type ReactiveInstruction = { id: InstructionId; - lvalue: LValue | null; + lvalue: Place | null; value: ReactiveValue; loc: SourceLocation; }; @@ -365,7 +365,7 @@ export type TernaryTerminal = { */ export type Instruction = { id: InstructionId; - lvalue: LValue; + lvalue: Place; value: InstructionValue; loc: SourceLocation; }; diff --git a/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts b/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts index 3c1a562dc7..0c2c166a45 100644 --- a/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts +++ b/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts @@ -12,7 +12,6 @@ import { GeneratedSource, HIRFunction, Instruction, - InstructionKind, } from "./HIR"; /** @@ -60,13 +59,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void { const instr: Instruction = { id: predecessor.terminal.id, lvalue: { - place: { - kind: "Identifier", - identifier: phi.id, - effect: Effect.Mutate, - loc: GeneratedSource, - }, - kind: InstructionKind.Const, + kind: "Identifier", + identifier: phi.id, + effect: Effect.Mutate, + loc: GeneratedSource, }, value: { kind: "LoadLocal", diff --git a/compiler/forget/src/HIR/PrintHIR.ts b/compiler/forget/src/HIR/PrintHIR.ts index 8efb151920..b9890c67f8 100644 --- a/compiler/forget/src/HIR/PrintHIR.ts +++ b/compiler/forget/src/HIR/PrintHIR.ts @@ -106,7 +106,7 @@ export function printInstruction(instr: ReactiveInstruction): string { const value = printInstructionValue(instr.value); if (instr.lvalue !== null) { - return `${id} ${printLValue(instr.lvalue)} = ${value}`; + return `${id} ${printPlace(instr.lvalue)} = ${value}`; } else { return `${id} ${value}`; } diff --git a/compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts b/compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts index 0ad9988a51..52bff620af 100644 --- a/compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts +++ b/compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts @@ -29,17 +29,13 @@ export function validateConsistentIdentifiers(fn: HIRFunction): void { } } for (const instr of block.instructions) { - if (instr.lvalue.place.identifier.name !== null) { + if (instr.lvalue.identifier.name !== null) { CompilerError.invariant( - `Expected all lvalues to be temporaries, found '${instr.lvalue.place.identifier.name}'`, - instr.lvalue.place.loc + `Expected all lvalues to be temporaries, found '${instr.lvalue.identifier.name}'`, + instr.lvalue.loc ); } - validate( - identifiers, - instr.lvalue.place.identifier, - instr.lvalue.place.loc - ); + validate(identifiers, instr.lvalue.identifier, instr.lvalue.loc); for (const operand of eachInstructionValueOperand(instr.value)) { validate(identifiers, operand.identifier, operand.loc); } diff --git a/compiler/forget/src/HIR/visitors.ts b/compiler/forget/src/HIR/visitors.ts index 85285b60d5..5c62a2f080 100644 --- a/compiler/forget/src/HIR/visitors.ts +++ b/compiler/forget/src/HIR/visitors.ts @@ -594,7 +594,7 @@ export function* eachBlockOperand(block: BasicBlock): Iterable { for (const instr of block.instructions) { yield* eachInstructionOperand(instr); if (instr.lvalue != null) { - yield instr.lvalue.place; + yield instr.lvalue; } } yield* eachTerminalOperand(block.terminal); diff --git a/compiler/forget/src/Inference/AnalyseFunctions.ts b/compiler/forget/src/Inference/AnalyseFunctions.ts index 12678f49e6..9990f8a8ee 100644 --- a/compiler/forget/src/Inference/AnalyseFunctions.ts +++ b/compiler/forget/src/Inference/AnalyseFunctions.ts @@ -56,15 +56,15 @@ export default function analyseFunctions(func: HIRFunction) { } case "PropertyLoad": { state.declareProperty( - instr.lvalue.place, + instr.lvalue, instr.value.object, instr.value.property ); break; } case "LoadLocal": { - if (instr.lvalue.place.identifier.name === null) { - state.declareTemporary(instr.lvalue.place, instr.value.place); + if (instr.lvalue.identifier.name === null) { + state.declareTemporary(instr.lvalue, instr.value.place); } break; } diff --git a/compiler/forget/src/Inference/InferAlias.ts b/compiler/forget/src/Inference/InferAlias.ts index e4f057fca5..9aacaeb94a 100644 --- a/compiler/forget/src/Inference/InferAlias.ts +++ b/compiler/forget/src/Inference/InferAlias.ts @@ -49,5 +49,5 @@ function inferInstr(instr: Instruction, aliases: DisjointSet) { return; } - aliases.union([lvalue.place.identifier, alias.identifier]); + aliases.union([lvalue.identifier, alias.identifier]); } diff --git a/compiler/forget/src/Inference/InferAliasForStores.ts b/compiler/forget/src/Inference/InferAliasForStores.ts index 79c40bcb73..6aa9e44f99 100644 --- a/compiler/forget/src/Inference/InferAliasForStores.ts +++ b/compiler/forget/src/Inference/InferAliasForStores.ts @@ -21,7 +21,7 @@ export function inferAliasForStores( for (const [_, block] of func.body.blocks) { for (const instr of block.instructions) { const { value, lvalue } = instr; - if (lvalue.place.effect !== Effect.Store) { + if (lvalue.effect !== Effect.Store) { continue; } if (value.kind === "StoreLocal") { @@ -32,7 +32,7 @@ export function inferAliasForStores( operand.effect === Effect.Capture || operand.effect === Effect.Store ) { - maybeAlias(aliases, lvalue.place, operand, instr.id); + maybeAlias(aliases, lvalue, operand, instr.id); } } } diff --git a/compiler/forget/src/Inference/InferMutableLifetimes.ts b/compiler/forget/src/Inference/InferMutableLifetimes.ts index f7373a51e6..eb52f7d2b0 100644 --- a/compiler/forget/src/Inference/InferMutableLifetimes.ts +++ b/compiler/forget/src/Inference/InferMutableLifetimes.ts @@ -129,7 +129,7 @@ export function inferMutableLifetimes( } } - const lvalueId = instr.lvalue.place.identifier; + const lvalueId = instr.lvalue.identifier; // lvalue start being mutable when they're initially assigned a // value. diff --git a/compiler/forget/src/Inference/InferReferenceEffects.ts b/compiler/forget/src/Inference/InferReferenceEffects.ts index 785883e99d..f289e31d46 100644 --- a/compiler/forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/forget/src/Inference/InferReferenceEffects.ts @@ -655,8 +655,8 @@ function inferBlock( ); } state.initialize(instrValue, ValueKind.Mutable); - state.define(instr.lvalue.place, instrValue); - instr.lvalue.place.effect = Effect.Store; + state.define(instr.lvalue, instrValue); + instr.lvalue.effect = Effect.Store; continue; } case "PropertyCall": { @@ -676,8 +676,8 @@ function inferBlock( state.reference(arg, Effect.Mutate); } state.initialize(instrValue, ValueKind.Mutable); - state.define(instr.lvalue.place, instrValue); - instr.lvalue.place.effect = Effect.Mutate; + state.define(instr.lvalue, instrValue); + instr.lvalue.effect = Effect.Mutate; continue; } case "ComputedCall": { @@ -698,8 +698,8 @@ function inferBlock( state.reference(arg, Effect.Mutate); } state.initialize(instrValue, ValueKind.Mutable); - state.define(instr.lvalue.place, instrValue); - instr.lvalue.place.effect = Effect.Mutate; + state.define(instr.lvalue, instrValue); + instr.lvalue.effect = Effect.Mutate; continue; } case "PropertyStore": { @@ -711,8 +711,8 @@ function inferBlock( state.reference(instrValue.object, Effect.Store); const lvalue = instr.lvalue; - state.alias(lvalue.place, instrValue.value); - lvalue.place.effect = Effect.Store; + state.alias(lvalue, instrValue.value); + lvalue.effect = Effect.Store; continue; } case "PropertyLoad": { @@ -729,9 +729,9 @@ function inferBlock( state.reference(instrValue.object, Effect.Read); const lvalue = instr.lvalue; - lvalue.place.effect = Effect.Mutate; + lvalue.effect = Effect.Mutate; state.initialize(instrValue, state.kind(instrValue.object)); - state.define(lvalue.place, instrValue); + state.define(lvalue, instrValue); continue; } case "ComputedStore": { @@ -744,8 +744,8 @@ function inferBlock( state.reference(instrValue.object, Effect.Store); const lvalue = instr.lvalue; - state.alias(lvalue.place, instrValue.value); - lvalue.place.effect = Effect.Store; + state.alias(lvalue, instrValue.value); + lvalue.effect = Effect.Store; continue; } case "ComputedLoad": { @@ -763,9 +763,9 @@ function inferBlock( state.reference(instrValue.object, Effect.Read); state.reference(instrValue.property, Effect.Read); const lvalue = instr.lvalue; - lvalue.place.effect = Effect.Mutate; + lvalue.effect = Effect.Mutate; state.initialize(instrValue, state.kind(instrValue.object)); - state.define(lvalue.place, instrValue); + state.define(lvalue, instrValue); continue; } case "TypeCastExpression": { @@ -778,16 +778,16 @@ function inferBlock( state.initialize(instrValue, state.kind(instrValue.value)); state.reference(instrValue.value, Effect.Read); const lvalue = instr.lvalue; - lvalue.place.effect = Effect.Mutate; - state.alias(lvalue.place, instrValue.value); + lvalue.effect = Effect.Mutate; + state.alias(lvalue, instrValue.value); continue; } case "LoadLocal": { state.reference(instrValue.place, Effect.Capture); const lvalue = instr.lvalue; - lvalue.place.effect = Effect.Mutate; + lvalue.effect = Effect.Mutate; // direct aliasing: `a = b`; - state.alias(lvalue.place, instrValue.place); + state.alias(lvalue, instrValue.place); continue; } case "StoreLocal": { @@ -799,8 +799,8 @@ function inferBlock( state.reference(instrValue.value, effect); const lvalue = instr.lvalue; - state.alias(lvalue.place, instrValue.value); - lvalue.place.effect = Effect.Store; + state.alias(lvalue, instrValue.value); + lvalue.effect = Effect.Store; state.alias(instrValue.lvalue.place, instrValue.value); instrValue.lvalue.place.effect = Effect.Store; continue; @@ -820,8 +820,8 @@ function inferBlock( } state.initialize(instrValue, valueKind); - state.define(instr.lvalue.place, instrValue); - instr.lvalue.place.effect = lvalueEffect; + state.define(instr.lvalue, instrValue); + instr.lvalue.effect = lvalueEffect; } const effect = diff --git a/compiler/forget/src/Optimization/ConstantPropagation.ts b/compiler/forget/src/Optimization/ConstantPropagation.ts index 6a7ca792f0..66dffffa37 100644 --- a/compiler/forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/forget/src/Optimization/ConstantPropagation.ts @@ -105,7 +105,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean { const value = evaluateInstruction(constants, instr); if (value !== null) { instr.value = value; - constants.set(instr.lvalue.place.identifier.id, value); + constants.set(instr.lvalue.identifier.id, value); } } diff --git a/compiler/forget/src/Optimization/DeadCodeElimination.ts b/compiler/forget/src/Optimization/DeadCodeElimination.ts index 4036a6c1cc..79210ba6b0 100644 --- a/compiler/forget/src/Optimization/DeadCodeElimination.ts +++ b/compiler/forget/src/Optimization/DeadCodeElimination.ts @@ -39,14 +39,14 @@ export function deadCodeElimination(fn: HIRFunction): void { for (let i = block.instructions.length - 1; i >= 0; i--) { const instr = block.instructions[i]!; if ( - !used.has(instr.lvalue.place.identifier) && + !used.has(instr.lvalue.identifier) && 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) ) { continue; } - used.add(instr.lvalue.place.identifier); + used.add(instr.lvalue.identifier); for (const operand of eachInstructionValueOperand(instr.value)) { used.add(operand.identifier); } @@ -67,7 +67,7 @@ export function deadCodeElimination(fn: HIRFunction): void { } } retainWhere(block.instructions, (instr) => - used.has(instr.lvalue.place.identifier) + used.has(instr.lvalue.identifier) ); } } diff --git a/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts b/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts index a779c75961..8cf556aaf5 100644 --- a/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts +++ b/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts @@ -7,7 +7,6 @@ import { InstructionId, - LValue, Place, ReactiveBlock, ReactiveFunction, @@ -74,12 +73,8 @@ class Visitor extends ReactiveFunctionVisitor { state.visitScope(scope); } } - override visitLValue( - id: InstructionId, - lvalue: LValue, - state: Context - ): void { - const scope = getPlaceScope(id, lvalue.place); + override visitLValue(id: InstructionId, lvalue: Place, state: Context): void { + const scope = getPlaceScope(id, lvalue); if (scope !== null) { state.visitScope(scope); } diff --git a/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts b/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts index 1690e4065e..07e3c6d41a 100644 --- a/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts +++ b/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts @@ -188,7 +188,7 @@ export function getInstructionScope({ "Expected lvalues to not be null when assigning scopes. " + "Pruning lvalues too early can result in missing scope information." ); - const lvalueScope = getPlaceScope(id, lvalue.place); + const lvalueScope = getPlaceScope(id, lvalue); if (lvalueScope !== null) { return lvalueScope; } diff --git a/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts index 28bcf0d542..4dc5f48356 100644 --- a/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts @@ -18,7 +18,6 @@ import { } from "../HIR"; import { HIRFunction, - InstructionKind, ReactiveBreakTerminal, ReactiveContinueTerminal, ReactiveFunction, @@ -471,7 +470,7 @@ class Driver { kind: "instruction", instruction: { id: terminal.id, - lvalue: { kind: InstructionKind.Const, place }, + lvalue: place, value, loc: terminal.loc, }, @@ -544,7 +543,7 @@ class Driver { const instr = defaultBlock.instructions[0]!; return { block: defaultBlock.id, - place: instr.lvalue!.place, + place: instr.lvalue!, value: instr.value, id: instr.id, }; @@ -559,7 +558,7 @@ class Driver { }; return { block: defaultBlock.id, - place: instr.lvalue!.place, + place: instr.lvalue!, value: sequence, id: instr.id, }; @@ -578,7 +577,7 @@ class Driver { { id: init.id, loc, - lvalue: { kind: InstructionKind.Const, place: init.place }, + lvalue: init.place, value: init.value, }, ], @@ -621,7 +620,7 @@ class Driver { { id: test.id, loc: terminal.loc, - lvalue: { kind: InstructionKind.Const, place: test.place }, + lvalue: test.place, value: test.value, }, ], diff --git a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts index e8eddd0509..150c56ff52 100644 --- a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -488,38 +488,27 @@ function codegenInstruction( if (instr.lvalue === null) { return t.expressionStatement(value); } - if (instr.lvalue.place.identifier.name === null) { + if (instr.lvalue.identifier.name === null) { // temporary - cx.temp.set(instr.lvalue.place.identifier.id, value); + cx.temp.set(instr.lvalue.identifier.id, value); return t.emptyStatement(); } else { - if (instr.lvalue.kind !== InstructionKind.Const) { - CompilerError.invariant( - `Expected all instruction lvalues to be const declarations`, - instr.lvalue.place.loc - ); - } - const kind = cx.hasDeclared(instr.lvalue.place.identifier) + const kind = cx.hasDeclared(instr.lvalue.identifier) ? InstructionKind.Reassign - : instr.lvalue.kind; - switch (kind) { - case InstructionKind.Const: { - return createVariableDeclaration(instr.loc, "const", [ - t.variableDeclarator(codegenLVal(instr.lvalue), value), - ]); - } - case InstructionKind.Reassign: { - return createExpressionStatement( - instr.loc, - t.assignmentExpression("=", codegenLVal(instr.lvalue), value) - ); - } - default: { - assertExhaustive( - kind, - `Unexpected instruction kind '${instr.lvalue.kind}'` - ); - } + : InstructionKind.Const; + if (cx.hasDeclared(instr.lvalue.identifier)) { + return createExpressionStatement( + instr.loc, + t.assignmentExpression( + "=", + convertIdentifier(instr.lvalue.identifier), + value + ) + ); + } else { + return createVariableDeclaration(instr.loc, "const", [ + t.variableDeclarator(convertIdentifier(instr.lvalue.identifier), value), + ]); } } } diff --git a/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts b/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts index f886032234..d2f9a49401 100644 --- a/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts +++ b/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts @@ -63,7 +63,7 @@ class Visitor extends ReactiveFunctionVisitor { // allow treating safe hooks as non-reactive. hasReactiveInput = true; } - state.reactivityMap.set(lval.place.identifier.id, hasReactiveInput); + state.reactivityMap.set(lval.identifier.id, hasReactiveInput); if (hasReactiveInput) { // all mutating effects must also be marked as reactive @@ -98,7 +98,7 @@ class Visitor extends ReactiveFunctionVisitor { if (instr.lvalue !== null) { if (instr.value.kind === "LoadLocal") { state.temporaries.set( - instr.lvalue.place.identifier.id, + instr.lvalue.identifier.id, instr.value.place.identifier.id ); } diff --git a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts index bbee09a376..68bc5d93c0 100644 --- a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts +++ b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts @@ -98,9 +98,9 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void { for (const instr of block.instructions) { const operands: Array = []; - const range = instr.lvalue.place.identifier.mutableRange; + const range = instr.lvalue.identifier.mutableRange; if (range.end > range.start + 1 || mayAllocate(instr.value)) { - operands.push(instr.lvalue!.place.identifier); + operands.push(instr.lvalue!.identifier); } if (instr.value.kind === "StoreLocal") { if ( diff --git a/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts b/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts index f44596c720..dfb9209c9f 100644 --- a/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts +++ b/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts @@ -7,7 +7,6 @@ import { InstructionId, - LValue, makeInstructionId, Place, ReactiveBlock, @@ -113,12 +112,8 @@ class Visitor extends ReactiveFunctionVisitor { override visitPlace(id: InstructionId, place: Place, state: Context): void { state.visitPlace(id, place); } - override visitLValue( - id: InstructionId, - lvalue: LValue, - state: Context - ): void { - state.visitPlace(id, lvalue.place); + override visitLValue(id: InstructionId, lvalue: Place, state: Context): void { + state.visitPlace(id, lvalue); } override visitBlock(block: ReactiveBlock, state: Context): void { state.enter(() => { diff --git a/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts index d73945d0fd..74fad09b1e 100644 --- a/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts @@ -17,7 +17,6 @@ import { import { printIdentifier, printInstructionValue, - printLValue, printPlace, } from "../HIR/PrintHIR"; import { assertExhaustive } from "../Utils/utils"; @@ -85,7 +84,9 @@ function printReactiveInstruction( const id = `[${instruction.id}]`; if (instruction.lvalue !== null) { - writer.write(`${id} ${printLValue(instruction.lvalue)} = `); + writer.write( + `${id} ${printIdentifier(instruction.lvalue.identifier)} = ` + ); printReactiveValue(writer, instruction.value); writer.newline(); } else { diff --git a/compiler/forget/src/ReactiveScopes/PromoteUsedTemporaries.ts b/compiler/forget/src/ReactiveScopes/PromoteUsedTemporaries.ts index 9c91b5ea2d..9468224522 100644 --- a/compiler/forget/src/ReactiveScopes/PromoteUsedTemporaries.ts +++ b/compiler/forget/src/ReactiveScopes/PromoteUsedTemporaries.ts @@ -56,10 +56,10 @@ class Visitor extends ReactiveFunctionVisitor { this.traverseInstruction(instruction, state); if ( instruction.lvalue !== null && - instruction.lvalue.place.identifier.name === null && + instruction.lvalue.identifier.name === null && instruction.value.kind !== "LoadLocal" ) { - state.temporaries.set(instruction.lvalue.place.identifier, 0); + state.temporaries.set(instruction.lvalue.identifier, 0); } } } diff --git a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts index 813b65c7d2..135617af57 100644 --- a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts +++ b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts @@ -11,7 +11,6 @@ import { IdentifierId, InstructionId, InstructionKind, - LValue, makeInstructionId, Place, ReactiveBlock, @@ -680,20 +679,20 @@ function visitInstructionValue( context: Context, id: InstructionId, value: ReactiveValue, - lvalue: LValue | null + lvalue: Place | null ): void { if (value.kind === "LoadLocal" && lvalue !== null) { if ( value.place.identifier.name !== null && - lvalue.place.identifier.name === null + lvalue.identifier.name === null ) { - context.declareTemporary(lvalue.place, value.place); + context.declareTemporary(lvalue, value.place); } else { context.visitOperand(value.place); } } else if (value.kind === "PropertyLoad") { if (lvalue !== null) { - context.declareProperty(lvalue.place, value.object, value.property); + context.declareProperty(lvalue, value.object, value.property); } else { context.visitProperty(value.object, value.property); } @@ -717,7 +716,7 @@ function visitInstruction(context: Context, instr: ReactiveInstruction): void { if (lvalue == null) { return; } - context.declare(lvalue.place.identifier, { + context.declare(lvalue.identifier, { id: instr.id, scope: context.currentScope, }); diff --git a/compiler/forget/src/ReactiveScopes/PruneTemporaryLValues.ts b/compiler/forget/src/ReactiveScopes/PruneTemporaryLValues.ts index fb7b1749e6..965d455c4b 100644 --- a/compiler/forget/src/ReactiveScopes/PruneTemporaryLValues.ts +++ b/compiler/forget/src/ReactiveScopes/PruneTemporaryLValues.ts @@ -8,7 +8,6 @@ import { Identifier, InstructionId, - InstructionKind, Place, ReactiveFunction, ReactiveInstruction, @@ -40,10 +39,9 @@ class Visitor extends ReactiveFunctionVisitor { this.traverseInstruction(instruction, state); if ( instruction.lvalue !== null && - instruction.lvalue.kind === InstructionKind.Const && - instruction.lvalue.place.identifier.name === null + instruction.lvalue.identifier.name === null ) { - state.set(instruction.lvalue.place.identifier, instruction); + state.set(instruction.lvalue.identifier, instruction); } } } diff --git a/compiler/forget/src/ReactiveScopes/RenameVariables.ts b/compiler/forget/src/ReactiveScopes/RenameVariables.ts index eddd274034..0109098372 100644 --- a/compiler/forget/src/ReactiveScopes/RenameVariables.ts +++ b/compiler/forget/src/ReactiveScopes/RenameVariables.ts @@ -60,7 +60,7 @@ class Visitor extends ReactiveFunctionVisitor { state.visit(operand.identifier); } if (instruction.lvalue !== null) { - state.visit(instruction.lvalue.place.identifier); + state.visit(instruction.lvalue.identifier); } } override visitScope(scope: ReactiveScopeBlock, state: Scopes): void { diff --git a/compiler/forget/src/ReactiveScopes/visitors.ts b/compiler/forget/src/ReactiveScopes/visitors.ts index 7ecdf0b1c3..37933a6372 100644 --- a/compiler/forget/src/ReactiveScopes/visitors.ts +++ b/compiler/forget/src/ReactiveScopes/visitors.ts @@ -7,7 +7,6 @@ import { InstructionId, - LValue, Place, ReactiveBlock, ReactiveFunction, @@ -31,7 +30,7 @@ export function visitReactiveFunction( export class ReactiveFunctionVisitor { visitID(_id: InstructionId, _state: TState): void {} - visitLValue(_id: InstructionId, _lvalue: LValue, _state: TState): void {} + visitLValue(_id: InstructionId, _lvalue: Place, _state: TState): void {} visitPlace(_id: InstructionId, _place: Place, _state: TState): void {} visitValue(id: InstructionId, value: ReactiveValue, state: TState): void { diff --git a/compiler/forget/src/SSA/EliminateRedundantPhi.ts b/compiler/forget/src/SSA/EliminateRedundantPhi.ts index 3565eb94a7..773ca6aae7 100644 --- a/compiler/forget/src/SSA/EliminateRedundantPhi.ts +++ b/compiler/forget/src/SSA/EliminateRedundantPhi.ts @@ -82,7 +82,7 @@ export function eliminateRedundantPhi(fn: HIRFunction) { for (const place of eachInstructionOperand(instr)) { rewritePlace(place, rewrites); } - rewritePlace(instr.lvalue.place, rewrites); + rewritePlace(instr.lvalue, rewrites); } // Rewrite all terminal operands diff --git a/compiler/forget/src/SSA/EnterSSA.ts b/compiler/forget/src/SSA/EnterSSA.ts index 02a16508af..d34c9e773b 100644 --- a/compiler/forget/src/SSA/EnterSSA.ts +++ b/compiler/forget/src/SSA/EnterSSA.ts @@ -7,7 +7,6 @@ import { HIRFunction, Identifier, IdentifierId, - InstructionKind, makeInstructionId, makeType, Phi, @@ -215,7 +214,6 @@ export default function enterSSA(func: HIRFunction): void { 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); @@ -223,10 +221,9 @@ export default function enterSSA(func: HIRFunction): void { mapInstructionOperands(instr, (place) => builder.getPlace(place)); } - const oldPlace = instr.lvalue.place; + const oldPlace = instr.lvalue; const newPlace = builder.definePlace(oldPlace); - instr.lvalue.kind = InstructionKind.Const; - instr.lvalue.place = newPlace; + instr.lvalue = newPlace; } mapTerminalOperands(block.terminal, (place) => builder.getPlace(place)); diff --git a/compiler/forget/src/SSA/LeaveSSA.ts b/compiler/forget/src/SSA/LeaveSSA.ts index 223c60664b..f6e1736d08 100644 --- a/compiler/forget/src/SSA/LeaveSSA.ts +++ b/compiler/forget/src/SSA/LeaveSSA.ts @@ -112,17 +112,6 @@ export function leaveSSA(fn: HIRFunction): void { // `let` or `reassign` where possible. const { lvalue, value } = instr; if ( - lvalue.kind === InstructionKind.Const && - rewrites.has(lvalue.place.identifier) - ) { - // For rewrites, the declaration of the canonical identifier has to be `let`, - // all other assignments are reassignments (which we annotate for codegen - // purposes). - lvalue.kind = - rewrites.get(lvalue.place.identifier) === lvalue.place.identifier - ? InstructionKind.Let - : InstructionKind.Reassign; - } else if ( value.kind === "StoreLocal" && value.lvalue.place.identifier.name != null ) { @@ -147,7 +136,7 @@ export function leaveSSA(fn: HIRFunction): void { ? InstructionKind.Let : InstructionKind.Reassign; } - rewritePlace(lvalue.place, rewrites, declarations); + rewritePlace(lvalue, rewrites, declarations); for (const operand of eachInstructionValueOperand(instr.value)) { rewritePlace(operand, rewrites, declarations); } @@ -260,10 +249,7 @@ export function leaveSSA(fn: HIRFunction): void { }; block.instructions.push({ id: block.terminal.id, - lvalue: { - place: { ...initValue, effect: Effect.Mutate }, - kind: InstructionKind.Const, - }, + lvalue: { ...initValue, effect: Effect.Mutate }, value: { kind: "Primitive", // TODO: consider leaving the variable uninitialized rather than explicitly undefined. @@ -295,22 +281,19 @@ export function leaveSSA(fn: HIRFunction): void { // the if) to the phi, so it's safe to reuse the terminal's id. id: block.terminal.id, lvalue: { - place: { - kind: "Identifier", - identifier: { - id: fn.env.nextIdentifierId, - mutableRange: { - start: block.terminal.id, - end: makeInstructionId(block.terminal.id + 1), - }, - name: null, - scope: null, - type: phi.id.type, + kind: "Identifier", + identifier: { + id: fn.env.nextIdentifierId, + mutableRange: { + start: block.terminal.id, + end: makeInstructionId(block.terminal.id + 1), }, - effect: Effect.Mutate, - loc: GeneratedSource, + name: null, + scope: null, + type: phi.id.type, }, - kind: InstructionKind.Const, + effect: Effect.Mutate, + loc: GeneratedSource, }, value: { kind: "StoreLocal", diff --git a/compiler/forget/src/TypeInference/InferTypes.ts b/compiler/forget/src/TypeInference/InferTypes.ts index 1d52f7e21a..6e19bcc5a3 100644 --- a/compiler/forget/src/TypeInference/InferTypes.ts +++ b/compiler/forget/src/TypeInference/InferTypes.ts @@ -54,7 +54,7 @@ function apply(func: HIRFunction, unifier: Unifier) { place.identifier.type = unifier.get(place.identifier.type); } const { lvalue } = instr; - lvalue.place.identifier.type = unifier.get(lvalue.place.identifier.type); + lvalue.identifier.type = unifier.get(lvalue.identifier.type); } } } @@ -93,7 +93,7 @@ function* generateInstructionTypes( instr: Instruction ): Generator { const { lvalue, value } = instr; - const left = lvalue.place.identifier.type; + const left = lvalue.identifier.type; switch (value.kind) { case "JSXText":