From 33ad0f9438f112197b1f54d7bf47595b740bc237 Mon Sep 17 00:00:00 2001 From: bgk- Date: Sun, 8 Sep 2024 09:46:29 -0700 Subject: [PATCH] Fix class state deserialization --- src/runtime/state.zig | 19 +++++++++++-------- src/runtime/vm.zig | 4 ++-- src/types/class.zig | 2 ++ test/vm.test.zig | 23 +++++++++++++++++++++++ 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/runtime/state.zig b/src/runtime/state.zig index aa64eb9..de46133 100644 --- a/src/runtime/state.zig +++ b/src/runtime/state.zig @@ -50,8 +50,8 @@ pub const State = struct { is_func = value.obj.data == .closure or value.obj.data == .function; is_str = value.obj.data == .string; } - // we don't need to save 'const' values - if (!is_mut and !is_obj) continue; + // we don't need to save 'const' values (except visits) + if (!is_mut and !is_obj and value != .visit) continue; // or 'const' strings and functions; if (!is_mut and (is_func or is_str)) continue; @@ -228,21 +228,24 @@ pub const State = struct { const root = parsed.value.object; for (vm.bytecode.global_symbols) |sym| { const maybe_entry = root.get(sym.name); - if (maybe_entry) |entry| vm.globals[sym.index] = try deserializeEntry(vm, &root, entry, &refs, null); + if (maybe_entry) |entry| { + vm.globals[sym.index] = try deserializeEntry(vm, &root, entry, &refs, null); + } } } fn deserializeEntry(vm: *Vm, root: *const std.json.ObjectMap, entry: std.json.Value, refs: *std.AutoHashMap(UUID.ID, Value), id: ?UUID.ID) !Value { if (entry.object.get("void") != null) return Void; + if (entry.object.get("nil") != null) return Nil; if (entry.object.get("number")) |v| return .{ .number = @floatCast(v.float) }; if (entry.object.get("string")) |v| return try vm.gc.create(vm, .{ .string = try vm.allocator.dupe(u8, v.string) }); - if (entry.object.get("nil") != null) return Nil; if (entry.object.get("bool")) |v| return if (v.bool) True else False; if (entry.object.get("visit")) |v| return .{ .visit = @intCast(v.integer) }; if (entry.object.get("ref")) |v| { - if (refs.get(UUID.fromString(v.string))) |ref| return ref; + const uuid = UUID.fromString(v.string); + if (refs.get(uuid)) |ref| return ref; if (root.get(v.string)) |ref| { - const value = try deserializeEntry(vm, root, ref, refs, UUID.fromString(v.string)); + const value = try deserializeEntry(vm, root, ref, refs, uuid); try refs.put(UUID.fromString(v.string), value); return value; } @@ -347,11 +350,11 @@ pub const State = struct { return result; } if (entry.object.get("class")) |v| { - const name = v.object.get("name").?.string; + const name = try vm.allocator.dupe(u8, v.object.get("name").?.string); const ser_fields = v.object.get("fields").?.array.items; var fields = try vm.allocator.alloc(Class.Field, ser_fields.len); for (ser_fields, 0..) |f, i| { - fields[i].name = f.object.get("name").?.string; + fields[i].name = try vm.allocator.dupe(u8, f.object.get("name").?.string); fields[i].value = try deserializeEntry(vm, root, f.object.get("value").?, refs, null); } var result = try vm.gc.create(vm, .{ .class = .{ diff --git a/src/runtime/vm.zig b/src/runtime/vm.zig index 0ab396b..018d3a6 100644 --- a/src/runtime/vm.zig +++ b/src/runtime/vm.zig @@ -657,7 +657,7 @@ pub const Vm = struct { errdefer fields.deinit(); while (count > 0) : (count -= 1) { const name = try self.pop(); - const field_name = name.obj.data.string; + const field_name = try self.allocator.dupe(u8, name.obj.data.string); const field_value = try self.pop(); try fields.append(.{ .name = field_name, @@ -666,7 +666,7 @@ pub const Vm = struct { } std.mem.reverse(Class.Field, fields.items); - const class = try Class.init(self.allocator, value.obj.data.string, try fields.toOwnedSlice()); + const class = try Class.init(self.allocator, try self.allocator.dupe(u8, value.obj.data.string), try fields.toOwnedSlice()); try self.pushAlloc(.{ .class = class }); }, .instance => { diff --git a/src/types/class.zig b/src/types/class.zig index 93603ee..114e7b6 100644 --- a/src/types/class.zig +++ b/src/types/class.zig @@ -20,6 +20,8 @@ pub const Class = struct { } pub fn deinit(self: *const Class) void { + self.allocator.free(self.name); + for (self.fields) |f| self.allocator.free(f.name); self.allocator.free(self.fields); } diff --git a/test/vm.test.zig b/test/vm.test.zig index e6ee910..dbd7106 100644 --- a/test/vm.test.zig +++ b/test/vm.test.zig @@ -527,7 +527,10 @@ test "Builtin Functions" { vm.err.print(std.io.getStdErr().writer()); return err; }; + const writer = std.io.getStdErr().writer(); const value = vm.stack.previous(); + try value.print(writer); + try writer.writeAll("\n"); try testing.expect(value == .number); } } @@ -1357,6 +1360,17 @@ test "Jump Code" { \\ } , }, + .{ + .input = + \\ === START { + \\ if true { + \\ :: "Testing fin" + \\ fin + \\ } + \\ :: "Fin did not work!" + \\ } + , + }, .{ .input = \\ === START { @@ -1549,6 +1563,7 @@ test "Save and Load State" { \\ Two \\ } \\ var enumValue = Enum.One + \\ var set = Set{"set_value"} ; const alloc = testing.allocator; @@ -1573,6 +1588,7 @@ test "Save and Load State" { \\ One, \\ Two \\ } + \\ var set = Set{"will be overwritten"} ; var mod2 = try Module.initEmpty(allocator); @@ -1586,6 +1602,13 @@ test "Save and Load State" { try testing.expectEqual(vm2.globals[2].obj.data.instance.fields[1].number, 2); try vm2.interpret(); try testing.expectEqual(vm2.globals[0].number, 6); + + var data2 = std.ArrayList(u8).init(alloc); + defer data2.deinit(); + const size = try State.calculateSize(&vm2); + try testing.expectEqual(size, 677); + try State.serialize(&vm2, data2.writer()); + std.debug.print("{s}\n", .{data2.items}); } test "Includes" {