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

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const dispatch = @import("layer.zig");
 2 
 3 pub fn with(impl: anytype) With(@TypeOf(impl)) {
 4     return .{ .impl = impl };
 5 }
 6 
 7 pub fn bind(impl: anytype) With(@TypeOf(impl)) {
 8     return with(impl);
 9 }
10 
11 pub fn With(comptime Impl: type) type {
12     return struct {
13         impl: Impl,
14 
15         pub fn attach(self: @This(), next: anytype) Layer(stateValue(@TypeOf(next)), @TypeOf(next), Impl) {
16             return .{
17                 .next = next,
18                 .impl = self.impl,
19             };
20         }
21     };
22 }
23 
24 pub fn stack(specs: anytype) Stack(@TypeOf(specs)) {
25     return .{ .specs = specs };
26 }
27 
28 pub fn Stack(comptime Specs: type) type {
29     _ = stackLength(Specs);
30     return struct {
31         specs: Specs,
32 
33         pub fn attach(self: @This(), next: anytype) StackAttach(0, Specs, @TypeOf(next)) {
34             return attachFrom(0, self.specs, next);
35         }
36     };
37 }
38 
39 pub fn layer(comptime BoundValue: type, next: anytype, impl: anytype) Layer(BoundValue, @TypeOf(next), @TypeOf(impl)) {
40     return .{
41         .next = next,
42         .impl = impl,
43     };
44 }
45 
46 pub fn Layer(comptime BoundValue: type, comptime Next: type, comptime Impl: type) type {
47     return dispatch.Layer(BoundValue, Next, Impl);
48 }
49 
50 fn stateValue(comptime StateType: type) type {
51     return switch (@typeInfo(StateType)) {
52         .pointer => |info| info.child.Value,
53         else => StateType.Value,
54     };
55 }
56 
57 fn stackLength(comptime Specs: type) comptime_int {
58     const info = @typeInfo(Specs);
59     if (info != .@"struct" or !info.@"struct".is_tuple) {
60         @compileError("tensor.interpret.stack expects a tuple of interpreter specs");
61     }
62     if (info.@"struct".field_names.len == 0) {
63         @compileError("tensor.interpret.stack expects at least one interpreter spec");
64     }
65     return info.@"struct".field_names.len;
66 }
67 
68 fn StackAttach(comptime index: usize, comptime Specs: type, comptime Next: type) type {
69     const len = stackLength(Specs);
70     if (index == len) return Next;
71     const Spec = @typeInfo(Specs).@"struct".field_types[index];
72     return @TypeOf(@as(Spec, undefined).attach(@as(StackAttach(index + 1, Specs, Next), undefined)));
73 }
74 
75 fn attachFrom(comptime index: usize, specs: anytype, next: anytype) StackAttach(index, @TypeOf(specs), @TypeOf(next)) {
76     if (comptime index == stackLength(@TypeOf(specs))) return next;
77     const inner = attachFrom(index + 1, specs, next);
78     return @field(specs, @typeInfo(@TypeOf(specs)).@"struct".field_names[index]).attach(inner);
79 }