From c93e5a0fe2f9591a2ec2827a28922903cefb2261 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Thu, 9 Oct 2025 23:56:55 -0400 Subject: [PATCH] WIP rewriting generator for learning purposes --- src/main.zig | 4 + src/vulkan/render.zig | 192 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/src/main.zig b/src/main.zig index 7f4b39d..46da0ac 100644 --- a/src/main.zig +++ b/src/main.zig @@ -22,6 +22,7 @@ fn reportParseErrors(tree: std.zig.Ast) !void { } try w.writeAll("^\n"); } + try w.flush(); } fn oomPanic() noreturn { @@ -70,6 +71,9 @@ pub fn main() !void { ) catch |err| { std.process.fatal("failed to write to stdout: {s}", .{@errorName(err)}); }; + w.interface.flush() catch |err| { + std.process.fatal("failed to flush stdout: {s}", .{@errorName(err)}); + }; return; } else if (std.mem.eql(u8, arg, "-a") or std.mem.eql(u8, arg, "--api")) { const api_str = args.next() orelse { diff --git a/src/vulkan/render.zig b/src/vulkan/render.zig index a3982cc..6af36ed 100644 --- a/src/vulkan/render.zig +++ b/src/vulkan/render.zig @@ -335,6 +335,194 @@ pub fn trimVkNamespace(id: []const u8) []const u8 { return id; } +const Renderer2 = struct { + const Self = @This(); + + writer: *std.Io.Writer, + allocator: Allocator, + registry: *const reg.Registry, + id_renderer: *IdRenderer, + // decls_by_name: std.StringArrayHashMap(reg.DeclarationType), + // structure_types: std.StringHashMap(void), + have_video: bool, + + fn init( + writer: *std.Io.Writer, + allocator: Allocator, + registry: *const reg.Registry, + id_renderer: *IdRenderer, + have_video: bool, + ) !Self { + return Self{ + .writer = writer, + .allocator = allocator, + .registry = registry, + .id_renderer = id_renderer, + // .decls_by_name = decls_by_name, + // .structure_types = structure_types, + .have_video = have_video, + }; + } + + fn deinit(self: *Self) void { + _ = self; // autofix + // self.decls_by_name.deinit(); + } + + pub const Error = error{ + UnhandledBitfieldStruct, + InvalidApiConstant, + InvalidConstantExpr, + InvalidRegistry, + UnexpectedCharacter, + InvalidCharacter, + Overflow, + OutOfMemory, + WriteFailed, + }; + + fn render(self: *Self) Error!void { + try self.renderDecls(); + } + + fn text(self: *Self, str: []const u8) Error!void { + try self.writer.writeAll(str); + } + + fn print(self: *Self, comptime fmt: []const u8, args: anytype) Error!void { + try self.writer.print(fmt, args); + } + + fn idWithCase(self: *Self, case: CaseStyle, id: []const u8) Error!void { + try self.id_renderer.renderWithCase(self.writer, case, id); + } + + const _reserved_names = std.StaticStringMap([]const u8).initComptime(.{ + .{ "void", "void" }, + .{ "char", "u8" }, + .{ "float", "f32" }, + .{ "double", "f64" }, + .{ "uint8_t", "u8" }, + .{ "int8_t", "i8" }, + .{ "int16_t", "i16" }, + .{ "uint16_t", "u16" }, + .{ "uint32_t", "u32" }, + .{ "uint64_t", "u64" }, + .{ "int32_t", "i32" }, + .{ "int64_t", "i64" }, + .{ "size_t", "usize" }, + .{ "int", "c_int" }, + }); + + fn renderDecls(self: *Self) Error!void { + var arena = std.heap.ArenaAllocator.init(self.allocator); + defer arena.deinit(); + + for (self.registry.decls) |decl| { + defer _ = arena.reset(.retain_capacity); + + switch (decl.decl_type) { + .alias => |alias| { + switch (alias.target) { + .other_command => try self.print("pub const Pfn{s} = Pfn{s};\n", .{ + trimVkNamespace(decl.name), + trimVkNamespace(alias.name), + }), + .other_type => try self.print("pub const {s} = {s};\n", .{ + trimVkNamespace(decl.name), + trimVkNamespace(alias.name), + }), + } + }, + .handle => |handle| { + const backing_int = if (handle.is_dispatchable) "usize" else "u32"; + try self.print("pub const {s} = enum({s}) {{ null_handle = 0, _ }}; // parent {?s}\n", .{ + trimVkNamespace(decl.name), + backing_int, + handle.parent, + }); + }, + .typedef => |typ| { + try self.text("pub const "); + if (typ == .command_ptr) { + try self.text("Pfn"); + } + try self.text(trimVkNamespace(decl.name)); + try self.text(" = "); + try self.typeInfo(typ); + try self.text(";\n"); + }, + .foreign => |frn| { + if (_reserved_names.has(decl.name)) continue; + try self.print("pub const {s} = opaque {{}};", .{trimVkNamespace(decl.name)}); + if (frn.depends.len > 0) { + try self.print(" // requires \"{s}\"", .{frn.depends}); + } + try self.text("\n"); + }, + .command => |cmd| { + try self.text("pub const Pfn"); + try self.idWithCase(.title, trimVkNamespace(decl.name)); + try self.text(" = *const "); + try self.commandType(cmd); + try self.text(";\n"); + }, + else => try self.print("pub const {s} = undefined; // {s};\n", .{ + trimVkNamespace(decl.name), + @tagName(decl.decl_type), + }), + } + } + } + + fn commandType(self: *Self, cmd: reg.Command) Error!void { + try self.text("fn("); + for (cmd.params, 0..) |param, idx| { + if (idx > 0) try self.text(", "); + try self.idWithCase(.snake, param.name); + try self.text(": "); + try self.typeInfo(param.param_type); + } + try self.text(") void"); + } + + fn typeInfo(self: *Self, typ: reg.TypeInfo) Error!void { + switch (typ) { + .name => |name| { + if (_reserved_names.get(name)) |real| { + try self.text(real); + } else { + try self.text(trimVkNamespace(name)); + } + }, + .command_ptr => |cmd| { + try self.text("?*const "); + try self.commandType(cmd); + }, + .pointer => |ptr| { + if (ptr.is_optional) try self.text("?"); + switch (ptr.size) { + .one => try self.text("*"), + .many, .other_field => try self.text("[*]"), + .zero_terminated => try self.text("[*:0]"), + } + if (ptr.is_const) try self.text("const "); + try self.typeInfo(ptr.child.*); + }, + .array => |arr| { + if (arr.is_optional) try self.text("?"); + try self.text("["); + switch (arr.size) { + .int => |size| try self.print("{}", .{size}), + .alias => |_| @panic("Not implemented."), + } + try self.text("]"); + try self.typeInfo(arr.child.*); + }, + } + } +}; + const Renderer = struct { const Self = @This(); const RenderTypeInfoError = std.Io.Writer.Error || std.fmt.ParseIntError || error{ OutOfMemory, InvalidRegistry }; @@ -2141,7 +2329,9 @@ pub fn render( id_renderer: *IdRenderer, have_video: bool, ) !void { - var renderer = try Renderer.init(writer, allocator, registry, id_renderer, have_video); + // var renderer = try Renderer.init(writer, allocator, registry, id_renderer, have_video); + var renderer = try Renderer2.init(writer, allocator, registry, id_renderer, have_video); defer renderer.deinit(); try renderer.render(); + try writer.flush(); }