diff --git a/src/vstc/virtual_machine/bytecode_decoder.rs b/src/vstc/virtual_machine/bytecode_decoder.rs index 7f6eee5..9f82dd5 100644 --- a/src/vstc/virtual_machine/bytecode_decoder.rs +++ b/src/vstc/virtual_machine/bytecode_decoder.rs @@ -1,10 +1,6 @@ use std::rc::Rc; use super::vs_value::Val; -use super::vs_undefined::VsUndefined; -use super::vs_null::VsNull; -use super::vs_number::VsNumber; -use super::vs_string::VsString; use super::vs_pointer::VsPointer; use super::vs_function::VsFunction; use super::instruction::Instruction; @@ -83,19 +79,19 @@ impl BytecodeDecoder { return match self.decode_type() { End => std::panic!("Cannot decode end"), - Undefined => VsUndefined::new(), - Null => VsNull::new(), - False => std::panic!("Not implemented"), - True => std::panic!("Not implemented"), - SignedByte => VsNumber::from_f64( + Undefined => Val::Undefined, + Null => Val::Null, + False => Val::Bool(false), + True => Val::Bool(true), + SignedByte => Val::Number( self.decode_signed_byte() as f64 ), - Number => VsNumber::from_f64( + Number => Val::Number( self.decode_number() ), - String => VsString::from_string( + String => Val::String(Rc::new( self.decode_string() - ), + )), Array => std::panic!("Not implemented"), Object => std::panic!("Not implemented"), Function => self.decode_function_header(), @@ -184,12 +180,12 @@ impl BytecodeDecoder { let register_count = self.decode_byte() as usize; let parameter_count = self.decode_byte() as usize; - return Rc::new(VsFunction { + return Val::Function(Rc::new(VsFunction { bytecode: self.data.clone(), register_count: register_count, parameter_count: parameter_count, start: self.pos, - }); + })); } pub fn decode_instruction(&mut self) -> Instruction { diff --git a/src/vstc/virtual_machine/mod.rs b/src/vstc/virtual_machine/mod.rs index 4f04e4e..e655f97 100644 --- a/src/vstc/virtual_machine/mod.rs +++ b/src/vstc/virtual_machine/mod.rs @@ -1,9 +1,4 @@ mod vs_value; -mod vs_undefined; -mod vs_null; -mod vs_bool; -mod vs_number; -mod vs_string; mod vs_function; mod vs_pointer; mod operations; diff --git a/src/vstc/virtual_machine/operations.rs b/src/vstc/virtual_machine/operations.rs index d8a1f2a..f552a5b 100644 --- a/src/vstc/virtual_machine/operations.rs +++ b/src/vstc/virtual_machine/operations.rs @@ -1,31 +1,30 @@ +use std::rc::Rc; + use super::vs_value::Val; use super::vs_value::ValTrait; use super::vs_value::VsType; -use super::vs_string::VsString; -use super::vs_number::VsNumber; -use super::vs_bool::VsBool; pub fn op_plus(left: &Val, right: &Val) -> Val { let left_prim = left.to_primitive(); let right_prim = right.to_primitive(); if left_prim.typeof_() == VsType::String || right_prim.typeof_() == VsType::String { - return VsString::from_string(left_prim.to_string() + &right_prim.to_string()); + return Val::String(Rc::new(left_prim.val_to_string() + &right_prim.val_to_string())); } - return VsNumber::from_f64(left_prim.to_number() + right_prim.to_number()); + return Val::Number(left_prim.to_number() + right_prim.to_number()); } pub fn op_minus(left: &Val, right: &Val) -> Val { - return VsNumber::from_f64(left.to_number() - right.to_number()); + return Val::Number(left.to_number() - right.to_number()); } pub fn op_mul(left: &Val, right: &Val) -> Val { - return VsNumber::from_f64(left.to_number() * right.to_number()); + return Val::Number(left.to_number() * right.to_number()); } pub fn op_mod(left: &Val, right: &Val) -> Val { - return VsNumber::from_f64(left.to_number() % right.to_number()); + return Val::Number(left.to_number() % right.to_number()); } pub fn op_less(left: &Val, right: &Val) -> Val { @@ -33,7 +32,7 @@ pub fn op_less(left: &Val, right: &Val) -> Val { std::panic!("Not implemented"); } - return VsBool::from_bool(left.to_number() < right.to_number()); + return Val::Bool(left.to_number() < right.to_number()); } pub fn op_triple_ne(left: &Val, right: &Val) -> Val { @@ -41,5 +40,5 @@ pub fn op_triple_ne(left: &Val, right: &Val) -> Val { std::panic!("Not implemented"); } - return VsBool::from_bool(left.to_number() != right.to_number()); + return Val::Bool(left.to_number() != right.to_number()); } diff --git a/src/vstc/virtual_machine/virtual_machine.rs b/src/vstc/virtual_machine/virtual_machine.rs index 8c9385e..90d023e 100644 --- a/src/vstc/virtual_machine/virtual_machine.rs +++ b/src/vstc/virtual_machine/virtual_machine.rs @@ -1,8 +1,7 @@ use std::rc::Rc; use super::vs_value::Val; -use super::vs_undefined::VsUndefined; -use super::vs_number::VsNumber; +use super::vs_value::ValTrait; use super::operations; use super::bytecode_decoder::BytecodeDecoder; use super::bytecode_decoder::BytecodeType; @@ -48,8 +47,8 @@ impl VirtualMachine { }; let mut registers: Vec = Vec::with_capacity(2); - registers.push(VsUndefined::new()); - registers.push(VsUndefined::new()); + registers.push(Val::Undefined); + registers.push(Val::Undefined); let frame = StackFrame { decoder: BytecodeDecoder { @@ -88,7 +87,7 @@ impl VirtualMachine { OpInc => { let register_index = frame.decoder.decode_register_index().unwrap(); let mut val = frame.registers[register_index].clone(); - val = operations::op_plus(&val, &VsNumber::from_f64(1_f64)); + val = operations::op_plus(&val, &Val::Number(1_f64)); frame.registers[register_index] = val; }, diff --git a/src/vstc/virtual_machine/vs_bool.rs b/src/vstc/virtual_machine/vs_bool.rs deleted file mode 100644 index 0158815..0000000 --- a/src/vstc/virtual_machine/vs_bool.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::rc::Rc; - -use super::vs_value::Val; -use super::vs_value::VsType; -use super::vs_value::VsValue; -use super::virtual_machine::StackFrame; - -pub struct VsBool { - value: bool, -} - -impl VsBool { - pub fn from_bool(value: bool) -> Val { - return Rc::new(VsBool { value: value }); - } -} - -impl VsValue for VsBool { - fn typeof_(&self) -> VsType { - return VsType::Bool; - } - - fn to_string(&self) -> String { - return self.value.to_string(); - } - - fn to_number(&self) -> f64 { - return if self.value { 1_f64 } else { 0_f64 }; - } - - fn is_primitive(&self) -> bool { - return true; - } - - fn make_frame(&self) -> Option { - return None; - } - - fn is_truthy(&self) -> bool { - return self.value; - } -} diff --git a/src/vstc/virtual_machine/vs_function.rs b/src/vstc/virtual_machine/vs_function.rs index 6651254..b892398 100644 --- a/src/vstc/virtual_machine/vs_function.rs +++ b/src/vstc/virtual_machine/vs_function.rs @@ -1,9 +1,8 @@ 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::vs_value::ValTrait; use super::virtual_machine::StackFrame; use super::bytecode_decoder::BytecodeDecoder; @@ -14,12 +13,12 @@ pub struct VsFunction { pub start: usize, } -impl VsValue for VsFunction { +impl ValTrait for VsFunction { fn typeof_(&self) -> VsType { return VsType::Function; } - fn to_string(&self) -> String { + fn val_to_string(&self) -> String { return "[function]".to_string(); } @@ -31,11 +30,15 @@ impl VsValue for VsFunction { return false; } + fn to_primitive(&self) -> Val { + return Val::String(Rc::new(self.val_to_string())); + } + fn make_frame(&self) -> Option { let mut registers: Vec = Vec::with_capacity(self.register_count - 1); for _ in 0..(self.register_count - 1) { - registers.push(VsUndefined::new()); + registers.push(Val::Undefined); } return Some(StackFrame { diff --git a/src/vstc/virtual_machine/vs_null.rs b/src/vstc/virtual_machine/vs_null.rs deleted file mode 100644 index 9439f03..0000000 --- a/src/vstc/virtual_machine/vs_null.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::rc::Rc; - -use super::vs_value::Val; -use super::vs_value::VsType; -use super::vs_value::VsValue; -use super::virtual_machine::StackFrame; - -pub struct VsNull {} - -impl VsNull { - pub fn new() -> Val { - return Rc::new(VsNull {}); - } -} - -impl VsValue for VsNull { - fn typeof_(&self) -> VsType { - return VsType::Null; - } - - fn to_string(&self) -> String { - return "null".to_string(); - } - - fn to_number(&self) -> f64 { - return 0_f64; - } - - fn is_primitive(&self) -> bool { - return true; - } - - fn make_frame(&self) -> Option { - return None; - } - - fn is_truthy(&self) -> bool { - return false; - } -} diff --git a/src/vstc/virtual_machine/vs_number.rs b/src/vstc/virtual_machine/vs_number.rs deleted file mode 100644 index a095902..0000000 --- a/src/vstc/virtual_machine/vs_number.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::rc::Rc; - -use super::vs_value::Val; -use super::vs_value::VsType; -use super::vs_value::VsValue; -use super::virtual_machine::StackFrame; - -pub struct VsNumber { - value: f64, -} - -impl VsNumber { - pub fn from_f64(value: f64) -> Val { - return Rc::new(VsNumber { value: value }); - } -} - -impl VsValue for VsNumber { - fn typeof_(&self) -> VsType { - return VsType::Number; - } - - fn to_string(&self) -> String { - return self.value.to_string(); - } - - fn to_number(&self) -> f64 { - return self.value; - } - - fn is_primitive(&self) -> bool { - return true; - } - - fn make_frame(&self) -> Option { - return None; - } - - fn is_truthy(&self) -> bool { - return self.value != 0_f64; - } -} diff --git a/src/vstc/virtual_machine/vs_pointer.rs b/src/vstc/virtual_machine/vs_pointer.rs index e94d340..4930ad7 100644 --- a/src/vstc/virtual_machine/vs_pointer.rs +++ b/src/vstc/virtual_machine/vs_pointer.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use std::cell::RefCell; use super::vs_value::Val; -use super::vs_value::VsValue; +use super::vs_value::ValTrait; use super::vs_value::VsType; use super::virtual_machine::StackFrame; use super::bytecode_decoder::BytecodeDecoder; @@ -16,11 +16,11 @@ pub struct VsPointer { impl VsPointer { pub fn new(bytecode: &Rc>, pos: usize) -> Val { - return Rc::new(VsPointer { + return Val::Custom(Rc::new(VsPointer { bytecode: bytecode.clone(), pos: pos, decoded: RefCell::new(None), - }); + })); } pub fn decode(&self) -> Val { @@ -45,7 +45,7 @@ impl VsPointer { } } -impl VsValue for VsPointer { +impl ValTrait for VsPointer { fn typeof_(&self) -> VsType { let mut bd = BytecodeDecoder { data: self.bytecode.clone(), @@ -70,8 +70,8 @@ impl VsValue for VsPointer { } } - fn to_string(&self) -> String { - return self.decode().to_string(); + fn val_to_string(&self) -> String { + return self.decode().val_to_string(); } fn to_number(&self) -> f64 { @@ -91,6 +91,10 @@ impl VsValue for VsPointer { } } + fn to_primitive(&self) -> Val { + return self.decode().to_primitive(); + } + fn make_frame(&self) -> Option { return self.decode().make_frame(); } diff --git a/src/vstc/virtual_machine/vs_string.rs b/src/vstc/virtual_machine/vs_string.rs deleted file mode 100644 index 68615c0..0000000 --- a/src/vstc/virtual_machine/vs_string.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::rc::Rc; - -use super::vs_value::Val; -use super::vs_value::VsType; -use super::vs_value::VsValue; -use super::virtual_machine::StackFrame; - -pub struct VsString { - value: String, -} - -impl VsString { - pub fn from_str(value: &str) -> Val { - return Rc::new(VsString { value: value.to_string() }); - } - - pub fn from_string(value: String) -> Val { - return Rc::new(VsString { value: value }); - } -} - -impl VsValue for VsString { - fn typeof_(&self) -> VsType { - return VsType::String; - } - - fn to_string(&self) -> String { - return self.value.clone(); - } - - fn to_number(&self) -> f64 { - std::panic!("not implemented"); - } - - fn is_primitive(&self) -> bool { - return true; - } - - fn make_frame(&self) -> Option { - return None; - } - - fn is_truthy(&self) -> bool { - return self.value != ""; - } -} diff --git a/src/vstc/virtual_machine/vs_undefined.rs b/src/vstc/virtual_machine/vs_undefined.rs deleted file mode 100644 index 594f0cb..0000000 --- a/src/vstc/virtual_machine/vs_undefined.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::rc::Rc; - -use super::vs_value::Val; -use super::vs_value::VsType; -use super::vs_value::VsValue; -use super::virtual_machine::StackFrame; - -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 make_frame(&self) -> Option { - return None; - } - - fn is_truthy(&self) -> bool { - return false; - } -} diff --git a/src/vstc/virtual_machine/vs_value.rs b/src/vstc/virtual_machine/vs_value.rs index 6a5e9b0..44b02e9 100644 --- a/src/vstc/virtual_machine/vs_value.rs +++ b/src/vstc/virtual_machine/vs_value.rs @@ -1,9 +1,23 @@ use std::rc::Rc; +use std::collections::BTreeMap; +use std::str::FromStr; -use super::vs_string::VsString; +use super::vs_function::VsFunction; use super::virtual_machine::StackFrame; -pub type Val = Rc; +#[derive(Clone)] +pub enum Val { + Void, + Undefined, + Null, + Bool(bool), + Number(f64), + String(Rc), + Array(Rc>), + Object(Rc>), + Function(Rc), + Custom(Rc), +} #[derive(PartialEq)] pub enum VsType { @@ -17,47 +31,144 @@ pub enum VsType { Function, } -impl VsType { - pub fn as_val(&self) -> Val { - return VsString::from_str(match self { - Undefined => "undefined", - Null => "object", - Bool => "boolean", - Number => "number", - String => "string", - Array => "object", - Object => "object", - Function => "function", - }); - } -} - -pub trait VsValue { +pub trait ValTrait { fn typeof_(&self) -> VsType; - fn to_string(&self) -> String; + fn val_to_string(&self) -> String; fn to_number(&self) -> f64; fn is_primitive(&self) -> bool; + fn to_primitive(&self) -> Val; fn is_truthy(&self) -> bool; fn make_frame(&self) -> Option; } -pub trait ValTrait { - fn to_primitive(&self) -> Val; -} - impl ValTrait for Val { + fn typeof_(&self) -> VsType { + use Val::*; + + return match self { + Void => VsType::Undefined, + Undefined => VsType::Undefined, + Null => VsType::Null, + Bool(_) => VsType::Bool, + Number(_) => VsType::Number, + String(_) => VsType::String, + Array(_) => VsType::Array, + Object(_) => VsType::Object, + Function(_) => VsType::Function, + Custom(val) => val.typeof_(), + }; + } + + fn val_to_string(&self) -> String { + use Val::*; + + return match self { + Void => "undefined".to_string(), + Undefined => "undefined".to_string(), + Null => "null".to_string(), + Bool(b) => b.to_string(), + Number(x) => x.to_string(), // TODO: Match js's number string format + String(s) => s.to_string(), + Array(vals) => { + if vals.len() == 0 { + "".to_string() + } else if vals.len() == 1 { + vals[0].val_to_string() + } else { + let mut iter = vals.iter(); + let mut res = iter.next().unwrap().val_to_string(); + + for val in iter { + res += ","; + res += val.val_to_string().as_str(); + } + + res + } + }, + Object(_) => "[object Object]".to_string(), + Function(_) => "[function]".to_string(), + Custom(val) => val.val_to_string(), + }; + } + + fn to_number(&self) -> f64 { + use Val::*; + + return match self { + Void => f64::NAN, + Undefined => f64::NAN, + Null => 0_f64, + Bool(b) => *b as u8 as f64, + Number(x) => *x, + String(s) => f64::from_str(s).unwrap_or(f64::NAN), + Array(vals) => match vals.len() { + 0 => 0_f64, + 1 => vals[0].to_number(), + _ => f64::NAN, + }, + Object(_) => f64::NAN, + Function(_) => f64::NAN, + Custom(val) => val.to_number(), + }; + } + + fn is_primitive(&self) -> bool { + use Val::*; + + return match self { + Void => true, + Undefined => true, + Null => true, + Bool(_) => true, + Number(_) => true, + String(_) => true, + Array(_) => false, + Object(_) => false, + Function(_) => false, + Custom(val) => val.is_primitive(), + } + } + fn to_primitive(&self) -> Val { if self.is_primitive() { return self.clone(); } - return VsString::from_string(self.to_string()); + return Val::String(Rc::new(self.val_to_string())); + } + + fn is_truthy(&self) -> bool { + use Val::*; + + return match self { + Void => false, + Undefined => false, + Null => false, + Bool(b) => *b, + Number(x) => *x != 0_f64, + String(s) => s.len() > 0, + Array(_) => true, + Object(_) => true, + Function(_) => true, + Custom(val) => val.is_truthy(), + } + } + + fn make_frame(&self) -> Option { + use Val::*; + + return match self { + Function(f) => f.make_frame(), + Custom(val) => val.make_frame(), + _ => None, + } } } -impl std::fmt::Display for dyn VsValue { +impl std::fmt::Display for Val { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self.val_to_string()) } }