From 9af227424676dbd673898158de207c5029d4e7b1 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Mon, 2 May 2022 15:17:33 +1000 Subject: [PATCH] wip vm::run --- src/vstc/run.rs | 3 +- src/vstc/virtual_machine/bytecode_decoder.rs | 23 ++++++ src/vstc/virtual_machine/instruction.rs | 44 +++++++++++ src/vstc/virtual_machine/mod.rs | 2 + src/vstc/virtual_machine/virtual_machine.rs | 79 ++++++++++++++++++-- src/vstc/virtual_machine/vs_function.rs | 25 +++++++ src/vstc/virtual_machine/vs_number.rs | 5 ++ src/vstc/virtual_machine/vs_pointer.rs | 5 ++ src/vstc/virtual_machine/vs_string.rs | 7 +- src/vstc/virtual_machine/vs_undefined.rs | 36 +++++++++ src/vstc/virtual_machine/vs_value.rs | 3 + 11 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 src/vstc/virtual_machine/instruction.rs create mode 100644 src/vstc/virtual_machine/vs_undefined.rs diff --git a/src/vstc/run.rs b/src/vstc/run.rs index 29de31b..22fab56 100644 --- a/src/vstc/run.rs +++ b/src/vstc/run.rs @@ -24,7 +24,8 @@ pub fn command(args: &Vec) { let mut vm = VirtualMachine::new(); vm.run(&bytecode); - vm.print(); + + println!("{}", vm.return_value); } fn to_bytecode(option: &String, file_path: &String) -> Rc> { diff --git a/src/vstc/virtual_machine/bytecode_decoder.rs b/src/vstc/virtual_machine/bytecode_decoder.rs index d8d3f35..66e793e 100644 --- a/src/vstc/virtual_machine/bytecode_decoder.rs +++ b/src/vstc/virtual_machine/bytecode_decoder.rs @@ -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 { + // 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"), + } + } } diff --git a/src/vstc/virtual_machine/instruction.rs b/src/vstc/virtual_machine/instruction.rs new file mode 100644 index 0000000..9096d3d --- /dev/null +++ b/src/vstc/virtual_machine/instruction.rs @@ -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, +} diff --git a/src/vstc/virtual_machine/mod.rs b/src/vstc/virtual_machine/mod.rs index 41bacc4..bd456fa 100644 --- a/src/vstc/virtual_machine/mod.rs +++ b/src/vstc/virtual_machine/mod.rs @@ -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; diff --git a/src/vstc/virtual_machine/virtual_machine.rs b/src/vstc/virtual_machine/virtual_machine.rs index 0d21009..ca321eb 100644 --- a/src/vstc/virtual_machine/virtual_machine.rs +++ b/src/vstc/virtual_machine/virtual_machine.rs @@ -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, +} + +pub struct StackFrame { + pub decoder: BytecodeDecoder, + pub registers: Vec, + pub this_target: usize, + pub return_target: usize, } impl VirtualMachine { pub fn run(&mut self, bytecode: &Rc>) { + 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(); + } } } diff --git a/src/vstc/virtual_machine/vs_function.rs b/src/vstc/virtual_machine/vs_function.rs index a614274..56dffd8 100644 --- a/src/vstc/virtual_machine/vs_function.rs +++ b/src/vstc/virtual_machine/vs_function.rs @@ -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>, @@ -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 = 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; + } } diff --git a/src/vstc/virtual_machine/vs_number.rs b/src/vstc/virtual_machine/vs_number.rs index 93f4fb1..319a8b8 100644 --- a/src/vstc/virtual_machine/vs_number.rs +++ b/src/vstc/virtual_machine/vs_number.rs @@ -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; + } } diff --git a/src/vstc/virtual_machine/vs_pointer.rs b/src/vstc/virtual_machine/vs_pointer.rs index 0537fb6..1c92d68 100644 --- a/src/vstc/virtual_machine/vs_pointer.rs +++ b/src/vstc/virtual_machine/vs_pointer.rs @@ -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); + } } diff --git a/src/vstc/virtual_machine/vs_string.rs b/src/vstc/virtual_machine/vs_string.rs index 40bab25..103cd0a 100644 --- a/src/vstc/virtual_machine/vs_string.rs +++ b/src/vstc/virtual_machine/vs_string.rs @@ -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; } -} \ No newline at end of file + + fn push_frame(&self, vm: &mut VirtualMachine) -> bool { + return false; + } +} diff --git a/src/vstc/virtual_machine/vs_undefined.rs b/src/vstc/virtual_machine/vs_undefined.rs new file mode 100644 index 0000000..c6782bc --- /dev/null +++ b/src/vstc/virtual_machine/vs_undefined.rs @@ -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; + } +} diff --git a/src/vstc/virtual_machine/vs_value.rs b/src/vstc/virtual_machine/vs_value.rs index 41f638b..f7682d8 100644 --- a/src/vstc/virtual_machine/vs_value.rs +++ b/src/vstc/virtual_machine/vs_value.rs @@ -1,6 +1,7 @@ use std::rc::Rc; use super::vs_string::VsString; +use super::virtual_machine::VirtualMachine; pub type Val = Rc; @@ -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 {