kym-tables-overhaul #30

Merged
kayomn merged 12 commits from kym-tables-overhaul into main 2023-08-12 15:20:18 +02:00
3 changed files with 68 additions and 18 deletions
Showing only changes of commit b012e1e5f6 - Show all commits

View File

@ -8,6 +8,6 @@ options = {
.tick_rate = 60, .tick_rate = 60,
} }
# @log_info(options.title) @log_info(options.title)
return options return options

View File

@ -27,7 +27,7 @@ pub const RuntimeEnv = struct {
interned_symbols: SymbolSet, interned_symbols: SymbolSet,
allocator: coral.io.Allocator, allocator: coral.io.Allocator,
error_handler: ErrorHandler, error_handler: ErrorHandler,
syscallables: RefTable, system_bindings: RefTable,
locals: RefList, locals: RefList,
frames: FrameStack, frames: FrameStack,
@ -348,7 +348,7 @@ pub const RuntimeEnv = struct {
}, },
.push_system => |push_system| { .push_system => |push_system| {
if (self.env.syscallables.lookup(self.constants.values[push_system])) |syscallable| { if (self.env.system_bindings.lookup(self.constants.values[push_system])) |syscallable| {
try self.env.locals.push_one(try self.env.acquire(syscallable)); try self.env.locals.push_one(try self.env.acquire(syscallable));
} else { } else {
try self.env.locals.push_one(null); try self.env.locals.push_one(null);
@ -413,12 +413,20 @@ pub const RuntimeEnv = struct {
try self.env.set(indexable, index, value); try self.env.set(indexable, index, value);
}, },
.object_call => { .object_call => |object_call| {
const result = call: { const result = call: {
const callable = try self.env.expect(try self.pop_local()); const callable = try self.env.expect(try self.pop_local());
defer self.env.discard(callable); defer self.env.discard(callable);
try self.env.frames.push_one(.{
.name = "<lambda>",
.arg_count = object_call,
.locals_top = self.env.locals.values.len,
});
defer coral.debug.assert(self.env.frames.pop() != null);
break: call try switch (callable.object().payload) { break: call try switch (callable.object().payload) {
.dynamic => |dynamic| dynamic.typeinfo().call(.{ .dynamic => |dynamic| dynamic.typeinfo().call(.{
.userdata = dynamic.userdata(), .userdata = dynamic.userdata(),
@ -429,6 +437,12 @@ pub const RuntimeEnv = struct {
}; };
}; };
for (0 .. object_call) |_| {
if (try self.pop_local()) |popped_arg| {
self.env.discard(popped_arg);
}
}
errdefer { errdefer {
if (result) |ref| { if (result) |ref| {
self.env.discard(ref); self.env.discard(ref);
@ -901,8 +915,19 @@ pub const RuntimeEnv = struct {
return null; return null;
} }
pub fn bind_syscaller(_: *RuntimeEnv, comptime _: []const coral.io.Byte, _: Caller) RuntimeError!void { pub fn bind_system(self: *RuntimeEnv, name: []const coral.io.Byte, value: *const RuntimeRef) RuntimeError!void {
const name_symbol = try self.new_symbol(name);
errdefer self.discard(name_symbol);
const acquired_value = try self.acquire(value);
errdefer self.discard(acquired_value);
if (try self.system_bindings.replace(name_symbol, acquired_value)) |replaced| {
self.discard(replaced.key);
self.discard(replaced.value);
}
} }
pub fn call(self: *RuntimeEnv, callable: *RuntimeRef, args: []const *RuntimeRef) RuntimeError!?*RuntimeRef { pub fn call(self: *RuntimeEnv, callable: *RuntimeRef, args: []const *RuntimeRef) RuntimeError!?*RuntimeRef {
@ -1006,16 +1031,17 @@ pub const RuntimeEnv = struct {
} }
{ {
var iterable = self.syscallables.as_iterable(); var iterable = self.system_bindings.as_iterable();
while (iterable.next()) |entry| { while (iterable.next()) |entry| {
self.discard(entry.key);
self.discard(entry.value); self.discard(entry.value);
} }
} }
self.frames.free(); self.frames.free();
self.locals.free(); self.locals.free();
self.syscallables.free(); self.system_bindings.free();
self.interned_symbols.free(); self.interned_symbols.free();
} }
@ -1042,7 +1068,7 @@ pub const RuntimeEnv = struct {
return RuntimeEnv{ return RuntimeEnv{
.locals = RefList.make(allocator), .locals = RefList.make(allocator),
.frames = FrameStack.make(allocator), .frames = FrameStack.make(allocator),
.syscallables = RefTable.make(allocator, .{}), .system_bindings = RefTable.make(allocator, .{}),
.interned_symbols = SymbolSet.make(allocator, .{}), .interned_symbols = SymbolSet.make(allocator, .{}),
.error_handler = error_handler, .error_handler = error_handler,
.allocator = allocator, .allocator = allocator,
@ -1056,13 +1082,17 @@ pub const RuntimeEnv = struct {
}); });
} }
pub fn new_dynamic(self: *RuntimeEnv, typeinfo: *const Typeinfo) RuntimeError!*RuntimeRef { pub fn new_dynamic(
self: *RuntimeEnv,
userdata: [*]const coral.io.Byte,
typeinfo: *const Typeinfo,
) RuntimeError!*RuntimeRef {
const dynamic = try self.allocator.reallocate(null, @sizeOf(usize) + typeinfo.size); const dynamic = try self.allocator.reallocate(null, @sizeOf(usize) + typeinfo.size);
errdefer self.allocator.deallocate(dynamic); errdefer self.allocator.deallocate(dynamic);
coral.io.copy(dynamic, coral.io.bytes_of(&typeinfo)); coral.io.copy(dynamic, coral.io.bytes_of(&typeinfo));
coral.io.zero(dynamic[@sizeOf(usize) ..]); coral.io.copy(dynamic[@sizeOf(usize) ..], userdata[0 .. typeinfo.size]);
return RuntimeRef.allocate(self.allocator, .{ return RuntimeRef.allocate(self.allocator, .{
.ref_count = 1, .ref_count = 1,
@ -1134,17 +1164,13 @@ pub const RuntimeEnv = struct {
table.contiguous.free(); table.contiguous.free();
} }
const newed = try self.new_dynamic(&.{ return try self.new_dynamic(coral.io.bytes_of(&table).ptr, &.{
.name = "table", .name = "table",
.size = @sizeOf(Table), .size = @sizeOf(Table),
.destruct = Table.typeinfo_destruct, .destruct = Table.typeinfo_destruct,
.get = Table.typeinfo_get, .get = Table.typeinfo_get,
.set = Table.typeinfo_set, .set = Table.typeinfo_set,
}); });
coral.io.copy(self.unbox_dynamic(newed) catch unreachable, coral.io.bytes_of(&table));
return newed;
} }
pub fn raise(self: *RuntimeEnv, error_value: RuntimeError, message: []const coral.io.Byte) RuntimeError { pub fn raise(self: *RuntimeEnv, error_value: RuntimeError, message: []const coral.io.Byte) RuntimeError {
@ -1364,3 +1390,27 @@ pub const Typeinfo = struct {
return method.env.raise(error.TypeMismatch, "object is not index-settable"); return method.env.raise(error.TypeMismatch, "object is not index-settable");
} }
}; };
pub fn bind_syscaller(env: *RuntimeEnv, name: []const coral.io.Byte, caller: Caller) RuntimeError!void {
const callable = try new_caller(env, caller);
defer env.discard(callable);
try env.bind_system(name, callable);
}
pub fn new_caller(env: *RuntimeEnv, value: Caller) RuntimeError!*RuntimeRef {
const Callable = struct {
fn call(method: Typeinfo.Method) RuntimeError!?*RuntimeRef {
coral.debug.assert(method.userdata.len == @sizeOf(Caller));
return @as(*Caller, @ptrCast(@alignCast(method.userdata))).invoke(method.env);
}
};
return env.new_dynamic(coral.io.bytes_of(&value).ptr, &.{
.name = "<native>",
.size = @sizeOf(Caller),
.call = Callable.call,
});
}

View File

@ -75,15 +75,15 @@ pub fn run_app(file_access: file.Access) void {
defer script_env.free(); defer script_env.free();
script_env.bind_syscaller("log_info", kym.Caller.from(kym_log_info)) catch { kym.bind_syscaller(&script_env, "log_info", kym.Caller.from(kym_log_info)) catch {
return app.log_fail("failed to bind `log_info` syscall"); return app.log_fail("failed to bind `log_info` syscall");
}; };
script_env.bind_syscaller("log_warn", kym.Caller.from(kym_log_warn)) catch { kym.bind_syscaller(&script_env, "log_warn", kym.Caller.from(kym_log_warn)) catch {
return app.log_fail("failed to bind `log_warn` syscall"); return app.log_fail("failed to bind `log_warn` syscall");
}; };
script_env.bind_syscaller("log_fail", kym.Caller.from(kym_log_fail)) catch { kym.bind_syscaller(&script_env, "log_fail", kym.Caller.from(kym_log_fail)) catch {
return app.log_fail("failed to bind `log_fail` syscall"); return app.log_fail("failed to bind `log_fail` syscall");
}; };