vm/file.rs

128 lines
3.8 KiB
Rust
Raw Normal View History

2026-03-20 18:39:03 +00:00
#[derive(Clone, Copy, Debug)]
enum Instruction {
LoadInt { dst: u8, value: i16 },
Copy { dst: u8, src: u8 },
Add { dst: u8, src1: u8, src2: u8 },
Sub { dst: u8, src1: u8, src2: u8 },
Call { func: u8, arg: u8, dst: u8 },
Return { src: u8 },
JumpNotLess { target: u8, src1: u8, src2: u8 },
}
struct Function {
code: Vec<Instruction>,
num_registers: usize,
}
struct Vm {
functions: Vec<Function>,
stack: Vec<i64>,
}
impl Vm {
pub fn new() -> Vm {
Vm {
functions: vec![],
stack: vec![],
}
}
pub fn call(&mut self, func: u8, arg: i64) -> i64 {
let func = func as usize;
let base_pointer = self.stack.len();
{
let function = &self.functions[func];
let stack_top = base_pointer + function.num_registers;
self.stack.resize(stack_top, 0);
self.stack[base_pointer] = arg;
}
let bp = base_pointer;
let mut program_counter = 0;
loop {
let func = &self.functions[func];
let instr = func.code[program_counter];
program_counter += 1;
match instr {
Instruction::LoadInt { dst, value } => {
*self.reg(bp, dst) = value as i64;
}
Instruction::Copy { dst, src } => {
*self.reg(bp, dst) = *self.reg(bp, src);
}
Instruction::Add { dst, src1, src2 } => {
*self.reg(bp, dst) = *self.reg(bp, src1) + *self.reg(bp, src2);
}
Instruction::Sub { dst, src1, src2 } => {
*self.reg(bp, dst) = *self.reg(bp, src1) - *self.reg(bp, src2);
}
Instruction::Call { func, arg, dst } => {
let arg = *self.reg(bp, arg);
let result = self.call(func, arg);
*self.reg(bp, dst) = result;
}
Instruction::Return { src } => {
let result = *self.reg(bp, src);
self.stack.truncate(base_pointer);
return result;
}
Instruction::JumpNotLess { target, src1, src2 } => {
let src1 = *self.reg(bp, src1);
let src2 = *self.reg(bp, src2);
if !(src1 < src2) {
program_counter = target as usize;
}
}
}
}
}
fn reg(&mut self, base_pointer: usize, index: u8) -> &mut i64 {
&mut self.stack[base_pointer + index as usize]
}
}
fn main() {
let mut vm = Vm::new();
let fib = 0;
vm.functions.push(Function {
code: {
let n = 0;
let two = 1;
let one = 2;
let temp = 3;
let recursive_1 = 4;
let recursive_2 = 5;
let result = 6;
vec![
Instruction::LoadInt { dst: two, value: 2 },
Instruction::JumpNotLess { target: 3, src1: n, src2: two },
Instruction::Return { src: n },
Instruction::Sub { dst: temp, src1: n, src2: two },
Instruction::Call { func: fib, arg: temp, dst: recursive_1 },
Instruction::LoadInt { dst: one, value: 1 },
Instruction::Sub { dst: temp, src1: n, src2: one },
Instruction::Call { func: fib, arg: temp, dst: recursive_2 },
Instruction::Add { dst: result, src1: recursive_1, src2: recursive_2 },
Instruction::Return { src: result },
]
},
num_registers: 7,
});
for i in 0..10 {
println!("fib({}) = {}", i, vm.call(fib, i));
}
}