mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-14 07:57:57 -05:00
Refactor Val to an enum
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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<Val> = 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;
|
||||
},
|
||||
|
||||
|
||||
@@ -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<StackFrame> {
|
||||
return None;
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
return self.value;
|
||||
}
|
||||
}
|
||||
@@ -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<StackFrame> {
|
||||
let mut registers: Vec<Val> = 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 {
|
||||
|
||||
@@ -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<StackFrame> {
|
||||
return None;
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -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<StackFrame> {
|
||||
return None;
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
return self.value != 0_f64;
|
||||
}
|
||||
}
|
||||
@@ -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<Vec<u8>>, 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<StackFrame> {
|
||||
return self.decode().make_frame();
|
||||
}
|
||||
|
||||
@@ -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<StackFrame> {
|
||||
return None;
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
return self.value != "";
|
||||
}
|
||||
}
|
||||
@@ -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<StackFrame> {
|
||||
return None;
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -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<dyn VsValue>;
|
||||
#[derive(Clone)]
|
||||
pub enum Val {
|
||||
Void,
|
||||
Undefined,
|
||||
Null,
|
||||
Bool(bool),
|
||||
Number(f64),
|
||||
String(Rc<String>),
|
||||
Array(Rc<Vec<Val>>),
|
||||
Object(Rc<BTreeMap<String, Val>>),
|
||||
Function(Rc<VsFunction>),
|
||||
Custom(Rc<dyn ValTrait>),
|
||||
}
|
||||
|
||||
#[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<StackFrame>;
|
||||
}
|
||||
|
||||
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<StackFrame> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user