From 6fdf8a714114cdacaf38ac1c387b5d2316186757 Mon Sep 17 00:00:00 2001 From: bgk- Date: Sun, 22 Dec 2024 11:43:54 -0800 Subject: [PATCH] Fix is_in_jump choices, and bytecode serialization --- src/backend/bytecode.zig | 22 +++++++++++++--------- src/export/main.zig | 3 ++- src/runtime/vm.zig | 8 ++++++-- test/export.test.zig | 6 +++--- test/vm.test.zig | 28 ++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/backend/bytecode.zig b/src/backend/bytecode.zig index 4e062d2..99210eb 100644 --- a/src/backend/bytecode.zig +++ b/src/backend/bytecode.zig @@ -48,6 +48,7 @@ pub const Bytecode = struct { } pub fn serialize(self: *Bytecode, seekable: anytype) !void { + std.debug.assert(@hasDecl(@TypeOf(seekable.*), "writer")); var writer = seekable.writer(); const isSeekable = @hasDecl(@TypeOf(seekable.*), "getPos"); const headerPos = if (isSeekable) try seekable.getPos() else 0; @@ -96,6 +97,7 @@ pub const Bytecode = struct { try writer.writeAll(self.loc); if (isSeekable) { + const end = try seekable.getPos(); try seekable.seekTo(headerPos); try writer.writeInt(u64, globalPos, .little); try writer.writeInt(u64, boughPos, .little); @@ -104,6 +106,7 @@ pub const Bytecode = struct { try writer.writeInt(u64, constPos, .little); try writer.writeInt(u64, uuidPos, .little); try writer.writeInt(u64, locPos, .little); + try seekable.seekTo(end); } } @@ -187,8 +190,8 @@ pub const Bytecode = struct { pub fn print(code: *Bytecode, writer: anytype) !void { try writer.print("\n==BYTECODE==\n", .{}); try printInstructions(writer, code.instructions); - try writer.print("\n==DEBUG==\n", .{}); - try printDebugInfo(writer, code.debug_info); + // try writer.print("\n==DEBUG==\n", .{}); + // try printDebugInfo(writer, code.debug_info); } pub fn printDebugInfo(writer: anytype, debug: []DebugInfo) !void { @@ -224,9 +227,9 @@ pub const Bytecode = struct { var count = instructions[i]; i += 1; const dest = std.mem.readVarInt(u32, instructions[i..(i + 4)], .little); - try writer.print("{d: >8} ", .{dest}); i += 4; count -= 1; + try writer.print("{d: >8} ", .{dest}); while (count > 0) : (count -= 1) { const next = std.mem.readVarInt(u32, instructions[i..(i + 4)], .little); try writer.print(" {d}", .{next}); @@ -263,27 +266,28 @@ pub const Bytecode = struct { const has_speaker = instructions[i] == 1; const tag_count = instructions[i + 1]; _ = tag_count; - const id = std.mem.readVarInt(u32, instructions[(i + 2)..(i + 6)], .little); - i += 6; + i += 2; + const id = std.mem.readVarInt(u32, instructions[i..(i + 4)], .little); + i += 4; try writer.print("{: >8}", .{has_speaker}); try writer.print(" = ", .{}); try writer.print("{}", .{id}); }, .choice => { const dest = std.mem.readVarInt(u32, instructions[i..(i + 4)], .little); - const is_unique = instructions[i + 4] == 1; i += 4; + const is_unique = instructions[i] == 1; + i += 1; const id = std.mem.readVarInt(u32, instructions[i..(i + 4)], .little); _ = id; i += 4; const visit_id = std.mem.readVarInt(u32, instructions[i..(i + 4)], .little); _ = visit_id; i += 4; - const tag_count = instructions[i + 1]; - _ = tag_count; + const tag_count = instructions[i]; i += 1; try writer.print("{d: >8}", .{dest}); - try writer.print(" unique: {}", .{is_unique}); + try writer.print(" unique: {}, tags: {d}", .{is_unique, tag_count}); }, .string, .closure => { const index = std.mem.readVarInt(u32, instructions[i..(i + 4)], .little); diff --git a/src/export/main.zig b/src/export/main.zig index dd23881..db620ca 100644 --- a/src/export/main.zig +++ b/src/export/main.zig @@ -26,9 +26,9 @@ var alloc = gpa.allocator(); /// for a compiled topi module pub export fn calculateCompileSize(path_ptr: [*:0]const u8, log_ptr: usize, log_severity: u8) callconv(.C) usize { const logger = ExportLogger{ .on_log = @ptrFromInt(log_ptr), .severity = @enumFromInt(log_severity), .allocator = alloc }; - logger.log("Calculating Compile size", .{}, .debug); var counter = std.io.countingWriter(std.io.null_writer); writeBytecode(std.mem.sliceTo(path_ptr, 0), &counter, logger); + logger.log("Calculated Compile size {d}", .{counter.bytes_written}, .debug); return counter.bytes_written; } @@ -38,6 +38,7 @@ pub export fn compile(path_ptr: [*:0]const u8, out_ptr: [*]u8, max: usize, log_p const logger = ExportLogger{ .on_log = @ptrFromInt(log_ptr), .severity = @enumFromInt(log_severity), .allocator = alloc }; var fbs = std.io.fixedBufferStream(out_ptr[0..max]); writeBytecode(std.mem.sliceTo(path_ptr, 0), &fbs, logger); + logger.log("Compiled size {d} / {d}", .{fbs.pos, max}, .debug); return fbs.pos; } diff --git a/src/runtime/vm.zig b/src/runtime/vm.zig index c21b9be..94fe3d9 100644 --- a/src/runtime/vm.zig +++ b/src/runtime/vm.zig @@ -927,11 +927,15 @@ pub const Vm = struct { try self.push(Void); }, .fork => { - if (is_in_jump) continue; self.is_waiting = true; self.current_choices = try self.choices_list.toOwnedSlice(); - self.runner.onChoices(self, self.current_choices); self.choices_list.clearRetainingCapacity(); + if (is_in_jump) { + for(self.current_choices) |c| self.allocator.free(c.tags); + self.allocator.free(self.current_choices); + continue; + } + self.runner.onChoices(self, self.current_choices); return; }, .choice => { diff --git a/test/export.test.zig b/test/export.test.zig index 4c3cb61..90b4ae2 100644 --- a/test/export.test.zig +++ b/test/export.test.zig @@ -91,15 +91,15 @@ test "Create and Destroy Vm" { try file.writer().writeAll(text); try file.seekTo(0); - const buf = try std.testing.allocator.alloc(u8, 8192); - defer std.testing.allocator.free(buf); const dir_path = try std.fs.cwd().realpathAlloc(std.testing.allocator, "."); defer std.testing.allocator.free(dir_path); const path = try std.fs.path.resolve(std.testing.allocator, &.{ dir_path, "tmp.topi" ++ "\x00" }); defer std.testing.allocator.free(path); const path_ptr: [*:0]const u8 = path[0 .. path.len - 1 :0]; const calc_size = main.calculateCompileSize(path_ptr, @intFromPtr(&TestRunner.log), @intFromEnum(ExportLogger.Severity.debug)); - const compile_size = main.compile(path_ptr, buf.ptr, buf.len, @intFromPtr(&TestRunner.onValueChanged), @intFromEnum(ExportLogger.Severity.debug)); + const buf = try std.testing.allocator.alloc(u8, calc_size); + defer std.testing.allocator.free(buf); + const compile_size = main.compile(path_ptr, buf.ptr, buf.len, @intFromPtr(&TestRunner.log), @intFromEnum(ExportLogger.Severity.debug)); try std.testing.expectEqual(compile_size, calc_size); const vm_ptr = main.createVm( diff --git a/test/vm.test.zig b/test/vm.test.zig index dbd7106..36e22dc 100644 --- a/test/vm.test.zig +++ b/test/vm.test.zig @@ -978,6 +978,34 @@ test "Boughs" { \\ assert(false, "should not be here") \\ } }, + .{ + .input = + \\ var count = 0 + \\ === START { + \\ :speaker: "Text goes here" + \\ === QS { + \\ :speaker: "Start fork" + \\ fork QUESTION { + \\ ~ "One" #test => ANSWERS.ONE + \\ ~ "Two" => ANSWERS.TWO + \\ } + \\ } + \\ :speaker: "More goes here" + \\ => QS + \\ === ANSWERS { + \\ === ONE { + \\ :speaker: "One" + \\ count += 1 + \\ if count < 3 => QS.QUESTION + \\ } + \\ === TWO { + \\ :speaker: "Two" + \\ count += 1 + \\ if count < 3 => QS.QUESTION + \\ } + \\ } + \\ } + } }; inline for (test_cases) |case| {