diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index bea08b63b2..570a940272 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -465,9 +465,12 @@ function lowerStatement( * The code leading up to the loop must jump to the conditional block, * to evaluate whether to enter the loop or bypass to the continuation. */ + const loc = stmt.node.loc; + invariant(loc, "while statement must have a location"); builder.terminateWithContinuation( { kind: "while", + loc, test: conditionalBlock.id, loop: loopBlock, fallthrough: continuationBlock.id, diff --git a/compiler/forget/src/HIR/Codegen.ts b/compiler/forget/src/HIR/Codegen.ts index 0fc01752b0..c095f1576c 100644 --- a/compiler/forget/src/HIR/Codegen.ts +++ b/compiler/forget/src/HIR/Codegen.ts @@ -25,10 +25,16 @@ import { todoInvariant } from "./todo"; function withLoc TNode>( fn: T -): (loc: SourceLocation, ...args: Parameters) => ReturnType { - return (loc: SourceLocation, ...args: Parameters): ReturnType => { +): ( + loc: SourceLocation | null | undefined, + ...args: Parameters +) => ReturnType { + return ( + loc: SourceLocation | null | undefined, + ...args: Parameters + ): ReturnType => { const node = fn(...args); - if (loc != GeneratedSource) { + if (loc != null && loc != GeneratedSource) { node.loc = loc; } // @ts-ignore @@ -36,9 +42,11 @@ function withLoc TNode>( }; } +const createExpressionStatement = withLoc(t.expressionStatement); const createFunctionDeclaration = withLoc(t.functionDeclaration); +const createLabelledStatement = withLoc(t.labeledStatement); const createVariableDeclaration = withLoc(t.variableDeclaration); -const createAssignmentExpression = withLoc(t.assignmentExpression); +const createWhileStatement = withLoc(t.whileStatement); /** * Converts HIR into Babel nodes, which can then be printed into source text. @@ -116,7 +124,7 @@ class CodegenVisitor } else { switch (instr.lvalue.kind) { case InstructionKind.Const: { - return t.variableDeclaration("const", [ + return createVariableDeclaration(instr.loc, "const", [ t.variableDeclarator(codegenLVal(instr.lvalue), value), ]); } @@ -126,13 +134,9 @@ class CodegenVisitor ]); } case InstructionKind.Reassign: { - return t.expressionStatement( - createAssignmentExpression( - instr.loc, - "=", - codegenLVal(instr.lvalue), - value - ) + return createExpressionStatement( + instr.loc, + t.assignmentExpression("=", codegenLVal(instr.lvalue), value) ); } default: { @@ -181,7 +185,7 @@ class CodegenVisitor return t.switchStatement(terminal.test, terminal.cases); } case "while": { - return t.whileStatement(terminal.test, terminal.loop); + return createWhileStatement(terminal.loc, terminal.test, terminal.loop); } case "return": { if (terminal.value !== null) { @@ -213,7 +217,7 @@ class CodegenVisitor return; } if (label !== undefined) { - block.push(t.labeledStatement(t.identifier(label), item)); + block.push(createLabelledStatement(item.loc, t.identifier(label), item)); } else { block.push(item); } diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index bc172b53b1..d72cbdf1e3 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -160,6 +160,7 @@ export type SwitchTerminal = { export type WhileTerminal = { kind: "while"; + loc: SourceLocation; test: BlockId; loop: BlockId; fallthrough: BlockId; diff --git a/compiler/forget/src/HIR/HIRTreeVisitor.ts b/compiler/forget/src/HIR/HIRTreeVisitor.ts index c70d8243ad..25e865107c 100644 --- a/compiler/forget/src/HIR/HIRTreeVisitor.ts +++ b/compiler/forget/src/HIR/HIRTreeVisitor.ts @@ -16,6 +16,7 @@ import { Instruction, InstructionValue, Place, + SourceLocation, } from "./HIR"; /** @@ -270,6 +271,7 @@ class Driver { blockValue, this.visitor.visitTerminal({ kind: "while", + loc: terminal.loc, test: testValue, loop: loopBody, }), @@ -281,6 +283,7 @@ class Driver { blockValue, this.visitor.visitTerminal({ kind: "while", + loc: terminal.loc, test: testValue, loop: loopBody, }) @@ -679,6 +682,6 @@ export type BlockTerminal = alternate: TItem | null; } | { kind: "switch"; test: TValue; cases: Array } - | { kind: "while"; test: TValue; loop: TItem } + | { kind: "while"; loc: SourceLocation; test: TValue; loop: TItem } | { kind: "break"; label: string | null } | { kind: "continue"; label: string | null }; diff --git a/compiler/forget/src/HIR/visitors.ts b/compiler/forget/src/HIR/visitors.ts index fbadc7c04a..d9652c4096 100644 --- a/compiler/forget/src/HIR/visitors.ts +++ b/compiler/forget/src/HIR/visitors.ts @@ -201,6 +201,7 @@ export function mapTerminalSuccessors( const fallthrough = fn(terminal.fallthrough, true); return { kind: "while", + loc: terminal.loc, test, loop, fallthrough,