diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 2b95d78685..e48a69a4ad 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -247,11 +247,11 @@ function lowerStatement( case "ForStatement": { const stmt = stmtPath as NodePath; - 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; // 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; 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( diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index debfca36d1..037c8934d4 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -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; diff --git a/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts b/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts index caadb23f39..19af293d69 100644 --- a/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts +++ b/compiler/forget/src/HIR/MergeConsecutiveBlocks.ts @@ -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]!; diff --git a/compiler/forget/src/Optimization/ConstantPropagation.ts b/compiler/forget/src/Optimization/ConstantPropagation.ts index 920421f1ba..139e9ebef3 100644 --- a/compiler/forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/forget/src/Optimization/ConstantPropagation.ts @@ -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; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ternary-assignment-expression.js b/compiler/forget/src/__tests__/fixtures/hir/ternary-assignment-expression.js index 654fa341fa..8149ac7839 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ternary-assignment-expression.js +++ b/compiler/forget/src/__tests__/fixtures/hir/ternary-assignment-expression.js @@ -1,4 +1,4 @@ -// @only +// @skip function ternary(props) { let x = 0; const y = props.a ? (x = 1) : (x = 2); diff --git a/compiler/forget/src/__tests__/fixtures/hir/ternary-assignment-expression.expect.md b/compiler/forget/src/__tests__/fixtures/hir/while-logical.expect.md similarity index 100% rename from compiler/forget/src/__tests__/fixtures/hir/ternary-assignment-expression.expect.md rename to compiler/forget/src/__tests__/fixtures/hir/while-logical.expect.md diff --git a/compiler/forget/src/__tests__/fixtures/hir/while-logical.js b/compiler/forget/src/__tests__/fixtures/hir/while-logical.js new file mode 100644 index 0000000000..0a1e6db8ce --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/while-logical.js @@ -0,0 +1,8 @@ +// @skip +function foo(props) { + let x = 0; + while (x > props.min && x < props.max) { + x *= 2; + } + return x; +}