fix: content inconsistencies in the vm

This commit is contained in:
Brett Broadhurst 2026-04-02 19:31:42 -06:00
parent 236acc7d60
commit ecd6017673
Failed to generate hash of commit
6 changed files with 259 additions and 115 deletions

View file

@ -857,7 +857,7 @@ fn inlineIfStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.
if (data.rhs) |rhs| {
// TODO: Revisit this. This isn't quite correct.
switch (rhs.tag) {
.content => _ = try content(&then_block, scope, rhs, false, false),
.content => _ = try content(&then_block, scope, rhs, false),
inline else => |tag| @panic("Unexpected node type: " ++ @tagName(tag)),
}
}
@ -1047,7 +1047,9 @@ fn switchStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.In
var case_block = gi.makeSubBlock();
defer case_block.unstack();
_ = try blockStmt(&case_block, scope, case_data.rhs.?);
if (case_data.rhs) |case_block_node| {
_ = try blockStmt(&case_block, scope, case_block_node);
}
if (!case_block.endsWithNoReturn()) {
_ = try case_block.addBreak(.@"break", case_stmt, switch_br, .void);
}
@ -1105,9 +1107,9 @@ fn content(
block: *GenIr,
scope: *Scope,
node: *const Ast.Node,
is_last: bool,
ignore_divert: bool,
) InnerError!void {
) InnerError!bool {
var suppress: bool = false;
const data = node.data.content;
if (data.leading_glue) {
_ = try block.addUnaryNode(.content_glue, .none);
@ -1122,33 +1124,43 @@ fn content(
const result = try inlineLogicExpr(block, scope, child_node);
_ = try block.addUnaryNode(.content_push, result);
},
.if_stmt => _ = try ifStmt(block, scope, child_node),
.multi_if_stmt => _ = try multiIfStmt(block, scope, child_node),
.switch_stmt => _ = try switchStmt(block, scope, child_node),
.if_stmt => _ = {
_ = try ifStmt(block, scope, child_node);
suppress = true;
},
.multi_if_stmt => {
_ = try multiIfStmt(block, scope, child_node);
suppress = true;
},
.switch_stmt => {
_ = try switchStmt(block, scope, child_node);
suppress = true;
},
.inline_if_stmt => _ = try inlineIfStmt(block, scope, child_node),
.divert_expr => _ = try divertExpr(block, scope, child_node),
else => unreachable,
}
}
if (is_last) {
_ = try block.addUnaryNode(.content_line, .none);
if (data.trailing_glue or data.trailing_divert != null) {
if (data.trailing_glue or data.trailing_divert != null) {
_ = try block.addUnaryNode(.content_glue, .none);
}
if (!ignore_divert) {
if (data.trailing_divert) |trailing| {
_ = try divertExpr(block, scope, trailing);
_ = try block.addUnaryNode(.content_glue, .none);
}
if (!ignore_divert) {
if (data.trailing_divert) |trailing| {
_ = try divertExpr(block, scope, trailing);
_ = try block.addUnaryNode(.content_glue, .none);
}
}
}
return suppress;
}
fn contentStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) !void {
const items = node.data.list.items;
for (items, 0..) |n, i| {
const is_last = i == items.len - 1;
try content(gi, scope, n, is_last, false);
var supress: bool = false;
const data = node.data.list;
for (data.items) |item_node| {
supress = try content(gi, scope, item_node, false);
}
if (!supress) {
_ = try gi.addUnaryNode(.content_line, .void);
}
}
@ -1186,11 +1198,11 @@ fn choiceStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void
defer block_1.unstack();
if (branch_expr.start_expr) |lhs| {
for (lhs) |n| {
if (n.data.content.trailing_divert) |trailing| {
for (lhs) |lhs_node| {
if (lhs_node.data.content.trailing_divert) |trailing| {
trailing_divert = trailing;
}
_ = try content(&block_1, scope, n, false, true);
_ = try content(&block_1, scope, lhs_node, true);
}
}
@ -1198,9 +1210,9 @@ fn choiceStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void
defer block_2.unstack();
if (branch_expr.option_expr) |mhs| {
for (mhs) |n| {
assert(n.data.content.trailing_divert == null);
_ = try content(&block_2, scope, n, false, true);
for (mhs) |mhs_node| {
assert(mhs_node.data.content.trailing_divert == null);
_ = try content(&block_2, scope, mhs_node, true);
}
}
@ -1208,11 +1220,11 @@ fn choiceStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void
defer block_3.unstack();
if (branch_expr.inner_expr) |rhs| {
for (rhs) |n| {
if (n.data.content.trailing_divert) |trailing| {
for (rhs) |rhs_node| {
if (rhs_node.data.content.trailing_divert) |trailing| {
trailing_divert = trailing;
}
_ = try content(&block_3, scope, n, false, true);
_ = try content(&block_3, scope, rhs_node, true);
}
}