diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 3a33048e51..44565f7ae6 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -79,7 +79,6 @@ export function lower( const place: Place = { kind: "Identifier", identifier, - memberPath: null, effect: Effect.Unknown, loc: param.loc ?? GeneratedSource, }; @@ -624,6 +623,10 @@ function lowerStatement( nodeKind === "let" ? InstructionKind.Let : InstructionKind.Const; for (const declaration of stmt.get("declarations")) { const id = declaration.get("id"); + invariant( + id.isIdentifier(), + "Support non-identifier variable declarations" + ); const init = declaration.get("init"); let value: InstructionValue; if (init.hasNode()) { @@ -942,11 +945,12 @@ function lowerExpression( const leftNode = left.node; switch (leftNode.type) { case "Identifier": { + const lvalue = left as NodePath; return lowerAssignment( builder, leftNode.loc ?? GeneratedSource, InstructionKind.Reassign, - left, + lvalue, lowerExpression(builder, expr.get("right")) ); } @@ -1247,7 +1251,6 @@ function lowerJsxElementName( const place: Place = { kind: "Identifier", identifier: identifier, - memberPath: null, effect: Effect.Unknown, loc: exprLoc, }; @@ -1373,47 +1376,12 @@ function lowerIdentifier( const place: Place = { kind: "Identifier", identifier: identifier, - memberPath: null, effect: Effect.Unknown, loc: exprLoc, }; return place; } -function lowerLVal(builder: HIRBuilder, exprPath: NodePath): Place { - const exprNode = exprPath.node; - const exprLoc = exprNode.loc ?? GeneratedSource; - switch (exprNode.type) { - case "Identifier": { - const expr = exprPath as NodePath; - return lowerIdentifier(builder, expr); - } - case "MemberExpression": { - const expr = exprPath as NodePath; - const objectPath = expr.get("object"); - todoInvariant(objectPath.isLVal(), "Support complex object assignment"); - const object = lowerLVal(builder, objectPath); - const propertyPath = expr.get("property"); - todoInvariant( - propertyPath.isIdentifier(), - "Support non-identifier properties" - ); - const place: Place = { - kind: "Identifier", - identifier: object.identifier, - memberPath: [...(object.memberPath ?? []), propertyPath.node.name], - effect: Effect.Unknown, - loc: exprLoc, - }; - return place; - } - default: { - todo(`lowerLVal(${exprNode.type})`); - // assertExhaustive(exprNode, "Unexpected lval kind"); - } - } -} - /** * Creates a temporary Identifier and Place referencing that identifier. */ @@ -1421,7 +1389,6 @@ function buildTemporaryPlace(builder: HIRBuilder, loc: SourceLocation): Place { const place: Place = { kind: "Identifier", identifier: builder.makeTemporary(), - memberPath: null, effect: Effect.Unknown, loc, }; @@ -1432,10 +1399,10 @@ function lowerAssignment( builder: HIRBuilder, loc: SourceLocation, kind: InstructionKind, - lvalue: NodePath, + lvalue: NodePath, value: InstructionValue ): InstructionValue { - const id = lowerLVal(builder, lvalue); + const id = lowerIdentifier(builder, lvalue); builder.push({ id: makeInstructionId(0), lvalue: { place: id, kind }, diff --git a/compiler/forget/src/HIR/Codegen.ts b/compiler/forget/src/HIR/Codegen.ts index 2f19e26955..0e6b776df1 100644 --- a/compiler/forget/src/HIR/Codegen.ts +++ b/compiler/forget/src/HIR/Codegen.ts @@ -302,10 +302,7 @@ export function codegenInstruction( if (instr.lvalue === null) { return t.expressionStatement(value); } - if ( - instr.lvalue.place.memberPath === null && - instr.lvalue.place.identifier.name === null - ) { + if (instr.lvalue.place.identifier.name === null) { // temporary temp.set(instr.lvalue.place.identifier.id, value); return t.emptyStatement(); @@ -511,15 +508,7 @@ function codegenJsxElement( } export function codegenLVal(lval: LValue): t.LVal { - const expr = convertIdentifier(lval.place.identifier); - const memberPath = lval.place.memberPath; - return memberPath == null - ? expr - : memberPath.reduceRight( - (path: t.Identifier | t.MemberExpression, member) => - t.memberExpression(path, t.identifier(member)), - expr - ); + return convertIdentifier(lval.place.identifier); } function codegenValue( @@ -543,19 +532,11 @@ function codegenValue( export function codegenPlace(temp: Temporaries, place: Place): t.Expression { todoInvariant(place.kind === "Identifier", "support scope values"); - if (place.memberPath === null) { - let tmp = temp.get(place.identifier.id); - if (tmp != null) { - return tmp; - } - return convertIdentifier(place.identifier); - } else { - let object: t.Expression = convertIdentifier(place.identifier); - for (const path of place.memberPath) { - object = t.memberExpression(object, t.identifier(path)); - } - return object; + let tmp = temp.get(place.identifier.id); + if (tmp != null) { + return tmp; } + return convertIdentifier(place.identifier); } export function convertIdentifier(identifier: Identifier): t.Identifier { diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 3187297bc2..a3eaf3916a 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -316,7 +316,6 @@ export type InstructionData = export type Place = { kind: "Identifier"; identifier: Identifier; - memberPath: Array | null; effect: Effect; loc: SourceLocation; }; diff --git a/compiler/forget/src/HIR/InferAlias.ts b/compiler/forget/src/HIR/InferAlias.ts index 163816b85a..7bed382a12 100644 --- a/compiler/forget/src/HIR/InferAlias.ts +++ b/compiler/forget/src/HIR/InferAlias.ts @@ -7,11 +7,6 @@ class AliasAnalyser { aliases = new DisjointSet(); alias(lvalue: LValue, alias: Place) { - // This is handled by InferAliasForStores. - if (lvalue.place.memberPath !== null) { - return; - } - this.aliases.union([lvalue.place.identifier, alias.identifier]); } } diff --git a/compiler/forget/src/HIR/InferMutableLifetimes.ts b/compiler/forget/src/HIR/InferMutableLifetimes.ts index 3ad3f9d4c3..2c84933eec 100644 --- a/compiler/forget/src/HIR/InferMutableLifetimes.ts +++ b/compiler/forget/src/HIR/InferMutableLifetimes.ts @@ -122,19 +122,15 @@ export function inferMutableLifetimes( } if (instr.lvalue !== null) { - if (instr.lvalue.place.memberPath === null) { - const lvalueId = instr.lvalue.place.identifier; + const lvalueId = instr.lvalue.place.identifier; - // lvalue start being mutable when they're initially assigned a - // value. - lvalueId.mutableRange.start = instr.id; + // lvalue start being mutable when they're initially assigned a + // value. + lvalueId.mutableRange.start = instr.id; - // Let's be optimistic and assume this lvalue is not mutable by - // default. - lvalueId.mutableRange.end = makeInstructionId(instr.id + 1); - } else { - inferPlace(instr.lvalue.place, instr, inferMutableRangeForStores); - } + // Let's be optimistic and assume this lvalue is not mutable by + // default. + lvalueId.mutableRange.end = makeInstructionId(instr.id + 1); } } } diff --git a/compiler/forget/src/HIR/InferReferenceEffects.ts b/compiler/forget/src/HIR/InferReferenceEffects.ts index 0a0934be0e..a873245abb 100644 --- a/compiler/forget/src/HIR/InferReferenceEffects.ts +++ b/compiler/forget/src/HIR/InferReferenceEffects.ts @@ -74,7 +74,6 @@ export default function inferReferenceEffects(fn: HIRFunction) { const initialEnvironment = Environment.empty(); const id: Place = { kind: "Identifier", - memberPath: null, identifier: fn.id as any, loc: fn.loc, effect: Effect.Freeze, @@ -172,7 +171,7 @@ class Environment { */ initialize(value: InstructionValue, kind: ValueKind) { invariant( - value.kind !== "Identifier" || value.memberPath !== null, + value.kind !== "Identifier", "Expected all top-level identifiers to be defined as variables, not values" ); this.#values.set(value, kind); @@ -218,10 +217,6 @@ class Environment { * Defines (initializing or updating) a variable with a specific kind of value. */ define(place: Place, value: InstructionValue) { - invariant( - place.memberPath === null, - "Expected a top-level identifier, not a member path" - ); invariant( this.#values.has(value), `Expected value to be initialized at '${printSourceLocation(value.loc)}'` @@ -587,10 +582,6 @@ function inferBlock(env: Environment, block: BasicBlock) { const lvalue = instr.lvalue; if (lvalue !== null) { - invariant( - lvalue.place.memberPath === null, - "PropertyLoad must always be saved to a temporary" - ); env.alias(lvalue.place, instrValue.value); lvalue.place.effect = Effect.Store; } @@ -611,27 +602,15 @@ function inferBlock(env: Environment, block: BasicBlock) { env.reference(instrValue.object, Effect.Read); const lvalue = instr.lvalue; if (lvalue !== null) { - invariant( - lvalue.place.memberPath === null, - "PropertyLoad must always be saved to a temporary" - ); env.initialize(instrValue, env.kind(instrValue.object)); env.define(lvalue.place, instrValue); } continue; } case "Identifier": { - invariant( - instrValue.memberPath === null, - "Expected RHS memberPath to be lowered to PropertyLoad" - ); env.reference(instrValue, Effect.Read); const lvalue = instr.lvalue; if (lvalue !== null) { - invariant( - lvalue.place.memberPath === null, - "Expected lvalue member path to be null" - ); lvalue.place.effect = Effect.Mutate; // direct aliasing: `a = b`; env.alias(lvalue.place, instrValue); @@ -654,10 +633,6 @@ function inferBlock(env: Environment, block: BasicBlock) { env.initialize(instrValue, valueKind); if (instr.lvalue !== null) { - invariant( - instr.lvalue.place.memberPath === null, - "Expected lvalue member path to be null" - ); env.define(instr.lvalue.place, instrValue); instr.lvalue.place.effect = lvalueEffect; } @@ -695,10 +670,6 @@ type HookKind = { kind: "State" } | { kind: "Ref" } | { kind: "Custom" }; type Hook = HookKind & { effectKind: Effect; valueKind: ValueKind }; function parseHookCall(place: Place): Hook | null { - if (place.memberPath !== null) { - // Hook calls must be statically resolved - return null; - } const name = place.identifier.name; if (name === null || !name.match(/^_?use/)) { return null; diff --git a/compiler/forget/src/HIR/InferTypes.ts b/compiler/forget/src/HIR/InferTypes.ts index 0f33e9401e..2e7da0da31 100644 --- a/compiler/forget/src/HIR/InferTypes.ts +++ b/compiler/forget/src/HIR/InferTypes.ts @@ -132,7 +132,7 @@ function generateTypeEquation( function assignType(place: Place | undefined): Type | null { // We type only top level identifiers. Typing objects is not very useful // when we have to be so conservative. - if (place?.memberPath !== null) { + if (place === undefined) { return null; } diff --git a/compiler/forget/src/HIR/PrintHIR.ts b/compiler/forget/src/HIR/PrintHIR.ts index 4b84f0be13..80527b34f1 100644 --- a/compiler/forget/src/HIR/PrintHIR.ts +++ b/compiler/forget/src/HIR/PrintHIR.ts @@ -321,14 +321,7 @@ export function printLValue(lval: LValue): string { export function printPlace(place: Place): string { const items = [place.effect, " ", printIdentifier(place.identifier)]; - if (place.memberPath !== null) { - for (const path of place.memberPath) { - items.push("."); - items.push(path); - } - } else { - items.push(printType(place.identifier.type)); - } + items.push(printType(place.identifier.type)); return items.filter((x) => x != null).join(""); } diff --git a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts index 10f1bea45f..0c9b939b66 100644 --- a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -305,11 +305,7 @@ export function codegenInstructionNullable( value: t.Expression ): t.Statement | null { let statement; - if ( - instr.lvalue !== null && - instr.lvalue.place.memberPath === null && - cx.declared(instr.lvalue.place.identifier) - ) { + if (instr.lvalue !== null && cx.declared(instr.lvalue.place.identifier)) { statement = codegenInstruction( cx.temp, { diff --git a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts index 83288a9f0b..546521500b 100644 --- a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts +++ b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts @@ -80,11 +80,7 @@ export function inferReactiveScopeVariables(fn: HIRFunction) { const operands: Array = []; if (instr.lvalue !== null) { const range = instr.lvalue.place.identifier.mutableRange; - if ( - instr.lvalue.place.memberPath !== null || - range.end > range.start + 1 || - mayAllocate(instr.value) - ) { + if (range.end > range.start + 1 || mayAllocate(instr.value)) { operands.push(instr.lvalue!.place.identifier); } } diff --git a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts index 3817d54a5c..6a497bf083 100644 --- a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts +++ b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts @@ -21,7 +21,6 @@ import { ReactiveValueBlock, } from "../HIR/HIR"; import { eachInstructionValueOperand } from "../HIR/visitors"; -import { invariant } from "../Utils/CompilerError"; import { assertExhaustive } from "../Utils/utils"; /** @@ -76,14 +75,6 @@ class Context { } declareProperty(lvalue: Place, object: Place, property: string): void { - invariant( - lvalue.memberPath === null, - "Expected property loads to be stored to a temporary (no member path)" - ); - invariant( - object.memberPath === null, - "Expected operands to have null memberPath" - ); const objectDependency = this.#properties.get(object.identifier); let nextDependency: ReactiveScopeDependency; if (objectDependency === undefined) { @@ -281,17 +272,7 @@ function visitInstructionValue( ): void { for (const operand of eachInstructionValueOperand(value)) { // check for method invocation, we want to depend on the callee, not the method - if ( - value.kind === "CallExpression" && - operand === value.callee && - operand.memberPath !== null - ) { - const callee = { - ...operand, - memberPath: operand.memberPath.slice(0, -1), - }; - context.visitOperand(callee); - } else if (value.kind === "PropertyLoad" && lvalue !== null) { + if (value.kind === "PropertyLoad" && lvalue !== null) { context.declareProperty(lvalue.place, value.object, value.property); } else { context.visitOperand(operand); @@ -302,11 +283,7 @@ function visitInstructionValue( function visitInstruction(context: Context, instr: Instruction): void { const { lvalue } = instr; visitInstructionValue(context, instr.value, lvalue); - if ( - lvalue !== null && - lvalue.kind !== InstructionKind.Reassign && - lvalue.place.memberPath === null - ) { + if (lvalue !== null && lvalue.kind !== InstructionKind.Reassign) { const range = lvalue.place.identifier.mutableRange; // TODO: only assign Const if the value is never reassigned const kind = diff --git a/compiler/forget/src/SSA/EnterSSA.ts b/compiler/forget/src/SSA/EnterSSA.ts index eb2a4db3e0..cdc9dc1584 100644 --- a/compiler/forget/src/SSA/EnterSSA.ts +++ b/compiler/forget/src/SSA/EnterSSA.ts @@ -199,12 +199,8 @@ export default function enterSSA(func: HIRFunction, env: Environment) { if (instr.lvalue != null) { const oldPlace = instr.lvalue.place; let newPlace: Place; - if (oldPlace.memberPath !== null) { - newPlace = builder.getPlace(oldPlace); - } else { - newPlace = builder.definePlace(oldPlace); - instr.lvalue.kind = InstructionKind.Const; - } + newPlace = builder.definePlace(oldPlace); + instr.lvalue.kind = InstructionKind.Const; instr.lvalue.place = newPlace; } } diff --git a/compiler/forget/src/SSA/LeaveSSA.ts b/compiler/forget/src/SSA/LeaveSSA.ts index a560a11408..e5c30cb3f4 100644 --- a/compiler/forget/src/SSA/LeaveSSA.ts +++ b/compiler/forget/src/SSA/LeaveSSA.ts @@ -136,13 +136,6 @@ export function leaveSSA(fn: HIRFunction) { const update = fn.body.blocks.get(terminal.update)!; rewritePhis.push(...update.phis); update.phis.clear(); - - // find declarations in the for init - for (const instr of init.instructions) { - if (instr.lvalue !== null && instr.lvalue.place.memberPath === null) { - // hasDeclaration.add(instr.lvalue.place.identifier); - } - } } for (const phi of reassignmentPhis) { @@ -197,7 +190,6 @@ export function leaveSSA(fn: HIRFunction) { lvalue: { place: { kind: "Identifier", - memberPath: null, identifier: canonicalId, effect: Effect.Mutate, loc: GeneratedSource, @@ -208,7 +200,6 @@ export function leaveSSA(fn: HIRFunction) { initOperand !== null ? { kind: "Identifier", - memberPath: null, identifier: initOperand, effect: Effect.Read, loc: GeneratedSource, @@ -234,7 +225,6 @@ export function leaveSSA(fn: HIRFunction) { lvalue: { place: { kind: "Identifier", - memberPath: null, identifier: canonicalId, effect: Effect.Mutate, loc: GeneratedSource, @@ -243,7 +233,6 @@ export function leaveSSA(fn: HIRFunction) { }, value: { kind: "Identifier", - memberPath: null, identifier: operand, effect: Effect.Read, loc: GeneratedSource, @@ -295,7 +284,6 @@ export function leaveSSA(fn: HIRFunction) { if (lvalue !== null) { if ( lvalue.kind === InstructionKind.Const && - lvalue.place.memberPath === null && rewrites.has(lvalue.place.identifier) ) { // For rewrites, the declaration of the canonical identifier has to be `let`,