diff --git a/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts b/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts index 557c85c875..37dee87566 100644 --- a/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts +++ b/compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts @@ -15,8 +15,8 @@ import { ScopeId, } from "../HIR/HIR"; import { invariant } from "../Utils/CompilerError"; -import { getInstructionScope } from "./BuildReactiveBlocks"; -import { eachTerminalBlock } from "./visitors"; +import { getInstructionScope, getPlaceScope } from "./BuildReactiveBlocks"; +import { eachTerminalBlock, eachTerminalOperand } from "./visitors"; /** * Note: this is the 2nd of 3 passes that determine how to break a function into discrete @@ -81,13 +81,23 @@ function visitBlock(context: Context, block: ReactiveBlock): void { if (id !== null) { context.visitId(id); } - // TODO: visit terminal operands! + eachTerminalOperand(stmt.terminal, (operand) => { + const scope = getPlaceScope(id!, operand); + if (scope !== null) { + context.visitScope(scope); + } + }); eachTerminalBlock( stmt.terminal, (block) => { context.enter(() => visitBlock(context, block)); }, - (valueBlock) => visitValueBlock(context, valueBlock, id!) + (valueBlock) => { + context.enter( + () => visitValueBlock(context, valueBlock, id!), + "value" + ); + } ); break; } @@ -143,8 +153,8 @@ class Context { // the above data structures they're in, to avoid tracking the same scope twice. #seenScopes: Set = new Set(); - enter(fn: () => void): void { - this.#blockScopes.push({ kind: "block", scopes: [] }); + enter(fn: () => void, kind: "block" | "value" = "block"): void { + this.#blockScopes.push({ kind, scopes: [] }); fn(); const lastScope = this.#blockScopes.pop()!; for (const scope of lastScope.scopes) { diff --git a/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts b/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts index 440415efc8..bc376468e9 100644 --- a/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts +++ b/compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts @@ -9,6 +9,7 @@ import invariant from "invariant"; import { InstructionId, makeInstructionId, + Place, ReactiveBlock, ReactiveFunction, ReactiveInstruction, @@ -100,24 +101,30 @@ export function getInstructionScope({ "Expected lvalues to not be null when assigning scopes. " + "Pruning lvalues too early can result in missing scope information." ); - if ( - lvalue.place.identifier.scope !== null && - isScopeActive(lvalue.place.identifier.scope, id) - ) { - return lvalue.place.identifier.scope; - } else { - for (const operand of eachInstructionValueOperand(value)) { - if ( - operand.identifier.scope !== null && - isScopeActive(operand.identifier.scope, id) - ) { - return operand.identifier.scope; - } + const lvalueScope = getPlaceScope(id, lvalue.place); + if (lvalueScope !== null) { + return lvalueScope; + } + for (const operand of eachInstructionValueOperand(value)) { + const operandScope = getPlaceScope(id, operand); + if (operandScope !== null) { + return operandScope; } } return null; } +export function getPlaceScope( + id: InstructionId, + place: Place +): ReactiveScope | null { + const scope = place.identifier.scope; + if (scope !== null && isScopeActive(scope, id)) { + return scope; + } + return null; +} + function isScopeActive(scope: ReactiveScope, id: InstructionId): boolean { return id >= scope.range.start && id < scope.range.end; }