[codegen] location refinements
- Add a `loc` to the `while` terminal node. - Move location data for assignments 1 level higher as that seems to work better in the generated code (not tested with actual debugger yet though, we'll probably want to look at this more closely.
Jan Kassens committed
Nov 21, 2022 at 15:35 UTC
d44082d63c835df9b4f209a260539c640c783f30
5 files changed
+27
-15
compiler/forget/src/HIR/BuildHIR.ts
+3
@@ -465,9 +465,12 @@ function lowerStatement(
465
* The code leading up to the loop must jump to the conditional block,
466
* to evaluate whether to enter the loop or bypass to the continuation.
467
*/
468
+ const loc = stmt.node.loc;
469
+ invariant(loc, "while statement must have a location");
470
builder.terminateWithContinuation(
471
{
472
kind: "while",
473
+ loc,
474
test: conditionalBlock.id,
475
loop: loopBlock,
476
fallthrough: continuationBlock.id,
compiler/forget/src/HIR/Codegen.ts
+18
-14
@@ -25,10 +25,16 @@ import { todoInvariant } from "./todo";
25
26
function withLoc<TNode extends t.Node, T extends (...args: any[]) => TNode>(
27
fn: T
28
-): (loc: SourceLocation, ...args: Parameters<T>) => ReturnType<T> {
29
- return (loc: SourceLocation, ...args: Parameters<T>): ReturnType<T> => {
28
+): (
29
+ loc: SourceLocation | null | undefined,
30
+ ...args: Parameters<T>
31
+) => ReturnType<T> {
32
+ return (
33
+ loc: SourceLocation | null | undefined,
34
+ ...args: Parameters<T>
35
+ ): ReturnType<T> => {
36
const node = fn(...args);
31
- if (loc != GeneratedSource) {
37
+ if (loc != null && loc != GeneratedSource) {
38
node.loc = loc;
39
}
40
// @ts-ignore
@@ -36,9 +42,11 @@ function withLoc<TNode extends t.Node, T extends (...args: any[]) => TNode>(
42
};
43
}
44
45
+const createExpressionStatement = withLoc(t.expressionStatement);
46
const createFunctionDeclaration = withLoc(t.functionDeclaration);
47
+const createLabelledStatement = withLoc(t.labeledStatement);
48
const createVariableDeclaration = withLoc(t.variableDeclaration);
41
-const createAssignmentExpression = withLoc(t.assignmentExpression);
49
+const createWhileStatement = withLoc(t.whileStatement);
50
51
/**
52
* Converts HIR into Babel nodes, which can then be printed into source text.
@@ -116,7 +124,7 @@ class CodegenVisitor
124
} else {
125
switch (instr.lvalue.kind) {
126
case InstructionKind.Const: {
119
- return t.variableDeclaration("const", [
127
+ return createVariableDeclaration(instr.loc, "const", [
128
t.variableDeclarator(codegenLVal(instr.lvalue), value),
129
]);
130
}
@@ -126,13 +134,9 @@ class CodegenVisitor
134
]);
135
}
136
case InstructionKind.Reassign: {
129
- return t.expressionStatement(
130
- createAssignmentExpression(
131
- instr.loc,
132
- "=",
133
- codegenLVal(instr.lvalue),
134
- value
135
- )
137
+ return createExpressionStatement(
138
+ instr.loc,
139
+ t.assignmentExpression("=", codegenLVal(instr.lvalue), value)
140
);
141
}
142
default: {
@@ -181,7 +185,7 @@ class CodegenVisitor
185
return t.switchStatement(terminal.test, terminal.cases);
186
}
187
case "while": {
184
- return t.whileStatement(terminal.test, terminal.loop);
188
+ return createWhileStatement(terminal.loc, terminal.test, terminal.loop);
189
}
190
case "return": {
191
if (terminal.value !== null) {
@@ -213,7 +217,7 @@ class CodegenVisitor
217
return;
218
}
219
if (label !== undefined) {
216
- block.push(t.labeledStatement(t.identifier(label), item));
220
+ block.push(createLabelledStatement(item.loc, t.identifier(label), item));
221
} else {
222
block.push(item);
223
}
compiler/forget/src/HIR/HIR.ts
+1
@@ -160,6 +160,7 @@ export type SwitchTerminal = {
160
161
export type WhileTerminal = {
162
kind: "while";
163
+ loc: SourceLocation;
164
test: BlockId;
165
loop: BlockId;
166
fallthrough: BlockId;
compiler/forget/src/HIR/HIRTreeVisitor.ts
+4
-1
@@ -16,6 +16,7 @@ import {
16
Instruction,
17
InstructionValue,
18
Place,
19
+ SourceLocation,
20
} from "./HIR";
21
22
/**
@@ -270,6 +271,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
271
blockValue,
272
this.visitor.visitTerminal({
273
kind: "while",
274
+ loc: terminal.loc,
275
test: testValue,
276
loop: loopBody,
277
}),
@@ -281,6 +283,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
283
blockValue,
284
this.visitor.visitTerminal({
285
kind: "while",
286
+ loc: terminal.loc,
287
test: testValue,
288
loop: loopBody,
289
})
@@ -679,6 +682,6 @@ export type BlockTerminal<TBlock, TValue, TItem, TCase> =
682
alternate: TItem | null;
683
}
684
| { kind: "switch"; test: TValue; cases: Array<TCase> }
682
- | { kind: "while"; test: TValue; loop: TItem }
685
+ | { kind: "while"; loc: SourceLocation; test: TValue; loop: TItem }
686
| { kind: "break"; label: string | null }
687
| { kind: "continue"; label: string | null };
compiler/forget/src/HIR/visitors.ts
+1
@@ -201,6 +201,7 @@ export function mapTerminalSuccessors(
201
const fallthrough = fn(terminal.fallthrough, true);
202
return {
203
kind: "while",
204
+ loc: terminal.loc,
205
test,
206
loop,
207
fallthrough,