Skip to content

Commit 6e648a6

Browse files
committed
Add writeStaticMethod
1 parent 92710ab commit 6e648a6

File tree

3 files changed

+86
-32
lines changed

3 files changed

+86
-32
lines changed

src/bindings.zig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const std = @import("std");
2+
const jui = @import("jui");
3+
4+
fn returnTypeLookup(comptime descriptor: []const u8, comptime descriptor_table: []const []const u8, comptime return_type: []const type) type {
5+
inline for (descriptor_table) |desc, i| {
6+
if (std.mem.eql(u8, desc, descriptor)) {
7+
return return_type[i];
8+
}
9+
}
10+
@compileError("Return Type Lookup: No descriptor " ++ descriptor ++ " found in descriptor_table");
11+
}

src/jui.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const std = @import("std");
22
const builtin = @import("builtin");
33

4+
pub const bindings = @import("bindings.zig");
45
pub const descriptors = @import("descriptors.zig");
56
pub const Reflector = @import("Reflector.zig");
67
const types = @import("types.zig");

tools/class2zig.zig

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ pub fn main() !void {
6464

6565
for (class_file.methods.items) |method| {
6666
const name = method.getName().bytes;
67+
if (std.mem.eql(u8, name, "<init>")) {
68+
try constructor_overloads.append(method);
69+
continue;
70+
}
6771
if (method.access_flags.static) {
68-
if (std.mem.eql(u8, name, "<init>")) {
69-
try constructor_overloads.append(method);
70-
continue;
71-
}
7272
const entry = try static_method_overloads.getOrPut(name);
7373
if (!entry.found_existing) entry.value_ptr.* = std.ArrayList(cf.MethodInfo).init(arena_alloc);
7474
try entry.value_ptr.*.append(method);
@@ -79,22 +79,26 @@ pub fn main() !void {
7979
try entry.value_ptr.*.append(method);
8080
}
8181

82+
std.log.info("Found {} constructors", .{
83+
constructor_overloads.items.len,
84+
});
85+
8286
// Write methods
8387

8488
var constructors = std.ArrayList(u8).init(arena_alloc);
8589
defer constructors.deinit();
8690

87-
try writeConstructors(constructor_overloads.items, arena_alloc, constructors.writer());
91+
try writeConstructors(constructor_overloads.items, constructors.writer());
8892

8993
var static_method_accessors = std.ArrayList(u8).init(arena_alloc);
9094
defer static_method_accessors.deinit();
9195

92-
// {
93-
// var iter = static_method_overloads.iterator();
94-
// while (iter.next()) |entry| {
95-
// try writeStaticMethodAccessors(entry.key_ptr.*, entry.value_ptr.*.items, arena_alloc, static_method_accessors.writer());
96-
// }
97-
// }
96+
{
97+
var iter = static_method_overloads.iterator();
98+
while (iter.next()) |entry| {
99+
try writeStaticMethod(entry.key_ptr.*, entry.value_ptr.*.items, arena_alloc, static_method_accessors.writer());
100+
}
101+
}
98102

99103
var method_accessors = std.ArrayList(u8).init(arena_alloc);
100104
defer method_accessors.deinit();
@@ -280,33 +284,71 @@ fn writeMethodDecls(methods: []cf.MethodInfo, writer: anytype) !void {
280284
}
281285
}
282286

283-
fn writeConstructors(methods: []cf.MethodInfo, allocator: std.mem.Allocator, writer: anytype) !void {
287+
fn writeConstructors(methods: []cf.MethodInfo, writer: anytype) !void {
288+
if (methods.len == 0) return;
289+
try writer.writeAll("\n");
290+
291+
try std.fmt.format(writer,
292+
\\ pub fn new(self: @This(), env: *jui.JNIEnv, descriptor: []const u8, args: ?[*]const jui.jvalue) !*Instance {{
293+
\\ const method_id = @field(self.Class.methods, "<init>" ++ descriptor) orelse method_id: {{
294+
\\ @field(self.Class.methods, "<init>" ++ descriptor) = try env.getMethodId(self.class, "<init>", descriptor);
295+
\\ break :method_id @field(self.Class.methods, "<init>" ++ descriptor).?;
296+
\\ }};
297+
\\ const object = try env.newObject(self.class, method_id, args);
298+
\\ return Instance {{ .class = self, .object = object }};
299+
\\ }}
300+
\\
301+
, .{});
302+
}
303+
304+
fn writeStaticMethod(name: []const u8, methods: []cf.MethodInfo, allocator: std.mem.Allocator, writer: anytype) !void {
284305
if (methods.len > 0) try writer.writeAll("\n");
285-
for (methods) |method| {
286-
const name = method.getName().bytes;
287-
if (!std.mem.eql(u8, name, "<init>")) continue;
288306

307+
// TODO: make sure the method_name is a valid identifier string
308+
309+
var overloads = std.ArrayList(u8).init(allocator);
310+
defer overloads.deinit();
311+
try overloads.writer().print(" const {s}_overloads = &[_][]const u8{{", .{name});
312+
313+
var return_types = std.ArrayList(u8).init(allocator);
314+
defer return_types.deinit();
315+
try return_types.writer().print(" const {s}_return_types = &[_]type{{", .{name});
316+
317+
for (methods) |method| {
289318
const descriptor = method.getDescriptor().bytes;
290319
var descriptor_info = try jui.descriptors.parseString(allocator, descriptor);
320+
defer descriptor_info.deinit(allocator);
291321
std.debug.assert(descriptor_info.* == .method);
292-
try std.fmt.format(writer,
293-
\\ pub fn @"<init>{[descriptor]s}"(self: @This(), env: *jui.JNIEnv, args: anytype) !*@This() {{
294-
\\ const method_id = self.methods.@"<init>{[descriptor]s}" orelse method_id: {{
295-
\\ self.methods.@"<init>{[descriptor]s}" = try env.getMethodId(self.class, "<init>", "{[descriptor]s}");
296-
\\ break :method_id self.methods.@"<init>{[descriptor]s}".?;
297-
\\ }};
298-
\\ comptime var arg_array = [_]jui.jvalue{{}};
299-
\\ inline for (args) |arg| {{
300-
\\ arg_array ++ .{{jui.jvalue.fromValue(arg)}};
301-
\\ }}
302-
\\ const object = try env.newObject(self.class, method_id, &arg_array);
303-
\\ return Instance {{ .class = self, .object = object }};
304-
\\ }}
305-
\\
306-
, .{
307-
.descriptor = descriptor,
308-
});
322+
323+
try overloads.writer().writeAll("\n \"");
324+
try overloads.writer().writeAll(descriptor);
325+
try overloads.writer().writeAll("\",");
326+
327+
try return_types.writer().writeAll("\n ");
328+
try return_types.writer().writeAll(descriptorAsTypeString(descriptor_info.*.method.return_type.*));
329+
try return_types.writer().writeAll(",");
309330
}
331+
332+
try overloads.writer().writeAll("\n };");
333+
try return_types.writer().writeAll("\n };");
334+
335+
try std.fmt.format(writer,
336+
\\{[overloads]s}
337+
\\{[return_types]s}
338+
\\ pub fn {[name]s}(self: @This(), env: *jui.JNIEnv, comptime descriptor: []const u8, args: ?[*]const jui.jvalue) !jui.bindings.returnTypeLookup(descriptor, {[name]s}_overloads, {[name]s}_return_types) {{
339+
\\ const method_id = @field(self.Class.methods, "{[name]s}" ++ descriptor) orelse method_id: {{
340+
\\ @field(self.Class.methods, "{[name]s}" ++ descriptor) = try env.getMethodId(self.class, "{[name]s}", descriptor);
341+
\\ break :method_id @field(self.Class.methods, "{[name]s}" ++ descriptor).?;
342+
\\ }};
343+
\\ const object = try env.newObject(self.class, method_id, arg_array);
344+
\\ return Instance {{ .class = self, .object = object }};
345+
\\ }}
346+
\\
347+
, .{
348+
.name = name,
349+
.overloads = overloads.items,
350+
.return_types = return_types.items,
351+
});
310352
}
311353

312354
fn descriptorAsTypeString(descriptor: jui.descriptors.Descriptor) []const u8 {

0 commit comments

Comments
 (0)