I am trying to optimize the size of my bytecode, and decided to handle compression with these two methods:
pub fn asBytes(self: OpCode) struct { bytes: [3]u8, len: usize } {
return switch (self) {
.Return, .PushNil, .PushTrue, .PushFalse, .Add, .Negate, .Not, .Minus, .Multiply, .Divide, .Equal, .Greater, .Less, .Pop, .PopPreserve, .Inherit => .{
.bytes = .{ @intFromEnum(self), 0, 0 },
.len = 1,
},
.PushConstant, .DefineGlobal, .GetGlobal, .SetGlobal, .GetLocal, .SetLocal, .GetProperty, .SetProperty, .JumpAlways, .JumpIfFalse, .PopJumpIfFalse, .LoopAlways, .Call, .NewClass, .AddMethod, .AddField => |data| .{
.bytes = .{ @intFromEnum(self), data, 0 },
.len = 2,
},
.Invoke => |invocation| .{
.bytes = .{ @intFromEnum(self), invocation.name, invocation.numArg },
.len = 3,
},
};
}
pub fn read(bytes: []const u8, index: usize) struct { opcode: OpCode, len: usize } {
const typ: OpCodeType = @enumFromInt(bytes[index]);
return switch (typ) {
.Return, .PushNil, .PushTrue, .PushFalse, .Add, .Negate, .Not, .Minus, .Multiply, .Divide, .Equal, .Greater, .Less, .Pop, .PopPreserve, .Inherit => .{
.opcode = OpCode{ .typ = void{} },
.len = 1,
},
.PushConstant, .DefineGlobal, .GetGlobal, .SetGlobal, .GetLocal, .SetLocal, .GetProperty, .SetProperty, .JumpAlways, .JumpIfFalse, .PopJumpIfFalse, .LoopAlways, .Call, .NewClass, .AddMethod, .AddField => .{
.opcode = OpCode{ .typ = bytes[index + 1] },
.len = 2,
},
.Invoke => .{
.opcode = OpCode{ .typ = .{ .name = bytes[index + 1], .numArg = bytes[index + 2] } },
.len = 3,
},
};
}
But read() does not compile right now, because typ is not a member of the enum. How can I get it to compile ? Am I forced to have a case for each instruction ?
Here is the precise error message:
OpCode.zig:180:36: error: no field named 'typ' in union 'OpCode.OpCode'
.opcode = OpCode{ .typ = .{ .name = bytes[index + 1], .numArg = bytes[index + 2] } },