From 351c593f5e2af7a3539303abe8281ce4780c9af3 Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Sun, 24 Dec 2023 05:58:11 +0100 Subject: [PATCH 1/2] Added support for function typedefs. Tested on RecastAssert.h -fparse-all-comments was needed to make sure all of the comments for it was included in the AST, not sure why. --- src/Transpiler.zig | 51 ++++++++++++++++++++++++++++++++++++++++------ src/main.zig | 1 + 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/Transpiler.zig b/src/Transpiler.zig index 0d44c7d..6127ce0 100644 --- a/src/Transpiler.zig +++ b/src/Transpiler.zig @@ -1594,13 +1594,10 @@ fn visitTypedefDecl(self: *Self, value: *const json.Value) !void { self.nodes_visited += 1; const name = value.object.get("name").?.string; + const v_inner_opt = value.object.getPtr("inner"); + try self.writeDocs(v_inner_opt); - if (value.object.get("inner")) |v_inner| { - if (v_inner.array.items.len != 1) { - log.err("complex typedef `{s}`", .{name}); - return; - } - + if (v_inner_opt) |v_inner| { const v_item = &v_inner.array.items[0]; const tag = v_item.object.get("kind").?.string; if (mem.eql(u8, tag, "BuiltinType") or mem.eql(u8, tag, "TypedefType")) { @@ -1652,6 +1649,16 @@ fn visitTypedefDecl(self: *Self, value: *const json.Value) !void { self.nodes_visited += 1; try self.out.print("pub const {s} = {s};\n\n", .{ name, typeQualifier(v_item).? }); return; + } else if (mem.eql(u8, tag, "ParenType")) { + self.nodes_visited += 1; + const parentype_inner_opt = v_inner.array.items[0].object.getPtr("inner"); + if (parentype_inner_opt) |parentype_inner| { + const parentype_inner_kind = parentype_inner.array.items[0].object.get("kind").?.string; + if (mem.eql(u8, parentype_inner_kind, "FunctionProtoType")) { + try self.visitFunctionProtoType(name, &parentype_inner.array.items[0]); + } + } + return; } else { log.err("unhandled `{s}` in typedef `{s}`", .{ tag, name }); return; @@ -1664,6 +1671,38 @@ fn visitTypedefDecl(self: *Self, value: *const json.Value) !void { } } +fn visitFunctionProtoType(self: *Self, name: []const u8, value: *const json.Value) !void { + self.nodes_visited += 1; + + try self.out.print("pub const {s} = fn(", .{name}); + + var return_type_opt: ?*const json.Value = null; + var inner_opt = value.object.getPtr("inner"); + if (inner_opt) |inner| { + for (inner.array.items, 0..) |*item, i| { + if (return_type_opt == null) { + return_type_opt = item; + continue; + } + + const zig_type = try self.transpileType(typeQualifier(item).?); + defer self.allocator.free(zig_type); + try self.out.print("{s}", .{zig_type}); + if (i + 1 < inner.array.items.len) { + try self.out.print(", ", .{}); + } + } + } + + if (return_type_opt) |return_type| { + const zig_type = try self.transpileType(typeQualifier(return_type).?); + defer self.allocator.free(zig_type); + try self.out.print(") callconv(.C) {s};\n\n", .{zig_type}); + } else { + try self.out.print(") callconv(.C) {s};\n\n", .{"void"}); + } +} + fn visitNamespaceDecl(self: *Self, value: *const json.Value) !void { if (self.shouldSkip(value)) { self.nodes_visited += nodeCount(value); diff --git a/src/main.zig b/src/main.zig index 48f950f..7082824 100644 --- a/src/main.zig +++ b/src/main.zig @@ -27,6 +27,7 @@ pub fn main() !void { try clang.append("-Xclang"); try clang.append("-ast-dump=json"); try clang.append("-fsyntax-only"); + try clang.append("-fparse-all-comments"); const argv = try std.process.argsAlloc(allocator); defer std.process.argsFree(allocator, argv); From 408318cfb6f77552bf17ba0d15facde1b0a3107d Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Tue, 26 Dec 2023 21:28:28 +0100 Subject: [PATCH 2/2] var -> const fix --- src/Transpiler.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Transpiler.zig b/src/Transpiler.zig index 6127ce0..2199cf3 100644 --- a/src/Transpiler.zig +++ b/src/Transpiler.zig @@ -1677,7 +1677,7 @@ fn visitFunctionProtoType(self: *Self, name: []const u8, value: *const json.Valu try self.out.print("pub const {s} = fn(", .{name}); var return_type_opt: ?*const json.Value = null; - var inner_opt = value.object.getPtr("inner"); + const inner_opt = value.object.getPtr("inner"); if (inner_opt) |inner| { for (inner.array.items, 0..) |*item, i| { if (return_type_opt == null) {