diff --git a/source/coral/list.zig b/source/coral/list.zig index 4e040f6..d9b794d 100644 --- a/source/coral/list.zig +++ b/source/coral/list.zig @@ -73,7 +73,7 @@ pub fn Stack(comptime Value: type) type { self.capacity = packed_size; } - pub fn peek(self: *Self) ?Value { + pub fn peek(self: Self) ?Value { if (self.values.len == 0) { return null; } diff --git a/source/ona/kym.zig b/source/ona/kym.zig index 6c1d38c..091e86b 100644 --- a/source/ona/kym.zig +++ b/source/ona/kym.zig @@ -13,7 +13,7 @@ const tokens = @import("./kym/tokens.zig"); pub const CallContext = struct { env: *RuntimeEnv, caller: ?*const RuntimeRef, - userdata: []u8, + userdata: []coral.io.Byte, args: []const ?*const RuntimeRef = &.{}, pub fn arg_at(self: CallContext, index: u8) RuntimeError!*const RuntimeRef { @@ -25,6 +25,8 @@ pub const CallContext = struct { } }; +pub const Callable = coral.io.Generator(RuntimeError!?*RuntimeRef, CallContext); + pub const DynamicObject = struct { userdata: []coral.io.Byte, typeinfo: *const Typeinfo, @@ -46,6 +48,7 @@ pub const RuntimeEnv = struct { ref_values: RefSlab, const FrameStack = coral.list.Stack(struct { + arg_count: u8, locals_top: usize, }); @@ -74,7 +77,7 @@ pub const RuntimeEnv = struct { }; pub fn acquire(self: *RuntimeEnv, ref: ?*const RuntimeRef) ?*RuntimeRef { - const key = @intFromPtr(ref); + const key = @intFromPtr(ref orelse return null); var ref_data = self.ref_values.remove(key); coral.debug.assert(ref_data != null); @@ -88,23 +91,24 @@ pub const RuntimeEnv = struct { pub fn call( self: *RuntimeEnv, - caller_ref: *const RuntimeRef, - callable_ref: *const RuntimeRef, + caller_ref: ?*const RuntimeRef, + callable_ref: ?*const RuntimeRef, arg_refs: []const *const RuntimeRef, - ) RuntimeError!*RuntimeRef { - const callable = (try callable_ref.fetch(self)).to_object(); + ) RuntimeError!?*RuntimeRef { + return switch (self.unbox(callable_ref)) { + .dynamic => |dynamic| dynamic.typeinfo.call(.{ + .env = self, + .caller = caller_ref, + .userdata = dynamic.userdata, + .args = arg_refs, + }), - return callable.userinfo.call(.{ - .env = self, - .caller = caller_ref, - .callable = callable_ref, - .userdata = callable.userdata, - .args = arg_refs, - }); + else => self.raise(error.TypeMismatch, "type is not callable"), + }; } - pub fn discard(self: *RuntimeEnv, ref: *?*RuntimeRef) void { - const key = @intFromPtr(ref.* orelse return); + pub fn discard(self: *RuntimeEnv, ref: ?*RuntimeRef) void { + const key = @intFromPtr(ref orelse return); var ref_data = self.ref_values.remove(key) orelse unreachable; coral.debug.assert(ref_data.ref_count != 0); @@ -120,8 +124,36 @@ pub const RuntimeEnv = struct { } else { coral.debug.assert(self.ref_values.insert_at(key, ref_data)); } + } - ref.* = null; + pub fn dynamic_get(self: *RuntimeEnv, indexable_ref: ?*const RuntimeRef, index_ref: ?*const RuntimeRef) RuntimeError!?*RuntimeRef { + return switch (self.unbox(indexable_ref)) { + .nil => self.raise(error.BadOperation, "nil has no such index"), + .boolean => self.raise(error.BadOperation, "boolean has no such index"), + .number => self.raise(error.BadOperation, "number has no such index"), + .string => self.raise(error.BadOperation, "string has no such index"), + + .dynamic => |dynamic| dynamic.typeinfo.get(.{ + .userdata = dynamic.userdata, + .env = self, + .index_ref = index_ref, + }), + }; + } + + pub fn dynamic_set(self: *RuntimeEnv, indexable_ref: ?*const RuntimeRef, index_ref: ?*const RuntimeRef, value_ref: ?*const RuntimeRef) RuntimeError!void { + return switch (self.unbox(indexable_ref)) { + .nil => self.raise(error.BadOperation, "nil is immutable"), + .boolean => self.raise(error.BadOperation, "boolean is immutable"), + .number => self.raise(error.BadOperation, "number is immutable"), + .string => self.raise(error.BadOperation, "string is immutable"), + + .dynamic => |dynamic| dynamic.typeinfo.set(.{ + .userdata = dynamic.userdata, + .env = self, + .index_ref = index_ref, + }, value_ref), + }; } pub fn execute_file(self: *RuntimeEnv, global_ref: ?*const RuntimeRef, file_access: file.Access, file_path: file.Path) RuntimeError!?*RuntimeRef { @@ -162,16 +194,20 @@ pub const RuntimeEnv = struct { return exe.execute(global_ref, source.name); } - pub fn frame_pop(self: *RuntimeEnv) RuntimeError!void { - const frame = self.frames.pop() orelse return self.raise(error.IllegalState, "stack underflow"); + pub fn frame_pop(self: *RuntimeEnv) void { + const frame = self.frames.pop(); - coral.debug.assert(self.local_refs.drop(self.local_refs.values.len - frame.locals_top)); + coral.debug.assert(frame != null); + coral.debug.assert(self.local_refs.drop((self.local_refs.values.len - frame.?.locals_top) + frame.?.arg_count)); } - pub fn frame_push(self: *RuntimeEnv) RuntimeError!void { - return self.frames.push_one(.{ + pub fn frame_push(self: *RuntimeEnv, arg_count: u8) RuntimeError![]const *const RuntimeRef { + try self.frames.push_one(.{ + .arg_count = arg_count, .locals_top = self.local_refs.values.len, }); + + return @as([]const *const RuntimeRef, @ptrCast(self.local_refs.values[(self.local_refs.values.len - arg_count) .. self.local_refs.values.len])); } pub fn free(self: *RuntimeEnv) void { @@ -179,27 +215,16 @@ pub const RuntimeEnv = struct { self.ref_values.free(); } - pub fn get_dynamic(self: *RuntimeEnv, indexable_ref: ?*const RuntimeRef, index_ref: ?*const RuntimeRef) RuntimeError!?*RuntimeRef { - return switch (self.unbox(indexable_ref)) { - .nil => self.raise(error.BadOperation, "nil is immutable"), - .boolean => self.raise(error.BadOperation, "boolean has no such index"), - .number => self.raise(error.BadOperation, "number has no such index"), - .string => self.raise(error.BadOperation, "string has no such index"), - - .dynamic => |dynamic| dynamic.typeinfo.get(.{ - .userdata = dynamic.userdata, - .env = self, - .index_ref = index_ref, - }), - }; - } - - pub fn local_get(self: *RuntimeEnv, local: u8) RuntimeError!?*RuntimeRef { + pub fn local_get(self: *RuntimeEnv, local: u8) ?*RuntimeRef { return self.local_refs.values[local]; } - pub fn local_pop(self: *RuntimeEnv) RuntimeError!?*RuntimeRef { - return self.local_refs.pop() orelse self.raise(error.IllegalState, "stack underflow"); + pub fn local_pop(self: *RuntimeEnv) ?*RuntimeRef { + const ref = self.local_refs.pop(); + + coral.debug.assert(ref != null); + + return ref.?; } pub fn local_push_ref(self: *RuntimeEnv, ref: ?*RuntimeRef) RuntimeError!void { @@ -214,7 +239,7 @@ pub const RuntimeEnv = struct { return self.local_refs.push_one(try self.new_number(number)); } - pub fn local_set(self: *RuntimeEnv, local: u8, value: ?*RuntimeRef) RuntimeError!void { + pub fn local_set(self: *RuntimeEnv, local: u8, value: ?*RuntimeRef) void { self.local_refs.values[local] = self.acquire(value); } @@ -271,7 +296,7 @@ pub const RuntimeEnv = struct { })); } - pub fn raise(self: *RuntimeEnv, error_value: RuntimeError, error_message: []const u8) RuntimeError { + pub fn raise(self: *RuntimeEnv, error_value: RuntimeError, error_message: []const coral.io.Byte) RuntimeError { // TODO: Print stack trace from state. coral.utf8.print_formatted(self.err_writer, "{name}@{line}: {message}", .{ .name = "???", @@ -282,21 +307,6 @@ pub const RuntimeEnv = struct { return error_value; } - pub fn set_dynamic(self: *RuntimeEnv, indexable_ref: ?*const RuntimeRef, index_ref: ?*const RuntimeRef, value_ref: ?*const RuntimeRef) RuntimeError!void { - return switch (self.unbox(indexable_ref)) { - .nil => self.raise(error.BadOperation, "nil is immutable"), - .boolean => self.raise(error.BadOperation, "boolean is immutable"), - .number => self.raise(error.BadOperation, "number is immutable"), - .string => self.raise(error.BadOperation, "string is immutable"), - - .dynamic => |dynamic| dynamic.typeinfo.set(.{ - .userdata = dynamic.userdata, - .env = self, - .index_ref = index_ref, - }, value_ref), - }; - } - pub fn unbox(self: *RuntimeEnv, ref: ?*const RuntimeRef) Unboxed { const ref_data = self.ref_values.lookup(@intFromPtr(ref orelse return .nil)); @@ -329,13 +339,29 @@ pub const TestContext = struct { }; pub const Typeinfo = struct { - call: *const fn (context: CallContext) RuntimeError!?*RuntimeRef, - clean: *const fn (userdata: []u8) void, - get: *const fn (context: IndexContext) RuntimeError!?*RuntimeRef, - set: *const fn (context: IndexContext, value: ?*const RuntimeRef) RuntimeError!void, + call: *const fn (context: CallContext) RuntimeError!?*RuntimeRef = default_call, + clean: *const fn (userdata: []coral.io.Byte) void = default_clean, + get: *const fn (context: IndexContext) RuntimeError!?*RuntimeRef = default_get, + set: *const fn (context: IndexContext, value: ?*const RuntimeRef) RuntimeError!void = default_set, test_difference: *const fn (context: TestContext) RuntimeError!Float = default_test_difference, test_equality: *const fn (context: TestContext) RuntimeError!bool = default_test_equality, + fn default_call(context: CallContext) RuntimeError!?*RuntimeRef { + return context.env.raise(error.TypeMismatch, "object is not callable"); + } + + fn default_clean(_: []coral.io.Byte) void { + // Nothing to clean by default. + } + + fn default_get(context: IndexContext) RuntimeError!?*RuntimeRef { + return context.env.raise(error.TypeMismatch, "object is not indexable"); + } + + fn default_set(context: IndexContext, _: ?*const RuntimeRef) RuntimeError!void { + return context.env.raise(error.TypeMismatch, "object is not indexable"); + } + fn default_test_difference(context: TestContext) RuntimeError!Float { return context.env.raise(error.TypeMismatch, "object is not comparable"); } @@ -352,16 +378,28 @@ pub const Unboxed = union (enum) { nil, boolean: bool, number: Float, - string: []const u8, + string: []const coral.io.Byte, dynamic: *const DynamicObject, }; -pub fn get_dynamic_field(env: *RuntimeEnv, indexable: ?*const RuntimeRef, field: []const u8) RuntimeError!?*RuntimeRef { - var interned_field = try env.new_string(field); +pub fn get_dynamic_field(env: *RuntimeEnv, indexable_ref: ?*const RuntimeRef, field_name: []const coral.io.Byte) RuntimeError!?*RuntimeRef { + const field_name_ref = try env.new_string(field_name); - defer env.discard(&interned_field); + defer env.discard(field_name_ref); - return env.get_dynamic(indexable, interned_field); + return env.dynamic_get(indexable_ref, field_name_ref); +} + +pub fn new_callable(env: *RuntimeEnv, generator: Callable) RuntimeError!?*RuntimeRef { + const Concrete = struct { + fn call(context: CallContext) RuntimeError!?*RuntimeRef { + return @as(*Callable, @ptrCast(@alignCast(context.userdata.ptr))).invoke(context); + } + }; + + return env.new_dynamic(coral.io.bytes_of(&generator), &.{ + .call = Concrete.call, + }); } pub fn new_table(env: *RuntimeEnv) RuntimeError!?*RuntimeRef { @@ -372,6 +410,14 @@ pub fn new_table(env: *RuntimeEnv) RuntimeError!?*RuntimeRef { return try env.new_dynamic(coral.io.bytes_of(&table), &Table.typeinfo); } +pub fn set_dynamic_field(env: *RuntimeEnv, indexable_ref: ?*const RuntimeRef, field_name: []const coral.io.Byte, value_ref: ?*const RuntimeRef) RuntimeError!void { + const field_name_ref = try env.new_string(field_name); + + defer env.discard(field_name_ref); + + return env.dynamic_set(indexable_ref, field_name_ref, value_ref); +} + pub fn test_difference(env: *RuntimeEnv, lhs_ref: ?*const RuntimeRef, rhs_ref: ?*const RuntimeRef) RuntimeError!Float { return switch (env.unbox(lhs_ref)) { .nil => env.raise(error.TypeMismatch, "cannot compare nil objects"), diff --git a/source/ona/kym/Chunk.zig b/source/ona/kym/Chunk.zig index 7ede24b..5013c3c 100644 --- a/source/ona/kym/Chunk.zig +++ b/source/ona/kym/Chunk.zig @@ -51,8 +51,7 @@ const AstCompiler = struct { }); } - try self.chunk.append_opcode(.{ - .push_table = .{.field_count = @intCast(fields.values.len)}}); + try self.chunk.append_opcode(.{.push_table = @intCast(fields.values.len)}); }, .binary_operation => |operation| { @@ -87,7 +86,7 @@ const AstCompiler = struct { .get_local => |local| { try self.chunk.append_opcode(.{ - .local_push_ref = self.resolve_local(local) orelse return self.chunk.env.raise(error.OutOfMemory, "undefined local"), + .push_local = self.resolve_local(local) orelse return self.chunk.env.raise(error.OutOfMemory, "undefined local"), }); }, @@ -101,12 +100,7 @@ const AstCompiler = struct { } try self.chunk.append_opcode(.{.push_const = try self.chunk.declare_constant_string(call.identifier)}); - - try self.chunk.append_opcode(.{ - .global_call = .{ - .arg_count = @intCast(call.argument_expressions.values.len), - }, - }); + try self.chunk.append_opcode(.{.call = @intCast(call.argument_expressions.values.len)}); }, } } @@ -136,12 +130,8 @@ const AstCompiler = struct { } try self.chunk.append_opcode(.{.push_const = try self.chunk.declare_constant_string(call.identifier)}); - - try self.chunk.append_opcode(.{ - .global_call = .{ - .arg_count = @intCast(call.argument_expressions.values.len), - }, - }); + try self.chunk.append_opcode(.get_global); + try self.chunk.append_opcode(.{.call = @intCast(call.argument_expressions.values.len)}); } } } @@ -185,17 +175,11 @@ pub const Opcode = union (enum) { push_true, push_false, push_const: Constant, - local_push_ref: u8, + push_local: u8, + push_table: u32, set_local: u8, get_global, - - push_table: struct { - field_count: u32, - }, - - global_call: struct { - arg_count: u8, - }, + call: u8, not, neg, @@ -242,9 +226,9 @@ pub fn declare_constant_number(self: *Self, constant: kym.Float) kym.RuntimeErro return self.env.raise(error.BadSyntax, "functions may contain a maximum of 65,535 constants"); } - var constant_ref = try self.env.new_number(constant); + const constant_ref = try self.env.new_number(constant); - errdefer self.env.discard(&constant_ref); + errdefer self.env.discard(constant_ref); try self.constant_refs.push_one(constant_ref); @@ -258,9 +242,9 @@ pub fn declare_constant_string(self: *Self, constant: []const coral.io.Byte) kym return self.env.raise(error.BadSyntax, "functions may contain a maximum of 65,535 constants"); } - var constant_ref = try self.env.new_string(constant); + const constant_ref = try self.env.new_string(constant); - errdefer self.env.discard(&constant_ref); + errdefer self.env.discard(constant_ref); try self.constant_refs.push_one(constant_ref); @@ -269,8 +253,9 @@ pub fn declare_constant_string(self: *Self, constant: []const coral.io.Byte) kym pub fn execute(self: *Self, global_ref: ?*const kym.RuntimeRef, name: []const coral.io.Byte) kym.RuntimeError!?*kym.RuntimeRef { _ = name; + _ = try self.env.frame_push(0); - try self.env.frame_push(); + defer self.env.frame_pop(); for (self.opcodes.values) |opcode| { switch (opcode) { @@ -279,72 +264,84 @@ pub fn execute(self: *Self, global_ref: ?*const kym.RuntimeRef, name: []const co .push_false => try self.env.local_push_boolean(false), .push_const => |constant| try self.env.local_push_ref(self.constant_refs.values[constant]), - .push_table => |push_table| { - var table_ref = try kym.new_table(self.env); + .push_table => |field_count| { + const table_ref = try kym.new_table(self.env); - defer self.env.discard(&table_ref); + defer self.env.discard(table_ref); { var popped = @as(usize, 0); - while (popped < push_table.field_count) : (popped += 1) { - try self.env.set_dynamic(table_ref, try self.env.local_pop(), try self.env.local_pop()); + while (popped < field_count) : (popped += 1) { + try self.env.dynamic_set(table_ref, self.env.local_pop(), self.env.local_pop()); } } try self.env.local_push_ref(table_ref); }, - .local_push_ref => |local| { - var ref = try self.env.local_get(local); + .push_local => |local| { + const ref = self.env.local_get(local); - defer self.env.discard(&ref); + defer self.env.discard(ref); try self.env.local_push_ref(ref); }, .get_global => { - var identifier_ref = try self.env.local_pop(); + const identifier_ref = self.env.local_pop(); - defer self.env.discard(&identifier_ref); + defer self.env.discard(identifier_ref); - var ref = try self.env.get_dynamic(global_ref, identifier_ref); + const ref = try self.env.dynamic_get(global_ref, identifier_ref); - defer self.env.discard(&ref); + defer self.env.discard(ref); try self.env.local_push_ref(ref); }, .set_local => |local| { - var ref = try self.env.local_pop(); + const ref = self.env.local_pop(); - defer self.env.discard(&ref); + defer self.env.discard(ref); - try self.env.local_set(local, ref); + self.env.local_set(local, ref); }, - .global_call => |_| { + .call => |arg_count| { + const callable_ref = self.env.local_pop(); + defer self.env.discard(callable_ref); + + const args = try self.env.frame_push(arg_count); + + defer self.env.frame_pop(); + + const result_ref = try self.env.call(global_ref, callable_ref, args); + + defer self.env.discard(result_ref); + + try self.env.local_push_ref(result_ref); }, - .neg => try self.env.local_push_number(switch (self.env.unbox(try self.env.local_pop())) { + .neg => try self.env.local_push_number(switch (self.env.unbox(self.env.local_pop())) { .number => |number| -number, else => return self.env.raise(error.TypeMismatch, "object is not scalar negatable"), }), - .not => try self.env.local_push_boolean(switch (self.env.unbox(try self.env.local_pop())) { + .not => try self.env.local_push_boolean(switch (self.env.unbox(self.env.local_pop())) { .boolean => |boolean| !boolean, else => return self.env.raise(error.TypeMismatch, "object is not boolean negatable"), }), .add => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_ref(switch (self.env.unbox(lhs_ref)) { .number => |lhs_number| switch (self.env.unbox(rhs_ref)) { @@ -357,13 +354,13 @@ pub fn execute(self: *Self, global_ref: ?*const kym.RuntimeRef, name: []const co }, .sub => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_ref(switch (self.env.unbox(lhs_ref)) { .number => |lhs_number| switch (self.env.unbox(rhs_ref)) { @@ -376,13 +373,13 @@ pub fn execute(self: *Self, global_ref: ?*const kym.RuntimeRef, name: []const co }, .mul => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_ref(switch (self.env.unbox(lhs_ref)) { .number => |lhs_number| switch (self.env.unbox(rhs_ref)) { @@ -395,13 +392,13 @@ pub fn execute(self: *Self, global_ref: ?*const kym.RuntimeRef, name: []const co }, .div => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_ref(switch (self.env.unbox(lhs_ref)) { .number => |lhs_number| switch (self.env.unbox(rhs_ref)) { @@ -414,76 +411,72 @@ pub fn execute(self: *Self, global_ref: ?*const kym.RuntimeRef, name: []const co }, .eql => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_boolean(try kym.test_equality(self.env, lhs_ref, rhs_ref)); }, .cgt => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_boolean(try kym.test_difference(self.env, lhs_ref, rhs_ref) > 0); }, .clt => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_boolean(try kym.test_difference(self.env, lhs_ref, rhs_ref) < 0); }, .cge => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_boolean(try kym.test_difference(self.env, lhs_ref, rhs_ref) >= 0); }, .cle => { - var rhs_ref = try self.env.local_pop(); + const rhs_ref = self.env.local_pop(); - defer self.env.discard(&rhs_ref); + defer self.env.discard(rhs_ref); - var lhs_ref = try self.env.local_pop(); + const lhs_ref = self.env.local_pop(); - defer self.env.discard(&lhs_ref); + defer self.env.discard(lhs_ref); try self.env.local_push_boolean(try kym.test_difference(self.env, lhs_ref, rhs_ref) <= 0); }, } } - const result = try self.env.local_pop(); - - try self.env.frame_pop(); - - return result; + return self.env.local_pop(); } pub fn free(self: *Self) void { - for (self.constant_refs.values) |*constant| { + for (self.constant_refs.values) |constant| { self.env.discard(constant); } diff --git a/source/ona/kym/Table.zig b/source/ona/kym/Table.zig index 8867bcc..ae6af0a 100644 --- a/source/ona/kym/Table.zig +++ b/source/ona/kym/Table.zig @@ -22,16 +22,11 @@ pub fn make(env: *kym.RuntimeEnv) Self { } pub const typeinfo = kym.Typeinfo{ - .call = typeinfo_call, .clean = typeinfo_clean, .get = typeinfo_get, .set = typeinfo_set, }; -fn typeinfo_call(context: kym.CallContext) kym.RuntimeError!?*kym.RuntimeRef { - return context.env.raise(error.TypeMismatch, "cannot call a table"); -} - fn typeinfo_clean(userdata: []u8) void { @as(*Self, @ptrCast(@alignCast(userdata.ptr))).free(); } @@ -49,15 +44,15 @@ fn typeinfo_get(context: kym.IndexContext) kym.RuntimeError!?*kym.RuntimeRef { fn typeinfo_set(context: kym.IndexContext, value_ref: ?*const kym.RuntimeRef) kym.RuntimeError!void { const table = @as(*Self, @ptrCast(@alignCast(context.userdata.ptr))); - var acquired_value_ref = context.env.acquire(value_ref); + const acquired_value_ref = context.env.acquire(value_ref); - errdefer context.env.discard(&acquired_value_ref); + errdefer context.env.discard(acquired_value_ref); switch (context.env.unbox(context.index_ref)) { .string => |string| { - var acquired_index_ref = context.env.acquire(context.index_ref); + const acquired_index_ref = context.env.acquire(context.index_ref); - errdefer context.env.discard(&acquired_index_ref); + errdefer context.env.discard(acquired_index_ref); var displaced_table_entry = if (acquired_value_ref) |ref| try table.fields.replace(string, .{ .key_ref = acquired_index_ref, @@ -65,8 +60,8 @@ fn typeinfo_set(context: kym.IndexContext, value_ref: ?*const kym.RuntimeRef) ky }) else table.fields.remove(string); if (displaced_table_entry) |*entry| { - context.env.discard(&entry.value.key_ref); - context.env.discard(&entry.value.value_ref); + context.env.discard(entry.value.key_ref); + context.env.discard(entry.value.value_ref); } },