see test:
const std = @import("std");
pub const Opcodes = enum(u8) {
OP_1 = 0x51,
OP_ADD = 0x93,
};
const StackValue = struct {
bytes: []const u8,
};
fn evaluate(code: []const u8,) !StackValue {
var stack = try std.BoundedArray(StackValue, 10).init(0);
var ip: usize = 0;
return vm: switch (@as(Opcodes, @enumFromInt(code[ip]))) {
.OP_1 => {
const pushed_byte = try push_byte(code[ip]);
const val = &[_]u8{pushed_byte};
try stack.append(StackValue{ .bytes = val });
ip += 1;
const is_end = ip == code.len;
if (is_end) {
break :vm stack.pop();
}
continue :vm @enumFromInt(code[ip]);
},
else => {
std.debug.print("Unimplemented {any}\n", .{stack.len});
if (stack.len == 0) {
break :vm error.read_empty_stack;
}
break :vm stack.pop();
},
};
}
pub fn push_byte(ins: u8) !u8 {
return switch (@as(Opcodes, @enumFromInt(ins))) {
// .OP_0 => 0,
.OP_1 => 1,
// .OP_2 => 2,
// .OP_3 => 3,
// .OP_4 => 4,
// .OP_5 => 5,
// .OP_6 => 6,
// .OP_7 => 7,
// .OP_8 => 8,
// .OP_9 => 9,
// .OP_10 => 10,
// .OP_11 => 11,
// .OP_12 => 12,
// .OP_13 => 13,
// .OP_14 => 14,
// .OP_15 => 15,
// .OP_16 => 16,
else => error.non_push,
};
}
test "push 3 bytes to stack" {
const push3 = try evaluate(&.{ 0x51,0x51, 0x51 });
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout = bw.writer();
std.debug.print("Expected Val {any}\n",.{push3.bytes[0]} );
try stdout.print("{any}.\n", .{push3.bytes[0]});
try stdout.print("{any}.\n", .{push3.bytes});
std.debug.print("Val changed {any}\n",.{push3.bytes} );
try bw.flush();
}