lib/accy/src/kernel/interpret/spec.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const dispatch = @import("layer.zig");
  2 const policy = @import("policy.zig");
  3 const program = @import("../program/root.zig");
  4 
  5 pub const Graph = struct {};
  6 
  7 pub fn graph() With(Graph) {
  8     return with(Graph{});
  9 }
 10 
 11 pub fn with(impl: anytype) With(@TypeOf(impl)) {
 12     return .{ .impl = impl };
 13 }
 14 
 15 pub fn InterpretSpec(comptime Initial: type) type {
 16     if (comptime @hasDecl(Initial, "attach")) return Initial;
 17     return With(Initial);
 18 }
 19 
 20 pub fn asSpec(initial: anytype) InterpretSpec(@TypeOf(initial)) {
 21     if (comptime @hasDecl(@TypeOf(initial), "attach")) return initial;
 22     return with(initial);
 23 }
 24 
 25 pub fn deinitIfPresent(value: anytype) void {
 26     const Value = @typeInfo(@TypeOf(value)).pointer.child;
 27     switch (@typeInfo(Value)) {
 28         .@"struct", .@"union", .@"enum", .@"opaque" => if (comptime @hasDecl(Value, "deinit")) value.deinit(),
 29         else => {},
 30     }
 31 }
 32 
 33 pub fn With(comptime Impl: type) type {
 34     return WithPolicy(Impl, policy.implUnhandled(Impl, policy.lower));
 35 }
 36 
 37 pub fn bind(impl: anytype) WithPolicy(@TypeOf(impl), policy.transparent) {
 38     return .{ .impl = impl };
 39 }
 40 
 41 pub fn bindIndexed(impl: anytype) WithPolicy(@TypeOf(impl), policy.indexed) {
 42     return .{ .impl = impl };
 43 }
 44 
 45 pub fn WithPolicy(comptime Impl: type, comptime unhandled: policy.Unhandled) type {
 46     return struct {
 47         impl: Impl,
 48 
 49         pub fn attach(self: @This(), next: anytype) Layer(@TypeOf(next), Impl, unhandled) {
 50             return .{
 51                 .next = next,
 52                 .impl = self.impl,
 53             };
 54         }
 55     };
 56 }
 57 
 58 pub fn stack(specs: anytype) Stack(@TypeOf(specs)) {
 59     return .{ .specs = specs };
 60 }
 61 
 62 pub fn Stack(comptime Specs: type) type {
 63     _ = stackLength(Specs);
 64     return struct {
 65         specs: Specs,
 66 
 67         pub fn attach(self: @This(), next: anytype) StackAttach(0, Specs, @TypeOf(next)) {
 68             return attachFrom(0, self.specs, next);
 69         }
 70     };
 71 }
 72 
 73 pub fn layer(next: anytype, impl: anytype) Layer(@TypeOf(next), @TypeOf(impl), policy.implUnhandled(@TypeOf(impl), policy.lower)) {
 74     return .{
 75         .next = next,
 76         .impl = impl,
 77     };
 78 }
 79 
 80 pub fn State(comptime Spec: type) type {
 81     return @TypeOf(@as(Spec, undefined).attach(@as(*program.Builder, undefined)));
 82 }
 83 
 84 pub fn Result(comptime Spec: type) type {
 85     return State(Spec).Result;
 86 }
 87 
 88 pub fn Layer(comptime Next: type, comptime Impl: type, comptime unhandled: policy.Unhandled) type {
 89     return dispatch.Layer(Next, Impl, unhandled);
 90 }
 91 
 92 fn stackLength(comptime Specs: type) comptime_int {
 93     const info = @typeInfo(Specs);
 94     if (info != .@"struct" or !info.@"struct".is_tuple) {
 95         @compileError("kernel.interpret.stack expects a tuple of interpreter specs");
 96     }
 97     if (info.@"struct".field_names.len == 0) {
 98         @compileError("kernel.interpret.stack expects at least one interpreter spec");
 99     }
100     return info.@"struct".field_names.len;
101 }
102 
103 fn StackAttach(comptime index: usize, comptime Specs: type, comptime Next: type) type {
104     const len = stackLength(Specs);
105     if (index == len) return Next;
106     const Spec = @typeInfo(Specs).@"struct".field_types[index];
107     return @TypeOf(@as(Spec, undefined).attach(@as(StackAttach(index + 1, Specs, Next), undefined)));
108 }
109 
110 fn attachFrom(comptime index: usize, specs: anytype, next: anytype) StackAttach(index, @TypeOf(specs), @TypeOf(next)) {
111     if (comptime index == stackLength(@TypeOf(specs))) return next;
112     const inner = attachFrom(index + 1, specs, next);
113     return @field(specs, @typeInfo(@TypeOf(specs)).@"struct".field_names[index]).attach(inner);
114 }