Format instructions, exceptions, inner classes and enclosing methods
This commit is contained in:
parent
7d7df22df3
commit
ba2c8a59b5
2 changed files with 163 additions and 5 deletions
13
Main.java
13
Main.java
|
|
@ -23,5 +23,18 @@ public class Main implements Runnable, Supplier<Integer>, Interface {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void throwSomething() throws Throwable {
|
||||||
|
throw new Throwable() {
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "Hello";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Inner {
|
||||||
|
private static final String name = "Inner John";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
155
src/Class.zig
155
src/Class.zig
|
|
@ -364,12 +364,112 @@ fn formatAttribute(self: *const Self, w: *std.Io.Writer, depth: usize, indent: u
|
||||||
try w.splatByteAll(' ', depth * indent);
|
try w.splatByteAll(' ', depth * indent);
|
||||||
try w.print("max_locals: {d}\n", .{ attr.max_locals });
|
try w.print("max_locals: {d}\n", .{ attr.max_locals });
|
||||||
|
|
||||||
// TODO: Properly parse and format instructions
|
try w.splatByteAll(' ', depth * indent);
|
||||||
|
_ = try w.write("code:\n");
|
||||||
|
var instr_indent = indent;
|
||||||
|
for (attr.code, 0..) |instr, i| {
|
||||||
|
instr_indent += 1;
|
||||||
|
defer instr_indent -= 1;
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', depth * instr_indent);
|
||||||
|
try w.print("{d}: {d}\n", .{ i, instr });
|
||||||
|
}
|
||||||
|
|
||||||
|
//try w.splatByteAll(' ', depth * indent);
|
||||||
|
//_ = try w.write("exception_table:\n");
|
||||||
|
//var exception_indent = indent;
|
||||||
|
//for (attr.exception_table, 0..) |*exception, i| {
|
||||||
|
// exception_indent += 1;
|
||||||
|
// defer exception_indent -= 1;
|
||||||
|
|
||||||
|
// try w.splatByteAll(' ', depth * exception_indent);
|
||||||
|
// try w.print("{d}:\n", .{ i });
|
||||||
|
|
||||||
|
// try self.formatExceptionHandler(w, depth, exception_indent + 1, exception);
|
||||||
|
//}
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', depth * indent);
|
||||||
|
_ = try w.write("attributes:\n");
|
||||||
|
var attr_indent = indent;
|
||||||
|
for (attr.attributes, 0..) |*a, i| {
|
||||||
|
attr_indent += 1;
|
||||||
|
defer attr_indent -= 1;
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', depth * attr_indent);
|
||||||
|
try w.print("{d}:\n", .{ i });
|
||||||
|
|
||||||
|
try self.formatAttribute(w, depth, attr_indent + 1, a);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
//.stack_map_table,
|
//.stack_map_table,
|
||||||
//.exceptions,
|
.exceptions => |attr| {
|
||||||
//.inner_classes,
|
try w.splatByteAll(' ', depth * indent);
|
||||||
//.enclosing_method,
|
_ = try w.write("exceptions:\n");
|
||||||
|
var attr_indent = indent;
|
||||||
|
for (attr.exception_index_table, 0..) |exception, i| {
|
||||||
|
attr_indent += 1;
|
||||||
|
defer attr_indent -= 1;
|
||||||
|
|
||||||
|
if (exception >= self.constant_pool.len) return error.WriteFailed;
|
||||||
|
const cp_info = self.constant_pool[exception - 1];
|
||||||
|
if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .class) return error.WriteFailed;
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', depth * attr_indent);
|
||||||
|
try w.print("{d}:\n", .{ i });
|
||||||
|
try self.formatCpInfo(w, depth, attr_indent + 1, &cp_info.?);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.inner_classes => |attr| {
|
||||||
|
try w.splatByteAll(' ', depth * indent);
|
||||||
|
_ = try w.write("classes:\n");
|
||||||
|
var inner_classes_indent = indent;
|
||||||
|
for (attr.classes) |*class| {
|
||||||
|
inner_classes_indent += 1;
|
||||||
|
defer inner_classes_indent -= 1;
|
||||||
|
|
||||||
|
const inner_class = class.innerClass(self.constant_pool) catch return error.WriteFailed;
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', depth * inner_classes_indent);
|
||||||
|
_ = try w.write("inner_class:\n");
|
||||||
|
|
||||||
|
try self.formatCpInfo(w, depth, inner_classes_indent + 1, &.{ .class = inner_class });
|
||||||
|
|
||||||
|
const outer_class = class.outerClass(self.constant_pool) catch return error.WriteFailed;
|
||||||
|
if (outer_class) |oc| {
|
||||||
|
try w.splatByteAll(' ', depth * inner_classes_indent);
|
||||||
|
_ = try w.write("outer_class:\n");
|
||||||
|
|
||||||
|
try self.formatCpInfo(w, depth, inner_classes_indent + 1, &.{ .class = oc });
|
||||||
|
}
|
||||||
|
|
||||||
|
const inner_name = class.innerName(self.constant_pool) catch return error.WriteFailed;
|
||||||
|
if (inner_name) |in| {
|
||||||
|
try w.splatByteAll(' ', depth * inner_classes_indent);
|
||||||
|
_ = try w.write("inner_name:\n");
|
||||||
|
|
||||||
|
try self.formatCpInfo(w, depth, inner_classes_indent + 1, &.{ .utf8 = in });
|
||||||
|
}
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', depth * inner_classes_indent);
|
||||||
|
try w.print("flags: {f}\n", .{ class.inner_class_access_flags });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.enclosing_method => |attr| {
|
||||||
|
const class = attr.class(self.constant_pool) catch return error.WriteFailed;
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', depth * indent);
|
||||||
|
_ = try w.write("class:\n");
|
||||||
|
|
||||||
|
try self.formatCpInfo(w, depth, indent + 1, &.{ .class = class });
|
||||||
|
|
||||||
|
const method = attr.method(self.constant_pool) catch return error.WriteFailed;
|
||||||
|
if (method) |m| {
|
||||||
|
try w.splatByteAll(' ', depth * indent);
|
||||||
|
_ = try w.write("method:\n");
|
||||||
|
|
||||||
|
try self.formatCpInfo(w, depth, indent + 1, &.{ .name_and_type = m });
|
||||||
|
}
|
||||||
|
},
|
||||||
.synthetic => {},
|
.synthetic => {},
|
||||||
.signature => |attr| {
|
.signature => |attr| {
|
||||||
const signature = attr.signature(self.constant_pool) catch return error.WriteFailed;
|
const signature = attr.signature(self.constant_pool) catch return error.WriteFailed;
|
||||||
|
|
@ -383,7 +483,7 @@ fn formatAttribute(self: *const Self, w: *std.Io.Writer, depth: usize, indent: u
|
||||||
//.line_number_table,
|
//.line_number_table,
|
||||||
//.local_variable_table,
|
//.local_variable_table,
|
||||||
//.local_variable_type_table,
|
//.local_variable_type_table,
|
||||||
//.deprecated,
|
.deprecated => {},
|
||||||
//.runtime_visible_annotations,
|
//.runtime_visible_annotations,
|
||||||
//.runtime_invisible_annotations,
|
//.runtime_invisible_annotations,
|
||||||
//.runtime_visible_parameter_annotations,
|
//.runtime_visible_parameter_annotations,
|
||||||
|
|
@ -1227,6 +1327,34 @@ pub const AttributeInfo = struct {
|
||||||
outer_class_info_index: u16,
|
outer_class_info_index: u16,
|
||||||
inner_name_index: u16,
|
inner_name_index: u16,
|
||||||
inner_class_access_flags: InnerClassAccessFlags,
|
inner_class_access_flags: InnerClassAccessFlags,
|
||||||
|
|
||||||
|
pub fn innerClass(self: *const InnerClass, constant_pool: []const ?CpInfo) ResolveError!CpInfo.Class {
|
||||||
|
const inner_class_info_index = self.inner_class_info_index - 1;
|
||||||
|
if (inner_class_info_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
|
||||||
|
const cp_info = constant_pool[inner_class_info_index];
|
||||||
|
if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
|
||||||
|
return cp_info.?.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outerClass(self: *const InnerClass, constant_pool: []const ?CpInfo) ResolveError!?CpInfo.Class {
|
||||||
|
if (self.outer_class_info_index == 0) return null;
|
||||||
|
const outer_class_info_index = self.outer_class_info_index - 1;
|
||||||
|
if (outer_class_info_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
|
||||||
|
|
||||||
|
const cp_info = constant_pool[outer_class_info_index];
|
||||||
|
if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
|
||||||
|
return cp_info.?.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn innerName(self: *const InnerClass, constant_pool: []const ?CpInfo) ResolveError!?CpInfo.Utf8 {
|
||||||
|
if (self.inner_name_index == 0) return null;
|
||||||
|
const inner_name_index = self.inner_name_index - 1;
|
||||||
|
if (inner_name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
|
||||||
|
|
||||||
|
const cp_info = constant_pool[inner_name_index];
|
||||||
|
if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
|
||||||
|
return cp_info.?.utf8;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const InnerClassFlags = enum(u16) {
|
pub const InnerClassFlags = enum(u16) {
|
||||||
|
|
@ -1248,6 +1376,23 @@ pub const AttributeInfo = struct {
|
||||||
pub const EnclosingMethod = struct {
|
pub const EnclosingMethod = struct {
|
||||||
class_index: u16,
|
class_index: u16,
|
||||||
method_index: u16,
|
method_index: u16,
|
||||||
|
|
||||||
|
pub fn class(self: *const EnclosingMethod, constant_pool: []const ?CpInfo) ResolveError!CpInfo.Class {
|
||||||
|
const class_index = self.class_index - 1;
|
||||||
|
if (class_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
|
||||||
|
const cp_info = constant_pool[class_index];
|
||||||
|
if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
|
||||||
|
return cp_info.?.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn method(self: *const EnclosingMethod, constant_pool: []const ?CpInfo) ResolveError!?CpInfo.NameAndType {
|
||||||
|
if (self.method_index == 0) return null;
|
||||||
|
const method_index = self.method_index - 1;
|
||||||
|
if (method_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
|
||||||
|
const cp_info = constant_pool[method_index];
|
||||||
|
if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .name_and_type) return ResolveError.InvalidConstantType;
|
||||||
|
return cp_info.?.name_and_type;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Synthetic = struct { };
|
pub const Synthetic = struct { };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue