gen_kernel.zig (3627B)
1 const std = @import("std"); 2 3 // Minimal Node definition for the DAG format (no App variant for kernels) 4 const Node = union(enum(u8)) { 5 leaf, 6 stem: struct { child: u32 }, 7 fork: struct { left: u32, right: u32 }, 8 }; 9 10 fn parseLine(line: []const u8) !Node { 11 var it = std.mem.splitScalar(u8, std.mem.trim(u8, line, " \t\n\r"), ' '); 12 const tag = it.next() orelse return error.EmptyLine; 13 if (std.mem.eql(u8, tag, "leaf")) { 14 return .leaf; 15 } else if (std.mem.eql(u8, tag, "stem")) { 16 const child_str = it.next() orelse return error.MissingChild; 17 const child = try std.fmt.parseInt(u32, child_str, 10); 18 return .{ .stem = .{ .child = child } }; 19 } else if (std.mem.eql(u8, tag, "fork")) { 20 const left_str = it.next() orelse return error.MissingLeft; 21 const right_str = it.next() orelse return error.MissingRight; 22 const left = try std.fmt.parseInt(u32, left_str, 10); 23 const right = try std.fmt.parseInt(u32, right_str, 10); 24 return .{ .fork = .{ .left = left, .right = right } }; 25 } else { 26 return error.UnknownTag; 27 } 28 } 29 30 pub fn main(init: std.process.Init) !void { 31 const gpa = init.gpa; 32 const io = init.io; 33 34 const args = try init.minimal.args.toSlice(init.arena.allocator()); 35 if (args.len != 3) { 36 std.debug.print("Usage: gen_kernel <input.dag> <output.zig>\n", .{}); 37 std.process.exit(1); 38 } 39 40 const input_path = args[1]; 41 const output_path = args[2]; 42 43 const source = try std.Io.Dir.cwd().readFileAlloc(io, input_path, gpa, .limited(10 * 1024 * 1024)); 44 defer gpa.free(source); 45 46 var nodes = std.ArrayList(Node).empty; 47 defer nodes.deinit(gpa); 48 49 var it = std.mem.splitScalar(u8, source, '\n'); 50 const root_line = it.next() orelse return error.EmptyFile; 51 const root = try std.fmt.parseInt(u32, std.mem.trim(u8, root_line, " \t\n\r"), 10); 52 53 while (it.next()) |line| { 54 const trimmed = std.mem.trim(u8, line, " \t\n\r"); 55 if (trimmed.len == 0) continue; 56 const node = try parseLine(trimmed); 57 try nodes.append(gpa, node); 58 } 59 60 const file = try std.Io.Dir.cwd().createFile(io, output_path, .{}); 61 defer file.close(io); 62 63 var buf: [4096]u8 = undefined; 64 var writer = file.writer(io, &buf); 65 66 try writer.interface.writeAll("// Auto-generated from "); 67 try writer.interface.writeAll(input_path); 68 try writer.interface.writeAll("\n// Do not edit manually.\n\n"); 69 70 try writer.interface.writeAll("pub const NodeTag = enum(u8) { leaf = 0, stem = 1, fork = 2 };\n\n"); 71 try writer.interface.writeAll("pub const Node = union(NodeTag) {\n"); 72 try writer.interface.writeAll(" leaf,\n"); 73 try writer.interface.writeAll(" stem: struct { child: u32 },\n"); 74 try writer.interface.writeAll(" fork: struct { left: u32, right: u32 },\n"); 75 try writer.interface.writeAll("};\n\n"); 76 77 try writer.interface.print("pub const kernel_root: u32 = {d};\n\n", .{root}); 78 try writer.interface.writeAll("pub const kernel_nodes = [_]Node{\n"); 79 80 for (nodes.items) |node| { 81 switch (node) { 82 .leaf => try writer.interface.writeAll(" .leaf,\n"), 83 .stem => |s| try writer.interface.print(" .{{ .stem = .{{ .child = {d} }} }},\n", .{s.child}), 84 .fork => |f| try writer.interface.print(" .{{ .fork = .{{ .left = {d}, .right = {d} }} }},\n", .{f.left, f.right}), 85 } 86 } 87 88 try writer.interface.writeAll("};\n"); 89 try writer.flush(); 90 91 std.debug.print("Generated {d} kernel nodes, root={d} -> {s}\n", .{ nodes.items.len, root, output_path }); 92 }