feat: runtime content processing, supporting glue

This commit is contained in:
Brett Broadhurst 2026-03-30 16:47:05 -06:00
parent d325cdf965
commit f5eac49729
Failed to generate hash of commit
12 changed files with 387 additions and 286 deletions

View file

@ -285,6 +285,13 @@ const GenIr = struct {
return last_inst.isNoReturn();
}
fn endsWithContent(self: *GenIr) bool {
if (self.isEmpty()) return false;
const last_inst_index = self.instructions.items[self.instructions.items.len - 1];
const last_inst = self.astgen.instructions.items[@intFromEnum(last_inst_index)];
return last_inst.tag == .content_push;
}
fn makeSubBlock(self: *GenIr) GenIr {
return .{
.astgen = self.astgen,
@ -807,7 +814,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 contentExpr(&then_block, scope, rhs),
.content => _ = try content(&then_block, scope, rhs),
inline else => |tag| @panic("Unexpected node type: " ++ @tagName(tag)),
}
}
@ -1051,8 +1058,11 @@ fn switchStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.In
return switch_br.toRef();
}
fn contentExpr(block: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
fn content(block: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
const data = node.data.content;
if (data.leading_glue) {
_ = try block.addUnaryNode(.content_glue, .none);
}
for (data.items) |child_node| {
switch (child_node.tag) {
.string_literal => {
@ -1070,13 +1080,17 @@ fn contentExpr(block: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!I
else => unreachable,
}
}
if (data.trailing_glue) {
_ = try block.addUnaryNode(.content_glue, .none);
} else if (block.endsWithContent()) {
_ = try block.addUnaryNode(.content_line, .none);
}
return .none;
}
fn contentStmt(gen: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
const expr_node = node.data.bin.lhs.?;
const expr_ref = try contentExpr(gen, scope, expr_node);
return gen.addUnaryNode(.content_flush, expr_ref);
fn contentStmt(block: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
const data = node.data.bin;
_ = try content(block, scope, data.lhs.?);
}
fn assignStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
@ -1133,6 +1147,9 @@ fn choiceStmt(
if (branch_data.rhs) |branch_body| {
_ = try blockStmt(&sub_block, scope, branch_body);
}
if (!sub_block.endsWithNoReturn()) {
_ = try sub_block.addUnaryNode(.implicit_ret, .none);
}
const body = sub_block.instructionsSlice();
const case_extra_len = @typeInfo(Ir.Inst.SwitchBr.Case).@"struct".fields.len + body.len;