diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index d197ec95e1..3f92439691 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -1815,7 +1815,7 @@ function lowerOptionalMemberExpression( builder.terminateWithContinuation( { - kind: "optional-call", + kind: "optional", optional, test: testBlock, fallthrough: continuationBlock.id, @@ -1966,7 +1966,7 @@ function lowerOptionalCallExpression( builder.terminateWithContinuation( { - kind: "optional-call", + kind: "optional", optional, test: testBlock, fallthrough: continuationBlock.id, diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index d9fe6f231c..1b6dcaefca 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -118,9 +118,9 @@ export type ReactiveSequenceValue = { }; export type ReactiveOptionalCallValue = { - kind: "OptionalCall"; + kind: "OptionalExpression"; id: InstructionId; - call: ReactiveValue; + value: ReactiveValue; optional: boolean; loc: SourceLocation; }; @@ -275,7 +275,7 @@ export type Terminal = | WhileTerminal | LogicalTerminal | TernaryTerminal - | OptionalCallTerminal + | OptionalTerminal | LabelTerminal; function _staticInvariantTerminalHasLocation( @@ -421,11 +421,12 @@ export type LabelTerminal = { loc: SourceLocation; }; -export type OptionalCallTerminal = { - kind: "optional-call"; - // Whether the call itself is optional. If false, this means that the callee itself - // is optionally evaluated (has some OptionalMemberExpresion) but the final call is - // required (if the callee is not null/undefined). +export type OptionalTerminal = { + kind: "optional"; + // Specifies whether this node was optional. If false, it means that the original + // node was part of an optional chain but this specific item was non-optional. + // For example, in `a?.b.c?.()`, the `.b` access is non-optional but appears within + // an optional chain. optional: boolean; test: BlockId; fallthrough: BlockId; diff --git a/compiler/forget/src/HIR/HIRBuilder.ts b/compiler/forget/src/HIR/HIRBuilder.ts index aa5dc76b6f..1f76461e75 100644 --- a/compiler/forget/src/HIR/HIRBuilder.ts +++ b/compiler/forget/src/HIR/HIRBuilder.ts @@ -652,7 +652,7 @@ export function reversePostorderBlocks(func: HIR): void { } break; } - case "optional-call": + case "optional": case "ternary": case "logical": { visit(terminal.test); diff --git a/compiler/forget/src/HIR/PrintHIR.ts b/compiler/forget/src/HIR/PrintHIR.ts index d59e2e11a0..53840e5861 100644 --- a/compiler/forget/src/HIR/PrintHIR.ts +++ b/compiler/forget/src/HIR/PrintHIR.ts @@ -80,7 +80,7 @@ export function printMixedHIR( } switch (value.kind) { case "label": - case "optional-call": + case "optional": case "branch": case "if": case "logical": @@ -158,8 +158,8 @@ export function printTerminal(terminal: Terminal): Array | string { value = `[${terminal.id}] Ternary test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`; break; } - case "optional-call": { - value = `[${terminal.id}] OptionalCall test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`; + case "optional": { + value = `[${terminal.id}] Optional test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`; break; } case "throw": { @@ -458,8 +458,8 @@ export function printInstructionValue(instrValue: ReactiveValue): string { value = `Global ${instrValue.name}`; break; } - case "OptionalCall": { - value = `OptionalCall ${printInstructionValue(instrValue.call)}`; + case "OptionalExpression": { + value = `OptionalExpression ${printInstructionValue(instrValue.value)}`; break; } case "RegExpLiteral": { diff --git a/compiler/forget/src/HIR/visitors.ts b/compiler/forget/src/HIR/visitors.ts index 031d73b59d..44d784354a 100644 --- a/compiler/forget/src/HIR/visitors.ts +++ b/compiler/forget/src/HIR/visitors.ts @@ -598,11 +598,11 @@ export function mapTerminalSuccessors( loc: terminal.loc, }; } - case "optional-call": { + case "optional": { const test = fn(terminal.test); const fallthrough = fn(terminal.fallthrough); return { - kind: "optional-call", + kind: "optional", optional: terminal.optional, test, fallthrough, @@ -721,7 +721,7 @@ export function terminalFallthrough(terminal: Terminal): BlockId | null { case "if": case "label": case "logical": - case "optional-call": + case "optional": case "switch": case "ternary": case "while": { @@ -768,7 +768,7 @@ export function mapOptionalFallthroughs( const _: BlockId = terminal.fallthrough; break; } - case "optional-call": { + case "optional": { const _: BlockId = terminal.fallthrough; break; } @@ -834,7 +834,7 @@ export function* eachTerminalSuccessor(terminal: Terminal): Iterable { } break; } - case "optional-call": + case "optional": case "ternary": case "logical": { yield terminal.test; @@ -906,7 +906,7 @@ export function mapTerminalOperands( break; } case "label": - case "optional-call": + case "optional": case "ternary": case "logical": case "do-while": @@ -953,7 +953,7 @@ export function* eachTerminalOperand(terminal: Terminal): Iterable { break; } case "label": - case "optional-call": + case "optional": case "ternary": case "logical": case "do-while": diff --git a/compiler/forget/src/Inference/InlineUseMemo.ts b/compiler/forget/src/Inference/InlineUseMemo.ts index 8664111f87..78ace5f73c 100644 --- a/compiler/forget/src/Inference/InlineUseMemo.ts +++ b/compiler/forget/src/Inference/InlineUseMemo.ts @@ -171,7 +171,7 @@ export function inlineUseMemo(fn: HIRFunction): void { } // These all have non-nullable fallthroughs: there is always some code in the // CFG that succeeds them which we should find instead - case "optional-call": + case "optional": case "ternary": case "logical": case "while": @@ -282,7 +282,7 @@ function getTerminalBlock(cfg: HIR, start: BlockId): BasicBlock { return current; } } - case "optional-call": + case "optional": case "ternary": case "logical": case "while": diff --git a/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts index ac14e933ee..3d5427f212 100644 --- a/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts @@ -560,7 +560,7 @@ class Driver { break; } - case "optional-call": + case "optional": case "ternary": case "logical": { const fallthroughId = terminal.fallthrough; @@ -756,7 +756,7 @@ class Driver { id: InstructionId; } { switch (terminal.kind) { - case "optional-call": { + case "optional": { const test = this.visitValueBlock(terminal.test, terminal.loc); const testBlock = this.cx.ir.blocks.get(test.block)!; invariant( @@ -785,9 +785,9 @@ class Driver { return { place: { ...consequent.place }, value: { - kind: "OptionalCall", + kind: "OptionalExpression", optional: terminal.optional, - call: call, + value: call, id: terminal.id, loc: terminal.loc, }, diff --git a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts index 23e55817f3..129986cb70 100644 --- a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -684,8 +684,8 @@ function codegenInstructionValue( value = createCallExpression(instrValue.loc, callee, args); break; } - case "OptionalCall": { - const optionalValue = codegenInstructionValue(cx, instrValue.call); + case "OptionalExpression": { + const optionalValue = codegenInstructionValue(cx, instrValue.value); switch (optionalValue.type) { case "OptionalCallExpression": case "CallExpression": { diff --git a/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts b/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts index e970b5a438..677c18796c 100644 --- a/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts +++ b/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts @@ -125,7 +125,7 @@ class Visitor extends ReactiveFunctionVisitor { if ( instruction.value.kind === "ConditionalExpression" || instruction.value.kind === "LogicalExpression" || - instruction.value.kind === "OptionalCall" + instruction.value.kind === "OptionalExpression" ) { state.enter(() => { super.visitInstruction(instruction, state); diff --git a/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts index dc50874395..af8b5b07d4 100644 --- a/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts @@ -151,11 +151,11 @@ function printReactiveValue(writer: Writer, value: ReactiveValue): void { }); break; } - case "OptionalCall": { - writer.append(`OptionalCall optional=${value.optional}`); + case "OptionalExpression": { + writer.append(`OptionalExpression optional=${value.optional}`); writer.newline(); writer.indented(() => { - printReactiveValue(writer, value.call); + printReactiveValue(writer, value.value); }); break; } diff --git a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts index 39bf3807fd..5c27e56e1e 100644 --- a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts +++ b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts @@ -450,9 +450,9 @@ class PropagationVisitor extends ReactiveFunctionVisitor { value: ReactiveValue ): void { switch (value.kind) { - case "OptionalCall": { + case "OptionalExpression": { context.enterConditional(() => { - this.visitReactiveValue(context, id, value.call); + this.visitReactiveValue(context, id, value.value); }); break; } diff --git a/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts b/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts index 1cdd9bd3e8..9ced59c1e5 100644 --- a/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts +++ b/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts @@ -525,7 +525,7 @@ function computeMemoizationInputs( rvalues: [value.value], }; } - case "OptionalCall": + case "OptionalExpression": case "RegExpLiteral": case "FunctionExpression": case "TaggedTemplateExpression": diff --git a/compiler/forget/src/ReactiveScopes/visitors.ts b/compiler/forget/src/ReactiveScopes/visitors.ts index 1c1a4c2b36..d7b80fd8b8 100644 --- a/compiler/forget/src/ReactiveScopes/visitors.ts +++ b/compiler/forget/src/ReactiveScopes/visitors.ts @@ -41,8 +41,8 @@ export class ReactiveFunctionVisitor { } traverseValue(id: InstructionId, value: ReactiveValue, state: TState): void { switch (value.kind) { - case "OptionalCall": { - this.visitValue(id, value.call, state); + case "OptionalExpression": { + this.visitValue(id, value.value, state); break; } case "LogicalExpression": { @@ -290,8 +290,8 @@ export function* eachReactiveValueOperand( instrValue: ReactiveValue ): Iterable { switch (instrValue.kind) { - case "OptionalCall": { - yield* eachReactiveValueOperand(instrValue.call); + case "OptionalExpression": { + yield* eachReactiveValueOperand(instrValue.value); break; } case "LogicalExpression": { diff --git a/compiler/forget/src/Utils/VisualizeHIRMermaid.ts b/compiler/forget/src/Utils/VisualizeHIRMermaid.ts index a265bb5361..73bd38fbab 100644 --- a/compiler/forget/src/Utils/VisualizeHIRMermaid.ts +++ b/compiler/forget/src/Utils/VisualizeHIRMermaid.ts @@ -114,8 +114,8 @@ function printTerminalLabel(terminal: Terminal): string { buffer.push("Ternary"); break; } - case "optional-call": { - buffer.push("OptionalCall"); + case "optional": { + buffer.push("Optional"); break; } case "do-while": { @@ -175,7 +175,7 @@ function printTerminalArrows(blockId: BlockId, terminal: Terminal): string { buffer.push(printJumpArrow(blockId, terminal.fallthrough, "fallthrough")); break; } - case "optional-call": { + case "optional": { buffer.push(printJumpArrow(blockId, terminal.test, "test")); buffer.push(printJumpArrow(blockId, terminal.fallthrough, "fallthrough")); break;