zig-webgpu-gen

git clone git://git.electrosoup.com/zig-webgpu-gen
Log | Files | Refs

commit afa0b976ab44e75e949913d694be891b3eb92191
parent 692eb741b4ae33f4f5f5d7c897ee1b95659a8df0
Author: Christian Ermann <christianermann@gmail.com>
Date:   Wed,  4 Mar 2026 21:16:05 -0800

Restructure

Diffstat:
Msrc/main.zig | 722+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 509 insertions(+), 213 deletions(-)

diff --git a/src/main.zig b/src/main.zig @@ -97,18 +97,6 @@ const PrimitiveType = enum { @"array<float32>", @"array<float64>", - pub fn isInt(self: PrimitiveType) bool { - return switch (self) { - .uint16 => true, - .uint32 => true, - .uint64 => true, - .usize => true, - .int16 => true, - .int32 => true, - else => false, - }; - } - pub fn isArray(self: PrimitiveType) bool { return switch (self) { .@"array<bool>" => true, @@ -142,47 +130,138 @@ const PrimitiveType = enum { .nullable_float32 => "f32", .float64 => "f64", .float64_supertype => "f64", - .@"array<bool>" => "Slice(bool)", - .@"array<string>" => "Slice(StringView)", - .@"array<uint16>" => "Slice(u16)", - .@"array<uint32>" => "Slice(u32)", - .@"array<uint64>" => "Slice(u64)", - .@"array<usize>" => "Slice(usize)", - .@"array<int16>" => "Slice(i16)", - .@"array<int32>" => "Slice(i32)", - .@"array<float32>" => "Slice(f32)", - .@"array<float64>" => "Slice(f64)", + .@"array<bool>" => "bool", + .@"array<string>" => "StringView", + .@"array<uint16>" => "u16", + .@"array<uint32>" => "u32", + .@"array<uint64>" => "u64", + .@"array<usize>" => "usize", + .@"array<int16>" => "i16", + .@"array<int32>" => "i32", + .@"array<float32>" => "f32", + .@"array<float64>" => "f64", }; } - fn toStringConst(self: PrimitiveType) ![]const u8 { - return switch (self) { - .@"array<bool>" => "Slice(bool)", - .@"array<string>" => "Slice(StringView)", - .@"array<uint16>" => "Slice(u16)", - .@"array<uint32>" => "Slice(u32)", - .@"array<uint64>" => "Slice(u64)", - .@"array<usize>" => "Slice(usize)", - .@"array<int16>" => "Slice(i16)", - .@"array<int32>" => "Slice(i32)", - .@"array<float32>" => "Slice(f32)", - .@"array<float64>" => "Slice(f64)", - else => error.Unimplemented, - }; - } - - pub fn render(self: PrimitiveType, writer: anytype) !void { + pub fn renderDefn( + self: PrimitiveType, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(": "); + if (optional) { + try writer.writeAll("?"); + } + if (self.isArray()) { + try writer.writeAll("[]"); + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("const "), + .mutable => {}, + } + } + } else { + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("*const "), + .mutable => try writer.writeAll("*"), + } + } + } try writer.writeAll(self.toString()); + try writer.writeAll(",\n"); } - pub fn renderConst(self: PrimitiveType, writer: anytype) !void { + pub fn renderExternDefn( + self: PrimitiveType, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { if (self.isArray()) { - try writer.writeAll(try self.toStringConst()); + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll("_len: usize,\n"); + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll("_ptr: "); + if (optional) { + try writer.writeAll("?"); + } + try writer.writeAll("[*]"); + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("const "), + .mutable => {}, + } + } + try writer.writeAll(self.toString()); + try writer.writeAll(",\n"); } else { - try writer.writeAll("const "); + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(": "); + if (optional) { + try writer.writeAll("?"); + } + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("*const "), + .mutable => try writer.writeAll("*"), + } + } try writer.writeAll(self.toString()); + try writer.writeAll(",\n"); + } + } + + pub fn renderExternCall( + self: PrimitiveType, + writer: anytype, + name: []const u8, + indent: u32, + ) !void { + if (self.isArray()) { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(".len,\n"); + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(".ptr,\n"); + } else { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(",\n"); } } + + fn renderReturn( + self: PrimitiveType, + writer: anytype, + optional: bool, + pointer: ?Pointer, + ) !void { + if (self.isArray()) { + return error.Unimplemented; + } + if (optional) { + try writer.writeAll("?"); + } + if (pointer) |ptr_type| { + try switch (ptr_type) { + .immutable => writer.writeAll("*const "), + .mutable => writer.writeAll("*"), + }; + } + try writer.writeAll(self.toString()); + } }; const ComplexType = union(enum) { @@ -210,41 +289,139 @@ const ComplexType = union(enum) { }; } - pub fn isPointer(self: ComplexType) bool { - return switch (self) { - .single => |inner| { - return inner.category == .object; + pub fn renderDefn( + self: ComplexType, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(": "); + if (optional) { + try writer.writeAll("?"); + } + switch (self) { + .single => |single| { + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("*const "), + .mutable => try writer.writeAll("*"), + } + } else if (single.category == .object) { + try writer.writeAll("*"); + } + try snakeToPascal(single.name, writer); }, - .array => |inner| { - return inner.category == .object; + .array => |array| { + try writer.writeAll("[]"); + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("const "), + .mutable => {}, + } + } + try snakeToPascal(array.name, writer); }, - }; + } + try writer.writeAll(",\n"); } - pub fn render(self: ComplexType, writer: anytype) !void { + pub fn renderExternDefn( + self: ComplexType, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { switch (self) { .single => |single| { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(": "); + if (optional) { + try writer.writeAll("?"); + } + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("*const "), + .mutable => try writer.writeAll("*"), + } + } else if (single.category == .object) { + try writer.writeAll("*"); + } try snakeToPascal(single.name, writer); + try writer.writeAll(",\n"); }, .array => |array| { - try writer.writeAll("Slice("); + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll("_len: usize,\n"); + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll("_ptr: "); + if (optional) { + try writer.writeAll("?"); + } + try writer.writeAll("[*]"); + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("const "), + .mutable => {}, + } + } try snakeToPascal(array.name, writer); - try writer.writeAll(")"); + try writer.writeAll(",\n"); }, } } - pub fn renderConst(self: ComplexType, writer: anytype) !void { + pub fn renderExternCall( + self: ComplexType, + writer: anytype, + name: []const u8, + indent: u32, + ) !void { + switch (self) { + .single => { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(",\n"); + }, + .array => { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(".len,\n"); + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(".ptr,\n"); + }, + } + } + + fn renderReturn( + self: ComplexType, + writer: anytype, + optional: bool, + pointer: ?Pointer, + ) !void { switch (self) { .single => |single| { - try writer.writeAll("const "); + if (optional) { + try writer.writeAll("?"); + } + if (pointer) |ptr_type| { + try switch (ptr_type) { + .immutable => writer.writeAll("*const "), + .mutable => writer.writeAll("*"), + }; + } try snakeToPascal(single.name, writer); }, - .array => |array| { - try writer.writeAll("Slice("); - try snakeToPascal(array.name, writer); - try writer.writeAll(")"); - }, + .array => return error.Unimplemented, } } @@ -299,9 +476,64 @@ const ComplexType = union(enum) { const CallbackType = struct { name: []const u8, - pub fn render(self: CallbackType, writer: anytype) !void { + pub fn renderDefn( + self: CallbackType, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(": "); + if (optional) { + try writer.writeAll("?"); + } + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("*const "), + .mutable => try writer.writeAll("*"), + } + } try snakeToPascal(self.name, writer); - try writer.writeAll("Callback"); + try writer.writeAll("Callback,\n"); + } + + pub fn renderExternDefn( + self: CallbackType, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(": "); + if (optional) { + try writer.writeAll("?"); + } + if (pointer) |ptr_type| { + switch (ptr_type) { + .immutable => try writer.writeAll("*const "), + .mutable => try writer.writeAll("*"), + } + } + try snakeToPascal(self.name, writer); + try writer.writeAll("Callback,\n"); + } + + pub fn renderExternCall( + self: CallbackType, + writer: anytype, + name: []const u8, + indent: u32, + ) !void { + _ = self; + try renderIndent(indent, writer); + try writer.writeAll(name); + try writer.writeAll(",\n"); } pub fn parse(raw: []const u8) ?CallbackType { @@ -339,43 +571,80 @@ const Type = union(enum) { complex: ComplexType, callback: CallbackType, - pub fn isInt(self: Type) bool { + pub fn isArray(self: Type) bool { return switch (self) { - .primitive => |inner| inner.isInt(), - .complex => false, + .primitive => |inner| inner.isArray(), + .complex => |inner| inner.isArray(), .callback => false, }; } - pub fn isArray(self: Type) bool { + pub fn renderDefn( + self: Type, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { return switch (self) { - .primitive => |inner| inner.isArray(), - .complex => |inner| inner.isArray(), - .callback => false, + inline else => |inner| inner.renderDefn( + writer, + name, + optional, + pointer, + indent + ), }; } - pub fn isPointer(self: Type) bool { + pub fn renderExternDefn( + self: Type, + writer: anytype, + name: []const u8, + optional: bool, + pointer: ?Pointer, + indent: u32, + ) !void { return switch (self) { - .primitive => false, - .complex => |inner| inner.isPointer(), - .callback => false, + inline else => |inner| inner.renderExternDefn( + writer, + name, + optional, + pointer, + indent + ), }; } - pub fn render(self: Type, writer: anytype) !void { + pub fn renderExternCall( + self: Type, + writer: anytype, + name: []const u8, + indent: u32, + ) !void { return switch (self) { - .primitive => |inner| inner.render(writer), - .complex => |inner| inner.render(writer), - .callback => |inner| inner.render(writer), + inline else => |inner| inner.renderExternCall( + writer, + name, + indent + ), }; } - pub fn renderConst(self: Type, writer: anytype) !void { + fn renderReturn( + self: Type, + writer: anytype, + optional: bool, + pointer: ?Pointer, + ) !void { return switch (self) { - .primitive => |inner| inner.renderConst(writer), - .complex => |inner| inner.renderConst(writer), - .callback => error.Unimplemented, + .callback => return error.Unimplemented, + inline else => |inner| inner.renderReturn( + writer, + optional, + pointer, + ), }; } @@ -456,46 +725,50 @@ const ParameterType = struct { optional: bool = false, default: ?DefaultValue = null, - fn renderAsParam(self: ParameterType, writer: anytype) !void { - try writer.writeAll(self.name); - try writer.writeAll(": "); - if (self.optional) { - try writer.writeAll("?"); - } - if (self.pointer) |pointer| { - if (!self.type.isArray()) { - try writer.writeAll("*"); - } - switch (pointer) { - .immutable => try self.type.renderConst(writer), - .mutable => try self.type.render(writer), - } - } else if (self.type.isPointer()) { - try writer.writeAll("*"); - try self.type.render(writer); - } else { - try self.type.render(writer); - } + fn isArray(self: ParameterType) bool { + return self.type.isArray(); } - fn renderAsArg(self: ParameterType, writer: anytype) !void { - if (self.pointer) |_| { - try writer.writeAll("@ptrCast("); - } else if (self.type.isPointer()) { - try writer.writeAll("@ptrCast("); - } - if (self.type.isInt()) { - try writer.writeAll("@intCast("); - } - try writer.writeAll(self.name); - if (self.pointer) |_| { - try writer.writeAll(")"); - } else if (self.type.isPointer()) { - try writer.writeAll(")"); - } - if (self.type.isInt()) { - try writer.writeAll(")"); - } + fn renderDefn( + self: ParameterType, + writer: anytype, + indent: u32, + ) !void { + try renderDoc(self, writer, indent); + try self.type.renderDefn( + writer, + self.name, + self.optional, + self.pointer, + indent + ); + } + + fn renderExternDefn( + self: ParameterType, + writer: anytype, + indent: u32, + ) !void { + try renderDoc(self, writer, indent); + try self.type.renderExternDefn( + writer, + self.name, + self.optional, + self.pointer, + indent + ); + } + + fn renderExternCall( + self: ParameterType, + writer: anytype, + indent: u32, + ) !void { + return self.type.renderExternCall( + writer, + self.name, + indent + ); } }; @@ -672,15 +945,44 @@ const Struct = struct { } if (self.members) |members| { for (members) |member| { - try renderDoc(member, writer, indent + 1); - try renderIndent(indent + 1, writer); - try member.renderAsParam(writer); - try writer.writeAll(",\n"); + try member.renderExternDefn(writer, indent + 1); + } + for (members) |member| { + if (member.isArray()) { + try writer.writeAll("\n"); + try self.renderInitMethod(writer, indent + 1); + break; + } } } try renderIndent(indent, writer); try writer.writeAll("};\n"); } + + fn renderInitMethod(self: Struct, writer: anytype, indent: u32) !void { + try renderIndent(indent, writer); + try writer.writeAll("pub fn init(\n"); + if (self.members) |members| { + for (members) |member| { + try member.renderDefn(writer, indent + 1); + } + } + try renderIndent(indent, writer); + try writer.writeAll(") "); + try snakeToPascal(self.name, writer); + try writer.writeAll(" {\n"); + try renderIndent(indent + 1, writer); + try writer.writeAll("return .{\n"); + if (self.members) |members| { + for (members) |member| { + try member.renderExternCall(writer, indent + 1); + } + } + try renderIndent(indent + 1, writer); + try writer.writeAll("};\n"); + try renderIndent(indent, writer); + try writer.writeAll("}\n"); + } }; const Callback = struct { @@ -696,9 +998,7 @@ const Callback = struct { try writer.writeAll("Callback = fn (\n"); if (self.args) |args| { for (args) |arg| { - try writer.writeAll(" "); - try arg.renderAsParam(writer); - try writer.writeAll(",\n"); + try arg.renderExternDefn(writer, 1); } } try writer.writeAll(") callconv(.C) void;\n"); @@ -713,23 +1013,11 @@ const ReturnType = struct { pointer: ?Pointer = null, pub fn render(self: ReturnType, writer: anytype) !void { - if (self.optional) { - try writer.writeAll("?"); - } - if (self.pointer) |pointer| { - if (!self.type.isArray()) { - try writer.writeAll("*"); - } - switch (pointer) { - .immutable => try self.type.renderConst(writer), - .mutable => try self.type.render(writer), - } - } else if (self.type.isPointer()) { - try writer.writeAll("*"); - try self.type.render(writer); - } else { - try self.type.render(writer); - } + try self.type.renderReturn( + writer, + self.optional, + self.pointer, + ); } }; @@ -741,7 +1029,7 @@ const Function = struct { callback: ?CallbackType = null, args: ?[]ParameterType = null, - fn renderArgsZig( + fn renderArgsExternDefn( self: Function, writer: anytype, object: ?[]const u8, @@ -755,14 +1043,12 @@ const Function = struct { } if (self.args) |args| { for (args) |arg| { - try renderIndent(indent, writer); - try arg.renderAsParam(writer); - try writer.writeAll(",\n"); + try arg.renderExternDefn(writer, indent); } } } - fn renderArgsC( + fn renderArgsExternCall( self: Function, writer: anytype, object: ?[]const u8, @@ -770,39 +1056,88 @@ const Function = struct { ) !void { if (object) |_| { try renderIndent(indent, writer); - try writer.writeAll("@ptrCast(self),\n"); + try writer.writeAll("self,\n"); } if (self.args) |args| { for (args) |arg| { - if (arg.type.isArray()) { - try renderIndent(indent, writer); - try writer.writeAll("@intCast("); - try writer.writeAll(arg.name); - try writer.writeAll(".len),\n"); - try renderIndent(indent, writer); - try writer.writeAll("@ptrCast("); - try writer.writeAll(arg.name); - try writer.writeAll(".ptr),\n"); - } else { - try renderIndent(indent, writer); - try arg.renderAsArg(writer); - try writer.writeAll(",\n"); - } + try arg.renderExternCall(writer, indent); + } + } + } + + fn renderArgsDefn( + self: Function, + writer: anytype, + object: ?[]const u8, + indent: u32 + ) !void { + if (object) |obj| { + try renderIndent(indent, writer); + try writer.writeAll("self: *"); + try snakeToPascal(obj, writer); + try writer.writeAll(",\n"); + } + if (self.args) |args| { + for (args) |arg| { + try arg.renderDefn(writer, indent); } } } - pub fn render( + fn renderExternDefn( + self: Function, + writer: anytype, + object: ?[]const u8, + indent: u32, + ) !void { + try renderDoc(self, writer, indent); + try renderIndent(indent, writer); + try writer.writeAll("extern fn wgpu"); + if (object) |obj| { + try snakeToPascal(obj, writer); + } + try snakeToPascal(self.name, writer); + try writer.writeAll("(\n"); + try self.renderArgsExternDefn(writer, object, indent + 1); + try renderIndent(indent, writer); + try writer.writeAll(") "); + if (self.returns) |returns| { + try returns.render(writer); + } else { + try writer.writeAll("void"); + } + try writer.writeAll(";\n"); + } + + fn renderExternCall( + self: Function, + writer: anytype, + object: ?[]const u8, + indent: u32, + ) !void { + try writer.writeAll("wgpu"); + if (object) |obj| { + try snakeToPascal(obj, writer); + } + try snakeToPascal(self.name, writer); + try writer.writeAll("(\n"); + try self.renderArgsExternCall(writer, object, indent + 1); + try renderIndent(indent, writer); + try writer.writeAll(");\n"); + } + + fn renderDefn( self: Function, writer: anytype, object: ?[]const u8, indent: u32, ) !void { + try renderDoc(self, writer, indent); try renderIndent(indent, writer); try writer.writeAll("pub fn "); try snakeToCamel(self.name, writer); try writer.writeAll("(\n"); - try self.renderArgsZig(writer, object, indent + 1); + try self.renderArgsDefn(writer, object, indent + 1); try renderIndent(indent, writer); try writer.writeAll(") "); if (self.returns) |returns| { @@ -812,29 +1147,10 @@ const Function = struct { } try writer.writeAll(" {\n"); try renderIndent(indent + 1, writer); - if (self.returns) |returns| { + if (self.returns) |_| { try writer.writeAll("return "); - if (returns.pointer) |_| { - try writer.writeAll("@ptrCast("); - } - if (returns.type.isInt()) { - try writer.writeAll("@intCast("); - } } - try writer.writeAll("c.wgpu"); - try snakeToPascal(self.name, writer); - try writer.writeAll("(\n"); - try self.renderArgsC(writer, object, indent + 2); - try renderIndent(indent + 1, writer); - if (self.returns) |returns| { - if (returns.pointer) |_| { - try writer.writeAll(")"); - } - if (returns.type.isInt()) { - try writer.writeAll(")"); - } - } - try writer.writeAll(");\n"); + try self.renderExternCall(writer, object, indent + 1); try renderIndent(indent, writer); try writer.writeAll("}\n"); } @@ -848,6 +1164,11 @@ const Object = struct { methods: []Function, pub fn render(self: Object, writer: anytype, indent: u32) !void { + for (self.methods) |method| { + try method.renderExternDefn(writer, self.name, indent); + try writer.writeAll("\n"); + } + try renderDoc(self, writer, indent); try renderIndent(indent, writer); try writer.writeAll("pub const "); @@ -855,7 +1176,7 @@ const Object = struct { try writer.writeAll(" = opaque {\n"); try renderIndent(indent, writer); for (self.methods) |method| { - try method.render(writer, self.name, indent + 1); + try method.renderDefn(writer, self.name, indent + 1); try writer.writeAll("\n"); } try writer.writeAll("};\n"); @@ -921,11 +1242,6 @@ fn renderHeader(writer: anytype) !void { \\ \\const std = @import("std"); \\ - \\const c = @cImport({ - \\ @cInclude("webgpu.h"); - \\ @cInclude("wgpu.h"); - \\}); - \\ \\pub const ChainedStruct = extern struct { \\ next: ?*const ChainedStruct, \\ struct_type: SType, @@ -956,26 +1272,6 @@ fn renderHeader(writer: anytype) !void { \\ } \\}; \\ - \\pub fn Slice(comptime T: type) type { - \\ return extern struct { - \\ len: usize, - \\ ptr: [*]T, - \\ - \\ const Self = @This(); - \\ - \\ pub fn fromSlice(slice: []T) Self { - \\ return .{ - \\ .ptr = slice.ptr, - \\ .len = slice.len, - \\ }; - \\ } - \\ - \\ pub fn toSlice(self: Self) []T { - \\ return self.ptr[0..self.len]; - \\ } - \\ }; - \\} - \\ ; try writer.writeAll(header); try writer.writeAll("\n"); @@ -1033,9 +1329,9 @@ pub fn main() !void { try callback.render(stdout); try stdout.writeAll("\n"); } - try stdout.writeAll("// functions\n"); + try stdout.writeAll("// extern functions\n"); for (parsed.value.functions) |function| { - try function.render(stdout, null, 0); + try function.renderExternDefn(stdout, null, 0); try stdout.writeAll("\n"); } try stdout.writeAll("// methods\n");