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

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 
 3 const policy = @import("policy.zig");
 4 const program = @import("../program/root.zig");
 5 const spec = @import("spec.zig");
 6 
 7 pub const ExclusionKind = enum {
 8     lifecycle,
 9     diagnostic_finish,
10     schedule_construction,
11 };
12 
13 pub const Exclusion = struct {
14     name: []const u8,
15     kind: ExclusionKind,
16 };
17 
18 pub const excluded_methods = [_]Exclusion{
19     .{ .name = "init", .kind = .lifecycle },
20     .{ .name = "deinit", .kind = .lifecycle },
21     .{ .name = "finishWithDiagnostic", .kind = .diagnostic_finish },
22     .{ .name = "axis", .kind = .schedule_construction },
23     .{ .name = "split", .kind = .schedule_construction },
24     .{ .name = "bind", .kind = .schedule_construction },
25     .{ .name = "vectorize", .kind = .schedule_construction },
26     .{ .name = "unroll", .kind = .schedule_construction },
27 };
28 
29 pub fn exclusion(comptime name: []const u8) ?Exclusion {
30     inline for (excluded_methods) |item| {
31         if (std.mem.eql(u8, item.name, name)) return item;
32     }
33     return null;
34 }
35 
36 pub fn supports(comptime name: []const u8) bool {
37     return isFnDecl(program.Builder, name) and exclusion(name) == null and @hasDecl(DefaultLayer(), name);
38 }
39 
40 pub fn assertLayerCoversBuilder(comptime LayerType: type) void {
41     assertExclusionsReferToBuilderMethods();
42     inline for (@typeInfo(program.Builder).@"struct".decl_names) |decl_name| {
43         if (!isFnDecl(program.Builder, decl_name)) continue;
44         if (exclusion(decl_name) != null) continue;
45         if (!@hasDecl(LayerType, decl_name)) {
46             @compileError("kernel.interpret.Layer missing typed builder method: " ++ decl_name);
47         }
48     }
49 }
50 
51 fn DefaultLayer() type {
52     return spec.Layer(*program.Builder, struct {}, policy.lower);
53 }
54 
55 fn assertExclusionsReferToBuilderMethods() void {
56     inline for (excluded_methods) |item| {
57         if (!isFnDecl(program.Builder, item.name)) {
58             @compileError("kernel.interpret surface exclusion is not a typed builder method: " ++ item.name);
59         }
60     }
61 }
62 
63 fn isFnDecl(comptime Type: type, comptime name: []const u8) bool {
64     if (!@hasDecl(Type, name)) return false;
65     return switch (@typeInfo(@TypeOf(@field(Type, name)))) {
66         .@"fn" => true,
67         else => false,
68     };
69 }
70 
71 test "kernel interpret Layer covers typed builder body surface" {
72     assertLayerCoversBuilder(DefaultLayer());
73     try std.testing.expect(supports("forScope"));
74     try std.testing.expect(supports("tan"));
75     try std.testing.expect(exclusion("axis").?.kind == .schedule_construction);
76 }