push
This commit is contained in:
commit
93f4b9ce51
1 changed files with 127 additions and 0 deletions
127
file.rs
Normal file
127
file.rs
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#[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));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue