wip vm::run

This commit is contained in:
Andrew Morris
2022-05-02 15:17:33 +10:00
parent 74c442ffea
commit 9af2274246
11 changed files with 225 additions and 7 deletions

View File

@@ -24,7 +24,8 @@ pub fn command(args: &Vec<String>) {
let mut vm = VirtualMachine::new();
vm.run(&bytecode);
vm.print();
println!("{}", vm.return_value);
}
fn to_bytecode(option: &String, file_path: &String) -> Rc<Vec<u8>> {

View File

@@ -5,6 +5,7 @@ use super::vs_number::VsNumber;
use super::vs_string::VsString;
use super::vs_pointer::VsPointer;
use super::vs_function::VsFunction;
use super::instruction::Instruction;
pub struct BytecodeDecoder {
// TODO: Enable borrow usage to avoid the rc overhead
@@ -128,6 +129,17 @@ impl BytecodeDecoder {
return self.decode_byte() as usize;
}
pub fn decode_register(&mut self) -> Option<usize> {
// TODO: Handle multi-byte registers
let byte = self.decode_byte();
if byte == 0xff {
return None;
}
return Some(byte as usize);
}
pub fn clone_at(&self, pos: usize) -> BytecodeDecoder {
return BytecodeDecoder { data: self.data.clone(), pos: pos };
}
@@ -160,4 +172,15 @@ impl BytecodeDecoder {
start: self.pos,
});
}
pub fn decode_instruction(&mut self) -> Instruction {
use Instruction::*;
return match self.decode_byte() {
0x00 => End,
0x04 => OpPlus,
_ => std::panic!("Not implemented"),
}
}
}

View File

@@ -0,0 +1,44 @@
// TODO: Fix duplication with assembler (requires internal crate?)
pub enum Instruction {
End = 0x00,
Mov = 0x01,
OpInc = 0x02,
OpDec = 0x03,
OpPlus = 0x04,
OpMinus = 0x05,
OpMul = 0x06,
OpDiv = 0x07,
OpMod = 0x08,
OpExp = 0x09,
OpEq = 0x0a,
OpNe = 0x0b,
OpTripleEq = 0x0c,
OpTripleNe = 0x0d,
OpAnd = 0x0e,
OpOr = 0x0f,
OpNot = 0x10,
OpLess = 0x11,
OpLessEq = 0x12,
OpGreater = 0x13,
OpGreaterEq = 0x14,
OpNullishCoalesce = 0x15,
OpOptionalChain = 0x16,
OpBitAnd = 0x17,
OpBitOr = 0x18,
OpBitNot = 0x19,
OpBitXor = 0x1a,
OpLeftShift = 0x1b,
OpRightShift = 0x1c,
OpRightShiftUnsigned = 0x1d,
TypeOf = 0x1e,
InstanceOf = 0x1f,
In = 0x20,
Call = 0x21,
Apply = 0x22,
Bind = 0x23,
Sub = 0x24,
SubMov = 0x25,
SubCall = 0x26,
Jmp = 0x27,
JmpIf = 0x28,
}

View File

@@ -1,4 +1,5 @@
mod vs_value;
mod vs_undefined;
mod vs_number;
mod vs_string;
mod vs_function;
@@ -6,5 +7,6 @@ mod vs_pointer;
mod operations;
mod bytecode_decoder;
mod virtual_machine;
mod instruction;
pub use virtual_machine::VirtualMachine;

View File

@@ -1,15 +1,43 @@
use std::rc::Rc;
use super::vs_value::Val;
use super::vs_undefined::VsUndefined;
use super::vs_number::VsNumber;
use super::vs_string::VsString;
use super::operations::op_plus;
use super::bytecode_decoder::BytecodeDecoder;
use super::instruction::Instruction;
#[derive(Default)]
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();
if !main_fn.push_frame(self) {
std::panic!("bytecode does start with function")
}
while self.stack.len() > 0 {
self.step();
}
let a = VsNumber::from_f64(1_f64);
let b = VsString::from_str("2");
@@ -18,11 +46,52 @@ impl VirtualMachine {
std::panic!("Not implemented");
}
pub fn new() -> Self {
return Default::default();
pub fn new() -> VirtualMachine {
return VirtualMachine {
root: VsUndefined::new(),
return_value: VsUndefined::new(),
stack: Default::default(),
};
}
pub fn print(&self) {
std::panic!("Not implemented");
pub fn step(&mut self) {
use Instruction::*;
let frame = self.stack.last_mut().unwrap();
match frame.decoder.decode_instruction() {
End => {
self.pop();
},
OpPlus => {
let left = frame.decoder.decode_val();
let right = frame.decoder.decode_val();
let register_index = frame.decoder.decode_register();
if register_index.is_some() {
frame.registers[register_index.unwrap()] = op_plus(&left, &right);
}
},
_ => 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();
}
}
}

View File

@@ -2,6 +2,11 @@ use std::rc::Rc;
use super::vs_value::VsType;
use super::vs_value::VsValue;
use super::vs_value::Val;
use super::vs_undefined::VsUndefined;
use super::virtual_machine::VirtualMachine;
use super::virtual_machine::StackFrame;
use super::bytecode_decoder::BytecodeDecoder;
pub struct VsFunction {
pub bytecode: Rc<Vec<u8>>,
@@ -26,4 +31,24 @@ impl VsValue for VsFunction {
fn is_primitive(&self) -> bool {
return false;
}
fn push_frame(&self, vm: &mut VirtualMachine) -> bool {
let mut registers: Vec<Val> = Vec::with_capacity(self.register_count - 1);
for i in 0..(self.register_count - 1) {
registers[i] = VsUndefined::new();
}
vm.stack.push(StackFrame {
decoder: BytecodeDecoder {
data: self.bytecode.clone(),
pos: self.start,
},
registers: registers,
this_target: 0,
return_target: 0,
});
return true;
}
}

View File

@@ -3,6 +3,7 @@ use std::rc::Rc;
use super::vs_value::Val;
use super::vs_value::VsType;
use super::vs_value::VsValue;
use super::virtual_machine::VirtualMachine;
pub struct VsNumber {
value: f64,
@@ -30,4 +31,8 @@ impl VsValue for VsNumber {
fn is_primitive(&self) -> bool {
return true;
}
fn push_frame(&self, vm: &mut VirtualMachine) -> bool {
return false;
}
}

View File

@@ -4,6 +4,7 @@ use std::cell::RefCell;
use super::vs_value::Val;
use super::vs_value::VsValue;
use super::vs_value::VsType;
use super::virtual_machine::VirtualMachine;
use super::bytecode_decoder::BytecodeDecoder;
use super::bytecode_decoder::BytecodeType;
@@ -88,4 +89,8 @@ impl VsValue for VsPointer {
Function => false,
}
}
fn push_frame(&self, vm: &mut VirtualMachine) -> bool {
return self.decode().push_frame(vm);
}
}

View File

@@ -3,6 +3,7 @@ use std::rc::Rc;
use super::vs_value::Val;
use super::vs_value::VsType;
use super::vs_value::VsValue;
use super::virtual_machine::VirtualMachine;
pub struct VsString {
value: String,
@@ -34,4 +35,8 @@ impl VsValue for VsString {
fn is_primitive(&self) -> bool {
return true;
}
}
fn push_frame(&self, vm: &mut VirtualMachine) -> bool {
return false;
}
}

View File

@@ -0,0 +1,36 @@
use std::rc::Rc;
use super::vs_value::Val;
use super::vs_value::VsType;
use super::vs_value::VsValue;
use super::virtual_machine::VirtualMachine;
pub struct VsUndefined {}
impl VsUndefined {
pub fn new() -> Val {
return Rc::new(VsUndefined {});
}
}
impl VsValue for VsUndefined {
fn typeof_(&self) -> VsType {
return VsType::Undefined;
}
fn to_string(&self) -> String {
return "undefined".to_string();
}
fn to_number(&self) -> f64 {
return f64::NAN;
}
fn is_primitive(&self) -> bool {
return true;
}
fn push_frame(&self, vm: &mut VirtualMachine) -> bool {
return false;
}
}

View File

@@ -1,6 +1,7 @@
use std::rc::Rc;
use super::vs_string::VsString;
use super::virtual_machine::VirtualMachine;
pub type Val = Rc<dyn VsValue>;
@@ -36,6 +37,8 @@ pub trait VsValue {
fn to_string(&self) -> String;
fn to_number(&self) -> f64;
fn is_primitive(&self) -> bool;
fn push_frame(&self, vm: &mut VirtualMachine) -> bool;
}
pub trait ValTrait {