@samitouri / QOS-React-2 / commits / d44082d63c

[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,