93 lines
3.5 KiB
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 });
|
|
}
|