[valueblocks] Disallow AssignmentExpression in value blocks (temporarily)

There's a bug with assignment expression in normal value blocks due to LeaveSSA. 
Until that's resolved i'm temporarily distinguishing "loop" blocks and "value" 
blocks, and disallowing assignment expressions in value blocks specifically.
This commit is contained in:
Joe Savona
2023-01-31 13:39:36 -08:00
parent 8c13c91f27
commit d6505572cb
7 changed files with 28 additions and 11 deletions
+15 -6
View File
@@ -247,11 +247,11 @@ function lowerStatement(
case "ForStatement": {
const stmt = stmtPath as NodePath<t.ForStatement>;
const testBlock = builder.reserve("value");
const testBlock = builder.reserve("loop");
// Block for code following the loop
const continuationBlock = builder.reserve("block");
const initBlock = builder.enter("value", (blockId) => {
const initBlock = builder.enter("loop", (blockId) => {
const init = stmt.get("init");
if (!init.isVariableDeclaration()) {
builder.errors.push({
@@ -271,7 +271,7 @@ function lowerStatement(
};
});
const updateBlock = builder.enter("value", (blockId) => {
const updateBlock = builder.enter("loop", (blockId) => {
const update = stmt.get("update");
if (update.node == null) {
builder.errors.push({
@@ -342,7 +342,7 @@ function lowerStatement(
case "WhileStatement": {
const stmt = stmtPath as NodePath<t.WhileStatement>;
// Block used to evaluate whether to (re)enter or exit the loop
const conditionalBlock = builder.reserve("value");
const conditionalBlock = builder.reserve("loop");
// Block for code following the loop
const continuationBlock = builder.reserve("block");
// Loop body
@@ -899,7 +899,7 @@ function lowerExpression(
const place = buildTemporaryPlace(builder, exprLoc);
// Block for the consequent (if the test is truthy)
const consequentBlock = builder.enter("block", (blockId) => {
const consequentBlock = builder.enter("value", (blockId) => {
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
@@ -914,7 +914,7 @@ function lowerExpression(
};
});
// Block for the alternate (if the test is not truthy)
const alternateBlock = builder.enter("block", (blockId) => {
const alternateBlock = builder.enter("value", (blockId) => {
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
@@ -1023,6 +1023,15 @@ function lowerExpression(
const expr = exprPath as NodePath<t.AssignmentExpression>;
const operator = expr.node.operator;
if (builder.currentBlockKind() === "value") {
builder.errors.push({
reason: `(BuildHIR::lowerExpression) Handle AssignmentExpression within a LogicalExpression or ConditionalExpression`,
severity: ErrorSeverity.Todo,
nodePath: expr,
});
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
}
if (operator === "=") {
const left = expr.get("left");
return lowerAssignment(
+1 -1
View File
@@ -223,7 +223,7 @@ export type HIR = {
* an exception occurs, therefore the block model only represents explicit throw
* statements and not implicit exceptions which may occur.
*/
export type BlockKind = "block" | "value";
export type BlockKind = "block" | "value" | "loop";
export type BasicBlock = {
kind: BlockKind;
id: BlockId;
@@ -21,7 +21,7 @@ import {
* (ie ends in a goto) and where the predecessor is the only predecessor
* for that successor (ie, there is no other way to reach the successor).
*
* Note that this pass leaves "value" blocks alone because they cannot
* Note that this pass leaves value/loop blocks alone because they cannot
* be merged without breaking the structure of the high-level terminals
* that reference them.
*
@@ -32,7 +32,7 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
for (const [, block] of fn.body.blocks) {
// Can only merge blocks with a single predecessor, can't merge
// value blocks
if (block.kind === "value" || block.preds.size !== 1) {
if (block.kind !== "block" || block.preds.size !== 1) {
continue;
}
const originalPredecessorId = Array.from(block.preds)[0]!;
@@ -104,7 +104,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
}
}
if (block.kind === "value") {
if (block.kind !== "block") {
// can't rewrite terminals in value blocks yet
continue;
}
@@ -1,4 +1,4 @@
// @only
// @skip
function ternary(props) {
let x = 0;
const y = props.a ? (x = 1) : (x = 2);
@@ -0,0 +1,8 @@
// @skip
function foo(props) {
let x = 0;
while (x > props.min && x < props.max) {
x *= 2;
}
return x;
}