kym-tables-overhaul #30

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

View File

@ -1,7 +1,5 @@
const Ast = @import("./kym/Ast.zig");
const Table = @import("./kym/Table.zig");
const coral = @import("coral");
const file = @import("./file.zig");
@ -786,6 +784,101 @@ pub const RuntimeEnv = struct {
const SymbolSet = coral.map.StringTable([:0]coral.io.Byte);
const Table = struct {
associative: RefTable,
contiguous: RefList,
fn typeinfo_destruct(method: Typeinfo.Method) void {
const table = @as(*Table, @ptrCast(@alignCast(method.userdata.ptr)));
{
var field_iterable = table.associative.as_iterable();
while (field_iterable.next()) |entry| {
method.env.discard(entry.key);
method.env.discard(entry.value);
}
}
table.associative.free();
while (table.contiguous.pop()) |value| {
if (value) |ref| {
method.env.discard(ref);
}
}
table.contiguous.free();
}
fn typeinfo_get(method: Typeinfo.Method, index: *const RuntimeRef) RuntimeError!?*RuntimeRef {
const table = @as(*Table, @ptrCast(@alignCast(method.userdata.ptr)));
const acquired_index = try method.env.acquire(index);
defer method.env.discard(acquired_index);
if (acquired_index.is_fixed()) |fixed| {
if (fixed < 0) {
// TODO: Negative indexing.
unreachable;
}
if (fixed < table.contiguous.values.len) {
return method.env.acquire(table.contiguous.values[@intCast(fixed)] orelse return null);
}
}
if (table.associative.lookup(acquired_index)) |value_ref| {
return method.env.acquire(value_ref);
}
return null;
}
fn typeinfo_set(method: Typeinfo.Method, index: *const RuntimeRef, value: ?*const RuntimeRef) RuntimeError!void {
const table = @as(*Table, @ptrCast(@alignCast(method.userdata.ptr)));
const acquired_index = try method.env.acquire(index);
errdefer method.env.discard(acquired_index);
if (acquired_index.is_fixed()) |fixed| {
if (fixed < 0) {
// TODO: Negative indexing.
unreachable;
}
if (fixed < table.contiguous.values.len) {
const maybe_replacing = &table.contiguous.values[@intCast(fixed)];
if (maybe_replacing.*) |replacing| {
method.env.discard(replacing);
}
maybe_replacing.* = if (value) |ref| try method.env.acquire(ref) else null;
return;
}
}
const acquired_value = try method.env.acquire(value orelse {
if (table.associative.remove(acquired_index)) |removed| {
method.env.discard(removed.key);
method.env.discard(removed.value);
}
return;
});
errdefer method.env.discard(acquired_value);
if (try table.associative.replace(acquired_index, acquired_value)) |replaced| {
method.env.discard(replaced.key);
method.env.discard(replaced.value);
}
}
};
pub fn acquire(self: *RuntimeEnv, value: *const RuntimeRef) RuntimeError!*RuntimeRef {
const object = value.object();
@ -1031,8 +1124,27 @@ pub const RuntimeEnv = struct {
}
pub fn new_table(self: *RuntimeEnv) RuntimeError!*RuntimeRef {
// TODO: Unroll this call logic into the environment.
return Table.new(self);
var table = Table{
.associative = RefTable.make(self.allocator, .{}),
.contiguous = RefList.make(self.allocator),
};
errdefer {
table.associative.free();
table.contiguous.free();
}
const newed = try self.new_dynamic(&.{
.name = "table",
.size = @sizeOf(Table),
.destruct = Table.typeinfo_destruct,
.get = Table.typeinfo_get,
.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 {

View File

@ -1,133 +0,0 @@
const coral = @import("coral");
const kym = @import("../kym.zig");
associative: AssociativeTable,
contiguous: ContiguousList,
const AssociativeTable = coral.map.Table(*kym.RuntimeRef, *kym.RuntimeRef, struct {
pub fn hash(key: *kym.RuntimeRef) usize {
return key.hash();
}
pub fn equals(key_a: *kym.RuntimeRef, key_b: *kym.RuntimeRef) bool {
return key_a.equals(key_b);
}
});
const ContiguousList = coral.list.Stack(?*kym.RuntimeRef);
const Self = @This();
pub fn new(env: *kym.RuntimeEnv) kym.RuntimeError!*kym.RuntimeRef {
var self = Self{
.associative = AssociativeTable.make(env.allocator, .{}),
.contiguous = ContiguousList.make(env.allocator),
};
errdefer {
self.associative.free();
self.contiguous.free();
}
const table = try env.new_dynamic(&.{
.name = "table",
.size = @sizeOf(Self),
.destruct = typeinfo_destruct,
.get = typeinfo_get,
.set = typeinfo_set,
});
coral.io.copy(env.unbox_dynamic(table) catch unreachable, coral.io.bytes_of(&self));
return table;
}
fn typeinfo_destruct(method: kym.Typeinfo.Method) void {
const table = @as(*Self, @ptrCast(@alignCast(method.userdata.ptr)));
{
var field_iterable = table.associative.as_iterable();
while (field_iterable.next()) |entry| {
method.env.discard(entry.key);
method.env.discard(entry.value);
}
}
table.associative.free();
while (table.contiguous.pop()) |value| {
if (value) |ref| {
method.env.discard(ref);
}
}
table.contiguous.free();
}
fn typeinfo_get(method: kym.Typeinfo.Method, index: *const kym.RuntimeRef) kym.RuntimeError!?*kym.RuntimeRef {
const table = @as(*Self, @ptrCast(@alignCast(method.userdata.ptr)));
const acquired_index = try method.env.acquire(index);
defer method.env.discard(acquired_index);
if (acquired_index.is_fixed()) |fixed| {
if (fixed < 0) {
// TODO: Negative indexing.
unreachable;
}
if (fixed < table.contiguous.values.len) {
return method.env.acquire(table.contiguous.values[@intCast(fixed)] orelse return null);
}
}
if (table.associative.lookup(acquired_index)) |value_ref| {
return method.env.acquire(value_ref);
}
return null;
}
fn typeinfo_set(method: kym.Typeinfo.Method, index: *const kym.RuntimeRef, value: ?*const kym.RuntimeRef) kym.RuntimeError!void {
const table = @as(*Self, @ptrCast(@alignCast(method.userdata.ptr)));
const acquired_index = try method.env.acquire(index);
errdefer method.env.discard(acquired_index);
if (acquired_index.is_fixed()) |fixed| {
if (fixed < 0) {
// TODO: Negative indexing.
unreachable;
}
if (fixed < table.contiguous.values.len) {
const maybe_replacing = &table.contiguous.values[@intCast(fixed)];
if (maybe_replacing.*) |replacing| {
method.env.discard(replacing);
}
maybe_replacing.* = if (value) |ref| try method.env.acquire(ref) else null;
return;
}
}
const acquired_value = try method.env.acquire(value orelse {
if (table.associative.remove(acquired_index)) |removed| {
method.env.discard(removed.key);
method.env.discard(removed.value);
}
return;
});
errdefer method.env.discard(acquired_value);
if (try table.associative.replace(acquired_index, acquired_value)) |replaced| {
method.env.discard(replaced.key);
method.env.discard(replaced.value);
}
}