Enforce terminal has a .loc (and .id)

This PR ensures (via a static assertion function) that all terminal variants 
have a SourceLocation, and adds locations to the variants which didn't have it 
before. This also adds a static assertion that terminals have an InstructionId, 
though we already relied on that so it was checked via usage.
This commit is contained in:
Joe Savona
2023-04-06 15:50:43 -07:00
parent 5622c0ee91
commit f51e2a6bf4
5 changed files with 84 additions and 17 deletions
+49 -15
View File
@@ -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
);
+29 -2
View File
@@ -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 = {
+1
View File
@@ -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,
};
}
}
+4
View File
@@ -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": {
@@ -135,6 +135,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
variant: GotoVariant.Break,
block: targetBlockId,
id: terminal.id,
loc: terminal.loc,
};
}
break;