From 3ea364413ba8dfe121b6f03d6f5e87116a59def6 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 14 Jul 2024 10:04:00 -0700 Subject: [PATCH] objc-generator: move to github.com/hexops/mach-objc Signed-off-by: Stephen Gutekanst --- src/mach/objc-generator/main.zig | 1932 -------------------------- src/mach/objc-generator/registry.zig | 240 ---- 2 files changed, 2172 deletions(-) delete mode 100644 src/mach/objc-generator/main.zig delete mode 100644 src/mach/objc-generator/registry.zig diff --git a/src/mach/objc-generator/main.zig b/src/mach/objc-generator/main.zig deleted file mode 100644 index ee32a67c..00000000 --- a/src/mach/objc-generator/main.zig +++ /dev/null @@ -1,1932 +0,0 @@ -const std = @import("std"); -const reg = @import("registry.zig"); - -const Container = reg.Container; -const Enum = reg.Enum; -const EnumValue = reg.EnumValue; -const Method = reg.Method; -const Param = reg.Param; -const Property = reg.Property; -const Registry = reg.Registry; -const Type = reg.Type; -const TypeParam = reg.TypeParam; - -var registry: Registry = undefined; - -// ------------------------------------------------------------------------------------------------ -pub const ParseError = error{ UnexpectedCharacter, UnexpectedToken }; - -pub const Token = struct { - kind: Kind, - text: []const u8, - - const Kind = enum { - int, - id, - dot, - comma, - lparen, - rparen, - lbracket, - rbracket, - less, - greater, - caret, - star, - quote, - kw_bool, - kw_char, - kw_class, - kw_const, - kw_double, - kw_float, - kw_id, - kw_imp, - kw_instancetype, - kw_int, - kw_int8_t, - kw_int16_t, - kw_int32_t, - kw_int64_t, - kw_kindof, - kw_long, - kw_nonnull, - kw_nullable, - kw_null_unspecified, - kw_nullable_result, - kw_short, - kw_sel, - kw_struct, - kw_unsigned, - kw_uint, - kw_uint8_t, - kw_uint16_t, - kw_uint32_t, - kw_uint64_t, - kw_void, - eof, - }; -}; - -fn isdigit(c: u8) bool { - switch (c) { - '0'...'9' => return true, - else => return false, - } -} - -fn isalnum(c: u8) bool { - switch (c) { - 'a'...'z', 'A'...'Z', '0'...'9' => return true, - else => return false, - } -} - -pub const Lexer = struct { - const Self = @This(); - - source: []const u8, - offset: usize = 0, - - pub fn next(self: *Self) !Token { - while (true) { - const start = self.offset; - var c = self.peek(); - switch (c) { - ' ', '\t', '\n', '\r' => { - self.skip(); - }, - '0'...'9' => { - self.skip(); - c = self.peek(); - while (isdigit(c)) { - self.skip(); - c = self.peek(); - } - - return self.token(Token.Kind.int, start); - }, - 'a'...'z', 'A'...'Z', '_' => { - self.skip(); - c = self.peek(); - while (isalnum(c) or c == '_') { - self.skip(); - c = self.peek(); - } - - const text = self.source[start..self.offset]; - const kind = if (std.mem.eql(u8, text, "BOOL")) - Token.Kind.kw_bool - else if (std.mem.eql(u8, text, "char")) - Token.Kind.kw_char - else if (std.mem.eql(u8, text, "Class")) - Token.Kind.kw_class - else if (std.mem.eql(u8, text, "const")) - Token.Kind.kw_const - else if (std.mem.eql(u8, text, "double")) - Token.Kind.kw_double - else if (std.mem.eql(u8, text, "float")) - Token.Kind.kw_float - else if (std.mem.eql(u8, text, "id")) - Token.Kind.kw_id - else if (std.mem.eql(u8, text, "IMP")) - Token.Kind.kw_imp - else if (std.mem.eql(u8, text, "instancetype")) - Token.Kind.kw_instancetype - else if (std.mem.eql(u8, text, "int")) - Token.Kind.kw_int - else if (std.mem.eql(u8, text, "int8_t")) - Token.Kind.kw_int8_t - else if (std.mem.eql(u8, text, "int16_t")) - Token.Kind.kw_int16_t - else if (std.mem.eql(u8, text, "int32_t")) - Token.Kind.kw_int32_t - else if (std.mem.eql(u8, text, "int64_t")) - Token.Kind.kw_int64_t - else if (std.mem.eql(u8, text, "__kindof")) - Token.Kind.kw_kindof - else if (std.mem.eql(u8, text, "long")) - Token.Kind.kw_long - else if (std.mem.eql(u8, text, "_Nonnull")) - Token.Kind.kw_nonnull - else if (std.mem.eql(u8, text, "_Nullable")) - Token.Kind.kw_nullable - else if (std.mem.eql(u8, text, "_Null_unspecified")) - Token.Kind.kw_null_unspecified - else if (std.mem.eql(u8, text, "_Nullable_result")) - Token.Kind.kw_nullable_result - else if (std.mem.eql(u8, text, "SEL")) - Token.Kind.kw_sel - else if (std.mem.eql(u8, text, "short")) - Token.Kind.kw_short - else if (std.mem.eql(u8, text, "struct")) - Token.Kind.kw_struct - else if (std.mem.eql(u8, text, "uint8_t")) - Token.Kind.kw_uint8_t - else if (std.mem.eql(u8, text, "uint16_t")) - Token.Kind.kw_uint16_t - else if (std.mem.eql(u8, text, "uint32_t")) - Token.Kind.kw_uint32_t - else if (std.mem.eql(u8, text, "uint64_t")) - Token.Kind.kw_uint64_t - else if (std.mem.eql(u8, text, "unsigned")) - Token.Kind.kw_unsigned - else if (std.mem.eql(u8, text, "void")) - Token.Kind.kw_void - else - Token.Kind.id; - - return self.token(kind, start); - }, - '(' => { - self.skip(); - return self.token(Token.Kind.lparen, start); - }, - ')' => { - self.skip(); - return self.token(Token.Kind.rparen, start); - }, - '[' => { - self.skip(); - return self.token(Token.Kind.lbracket, start); - }, - ']' => { - self.skip(); - return self.token(Token.Kind.rbracket, start); - }, - '<' => { - self.skip(); - return self.token(Token.Kind.less, start); - }, - '>' => { - self.skip(); - return self.token(Token.Kind.greater, start); - }, - '^' => { - self.skip(); - return self.token(Token.Kind.caret, start); - }, - '*' => { - self.skip(); - return self.token(Token.Kind.star, start); - }, - '"' => { - self.skip(); - return self.token(Token.Kind.quote, start); - }, - ',' => { - self.skip(); - return self.token(Token.Kind.comma, start); - }, - '.' => { - self.skip(); - return self.token(Token.Kind.dot, start); - }, - 0 => { - return self.token(Token.Kind.eof, start); - }, - else => { - std.debug.print("Unexpected character {c} {}\n", .{ c, c }); - std.debug.print("Parsing {s}\n", .{self.source}); - return error.UnexpectedCharacter; - }, - } - } - } - - fn skip(self: *Self) void { - self.offset += 1; - } - - fn peek(self: *Self) u8 { - if (self.offset < self.source.len) { - return self.source[self.offset]; - } else { - return 0; - } - } - - fn token(self: *Self, kind: Token.Kind, start: usize) Token { - return Token{ .kind = kind, .text = self.source[start..self.offset] }; - } -}; - -pub const Parser = struct { - const Self = @This(); - const PointerProps = struct { is_const: bool, is_optional: bool }; - - allocator: std.mem.Allocator, - lookahead: Token, - lexer: *Lexer, - - pub fn init(allocator: std.mem.Allocator, lexer: *Lexer) !Parser { - return Parser{ .allocator = allocator, .lookahead = try lexer.next(), .lexer = lexer }; - } - - pub fn parseType(self: *Self) !Type { - if (self.lookahead.kind == .id) { - const text = self.lookahead.text; - if (std.mem.eql(u8, text, "API_AVAILABLE")) { - try self.match(.id); - try self.skipParenContent(); - } else if (std.mem.eql(u8, text, "API_UNAVAILABLE")) { - try self.match(.id); - try self.skipParenContent(); - } else if (std.mem.eql(u8, text, "API_DEPRECATED_WITH_REPLACEMENT")) { - try self.match(.id); - try self.skipParenContent(); - } else if (std.mem.eql(u8, text, "NS_SWIFT_UNAVAILABLE")) { - try self.match(.id); - try self.skipParenContent(); - } else if (std.mem.eql(u8, text, "NS_SWIFT_UNAVAILABLE_FROM_ASYNC")) { - try self.match(.id); - try self.skipParenContent(); - } - } - const is_const = self.lookahead.kind == .kw_const; - if (is_const) - try self.match(.kw_const); - - // TODO - what does this mean? - if (self.lookahead.kind == .kw_kindof) - try self.match(.kw_kindof); - - switch (self.lookahead.kind) { - .kw_void => { - try self.match(.kw_void); - return self.parseTypeSuffix(.{ .void = {} }, is_const, false); - }, - .kw_bool => { - try self.match(.kw_bool); - return self.parseTypeSuffix(.{ .bool = {} }, is_const, false); - }, - .kw_char => { - try self.match(.kw_char); - return self.parseTypeSuffix(.{ .uint = 8 }, is_const, false); - }, - .kw_short => { - try self.match(.kw_short); - return self.parseTypeSuffix(.{ .c_short = {} }, is_const, false); - }, - .kw_int => { - try self.match(.kw_int); - return self.parseTypeSuffix(.{ .c_int = {} }, is_const, false); - }, - .kw_long => { - try self.match(.kw_long); - if (self.lookahead.kind == .kw_long) { - try self.match(.kw_long); - return self.parseTypeSuffix(.{ .c_longlong = {} }, is_const, false); - } else { - return self.parseTypeSuffix(.{ .c_long = {} }, is_const, false); - } - }, - .kw_unsigned => { - try self.match(.kw_unsigned); - switch (self.lookahead.kind) { - .kw_char => { - try self.match(.kw_char); - return self.parseTypeSuffix(.{ .uint = 8 }, is_const, false); - }, - .kw_short => { - try self.match(.kw_short); - return self.parseTypeSuffix(.{ .c_ushort = {} }, is_const, false); - }, - .kw_int => { - try self.match(.kw_int); - return self.parseTypeSuffix(.{ .c_uint = {} }, is_const, false); - }, - .kw_long => { - try self.match(.kw_long); - if (self.lookahead.kind == .kw_long) { - try self.match(.kw_long); - return self.parseTypeSuffix(.{ .c_ulonglong = {} }, is_const, false); - } else { - return self.parseTypeSuffix(.{ .c_ulong = {} }, is_const, false); - } - }, - else => { - return self.parseTypeSuffix(.{ .c_uint = {} }, is_const, false); - }, - } - }, - .kw_int8_t => { - try self.match(.kw_int8_t); - return self.parseTypeSuffix(.{ .int = 8 }, is_const, false); - }, - .kw_int16_t => { - try self.match(.kw_int16_t); - return self.parseTypeSuffix(.{ .int = 16 }, is_const, false); - }, - .kw_int32_t => { - try self.match(.kw_int32_t); - return self.parseTypeSuffix(.{ .int = 32 }, is_const, false); - }, - .kw_int64_t => { - try self.match(.kw_int64_t); - return self.parseTypeSuffix(.{ .int = 64 }, is_const, false); - }, - .kw_uint => { - try self.match(.kw_uint); - return self.parseTypeSuffix(.{ .uint = 32 }, is_const, false); - }, - .kw_uint8_t => { - try self.match(.kw_uint8_t); - return self.parseTypeSuffix(.{ .uint = 8 }, is_const, false); - }, - .kw_uint16_t => { - try self.match(.kw_uint16_t); - return self.parseTypeSuffix(.{ .uint = 16 }, is_const, false); - }, - .kw_uint32_t => { - try self.match(.kw_uint32_t); - return self.parseTypeSuffix(.{ .uint = 32 }, is_const, false); - }, - .kw_uint64_t => { - try self.match(.kw_uint64_t); - return self.parseTypeSuffix(.{ .uint = 64 }, is_const, false); - }, - .kw_float => { - try self.match(.kw_float); - return self.parseTypeSuffix(.{ .float = 32 }, is_const, false); - }, - .kw_double => { - try self.match(.kw_double); - return self.parseTypeSuffix(.{ .float = 64 }, is_const, false); - }, - .kw_class => { - try self.match(.kw_class); - const props = try self.parsePointerProps(is_const); - - const t = Type{ .name = "c.objc_class" }; - - const child = try self.allocator.create(Type); - child.* = t; - - return Type{ .pointer = .{ - .is_single = true, - .is_const = props.is_const, - .is_optional = props.is_optional, - .child = child, - } }; - }, - .kw_sel => { - try self.match(.kw_sel); - const t = Type{ .name = "c.objc_selector" }; - const child = try self.allocator.create(Type); - child.* = t; - - return Type{ .pointer = .{ .is_single = true, .is_const = is_const, .is_optional = false, .child = child } }; - }, - .kw_id => { - try self.match(.kw_id); - - if (self.lookahead.kind == .less) { - try self.match(.less); - const types = try self.parseTypeList(); - try self.match(.greater); - - // TODO - how should handle multiple types? - - return self.parsePointerSuffix(types.items[0], is_const, true); - } else { - const t = Type{ .name = "c.objc_object" }; - return self.parsePointerSuffix(t, is_const, true); - } - }, - .kw_imp => { - try self.match(.kw_imp); - - //void (*)(void) - const return_type = try self.allocator.create(Type); - return_type.* = .{ .void = {} }; - - const ty = .{ - .function = .{ - .return_type = return_type, - .params = std.ArrayList(Type).init(self.allocator), - }, - }; - - return self.parseTypeSuffix(ty, is_const, true); - }, - .kw_instancetype => { - try self.match(.kw_instancetype); - - const child = try self.allocator.create(Type); - child.* = .{ .instance_type = {} }; - - return Type{ .pointer = .{ .is_single = true, .is_const = is_const, .is_optional = false, .child = child } }; - }, - .kw_struct => { - try self.match(.kw_struct); - const name = self.lookahead.text; - try self.match(.id); - return self.parseTypeSuffix(.{ .name = name }, is_const, false); - }, - else => { - const text = self.lookahead.text; - try self.match(.id); - return self.parseTypeSuffix(.{ .name = text }, is_const, false); - }, - } - } - - fn parseTypeList(self: *Self) (ParseError || error{OutOfMemory})!std.ArrayList(Type) { - var types = std.ArrayList(Type).init(self.allocator); - - try types.append(try self.parseType()); - while (self.lookahead.kind == .comma) { - try self.match(.comma); - try types.append(try self.parseType()); - } - - return types; - } - - fn parseTypeSuffix(self: *Self, base_type: Type, is_const: bool, is_single: bool) !Type { - if (self.lookahead.kind == .star) { - try self.match(.star); - - return self.parsePointerSuffix(base_type, is_const, is_single); - } else if (self.lookahead.kind == .lbracket) { - // TODO - handle arrays - try self.match(.lbracket); - if (self.lookahead.kind == .int) - try self.match(.int); - try self.match(.rbracket); - - return self.parsePointerSuffix(base_type, is_const, is_single); - } else if (self.lookahead.kind == .lparen) { - try self.match(.lparen); - - if (self.lookahead.kind == .star) { - try self.match(.star); - - const props = try self.parsePointerProps(is_const); - _ = props; - - try self.match(.rparen); - try self.match(.lparen); - _ = try self.parseTypeList(); - try self.match(.rparen); - } else if (self.lookahead.kind == .caret) { - try self.match(.caret); - - const props = try self.parsePointerProps(is_const); - _ = props; - - try self.match(.rparen); - try self.match(.lparen); - const params = try self.parseTypeList(); - try self.match(.rparen); - - const return_type = try self.allocator.create(Type); - return_type.* = base_type; - - return .{ - .function = .{ - .return_type = return_type, - .params = params, - }, - }; - } else { - _ = try self.parseTypeList(); - try self.match(.rparen); - } - - return base_type; - } else if (self.lookahead.kind == .less) { - try self.match(.less); - const types = try self.parseTypeList(); - try self.match(.greater); - - const child = try self.allocator.create(Type); - child.* = base_type; - - return self.parseTypeSuffix(.{ .generic = .{ .base_type = child, .args = types } }, is_const, true); - } else { - const props = try self.parsePointerProps(false); - _ = props; - - return base_type; - } - } - - fn parsePointerProps(self: *Self, elem_is_const: bool) !PointerProps { - var is_const = elem_is_const; - var is_optional = false; - while (true) { - if (self.lookahead.kind == .kw_const) { - try self.match(.kw_const); - is_const = true; - } else if (self.lookahead.kind == .kw_nullable) { - try self.match(.kw_nullable); - is_optional = true; - } else if (self.lookahead.kind == .kw_nonnull) { - try self.match(.kw_nonnull); - } else if (self.lookahead.kind == .kw_null_unspecified) { - try self.match(.kw_null_unspecified); - } else if (self.lookahead.kind == .kw_nullable_result) { - try self.match(.kw_nullable_result); - } else break; - } - - return .{ .is_const = is_const, .is_optional = is_optional }; - } - - fn parsePointerSuffix(self: *Self, base_type: Type, is_const: bool, is_single: bool) error{ - OutOfMemory, - UnexpectedToken, - UnexpectedCharacter, - }!Type { - const props = try self.parsePointerProps(is_const); - const child = try self.allocator.create(Type); - child.* = base_type; - - const t = Type{ .pointer = .{ - .is_single = is_single, - .is_const = props.is_const, - .is_optional = props.is_optional, - .child = child, - } }; - return self.parseTypeSuffix(t, false, is_single); - } - - fn skipParenContent(self: *Self) !void { - var nestLevel: u32 = 0; - while (true) { - if (self.lookahead.kind == .lparen) { - try self.match(.lparen); - nestLevel = nestLevel + 1; - } else if (self.lookahead.kind == .rparen) { - try self.match(.rparen); - nestLevel = nestLevel - 1; - } else { - self.lookahead = try self.lexer.next(); - } - if (nestLevel == 0) - break; - } - } - - fn match(self: *Self, k: Token.Kind) !void { - if (self.lookahead.kind == k) { - self.lookahead = try self.lexer.next(); - } else { - std.debug.print("Expected {any} but found {any}\n", .{ k, self.lookahead.kind }); - return error.UnexpectedToken; - } - } -}; - -// ------------------------------------------------------------------------------------------------ - -pub fn getObject(x: std.json.Value, key: []const u8) ?std.json.Value { - switch (x) { - .object => |o| { - if (o.get(key)) |v| { - switch (v) { - .object => return v, - else => return null, - } - } else { - return null; - } - }, - else => return null, - } -} - -pub fn getArray(x: std.json.Value, key: []const u8) []std.json.Value { - switch (x) { - .object => |o| { - if (o.get(key)) |v| { - switch (v) { - .array => |a| { - return a.items; - }, - else => return &[_]std.json.Value{}, - } - } else { - return &[_]std.json.Value{}; - } - }, - else => return &[_]std.json.Value{}, - } -} - -pub fn getString(x: std.json.Value, key: []const u8) []const u8 { - switch (x) { - .object => |o| { - if (o.get(key)) |v| { - switch (v) { - .string => |s| { - return s; - }, - else => return "", - } - } else { - return ""; - } - }, - else => return "", - } -} - -pub fn getBool(x: std.json.Value, key: []const u8) bool { - switch (x) { - .object => |o| { - if (o.get(key)) |v| { - switch (v) { - .bool => |b| { - return b; - }, - else => return false, - } - } else { - return false; - } - }, - else => return false, - } -} - -pub const Converter = struct { - const Self = @This(); - - allocator: std.mem.Allocator, - arena: std.heap.ArenaAllocator, - - pub fn init(allocator: std.mem.Allocator) Converter { - return Converter{ .allocator = allocator, .arena = std.heap.ArenaAllocator.init(allocator) }; - } - - pub fn deinit(self: *Self) void { - self.arena.deinit(); - } - - pub fn convert(self: *Self, n: std.json.Value) !void { - const kind = getString(n, "kind"); - if (std.mem.eql(u8, kind, "TranslationUnitDecl")) { - try self.convertTranslationUnitDecl(n); - } - } - - fn convertTranslationUnitDecl(self: *Self, n: std.json.Value) !void { - for (getArray(n, "inner")) |child| { - const childKind = getString(child, "kind"); - if (std.mem.eql(u8, childKind, "EnumDecl")) { - try self.convertEnumDecl(child); - } else if (std.mem.eql(u8, childKind, "FunctionDecl")) { - self.convertFunctionDecl(child); - } else if (std.mem.eql(u8, childKind, "ObjCCategoryDecl")) { - try self.convertObjCCategoryDecl(child); - } else if (std.mem.eql(u8, childKind, "ObjCInterfaceDecl")) { - try self.convertObjCInterfaceDecl(child); - } else if (std.mem.eql(u8, childKind, "ObjCProtocolDecl")) { - try self.convertObjcProtocolDecl(child); - } else if (std.mem.eql(u8, childKind, "RecordDecl")) { - self.convertRecordDecl(child); - } else if (std.mem.eql(u8, childKind, "TypedefDecl")) { - try self.convertTypedefDecl(child); - } else if (std.mem.eql(u8, childKind, "VarDecl")) { - self.convertVarDecl(child); - } - } - } - - fn convertEnumDecl(self: *Self, n: std.json.Value) !void { - const name = getString(n, "name"); - if (name.len == 0) { - return; - } - - var e = try registry.getEnum(name); - if (getObject(n, "fixedUnderlyingType")) |ty| { - e.ty = try self.convertType(ty); - } else { - e.ty = .{ .int = 32 }; - } - - for (getArray(n, "inner")) |child| { - const childKind = getString(child, "kind"); - if (std.mem.eql(u8, childKind, "EnumConstantDecl")) { - const v = try self.convertEnumConstantDecl(child); - try e.values.append(v); - } - } - } - - fn convertEnumConstantDecl(self: *Self, n: std.json.Value) !EnumValue { - var value: i64 = 0; - for (getArray(n, "inner")) |child| { - const childKind = getString(child, "kind"); - if (std.mem.eql(u8, childKind, "ConstantExpr")) { - value = self.convertConstantExpr(child); - } else if (std.mem.eql(u8, childKind, "ImplicitCastExpr")) { - value = self.convertImplicitCastExpr(child); - } - } - - return .{ .name = getString(n, "name"), .value = value }; - } - - fn convertConstantExpr(_: *Self, n: std.json.Value) i64 { - const value = getString(n, "value"); - return std.fmt.parseInt(i64, value, 10) catch 0; - } - - fn convertImplicitCastExpr(self: *Self, n: std.json.Value) i64 { - for (getArray(n, "inner")) |child| { - const childKind = getString(child, "kind"); - if (std.mem.eql(u8, childKind, "ConstantExpr")) { - return self.convertConstantExpr(child); - } - } - - return 0; - } - - fn convertFunctionDecl(self: *Self, n: std.json.Value) void { - _ = self; - _ = n; - } - - fn convertObjCCategoryDecl(self: *Self, n: std.json.Value) !void { - const interfaceDecl = getObject(n, "interface").?; - const container = try registry.getInterface(getString(interfaceDecl, "name")); - try self.convertContainer(container, n); - } - - fn convertObjCInterfaceDecl(self: *Self, n: std.json.Value) !void { - var container = try registry.getInterface(getString(n, "name")); - if (getObject(n, "super")) |super| { - const superName = getString(super, "name"); - if (superName.len > 0) { - container.super = try registry.getInterface(superName); - } - } - - try self.convertContainer(container, n); - } - - fn convertObjcProtocolDecl(self: *Self, n: std.json.Value) !void { - var container = try registry.getProtocol(getString(n, "name")); - if (getObject(n, "super")) |super| { - const superName = getString(super, "name"); - if (superName.len > 0) { - container.super = try registry.getProtocol(superName); - } - } - - try self.convertContainer(container, n); - } - - fn convertRecordDecl(self: *Self, n: std.json.Value) void { - _ = self; - _ = n; - } - - fn convertTypedefDecl(self: *Self, n: std.json.Value) !void { - const name = getString(n, "name"); - const ty = try self.convertType(getObject(n, "type").?); - try registry.typedefs.put(name, ty); - } - - fn convertVarDecl(self: *Self, n: std.json.Value) void { - _ = self; - _ = n; - } - - fn convertContainer(self: *Self, container: *Container, n: std.json.Value) !void { - // TODO - better solution for this? - container.type_params.clearAndFree(); - container.protocols.clearAndFree(); - - for (getArray(n, "protocols")) |protocolJson| { - const protocolName = getString(protocolJson, "name"); - const protocol = try registry.getProtocol(protocolName); - try container.protocols.append(protocol); - } - - for (getArray(n, "inner")) |child| { - const childKind = getString(child, "kind"); - if (std.mem.eql(u8, childKind, "ObjCTypeParamDecl")) { - const type_param = try self.convertTypeParam(child); - try container.type_params.append(type_param); - } else if (std.mem.eql(u8, childKind, "ObjCPropertyDecl")) { - const property = try self.convertProperty(child); - try container.properties.append(property); - } else if (std.mem.eql(u8, childKind, "ObjCMethodDecl")) { - const method = try self.convertMethod(child); - try container.methods.append(method); - } - } - } - - fn convertTypeParam(self: *Self, n: std.json.Value) !TypeParam { - _ = self; - return TypeParam.init(getString(n, "name")); - } - - fn convertProperty(self: *Self, n: std.json.Value) !Property { - const ty = try self.convertType(getObject(n, "type").?); - return Property.init(getString(n, "name"), ty); - } - - fn convertMethod(self: *Self, n: std.json.Value) !Method { - const return_type = try self.convertType(getObject(n, "returnType").?); - var params = std.ArrayList(Param).init(registry.allocator); - - for (getArray(n, "inner")) |child| { - const childKind = getString(child, "kind"); - if (std.mem.eql(u8, childKind, "ParmVarDecl")) { - const param = try self.convertParam(child); - try params.append(param); - } - } - - return Method.init(getString(n, "name"), getBool(n, "instance"), return_type, params); - } - - fn convertParam(self: *Self, n: std.json.Value) !Param { - const ty = try self.convertType(getObject(n, "type").?); - return Param.init(getString(n, "name"), ty); - } - - fn convertType(self: *Self, t: std.json.Value) !Type { - //std.debug.print("convertType: {s}\n", .{t.qualType}); - var lexer = Lexer{ .source = getString(t, "qualType") }; - var parser = try Parser.init(self.arena.allocator(), &lexer); - return parser.parseType(); - } -}; - -// ------------------------------------------------------------------------------------------------ - -const prefixes = [_][]const u8{ "CA", "CF", "CG", "MTK", "MTL", "NS" }; - -pub fn getNamespace(id: []const u8) []const u8 { - for (prefixes) |prefix| { - if (std.mem.startsWith(u8, id, prefix)) { - return prefix; - } - } - - return &[_]u8{}; -} - -pub fn trimNamespace(id: []const u8) []const u8 { - for (prefixes) |prefix| { - if (std.mem.startsWith(u8, id, prefix)) { - return id[prefix.len..]; - } - } - - return id; -} - -pub fn trimTrailingColon(id: []const u8) []const u8 { - if (id.len == 0) { - return id; - } else if (id[id.len - 1] == ':') { - return id[0 .. id.len - 1]; - } else { - return id; - } -} - -fn isKeyword(id: []const u8) bool { - if (std.mem.eql(u8, id, "error")) { - return true; - } else if (std.mem.eql(u8, id, "opaque")) { - return true; - } else if (std.mem.eql(u8, id, "type")) { - return true; - } else { - return false; - } -} - -fn Generator(comptime WriterType: type) type { - return struct { - const Self = @This(); - const WriteError = WriterType.Error; - const EnumList = std.ArrayList(*reg.Enum); - const ContainerList = std.ArrayList(*reg.Container); - const SelectorHashSet = std.StringHashMap(void); - - allocator: std.mem.Allocator, - writer: WriterType, - enums: EnumList, - containers: ContainerList, - selectors: SelectorHashSet, - - fn init(allocator: std.mem.Allocator, writer: WriterType) Self { - return Self{ - .allocator = allocator, - .writer = writer, - .enums = EnumList.init(allocator), - .containers = ContainerList.init(allocator), - .selectors = SelectorHashSet.init(allocator), - }; - } - - fn deinit(self: *Self) void { - self.enums.deinit(); - self.containers.deinit(); - self.selectors.deinit(); - } - - pub fn addProtocol(self: *Self, name: []const u8) !void { - const container = registry.protocols.get(name) orelse { - std.debug.print("Protocol {s} not found\n", .{name}); - return; - }; - - try self.addContainer(container); - } - - pub fn addInterface(self: *Self, name: []const u8) !void { - const container = registry.interfaces.get(name) orelse { - std.debug.print("Interface {s} not found\n", .{name}); - return; - }; - - try self.addContainer(container); - } - - pub fn addEnum(self: *Self, name: []const u8) !void { - const e = registry.enums.get(name) orelse { - std.debug.print("Enum {s} not found\n", .{name}); - return; - }; - - try self.enums.append(e); - } - - fn addContainer(self: *Self, container: *Container) !void { - try self.containers.append(container); - - for (container.methods.items) |method| { - try self.selectors.put(method.name, {}); - } - } - - pub fn generate(self: *Self) !void { - try self.generateEnumerations(); - try self.generateContainers(); - try self.generateClasses(); - try self.generateSelectors(); - try self.generateInit(); - } - - fn generateClasses(self: *Self) !void { - for (self.containers.items) |container| { - if (container.is_interface) { - try self.writer.print("var class_", .{}); - try self.generateContainerName(container); - try self.writer.print(": *c.objc_class = undefined;\n", .{}); - } - } - } - - fn generateSelectors(self: *Self) !void { - var it = self.selectors.iterator(); - while (it.next()) |entry| { - const method_name = entry.key_ptr.*; - try self.writer.print("var sel_", .{}); - try self.generateSelectorName(method_name); - try self.writer.print(": *c.objc_selector = undefined;\n", .{}); - } - try self.writer.print("\n", .{}); - } - - fn generateInit(self: *Self) !void { - try self.writer.print("pub fn init() void {{\n", .{}); - try self.generateInitClasses(); - try self.writer.print("\n", .{}); - try self.generateInitSelectors(); - try self.writer.print("}}\n", .{}); - } - - fn generateInitClasses(self: *Self) !void { - for (self.containers.items) |container| { - if (container.is_interface) { - try self.writer.print(" class_", .{}); - try self.generateContainerName(container); - try self.writer.print(" = c.objc_getClass(\"{s}\").?;\n", .{container.name}); - } - } - } - - fn generateInitSelectors(self: *Self) !void { - var it = self.selectors.iterator(); - while (it.next()) |entry| { - const method_name = entry.key_ptr.*; - try self.writer.print(" sel_", .{}); - try self.generateSelectorName(method_name); - try self.writer.print(" = c.sel_registerName(\"{s}\").?;\n", .{method_name}); - } - } - - fn generateEnumerations(self: *Self) !void { - for (self.enums.items) |e| { - try self.writer.writeAll("\n"); - try self.writer.print("pub const ", .{}); - try self.generateTypeName(e.name); - try self.writer.print(" = ", .{}); - try self.generateType(e.ty); - try self.writer.print(";\n", .{}); - - for (e.values.items) |v| { - try self.writer.print("pub const ", .{}); - try self.generateTypeName(v.name); - try self.writer.print(": ", .{}); - try self.generateTypeName(e.name); - try self.writer.print(" = {d};\n", .{v.value}); - } - } - } - - fn generateContainers(self: *Self) !void { - for (self.containers.items) |container| { - try self.generateContainer(container); - } - } - - fn generateContainer(self: *Self, container: *Container) !void { - try self.writer.writeAll("\n"); - if (container.type_params.items.len > 0) { - try self.writer.print("pub fn ", .{}); - try self.generateContainerName(container); - try self.writer.print("(", .{}); - var first = true; - for (container.type_params.items) |type_param| { - if (!first) - try self.writer.writeAll(", "); - first = false; - try self.writer.print("comptime {s}: type", .{type_param.name}); - } - try self.writer.print(") type {{ return opaque {{\n", .{}); - } else { - try self.writer.print("pub const ", .{}); - try self.generateContainerName(container); - try self.writer.print(" = opaque {{\n", .{}); - } - if (container.super) |super| { - _ = super; - // try self.writer.print(" pub const Super = ", .{}); - // try self.generateContainerName(super); - // try self.writer.print(";\n", .{}); - } - if (container.protocols.items.len > 0) { - // try self.writer.print(" pub const ConformsTo = &[_]type{{ ", .{}); - // var first = true; - // for (container.protocols.items) |protocol| { - // if (!first) - // try self.writer.writeAll(", "); - // first = false; - // try self.generateContainerName(protocol); - // } - // try self.writer.print(" }};\n", .{}); - } - if (container.is_interface) { - try self.writer.print(" pub fn class() *c.objc_class {{ return class_", .{}); - try self.generateContainerName(container); - try self.writer.print("; }}\n", .{}); - } - try self.writer.print(" pub usingnamespace Methods(", .{}); - try self.generateContainerName(container); - try self.writer.print(");\n", .{}); - try self.writer.print("\n", .{}); - try self.writer.print(" pub fn Methods(comptime T: type) type {{\n", .{}); - try self.writer.print(" return struct {{\n", .{}); - - var hasParent = false; - if (container.super) |super| { - try self.writer.print(" pub usingnamespace ", .{}); - try self.generateContainerName(super); - try self.writer.print(".Methods(T);\n", .{}); - hasParent = true; - } - - for (container.protocols.items) |protocol| { - try self.writer.print(" pub usingnamespace ", .{}); - try self.generateContainerName(protocol); - try self.writer.print(".Methods(T);\n", .{}); - hasParent = true; - } - - if (hasParent) { - try self.writer.print("\n", .{}); - } - - for (container.methods.items) |method| { - try self.generateMethod(container, method); - } - - try self.writer.print(" }};\n", .{}); - try self.writer.print(" }}\n", .{}); - try self.writer.print("}};\n", .{}); - if (container.type_params.items.len > 0) { - try self.writer.print("}}\n", .{}); - } - } - - fn generateMethod(self: *Self, container: *Container, method: Method) !void { - if (container.super) |super| { - if (self.doesParentHaveMethod(super, method.name)) - return; - } - - try self.writer.writeAll(" pub fn "); - try self.generateMethodName(method.name); - try self.writer.print("(", .{}); - try self.generateMethodParams(method); - try self.writer.print(") ", .{}); - try self.generateType(method.return_type); - try self.writer.print(" {{\n", .{}); - try self.generateBlockHelpers(method); - try self.writer.writeAll(" return @as("); - try self.generateObjcSignature(method); - try self.writer.writeAll(", @ptrCast(&c.objc_msgSend))("); - try self.generateMethodArgs(method); - try self.writer.print(");\n", .{}); - try self.writer.print(" }}\n", .{}); - } - - fn doesParentHaveMethod(self: *Self, container: *Container, name: []const u8) bool { - if (container.super) |super| { - if (self.doesParentHaveMethod(super, name)) - return true; - } - - for (container.methods.items) |method| { - if (std.mem.eql(u8, method.name, name)) - return true; - } - - return false; - } - - fn generateMethodName(self: *Self, name: []const u8) !void { - if (isKeyword(name)) { - try self.writer.print("@\"{s}\"", .{name}); - } else { - try self.generateSelectorName(trimTrailingColon(name)); - } - } - - fn generateMethodParams(self: *Self, method: Method) !void { - var first = true; - if (method.instance) { - try self.writer.print("self_: *T", .{}); - first = false; - } - for (method.params.items) |param| { - if (!first) - try self.writer.writeAll(", "); - first = false; - try self.generateMethodParam(param); - } - } - - fn generateMethodParam(self: *Self, param: Param) !void { - if (getBlockType(param)) |f| { - try self.writer.writeAll("context: anytype, comptime "); - try self.writer.print("{s}_: ", .{param.name}); - try self.writer.writeAll("fn (ctx: @TypeOf(context)"); - for (f.params.items) |param_ty| { - try self.writer.writeAll(", _: "); - try self.generateType(param_ty); - } - try self.writer.writeAll(") "); - try self.generateType(f.return_type.*); - } else { - try self.writer.print("{s}_: ", .{param.name}); - try self.generateType(param.ty); - } - } - - fn generateBlockHelpers(self: *Self, method: Method) !void { - for (method.params.items) |param| { - if (getBlockType(param)) |f| { - try self.writer.writeAll(" const Literal = ns.BlockLiteral(@TypeOf(context));\n"); - try self.writer.writeAll(" const Helper = struct {\n"); - try self.writer.writeAll(" pub fn cCallback(literal: *Literal"); - for (f.params.items, 0..) |param_ty, i| { - try self.writer.print(", a{d}: ", .{i}); - try self.generateType(param_ty); - } - try self.writer.writeAll(") callconv(.C) void {\n"); - try self.writer.print(" {s}_(literal.context", .{param.name}); - for (0..f.params.items.len) |i| { - try self.writer.print(", a{d}", .{i}); - } - try self.writer.writeAll(");\n"); - try self.writer.writeAll(" }\n"); - try self.writer.writeAll(" };\n"); - try self.writer.writeAll(" const descriptor = ns.BlockDescriptor{ .reserved = 0, .size = @sizeOf(Literal) };\n"); - try self.writer.writeAll(" const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };\n"); - } - } - } - - fn generateObjcSignature(self: *Self, method: Method) !void { - try self.writer.writeAll("*const fn ("); - if (method.instance) { - try self.writer.writeAll("*T"); - } else { - try self.writer.writeAll("*c.objc_class"); - } - try self.writer.writeAll(", *c.objc_selector"); - for (method.params.items) |param| { - try self.writer.writeAll(", "); - if (getBlockType(param)) |_| { - try self.writer.writeAll("*const anyopaque"); - } else { - try self.generateType(param.ty); - } - } - try self.writer.writeAll(") callconv(.C) "); - try self.generateType(method.return_type); - } - - fn generateMethodArgs(self: *Self, method: Method) !void { - if (method.instance) { - try self.writer.print("self_", .{}); - } else { - try self.writer.print("T.class()", .{}); - } - try self.writer.print(", sel_", .{}); - try self.generateSelectorName(method.name); - - for (method.params.items) |param| { - try self.writer.writeAll(", "); - if (getBlockType(param)) |_| { - try self.writer.writeAll("@ptrCast(&block)"); - } else { - try self.writer.print("{s}_", .{param.name}); - } - } - } - - fn getBlockType(param: Param) ?Type.Function { - switch (param.ty) { - .name => |s| { - if (registry.typedefs.get(s)) |t| { - return switch (t) { - .function => |f| f, - else => null, - }; - } - }, - .function => |f| return f, - else => return null, - } - return null; - } - - fn generateSelectorName(self: *Self, name: []const u8) !void { - for (name) |ch| { - if (ch == ':') { - try self.writer.writeByte('_'); - } else { - try self.writer.writeByte(ch); - } - } - } - - fn generateType(self: *Self, ty: Type) WriteError!void { - switch (ty) { - .void => { - try self.writer.writeAll("void"); - }, - .bool => { - try self.writer.writeAll("bool"); - }, - .int => |bits| { - try self.writer.print("i{d}", .{bits}); - }, - .uint => |bits| { - try self.writer.print("u{d}", .{bits}); - }, - .float => |bits| { - try self.writer.print("f{d}", .{bits}); - }, - .c_short => { - try self.writer.writeAll("c_short"); - }, - .c_ushort => { - try self.writer.writeAll("c_ushort"); - }, - .c_int => { - try self.writer.writeAll("c_int"); - }, - .c_uint => { - try self.writer.writeAll("c_uint"); - }, - .c_long => { - try self.writer.writeAll("c_long"); - }, - .c_ulong => { - try self.writer.writeAll("c_ulong"); - }, - .c_longlong => { - try self.writer.writeAll("c_longlong"); - }, - .c_ulonglong => { - try self.writer.writeAll("c_ulonglong"); - }, - .name => |n| { - try self.generateTypeName(n); - }, - .instance_type => { - try self.writer.writeAll("T"); - }, - .pointer => |p| { - if (p.is_optional) - try self.writer.writeAll("?"); - if (p.is_single or p.is_optional) { - try self.writer.writeAll("*"); - } else { - //try self.writer.writeAll("[*c]"); - try self.writer.writeAll("*"); - } - if (p.is_const) - try self.writer.writeAll("const "); - if (p.child.* == .void) { - try self.writer.writeAll("anyopaque"); - } else { - try self.generateType(p.child.*); - } - }, - .function => |f| { - try self.writer.writeAll("fn ("); - for (f.params.items, 0..) |param_ty, i| { - if (i > 0) - try self.writer.writeAll(", "); - try self.generateType(param_ty); - } - try self.writer.writeAll(") callconv(.C) "); - try self.generateType(f.return_type.*); - }, - .generic => |g| { - try self.generateType(g.base_type.*); - try self.writer.writeAll("("); - for (g.args.items, 0..) |arg, i| { - if (i > 0) - try self.writer.writeAll(", "); - try self.generateType(arg); - } - try self.writer.writeAll(")"); - }, - } - } - - fn generateTypePrefix(self: *Self, name: []const u8) !void { - const namespace = getNamespace(name); - if (namespace.len > 0 and !std.mem.eql(u8, namespace, "MTL")) { - try self.generateLower(namespace); - try self.writer.writeAll("."); - } - } - - fn generateContainerSuffix(self: *Self, container: *Container) !void { - if (container.ambiguous) { - if (container.is_interface) { - try self.writer.writeAll("Interface"); - } else { - try self.writer.writeAll("Protocol"); - } - } - } - - fn generateTypeName(self: *Self, name: []const u8) !void { - try self.generateTypePrefix(name); - try self.writer.writeAll(trimNamespace(name)); - if (registry.protocols.get(name)) |container| { - try self.generateContainerSuffix(container); - } else if (registry.interfaces.get(name)) |container| { - try self.generateContainerSuffix(container); - } - } - - fn generateContainerName(self: *Self, container: *Container) !void { - try self.generateTypePrefix(container.name); - try self.writer.writeAll(trimNamespace(container.name)); - try self.generateContainerSuffix(container); - } - - fn generateLower(self: *Self, str: []const u8) !void { - for (str) |ch| { - try self.writer.writeByte(std.ascii.toLower(ch)); - } - } - }; -} - -// ------------------------------------------------------------------------------------------------ - -fn generateMetal(generator: anytype) !void { - // MTLAccelerationStructure.hpp - try generator.addEnum("MTLAccelerationStructureUsage"); - try generator.addEnum("MTLAccelerationStructureInstanceOptions"); - try generator.addInterface("MTLAccelerationStructureDescriptor"); - try generator.addInterface("MTLAccelerationStructureGeometryDescriptor"); - try generator.addEnum("MTLMotionBorderMode"); - try generator.addInterface("MTLPrimitiveAccelerationStructureDescriptor"); - try generator.addInterface("MTLAccelerationStructureTriangleGeometryDescriptor"); - try generator.addInterface("MTLAccelerationStructureBoundingBoxGeometryDescriptor"); - try generator.addInterface("MTLMotionKeyframeData"); - try generator.addInterface("MTLAccelerationStructureMotionTriangleGeometryDescriptor"); - try generator.addInterface("MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor"); - //try generator.addStruct("MTLAccelerationStructureInstanceDescriptor"); - //try generator.addStruct("MTLAccelerationStructureUserIDInstanceDescriptor"); - try generator.addEnum("MTLAccelerationStructureInstanceDescriptorType"); - //try generator.addStruct("MTLAccelerationStructureMotionInstanceDescriptor"); - try generator.addInterface("MTLInstanceAccelerationStructureDescriptor"); - try generator.addProtocol("MTLAccelerationStructure"); - - // MTLAccelerationStructureCommandEncoder.hpp - try generator.addEnum("MTLAccelerationStructureRefitOptions"); - try generator.addProtocol("MTLAccelerationStructureCommandEncoder"); - try generator.addInterface("MTLAccelerationStructurePassSampleBufferAttachmentDescriptor"); - try generator.addInterface("MTLAccelerationStructurePassSampleBufferAttachmentDescriptorArray"); - try generator.addInterface("MTLAccelerationStructurePassDescriptor"); - - // MTLAccelerationStructureTypes.hpp - //try generator.addStruct("MTLPackedFloat3"); - //try generator.addStruct("MTLPackedFloat4x3"); - //try generator.addStruct("MTLAxisAlignedBoundingBox"); - - // MTLArgument.hpp - try generator.addEnum("MTLDataType"); - try generator.addEnum("MTLBindingType"); - try generator.addEnum("MTLArgumentType"); - try generator.addEnum("MTLArgumentAccess"); - try generator.addInterface("MTLType"); - try generator.addInterface("MTLStructMember"); - try generator.addInterface("MTLStructType"); - try generator.addInterface("MTLArrayType"); - try generator.addInterface("MTLPointerType"); - try generator.addInterface("MTLTextureReferenceType"); - try generator.addInterface("MTLArgument"); - try generator.addProtocol("MTLBinding"); - try generator.addProtocol("MTLBufferBinding"); - try generator.addProtocol("MTLThreadgroupBinding"); - try generator.addProtocol("MTLTextureBinding"); - try generator.addProtocol("MTLObjectPayloadBinding"); - - // MTLArgumentEncoder.hpp - try generator.addProtocol("MTLArgumentEncoder"); - - // MTLBinaryArchive.hpp - try generator.addEnum("MTLBinaryArchiveError"); - try generator.addInterface("MTLBinaryArchiveDescriptor"); - try generator.addProtocol("MTLBinaryArchive"); - - // MTLBlitCommandEncoder.hpp - try generator.addEnum("MTLBlitOption"); - try generator.addProtocol("MTLBlitCommandEncoder"); - - // MTLBlitPass.hpp - try generator.addInterface("MTLBlitPassSampleBufferAttachmentDescriptor"); - try generator.addInterface("MTLBlitPassSampleBufferAttachmentDescriptorArray"); - try generator.addInterface("MTLBlitPassDescriptor"); - - // MTLBuffer.hpp - try generator.addProtocol("MTLBuffer"); - - // MTLCaptureManager.hpp - try generator.addEnum("MTLCaptureError"); - try generator.addEnum("MTLCaptureDestination"); - try generator.addInterface("MTLCaptureDescriptor"); - try generator.addInterface("MTLCaptureManager"); - - // MTLCaptureScope.hpp - try generator.addProtocol("MTLCaptureScope"); - - // MTLCommandBuffer.hpp - try generator.addEnum("MTLCommandBufferStatus"); - try generator.addEnum("MTLCommandBufferError"); - try generator.addEnum("MTLCommandBufferErrorOption"); - try generator.addEnum("MTLCommandEncoderErrorState"); - try generator.addInterface("MTLCommandBufferDescriptor"); - try generator.addProtocol("MTLCommandBufferEncoderInfo"); - try generator.addEnum("MTLDispatchType"); - //try generator.addType("MTLCommandBufferHandler"); - try generator.addProtocol("MTLCommandBuffer"); - - // MTLCommandEncoder.hpp - try generator.addEnum("MTLResourceUsage"); - try generator.addEnum("MTLBarrierScope"); - try generator.addProtocol("MTLCommandEncoder"); - - // MTLCommandQueue.hpp - try generator.addProtocol("MTLCommandQueue"); - - // MTLComputeCommandEncoder.hpp - //try generator.addStruct("MTLDispatchThreadgroupsIndirectArguments"); - //try generator.addStruct("MTLStageInRegionIndirectArguments"); - try generator.addProtocol("MTLComputeCommandEncoder"); - - // MTLComputePass.hpp - try generator.addInterface("MTLComputePassSampleBufferAttachmentDescriptor"); - try generator.addInterface("MTLComputePassSampleBufferAttachmentDescriptorArray"); - try generator.addInterface("MTLComputePassDescriptor"); - - // MTLComputePipeline.hpp - try generator.addInterface("MTLComputePipelineReflection"); - try generator.addInterface("MTLComputePipelineDescriptor"); - try generator.addProtocol("MTLComputePipelineState"); - - // MTLCounters.hpp - //try generator.addConst("MTLCounterErrorDomain"); - //try generator.addType("MTLCommonCounter"); - //try generator.addConst("MTLCommonCounterTimestamp"); - //try generator.addConst("MTLCommonCounterTessellationInputPatches"); - //try generator.addConst("MTLCommonCounterVertexInvocations"); - //try generator.addConst("MTLCommonCounterPostTessellationVertexInvocations"); - //try generator.addConst("MTLCommonCounterClipperInvocations"); - //try generator.addConst("MTLCommonCounterClipperPrimitivesOut"); - //try generator.addConst("MTLCommonCounterFragmentInvocations"); - //try generator.addConst("MTLCommonCounterFragmentsPassed"); - //try generator.addConst("MTLCommonCounterComputeKernelInvocations"); - //try generator.addConst("MTLCommonCounterTotalCycles"); - //try generator.addConst("MTLCommonCounterVertexCycles"); - //try generator.addConst("MTLCommonCounterTessellationCycles"); - //try generator.addConst("MTLCommonCounterPostTessellationVertexCycles"); - //try generator.addConst("MTLCommonCounterFragmentCycles"); - //try generator.addConst("MTLCommonCounterRenderTargetWriteCycles"); - //try generator.addType("MTLCommonCounterSet"); - //try generator.addConst("MTLCommonCounterSetTimestamp"); - //try generator.addConst("MTLCommonCounterSetStageUtilization"); - //try generator.addConst("MTLCommonCounterSetStatistic"); - //try generator.addStruct("MTLCounterResultTimestamp"); - //try generator.addStruct("MTLCounterResultStageUtilization"); - //try generator.addStruct("MTLCounterResultStatistic"); - try generator.addProtocol("MTLCounter"); - try generator.addProtocol("MTLCounterSet"); - try generator.addInterface("MTLCounterSampleBufferDescriptor"); - try generator.addProtocol("MTLCounterSampleBuffer"); - try generator.addEnum("MTLCounterSampleBufferError"); - - // MTLDepthStencil.hpp - try generator.addEnum("MTLCompareFunction"); - try generator.addEnum("MTLStencilOperation"); - try generator.addInterface("MTLStencilDescriptor"); - try generator.addInterface("MTLDepthStencilDescriptor"); - try generator.addProtocol("MTLDepthStencilState"); - - // MTLDevice.hpp - try generator.addEnum("MTLIOCompressionMethod"); - try generator.addEnum("MTLFeatureSet"); - try generator.addEnum("MTLGPUFamily"); - try generator.addEnum("MTLDeviceLocation"); - try generator.addEnum("MTLPipelineOption"); - try generator.addEnum("MTLReadWriteTextureTier"); - try generator.addEnum("MTLArgumentBuffersTier"); - try generator.addEnum("MTLSparseTextureRegionAlignmentMode"); - try generator.addEnum("MTLSparsePageSize"); - // try generator.addStruct("MTLAccelerationStructureSizes"); - try generator.addEnum("MTLCounterSamplingPoint"); - // try generator.addStruct("MTLSizeAndAlign"); - try generator.addInterface("MTLArgumentDescriptor"); - //try generator.addType("MTLDeviceNotificationName"); - //try generator.addConst("MTLDeviceWasAddedNotification"); - //try generator.addConst("MTLDeviceRemovalRequestedNotification)); - //try generator.addConst("MTLDeviceWasRemovedNotification)); - //try generator.addType("MTLDeviceNotificationHandlerBlock"); - //try generator.addType("MTLAutoreleasedComputePipelineReflection"); - //try generator.addType("MTLAutoreleasedRenderPipelineReflection"); - //try generator.addType("MTLNewLibraryCompletionHandler"); - //try generator.addType("MTLNewRenderPipelineStateCompletionHandler"); - //try generator.addType("MTLNewRenderPipelineStateWithReflectionCompletionHandler"); - //try generator.addType("MTLNewComputePipelineStateCompletionHandler"); - //try generator.addType("MTLNewComputePipelineStateWithReflectionCompletionHandler"); - //try generator.addType("MTLTimestamp"); - //try generator.addFunction("MTLCreateSystemDefaultDevice"); - //try generator.addFunction("MTLCopyAllDevices"); - //try generator.addFunction("MTLCopyAllDevicesWithObserver"); - //try generator.addFunction("MTLRemoveDeviceObserver"); - try generator.addProtocol("MTLDevice"); - - // MTLDrawable.hpp - //try generator.addType("MTLDrawablePresentedHandler"); - try generator.addProtocol("MTLDrawable"); - - // MTLDynamicLibrary.hpp - try generator.addEnum("MTLDynamicLibraryError"); - try generator.addProtocol("MTLDynamicLibrary"); - - // MTLEvent.hpp - try generator.addProtocol("MTLEvent"); - try generator.addInterface("MTLSharedEventListener"); - // try generator.addType("MTLSharedEventNotificationBlock"); - try generator.addProtocol("MTLSharedEvent"); - try generator.addInterface("MTLSharedEventHandle"); - // try generator.addStruct("MTLSharedEventHandlePrivate"); - - // MTLFence.hpp - try generator.addProtocol("MTLFence"); - - // MTLFunctionConstantValues.hpp - try generator.addInterface("MTLFunctionConstantValues"); - - // MTLFunctionDescriptor.hpp - try generator.addEnum("MTLFunctionOptions"); - try generator.addInterface("MTLFunctionDescriptor"); - try generator.addInterface("MTLIntersectionFunctionDescriptor"); - - // MTLFunctionHandle.hpp - try generator.addProtocol("MTLFunctionHandle"); - - // MTLFunctionLog.hpp - try generator.addEnum("MTLFunctionLogType"); - try generator.addProtocol("MTLLogContainer"); - try generator.addProtocol("MTLFunctionLogDebugLocation"); - try generator.addProtocol("MTLFunctionLog"); - - // MTLFunctionStitching.hpp - try generator.addProtocol("MTLFunctionStitchingAttribute"); - try generator.addInterface("MTLFunctionStitchingAttributeAlwaysInline"); - try generator.addProtocol("MTLFunctionStitchingNode"); - try generator.addInterface("MTLFunctionStitchingInputNode"); - try generator.addInterface("MTLFunctionStitchingFunctionNode"); - try generator.addInterface("MTLFunctionStitchingGraph"); - try generator.addInterface("MTLStitchedLibraryDescriptor"); - - // MTLHeap.hpp - try generator.addEnum("MTLHeapType"); - try generator.addInterface("MTLHeapDescriptor"); - try generator.addProtocol("MTLHeap"); - - // MTLIndirectCommandBuffer.hpp - try generator.addEnum("MTLIndirectCommandType"); - // try generator.addStruct("MTLIndirectCommandBufferExecutionRange"); - try generator.addInterface("MTLIndirectCommandBufferDescriptor"); - try generator.addProtocol("MTLIndirectCommandBuffer"); - - // MTLIndirectCommandEncoder.hpp - try generator.addProtocol("MTLIndirectRenderCommand"); - try generator.addProtocol("MTLIndirectComputeCommand"); - - // MTLIntersectionFunctionTable.hpp - try generator.addEnum("MTLIntersectionFunctionSignature"); - try generator.addInterface("MTLIntersectionFunctionTableDescriptor"); - try generator.addProtocol("MTLIntersectionFunctionTable"); - - // MTLIOCommandBuffer.hpp - try generator.addEnum("MTLIOStatus"); - //try generator.addType("MTLIOCommandBufferHandler"); - try generator.addProtocol("MTLIOCommandBuffer"); - - // MTLIOCommandQueue.hpp - try generator.addEnum("MTLIOPriority"); - try generator.addEnum("MTLIOCommandQueueType"); - //try generator.addConst("MTLIOErrorDomain"); - try generator.addEnum("MTLIOError"); - try generator.addProtocol("MTLIOCommandQueue"); - try generator.addProtocol("MTLIOScratchBuffer"); - try generator.addProtocol("MTLIOScratchBufferAllocator"); - try generator.addInterface("MTLIOCommandQueueDescriptor"); - try generator.addProtocol("MTLIOFileHandle"); - - // MTLLibrary.hpp - try generator.addEnum("MTLPatchType"); - try generator.addInterface("MTLVertexAttribute"); - try generator.addInterface("MTLAttribute"); - try generator.addEnum("MTLFunctionType"); - try generator.addInterface("MTLFunctionConstant"); - // try generator.addType("MTLAutoreleasedArgument"); - try generator.addProtocol("MTLFunction"); - try generator.addEnum("MTLLanguageVersion"); - try generator.addEnum("MTLLibraryType"); - try generator.addEnum("MTLLibraryOptimizationLevel"); - try generator.addEnum("MTLCompileSymbolVisibility"); - - try generator.addInterface("MTLCompileOptions"); - try generator.addEnum("MTLLibraryError"); - try generator.addProtocol("MTLLibrary"); - - // MTLLinkedFunctions.hpp - try generator.addInterface("MTLLinkedFunctions"); - - // MTLParallelRenderCommandEncoder.hpp - try generator.addProtocol("MTLParallelRenderCommandEncoder"); - - // MTLPipeline.hpp - try generator.addEnum("MTLMutability"); - try generator.addInterface("MTLPipelineBufferDescriptor"); - try generator.addInterface("MTLPipelineBufferDescriptorArray"); - - // MTLPixelFormat.hpp - try generator.addEnum("MTLPixelFormat"); - - // MTLRasterizationRate.hpp - try generator.addInterface("MTLRasterizationRateSampleArray"); - try generator.addInterface("MTLRasterizationRateLayerDescriptor"); - try generator.addInterface("MTLRasterizationRateLayerArray"); - try generator.addInterface("MTLRasterizationRateMapDescriptor"); - try generator.addProtocol("MTLRasterizationRateMap"); - - // MTLRenderCommandEncoder.hpp - try generator.addEnum("MTLPrimitiveType"); - try generator.addEnum("MTLVisibilityResultMode"); - // try generator.addStruct("MTLScissorRect"); - // try generator.addStruct("MTLViewport"); - try generator.addEnum("MTLCullMode"); - try generator.addEnum("MTLWinding"); - try generator.addEnum("MTLDepthClipMode"); - try generator.addEnum("MTLTriangleFillMode"); - // try generator.addStruct("MTLDrawPrimitivesIndirectArguments"); - // try generator.addStruct("MTLDrawIndexedPrimitivesIndirectArguments"); - // try generator.addStruct("MTLVertexAmplificationViewMapping"); - // try generator.addStruct("MTLDrawPatchIndirectArguments"); - // try generator.addStruct("MTLQuadTessellationFactorsHalf"); - // try generator.addStruct("MTLTriangleTessellationFactorsHalf"); - try generator.addEnum("MTLRenderStages"); - try generator.addProtocol("MTLRenderCommandEncoder"); - - // MTLRenderPass.hpp - try generator.addEnum("MTLLoadAction"); - try generator.addEnum("MTLStoreAction"); - try generator.addEnum("MTLStoreActionOptions"); - // try generator.addStruct("MTLClearColor"); - try generator.addInterface("MTLRenderPassAttachmentDescriptor"); - try generator.addInterface("MTLRenderPassColorAttachmentDescriptor"); - try generator.addEnum("MTLMultisampleDepthResolveFilter"); - try generator.addInterface("MTLRenderPassDepthAttachmentDescriptor"); - try generator.addEnum("MTLMultisampleStencilResolveFilter"); - try generator.addInterface("MTLRenderPassStencilAttachmentDescriptor"); - try generator.addInterface("MTLRenderPassColorAttachmentDescriptorArray"); - try generator.addInterface("MTLRenderPassSampleBufferAttachmentDescriptor"); - try generator.addInterface("MTLRenderPassSampleBufferAttachmentDescriptorArray"); - try generator.addInterface("MTLRenderPassDescriptor"); - - // MTLRenderPipeline.hpp - try generator.addEnum("MTLBlendFactor"); - try generator.addEnum("MTLBlendOperation"); - try generator.addEnum("MTLColorWriteMask"); - try generator.addEnum("MTLPrimitiveTopologyClass"); - try generator.addEnum("MTLTessellationPartitionMode"); - try generator.addEnum("MTLTessellationFactorStepFunction"); - try generator.addEnum("MTLTessellationFactorFormat"); - try generator.addEnum("MTLTessellationControlPointIndexType"); - try generator.addInterface("MTLRenderPipelineColorAttachmentDescriptor"); - try generator.addInterface("MTLRenderPipelineReflection"); - try generator.addInterface("MTLRenderPipelineDescriptor"); - try generator.addInterface("MTLRenderPipelineFunctionsDescriptor"); - try generator.addProtocol("MTLRenderPipelineState"); - try generator.addInterface("MTLRenderPipelineColorAttachmentDescriptorArray"); - try generator.addInterface("MTLTileRenderPipelineColorAttachmentDescriptor"); - try generator.addInterface("MTLTileRenderPipelineColorAttachmentDescriptorArray"); - try generator.addInterface("MTLTileRenderPipelineDescriptor"); - try generator.addInterface("MTLMeshRenderPipelineDescriptor"); - - // MTLResource.hpp - try generator.addEnum("MTLPurgeableState"); - try generator.addEnum("MTLCPUCacheMode"); - try generator.addEnum("MTLStorageMode"); - try generator.addEnum("MTLHazardTrackingMode"); - try generator.addEnum("MTLResourceOptions"); - try generator.addProtocol("MTLResource"); - - // MTLResourceStateCommandEncoder.hpp - try generator.addEnum("MTLSparseTextureMappingMode"); - // try generator.addStruct("MTLMapIndirectArguments"); - try generator.addProtocol("MTLResourceStateCommandEncoder"); - - // MTLResourceStatePass.hpp - try generator.addInterface("MTLResourceStatePassSampleBufferAttachmentDescriptor"); - try generator.addInterface("MTLResourceStatePassSampleBufferAttachmentDescriptorArray"); - try generator.addInterface("MTLResourceStatePassDescriptor"); - - // MTLSampler.hpp - try generator.addEnum("MTLSamplerMinMagFilter"); - try generator.addEnum("MTLSamplerMipFilter"); - try generator.addEnum("MTLSamplerAddressMode"); - try generator.addEnum("MTLSamplerBorderColor"); - try generator.addInterface("MTLSamplerDescriptor"); - try generator.addProtocol("MTLSamplerState"); - - // MTLStageInputOutputDescriptor.hpp - try generator.addEnum("MTLAttributeFormat"); - try generator.addEnum("MTLIndexType"); - try generator.addEnum("MTLStepFunction"); - try generator.addInterface("MTLBufferLayoutDescriptor"); - try generator.addInterface("MTLBufferLayoutDescriptorArray"); - try generator.addInterface("MTLAttributeDescriptor"); - try generator.addInterface("MTLAttributeDescriptorArray"); - try generator.addInterface("MTLStageInputOutputDescriptor"); - - // MTLTexture.hpp - try generator.addEnum("MTLTextureType"); - try generator.addEnum("MTLTextureSwizzle"); - // try generator.addStruct("MTLTextureSwizzleChannels"); - try generator.addInterface("MTLSharedTextureHandle"); - // try generator.addStruct("MTLSharedTextureHandlePrivate"); - try generator.addEnum("MTLTextureUsage"); - try generator.addEnum("MTLTextureCompressionType"); - try generator.addInterface("MTLTextureDescriptor"); - try generator.addProtocol("MTLTexture"); - - // MTLTypes.hpp - // try generator.addStruct("MTLOrigin"); - // try generator.addStruct("MTLSize"); - // try generator.addStruct("MTLRegion"); - // try generator.addType("MTLCoordinate2D"); - // try generator.addStruct("MTLSamplePosition"); - - // MTLVertexDescriptor.hpp - try generator.addEnum("MTLVertexFormat"); - try generator.addEnum("MTLVertexStepFunction"); - try generator.addInterface("MTLVertexBufferLayoutDescriptor"); - try generator.addInterface("MTLVertexBufferLayoutDescriptorArray"); - try generator.addInterface("MTLVertexAttributeDescriptor"); - try generator.addInterface("MTLVertexAttributeDescriptorArray"); - try generator.addInterface("MTLVertexDescriptor"); - - // MTLVisibleFunctionTable.hpp - try generator.addInterface("MTLVisibleFunctionTableDescriptor"); - try generator.addProtocol("MTLVisibleFunctionTable"); -} - -pub fn main() anyerror!void { - var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = 8 }){}; - defer std.debug.assert(general_purpose_allocator.deinit() == .ok); - - const allocator = general_purpose_allocator.allocator(); - - var file = try std.fs.cwd().openFile("headers.json", .{}); - defer file.close(); - - const file_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); - defer allocator.free(file_data); - - var valueTree = try std.json.parseFromSlice(std.json.Value, allocator, file_data, .{}); - defer valueTree.deinit(); - - registry = Registry.init(allocator); - defer registry.deinit(); - - var converter = Converter.init(allocator); - defer converter.deinit(); - - try converter.convert(valueTree.value); - - const stdout = std.io.getStdOut().writer(); - var generator = Generator(@TypeOf(stdout)).init(allocator, stdout); - defer generator.deinit(); - - try generateMetal(&generator); - - try generator.generate(); -} - -test { - std.testing.refAllDeclsRecursive(@This()); -} diff --git a/src/mach/objc-generator/registry.zig b/src/mach/objc-generator/registry.zig deleted file mode 100644 index 527e4465..00000000 --- a/src/mach/objc-generator/registry.zig +++ /dev/null @@ -1,240 +0,0 @@ -const std = @import("std"); - -// Types are dynamically allocated into the converter's arena so do not need a deinit -pub const Type = union(enum) { - void, - bool, - int: u8, - uint: u8, - float: u8, - c_short, - c_ushort, - c_int, - c_uint, - c_long, - c_ulong, - c_longlong, - c_ulonglong, - name: []const u8, - pointer: Pointer, - instance_type, - function: Function, - generic: Generic, - - pub const Pointer = struct { - is_single: bool, - is_const: bool, - is_optional: bool, - child: *Type, - }; - - pub const Function = struct { - return_type: *Type, - params: std.ArrayList(Type), - }; - - pub const Generic = struct { - base_type: *Type, - args: std.ArrayList(Type), - }; -}; - -pub const EnumValue = struct { - name: []const u8, - value: i64, -}; - -pub const Enum = struct { - const Self = @This(); - const ValueList = std.ArrayList(EnumValue); - - name: []const u8, - ty: Type, - values: ValueList, - - pub fn init(allocator: std.mem.Allocator, name: []const u8) Enum { - return Enum{ - .name = name, - .ty = undefined, - .values = ValueList.init(allocator), - }; - } - - pub fn deinit(self: *Self) void { - self.values.deinit(); - } -}; - -pub const TypeParam = struct { - name: []const u8, - - pub fn init(name: []const u8) TypeParam { - return TypeParam{ .name = name }; - } -}; - -pub const Property = struct { - name: []const u8, - ty: Type, - - pub fn init(name: []const u8, ty: Type) Property { - return Property{ .name = name, .ty = ty }; - } -}; - -pub const Param = struct { - name: []const u8, - ty: Type, - - pub fn init(name: []const u8, ty: Type) Param { - return Param{ .name = name, .ty = ty }; - } -}; - -pub const Method = struct { - const Self = @This(); - const ParamList = std.ArrayList(Param); - - name: []const u8, - instance: bool, - return_type: Type, - params: ParamList, - - pub fn init(name: []const u8, instance: bool, return_type: Type, params: ParamList) Method { - return Method{ - .name = name, - .instance = instance, - .return_type = return_type, - .params = params, - }; - } - - pub fn deinit(self: *Self) void { - self.params.deinit(); - } -}; - -pub const Container = struct { - const Self = @This(); - const ContainerList = std.ArrayList(*Container); - const TypeParamList = std.ArrayList(TypeParam); - const PropertyList = std.ArrayList(Property); - const MethodList = std.ArrayList(Method); - - name: []const u8, - super: ?*Container, - protocols: ContainerList, - type_params: TypeParamList, - properties: PropertyList, - methods: MethodList, - is_interface: bool, - ambiguous: bool, // Same typename as protocol and interface - - pub fn init(allocator: std.mem.Allocator, name: []const u8, is_interface: bool) Container { - return Container{ - .name = name, - .super = null, - .protocols = ContainerList.init(allocator), - .type_params = TypeParamList.init(allocator), - .properties = PropertyList.init(allocator), - .methods = MethodList.init(allocator), - .is_interface = is_interface, - .ambiguous = false, - }; - } - - pub fn deinit(self: *Self) void { - self.protocols.deinit(); - self.type_params.deinit(); - self.properties.deinit(); - for (self.methods.items) |*method| { - method.deinit(); - } - self.methods.deinit(); - } -}; - -pub const Registry = struct { - const Self = @This(); - const TypedefHashMap = std.StringHashMap(Type); - const EnumHashMap = std.StringHashMap(*Enum); - const ContainerHashMap = std.StringHashMap(*Container); - - allocator: std.mem.Allocator, - typedefs: TypedefHashMap, - enums: EnumHashMap, - protocols: ContainerHashMap, - interfaces: ContainerHashMap, - - pub fn init(allocator: std.mem.Allocator) Registry { - return Registry{ - .allocator = allocator, - .typedefs = TypedefHashMap.init(allocator), - .enums = EnumHashMap.init(allocator), - .protocols = ContainerHashMap.init(allocator), - .interfaces = ContainerHashMap.init(allocator), - }; - } - - pub fn deinit(self: *Self) void { - self.typedefs.deinit(); - self.deinitMap(&self.enums); - self.deinitMap(&self.protocols); - self.deinitMap(&self.interfaces); - } - - fn deinitMap(self: *Self, map: anytype) void { - var it = map.iterator(); - while (it.next()) |entry| { - var value = entry.value_ptr.*; - value.deinit(); - self.allocator.destroy(value); - } - map.deinit(); - } - - pub fn getEnum(self: *Self, name: []const u8) !*Enum { - const v = try self.enums.getOrPut(name); - if (v.found_existing) { - return v.value_ptr.*; - } else { - const e = try self.allocator.create(Enum); - e.* = Enum.init(self.allocator, name); - v.value_ptr.* = e; - return e; - } - } - - pub fn getProtocol(self: *Self, name: []const u8) !*Container { - return try self.getContainer(&self.protocols, &self.interfaces, name, false); - } - - pub fn getInterface(self: *Self, name: []const u8) !*Container { - return try self.getContainer(&self.interfaces, &self.protocols, name, true); - } - - fn getContainer( - self: *Self, - primary: *ContainerHashMap, - secondary: *ContainerHashMap, - name: []const u8, - is_interface: bool, - ) !*Container { - const v = try primary.getOrPut(name); - var container: *Container = undefined; - if (v.found_existing) { - container = v.value_ptr.*; - } else { - container = try self.allocator.create(Container); - container.* = Container.init(self.allocator, name, is_interface); - v.value_ptr.* = container; - } - - if (secondary.get(name)) |other| { - other.ambiguous = true; - container.ambiguous = true; - } - - return container; - } -};