diff --git a/src/compile.zig b/src/compile.zig index ea70b73..e57d975 100644 --- a/src/compile.zig +++ b/src/compile.zig @@ -184,7 +184,7 @@ pub const Module = struct { }; pub const Stitch = struct { - knot_index: Knot.Index, + knot_index: ?Knot.Index, code_index: CodeChunk.Index, name_index: InternPool.Constant.Index, @@ -252,6 +252,7 @@ pub const Module = struct { } while (mod.work_queue.pop()) |work_unit| { const chunk_index = mod.intern_pool.code_chunks.items.len; + var knot_index: ?Knot.Index = null; var chunk: Sema.Chunk = .{ .sema = &sema, .code = try mod.createCodeChunk(), @@ -266,6 +267,7 @@ pub const Module = struct { try sema.analyzeKnot(&chunk, work_unit.inst_index); try chunk.finalize(); + knot_index = @enumFromInt(mod.knots.items.len); try mod.intern_pool.code_chunks.append(gpa, chunk.code); try mod.knots.append(gpa, .{ .name_index = work_unit.decl_name, @@ -273,13 +275,12 @@ pub const Module = struct { }); }, .stitch => { - const knot_index = mod.knots.items.len - 1; try sema.analyzeStitch(&chunk, work_unit.inst_index); try chunk.finalize(); try mod.intern_pool.code_chunks.append(gpa, chunk.code); try mod.stitches.append(gpa, .{ - .knot_index = @enumFromInt(knot_index), + .knot_index = knot_index, .name_index = work_unit.decl_name, .code_index = @enumFromInt(chunk_index), }); @@ -406,11 +407,12 @@ pub const Module = struct { .code_bytes = try code_chunk.bytecode.toOwnedSlice(gpa), }), }); - - const parent_knot = mod.knots.items[@intFromEnum(stitch.knot_index)]; - const parent_knot_name = mod.intern_pool.getStrBytes(mod.ir, parent_knot.name_index); - const parent_knot_obj: *Object.Knot = @ptrCast(story.globals.get(parent_knot_name).?); - try parent_knot_obj.members.put(story.allocator, name_bytes, &stitch_obj.base); + if (stitch.knot_index) |index| { + const parent_knot = mod.knots.items[@intFromEnum(index)]; + const parent_knot_name = mod.intern_pool.getStrBytes(mod.ir, parent_knot.name_index); + const parent_knot_obj: *Object.Knot = @ptrCast(story.globals.get(parent_knot_name).?); + try parent_knot_obj.members.put(story.allocator, name_bytes, &stitch_obj.base); + } } story.string_bytes = mod.ir.string_bytes; mod.ir.string_bytes = &.{}; diff --git a/src/parser_tests.zig b/src/parser_tests.zig index aeecf45..40c209a 100644 --- a/src/parser_tests.zig +++ b/src/parser_tests.zig @@ -225,6 +225,46 @@ test "parser: empty knot declarations" { ); } +test "parser: stitch declarations, inside knot" { + try testEqual( + \\=== knot === + \\= stitch + \\Hello, world! + , + \\File "" + \\`--KnotDecl + \\ |--KnotProto + \\ | `--Identifier `knot` + \\ `--StitchDecl + \\ |--StitchProto + \\ | `--Identifier `stitch` + \\ `--BlockStmt + \\ `--ContentStmt + \\ `--Content + \\ `--StringLiteral `Hello, world!` + \\ + , + ); +} + +test "parser: stitch declarations, simple" { + try testEqual( + \\= stitch + \\Hello, world! + , + \\File "" + \\`--StitchDecl + \\ |--StitchProto + \\ | `--Identifier `stitch` + \\ `--BlockStmt + \\ `--ContentStmt + \\ `--Content + \\ `--StringLiteral `Hello, world!` + \\ + , + ); +} + fn testEqual(source_bytes: [:0]const u8, expected_ast: []const u8) !void { const gpa = std.testing.allocator; var arena_allocator = std.heap.ArenaAllocator.init(gpa); diff --git a/testing/regression/syntax/nested-stitch.ink b/testing/regression/syntax/nested-stitch.ink deleted file mode 100644 index d57f3ec..0000000 --- a/testing/regression/syntax/nested-stitch.ink +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %ink-compiler --stdin --compile-only --dump-ast < %s | FileCheck %s - -// CHECK: File "" -// CHECK-NEXT: `--KnotDecl -// CHECK-NEXT: |--KnotProto -// CHECK-NEXT: | `--Identifier `knot` -// CHECK-NEXT: `--StitchDecl -// CHECK-NEXT: |--StitchProto -// CHECK-NEXT: | `--Identifier `stitch` -// CHECK-NEXT: `--BlockStmt -// CHECK-NEXT: `--ContentStmt -// CHECK-NEXT: `--Content -// CHECK-NEXT: `--StringLiteral `Hello, world!` - -=== knot === -= stitch -Hello, world! diff --git a/testing/regression/syntax/simple-stitch.ink b/testing/regression/syntax/simple-stitch.ink deleted file mode 100644 index 099844f..0000000 --- a/testing/regression/syntax/simple-stitch.ink +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: %ink-compiler --stdin --compile-only --dump-ast < %s | FileCheck %s - -// CHECK: File "" -// CHECK-NEXT: `--StitchDecl -// CHECK-NEXT: |--StitchProto -// CHECK-NEXT: | `--Identifier `stitch` -// CHECK-NEXT: `--BlockStmt -// CHECK-NEXT: `--ContentStmt -// CHECK-NEXT: `--Content -// CHECK-NEXT: `--StringLiteral `Hello, world!` - -= stitch -Hello, world!