Skip to content

Commit

Permalink
Fix class state deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
bgk- committed Sep 8, 2024
1 parent 93bc38e commit 33ad0f9
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 10 deletions.
19 changes: 11 additions & 8 deletions src/runtime/state.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 = .{
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/vm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 => {
Expand Down
2 changes: 2 additions & 0 deletions src/types/class.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
23 changes: 23 additions & 0 deletions test/vm.test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -1357,6 +1360,17 @@ test "Jump Code" {
\\ }
,
},
.{
.input =
\\ === START {
\\ if true {
\\ :: "Testing fin"
\\ fin
\\ }
\\ :: "Fin did not work!"
\\ }
,
},
.{
.input =
\\ === START {
Expand Down Expand Up @@ -1549,6 +1563,7 @@ test "Save and Load State" {
\\ Two
\\ }
\\ var enumValue = Enum.One
\\ var set = Set{"set_value"}
;
const alloc = testing.allocator;

Expand All @@ -1573,6 +1588,7 @@ test "Save and Load State" {
\\ One,
\\ Two
\\ }
\\ var set = Set{"will be overwritten"}
;

var mod2 = try Module.initEmpty(allocator);
Expand All @@ -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" {
Expand Down

0 comments on commit 33ad0f9

Please sign in to comment.