Compare commits
1 commit
master
...
feature/fo
| Author | SHA1 | Date | |
|---|---|---|---|
| ce6ce6575d |
14 changed files with 314 additions and 1662 deletions
|
|
@ -18,7 +18,9 @@ pub fn build(b: *std.Build) void {
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
run_cmd.addPassthruArgs();
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
const run_step = b.step("run", "Run the app");
|
const run_step = b.step("run", "Run the app");
|
||||||
run_step.dependOn(&run_cmd.step);
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
|
||||||
12
flake.lock
generated
12
flake.lock
generated
|
|
@ -5,11 +5,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1791914995,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-Zf/xfQEAasnwnmEfHqW/4hjDE/s44yn2hD4RuVIZRjA=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "b7a79d3fea1e214f6d668d521cecec0c01e26544",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1793110635,
|
"lastModified": 1781577229,
|
||||||
"narHash": "sha256-dhoW6VgFWlaodSY5jrBn+CF2FLmaUvDVgM7+C7T2+NM=",
|
"narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "31ecbaca1bdefa45dffc409f0250bd8039ea0010",
|
"rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const EnumFlags = @import("EnumFlags.zig").EnumFlags;
|
const EnumFlags = @import("EnumFlags.zig").EnumFlags;
|
||||||
|
const Formatter = @import("Formatter.zig");
|
||||||
|
|
||||||
pub const FieldInfo = @import("Class/FieldInfo.zig");
|
allocator: std.mem.Allocator,
|
||||||
pub const MethodInfo = @import("Class/MethodInfo.zig");
|
|
||||||
pub const AttributeInfo = @import("Class/AttributeInfo.zig").AttributeInfo;
|
|
||||||
pub const ConstantPool = @import("Class/ConstantPool.zig");
|
|
||||||
|
|
||||||
magic: u32,
|
magic: u32,
|
||||||
minor_version: u16,
|
minor_version: u16,
|
||||||
|
|
@ -21,6 +19,11 @@ attributes: []AttributeInfo,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
pub const FieldInfo = @import("Class/FieldInfo.zig");
|
||||||
|
pub const MethodInfo = @import("Class/MethodInfo.zig");
|
||||||
|
pub const AttributeInfo = @import("Class/AttributeInfo.zig").AttributeInfo;
|
||||||
|
pub const ConstantPool = @import("Class/ConstantPool.zig");
|
||||||
|
|
||||||
pub const ClassAccessFlags = EnumFlags(enum(u16) {
|
pub const ClassAccessFlags = EnumFlags(enum(u16) {
|
||||||
public = 0x0001,
|
public = 0x0001,
|
||||||
final = 0x0010,
|
final = 0x0010,
|
||||||
|
|
@ -33,14 +36,12 @@ pub const ClassAccessFlags = EnumFlags(enum(u16) {
|
||||||
module = 0x8000,
|
module = 0x8000,
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const ParseError = std.Io.Reader.Error || std.mem.Allocator.Error || error{
|
pub const ParseError = std.Io.Reader.Error || std.mem.Allocator.Error || error {
|
||||||
InvalidMagicNumber,
|
InvalidMagicNumber,
|
||||||
InvalidTag,
|
InvalidTag,
|
||||||
InvalidOp,
|
|
||||||
InvalidArrayType,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ResolveError = error{
|
pub const ResolveError = error {
|
||||||
InvalidConstantPoolIndex,
|
InvalidConstantPoolIndex,
|
||||||
InvalidConstantType,
|
InvalidConstantType,
|
||||||
};
|
};
|
||||||
|
|
@ -57,7 +58,7 @@ pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) (ParseError ||
|
||||||
var constant_pool: ConstantPool = try .parse(input, allocator);
|
var constant_pool: ConstantPool = try .parse(input, allocator);
|
||||||
errdefer constant_pool.deinit(allocator);
|
errdefer constant_pool.deinit(allocator);
|
||||||
|
|
||||||
const access_flags: ClassAccessFlags = .from(try input.takeInt(u16, .big));
|
const access_flags: ClassAccessFlags = .{ .mask = try input.takeInt(u16, .big) };
|
||||||
|
|
||||||
const this_class = try input.takeInt(u16, .big);
|
const this_class = try input.takeInt(u16, .big);
|
||||||
const super_class = try input.takeInt(u16, .big);
|
const super_class = try input.takeInt(u16, .big);
|
||||||
|
|
@ -90,6 +91,7 @@ pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) (ParseError ||
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
|
.allocator = allocator,
|
||||||
.magic = magic,
|
.magic = magic,
|
||||||
.minor_version = minor_version,
|
.minor_version = minor_version,
|
||||||
.major_version = major_version,
|
.major_version = major_version,
|
||||||
|
|
@ -121,12 +123,8 @@ fn parseFields(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: st
|
||||||
const fields = try allocator.alloc(FieldInfo, fields_count);
|
const fields = try allocator.alloc(FieldInfo, fields_count);
|
||||||
errdefer allocator.free(fields);
|
errdefer allocator.free(fields);
|
||||||
|
|
||||||
var parsed: usize = 0;
|
|
||||||
errdefer for (0..parsed) |i| fields[i].deinit(allocator);
|
|
||||||
|
|
||||||
for (0..fields_count) |i| {
|
for (0..fields_count) |i| {
|
||||||
fields[i] = try .parse(input, constant_pool, allocator);
|
fields[i] = try FieldInfo.parse(input, constant_pool, allocator);
|
||||||
parsed += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
|
|
@ -137,12 +135,8 @@ fn parseMethods(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: s
|
||||||
const methods = try allocator.alloc(MethodInfo, methods_count);
|
const methods = try allocator.alloc(MethodInfo, methods_count);
|
||||||
errdefer allocator.free(methods);
|
errdefer allocator.free(methods);
|
||||||
|
|
||||||
var parsed: usize = 0;
|
|
||||||
errdefer for (0..parsed) |i| methods[i].deinit(allocator);
|
|
||||||
|
|
||||||
for (0..methods_count) |i| {
|
for (0..methods_count) |i| {
|
||||||
methods[i] = try .parse(input, constant_pool, allocator);
|
methods[i] = try .parse(input, constant_pool, allocator);
|
||||||
parsed += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return methods;
|
return methods;
|
||||||
|
|
@ -153,47 +147,71 @@ pub fn parseAttributes(input: *std.Io.Reader, constant_pool: ConstantPool, alloc
|
||||||
const attributes = try allocator.alloc(AttributeInfo, attributes_count);
|
const attributes = try allocator.alloc(AttributeInfo, attributes_count);
|
||||||
errdefer allocator.free(attributes);
|
errdefer allocator.free(attributes);
|
||||||
|
|
||||||
var parsed: usize = 0;
|
|
||||||
errdefer for (0..parsed) |i| attributes[i].deinit(allocator);
|
|
||||||
|
|
||||||
for (0..attributes_count) |i| {
|
for (0..attributes_count) |i| {
|
||||||
attributes[i] = try .parse(input, constant_pool, allocator);
|
attributes[i] = try AttributeInfo.parse(input, constant_pool, allocator);
|
||||||
parsed += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *Self) void {
|
||||||
self.constant_pool.deinit(allocator);
|
self.constant_pool.deinit(self.allocator);
|
||||||
|
self.freeInterfaces();
|
||||||
|
self.freeFields();
|
||||||
|
self.freeMethods();
|
||||||
|
self.freeAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
allocator.free(self.interfaces);
|
fn freeInterfaces(self: *Self) void {
|
||||||
|
self.allocator.free(self.interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn freeFields(self: *Self) void {
|
||||||
for (self.fields) |*field_info| {
|
for (self.fields) |*field_info| {
|
||||||
field_info.deinit(allocator);
|
field_info.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
allocator.free(self.fields);
|
self.allocator.free(self.fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn freeMethods(self: *Self) void {
|
||||||
for (self.methods) |*method_info| {
|
for (self.methods) |*method_info| {
|
||||||
method_info.deinit(allocator);
|
method_info.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
allocator.free(self.methods);
|
self.allocator.free(self.methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn freeAttributes(self: *Self) void {
|
||||||
for (self.attributes) |*attr| {
|
for (self.attributes) |*attr| {
|
||||||
attr.deinit(allocator);
|
attr.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
allocator.free(self.attributes);
|
self.allocator.free(self.attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn jsonStringify(self: *const Self, jws: *std.json.Stringify) !void {
|
||||||
|
try jws.beginObject();
|
||||||
|
|
||||||
|
inline for (std.meta.fields(Self)) |field| {
|
||||||
|
if (comptime std.mem.eql(u8, field.name, "allocator")) continue;
|
||||||
|
try jws.objectField(field.name);
|
||||||
|
try jws.write(@field(self, field.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
try jws.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn acceptFormatter(self: *const Self, formatter: *Formatter) Formatter.Error!void {
|
||||||
|
try formatter.printField("magic", "0x{X}", .{ self.magic });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
const depth = 2;
|
const depth = 2;
|
||||||
var indent: u8 = 0;
|
var indent: u8 = 0;
|
||||||
|
|
||||||
try w.print("magic: 0x{X}\n", .{self.magic});
|
try w.print("magic: 0x{X}\n", .{ self.magic });
|
||||||
|
|
||||||
try w.print("version: {d}.{d}\n", .{ self.major_version, self.minor_version });
|
try w.print("version: {d}.{d}\n", .{ self.major_version, self.minor_version });
|
||||||
|
|
||||||
try w.print("flags: {f}\n", .{self.access_flags});
|
try w.print("flags: {f}\n", .{ self.access_flags });
|
||||||
|
|
||||||
const this_class = self.thisClass() catch return error.WriteFailed;
|
const this_class = self.thisClass() catch return error.WriteFailed;
|
||||||
_ = try w.write("this class:\n");
|
_ = try w.write("this class:\n");
|
||||||
|
|
@ -212,7 +230,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
const info = self.constant_pool.getTag(interface, .class) catch return error.WriteFailed;
|
const info = self.constant_pool.getTag(interface, .class) catch return error.WriteFailed;
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("{d}:\n", .{i});
|
try w.print("{d}:\n", .{ i });
|
||||||
try info.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
try info.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,7 +240,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
defer indent -= 1;
|
defer indent -= 1;
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("{d}:\n", .{i});
|
try w.print("{d}:\n", .{ i });
|
||||||
try field.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
try field.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,7 +250,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
defer indent -= 1;
|
defer indent -= 1;
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("{d}:\n", .{i});
|
try w.print("{d}:\n", .{ i });
|
||||||
try method.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
try method.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +260,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
defer indent -= 1;
|
defer indent -= 1;
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("{d}:\n", .{i});
|
try w.print("{d}:\n", .{ i });
|
||||||
try attribute.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
try attribute.indentedFormat(w, depth, indent + 1, self.constant_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -254,3 +272,4 @@ pub fn thisClass(self: *const Self) ResolveError!ConstantPool.Info {
|
||||||
pub fn superClass(self: *const Self) ResolveError!?ConstantPool.Info {
|
pub fn superClass(self: *const Self) ResolveError!?ConstantPool.Info {
|
||||||
return self.constant_pool.getTagOptional(self.super_class, .class);
|
return self.constant_pool.getTagOptional(self.super_class, .class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -355,23 +355,23 @@ pub const Info = union(Info.Tag) {
|
||||||
|
|
||||||
pub fn format(self: *const Info, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
pub fn format(self: *const Info, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
switch (self.*) {
|
switch (self.*) {
|
||||||
.class => |class| try w.print("#{d}", .{class.name_index}),
|
.class => |class| try w.print("#{d}", .{ class.name_index }),
|
||||||
.field_ref => |field_ref| try w.print("#{d}.#{d}", .{ field_ref.class_index, field_ref.name_and_type_index }),
|
.field_ref => |field_ref| try w.print("#{d}.#{d}", .{ field_ref.class_index, field_ref.name_and_type_index }),
|
||||||
.method_ref => |method_ref| try w.print("#{d}.#{d}", .{ method_ref.class_index, method_ref.name_and_type_index }),
|
.method_ref => |method_ref| try w.print("#{d}.#{d}", .{ method_ref.class_index, method_ref.name_and_type_index }),
|
||||||
.interface_method_ref => |interface_method_ref| try w.print("#{d}.#{d}", .{ interface_method_ref.class_index, interface_method_ref.name_and_type_index }),
|
.interface_method_ref => |interface_method_ref| try w.print("#{d}.#{d}", .{ interface_method_ref.class_index, interface_method_ref.name_and_type_index }),
|
||||||
.string => |string| try w.print("#{d}", .{string.string_index}),
|
.string => |string| try w.print("#{d}", .{ string.string_index }),
|
||||||
.integer => |integer| try w.print("{d}", .{integer.bytes}),
|
.integer => |integer| try w.print("{d}", .{ integer.bytes }),
|
||||||
.float => |float| try w.print("{d}", .{float.float()}),
|
.float => |float| try w.print("{d}", .{ float.float() }),
|
||||||
.long => |long| try w.print("{d}", .{long.long()}),
|
.long => |long| try w.print("{d}", .{ long.long() }),
|
||||||
.double => |double| try w.print("{d}", .{double.double()}),
|
.double => |double| try w.print("{d}", .{ double.double() }),
|
||||||
.name_and_type => |name_and_type| try w.print("#{d}:#{d}", .{ name_and_type.name_index, name_and_type.descriptor_index }),
|
.name_and_type => |name_and_type| try w.print("#{d}:#{d}", .{ name_and_type.name_index, name_and_type.descriptor_index }),
|
||||||
.utf8 => |utf8| try w.print("\"{s}\"", .{utf8.bytes}),
|
.utf8 => |utf8| try w.print("\"{s}\"", .{ utf8.bytes }),
|
||||||
.method_handle => |method_handle| try w.print("{t} #{d}", .{ method_handle.reference_kind, method_handle.reference_index }),
|
.method_handle => |method_handle| try w.print("{t} #{d}", .{ method_handle.reference_kind, method_handle.reference_index }),
|
||||||
.method_type => |method_type| try w.print("#{d}", .{method_type.descriptor_index}),
|
.method_type => |method_type| try w.print("#{d}", .{ method_type.descriptor_index }),
|
||||||
.dynamic => |dynamic| try w.print("#{d} #{d}", .{ dynamic.bootstrap_method_attr_index, dynamic.name_and_type_index }),
|
.dynamic => |dynamic| try w.print("#{d} #{d}", .{ dynamic.bootstrap_method_attr_index, dynamic.name_and_type_index }),
|
||||||
.invoke_dynamic => |invoke_dynamic| try w.print("#{d} #{d}", .{ invoke_dynamic.bootstrap_method_attr_index, invoke_dynamic.name_and_type_index }),
|
.invoke_dynamic => |invoke_dynamic| try w.print("#{d} #{d}", .{ invoke_dynamic.bootstrap_method_attr_index, invoke_dynamic.name_and_type_index }),
|
||||||
.module => |module| try w.print("#{d}", .{module.name_index}),
|
.module => |module| try w.print("#{d}", .{ module.name_index }),
|
||||||
.package => |package| try w.print("#{d}", .{package.name_index}),
|
.package => |package| try w.print("#{d}", .{ package.name_index }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,7 +383,7 @@ pub const Info = union(Info.Tag) {
|
||||||
constant_pool: Self,
|
constant_pool: Self,
|
||||||
) std.Io.Writer.Error!void {
|
) std.Io.Writer.Error!void {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("constant_value_type: {t}\n", .{self.*});
|
try w.print("constant_value_type: {t}\n", .{ self.* });
|
||||||
|
|
||||||
switch (self.*) {
|
switch (self.*) {
|
||||||
.class => |*class| {
|
.class => |*class| {
|
||||||
|
|
@ -409,19 +409,19 @@ pub const Info = union(Info.Tag) {
|
||||||
},
|
},
|
||||||
.integer => |*integer| {
|
.integer => |*integer| {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("integer: {d}\n", .{integer.bytes});
|
try w.print("integer: {d}\n", .{ integer.bytes });
|
||||||
},
|
},
|
||||||
.float => |*float| {
|
.float => |*float| {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("float: {d}\n", .{float.float()});
|
try w.print("float: {d}\n", .{ float.float() });
|
||||||
},
|
},
|
||||||
.long => |*long| {
|
.long => |*long| {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("long: {d}\n", .{long.long()});
|
try w.print("long: {d}\n", .{ long.long() });
|
||||||
},
|
},
|
||||||
.double => |*double| {
|
.double => |*double| {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("double: {d}\n", .{double.double()});
|
try w.print("double: {d}\n", .{ double.double() });
|
||||||
},
|
},
|
||||||
.name_and_type => |*name_and_type| {
|
.name_and_type => |*name_and_type| {
|
||||||
try formatInfo(w, depth, indent, "name", name_and_type, .name, constant_pool);
|
try formatInfo(w, depth, indent, "name", name_and_type, .name, constant_pool);
|
||||||
|
|
@ -430,11 +430,11 @@ pub const Info = union(Info.Tag) {
|
||||||
},
|
},
|
||||||
.utf8 => |*utf8| {
|
.utf8 => |*utf8| {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("bytes: \"{s}\"\n", .{utf8.bytes});
|
try w.print("bytes: \"{s}\"\n", .{ utf8.bytes });
|
||||||
},
|
},
|
||||||
.method_handle => |*method_handle| {
|
.method_handle => |*method_handle| {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("kind: {t}\n", .{method_handle.reference_kind});
|
try w.print("kind: {t}\n", .{ method_handle.reference_kind });
|
||||||
|
|
||||||
try formatInfo(w, depth, indent, "descriptor", method_handle, .reference, constant_pool);
|
try formatInfo(w, depth, indent, "descriptor", method_handle, .reference, constant_pool);
|
||||||
},
|
},
|
||||||
|
|
@ -466,18 +466,8 @@ pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Sel
|
||||||
const constant_pool = try allocator.alloc(?Info, constant_pool_size - 1);
|
const constant_pool = try allocator.alloc(?Info, constant_pool_size - 1);
|
||||||
errdefer allocator.free(constant_pool);
|
errdefer allocator.free(constant_pool);
|
||||||
|
|
||||||
var parsed: usize = 0;
|
|
||||||
errdefer {
|
|
||||||
for (0..parsed) |i| {
|
|
||||||
if (constant_pool[i]) |*info| {
|
|
||||||
info.deinit(allocator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < constant_pool_size - 1) {
|
while (i < constant_pool_size - 1) {
|
||||||
defer parsed = i;
|
|
||||||
defer i += 1;
|
defer i += 1;
|
||||||
|
|
||||||
const info: Info = try .parse(input, allocator);
|
const info: Info = try .parse(input, allocator);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ pub const FieldAccessFlags = EnumFlags(enum(u16) {
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn parse(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: std.mem.Allocator) !Self {
|
pub fn parse(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: std.mem.Allocator) !Self {
|
||||||
const access_flags: FieldAccessFlags = .from(try input.takeInt(u16, .big));
|
const access_flags: FieldAccessFlags = .{ .mask = try input.takeInt(u16, .big) };
|
||||||
const name_index = try input.takeInt(u16, .big);
|
const name_index = try input.takeInt(u16, .big);
|
||||||
const descriptor_index = try input.takeInt(u16, .big);
|
const descriptor_index = try input.takeInt(u16, .big);
|
||||||
const attributes = try Class.parseAttributes(input, constant_pool, allocator);
|
const attributes = try Class.parseAttributes(input, constant_pool, allocator);
|
||||||
|
|
@ -54,7 +54,7 @@ pub fn indentedFormat(
|
||||||
constant_pool: ConstantPool,
|
constant_pool: ConstantPool,
|
||||||
) std.Io.Writer.Error!void {
|
) std.Io.Writer.Error!void {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("flags: {f}\n", .{self.access_flags});
|
try w.print("flags: {f}\n", .{ self.access_flags });
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
_ = try w.write("name:\n");
|
_ = try w.write("name:\n");
|
||||||
|
|
@ -74,7 +74,7 @@ pub fn indentedFormat(
|
||||||
defer attr_indent -= 1;
|
defer attr_indent -= 1;
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * attr_indent);
|
try w.splatByteAll(' ', depth * attr_indent);
|
||||||
try w.print("{d}:\n", .{j});
|
try w.print("{d}:\n", .{ j });
|
||||||
|
|
||||||
try attribute.indentedFormat(w, depth, attr_indent + 1, constant_pool);
|
try attribute.indentedFormat(w, depth, attr_indent + 1, constant_pool);
|
||||||
}
|
}
|
||||||
|
|
@ -87,3 +87,4 @@ pub fn name(self: *const Self, constant_pool: ConstantPool) ResolveError!Constan
|
||||||
pub fn descriptor(self: *const Self, constant_pool: ConstantPool) ResolveError!ConstantPool.Info {
|
pub fn descriptor(self: *const Self, constant_pool: ConstantPool) ResolveError!ConstantPool.Info {
|
||||||
return constant_pool.getTag(self.descriptor_index, .utf8);
|
return constant_pool.getTag(self.descriptor_index, .utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ pub const MethodAccessFlags = EnumFlags(enum(u16) {
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn parse(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: std.mem.Allocator) !Self {
|
pub fn parse(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: std.mem.Allocator) !Self {
|
||||||
const access_flags: MethodAccessFlags = .from(try input.takeInt(u16, .big));
|
const access_flags: MethodAccessFlags = .{ .mask = try input.takeInt(u16, .big) };
|
||||||
const name_index = try input.takeInt(u16, .big);
|
const name_index = try input.takeInt(u16, .big);
|
||||||
const descriptor_index = try input.takeInt(u16, .big);
|
const descriptor_index = try input.takeInt(u16, .big);
|
||||||
const attributes = try Class.parseAttributes(input, constant_pool, allocator);
|
const attributes = try Class.parseAttributes(input, constant_pool, allocator);
|
||||||
|
|
@ -57,7 +57,7 @@ pub fn indentedFormat(
|
||||||
constant_pool: ConstantPool,
|
constant_pool: ConstantPool,
|
||||||
) std.Io.Writer.Error!void {
|
) std.Io.Writer.Error!void {
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("flags: {f}\n", .{self.access_flags});
|
try w.print("flags: {f}\n", .{ self.access_flags });
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
_ = try w.write("name:\n");
|
_ = try w.write("name:\n");
|
||||||
|
|
@ -77,7 +77,7 @@ pub fn indentedFormat(
|
||||||
defer attr_indent -= 1;
|
defer attr_indent -= 1;
|
||||||
|
|
||||||
try w.splatByteAll(' ', depth * attr_indent);
|
try w.splatByteAll(' ', depth * attr_indent);
|
||||||
try w.print("{d}:\n", .{j});
|
try w.print("{d}:\n", .{ j });
|
||||||
|
|
||||||
try attribute.indentedFormat(w, depth, attr_indent + 1, constant_pool);
|
try attribute.indentedFormat(w, depth, attr_indent + 1, constant_pool);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,40 +10,35 @@ pub fn EnumFlags(comptime E: type) type {
|
||||||
|
|
||||||
pub const empty: Self = .{ .data = 0 };
|
pub const empty: Self = .{ .data = 0 };
|
||||||
|
|
||||||
pub fn from(mask: BackingInt) Self {
|
|
||||||
return .{
|
|
||||||
.mask = mask,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn contains(self: Self, flag: E) bool {
|
pub fn contains(self: Self, flag: E) bool {
|
||||||
return (self.mask & @backingInt(flag)) != 0;
|
return (self.mask & @intFromEnum(flag)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(self: *Self, flag: E) void {
|
pub fn insert(self: *Self, flag: E) void {
|
||||||
self.mask |= @backingInt(flag);
|
self.mask |= @intFromEnum(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(self: *Self, flag: E) void {
|
pub fn remove(self: *Self, flag: E) void {
|
||||||
self.mask &= ~@backingInt(flag);
|
self.mask &= ~@intFromEnum(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle(self: *Self, flag: E) void {
|
pub fn toggle(self: *Self, flag: E) void {
|
||||||
self.mask ^= @backingInt(flag);
|
self.mask ^= @intFromEnum(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
inline for (@typeInfo(E).@"enum".field_names) |field| {
|
inline for (std.meta.fields(E)) |field| {
|
||||||
const key = @field(E, field);
|
const key = @field(E, field.name);
|
||||||
if (self.contains(key)) {
|
if (self.contains(key)) {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
_ = try w.write(" | ");
|
_ = try w.write(" | ");
|
||||||
}
|
}
|
||||||
try w.print("{s}", .{field});
|
try w.print("{s}", .{ field.name });
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
57
src/Formatter.zig
Normal file
57
src/Formatter.zig
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const Error = error {};
|
||||||
|
|
||||||
|
vtable: *const VTable,
|
||||||
|
w: *std.Io.Writer,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub const VTable = struct {
|
||||||
|
printField: *const fn (
|
||||||
|
ptr: *Self,
|
||||||
|
comptime field: []const u8,
|
||||||
|
comptime fmt: []const u8,
|
||||||
|
args: anytype,
|
||||||
|
) Error!void,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn printField(
|
||||||
|
self: *const Self,
|
||||||
|
comptime field: []const u8,
|
||||||
|
value: anytype,
|
||||||
|
) Error!void {
|
||||||
|
self.vtable.field(self, field);
|
||||||
|
self.vtable.value(self, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const IndentedFormatter = struct {
|
||||||
|
indent: u8 = 0,
|
||||||
|
depth: usize = 0,
|
||||||
|
|
||||||
|
interface: Self,
|
||||||
|
|
||||||
|
pub fn init(w: *std.Io.Writer) IndentedFormatter {
|
||||||
|
return .{
|
||||||
|
.interface = .{
|
||||||
|
.vtable = &.{
|
||||||
|
.printField = IndentedFormatter.printField,
|
||||||
|
},
|
||||||
|
.w = w,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printField(
|
||||||
|
f: *Self,
|
||||||
|
comptime field: []const u8,
|
||||||
|
comptime fmt: []const u8,
|
||||||
|
args: anytype,
|
||||||
|
) Error!void {
|
||||||
|
const self: *IndentedFormatter = @alignCast(@fieldParentPtr("interface", f));
|
||||||
|
|
||||||
|
_ = try self.interface.w.splatByteAll(' ', self.indent * self.depth);
|
||||||
|
try self.interface.w.print(field ++ ": " ++ fmt ++ "\n", args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
18
src/main.zig
18
src/main.zig
|
|
@ -2,6 +2,8 @@ const std = @import("std");
|
||||||
|
|
||||||
const Class = @import("Class.zig");
|
const Class = @import("Class.zig");
|
||||||
|
|
||||||
|
const Formatter = @import("Formatter.zig");
|
||||||
|
|
||||||
pub fn main(init: std.process.Init) !void {
|
pub fn main(init: std.process.Init) !void {
|
||||||
const io = init.io;
|
const io = init.io;
|
||||||
const allocator = init.gpa;
|
const allocator = init.gpa;
|
||||||
|
|
@ -19,17 +21,17 @@ pub fn main(init: std.process.Init) !void {
|
||||||
std.debug.assert(args.skip());
|
std.debug.assert(args.skip());
|
||||||
const file_path = if (args.next()) |fp| fp else {
|
const file_path = if (args.next()) |fp| fp else {
|
||||||
try stderr.writeAll("No file argument provided.\n");
|
try stderr.writeAll("No file argument provided.\n");
|
||||||
std.process.exit(1);
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
const file = std.Io.Dir.cwd().openFile(io, file_path, .{}) catch |err| switch (err) {
|
const file = std.Io.Dir.cwd().openFile(io, file_path, .{}) catch |err| switch (err) {
|
||||||
error.FileNotFound => {
|
error.FileNotFound => {
|
||||||
try stderr.writeAll("File not found.\n");
|
try stderr.writeAll("File not found.\n");
|
||||||
std.process.exit(1);
|
return;
|
||||||
},
|
},
|
||||||
error.IsDir => {
|
error.IsDir => {
|
||||||
try stderr.writeAll("Path is a directory.\n");
|
try stderr.writeAll("Path is a directory.\n");
|
||||||
std.process.exit(1);
|
return;
|
||||||
},
|
},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|
@ -42,17 +44,19 @@ pub fn main(init: std.process.Init) !void {
|
||||||
var class = Class.parse(reader, allocator) catch |err| switch (err) {
|
var class = Class.parse(reader, allocator) catch |err| switch (err) {
|
||||||
error.InvalidMagicNumber => {
|
error.InvalidMagicNumber => {
|
||||||
try stderr.writeAll("Invalid magic number.\n");
|
try stderr.writeAll("Invalid magic number.\n");
|
||||||
std.process.exit(1);
|
return;
|
||||||
},
|
},
|
||||||
error.InvalidTag => {
|
error.InvalidTag => {
|
||||||
try stderr.writeAll("Unrecognized tag type.\n");
|
try stderr.writeAll("Unrecognized tag type.\n");
|
||||||
std.process.exit(1);
|
return;
|
||||||
},
|
},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
defer class.deinit(allocator);
|
defer class.deinit();
|
||||||
|
|
||||||
try stdout.print("{f}", .{class});
|
var indented_formatter: Formatter.IndentedFormatter = .init(stdout);
|
||||||
|
const formatter = &indented_formatter.interface;
|
||||||
|
try class.acceptFormatter(formatter);
|
||||||
|
|
||||||
try stdout.flush();
|
try stdout.flush();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,52 +17,6 @@ public class Main implements Runnable, Supplier<Integer>, Interface {
|
||||||
} finally {
|
} finally {
|
||||||
System.err.println("Finally block");
|
System.err.println("Finally block");
|
||||||
}
|
}
|
||||||
|
|
||||||
var a = 8;
|
|
||||||
a <<= 3;
|
|
||||||
final var b = a >> 1;
|
|
||||||
switch (b) {
|
|
||||||
case 1:
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
System.out.println("Good");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
System.out.println("Number " + a);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
final var o = getObject();
|
|
||||||
switch (o) {
|
|
||||||
case Integer i:
|
|
||||||
switch (i) {
|
|
||||||
case 1:
|
|
||||||
System.out.println("One");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
System.out.println("Two");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
System.out.println("Three");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
System.out.println("Something else");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
inc(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object getObject() {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void inc(int i) {
|
|
||||||
i += 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
BIN
testsuite/classes/java/Object.class
Normal file
BIN
testsuite/classes/java/Object.class
Normal file
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
||||||
public record Record(String name, int age) {}
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue