diff --git a/src/AstGen.zig b/src/AstGen.zig index c3199e9..5895b65 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -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); } - - 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, - }); + return .{ .decl_name = decl_name }; } -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().?, - }); + 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) { + node_index += 1; + break :blk first_child; + } } - } - if (data.children.len > 0) { - const first_child = data.children[0]; - if (first_child.tag == .block_stmt) { - try blockStmt(&child_block, &child_scope, first_child); - node_index += 1; - } - } - 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, }); } diff --git a/src/Story/runtime_tests.zig b/src/Story/runtime_tests.zig index 9084585..99af845 100644 --- a/src/Story/runtime_tests.zig +++ b/src/Story/runtime_tests.zig @@ -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 = "", .error_writer = options.error_writer, }); defer story.deinit();