Fix a whole bunch of issues exposed by ziglang/zig#9191

This also includes a workaround for the fact that @"type" refers to the builtin
and not to a variable called "type". See ziglang/zig#2897.
This commit is contained in:
Robin Voetter
2021-06-24 02:11:36 +02:00
parent de0a048f45
commit 79d901a3e0
10 changed files with 82 additions and 75 deletions

View File

@@ -2,6 +2,41 @@ const std = @import("std");
const mem = std.mem;
const Allocator = mem.Allocator;
pub fn isZigPrimitiveType(name: []const u8) bool {
if (name.len > 1 and (name[0] == 'u' or name[0] == 'i')) {
for (name[1..]) |c| {
switch (c) {
'0'...'9' => {},
else => return false,
}
}
return true;
}
const primitives = [_][]const u8{ "void", "comptime_float", "comptime_int", "bool", "isize", "usize", "f16", "f32", "f64", "f128", "c_longdouble", "noreturn", "type", "anyerror", "c_short", "c_ushort", "c_int", "c_uint", "c_long", "c_ulong", "c_longlong", "c_ulonglong" };
for (primitives) |reserved| {
if (mem.eql(u8, reserved, name)) {
return true;
}
}
return false;
}
fn needZigEscape(name: []const u8) bool {
return !std.zig.fmt.isValidId(name) or isZigPrimitiveType(name);
}
pub fn writeIdentifier(out: anytype, id: []const u8) !void {
// https://github.com/ziglang/zig/issues/2897
if (isZigPrimitiveType(id)) {
try out.print("{s}_", .{id});
} else {
try out.print("{}", .{std.zig.fmtId(id)});
}
}
pub const CaseStyle = enum {
snake,
screaming_snake,
@@ -138,14 +173,10 @@ pub const IdRenderer = struct {
}
}
pub fn render(self: IdRenderer, out: anytype, id: []const u8) !void {
try out.print("{}", .{std.zig.fmtId(id)});
}
pub fn renderFmt(self: *IdRenderer, out: anytype, comptime fmt: []const u8, args: anytype) !void {
self.text_cache.items.len = 0;
try std.fmt.format(self.text_cache.writer(), fmt, args);
try out.print("{}", .{std.zig.fmtId(self.text_cache.items)});
try writeIdentifier(out, self.text_cache.items);
}
pub fn renderWithCase(self: *IdRenderer, out: anytype, case_style: CaseStyle, id: []const u8) !void {
@@ -162,7 +193,7 @@ pub const IdRenderer = struct {
.camel => try self.renderCamel(false, adjusted_id, tag),
}
try out.print("{}", .{std.zig.fmtId(self.text_cache.items)});
try writeIdentifier(out, self.text_cache.items);
}
pub fn getAuthorTag(self: IdRenderer, id: []const u8) ?[]const u8 {

View File

@@ -1,6 +1,5 @@
pub const generateVk = @import("vulkan/generator.zig").generate;
pub const VkGenerateStep = @import("vulkan/build_integration.zig").GenerateStep;
pub const generateSpirv = @import("spirv/generator.zig").generate;
pub const ShaderCompileStep = @import("build_integration.zig").ShaderCompileStep;
test "main" {

View File

@@ -5,7 +5,6 @@ const usage = "Usage: {s} [-h|--help] <spec xml path> <output zig source>\n";
pub fn main() !void {
const stderr = std.io.getStdErr();
const stdout = std.io.getStdOut();
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();

View File

@@ -514,7 +514,7 @@ pub fn parseVersion(xctok: *XmlCTokenizer) ![4][]const u8 {
return error.InvalidVersion;
}
const name = try xctok.expect(.name);
_ = try xctok.expect(.name);
const vk_make_version = try xctok.expect(.type_name);
if (!mem.eql(u8, vk_make_version.text, "VK_MAKE_API_VERSION")) {
return error.NotVersion;

View File

@@ -171,7 +171,7 @@ pub const Generator = struct {
if (e.is_bitmask and seen_bits.get(decl.name) == null)
continue;
},
else => {}
else => {},
}
self.registry.decls[i] = decl;
i += 1;

View File

@@ -74,7 +74,7 @@ fn parseTypes(allocator: *Allocator, out: []registry.Declaration, types_elem: *x
} else if (mem.eql(u8, category, "funcpointer")) {
break :blk try parseFuncPointer(allocator, ty);
} else if (mem.eql(u8, category, "enum")) {
break :blk (try parseEnumAlias(allocator, ty)) orelse continue;
break :blk (try parseEnumAlias(ty)) orelse continue;
}
continue;
@@ -297,7 +297,7 @@ fn parsePointerMeta(fields: Fields, type_info: *registry.TypeInfo, elem: *xml.El
}
}
fn parseEnumAlias(allocator: *Allocator, elem: *xml.Element) !?registry.Declaration {
fn parseEnumAlias(elem: *xml.Element) !?registry.Declaration {
if (elem.getAttribute("alias")) |alias| {
const name = elem.getAttribute("name") orelse return error.InvalidRegistry;
return registry.Declaration{

View File

@@ -40,7 +40,7 @@ const preamble =
\\ return fromInt(toInt(lhs) & toInt(rhs));
\\ }
\\ pub fn complement(self: FlagsType) FlagsType {
\\ return fromInt(~toInt(lhs));
\\ return fromInt(~toInt(self));
\\ }
\\ pub fn subtract(lhs: FlagsType, rhs: FlagsType) FlagsType {
\\ return fromInt(toInt(lhs) & toInt(rhs.complement()));
@@ -214,7 +214,7 @@ fn Renderer(comptime WriterType: type) type {
}
fn writeIdentifier(self: Self, id: []const u8) !void {
try self.id_renderer.render(self.writer, id);
try id_render.writeIdentifier(self.writer, id);
}
fn writeIdentifierWithCase(self: *Self, case: CaseStyle, id: []const u8) !void {
@@ -242,7 +242,7 @@ fn Renderer(comptime WriterType: type) type {
}
}
fn extractBitflagFieldName(self: Self, bitflag_name: BitflagName, field_name: []const u8) ![]const u8 {
fn extractBitflagFieldName(bitflag_name: BitflagName, field_name: []const u8) ![]const u8 {
var flag_it = id_render.SegmentIterator.init(bitflag_name.base_name);
var field_it = id_render.SegmentIterator.init(field_name);
@@ -295,16 +295,6 @@ fn Renderer(comptime WriterType: type) type {
return mem.endsWith(u8, base_name, "Flags");
}
fn containerHasField(self: Self, container: *const reg.Container, field_name: []const u8) bool {
for (container.fields) |field| {
if (mem.eql(u8, field, field_name)) {
return true;
}
}
return false;
}
fn isInOutPointer(self: Self, ptr: reg.Pointer) !bool {
if (ptr.child.* != .name) {
return false;
@@ -373,7 +363,7 @@ fn Renderer(comptime WriterType: type) type {
}
},
.name => |name| {
if ((try self.extractBitflagName(param.param_type.name)) != null or self.isFlags(param.param_type.name)) {
if ((try self.extractBitflagName(name)) != null or self.isFlags(name)) {
return .bitflags;
}
},
@@ -387,7 +377,7 @@ fn Renderer(comptime WriterType: type) type {
return .other;
}
fn classifyCommandDispatch(self: Self, name: []const u8, command: reg.Command) CommandDispatchType {
fn classifyCommandDispatch(name: []const u8, command: reg.Command) CommandDispatchType {
const device_handles = std.ComptimeStringMap(void, .{
.{ "VkDevice", {} },
.{ "VkCommandBuffer", {} },
@@ -710,37 +700,6 @@ fn Renderer(comptime WriterType: type) type {
try self.writeIdentifierWithCase(.snake, try self.extractEnumFieldName(name, field_name));
}
fn renderEnumerationValue(self: *Self, enum_name: []const u8, enumeration: reg.Enum, value: reg.Enum.Value) !void {
var current_value = value;
var maybe_alias_of: ?[]const u8 = null;
while (true) {
switch (current_value) {
.int => |int| try self.writer.print(" = {}, ", .{int}),
.bitpos => |pos| try self.writer.print(" = 1 << {}, ", .{pos}),
.bit_vector => |bv| try self.writer.print("= 0x{X}, ", .{bv}),
.alias => |alias| {
// Find the alias
current_value = for (enumeration.fields) |field| {
if (mem.eql(u8, field.name, alias.name)) {
maybe_alias_of = field.name;
break field.value;
}
} else return error.InvalidRegistry; // There is no alias
continue;
},
}
break;
}
if (maybe_alias_of) |alias_of| {
try self.writer.writeAll("// alias of ");
try self.renderEnumFieldName(enum_name, alias_of);
try self.writer.writeByte('\n');
}
}
fn renderEnumeration(self: *Self, name: []const u8, enumeration: reg.Enum) !void {
if (enumeration.is_bitmask) {
try self.renderBitmaskBits(name, enumeration);
@@ -749,17 +708,37 @@ fn Renderer(comptime WriterType: type) type {
try self.writer.writeAll("pub const ");
try self.renderName(name);
try self.writer.writeAll(" = extern enum(i32) {");
try self.writer.writeAll(" = enum(c_int) {");
for (enumeration.fields) |field| {
if (field.value == .alias and field.value.alias.is_compat_alias)
if (field.value == .alias)
continue;
try self.renderEnumFieldName(name, field.name);
try self.renderEnumerationValue(name, enumeration, field.value);
switch (field.value) {
.int => |int| try self.writer.print(" = {}, ", .{int}),
.bitpos => |pos| try self.writer.print(" = 1 << {}, ", .{pos}),
.bit_vector => |bv| try self.writer.print("= 0x{X}, ", .{bv}),
.alias => unreachable,
}
}
try self.writer.writeAll("_,};\n");
try self.writer.writeAll("_,");
for (enumeration.fields) |field| {
if (field.value != .alias or field.value.alias.is_compat_alias)
continue;
try self.writer.writeAll("pub const ");
try self.renderEnumFieldName(name, field.name);
try self.writer.writeAll(" = ");
try self.renderName(name);
try self.writer.writeByte('.');
try self.renderEnumFieldName(name, field.value.alias.name);
try self.writer.writeAll(";\n");
}
try self.writer.writeAll("};\n");
}
fn bitmaskFlagsType(bitwidth: u8) ![]const u8 {
@@ -797,7 +776,7 @@ fn Renderer(comptime WriterType: type) type {
for (flags_by_bitpos[0..bits.bitwidth]) |maybe_flag_name, bitpos| {
if (maybe_flag_name) |flag_name| {
const field_name = try self.extractBitflagFieldName(bitflag_name, flag_name);
const field_name = try extractBitflagFieldName(bitflag_name, flag_name);
try self.writeIdentifierWithCase(.snake, field_name);
} else {
try self.writer.print("_reserved_bit_{}", .{bitpos});
@@ -843,7 +822,7 @@ fn Renderer(comptime WriterType: type) type {
try self.writer.writeAll("pub const ");
try self.renderName(name);
try self.writer.print(" = extern enum({s}) {{null_handle = 0, _}};\n", .{backing_type});
try self.writer.print(" = enum({s}) {{null_handle = 0, _}};\n", .{backing_type});
}
fn renderAlias(self: *Self, name: []const u8, alias: reg.Alias) !void {
@@ -948,7 +927,7 @@ fn Renderer(comptime WriterType: type) type {
for (self.registry.decls) |decl| {
if (decl.decl_type == .command) {
const command = decl.decl_type.command;
if (self.classifyCommandDispatch(decl.name, command) == dispatch_type) {
if (classifyCommandDispatch(decl.name, command) == dispatch_type) {
try self.renderWrapper(decl.name, decl.decl_type.command);
}
}
@@ -1208,13 +1187,13 @@ fn Renderer(comptime WriterType: type) type {
try self.writer.writeAll(") {\n");
for (command.success_codes) |success| {
try self.writer.writeByte('.');
try self.writer.writeAll("Result.");
try self.renderEnumFieldName("VkResult", success);
try self.writer.writeAll(" => {},");
}
for (command.error_codes) |err| {
try self.writer.writeByte('.');
try self.writer.writeAll("Result.");
try self.renderEnumFieldName("VkResult", err);
try self.writer.writeAll(" => return error.");
try self.renderResultAsErrorName(err);