obj::class.zig (2627B)
1 const std = @import("std"); 2 3 const utils = @import("lib::utils.zig"); 4 const table = @import("lib::table.zig"); 5 const hash = @import("hash.zig"); 6 7 const Packed = @import("lib::packed.zig").Packed; 8 const Obj = @import("obj.zig").Obj; 9 const Value = @import("value.zig").Value; 10 const GC = @import("gc.zig").GC; 11 12 pub fn Class(fields: anytype) type { 13 const Super = Obj(fields); 14 15 return packed struct { 16 const Self = @This(); 17 18 pub const Arg = void; 19 pub const Error = error{OutOfMemory}; 20 21 pub const Methods = table.Table(*Super.String, *Super.Function, hash.hash_t(*Super.String), Super.String.eql); 22 23 obj: Super, 24 methods: Packed(*Methods), 25 26 pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self { 27 const self: *Self = try allocator.create(Self); 28 self.* = Self{ 29 .obj = Super.make(Self), 30 .methods = try Packed(*Methods).create(allocator), 31 }; 32 return self; 33 } 34 35 pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { 36 return @ptrCast(self); 37 } 38 39 pub fn method(self: *Self, name: *Super.String) !union(enum) { 40 Static: *Super.Function, 41 Unbound: struct { 42 this: usize, 43 fun: *Super.Function, 44 45 pub fn bind(sel: *const @This(), gc: *GC, this: *Super.Instance) !*Super.Function { 46 var fun = try gc.emplace(.Function, GC.name_of(sel.fun.cast()), .{ 47 .chunk = sel.fun.chunk.ptr(), 48 .arity = sel.fun.arity, 49 .upvalues = @intCast(sel.fun.upvalues.len()), 50 }); 51 52 fun.upvalues.set(sel.fun.upvalues.ptr()); 53 54 var thi = Value.init(this.cast()); 55 56 fun.upvalues.ptr()[sel.this] = try gc.emplace(.Upvalue, null, .{ 57 .val = &thi, 58 .slot = 0, 59 .closed = true, 60 }); 61 62 return fun; 63 } 64 }, 65 } { 66 const met = try self.methods.ptr().get(name); 67 68 for (met.upvalues.ptr(), 0..) |upvalue, idx| { 69 if (upvalue == null) { 70 return .{ .Unbound = .{ .fun = met, .this = idx } }; 71 } 72 } 73 74 return .{ .Static = met }; 75 } 76 77 pub fn free(self: *const Self, allocator: std.mem.Allocator) void { 78 self.methods.destroy(allocator); 79 allocator.destroy(self); 80 } 81 }; 82 }