Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eliminate usingnamespace and runtime initialization #19

Merged
merged 4 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app_kit_manual.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const c = @import("c.zig");
const ca = @import("quartz_core.zig");
const cf = @import("core_foundation.zig");
const ns = @import("foundation.zig");
Expand All @@ -19,7 +18,6 @@ pub const TimeInterval = ns.TimeInterval;
pub const UInteger = ns.UInteger;
pub const unichar = ns.unichar;
pub const Range = ns.Range;
pub const Protocol = objc.Protocol;
pub const StringEncoding = ns.StringEncoding;
pub const StringTransform = ns.StringTransform;
pub const StringEncodingDetectionOptionsKey = ns.StringEncodingDetectionOptionsKey;
Expand Down
4 changes: 0 additions & 4 deletions avf_audio_manual.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const c = @import("c.zig");
const cf = @import("core_foundation.zig");
const ns = @import("foundation.zig");
const objc = @import("objc.zig");
Expand All @@ -14,6 +13,3 @@ pub const AVAudioSessionLocation = *ns.String;
pub const AVAudioSessionOrientation = *ns.String;

pub const AudioChannelLabel = u32;

// TODO - can we use definition in ns
extern const _NSConcreteStackBlock: *anyopaque;
1 change: 0 additions & 1 deletion core_midi_manual.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const c = @import("c.zig");
const cf = @import("core_foundation.zig");
const ns = @import("foundation.zig");

Expand Down
172 changes: 43 additions & 129 deletions generator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ pub const Parser = struct {
try self.match(.kw_class);
const props = try self.parsePointerProps(is_const);

const t = Type{ .name = "c.objc_class" };
const t = Type{ .name = "objc.Class" };

const child = try self.allocator.create(Type);
child.* = t;
Expand Down Expand Up @@ -469,7 +469,7 @@ pub const Parser = struct {

return self.parsePointerSuffix(types.items[0], is_const, true);
} else {
const t = Type{ .name = "c.objc_object" };
const t = Type{ .name = "objc.Id" };
return self.parsePointerSuffix(t, is_const, true);
}
},
Expand Down Expand Up @@ -1062,34 +1062,6 @@ fn Generator(comptime WriterType: type) type {
pub fn generate(self: *Self) !void {
try self.generateEnumerations();
try self.generateContainers();
try self.generateClasses();
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 generateInit(self: *Self) !void {
try self.writer.print("pub fn init() void {{\n", .{});
try self.generateInitClasses();
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 generateEnumerations(self: *Self) !void {
Expand Down Expand Up @@ -1136,90 +1108,52 @@ fn Generator(comptime WriterType: type) type {
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", .{});

var inherited_method_sets = std.ArrayList(*Container).init(self.allocator);
defer inherited_method_sets.deinit();
if (container.super) |super| {
const will_generate = blk: {
if (self.isExternalContainerName(super)) break :blk true;
if (getNamespace(super.name).len > 0) break :blk true;
for (self.containers.items) |container2| {
if (std.mem.eql(u8, container2.name, super.name)) break :blk true;
}
break :blk false;
};
if (will_generate) try inherited_method_sets.append(super);
}
for (container.protocols.items) |protocol| {
const will_generate = blk: {
if (self.isExternalContainerName(protocol)) break :blk true;
if (getNamespace(protocol.name).len > 0) break :blk true;

for (self.containers.items) |container2| {
if (std.mem.eql(u8, container2.name, protocol.name)) break :blk true;
}
break :blk false;
};
if (will_generate) try inherited_method_sets.append(protocol);
}

if (inherited_method_sets.items.len == 0 and container.methods.items.len == 0) {
try self.writer.print(" pub fn Methods(comptime _: type) type {{\n", .{});
try self.writer.print(" pub const InternalInfo = objc.ExternClass(\"{s}\", @This(), ", .{
container.name,
});
if (container.super) |super| {
try self.generateContainerName(super);
} else {
try self.writer.writeAll("objc.Id");
}
try self.writer.writeAll(", &.{");
} else {
try self.writer.print(" pub fn Methods(comptime T: type) type {{\n", .{});
try self.writer.writeAll(" pub const InternalInfo = objc.ExternProtocol(@This(), &.{");
}
try self.writer.print(" return struct {{\n", .{});

for (inherited_method_sets.items) |inherited| {
const will_generate = blk: {
if (self.isExternalContainerName(inherited)) break :blk true;
for (self.containers.items) |container2| {
if (std.mem.eql(u8, container2.name, inherited.name)) break :blk true;
var first = true;
for (container.protocols.items) |protocol| {
// TODO: optimize this O(n) lookup. We don't want to create references to protocols
// we don't generate, but this isn't a great way to do it. I plan on reworking the
// container generation code to take other frameworks into account so things like
// app_kit.zig doesn't duplicate NSObject (for example). Once that is done it will
// be easier to do an O(1) global symbol lookup across all frameworks.
for (self.containers.items) |c| {
if (std.mem.eql(u8, c.name, protocol.name)) {
if (!first) try self.writer.writeAll(", ");
first = false;
try self.generateContainerName(protocol);
}
break :blk false;
};
if (will_generate) {
try self.writer.print(" pub usingnamespace ", .{});
try self.generateContainerName(inherited);
try self.writer.print(".Methods(T);\n", .{});
}
}
if (inherited_method_sets.items.len > 0) {
try self.writer.print("\n", .{});
try self.writer.writeAll("});\n");
try self.writer.writeAll(" pub const as = InternalInfo.as;\n");
try self.writer.writeAll(" pub const retain = InternalInfo.retain;\n");
try self.writer.writeAll(" pub const release = InternalInfo.release;\n");
try self.writer.writeAll(" pub const autorelease = InternalInfo.autorelease;\n");

if (container.is_interface and self.doesParentHaveMethod(container, "init")) {
// TODO: check if the type (or one of its parents) marks new/alloc/init as NS_UNAVAILABLE.
try self.writer.writeAll(" pub const new = InternalInfo.new;\n");
try self.writer.writeAll(" pub const alloc = InternalInfo.alloc;\n");
try self.writer.writeAll(" pub const allocInit = InternalInfo.allocInit;\n");
}
try self.writer.writeByte('\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", .{});
Expand Down Expand Up @@ -1252,7 +1186,7 @@ fn Generator(comptime WriterType: type) type {
return;
}

try self.writer.writeAll(" pub fn ");
try self.writer.writeAll(" pub fn ");
try self.generateMethodName(method.name);
try self.writer.print("(", .{});
try self.generateMethodParams(method);
Expand All @@ -1262,7 +1196,7 @@ fn Generator(comptime WriterType: type) type {
try self.writer.writeAll(" return objc.msgSend(");
try self.generateMethodArgs(method);
try self.writer.print(");\n", .{});
try self.writer.print(" }}\n", .{});
try self.writer.print(" }}\n", .{});
}

fn doesParentHaveMethod(self: *Self, container: *Container, name: []const u8) bool {
Expand Down Expand Up @@ -1290,7 +1224,7 @@ fn Generator(comptime WriterType: type) type {
fn generateMethodParams(self: *Self, method: Method) !void {
var first = true;
if (method.instance) {
try self.writer.print("self_: *T", .{});
try self.writer.print("self_: *@This()", .{});
first = false;
}
for (method.params.items) |param| {
Expand Down Expand Up @@ -1319,31 +1253,11 @@ fn Generator(comptime WriterType: type) type {
}
}

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("@This().InternalInfo.class()", .{});
}
try self.writer.print(", \"{s}\", ", .{method.name});
try self.generateType(method.return_type);
Expand Down Expand Up @@ -1426,7 +1340,7 @@ fn Generator(comptime WriterType: type) type {
try self.generateTypeName(n);
},
.instance_type => {
try self.writer.writeAll("T");
try self.writer.writeAll("@This()");
},
.pointer => |p| {
if (p.is_optional)
Expand Down Expand Up @@ -1983,8 +1897,8 @@ fn generateAppKit(generator: anytype) !void {
generator.namespace = "NS";
generator.allow_methods = &.{
// TODO: move to generateFoundation
[2][]const u8{ "NSObject", "alloc" },
[2][]const u8{ "NSObject", "release" },
[2][]const u8{ "NSObject", "copy" },
[2][]const u8{ "NSObject", "retainCount" },

[2][]const u8{ "NSApplication", "sharedApplication" },
[2][]const u8{ "NSApplication", "setDelegate" },
Expand Down
4 changes: 0 additions & 4 deletions metal_manual.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const c = @import("c.zig");
const cf = @import("core_foundation.zig");
const ns = @import("foundation.zig");
const objc = @import("objc.zig");
Expand All @@ -10,9 +9,6 @@ pub const dispatch_data_t = *opaque {};
pub const dispatch_queue_t = *opaque {};
pub const IOSurfaceRef = *opaque {};

// TODO - can we use definition in ns
extern const _NSConcreteStackBlock: *anyopaque;

// ------------------------------------------------------------------------------------------------
// Types

Expand Down
Loading
Loading