feat: infrastructure to support qualified lookups
This commit is contained in:
parent
e8ad1cd5b5
commit
440ec68481
6 changed files with 1118 additions and 575 deletions
|
|
@ -14,7 +14,17 @@ node: std.SinglyLinkedList.Node,
|
|||
pub const Tag = enum {
|
||||
number,
|
||||
string,
|
||||
content_path,
|
||||
code,
|
||||
knot,
|
||||
|
||||
pub fn toStr(tag: Tag) []const u8 {
|
||||
return switch (tag) {
|
||||
.number => "Number",
|
||||
.string => "String",
|
||||
.code => "Code",
|
||||
.knot => "Knot",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn destroy(obj: *Object, story: *Story) void {
|
||||
|
|
@ -27,8 +37,12 @@ pub fn destroy(obj: *Object, story: *Story) void {
|
|||
const typed_obj: *Object.String = @alignCast(@fieldParentPtr("base", obj));
|
||||
typed_obj.destroy(story);
|
||||
},
|
||||
.content_path => {
|
||||
const typed_obj: *Object.ContentPath = @alignCast(@fieldParentPtr("base", obj));
|
||||
.code => {
|
||||
const typed_obj: *Object.Code = @alignCast(@fieldParentPtr("base", obj));
|
||||
typed_obj.destroy(story);
|
||||
},
|
||||
.knot => {
|
||||
const typed_obj: *Object.Knot = @alignCast(@fieldParentPtr("base", obj));
|
||||
typed_obj.destroy(story);
|
||||
},
|
||||
}
|
||||
|
|
@ -190,12 +204,13 @@ pub const String = struct {
|
|||
|
||||
const Type = Object.String;
|
||||
|
||||
pub fn create(
|
||||
story: *Story,
|
||||
pub const Options = struct {
|
||||
bytes: []const u8,
|
||||
) error{OutOfMemory}!*Object.String {
|
||||
};
|
||||
|
||||
pub fn create(story: *Story, options: Options) error{OutOfMemory}!*Object.String {
|
||||
const gpa = story.allocator;
|
||||
const alloc_len = @sizeOf(Type) + bytes.len + 1;
|
||||
const alloc_len = @sizeOf(Type) + options.bytes.len + 1;
|
||||
const raw = try gpa.alignedAlloc(u8, .of(Type), alloc_len);
|
||||
const object: *Type = @ptrCast(raw);
|
||||
|
||||
|
|
@ -206,15 +221,15 @@ pub const String = struct {
|
|||
.node = .{},
|
||||
},
|
||||
.hash = 0,
|
||||
.length = bytes.len,
|
||||
.length = options.bytes.len,
|
||||
.bytes = undefined,
|
||||
};
|
||||
|
||||
// Point bytes slice to the memory *after* the struct
|
||||
const buf = raw[@sizeOf(Type)..][0 .. bytes.len + 1];
|
||||
const buf = raw[@sizeOf(Type)..][0 .. options.bytes.len + 1];
|
||||
object.bytes = buf.ptr;
|
||||
@memcpy(buf[0..bytes.len], bytes);
|
||||
buf[bytes.len] = 0;
|
||||
@memcpy(buf[0..options.bytes.len], options.bytes);
|
||||
buf[options.bytes.len] = 0;
|
||||
|
||||
story.gc_objects.prepend(&object.base.node);
|
||||
return object;
|
||||
|
|
@ -227,6 +242,10 @@ pub const String = struct {
|
|||
gpa.free(base[0..alloc_len]);
|
||||
}
|
||||
|
||||
pub fn toSlice(obj: *Object.String) []const u8 {
|
||||
return obj.bytes[0..obj.length];
|
||||
}
|
||||
|
||||
pub fn fromObject(story: *Story, obj: *Object) !*Object.String {
|
||||
switch (obj.tag) {
|
||||
.number => {
|
||||
|
|
@ -237,7 +256,9 @@ pub const String = struct {
|
|||
const number_bytes = try std.fmt.bufPrint(&print_buffer, "{}", .{
|
||||
number_object.data.integer,
|
||||
});
|
||||
return .create(story, number_bytes);
|
||||
return .create(story, .{
|
||||
.bytes = number_bytes,
|
||||
});
|
||||
},
|
||||
.string => return @ptrCast(obj),
|
||||
else => unreachable,
|
||||
|
|
@ -254,59 +275,111 @@ pub const String = struct {
|
|||
@memcpy(bytes[lhs.length..], rhs.bytes[0..rhs.length]);
|
||||
//ink_gc_disown(story, INK_OBJ(lhs));
|
||||
//ink_gc_disown(story, INK_OBJ(rhs));
|
||||
return .create(story, bytes);
|
||||
return .create(story, .{
|
||||
.bytes = bytes,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
pub const ContentPath = struct {
|
||||
/// Immutable object type for code chunks.
|
||||
pub const Code = struct {
|
||||
base: Object,
|
||||
name: *Object.String,
|
||||
arity: usize,
|
||||
// TODO: Rename this to stack size.
|
||||
locals_count: usize,
|
||||
// TODO: Rename this to constant_pool.
|
||||
const_pool: []u32,
|
||||
bytes: []const u8,
|
||||
/// Number of arguments.
|
||||
args_count: u32,
|
||||
/// Number of local variables.
|
||||
locals_count: u32,
|
||||
/// Stack size required to load.
|
||||
stack_size: u32,
|
||||
/// Table of global constant indexes.
|
||||
constants: []const u8,
|
||||
/// Raw compiled bytecode.
|
||||
bytecode: []const u8,
|
||||
|
||||
const Type = Object.ContentPath;
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
name: *Object.String,
|
||||
arity: usize,
|
||||
locals_count: usize,
|
||||
const_pool: []u32,
|
||||
bytes: []const u8,
|
||||
pub const Options = struct {
|
||||
args_count: u32,
|
||||
locals_count: u32,
|
||||
stack_size: u32,
|
||||
constants: []const u8,
|
||||
code_bytes: []const u8,
|
||||
};
|
||||
|
||||
pub fn create(story: *Story, options: CreateOptions) error{OutOfMemory}!*Object.ContentPath {
|
||||
const Type = Code;
|
||||
|
||||
pub fn create(story: *Story, options: Options) error{OutOfMemory}!*Object.Code {
|
||||
const gpa = story.allocator;
|
||||
const alloc_len = @sizeOf(Type);
|
||||
const raw = try gpa.alignedAlloc(u8, .of(Type), alloc_len);
|
||||
const raw = try gpa.alignedAlloc(u8, .of(Type), @sizeOf(Type));
|
||||
const obj: *Type = @ptrCast(raw);
|
||||
|
||||
obj.* = .{
|
||||
.base = .{
|
||||
.tag = .content_path,
|
||||
.tag = .code,
|
||||
.is_marked = false,
|
||||
.node = .{},
|
||||
},
|
||||
.name = options.name,
|
||||
.arity = options.arity,
|
||||
.args_count = options.args_count,
|
||||
.locals_count = options.locals_count,
|
||||
.const_pool = options.const_pool,
|
||||
.bytes = options.bytes,
|
||||
.stack_size = options.stack_size,
|
||||
.constants = options.constants,
|
||||
.bytecode = options.code_bytes,
|
||||
};
|
||||
|
||||
story.gc_objects.prepend(&obj.base.node);
|
||||
return obj;
|
||||
}
|
||||
|
||||
pub fn destroy(obj: *ContentPath, story: *Story) void {
|
||||
pub fn destroy(obj: *Code, story: *Story) void {
|
||||
const gpa = story.allocator;
|
||||
gpa.free(obj.const_pool);
|
||||
gpa.free(obj.bytes);
|
||||
gpa.free(obj.constants);
|
||||
gpa.free(obj.bytecode);
|
||||
|
||||
const base: [*]align(@alignOf(Type)) u8 = @ptrCast(obj);
|
||||
gpa.free(base[0..@sizeOf(Type)]);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Knot = struct {
|
||||
base: Object,
|
||||
/// Pointer to the name of the knot.
|
||||
name: *Object.String,
|
||||
/// Pointer to the code object for the knot.
|
||||
code: *Object.Code,
|
||||
members: std.StringHashMapUnmanaged(*Object) = .empty,
|
||||
|
||||
pub const Options = struct {
|
||||
name: []const u8,
|
||||
code: *Object.Code,
|
||||
};
|
||||
|
||||
const Type = Knot;
|
||||
|
||||
pub fn create(story: *Story, options: Options) error{OutOfMemory}!*Object.Knot {
|
||||
const gpa = story.allocator;
|
||||
const raw = try gpa.alignedAlloc(u8, .of(Type), @sizeOf(Type));
|
||||
const obj: *Type = @ptrCast(raw);
|
||||
|
||||
obj.* = .{
|
||||
.base = .{
|
||||
.tag = .knot,
|
||||
.is_marked = false,
|
||||
.node = .{},
|
||||
},
|
||||
.name = try .create(story, .{
|
||||
.bytes = options.name,
|
||||
}),
|
||||
.code = options.code,
|
||||
.members = .empty,
|
||||
};
|
||||
|
||||
story.gc_objects.prepend(&obj.base.node);
|
||||
return obj;
|
||||
}
|
||||
|
||||
pub fn destroy(obj: *Knot, story: *Story) void {
|
||||
const gpa = story.allocator;
|
||||
obj.members.deinit(gpa);
|
||||
|
||||
const alloc_len = @sizeOf(Type);
|
||||
const base: [*]align(@alignOf(Type)) u8 = @ptrCast(obj);
|
||||
gpa.free(base[0..alloc_len]);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue