From 11d99fba383ce934a27395a6a72667757f4b4b72 Mon Sep 17 00:00:00 2001 From: Brett Broadhurst Date: Sun, 29 Mar 2026 06:21:53 -0600 Subject: [PATCH] fix: content behavior bugs --- src/AstGen.zig | 31 ++++++- src/Ir.zig | 2 + src/Sema.zig | 37 ++++++-- src/Story.zig | 18 +++- src/Story/Dumper.zig | 1 + src/Story/runtime_tests.zig | 91 ++++++++++++++++--- .../testdata/{hello-world => I001}/input.txt | 0 .../testdata/{hello-world => I001}/story.ink | 0 .../{hello-world => I001}/transcript.txt | 0 .../{monsieur-fogg => I002}/input.txt | 0 .../{monsieur-fogg => I002}/story.ink | 0 .../{monsieur-fogg => I002}/transcript.txt | 0 src/Story/testdata/I005/input.txt | 0 src/Story/testdata/I005/story.ink | 3 + src/Story/testdata/I005/transcript.txt | 1 + src/Story/testdata/I007/input.txt | 0 src/Story/testdata/I007/story.ink | 2 + src/Story/testdata/I007/transcript.txt | 1 + src/Story/testdata/I011/input.txt | 0 src/Story/testdata/I011/story.ink | 3 + src/Story/testdata/I011/transcript.txt | 1 + src/Story/testdata/I012/input.txt | 0 src/Story/testdata/I012/story.ink | 5 + src/Story/testdata/I012/transcript.txt | 1 + src/Story/testdata/I016/input.txt | 0 src/Story/testdata/I016/story.ink | 0 src/Story/testdata/I016/transcript.txt | 0 src/Story/testdata/I017/input.txt | 0 src/Story/testdata/I017/story.ink | 4 + src/Story/testdata/I017/transcript.txt | 1 + src/Story/testdata/I018/input.txt | 0 src/Story/testdata/I018/story.ink | 6 ++ src/Story/testdata/I018/transcript.txt | 1 + src/Story/testdata/I019/input.txt | 0 src/Story/testdata/I019/story.ink | 3 + src/Story/testdata/I019/transcript.txt | 0 src/Story/testdata/I021/input.txt | 0 src/Story/testdata/I021/story.ink | 7 ++ src/Story/testdata/I021/transcript.txt | 2 + src/Story/testdata/I023/input.txt | 0 src/Story/testdata/I023/story.ink | 7 ++ src/Story/testdata/I023/transcript.txt | 2 + src/Story/testdata/I035/input.txt | 1 + src/Story/testdata/I035/story.ink | 5 + src/Story/testdata/I035/transcript.txt | 3 + src/Story/testdata/I042/input.txt | 2 + src/Story/testdata/I042/story.ink | 4 + src/Story/testdata/I042/transcript.txt | 2 + src/Story/testdata/I051/input.txt | 0 src/Story/testdata/I051/story.ink | 3 + src/Story/testdata/I051/transcript.txt | 1 + src/Story/testdata/I064/input.txt | 0 src/Story/testdata/I064/story.ink | 2 + src/Story/testdata/I064/transcript.txt | 0 src/Story/testdata/I078/input.txt | 1 + src/Story/testdata/I078/story.ink | 2 + src/Story/testdata/I078/transcript.txt | 2 + src/compile.zig | 14 ++- src/print_ir.zig | 2 + 59 files changed, 243 insertions(+), 31 deletions(-) rename src/Story/testdata/{hello-world => I001}/input.txt (100%) rename src/Story/testdata/{hello-world => I001}/story.ink (100%) rename src/Story/testdata/{hello-world => I001}/transcript.txt (100%) rename src/Story/testdata/{monsieur-fogg => I002}/input.txt (100%) rename src/Story/testdata/{monsieur-fogg => I002}/story.ink (100%) rename src/Story/testdata/{monsieur-fogg => I002}/transcript.txt (100%) create mode 100644 src/Story/testdata/I005/input.txt create mode 100644 src/Story/testdata/I005/story.ink create mode 100644 src/Story/testdata/I005/transcript.txt create mode 100644 src/Story/testdata/I007/input.txt create mode 100644 src/Story/testdata/I007/story.ink create mode 100644 src/Story/testdata/I007/transcript.txt create mode 100644 src/Story/testdata/I011/input.txt create mode 100644 src/Story/testdata/I011/story.ink create mode 100644 src/Story/testdata/I011/transcript.txt create mode 100644 src/Story/testdata/I012/input.txt create mode 100644 src/Story/testdata/I012/story.ink create mode 100644 src/Story/testdata/I012/transcript.txt create mode 100644 src/Story/testdata/I016/input.txt create mode 100644 src/Story/testdata/I016/story.ink create mode 100644 src/Story/testdata/I016/transcript.txt create mode 100644 src/Story/testdata/I017/input.txt create mode 100644 src/Story/testdata/I017/story.ink create mode 100644 src/Story/testdata/I017/transcript.txt create mode 100644 src/Story/testdata/I018/input.txt create mode 100644 src/Story/testdata/I018/story.ink create mode 100644 src/Story/testdata/I018/transcript.txt create mode 100644 src/Story/testdata/I019/input.txt create mode 100644 src/Story/testdata/I019/story.ink create mode 100644 src/Story/testdata/I019/transcript.txt create mode 100644 src/Story/testdata/I021/input.txt create mode 100644 src/Story/testdata/I021/story.ink create mode 100644 src/Story/testdata/I021/transcript.txt create mode 100644 src/Story/testdata/I023/input.txt create mode 100644 src/Story/testdata/I023/story.ink create mode 100644 src/Story/testdata/I023/transcript.txt create mode 100644 src/Story/testdata/I035/input.txt create mode 100644 src/Story/testdata/I035/story.ink create mode 100644 src/Story/testdata/I035/transcript.txt create mode 100644 src/Story/testdata/I042/input.txt create mode 100644 src/Story/testdata/I042/story.ink create mode 100644 src/Story/testdata/I042/transcript.txt create mode 100644 src/Story/testdata/I051/input.txt create mode 100644 src/Story/testdata/I051/story.ink create mode 100644 src/Story/testdata/I051/transcript.txt create mode 100644 src/Story/testdata/I064/input.txt create mode 100644 src/Story/testdata/I064/story.ink create mode 100644 src/Story/testdata/I064/transcript.txt create mode 100644 src/Story/testdata/I078/input.txt create mode 100644 src/Story/testdata/I078/story.ink create mode 100644 src/Story/testdata/I078/transcript.txt diff --git a/src/AstGen.zig b/src/AstGen.zig index a3bbdea..1860258 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1224,7 +1224,34 @@ fn divertExpr(gi: *GenIr, scope: *Scope, node: *const Ast.Node) !void { // FIXME: Oh God, the AST is completely fucked for this. const lhs = node.data.bin.lhs.?; switch (lhs.tag) { - .identifier, .selector_expr => { + .identifier => { + // TODO: Revisit this + const str_slice = gi.astgen.tree.nodeSlice(lhs); + if (std.mem.eql(u8, str_slice, "DONE")) { + _ = try gi.addUnaryNode(.done, .none); + return; + } else if (std.mem.eql(u8, str_slice, "END")) { + _ = try gi.addUnaryNode(.exit, .none); + return; + } + const callee = try calleeExpr(gi, scope, lhs); + switch (callee) { + .direct => |callee_obj| { + _ = try gi.addPayloadNode(.divert, lhs, Ir.Inst.Call{ + .callee = callee_obj, + .args_len = 0, + }); + }, + .field => |callee_field| { + _ = try gi.addPayloadNode(.field_divert, lhs, Ir.Inst.FieldCall{ + .obj_ptr = callee_field.obj_ptr, + .field_name_start = callee_field.field_name_start, + .args_len = 0, + }); + }, + } + }, + .selector_expr => { const callee = try calleeExpr(gi, scope, lhs); switch (callee) { .direct => |callee_obj| { @@ -1310,7 +1337,7 @@ fn blockInner(gi: *GenIr, parent_scope: *Scope, stmt_list: []*Ast.Node) !void { .choice_stmt => try choiceStmt(gi, &child_scope, inner_node), .expr_stmt => try exprStmt(gi, &child_scope, inner_node), .divert_stmt => try divertStmt(gi, &child_scope, inner_node), - else => unreachable, + inline else => |e| @panic("Unexpected node: " ++ @tagName(e)), }; } _ = try gi.addUnaryNode(.implicit_ret, .none); diff --git a/src/Ir.zig b/src/Ir.zig index c01364a..c6d96e6 100644 --- a/src/Ir.zig +++ b/src/Ir.zig @@ -206,6 +206,8 @@ pub const Inst = struct { field_call, field_divert, param, + done, + exit, }; pub const Data = union { diff --git a/src/Sema.zig b/src/Sema.zig index 5402480..9096488 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -24,6 +24,7 @@ const InnerError = error{ pub const ValueInfo = union(enum) { none, + stack, value: InternPool.Index, variable: InternPool.Index, knot: InternPool.Index, @@ -288,6 +289,7 @@ pub const Builder = struct { fn ensureLoad(self: *Builder, info: ValueInfo) InnerError!void { switch (info) { .none => unreachable, // caller should never load .none + .stack => {}, .value => |index| { const local_index = try self.getOrPutConstantIndex(index); try self.addConstOp(.load_const, @intCast(local_index)); @@ -451,7 +453,7 @@ fn irUnaryOp( try builder.ensureLoad(lhs); try builder.addByteOp(op); - return .none; + return .stack; } fn irBinaryOp( @@ -485,7 +487,7 @@ fn irBinaryOp( try builder.ensureLoad(lhs); try builder.ensureLoad(rhs); try builder.addByteOp(op); - return .none; + return .stack; } fn irLogicalOp( @@ -567,8 +569,16 @@ fn irStore(sema: *Sema, builder: *Builder, inst: Ir.Inst.Index) InnerError!void try builder.ensureLoad(rhs); switch (lhs) { + .none => unreachable, + .stack => {}, .value => |_| return sema.fail(src, "could not assign to constant value", .{}), - else => unreachable, + .variable => |index| { + const local_index = try builder.getOrPutConstantIndex(index); + try builder.addConstOp(.store_global, @intCast(local_index)); + }, + .temp => |temp| try builder.addConstOp(.store, @intCast(temp)), + .stitch => |_| return sema.fail(src, "could not assign to stitch", .{}), + .knot => |_| return sema.fail(src, "could not assign to knot", .{}), } try builder.addByteOp(.pop); @@ -577,8 +587,10 @@ fn irStore(sema: *Sema, builder: *Builder, inst: Ir.Inst.Index) InnerError!void fn irLoad(sema: *Sema, builder: *Builder, inst: Ir.Inst.Index) InnerError!ValueInfo { const data = sema.ir.instructions[@intFromEnum(inst)].data.un; const lhs = sema.resolveInst(data.lhs); + if (lhs == .value) return lhs; + try builder.ensureLoad(lhs); - return .none; + return .stack; } fn irCondBr(sema: *Sema, builder: *Builder, inst: Ir.Inst.Index) InnerError!ValueInfo { @@ -670,9 +682,8 @@ fn irSwitchBr(sema: *Sema, builder: *Builder, inst: Ir.Inst.Index) InnerError!vo fn irContentPush(sema: *Sema, builder: *Builder, inst: Ir.Inst.Index) InnerError!void { const data = sema.ir.instructions[@intFromEnum(inst)].data.un; const lhs = sema.resolveInst(data.lhs); - if (lhs != .none) { - try builder.ensureLoad(lhs); - } + if (lhs == .none) return error.AnalysisFail; + if (lhs != .stack) try builder.ensureLoad(lhs); try builder.addByteOp(.stream_push); } @@ -820,6 +831,16 @@ fn irParam(_: *Sema, builder: *Builder, _: Ir.Inst.Index) !ValueInfo { return .{ .temp = builder.addParameter() }; } +fn irDone(_: *Sema, builder: *Builder, _: Ir.Inst.Index) !ValueInfo { + try builder.addByteOp(.done); + return .none; +} + +fn irExit(_: *Sema, builder: *Builder, _: Ir.Inst.Index) !ValueInfo { + try builder.addByteOp(.exit); + return .none; +} + fn analyzeArithmeticArg( sema: *Sema, builder: *Builder, @@ -939,6 +960,8 @@ fn analyzeBodyInner( }, .field_ptr => try irFieldPtr(sema, builder, inst), .param => try irParam(sema, builder, inst), + .done => try irDone(sema, builder, inst), + .exit => try irExit(sema, builder, inst), }; try sema.inst_map.put(sema.gpa, inst, result); } diff --git a/src/Story.zig b/src/Story.zig index a943717..d78bbff 100644 --- a/src/Story.zig +++ b/src/Story.zig @@ -235,6 +235,7 @@ pub const Choice = struct { pub const Opcode = enum(u8) { /// Exit the VM normally. exit, + done, ret, /// Pop a value off the stack, discarding it. pop, @@ -395,9 +396,8 @@ fn setGlobal(vm: *Story, key: Value, value: Value) !void { fn execute(vm: *Story) !std.ArrayListUnmanaged(u8) { const gpa = vm.allocator; - errdefer { - vm.can_advance = false; - } + errdefer vm.can_advance = false; + if (vm.isCallStackEmpty()) return .empty; var stream_writer = std.Io.Writer.Allocating.init(gpa); @@ -415,6 +415,10 @@ fn execute(vm: *Story) !std.ArrayListUnmanaged(u8) { vm.can_advance = false; return .empty; }, + .done => { + vm.can_advance = false; + return .empty; + }, .true => { const value: Value = .{ .bool = true }; try vm.pushStack(value); @@ -588,7 +592,6 @@ fn execute(vm: *Story) !std.ArrayListUnmanaged(u8) { frame.ip += 3; }, .br_table => { - // No-op currently. frame.ip += 1; }, .br_select_index => { @@ -599,7 +602,12 @@ fn execute(vm: *Story) !std.ArrayListUnmanaged(u8) { .br_dispatch => { const index = vm.choice_index; const branch_dispatch = vm.current_choices.items[index]; - defer vm.current_choices.clearRetainingCapacity(); + defer { + for (vm.current_choices.items) |*choice| { + choice.text.deinit(gpa); + } + vm.current_choices.clearRetainingCapacity(); + } frame.ip = branch_dispatch.dest_offset; }, diff --git a/src/Story/Dumper.zig b/src/Story/Dumper.zig index 1989dfb..da42c9f 100644 --- a/src/Story/Dumper.zig +++ b/src/Story/Dumper.zig @@ -129,6 +129,7 @@ pub fn dumpInst( } switch (op) { .exit => return self.dumpSimpleInst(w, offset, op), + .done => return self.dumpSimpleInst(w, offset, op), .ret => return self.dumpSimpleInst(w, offset, op), .pop => return self.dumpSimpleInst(w, offset, op), .true => return self.dumpSimpleInst(w, offset, op), diff --git a/src/Story/runtime_tests.zig b/src/Story/runtime_tests.zig index 4db4af9..cf9dd0c 100644 --- a/src/Story/runtime_tests.zig +++ b/src/Story/runtime_tests.zig @@ -2,14 +2,6 @@ const std = @import("std"); const fatal = std.process.fatal; const ink = @import("../root.zig"); -test "fixture - hello world" { - try testRuntimeFixture("hello-world"); -} - -test "fixture - monsieur-fogg" { - try testRuntimeFixture("monsieur-fogg"); -} - test "fixture - variable arithmetic" { try testRuntimeFixture("variable-arithmetic"); } @@ -18,6 +10,75 @@ test "fixture - constant folding" { try testRuntimeFixture("constant-folding"); } +test "fixture - I001 (Minimal story)" { + try testRuntimeFixture("I001"); +} + +test "fixture - I002 (Fogg comforts Passepartout)" { + try testRuntimeFixture("I002"); +} + +test "fixture - I005 (Const variable)" { + try testRuntimeFixture("I005"); +} + +test "fixture - I007 (Set non existant variable)" { + try testRuntimeFixture("I007"); +} + +test "fixture - I011 (Temporaries at global scope)" { + try testRuntimeFixture("I011"); +} + +// TODO: This needs gather points. +//test "fixture - I012 (Variable declaration in conditional)" { +// try testRuntimeFixture("I012"); +//} + +test "fixture - I016 (Empty)" { + try testRuntimeFixture("I016"); +} + +test "fixture - I017 (End)" { + try testRuntimeFixture("I017"); +} + +test "fixture - I018 (End, the return of the end)" { + try testRuntimeFixture("I018"); +} + +test "fixture - I019 (End of content)" { + try testRuntimeFixture("I019"); +} + +test "fixture - I021 (Identifiers can start with numbers)" { + try testRuntimeFixture("I021"); +} + +test "fixture - I023 (Whitespace)" { + try testRuntimeFixture("I023"); +} + +test "fixture - I035 (Newline consistency, the third)" { + try testRuntimeFixture("I035"); +} + +test "fixture - I042 (Weave options)" { + try testRuntimeFixture("I042"); +} + +test "fixture - I051 (String constants)" { + try testRuntimeFixture("I051"); +} + +test "fixture - I064 (Done stops thread)" { + try testRuntimeFixture("I064"); +} + +test "fixture - I078 (Choice with brackets only)" { + try testRuntimeFixture("I078"); +} + test "fixture - I118 (Literal unary)" { try testRuntimeFixture("I118"); } @@ -62,16 +123,20 @@ fn testRunner(gpa: std.mem.Allocator, source_bytes: [:0]const u8, options: Optio } if (story.current_choices.items.len > 0) { for (story.current_choices.items, 0..) |*choice, index| { - const choice_text = try choice.text.toOwnedSlice(gpa); - defer gpa.free(choice_text); - try io_w.print("{d}: {s}\n", .{ index + 1, choice_text }); + try io_w.print("{d}: {s}\n", .{ index + 1, choice.text.items }); } try io_w.print("?> ", .{}); const input_line = try io_r.takeDelimiter('\n'); if (input_line) |bytes| { - const choice_index = try std.fmt.parseUnsigned(usize, bytes, 10); - try story.selectChoiceIndex(if (choice_index == 0) 0 else choice_index - 1); + const parsed_choice_index = try std.fmt.parseUnsigned(usize, bytes, 10); + const choice_index = if (parsed_choice_index == 0) 0 else parsed_choice_index - 1; + // TODO: Seems like Ink proof wants to check the option text, not the actually + // rendered text. + //const result_text = story.current_choices.items[choice_index]; + //try io_w.print("{s}\n", .{result_text.text.items}); + + try story.selectChoiceIndex(choice_index); } } } diff --git a/src/Story/testdata/hello-world/input.txt b/src/Story/testdata/I001/input.txt similarity index 100% rename from src/Story/testdata/hello-world/input.txt rename to src/Story/testdata/I001/input.txt diff --git a/src/Story/testdata/hello-world/story.ink b/src/Story/testdata/I001/story.ink similarity index 100% rename from src/Story/testdata/hello-world/story.ink rename to src/Story/testdata/I001/story.ink diff --git a/src/Story/testdata/hello-world/transcript.txt b/src/Story/testdata/I001/transcript.txt similarity index 100% rename from src/Story/testdata/hello-world/transcript.txt rename to src/Story/testdata/I001/transcript.txt diff --git a/src/Story/testdata/monsieur-fogg/input.txt b/src/Story/testdata/I002/input.txt similarity index 100% rename from src/Story/testdata/monsieur-fogg/input.txt rename to src/Story/testdata/I002/input.txt diff --git a/src/Story/testdata/monsieur-fogg/story.ink b/src/Story/testdata/I002/story.ink similarity index 100% rename from src/Story/testdata/monsieur-fogg/story.ink rename to src/Story/testdata/I002/story.ink diff --git a/src/Story/testdata/monsieur-fogg/transcript.txt b/src/Story/testdata/I002/transcript.txt similarity index 100% rename from src/Story/testdata/monsieur-fogg/transcript.txt rename to src/Story/testdata/I002/transcript.txt diff --git a/src/Story/testdata/I005/input.txt b/src/Story/testdata/I005/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I005/story.ink b/src/Story/testdata/I005/story.ink new file mode 100644 index 0000000..5b8a3c4 --- /dev/null +++ b/src/Story/testdata/I005/story.ink @@ -0,0 +1,3 @@ +VAR x = c +CONST c = 5 +{x} diff --git a/src/Story/testdata/I005/transcript.txt b/src/Story/testdata/I005/transcript.txt new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/src/Story/testdata/I005/transcript.txt @@ -0,0 +1 @@ +5 diff --git a/src/Story/testdata/I007/input.txt b/src/Story/testdata/I007/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I007/story.ink b/src/Story/testdata/I007/story.ink new file mode 100644 index 0000000..759a9d1 --- /dev/null +++ b/src/Story/testdata/I007/story.ink @@ -0,0 +1,2 @@ +VAR x = "world" +Hello {x}. diff --git a/src/Story/testdata/I007/transcript.txt b/src/Story/testdata/I007/transcript.txt new file mode 100644 index 0000000..18249f3 --- /dev/null +++ b/src/Story/testdata/I007/transcript.txt @@ -0,0 +1 @@ +Hello world. diff --git a/src/Story/testdata/I011/input.txt b/src/Story/testdata/I011/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I011/story.ink b/src/Story/testdata/I011/story.ink new file mode 100644 index 0000000..4eca90c --- /dev/null +++ b/src/Story/testdata/I011/story.ink @@ -0,0 +1,3 @@ +VAR x = 5 +~ temp y = 4 +{x}{y} diff --git a/src/Story/testdata/I011/transcript.txt b/src/Story/testdata/I011/transcript.txt new file mode 100644 index 0000000..fb1e7bc --- /dev/null +++ b/src/Story/testdata/I011/transcript.txt @@ -0,0 +1 @@ +54 diff --git a/src/Story/testdata/I012/input.txt b/src/Story/testdata/I012/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I012/story.ink b/src/Story/testdata/I012/story.ink new file mode 100644 index 0000000..6f7efe6 --- /dev/null +++ b/src/Story/testdata/I012/story.ink @@ -0,0 +1,5 @@ +VAR x = 0 +{true: + - ~ x = 5 +} +{x} diff --git a/src/Story/testdata/I012/transcript.txt b/src/Story/testdata/I012/transcript.txt new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/src/Story/testdata/I012/transcript.txt @@ -0,0 +1 @@ +5 diff --git a/src/Story/testdata/I016/input.txt b/src/Story/testdata/I016/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I016/story.ink b/src/Story/testdata/I016/story.ink new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I016/transcript.txt b/src/Story/testdata/I016/transcript.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I017/input.txt b/src/Story/testdata/I017/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I017/story.ink b/src/Story/testdata/I017/story.ink new file mode 100644 index 0000000..2917980 --- /dev/null +++ b/src/Story/testdata/I017/story.ink @@ -0,0 +1,4 @@ +hello +-> END +world +-> END diff --git a/src/Story/testdata/I017/transcript.txt b/src/Story/testdata/I017/transcript.txt new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/src/Story/testdata/I017/transcript.txt @@ -0,0 +1 @@ +hello diff --git a/src/Story/testdata/I018/input.txt b/src/Story/testdata/I018/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I018/story.ink b/src/Story/testdata/I018/story.ink new file mode 100644 index 0000000..6922a8c --- /dev/null +++ b/src/Story/testdata/I018/story.ink @@ -0,0 +1,6 @@ +-> test +== test == +hello +-> END +world +-> END diff --git a/src/Story/testdata/I018/transcript.txt b/src/Story/testdata/I018/transcript.txt new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/src/Story/testdata/I018/transcript.txt @@ -0,0 +1 @@ +hello diff --git a/src/Story/testdata/I019/input.txt b/src/Story/testdata/I019/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I019/story.ink b/src/Story/testdata/I019/story.ink new file mode 100644 index 0000000..6b5ae57 --- /dev/null +++ b/src/Story/testdata/I019/story.ink @@ -0,0 +1,3 @@ +== test == +Content +-> END diff --git a/src/Story/testdata/I019/transcript.txt b/src/Story/testdata/I019/transcript.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I021/input.txt b/src/Story/testdata/I021/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I021/story.ink b/src/Story/testdata/I021/story.ink new file mode 100644 index 0000000..4fe8287 --- /dev/null +++ b/src/Story/testdata/I021/story.ink @@ -0,0 +1,7 @@ +-> 2tests +== 2tests == +~ temp 512x2 = 512 * 2 +~ temp 512x2p2 = 512x2 + 2 +512x2 = {512x2} +512x2p2 = {512x2p2} +-> DONE diff --git a/src/Story/testdata/I021/transcript.txt b/src/Story/testdata/I021/transcript.txt new file mode 100644 index 0000000..dfd58fa --- /dev/null +++ b/src/Story/testdata/I021/transcript.txt @@ -0,0 +1,2 @@ +512x2 = 1024 +512x2p2 = 1026 diff --git a/src/Story/testdata/I023/input.txt b/src/Story/testdata/I023/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I023/story.ink b/src/Story/testdata/I023/story.ink new file mode 100644 index 0000000..5c5b425 --- /dev/null +++ b/src/Story/testdata/I023/story.ink @@ -0,0 +1,7 @@ +-> firstKnot +=== firstKnot + Hello! + -> anotherKnot +=== anotherKnot + World. + -> END diff --git a/src/Story/testdata/I023/transcript.txt b/src/Story/testdata/I023/transcript.txt new file mode 100644 index 0000000..f0bac91 --- /dev/null +++ b/src/Story/testdata/I023/transcript.txt @@ -0,0 +1,2 @@ +Hello! +World. diff --git a/src/Story/testdata/I035/input.txt b/src/Story/testdata/I035/input.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/src/Story/testdata/I035/input.txt @@ -0,0 +1 @@ +1 diff --git a/src/Story/testdata/I035/story.ink b/src/Story/testdata/I035/story.ink new file mode 100644 index 0000000..5c43e85 --- /dev/null +++ b/src/Story/testdata/I035/story.ink @@ -0,0 +1,5 @@ +* hello + -> world +== world +world +-> END diff --git a/src/Story/testdata/I035/transcript.txt b/src/Story/testdata/I035/transcript.txt new file mode 100644 index 0000000..7c0c492 --- /dev/null +++ b/src/Story/testdata/I035/transcript.txt @@ -0,0 +1,3 @@ +1: hello +?> hello +world diff --git a/src/Story/testdata/I042/input.txt b/src/Story/testdata/I042/input.txt new file mode 100644 index 0000000..6ed281c --- /dev/null +++ b/src/Story/testdata/I042/input.txt @@ -0,0 +1,2 @@ +1 +1 diff --git a/src/Story/testdata/I042/story.ink b/src/Story/testdata/I042/story.ink new file mode 100644 index 0000000..b287020 --- /dev/null +++ b/src/Story/testdata/I042/story.ink @@ -0,0 +1,4 @@ +-> test +=== test + * Hello[.], world. + -> END diff --git a/src/Story/testdata/I042/transcript.txt b/src/Story/testdata/I042/transcript.txt new file mode 100644 index 0000000..8ae08ac --- /dev/null +++ b/src/Story/testdata/I042/transcript.txt @@ -0,0 +1,2 @@ +1: Hello. +?> Hello, world. diff --git a/src/Story/testdata/I051/input.txt b/src/Story/testdata/I051/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I051/story.ink b/src/Story/testdata/I051/story.ink new file mode 100644 index 0000000..eb6a5d2 --- /dev/null +++ b/src/Story/testdata/I051/story.ink @@ -0,0 +1,3 @@ +{x} +VAR x = kX +CONST kX = "hi" diff --git a/src/Story/testdata/I051/transcript.txt b/src/Story/testdata/I051/transcript.txt new file mode 100644 index 0000000..45b983b --- /dev/null +++ b/src/Story/testdata/I051/transcript.txt @@ -0,0 +1 @@ +hi diff --git a/src/Story/testdata/I064/input.txt b/src/Story/testdata/I064/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I064/story.ink b/src/Story/testdata/I064/story.ink new file mode 100644 index 0000000..1ab0a60 --- /dev/null +++ b/src/Story/testdata/I064/story.ink @@ -0,0 +1,2 @@ +-> DONE +This content is inaccessible. diff --git a/src/Story/testdata/I064/transcript.txt b/src/Story/testdata/I064/transcript.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Story/testdata/I078/input.txt b/src/Story/testdata/I078/input.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/src/Story/testdata/I078/input.txt @@ -0,0 +1 @@ +1 diff --git a/src/Story/testdata/I078/story.ink b/src/Story/testdata/I078/story.ink new file mode 100644 index 0000000..7702c23 --- /dev/null +++ b/src/Story/testdata/I078/story.ink @@ -0,0 +1,2 @@ +* [Option] + Text diff --git a/src/Story/testdata/I078/transcript.txt b/src/Story/testdata/I078/transcript.txt new file mode 100644 index 0000000..7aba55a --- /dev/null +++ b/src/Story/testdata/I078/transcript.txt @@ -0,0 +1,2 @@ +1: Option +?> Text diff --git a/src/compile.zig b/src/compile.zig index 7460ef9..cc80d51 100644 --- a/src/compile.zig +++ b/src/compile.zig @@ -153,9 +153,14 @@ pub const InternPool = struct { } pub fn deinit(ip: *InternPool, gpa: std.mem.Allocator) void { + for (ip.code_chunks.items) |chunk| { + chunk.constants.deinit(gpa); + chunk.bytecode.deinit(gpa); + } ip.values.deinit(gpa); ip.values_map.deinit(gpa); ip.code_chunks.deinit(gpa); + ip.* = undefined; } }; @@ -179,11 +184,11 @@ pub const Module = struct { arena: std.mem.Allocator, tree: Ast, ir: Ir, - intern_pool: InternPool = .{}, globals: std.ArrayListUnmanaged(Global) = .empty, knots: std.ArrayListUnmanaged(Knot) = .empty, stitches: std.ArrayListUnmanaged(Stitch) = .empty, errors: std.ArrayListUnmanaged(Error) = .empty, + intern_pool: InternPool = .{}, work_queue: WorkQueue = .{}, pub const Global = struct { @@ -277,9 +282,12 @@ pub const Module = struct { while (mod.work_queue.pop()) |work_unit| { const chunk_index = mod.intern_pool.code_chunks.items.len; + const code_chunk = try mod.createCodeChunk(); + try mod.intern_pool.code_chunks.append(gpa, code_chunk); + var builder: Sema.Builder = .{ .sema = &sema, - .code = try mod.createCodeChunk(), + .code = code_chunk, .namespace = work_unit.namespace, }; defer builder.deinit(gpa); @@ -292,7 +300,6 @@ pub const Module = struct { try builder.finalize(); knot_index = @enumFromInt(mod.knots.items.len); - try mod.intern_pool.code_chunks.append(gpa, builder.code); try mod.knots.append(gpa, .{ .name_index = work_unit.decl_name, .code_index = @enumFromInt(chunk_index), @@ -302,7 +309,6 @@ pub const Module = struct { try sema.analyzeStitch(&builder, work_unit.inst_index); try builder.finalize(); - try mod.intern_pool.code_chunks.append(gpa, builder.code); try mod.stitches.append(gpa, .{ .knot_index = knot_index, .name_index = work_unit.decl_name, diff --git a/src/print_ir.zig b/src/print_ir.zig index a17f00f..5fc3aa0 100644 --- a/src/print_ir.zig +++ b/src/print_ir.zig @@ -330,6 +330,8 @@ pub const Writer = struct { .field_divert => try self.writeCallInst(w, inst, .field), .field_ptr => try self.writeFieldPtrInst(w, inst), .param => try self.writeStrTokInst(w, inst), + .done => try self.writeUnaryInst(w, inst), + .exit => try self.writeUnaryInst(w, inst), } try w.writeAll(")"); try w.writeAll("\n");