From 89e548c8ccc701dc35927714c90f50d8bbef87ce Mon Sep 17 00:00:00 2001 From: ktkk Date: Tue, 7 Jul 2026 23:23:38 +0200 Subject: [PATCH] Introduce constant pool info formatting helper --- src/Class/ConstantPool.zig | 164 ++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 94 deletions(-) diff --git a/src/Class/ConstantPool.zig b/src/Class/ConstantPool.zig index 6c5afe3..54c233f 100644 --- a/src/Class/ConstantPool.zig +++ b/src/Class/ConstantPool.zig @@ -116,16 +116,28 @@ pub const Info = union(Info.Tag) { pub const Float = struct { bytes: u32, + + pub fn float(self: *const Float) f32 { + return @bitCast(self.bytes); + } }; pub const Long = struct { high_bytes: u32, low_bytes: u32, + + pub fn long(self: *const Long) u64 { + return (@as(u64, self.high_bytes) << 32) | self.low_bytes; + } }; pub const Double = struct { high_bytes: u32, low_bytes: u32, + + pub fn double(self: *const Double) f64 { + return @bitCast((@as(u64, self.high_bytes) << 32) | self.low_bytes); + } }; pub const NameAndType = struct { @@ -349,12 +361,12 @@ pub const Info = union(Info.Tag) { .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 }), .integer => |integer| try w.print("{d}", .{ integer.bytes }), - .float => |float| try w.print("{d}", .{ @as(f32, @bitCast(float.bytes)) }), - .long => |long| try w.print("{d}", .{ (@as(u64, long.high_bytes) << 32) | long.low_bytes }), - .double => |double| try w.print("{d}", .{ @as(f64, @bitCast((@as(u64, double.high_bytes) << 32) | double.low_bytes)) }), + .float => |float| try w.print("{d}", .{ float.float() }), + .long => |long| try w.print("{d}", .{ long.long() }), + .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 }), .utf8 => |utf8| try w.print("\"{s}\"", .{ utf8.bytes }), - .method_handle => |method_handle| try w.print("{s} #{d}", .{ @tagName(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 }), .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 }), @@ -371,128 +383,75 @@ pub const Info = union(Info.Tag) { constant_pool: Self, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("constant_value_type: {s}\n", .{ @tagName(self.*) }); + try w.print("constant_value_type: {t}\n", .{ self.* }); switch (self.*) { - .class => |class| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name:\n"); - const class_name = class.name(constant_pool) catch return error.WriteFailed; - try class_name.indentedFormat(w, depth, indent + 1, constant_pool); + .class => |*class| { + try formatInfo(w, depth, indent, "name", class, .name, constant_pool); }, - .field_ref => |field_ref| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("class:\n"); - const class = field_ref.class(constant_pool) catch return error.WriteFailed; - try class.indentedFormat(w, depth, indent + 1, constant_pool); + .field_ref => |*field_ref| { + try formatInfo(w, depth, indent, "class", field_ref, .class, constant_pool); - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name_and_type:\n"); - const name_and_type = field_ref.nameAndType(constant_pool) catch return error.WriteFailed; - try name_and_type.indentedFormat(w, depth, indent + 1, constant_pool); + try formatInfo(w, depth, indent, "name_and_type", field_ref, .nameAndType, constant_pool); }, - .method_ref => |method_ref| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("class:\n"); - const class = method_ref.class(constant_pool) catch return error.WriteFailed; - try class.indentedFormat(w, depth, indent + 1, constant_pool); + .method_ref => |*method_ref| { + try formatInfo(w, depth, indent, "class", method_ref, .class, constant_pool); - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name_and_type:\n"); - const name_and_type = method_ref.nameAndType(constant_pool) catch return error.WriteFailed; - try name_and_type.indentedFormat(w, depth, indent + 1, constant_pool); + try formatInfo(w, depth, indent, "name_and_type", method_ref, .nameAndType, constant_pool); }, - .interface_method_ref => |interface_method_ref| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("class:\n"); - const class = interface_method_ref.class(constant_pool) catch return error.WriteFailed; - try class.indentedFormat(w, depth, indent + 1, constant_pool); + .interface_method_ref => |*interface_method_ref| { + try formatInfo(w, depth, indent, "class", interface_method_ref, .class, constant_pool); - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name_and_type:\n"); - const name_and_type = interface_method_ref.nameAndType(constant_pool) catch return error.WriteFailed; - try name_and_type.indentedFormat(w, depth, indent + 1, constant_pool); + try formatInfo(w, depth, indent, "name_and_type", interface_method_ref, .nameAndType, constant_pool); }, - .string => |string| { - const s = string.string(constant_pool) catch return error.WriteFailed; - try s.indentedFormat(w, depth, indent + 1, constant_pool); + .string => |*string| { + try formatInfo(w, depth, indent, "string", string, .string, constant_pool); }, - .integer => |integer| { + .integer => |*integer| { try w.splatByteAll(' ', depth * indent); try w.print("integer: {d}\n", .{ integer.bytes }); }, - .float => |float| { - const f: f32 = @bitCast(float.bytes); - + .float => |*float| { try w.splatByteAll(' ', depth * indent); - try w.print("float: {d}\n", .{ f }); + try w.print("float: {d}\n", .{ float.float() }); }, - .long => |long| { - const l: u64 = (@as(u64, long.high_bytes) << 32) | long.low_bytes; - + .long => |*long| { try w.splatByteAll(' ', depth * indent); - try w.print("long: {d}\n", .{ l }); + try w.print("long: {d}\n", .{ long.long() }); }, - .double => |double| { - const l: u64 = (@as(u64, double.high_bytes) << 32) | double.low_bytes; - const d: f64 = @bitCast(l); - + .double => |*double| { try w.splatByteAll(' ', depth * indent); - try w.print("double: {d}\n", .{ d }); + try w.print("double: {d}\n", .{ double.double() }); }, - .name_and_type => |name_and_type| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name:\n"); - const name = name_and_type.name(constant_pool) catch return error.WriteFailed; - try name.indentedFormat(w, depth, indent + 1, constant_pool); + .name_and_type => |*name_and_type| { + try formatInfo(w, depth, indent, "name", name_and_type, .name, constant_pool); - try w.splatByteAll(' ', depth * indent); - _ = try w.write("descriptor:\n"); - const descriptor = name_and_type.descriptor(constant_pool) catch return error.WriteFailed; - try descriptor.indentedFormat(w, depth, indent + 1, constant_pool); + try formatInfo(w, depth, indent, "descriptor", name_and_type, .descriptor, constant_pool); }, - .utf8 => |utf8| { + .utf8 => |*utf8| { try w.splatByteAll(' ', depth * indent); try w.print("bytes: \"{s}\"\n", .{ utf8.bytes }); }, - .method_handle => |method_handle| { + .method_handle => |*method_handle| { try w.splatByteAll(' ', depth * indent); try w.print("kind: {t}\n", .{ method_handle.reference_kind }); - try w.splatByteAll(' ', depth * indent); - _ = try w.write("reference:\n"); - const reference = method_handle.reference(constant_pool) catch return error.WriteFailed; - try reference.indentedFormat(w, depth, indent + 1, constant_pool); + try formatInfo(w, depth, indent, "descriptor", method_handle, .reference, constant_pool); }, - .method_type => |method_type| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("descriptor:\n"); - const descriptor = method_type.descriptor(constant_pool) catch return error.WriteFailed; - try descriptor.indentedFormat(w, depth, indent + 1, constant_pool); + .method_type => |*method_type| { + try formatInfo(w, depth, indent, "descriptor", method_type, .descriptor, constant_pool); }, - .dynamic => |dynamic| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name_and_type:\n"); - const name_and_type = dynamic.nameAndType(constant_pool) catch return error.WriteFailed; - try name_and_type.indentedFormat(w, depth, indent + 1, constant_pool); + .dynamic => |*dynamic| { + try formatInfo(w, depth, indent, "name_and_type", dynamic, .nameAndType, constant_pool); }, - .invoke_dynamic => |invoke_dynamic| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name_and_type:\n"); - const name_and_type = invoke_dynamic.nameAndType(constant_pool) catch return error.WriteFailed; - try name_and_type.indentedFormat(w, depth, indent + 1, constant_pool); + .invoke_dynamic => |*invoke_dynamic| { + try formatInfo(w, depth, indent, "name_and_type", invoke_dynamic, .nameAndType, constant_pool); }, - .module => |module| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name:\n"); - const name = module.name(constant_pool) catch return error.WriteFailed; - try name.indentedFormat(w, depth, indent + 1, constant_pool); + .module => |*module| { + try formatInfo(w, depth, indent, "name", module, .name, constant_pool); }, - .package => |package| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name:\n"); - const name = package.name(constant_pool) catch return error.WriteFailed; - try name.indentedFormat(w, depth, indent + 1, constant_pool); + .package => |*package| { + try formatInfo(w, depth, indent, "name", package, .name, constant_pool); }, } } @@ -569,3 +528,20 @@ pub fn getLoadableOptional(self: *const Self, index: u16) ResolveError!?Info { if (index == 0) return null; return self.getLoadable(index); } + +pub fn formatInfo( + w: *std.Io.Writer, + depth: usize, + indent: u8, + comptime name: []const u8, + context: anytype, + comptime getter: std.meta.DeclEnum(@TypeOf(context.*)), + constant_pool: Self, +) std.Io.Writer.Error!void { + const func = @field(@TypeOf(context.*), @tagName(getter)); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write(name ++ ":\n"); + const info = func(context, constant_pool) catch return error.WriteFailed; + try info.indentedFormat(w, depth, indent + 1, constant_pool); +}