kym-tables-overhaul #30
|
@ -1,7 +1,5 @@
|
||||||
const Ast = @import("./kym/Ast.zig");
|
const Ast = @import("./kym/Ast.zig");
|
||||||
|
|
||||||
const Table = @import("./kym/Table.zig");
|
|
||||||
|
|
||||||
const coral = @import("coral");
|
const coral = @import("coral");
|
||||||
|
|
||||||
const file = @import("./file.zig");
|
const file = @import("./file.zig");
|
||||||
|
@ -786,6 +784,101 @@ pub const RuntimeEnv = struct {
|
||||||
|
|
||||||
const SymbolSet = coral.map.StringTable([:0]coral.io.Byte);
|
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 {
|
pub fn acquire(self: *RuntimeEnv, value: *const RuntimeRef) RuntimeError!*RuntimeRef {
|
||||||
const object = value.object();
|
const object = value.object();
|
||||||
|
|
||||||
|
@ -1031,8 +1124,27 @@ pub const RuntimeEnv = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_table(self: *RuntimeEnv) RuntimeError!*RuntimeRef {
|
pub fn new_table(self: *RuntimeEnv) RuntimeError!*RuntimeRef {
|
||||||
// TODO: Unroll this call logic into the environment.
|
var table = Table{
|
||||||
return Table.new(self);
|
.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 {
|
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