chore: remove duplicate code for knot-related ir generation functions

This commit is contained in:
Brett Broadhurst 2026-03-31 19:46:07 -06:00
parent d9f0a04417
commit 5c133e5fa2
Failed to generate hash of commit
2 changed files with 70 additions and 120 deletions

View file

@ -1514,32 +1514,24 @@ fn defaultBlock(
});
}
fn stitchDeclInner(
const KnotInfo = struct {
decl_name: IndexSlice,
};
fn prototypeAndBody(
gi: *GenIr,
scope: *Scope,
node: *const Ast.Node,
prototype_node: *const Ast.Node,
body_node: ?*const Ast.Node,
) InnerError!void {
const astgen = gi.astgen;
const prototype_data = prototype_node.data.bin;
const identifier_node = prototype_data.lhs.?;
const decl_inst = try gi.addAsIndex(.{
.tag = .declaration,
.data = .{ .payload = undefined },
});
) InnerError!KnotInfo {
const decl_name = try gi.astgen.strFromNode(prototype_node.data.bin.lhs.?);
var decl_block = gi.makeSubBlock();
defer decl_block.unstack();
const stitch_inst = try decl_block.makePayloadNode(.decl_stitch);
if (prototype_data.rhs) |args_node| {
if (prototype_node.data.bin.rhs) |args_node| {
const args_data = args_node.data.list;
for (args_data.items) |arg| {
assert(arg.tag == .parameter_decl);
const arg_str = try astgen.strFromNode(arg);
const arg_inst = try decl_block.addStrTok(.param, arg_str.index, arg.loc.start);
const arg_str = try gi.astgen.strFromNode(arg);
const arg_inst = try gi.addStrTok(.param, arg_str.index, arg.loc.start);
// TODO: Maybe make decl accept a ref?
try scope.insert(arg_str.index, .{
@ -1549,101 +1541,72 @@ fn stitchDeclInner(
}
}
if (body_node) |body| {
const body_data = body.data.list;
try blockInner(&decl_block, scope, body_data.items);
} else {
try blockInner(&decl_block, scope, &.{});
try blockStmt(gi, scope, body);
}
if (!decl_block.endsWithNoReturn()) {
_ = try decl_block.addUnaryNode(.implicit_ret, .none);
if (!gi.endsWithNoReturn()) {
_ = try gi.addUnaryNode(.implicit_ret, .none);
}
return .{ .decl_name = decl_name };
}
const decl_str = try astgen.strFromNode(identifier_node);
try setDeclStitchPayload(stitch_inst, &decl_block);
try setDeclaration(decl_inst, .{
.name = decl_str.index,
.value = stitch_inst,
.gi = gi,
.node = node,
});
}
fn stitchDecl(gi: *GenIr, parent_scope: *Scope, decl_node: *const Ast.Node) InnerError!void {
const knot_data = decl_node.data.bin;
const prototype_node = knot_data.lhs;
const body_node = knot_data.rhs;
var decl_scope = parent_scope.makeChild();
defer decl_scope.deinit();
return stitchDeclInner(gi, &decl_scope, decl_node, prototype_node.?, body_node);
}
fn functionDeclInner(
gi: *GenIr,
scope: *Scope,
node: *const Ast.Node,
prototype_node: *const Ast.Node,
body_node: ?*const Ast.Node,
) InnerError!void {
const astgen = gi.astgen;
const prototype_data = prototype_node.data.bin;
const identifier_node = prototype_data.lhs.?;
fn stitchDecl(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
const data = node.data.bin;
const prototype_node = data.lhs.?;
const body_node = data.rhs;
const decl_inst = try gi.addAsIndex(.{
.tag = .declaration,
.data = .{ .payload = undefined },
});
var decl_block = gi.makeSubBlock();
defer decl_block.unstack();
var child_block = gi.makeSubBlock();
defer child_block.unstack();
const stitch_inst = try decl_block.makePayloadNode(.decl_function);
var child_scope = scope.makeChild();
defer child_scope.deinit();
if (prototype_data.rhs) |args_node| {
const args_data = args_node.data.list;
for (args_data.items) |arg| {
assert(arg.tag == .parameter_decl);
const arg_str = try astgen.strFromNode(arg);
const arg_inst = try decl_block.addStrTok(.param, arg_str.index, arg.loc.start);
const knot_info = try prototypeAndBody(&child_block, &child_scope, prototype_node, body_node);
const stitch_inst = try child_block.makePayloadNode(.decl_stitch);
// TODO: Maybe make decl accept a ref?
try scope.insert(arg_str.index, .{
.decl_node = arg,
.inst_index = arg_inst.toIndex().?,
});
}
}
if (body_node) |body| {
try blockStmt(&decl_block, scope, body);
}
if (!decl_block.endsWithNoReturn()) {
_ = try decl_block.addUnaryNode(.implicit_ret, .none);
}
const decl_str = try astgen.strFromNode(identifier_node);
try setDeclStitchPayload(stitch_inst, &decl_block);
try setDeclStitchPayload(stitch_inst, &child_block);
try setDeclaration(decl_inst, .{
.name = decl_str.index,
.name = knot_info.decl_name.index,
.value = stitch_inst,
.gi = gi,
.node = node,
});
}
fn functionDecl(gi: *GenIr, parent_scope: *Scope, decl_node: *const Ast.Node) InnerError!void {
const knot_data = decl_node.data.bin;
const prototype_node = knot_data.lhs;
const body_node = knot_data.rhs;
var decl_scope = parent_scope.makeChild();
defer decl_scope.deinit();
fn functionDecl(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
const data = node.data.bin;
const prototype_node = data.lhs.?;
const body_node = data.rhs;
const decl_inst = try gi.addAsIndex(.{
.tag = .declaration,
.data = .{ .payload = undefined },
});
return functionDeclInner(gi, &decl_scope, decl_node, prototype_node.?, body_node);
var child_block = gi.makeSubBlock();
defer child_block.unstack();
var child_scope = scope.makeChild();
defer child_scope.deinit();
const knot_info = try prototypeAndBody(&child_block, &child_scope, prototype_node, body_node);
const stitch_inst = try child_block.makePayloadNode(.decl_function);
try setDeclStitchPayload(stitch_inst, &child_block);
try setDeclaration(decl_inst, .{
.name = knot_info.decl_name.index,
.value = stitch_inst,
.gi = gi,
.node = node,
});
}
fn knotDecl(gi: *GenIr, parent_scope: *Scope, decl_node: *const Ast.Node) InnerError!void {
const astgen = gi.astgen;
const data = decl_node.data.knot_decl;
fn knotDecl(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
const data = node.data.knot_decl;
const prototype_node = data.prototype;
const identifier_node = prototype_node.data.bin.lhs.?;
const nested_nodes = data.children;
const decl_inst = try gi.addAsIndex(.{
.tag = .declaration,
.data = .{ .payload = undefined },
@ -1653,39 +1616,26 @@ fn knotDecl(gi: *GenIr, parent_scope: *Scope, decl_node: *const Ast.Node) InnerE
var child_block = gi.makeSubBlock();
defer child_block.unstack();
const knot_inst = try gi.makePayloadNode(.decl_knot);
var child_scope = parent_scope.makeChild();
var child_scope = scope.makeChild();
defer child_scope.deinit();
if (prototype_node.data.bin.rhs) |args_node| {
const args_data = args_node.data.list;
for (args_data.items) |arg| {
assert(arg.tag == .parameter_decl);
const arg_str = try astgen.strFromNode(arg);
const arg_inst = try child_block.addStrTok(.param, arg_str.index, arg.loc.start);
// TODO: Maybe make decl accept a ref?
try child_scope.insert(arg_str.index, .{
.decl_node = arg,
.inst_index = arg_inst.toIndex().?,
});
}
}
if (data.children.len > 0) {
const first_child = data.children[0];
const knot_inst = try gi.makePayloadNode(.decl_knot);
const body_node: ?*const Ast.Node = blk: {
if (nested_nodes.len > 0) {
const first_child = nested_nodes[0];
if (first_child.tag == .block_stmt) {
try blockStmt(&child_block, &child_scope, first_child);
node_index += 1;
break :blk first_child;
}
}
if (!child_block.endsWithNoReturn()) {
_ = try child_block.addUnaryNode(.implicit_ret, .none);
}
break :blk null;
};
const knot_info = try prototypeAndBody(&child_block, &child_scope, prototype_node, body_node);
var nested_block = child_block.makeSubBlock();
defer nested_block.unstack();
for (data.children[node_index..]) |nested_decl_node| {
for (nested_nodes[node_index..]) |nested_decl_node| {
switch (nested_decl_node.tag) {
.stitch_decl => try stitchDecl(&nested_block, &child_scope, nested_decl_node),
.function_decl => try functionDecl(&nested_block, &child_scope, nested_decl_node),
@ -1693,13 +1643,12 @@ fn knotDecl(gi: *GenIr, parent_scope: *Scope, decl_node: *const Ast.Node) InnerE
}
}
const name_str = try gi.astgen.strFromNode(identifier_node);
try setDeclKnotPayload(knot_inst, &child_block, &nested_block);
try setDeclaration(decl_inst, .{
.name = name_str.index,
.name = knot_info.decl_name.index,
.value = knot_inst,
.gi = gi,
.node = decl_node,
.node = node,
});
}

View file

@ -217,7 +217,8 @@ const Options = struct {
fn testRunner(gpa: std.mem.Allocator, source_bytes: [:0]const u8, options: Options) !void {
const io_r = options.input_reader;
const io_w = options.transcript_writer;
var story = try ink.Story.loadFromString(gpa, source_bytes, .{
var story = try ink.Story.fromSourceBytes(gpa, source_bytes, .{
.filename = "<STDIN>",
.error_writer = options.error_writer,
});
defer story.deinit();