mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
156 lines
4.1 KiB
Rust
156 lines
4.1 KiB
Rust
use std::rc::Rc;
|
|
|
|
use super::vs_value::Val;
|
|
use super::vs_undefined::VsUndefined;
|
|
use super::vs_number::VsNumber;
|
|
use super::operations;
|
|
use super::bytecode_decoder::BytecodeDecoder;
|
|
use super::instruction::Instruction;
|
|
|
|
pub struct VirtualMachine {
|
|
pub return_value: Val,
|
|
pub root: Val,
|
|
pub stack: Vec<StackFrame>,
|
|
}
|
|
|
|
pub struct StackFrame {
|
|
pub decoder: BytecodeDecoder,
|
|
pub registers: Vec<Val>,
|
|
pub this_target: usize,
|
|
pub return_target: usize,
|
|
}
|
|
|
|
impl VirtualMachine {
|
|
pub fn run(&mut self, bytecode: &Rc<Vec<u8>>) {
|
|
let mut bd = BytecodeDecoder {
|
|
data: bytecode.clone(),
|
|
pos: 0,
|
|
};
|
|
|
|
let main_fn = bd.decode_val(&Vec::new());
|
|
|
|
if !main_fn.push_frame(self) {
|
|
std::panic!("bytecode does start with function")
|
|
}
|
|
|
|
while self.stack.len() > 0 {
|
|
self.step();
|
|
}
|
|
}
|
|
|
|
pub fn new() -> VirtualMachine {
|
|
return VirtualMachine {
|
|
root: VsUndefined::new(),
|
|
return_value: VsUndefined::new(),
|
|
stack: Default::default(),
|
|
};
|
|
}
|
|
|
|
pub fn step(&mut self) {
|
|
use Instruction::*;
|
|
|
|
let frame = self.stack.last_mut().unwrap();
|
|
|
|
match frame.decoder.decode_instruction() {
|
|
End => {
|
|
self.pop();
|
|
},
|
|
|
|
Mov => {
|
|
let val = frame.decoder.decode_val(&frame.registers);
|
|
let register_index = frame.decoder.decode_register_index();
|
|
|
|
if register_index.is_some() {
|
|
frame.registers[register_index.unwrap()] = val;
|
|
}
|
|
},
|
|
|
|
OpInc => {
|
|
let mut val = frame.decoder.decode_val(&frame.registers);
|
|
val = operations::op_plus(&val, &VsNumber::from_f64(1_f64));
|
|
let register_index = frame.decoder.decode_register_index();
|
|
|
|
if register_index.is_some() {
|
|
frame.registers[register_index.unwrap()] = val;
|
|
}
|
|
},
|
|
|
|
OpPlus => {
|
|
let left = frame.decoder.decode_val(&frame.registers);
|
|
let right = frame.decoder.decode_val(&frame.registers);
|
|
|
|
let register_index = frame.decoder.decode_register_index();
|
|
|
|
if register_index.is_some() {
|
|
frame.registers[register_index.unwrap()] = operations::op_plus(&left, &right);
|
|
}
|
|
},
|
|
|
|
OpMul => {
|
|
let left = frame.decoder.decode_val(&frame.registers);
|
|
let right = frame.decoder.decode_val(&frame.registers);
|
|
|
|
let register_index = frame.decoder.decode_register_index();
|
|
|
|
if register_index.is_some() {
|
|
frame.registers[register_index.unwrap()] = operations::op_mul(&left, &right);
|
|
}
|
|
},
|
|
|
|
OpMod => {
|
|
let left = frame.decoder.decode_val(&frame.registers);
|
|
let right = frame.decoder.decode_val(&frame.registers);
|
|
|
|
let register_index = frame.decoder.decode_register_index();
|
|
|
|
if register_index.is_some() {
|
|
frame.registers[register_index.unwrap()] = operations::op_mod(&left, &right);
|
|
}
|
|
},
|
|
|
|
OpLess => {
|
|
let left = frame.decoder.decode_val(&frame.registers);
|
|
let right = frame.decoder.decode_val(&frame.registers);
|
|
|
|
let register_index = frame.decoder.decode_register_index();
|
|
|
|
if register_index.is_some() {
|
|
frame.registers[register_index.unwrap()] = operations::op_less(&left, &right);
|
|
}
|
|
}
|
|
|
|
Jmp => {
|
|
let dst = frame.decoder.decode_pos();
|
|
frame.decoder.pos = dst;
|
|
}
|
|
|
|
JmpIf => {
|
|
let cond = frame.decoder.decode_val(&frame.registers);
|
|
let dst = frame.decoder.decode_pos();
|
|
|
|
if cond.is_truthy() {
|
|
frame.decoder.pos = dst;
|
|
}
|
|
}
|
|
|
|
_ => std::panic!("Not implemented"),
|
|
};
|
|
}
|
|
|
|
pub fn pop(&mut self) {
|
|
let old_frame = self.stack.pop().unwrap();
|
|
let optional_frame = self.stack.last_mut();
|
|
|
|
if optional_frame.is_some() {
|
|
let frame = optional_frame.unwrap();
|
|
|
|
frame.registers[frame.return_target] = old_frame.registers[0].clone();
|
|
frame.registers[frame.this_target] = old_frame.registers[1].clone();
|
|
} else {
|
|
// TODO: Use special init frame to avoid branching
|
|
self.return_value = old_frame.registers[0].clone();
|
|
self.root = old_frame.registers[1].clone();
|
|
}
|
|
}
|
|
}
|