ona/src/coral/script/Table.zig
kayomn 8fe734f9b7
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Reintroduce integrated scripting language
2024-06-04 23:51:00 +01:00

136 lines
2.9 KiB
Zig

const coral = @import("coral");
const script = @import("../script.zig");
associative: coral.map.Table(*script.Object, *script.Object, struct {
pub const hash = script.Object.hash;
pub const equals = script.Object.equals;
}),
contiguous: coral.Stack(?*script.Object),
const Self = @This();
pub fn deinit(self: *Self, env: *script.Runtime) void {
{
var entries = self.associative.entries();
while (entries.next()) |entry| {
env.release(entry.key);
env.release(entry.value);
}
}
self.associative.deinit();
while (self.contiguous.pop()) |value| {
if (value.*) |ref| {
env.release(ref);
}
}
self.contiguous.deinit();
}
pub fn init(env: *script.Runtime) Self {
return .{
.associative = .{
.allocator = env.allocator,
.traits = .{},
},
.contiguous = .{.allocator = env.allocator},
};
}
pub const typeinfo = script.Typeinfo{
.name = "table",
.destruct = typeinfo_destruct,
.get = typeinfo_get,
.set = typeinfo_set,
.count = typeinfo_count,
};
fn typeinfo_count(context: script.Typeinfo.CountContext) script.Error!script.Fixed {
const table = @as(*Self, @ptrCast(@alignCast(context.userdata)));
return @intCast(table.associative.len + table.contiguous.values.len);
}
fn typeinfo_destruct(context: script.Typeinfo.DestructContext) void {
@as(*Self, @ptrCast(@alignCast(context.userdata))).deinit(context.env);
}
fn typeinfo_get(context: script.Typeinfo.GetContext) script.Error!?*script.Object {
const table = @as(*Self, @ptrCast(@alignCast(context.userdata)));
const index = (try context.push_index()).pop().?;
defer context.env.release(index);
if (index.is_fixed()) |fixed| {
if (fixed < 0) {
// TODO: Negative indexing.
unreachable;
}
if (fixed < table.contiguous.values.len) {
return table.contiguous.values[@intCast(fixed)];
}
}
if (table.associative.lookup(index)) |value| {
return value;
}
return null;
}
fn typeinfo_set(context: script.Typeinfo.SetContext) script.Error!void {
const table = @as(*Self, @ptrCast(@alignCast(context.userdata)));
const index = (try context.push_index()).pop().?;
errdefer context.env.release(index);
if (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| {
context.env.release(replacing);
}
if ((try context.push_value()).pop()) |value| {
errdefer context.env.release(value);
maybe_replacing.* = value;
} else {
maybe_replacing.* = null;
}
return;
}
}
const value = (try context.push_value()).pop() orelse {
if (table.associative.remove(index)) |removed| {
context.env.release(removed.key);
context.env.release(removed.value);
}
return;
};
errdefer context.env.release(value);
if (try table.associative.replace(index, value)) |replaced| {
context.env.release(replaced.key);
context.env.release(replaced.value);
}
}