lib/accy/src/tensor/interpret/execute.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 const graph_mod = @import("graph.zig");
4 const leaf = @import("leaf.zig");
5 const program_mod = @import("../root.zig").program;
6 const step_mod = @import("step.zig");
7
8 pub fn run(
9 allocator: std.mem.Allocator,
10 source: *const program_mod.Program,
11 initial: anytype,
12 ) !result(@TypeOf(initial)) {
13 var state = normalize(initial);
14 const State = @TypeOf(state);
15 const Value = State.Value;
16
17 const values = try allocator.alloc(Value, source.valueCount());
18 defer allocator.free(values);
19
20 for (source.operations) |*op| {
21 var step = step_mod.Step(Value){
22 .source = source,
23 .values = values,
24 .op = op,
25 };
26 values[op.id.index] = try state.operation(&step);
27 }
28
29 const outputs = try allocator.alloc(Value, source.outputs.len);
30 defer allocator.free(outputs);
31 for (source.outputs, 0..) |id, index| {
32 outputs[index] = values[id.index];
33 }
34
35 return try state.finish(outputs);
36 }
37
38 pub fn result(comptime Initial: type) type {
39 if (comptime @hasDecl(Initial, "attach")) return @TypeOf(@as(Initial, undefined).attach(@as(graph_mod.Graph, undefined))).Result;
40 return Normalized(Initial).Result;
41 }
42
43 fn normalize(initial: anytype) Normalized(@TypeOf(initial)) {
44 const Initial = @TypeOf(initial);
45 if (comptime @hasDecl(Initial, "operation")) return initial;
46 if (comptime @hasDecl(Initial, "Value")) return leaf.semantics(Initial.Value, initial);
47 @compileError("tensor leaf semantics must provide Value or use tensor.interpret.semantics(Value, impl)");
48 }
49
50 fn Normalized(comptime Initial: type) type {
51 if (comptime @hasDecl(Initial, "operation")) return Initial;
52 if (comptime @hasDecl(Initial, "Value")) return leaf.Semantics(Initial.Value, Initial);
53 @compileError("tensor leaf semantics must provide Value or use tensor.interpret.semantics(Value, impl)");
54 }