Split out TypeInfo to TypeInfo and DeclarationType

This commit is contained in:
Robin Voetter
2020-06-15 01:56:39 +02:00
parent e6884a4622
commit b113aad195
4 changed files with 54 additions and 44 deletions

View File

@@ -24,12 +24,14 @@ fn cmpFeatureLevels(a: FeatureLevel, b: FeatureLevel) std.math.Order {
const DeclarationResolver = struct { const DeclarationResolver = struct {
const DeclarationSet = std.StringHashMap(void); const DeclarationSet = std.StringHashMap(void);
const EnumExtensionMap = std.StringHashMap(std.ArrayList(reg.Enum.Field)); const EnumExtensionMap = std.StringHashMap(std.ArrayList(reg.Enum.Field));
const FieldMap = std.StringHashMap(reg.Enum.Value);
allocator: *Allocator, allocator: *Allocator,
reg_arena: *Allocator, reg_arena: *Allocator,
registry: *reg.Registry, registry: *reg.Registry,
declarations: DeclarationSet, declarations: DeclarationSet,
enum_extensions: EnumExtensionMap, enum_extensions: EnumExtensionMap,
field_map: FieldMap,
fn init(allocator: *Allocator, reg_arena: *Allocator, registry: *reg.Registry) DeclarationResolver { fn init(allocator: *Allocator, reg_arena: *Allocator, registry: *reg.Registry) DeclarationResolver {
return .{ return .{
@@ -38,6 +40,7 @@ const DeclarationResolver = struct {
.registry = registry, .registry = registry,
.declarations = DeclarationSet.init(allocator), .declarations = DeclarationSet.init(allocator),
.enum_extensions = EnumExtensionMap.init(allocator), .enum_extensions = EnumExtensionMap.init(allocator),
.field_map = FieldMap.init(allocator),
}; };
} }
@@ -47,6 +50,7 @@ const DeclarationResolver = struct {
kv.value.deinit(); kv.value.deinit();
} }
self.field_map.deinit();
self.enum_extensions.deinit(); self.enum_extensions.deinit();
self.declarations.deinit(); self.declarations.deinit();
} }
@@ -78,22 +82,20 @@ const DeclarationResolver = struct {
// If there are no extensions for this enum, assume its valid. // If there are no extensions for this enum, assume its valid.
const extensions = self.enum_extensions.get(name) orelse return; const extensions = self.enum_extensions.get(name) orelse return;
// Todo: cache this in DeclarationResolver self.field_map.clear();
var field_map = std.StringHashMap(reg.Enum.Value).init(self.allocator);
defer field_map.deinit();
for (base_enum.fields) |field| { for (base_enum.fields) |field| {
_ = try field_map.put(field.name, field.value); _ = try self.field_map.put(field.name, field.value);
} }
// Assume that if a field name clobbers, the value is the same // Assume that if a field name clobbers, the value is the same
for (extensions.value.items) |field| { for (extensions.value.items) |field| {
_ = try field_map.put(field.name, field.value); _ = try self.field_map.put(field.name, field.value);
} }
const new_fields = try self.reg_arena.alloc(reg.Enum.Field, field_map.count()); const new_fields = try self.reg_arena.alloc(reg.Enum.Field, self.field_map.count());
var it = field_map.iterator(); var it = self.field_map.iterator();
for (new_fields) |*field| { for (new_fields) |*field| {
const kv = it.next().?; const kv = it.next().?;
field.* = .{ field.* = .{

View File

@@ -8,7 +8,28 @@ pub const Registry = struct {
pub const Declaration = struct { pub const Declaration = struct {
name: []const u8, name: []const u8,
decl_type: TypeInfo, decl_type: DeclarationType,
};
pub const DeclarationType = union(enum) {
container: Container,
enumeration: Enum,
bitmask: Bitmask,
handle: Handle,
command: Command,
alias: Alias,
foreign: Foreign,
typedef: TypeInfo,
};
pub const Alias = struct {
pub const Target = enum {
other_command,
other_type,
};
name: []const u8,
target: Target,
}; };
pub const ApiConstant = struct { pub const ApiConstant = struct {
@@ -27,16 +48,11 @@ pub const Tag = struct {
}; };
pub const TypeInfo = union(enum) { pub const TypeInfo = union(enum) {
container: Container, name: []const u8,
enumeration: Enum, command_ptr: Command,
bitmask: Bitmask,
handle: Handle,
command: Command,
alias: []const u8, // Alias of another declaration
pointer: Pointer, pointer: Pointer,
array: Array, array: Array,
opaque, opaque,
foreign: Foreign
}; };
pub const Container = struct { pub const Container = struct {

View File

@@ -229,7 +229,7 @@ pub fn parseTypedef(allocator: *Allocator, xctok: *XmlCTokenizer) !registry.Decl
return registry.Declaration{ return registry.Declaration{
.name = decl.name orelse return error.MissingTypeIdentifier, .name = decl.name orelse return error.MissingTypeIdentifier,
.decl_type = decl.decl_type, .decl_type = .{.typedef = decl.decl_type},
}; };
} }
@@ -268,7 +268,7 @@ pub fn parseParamOrProto(allocator: *Allocator, xctok: *XmlCTokenizer) !registry
} }
return registry.Declaration{ return registry.Declaration{
.name = decl.name orelse return error.MissingTypeIdentifier, .name = decl.name orelse return error.MissingTypeIdentifier,
.decl_type = decl.decl_type, .decl_type = .{.typedef = decl.decl_type},
}; };
} }
@@ -307,7 +307,7 @@ fn parseDeclaration(allocator: *Allocator, xctok: *XmlCTokenizer) ParseError!Dec
if (tok.id != .type_name and tok.id != .id) return error.InvalidSyntax; if (tok.id != .type_name and tok.id != .id) return error.InvalidSyntax;
const type_name = tok.text; const type_name = tok.text;
var type_info = TypeInfo{.alias = type_name}; var type_info = TypeInfo{.name = type_name};
// Parse pointers // Parse pointers
type_info = try parsePointers(allocator, xctok, inner_is_const, type_info); type_info = try parsePointers(allocator, xctok, inner_is_const, type_info);
@@ -366,32 +366,24 @@ fn parseFnPtrSuffix(allocator: *Allocator, xctok: *XmlCTokenizer, return_type: T
_ = try xctok.expect(.rparen); _ = try xctok.expect(.rparen);
_ = try xctok.expect(.lparen); _ = try xctok.expect(.lparen);
const command = try allocator.create(registry.TypeInfo); const return_type_heap = try allocator.create(TypeInfo);
command.* = .{ return_type_heap.* = return_type;
.command = .{
.params = &[_]registry.Command.Param{},
.return_type = try allocator.create(TypeInfo),
.success_codes = &[_][]const u8{},
.error_codes = &[_][]const u8{},
}
};
command.command.return_type.* = return_type; var command_ptr = Declaration{
const command_ptr = Declaration{
.name = name.text, .name = name.text,
.decl_type = .{ .decl_type = .{
.pointer = .{ .command_ptr = .{
.is_const = true, .params = &[_]registry.Command.Param{},
.is_optional = false, .return_type = return_type_heap,
.size = .one, .success_codes = &[_][]const u8{},
.child = command, .error_codes = &[_][]const u8{},
} }
}, }
}; };
const first_param = try parseDeclaration(allocator, xctok); const first_param = try parseDeclaration(allocator, xctok);
if (first_param.name == null) { if (first_param.name == null) {
if (first_param.decl_type != .alias or !mem.eql(u8, first_param.decl_type.alias, "void")) { if (first_param.decl_type != .name or !mem.eql(u8, first_param.decl_type.name, "void")) {
return error.InvalidSyntax; return error.InvalidSyntax;
} }
@@ -423,7 +415,7 @@ fn parseFnPtrSuffix(allocator: *Allocator, xctok: *XmlCTokenizer, return_type: T
} }
_ = try xctok.nextNoEof(); _ = try xctok.nextNoEof();
command.command.params = params.toOwnedSlice(); command_ptr.decl_type.command_ptr.params = params.toOwnedSlice();
return command_ptr; return command_ptr;
} }

View File

@@ -103,7 +103,7 @@ fn parseBitmaskType(ty: *xml.Element) !registry.Declaration {
const alias = ty.getAttribute("alias") orelse return error.InvalidRegistry; const alias = ty.getAttribute("alias") orelse return error.InvalidRegistry;
return registry.Declaration{ return registry.Declaration{
.name = name, .name = name,
.decl_type = .{.alias = alias}, .decl_type = .{.alias = .{.name = alias, .target = .other_type}},
}; };
} else { } else {
return registry.Declaration{ return registry.Declaration{
@@ -119,7 +119,7 @@ fn parseHandleType(ty: *xml.Element) !registry.Declaration {
const alias = ty.getAttribute("alias") orelse return error.InvalidRegistry; const alias = ty.getAttribute("alias") orelse return error.InvalidRegistry;
return registry.Declaration{ return registry.Declaration{
.name = name, .name = name,
.decl_type = .{.alias = alias}, .decl_type = .{.alias = .{.name = alias, .target = .other_type}},
}; };
} else { } else {
const name = ty.getCharData("name") orelse return error.InvalidRegistry; const name = ty.getCharData("name") orelse return error.InvalidRegistry;
@@ -151,7 +151,7 @@ fn parseBaseType(allocator: *Allocator, ty: *xml.Element) !registry.Declaration
// macros, which is why this part is not built into the xml/c parser. // macros, which is why this part is not built into the xml/c parser.
return registry.Declaration{ return registry.Declaration{
.name = name, .name = name,
.decl_type = .{.opaque = {}}, .decl_type = .{.typedef = .{.opaque = {}}},
}; };
} }
} }
@@ -162,7 +162,7 @@ fn parseContainer(allocator: *Allocator, ty: *xml.Element, is_union: bool) !regi
if (ty.getAttribute("alias")) |alias| { if (ty.getAttribute("alias")) |alias| {
return registry.Declaration{ return registry.Declaration{
.name = name, .name = name,
.decl_type = .{.alias = alias}, .decl_type = .{.alias = .{.name = alias, .target = .other_type}},
}; };
} }
@@ -345,7 +345,7 @@ fn parseCommand(allocator: *Allocator, elem: *xml.Element) !registry.Declaration
const name = elem.getAttribute("name") orelse return error.InvalidRegistry; const name = elem.getAttribute("name") orelse return error.InvalidRegistry;
return registry.Declaration{ return registry.Declaration{
.name = name, .name = name,
.decl_type = .{.alias = alias} .decl_type = .{.alias = .{.name = alias, .target = .other_command}}
}; };
} }
@@ -360,13 +360,13 @@ fn parseCommand(allocator: *Allocator, elem: *xml.Element) !registry.Declaration
while (it.next()) |param| { while (it.next()) |param| {
var xctok = xmlc.XmlCTokenizer.init(param); var xctok = xmlc.XmlCTokenizer.init(param);
const decl = try xmlc.parseParamOrProto(allocator, &xctok); const decl = try xmlc.parseParamOrProto(allocator, &xctok);
params[i] = .{.name = decl.name, .param_type = decl.decl_type}; params[i] = .{.name = decl.name, .param_type = decl.decl_type.typedef};
try parsePointerMeta(&params[i].param_type, param); try parsePointerMeta(&params[i].param_type, param);
i += 1; i += 1;
} }
const return_type = try allocator.create(registry.TypeInfo); const return_type = try allocator.create(registry.TypeInfo);
return_type.* = command_decl.decl_type; return_type.* = command_decl.decl_type.typedef;
const success_codes = if (elem.getAttribute("successcodes")) |codes| const success_codes = if (elem.getAttribute("successcodes")) |codes|
try splitCommaAlloc(allocator, codes) try splitCommaAlloc(allocator, codes)