diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 9e6ffa7fd9..a950a2e3d6 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -182,6 +182,7 @@ function lowerStatement( kind: "throw", value, id: makeInstructionId(0), + loc: stmt.node.loc ?? GeneratedSource, }; builder.terminate(terminal, "block"); return; @@ -211,12 +212,14 @@ function lowerStatement( const continuationBlock = builder.reserve("block"); // Block for the consequent (if the test is truthy) const consequentBlock = builder.enter("block", (_blockId) => { - lowerStatement(builder, stmt.get("consequent")); + const consequent = stmt.get("consequent"); + lowerStatement(builder, consequent); return { kind: "goto", block: continuationBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: consequent.node.loc ?? GeneratedSource, }; }); // Block for the alternate (if the test is not truthy) @@ -230,6 +233,7 @@ function lowerStatement( block: continuationBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: alternate.node?.loc ?? GeneratedSource, }; }); } else { @@ -244,6 +248,7 @@ function lowerStatement( alternate: alternateBlock, fallthrough: continuationBlock.id, id: makeInstructionId(0), + loc: stmt.node.loc ?? GeneratedSource, }; builder.terminateWithContinuation(terminal, continuationBlock); return; @@ -262,6 +267,7 @@ function lowerStatement( block, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: stmt.node.loc ?? GeneratedSource, }, "block" ); @@ -276,6 +282,7 @@ function lowerStatement( block, variant: GotoVariant.Continue, id: makeInstructionId(0), + loc: stmt.node.loc ?? GeneratedSource, }, "block" ); @@ -297,7 +304,11 @@ function lowerStatement( severity: ErrorSeverity.Todo, nodePath: stmt, }); - return { kind: "unsupported", id: makeInstructionId(0) }; + return { + kind: "unsupported", + id: makeInstructionId(0), + loc: init.node?.loc ?? GeneratedSource, + }; } lowerStatement(builder, init); return { @@ -305,6 +316,7 @@ function lowerStatement( block: testBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: init.node.loc ?? GeneratedSource, }; }); @@ -318,6 +330,7 @@ function lowerStatement( block: testBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: update.node?.loc ?? GeneratedSource, }; }); } @@ -328,12 +341,14 @@ function lowerStatement( updateBlock ?? testBlock.id, continuationBlock.id, () => { - lowerStatement(builder, stmt.get("body")); + const body = stmt.get("body"); + lowerStatement(builder, body); return { kind: "goto", block: updateBlock ?? testBlock.id, variant: GotoVariant.Continue, id: makeInstructionId(0), + loc: body.node.loc ?? GeneratedSource, }; } ); @@ -371,6 +386,7 @@ function lowerStatement( consequent: bodyBlock, alternate: continuationBlock.id, id: makeInstructionId(0), + loc: stmt.node.loc ?? GeneratedSource, }, continuationBlock ); @@ -390,12 +406,14 @@ function lowerStatement( conditionalBlock.id, continuationBlock.id, () => { - lowerStatement(builder, stmt.get("body")); + const body = stmt.get("body"); + lowerStatement(builder, body); return { kind: "goto", block: conditionalBlock.id, variant: GotoVariant.Continue, id: makeInstructionId(0), + loc: body.node.loc ?? GeneratedSource, }; } ); @@ -427,6 +445,7 @@ function lowerStatement( consequent: loopBlock, alternate: continuationBlock.id, id: makeInstructionId(0), + loc: stmt.node.loc ?? GeneratedSource, }; // Complete the conditional and continue with code after the loop builder.terminateWithContinuation(terminal, continuationBlock); @@ -452,14 +471,16 @@ function lowerStatement( // explicitly *don't* pass the label down const continuationBlock = builder.reserve("block"); const block = builder.enter("block", () => { + const body = stmt.get("body"); builder.label(label, continuationBlock.id, () => { - lowerStatement(builder, stmt.get("body")); + lowerStatement(builder, body); }); return { kind: "goto", block: continuationBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: body.node.loc ?? GeneratedSource, }; }); builder.terminateWithContinuation( @@ -521,6 +542,7 @@ function lowerStatement( block: fallthrough, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: case_.node.loc ?? GeneratedSource, }; }); }); @@ -561,6 +583,7 @@ function lowerStatement( cases, fallthrough: continuationBlock.id, id: makeInstructionId(0), + loc: stmt.node.loc ?? GeneratedSource, }, continuationBlock ); @@ -646,12 +669,14 @@ function lowerStatement( conditionalBlock.id, continuationBlock.id, () => { - lowerStatement(builder, stmt.get("body")); + const body = stmt.get("body"); + lowerStatement(builder, body); return { kind: "goto", block: conditionalBlock.id, variant: GotoVariant.Continue, id: makeInstructionId(0), + loc: body.node.loc ?? GeneratedSource, }; } ); @@ -681,6 +706,7 @@ function lowerStatement( consequent: loopBlock, alternate: continuationBlock.id, id: makeInstructionId(0), + loc, }; // Complete the conditional and continue with code after the loop builder.terminateWithContinuation(terminal, continuationBlock); @@ -729,12 +755,14 @@ function lowerStatement( const loopBlock = builder.enter("block", (_blockId) => { return builder.loop(label, initBlock.id, continuationBlock.id, () => { - lowerStatement(builder, stmt.get("body")); + const body = stmt.get("body"); + lowerStatement(builder, body); return { kind: "goto", block: initBlock.id, variant: GotoVariant.Continue, id: makeInstructionId(0), + loc: body.node.loc ?? GeneratedSource, }; }); }); @@ -794,6 +822,7 @@ function lowerStatement( test, consequent: loopBlock, alternate: continuationBlock.id, + loc: stmt.node.loc ?? GeneratedSource, }, continuationBlock ); @@ -1078,6 +1107,7 @@ function lowerExpression( variant: GotoVariant.Break, block: continuationBlock.id, id: makeInstructionId(0), + loc, }; }); @@ -1099,6 +1129,7 @@ function lowerExpression( variant: GotoVariant.Break, block: continuationBlock.id, id: makeInstructionId(0), + loc, }; }); @@ -1217,10 +1248,8 @@ function lowerExpression( // Block for the consequent (if the test is truthy) const consequentBlock = builder.enter("value", (_blockId) => { - const consequent = lowerExpressionToTemporary( - builder, - expr.get("consequent") - ); + const consequentPath = expr.get("consequent"); + const consequent = lowerExpressionToTemporary(builder, consequentPath); lowerValueToTemporary(builder, { kind: "StoreLocal", lvalue: { kind: InstructionKind.Const, place: { ...place } }, @@ -1232,14 +1261,13 @@ function lowerExpression( block: continuationBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: consequentPath.node.loc ?? GeneratedSource, }; }); // Block for the alternate (if the test is not truthy) const alternateBlock = builder.enter("value", (_blockId) => { - const alternate = lowerExpressionToTemporary( - builder, - expr.get("alternate") - ); + const alternatePath = expr.get("alternate"); + const alternate = lowerExpressionToTemporary(builder, alternatePath); lowerValueToTemporary(builder, { kind: "StoreLocal", lvalue: { kind: InstructionKind.Const, place: { ...place } }, @@ -1251,6 +1279,7 @@ function lowerExpression( block: continuationBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: alternatePath.node.loc ?? GeneratedSource, }; }); @@ -1272,6 +1301,7 @@ function lowerExpression( consequent: consequentBlock, alternate: alternateBlock, id: makeInstructionId(0), + loc: exprLoc, }, continuationBlock ); @@ -1299,6 +1329,7 @@ function lowerExpression( block: continuationBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: leftPlace.loc, }; }); const alternate = builder.enter("value", () => { @@ -1314,6 +1345,7 @@ function lowerExpression( block: continuationBlock.id, variant: GotoVariant.Break, id: makeInstructionId(0), + loc: right.loc, }; }); builder.terminateWithContinuation( @@ -1345,6 +1377,7 @@ function lowerExpression( consequent, alternate, id: makeInstructionId(0), + loc: exprLoc, }, continuationBlock ); @@ -2537,6 +2570,7 @@ function lowerAssignment( consequent, alternate, id: makeInstructionId(0), + loc, }, continuationBlock ); diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 3caad7f65d..48845b7605 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -278,13 +278,36 @@ export type Terminal = | OptionalCallTerminal | LabelTerminal; +function _staticInvariantTerminalHasLocation( + terminal: Terminal +): SourceLocation { + // If this fails, it is because a variant of Terminal is missing a .loc - add it! + return terminal.loc; +} + +function _staticInvariantTerminalHasInstructionId( + terminal: Terminal +): InstructionId { + // If this fails, it is because a variant of Terminal is missing a .id - add it! + return terminal.id; +} + /** * Terminal nodes allowed for a value block */ export type ValueTerminal = IfTerminal | GotoTerminal; // A terminal that couldn't be lowered correctly. -export type UnsupportedTerminal = { kind: "unsupported"; id: InstructionId }; -export type ThrowTerminal = { kind: "throw"; value: Place; id: InstructionId }; +export type UnsupportedTerminal = { + kind: "unsupported"; + id: InstructionId; + loc: SourceLocation; +}; +export type ThrowTerminal = { + kind: "throw"; + value: Place; + id: InstructionId; + loc: SourceLocation; +}; export type Case = { test: Place | null; block: BlockId }; export type ReturnTerminal = { @@ -299,6 +322,7 @@ export type GotoTerminal = { block: BlockId; variant: GotoVariant; id: InstructionId; + loc: SourceLocation; }; export enum GotoVariant { @@ -313,6 +337,7 @@ export type IfTerminal = { alternate: BlockId; fallthrough: BlockId | null; id: InstructionId; + loc: SourceLocation; }; export type BranchTerminal = { @@ -321,6 +346,7 @@ export type BranchTerminal = { consequent: BlockId; alternate: BlockId; id: InstructionId; + loc: SourceLocation; }; export type SwitchTerminal = { @@ -329,6 +355,7 @@ export type SwitchTerminal = { cases: Case[]; fallthrough: BlockId | null; id: InstructionId; + loc: SourceLocation; }; export type DoWhileTerminal = { diff --git a/compiler/forget/src/HIR/HIRBuilder.ts b/compiler/forget/src/HIR/HIRBuilder.ts index de09951927..4a54234d67 100644 --- a/compiler/forget/src/HIR/HIRBuilder.ts +++ b/compiler/forget/src/HIR/HIRBuilder.ts @@ -581,6 +581,7 @@ export function removeDeadDoWhileStatements(func: HIR): void { block: block.terminal.loop, variant: GotoVariant.Break, id: block.terminal.id, + loc: block.terminal.loc, }; } } diff --git a/compiler/forget/src/HIR/visitors.ts b/compiler/forget/src/HIR/visitors.ts index 44deff2d99..27ae476ba0 100644 --- a/compiler/forget/src/HIR/visitors.ts +++ b/compiler/forget/src/HIR/visitors.ts @@ -512,6 +512,7 @@ export function mapTerminalSuccessors( block: target, variant: terminal.variant, id: makeInstructionId(0), + loc: terminal.loc, }; } case "if": { @@ -526,6 +527,7 @@ export function mapTerminalSuccessors( alternate, fallthrough, id: makeInstructionId(0), + loc: terminal.loc, }; } case "branch": { @@ -537,6 +539,7 @@ export function mapTerminalSuccessors( consequent, alternate, id: makeInstructionId(0), + loc: terminal.loc, }; } case "switch": { @@ -555,6 +558,7 @@ export function mapTerminalSuccessors( cases, fallthrough, id: makeInstructionId(0), + loc: terminal.loc, }; } case "logical": { diff --git a/compiler/forget/src/Optimization/ConstantPropagation.ts b/compiler/forget/src/Optimization/ConstantPropagation.ts index 4dd321a393..2d62b7868d 100644 --- a/compiler/forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/forget/src/Optimization/ConstantPropagation.ts @@ -135,6 +135,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean { variant: GotoVariant.Break, block: targetBlockId, id: terminal.id, + loc: terminal.loc, }; } break;