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 }