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, gi: *GenIr,
scope: *Scope, scope: *Scope,
node: *const Ast.Node,
prototype_node: *const Ast.Node, prototype_node: *const Ast.Node,
body_node: ?*const Ast.Node, body_node: ?*const Ast.Node,
) InnerError!void { ) InnerError!KnotInfo {
const astgen = gi.astgen; const decl_name = try gi.astgen.strFromNode(prototype_node.data.bin.lhs.?);
const prototype_data = prototype_node.data.bin;
const identifier_node = prototype_data.lhs.?;
const decl_inst = try gi.addAsIndex(.{
.tag = .declaration,
.data = .{ .payload = undefined },
});
var decl_block = gi.makeSubBlock(); if (prototype_node.data.bin.rhs) |args_node| {
defer decl_block.unstack();
const stitch_inst = try decl_block.makePayloadNode(.decl_stitch);
if (prototype_data.rhs) |args_node| {
const args_data = args_node.data.list; const args_data = args_node.data.list;
for (args_data.items) |arg| { for (args_data.items) |arg| {
assert(arg.tag == .parameter_decl); assert(arg.tag == .parameter_decl);
const arg_str = try astgen.strFromNode(arg); const arg_str = try gi.astgen.strFromNode(arg);
const arg_inst = try decl_block.addStrTok(.param, arg_str.index, arg.loc.start); const arg_inst = try gi.addStrTok(.param, arg_str.index, arg.loc.start);
// TODO: Maybe make decl accept a ref? // TODO: Maybe make decl accept a ref?
try scope.insert(arg_str.index, .{ try scope.insert(arg_str.index, .{
@ -1549,101 +1541,72 @@ fn stitchDeclInner(
} }
} }
if (body_node) |body| { if (body_node) |body| {
const body_data = body.data.list; try blockStmt(gi, scope, body);
try blockInner(&decl_block, scope, body_data.items);
} else {
try blockInner(&decl_block, scope, &.{});
} }
if (!decl_block.endsWithNoReturn()) { if (!gi.endsWithNoReturn()) {
_ = try decl_block.addUnaryNode(.implicit_ret, .none); _ = 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 { fn stitchDecl(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
const knot_data = decl_node.data.bin; const data = node.data.bin;
const prototype_node = knot_data.lhs; const prototype_node = data.lhs.?;
const body_node = knot_data.rhs; const body_node = 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.?;
const decl_inst = try gi.addAsIndex(.{ const decl_inst = try gi.addAsIndex(.{
.tag = .declaration, .tag = .declaration,
.data = .{ .payload = undefined }, .data = .{ .payload = undefined },
}); });
var decl_block = gi.makeSubBlock(); var child_block = gi.makeSubBlock();
defer decl_block.unstack(); 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 knot_info = try prototypeAndBody(&child_block, &child_scope, prototype_node, body_node);
const args_data = args_node.data.list; const stitch_inst = try child_block.makePayloadNode(.decl_stitch);
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);
// TODO: Maybe make decl accept a ref? try setDeclStitchPayload(stitch_inst, &child_block);
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 setDeclaration(decl_inst, .{ try setDeclaration(decl_inst, .{
.name = decl_str.index, .name = knot_info.decl_name.index,
.value = stitch_inst, .value = stitch_inst,
.gi = gi, .gi = gi,
.node = node, .node = node,
}); });
} }
fn functionDecl(gi: *GenIr, parent_scope: *Scope, decl_node: *const Ast.Node) InnerError!void { fn functionDecl(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
const knot_data = decl_node.data.bin; const data = node.data.bin;
const prototype_node = knot_data.lhs; const prototype_node = data.lhs.?;
const body_node = knot_data.rhs; const body_node = data.rhs;
var decl_scope = parent_scope.makeChild(); const decl_inst = try gi.addAsIndex(.{
defer decl_scope.deinit(); .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 { fn knotDecl(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
const astgen = gi.astgen; const data = node.data.knot_decl;
const data = decl_node.data.knot_decl;
const prototype_node = data.prototype; const prototype_node = data.prototype;
const identifier_node = prototype_node.data.bin.lhs.?; const nested_nodes = data.children;
const decl_inst = try gi.addAsIndex(.{ const decl_inst = try gi.addAsIndex(.{
.tag = .declaration, .tag = .declaration,
.data = .{ .payload = undefined }, .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(); var child_block = gi.makeSubBlock();
defer child_block.unstack(); defer child_block.unstack();
const knot_inst = try gi.makePayloadNode(.decl_knot); var child_scope = scope.makeChild();
var child_scope = parent_scope.makeChild();
defer child_scope.deinit(); defer child_scope.deinit();
if (prototype_node.data.bin.rhs) |args_node| { const knot_inst = try gi.makePayloadNode(.decl_knot);
const args_data = args_node.data.list; const body_node: ?*const Ast.Node = blk: {
for (args_data.items) |arg| { if (nested_nodes.len > 0) {
assert(arg.tag == .parameter_decl); const first_child = nested_nodes[0];
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];
if (first_child.tag == .block_stmt) { if (first_child.tag == .block_stmt) {
try blockStmt(&child_block, &child_scope, first_child);
node_index += 1; node_index += 1;
break :blk first_child;
} }
} }
if (!child_block.endsWithNoReturn()) { break :blk null;
_ = try child_block.addUnaryNode(.implicit_ret, .none); };
} const knot_info = try prototypeAndBody(&child_block, &child_scope, prototype_node, body_node);
var nested_block = child_block.makeSubBlock(); var nested_block = child_block.makeSubBlock();
defer nested_block.unstack(); 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) { switch (nested_decl_node.tag) {
.stitch_decl => try stitchDecl(&nested_block, &child_scope, nested_decl_node), .stitch_decl => try stitchDecl(&nested_block, &child_scope, nested_decl_node),
.function_decl => try functionDecl(&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 setDeclKnotPayload(knot_inst, &child_block, &nested_block);
try setDeclaration(decl_inst, .{ try setDeclaration(decl_inst, .{
.name = name_str.index, .name = knot_info.decl_name.index,
.value = knot_inst, .value = knot_inst,
.gi = gi, .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 { fn testRunner(gpa: std.mem.Allocator, source_bytes: [:0]const u8, options: Options) !void {
const io_r = options.input_reader; const io_r = options.input_reader;
const io_w = options.transcript_writer; 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, .error_writer = options.error_writer,
}); });
defer story.deinit(); defer story.deinit();