88 lines
2.2 KiB
Zig
88 lines
2.2 KiB
Zig
const std = @import("std");
|
|
|
|
const Instruction = enum(u32) {
|
|
PSH,
|
|
ADD,
|
|
POP,
|
|
SET,
|
|
HLT,
|
|
};
|
|
|
|
const default_program = [_]u32{
|
|
@enumToInt(Instruction.PSH), 5,
|
|
@enumToInt(Instruction.PSH), 6,
|
|
@enumToInt(Instruction.ADD), @enumToInt(Instruction.POP),
|
|
@enumToInt(Instruction.HLT),
|
|
};
|
|
|
|
const Stack = std.ArrayList(u32);
|
|
|
|
const VM = struct {
|
|
program: []const u32,
|
|
stack: Stack,
|
|
|
|
instruction_pointer: usize = 0,
|
|
stack_pointer: usize = 0,
|
|
running: bool = false,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn init(allocator: *std.mem.Allocator, program: []const u32) !Self {
|
|
return Self{
|
|
.program = program,
|
|
.stack = try Stack.initCapacity(allocator, 256),
|
|
.instruction_pointer = 0,
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: Self) void {
|
|
self.stack.deinit();
|
|
}
|
|
|
|
pub fn fetch(self: Self) u32 {
|
|
return self.program[self.instruction_pointer];
|
|
}
|
|
|
|
pub fn runOne(self: *Self, instruction_as_number: u32) !void {
|
|
const instruction: Instruction = try std.meta.intToEnum(Instruction, instruction_as_number);
|
|
std.log.info("running {}", .{instruction});
|
|
|
|
switch (instruction) {
|
|
.PSH => {
|
|
self.instruction_pointer += 1;
|
|
const value = self.fetch();
|
|
self.stack.appendAssumeCapacity(value);
|
|
},
|
|
.POP => {
|
|
const value = self.stack.pop();
|
|
std.log.info("stack: popped {}", .{value});
|
|
},
|
|
.ADD => {
|
|
const value_a = self.stack.pop();
|
|
const value_b = self.stack.pop();
|
|
self.stack.appendAssumeCapacity(value_b + value_a);
|
|
},
|
|
.HLT => self.running = false,
|
|
else => unreachable,
|
|
}
|
|
}
|
|
};
|
|
|
|
pub fn main() anyerror!void {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer {
|
|
_ = gpa.deinit();
|
|
}
|
|
|
|
const allocator = &gpa.allocator;
|
|
|
|
var vm = try VM.init(allocator, &default_program);
|
|
defer vm.deinit();
|
|
|
|
vm.running = true;
|
|
while (vm.running) {
|
|
try vm.runOne(vm.fetch());
|
|
vm.instruction_pointer += 1;
|
|
}
|
|
}
|