mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-13 15:38:06 -05:00
wip vm::run
This commit is contained in:
@@ -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>> {
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
44
src/vstc/virtual_machine/instruction.rs
Normal file
44
src/vstc/virtual_machine/instruction.rs
Normal 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,
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
36
src/vstc/virtual_machine/vs_undefined.rs
Normal file
36
src/vstc/virtual_machine/vs_undefined.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user