DzLox

:)
git clone https://git.sr.ht/~ashymad/DzLox
Log | Files | Refs | Submodules | LICENSE

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 }