Compare commits

..

1 commit

Author SHA1 Message Date
9e0e5ff8ea Add EnumFlags tests 2026-08-25 12:07:43 +00:00
6 changed files with 84 additions and 1305 deletions

View file

@ -36,8 +36,6 @@ pub const ClassAccessFlags = EnumFlags(enum(u16) {
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 {

View file

@ -319,9 +319,7 @@ pub const AttributeInfo = union(enum) {
defer instr_indent -= 1; defer instr_indent -= 1;
try w.splatByteAll(' ', depth * instr_indent); try w.splatByteAll(' ', depth * instr_indent);
try w.print("{d}:\n", .{ i }); try w.print("{d}: 0x{x}\n", .{ i, instr });
try instr.indentedFormat(w, depth, instr_indent + 1, constant_pool);
} }
try w.splatByteAll(' ', depth * indent); try w.splatByteAll(' ', depth * indent);
@ -692,14 +690,12 @@ pub const ConstantValue = struct {
pub const Code = struct { pub const Code = struct {
max_stack: u16, max_stack: u16,
max_locals: u16, max_locals: u16,
code: []Instruction, code: []u8,
exception_table: []ExceptionHandler, exception_table: []ExceptionHandler,
attributes: []AttributeInfo, attributes: []AttributeInfo,
const Self = @This(); const Self = @This();
pub const Instruction = @import("Code/Instruction.zig").Instruction;
pub const ExceptionHandler = struct { pub const ExceptionHandler = struct {
start_pc: u16, start_pc: u16,
end_pc: u16, end_pc: u16,
@ -740,20 +736,8 @@ pub const Code = struct {
const max_locals = try input.takeInt(u16, .big); const max_locals = try input.takeInt(u16, .big);
const code_length = try input.takeInt(u32, .big); const code_length = try input.takeInt(u32, .big);
var code_reader_buf: [1024]u8 = undefined; const code = try input.readAlloc(allocator, code_length);
var code_reader = input.limited(.limited(code_length), &code_reader_buf); errdefer allocator.free(code);
var code = &code_reader.interface;
var byte_index: usize = 0;
var instructions: std.ArrayList(Instruction) = .empty;
defer instructions.deinit(allocator);
loop: while (true) {
_ = code.peekByte() catch |err| switch (err) {
error.EndOfStream => break :loop,
else => return err,
};
try instructions.append(allocator, try .parse(code, allocator, &byte_index));
}
const exception_table_length = try input.takeInt(u16, .big); const exception_table_length = try input.takeInt(u16, .big);
const exception_table = try allocator.alloc(ExceptionHandler, exception_table_length); const exception_table = try allocator.alloc(ExceptionHandler, exception_table_length);
@ -777,16 +761,13 @@ pub const Code = struct {
return .{ return .{
.max_stack = max_stack, .max_stack = max_stack,
.max_locals = max_locals, .max_locals = max_locals,
.code = try instructions.toOwnedSlice(allocator), .code = code,
.exception_table = exception_table, .exception_table = exception_table,
.attributes = attributes, .attributes = attributes,
}; };
} }
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
for (self.code) |*instruction| {
instruction.deinit(allocator);
}
allocator.free(self.code); allocator.free(self.code);
allocator.free(self.exception_table); allocator.free(self.exception_table);
for (self.attributes) |*attr| { for (self.attributes) |*attr| {

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,13 @@ pub fn EnumFlags(comptime E: type) type {
mask: BackingInt, mask: BackingInt,
pub const empty: Self = .{ .data = 0 }; pub const empty: Self = .{ .mask = 0 };
test empty {
const flags: EnumFlags(Enum) = .empty;
try std.testing.expectEqual(0b0000_0000, flags.mask);
}
pub fn from(mask: BackingInt) Self { pub fn from(mask: BackingInt) Self {
return .{ return .{
@ -16,6 +22,12 @@ pub fn EnumFlags(comptime E: type) type {
}; };
} }
test from {
const flags: EnumFlags(Enum) = .from(0b0000_0001);
try std.testing.expectEqual(0b0000_0001, flags.mask);
}
pub fn contains(self: Self, flag: E) bool { pub fn contains(self: Self, flag: E) bool {
return (self.mask & @intFromEnum(flag)) != 0; return (self.mask & @intFromEnum(flag)) != 0;
} }
@ -48,3 +60,64 @@ pub fn EnumFlags(comptime E: type) type {
}; };
} }
const Enum = enum(u8) {
a = 0b0000_0001,
b = 0b0000_0010,
c = 0b0000_0100,
};
test {
std.testing.refAllDecls(EnumFlags(Enum));
}
test "EnumFlags operations" {
var flags: EnumFlags(Enum) = .from(0b0000_0001);
try std.testing.expect(flags.contains(Enum.a));
flags.remove(Enum.a);
try std.testing.expect(!flags.contains(Enum.a));
flags.remove(Enum.a); // Removing twice should not enable the flag
try std.testing.expect(!flags.contains(Enum.a));
flags.insert(Enum.b);
try std.testing.expectEqual(0b0000_0010, flags.mask);
try std.testing.expect(flags.contains(Enum.b));
try std.testing.expect(!flags.contains(Enum.a));
flags.toggle(Enum.a);
try std.testing.expectEqual(0b0000_0011, flags.mask);
try std.testing.expect(flags.contains(Enum.a));
try std.testing.expect(flags.contains(Enum.b));
try std.testing.expect(!flags.contains(Enum.c));
}
fn testFormat(expected: []const u8, flags: EnumFlags(Enum)) !void {
var out_buf: [1024]u8 = undefined;
var out: std.Io.Writer = .fixed(&out_buf);
try flags.format(&out);
try std.testing.expectEqualStrings(expected, out.buffered());
}
test "EnumFlags format" {
var flags: EnumFlags(Enum) = .empty;
flags.toggle(Enum.a);
flags.toggle(Enum.b);
flags.toggle(Enum.c);
try testFormat("a | b | c", flags);
flags.toggle(Enum.b);
try testFormat("a | c", flags);
flags.remove(Enum.c);
try testFormat("a", flags);
flags.insert(Enum.b);
try testFormat("a | b", flags);
}

View file

@ -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

Binary file not shown.