136 lines
2.9 KiB
Zig
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);
|
|
}
|
|
}
|