kym-tables-overhaul #30
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue