From b28b1a86c96ba3cd920173c6a55cdbf20fbf265e Mon Sep 17 00:00:00 2001 From: kayomn Date: Mon, 6 Nov 2023 22:27:09 +0000 Subject: [PATCH] Fix double free and boxing bugs in VM --- debug/app.ona | 6 +++++- source/ona/kym.zig | 4 ++-- source/ona/kym/Chunk.zig | 23 +++++++++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/debug/app.ona b/debug/app.ona index bb14b64..6920724 100644 --- a/debug/app.ona +++ b/debug/app.ona @@ -1,5 +1,9 @@ -let test_param = "monkey wrench" +let wrench = "wrench" + +var test_param = "monkey {wrench}" + +test_param = "monkey" let printer = lambda (pfx): @print(test_param) diff --git a/source/ona/kym.zig b/source/ona/kym.zig index 69c40fe..7ad0543 100644 --- a/source/ona/kym.zig +++ b/source/ona/kym.zig @@ -282,7 +282,7 @@ pub const RuntimeEnv = struct { pub fn get_boxed(self: *RuntimeEnv, boxable: *RuntimeRef) RuntimeError!?*RuntimeRef { return switch (boxable.object().payload) { .boxed => |boxed| if (boxed) |boxed_value| boxed_value.acquire() else null, - else => self.raise(error.TypeMismatch, "{typename} is not boxable", .{.typename = boxable.typename()}), + else => self.raise(error.TypeMismatch, "{typename} is not box-gettable", .{.typename = boxable.typename()}), }; } @@ -624,7 +624,7 @@ pub const RuntimeEnv = struct { boxed.* = if (value) |ref| ref.acquire() else null; }, - else => return self.raise(error.TypeMismatch, "{typename} is not boxable", .{ + else => return self.raise(error.TypeMismatch, "{typename} is not box-settable", .{ .typename = boxable.typename(), }), } diff --git a/source/ona/kym/Chunk.zig b/source/ona/kym/Chunk.zig index 7ebb7fb..20be8b5 100644 --- a/source/ona/kym/Chunk.zig +++ b/source/ona/kym/Chunk.zig @@ -167,7 +167,14 @@ const Compiler = struct { .declaration_get => |declaration_get| { if (get_local_index(environment, declaration_get.declaration)) |index| { - return self.chunk.write(expression.line, .{.push_local = index}); + if (is_declaration_boxed(declaration_get.declaration)) { + try self.chunk.write(expression.line, .{.push_local = index}); + try self.chunk.write(expression.line, .get_box); + } else { + try self.chunk.write(expression.line, .{.push_local = index}); + } + + return; } if (try self.get_binding_index(environment, declaration_get.declaration)) |index| { @@ -187,12 +194,19 @@ const Compiler = struct { if (get_local_index(environment, declaration_set.declaration)) |index| { try self.compile_expression(environment, declaration_set.assign, null); - return self.chunk.write(expression.line, .{.set_local = index}); + if (is_declaration_boxed(declaration_set.declaration)) { + try self.chunk.write(expression.line, .{.push_local = index}); + try self.chunk.write(expression.line, .set_box); + } else { + try self.chunk.write(expression.line, .{.set_local = index}); + } + + return; } if (try self.get_binding_index(environment, declaration_set.declaration)) |index| { - try self.chunk.write(expression.line, .{.push_binding = index}); try self.compile_expression(environment, declaration_set.assign, null); + try self.chunk.write(expression.line, .{.push_binding = index}); if (is_declaration_boxed(declaration_set.declaration)) { try self.chunk.write(expression.line, .set_box); @@ -730,7 +744,8 @@ pub fn execute(self: *Self, env: *kym.RuntimeEnv, frame: *const kym.Frame) kym.R const value = try env.expect(try env.pop_local()); - defer env.discard(box); + errdefer env.discard(value); + try env.set_boxed(box, value); },