Files
tricu/ext/zig/tools/gen_kernel.zig

93 lines
3.5 KiB
Zig

const std = @import("std");
// Minimal Node definition for the DAG format (no App variant for kernels)
const Node = union(enum(u8)) {
leaf,
stem: struct { child: u32 },
fork: struct { left: u32, right: u32 },
};
fn parseLine(line: []const u8) !Node {
var it = std.mem.splitScalar(u8, std.mem.trim(u8, line, " \t\n\r"), ' ');
const tag = it.next() orelse return error.EmptyLine;
if (std.mem.eql(u8, tag, "leaf")) {
return .leaf;
} else if (std.mem.eql(u8, tag, "stem")) {
const child_str = it.next() orelse return error.MissingChild;
const child = try std.fmt.parseInt(u32, child_str, 10);
return .{ .stem = .{ .child = child } };
} else if (std.mem.eql(u8, tag, "fork")) {
const left_str = it.next() orelse return error.MissingLeft;
const right_str = it.next() orelse return error.MissingRight;
const left = try std.fmt.parseInt(u32, left_str, 10);
const right = try std.fmt.parseInt(u32, right_str, 10);
return .{ .fork = .{ .left = left, .right = right } };
} else {
return error.UnknownTag;
}
}
pub fn main(init: std.process.Init) !void {
const gpa = init.gpa;
const io = init.io;
const args = try init.minimal.args.toSlice(init.arena.allocator());
if (args.len != 3) {
std.debug.print("Usage: gen_kernel <input.dag> <output.zig>\n", .{});
std.process.exit(1);
}
const input_path = args[1];
const output_path = args[2];
const source = try std.Io.Dir.cwd().readFileAlloc(io, input_path, gpa, .limited(10 * 1024 * 1024));
defer gpa.free(source);
var nodes = std.ArrayList(Node).empty;
defer nodes.deinit(gpa);
var it = std.mem.splitScalar(u8, source, '\n');
const root_line = it.next() orelse return error.EmptyFile;
const root = try std.fmt.parseInt(u32, std.mem.trim(u8, root_line, " \t\n\r"), 10);
while (it.next()) |line| {
const trimmed = std.mem.trim(u8, line, " \t\n\r");
if (trimmed.len == 0) continue;
const node = try parseLine(trimmed);
try nodes.append(gpa, node);
}
const file = try std.Io.Dir.cwd().createFile(io, output_path, .{});
defer file.close(io);
var buf: [4096]u8 = undefined;
var writer = file.writer(io, &buf);
try writer.interface.writeAll("// Auto-generated from ");
try writer.interface.writeAll(input_path);
try writer.interface.writeAll("\n// Do not edit manually.\n\n");
try writer.interface.writeAll("pub const NodeTag = enum(u8) { leaf = 0, stem = 1, fork = 2 };\n\n");
try writer.interface.writeAll("pub const Node = union(NodeTag) {\n");
try writer.interface.writeAll(" leaf,\n");
try writer.interface.writeAll(" stem: struct { child: u32 },\n");
try writer.interface.writeAll(" fork: struct { left: u32, right: u32 },\n");
try writer.interface.writeAll("};\n\n");
try writer.interface.print("pub const kernel_root: u32 = {d};\n\n", .{root});
try writer.interface.writeAll("pub const kernel_nodes = [_]Node{\n");
for (nodes.items) |node| {
switch (node) {
.leaf => try writer.interface.writeAll(" .leaf,\n"),
.stem => |s| try writer.interface.print(" .{{ .stem = .{{ .child = {d} }} }},\n", .{s.child}),
.fork => |f| try writer.interface.print(" .{{ .fork = .{{ .left = {d}, .right = {d} }} }},\n", .{f.left, f.right}),
}
}
try writer.interface.writeAll("};\n");
try writer.flush();
std.debug.print("Generated {d} kernel nodes, root={d} -> {s}\n", .{ nodes.items.len, root, output_path });
}