lib/choir/src/core/operation/registration.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const interfaces = @import("../interfaces/root.zig");
  3 
  4 pub fn Methods(comptime Operation: type) type {
  5     return struct {
  6         pub fn getRegisteredInfo(self: *Operation) ?*const interfaces.OperationInfo {
  7             return self.name.resolveRegisteredInfo(self.context);
  8         }
  9 
 10         fn lookupRegisteredInfo(self: *const Operation) ?*const interfaces.OperationInfo {
 11             if (self.name.getRegisteredInfo()) |info| {
 12                 return info;
 13             }
 14             return self.context.lookupOperation(self.name.name);
 15         }
 16 
 17         pub fn getInherentAttributeNames(self: *const Operation) []const []const u8 {
 18             const info = lookupRegisteredInfo(self) orelse return &.{};
 19             return info.getInherentAttributeNames();
 20         }
 21 
 22         pub fn hasInherentAttributeName(self: *const Operation, name: []const u8) bool {
 23             const info = lookupRegisteredInfo(self) orelse return false;
 24             return info.hasInherentAttributeName(name);
 25         }
 26 
 27         pub fn isDiscardableAttrName(self: *const Operation, name: []const u8) bool {
 28             return !hasInherentAttributeName(self, name);
 29         }
 30 
 31         pub fn isRegistered(self: *Operation) bool {
 32             return getRegisteredInfo(self) != null;
 33         }
 34 
 35         pub fn getInterface(self: *Operation, comptime IFace: type) ?*const IFace.VTable {
 36             _ = self.name.resolveRegisteredInfo(self.context);
 37 
 38             if (self.name.getInterface(IFace)) |vtable| {
 39                 return vtable;
 40             }
 41 
 42             const fallbacks = self.context.dialect_registry.op_interface_fallbacks.lookup(IFace.id) orelse return null;
 43 
 44             const ns = self.name.getDialectNamespace();
 45             if (ns.len > 0) {
 46                 if (fallbacks.get(ns)) |fallback| {
 47                     if (fallback(self)) |vt_any| {
 48                         return @ptrCast(@alignCast(vt_any));
 49                     }
 50                 }
 51             }
 52 
 53             return null;
 54         }
 55 
 56         pub fn InterfaceHandle(comptime IFace: type) type {
 57             return struct {
 58                 op: *Operation,
 59                 vtable: *const IFace.VTable,
 60 
 61                 fn returnType(comptime fn_ptr_type: type) type {
 62                     const ptr_info = @typeInfo(fn_ptr_type);
 63                     const fn_type = switch (ptr_info) {
 64                         .pointer => |p| p.child,
 65                         else => @compileError("expected interface vtable field to be a function pointer"),
 66                     };
 67                     const fn_info = switch (@typeInfo(fn_type)) {
 68                         .@"fn" => |f| f,
 69                         else => @compileError("expected interface vtable field to be a function pointer"),
 70                     };
 71                     return fn_info.return_type orelse @compileError("generic interface vtable methods are not supported");
 72                 }
 73 
 74                 fn methodFnPtrType(comptime method: std.meta.FieldEnum(IFace.VTable)) type {
 75                     const dummy: IFace.VTable = undefined;
 76                     return @TypeOf(@field(dummy, @tagName(method)));
 77                 }
 78 
 79                 pub inline fn call(
 80                     self: @This(),
 81                     comptime method: std.meta.FieldEnum(IFace.VTable),
 82                     args: anytype,
 83                 ) returnType(methodFnPtrType(method)) {
 84                     const fn_ptr = @field(self.vtable, @tagName(method));
 85                     const op_any: *const anyopaque = @ptrCast(self.op);
 86                     return @call(.auto, fn_ptr, .{op_any} ++ args);
 87                 }
 88             };
 89         }
 90 
 91         pub fn interface(self: *Operation, comptime IFace: type) ?InterfaceHandle(IFace) {
 92             const vtable = getInterface(self, IFace) orelse return null;
 93             return .{ .op = self, .vtable = vtable };
 94         }
 95 
 96         pub fn hasInterface(self: *Operation, comptime IFace: type) bool {
 97             return getInterface(self, IFace) != null;
 98         }
 99 
100         pub fn getTraits(self: *Operation) interfaces.OperationTraits {
101             _ = self.name.resolveRegisteredInfo(self.context);
102             return self.name.getTraits();
103         }
104 
105         pub fn hasTrait(self: *Operation, comptime trait_field: []const u8) bool {
106             const traits = getTraits(self);
107             return @field(traits, trait_field);
108         }
109 
110         pub fn hasTraitId(self: *Operation, trait_id: interfaces.TraitId) bool {
111             _ = self.name.resolveRegisteredInfo(self.context);
112             return self.name.hasTraitId(trait_id);
113         }
114 
115         pub fn hasTraitName(self: *Operation, trait_name: []const u8) bool {
116             return hasTraitId(self, interfaces.traitIdRuntime(trait_name));
117         }
118     };
119 }