diff --git a/valuescript_vm/src/array_higher_functions/array_filter.rs b/valuescript_vm/src/array_higher_functions/array_filter.rs index 6ec6a00..17a0bac 100644 --- a/valuescript_vm/src/array_higher_functions/array_filter.rs +++ b/valuescript_vm/src/array_higher_functions/array_filter.rs @@ -1,9 +1,8 @@ -use std::rc::Rc; +use crate::vs_value::ToVal; -use super::super::vs_value::{Val, ValTrait}; -use super::super::vs_array::VsArray; use super::super::native_frame_function::NativeFrameFunction; -use super::array_mapping_frame::{ArrayMappingState, ArrayMappingFrame}; +use super::super::vs_value::{Val, ValTrait}; +use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState}; pub static FILTER: NativeFrameFunction = NativeFrameFunction { make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FilterState::default()))), @@ -26,6 +25,6 @@ impl ArrayMappingState for FilterState { fn finish(&mut self) -> Val { let mut filter_results = Vec::new(); std::mem::swap(&mut self.filter_results, &mut filter_results); - return Val::Array(Rc::new(VsArray::from(filter_results))); + filter_results.to_val() } } diff --git a/valuescript_vm/src/array_higher_functions/array_flat_map.rs b/valuescript_vm/src/array_higher_functions/array_flat_map.rs index 165ddb6..4c5d3ef 100644 --- a/valuescript_vm/src/array_higher_functions/array_flat_map.rs +++ b/valuescript_vm/src/array_higher_functions/array_flat_map.rs @@ -1,9 +1,8 @@ -use std::rc::Rc; +use crate::vs_value::ToVal; -use super::super::vs_value::{Val, ValTrait}; -use super::super::vs_array::VsArray; use super::super::native_frame_function::NativeFrameFunction; -use super::array_mapping_frame::{ArrayMappingState, ArrayMappingFrame}; +use super::super::vs_value::{Val, ValTrait}; +use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState}; pub static FLAT_MAP: NativeFrameFunction = NativeFrameFunction { make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FlatMapState::default()))), @@ -31,6 +30,6 @@ impl ArrayMappingState for FlatMapState { fn finish(&mut self) -> Val { let mut flat_map_results = Vec::new(); std::mem::swap(&mut self.flat_map_results, &mut flat_map_results); - return Val::Array(Rc::new(VsArray::from(flat_map_results))); + flat_map_results.to_val() } } diff --git a/valuescript_vm/src/array_higher_functions/array_map.rs b/valuescript_vm/src/array_higher_functions/array_map.rs index 5dfe69e..04ba679 100644 --- a/valuescript_vm/src/array_higher_functions/array_map.rs +++ b/valuescript_vm/src/array_higher_functions/array_map.rs @@ -1,9 +1,8 @@ -use std::rc::Rc; +use crate::vs_value::ToVal; -use super::super::vs_value::{Val}; -use super::super::vs_array::VsArray; use super::super::native_frame_function::NativeFrameFunction; -use super::array_mapping_frame::{ArrayMappingState, ArrayMappingFrame}; +use super::super::vs_value::Val; +use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState}; pub static MAP: NativeFrameFunction = NativeFrameFunction { make_frame: || Box::new(ArrayMappingFrame::new(Box::new(MapState::default()))), @@ -23,6 +22,6 @@ impl ArrayMappingState for MapState { fn finish(&mut self) -> Val { let mut map_results = Vec::new(); std::mem::swap(&mut self.map_results, &mut map_results); - return Val::Array(Rc::new(VsArray::from(map_results))); + map_results.to_val() } } diff --git a/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs b/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs index 6f1d2d2..8be0c85 100644 --- a/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs +++ b/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs @@ -1,11 +1,11 @@ use std::rc::Rc; +use crate::builtins::type_error_builtin::ToTypeError; use crate::native_function::ThisWrapper; use crate::stack_frame::FrameStepResult; use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait}; use crate::vs_array::VsArray; use crate::vs_value::{LoadFunctionResult, Val, ValTrait}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; pub trait ArrayMappingState { fn process(&mut self, i: usize, element: &Val, mapped: Val) -> Option; @@ -60,7 +60,7 @@ impl StackFrameTrait for ArrayMappingFrame { fn step(&mut self) -> FrameStepResult { let array_data = match &self.this { - None => return type_error!("Array fn called on non-array"), + None => return Err("Array fn called on non-array".to_type_error()), Some(ad) => ad, }; @@ -80,9 +80,7 @@ impl StackFrameTrait for ArrayMappingFrame { Some(el) => match el { Val::Void => Ok(FrameStepOk::Continue), _ => match self.mapper.load_function() { - LoadFunctionResult::NotAFunction => { - type_error!("map fn is not a function") - } + LoadFunctionResult::NotAFunction => Err("map fn is not a function".to_type_error()), LoadFunctionResult::NativeFunction(native_fn) => { match self.state.process( array_i, @@ -124,7 +122,7 @@ impl StackFrameTrait for ArrayMappingFrame { let element = match &self.this { None => { - self.early_exit = Some(type_error!("Array fn called on non-array")); + self.early_exit = Some(Err("Array fn called on non-array".to_type_error())); return; } Some(ad) => &ad.elements[array_i], diff --git a/valuescript_vm/src/array_higher_functions/array_reduce.rs b/valuescript_vm/src/array_higher_functions/array_reduce.rs index f0d9ffc..e3d2b99 100644 --- a/valuescript_vm/src/array_higher_functions/array_reduce.rs +++ b/valuescript_vm/src/array_higher_functions/array_reduce.rs @@ -1,11 +1,11 @@ use std::rc::Rc; +use crate::builtins::type_error_builtin::ToTypeError; use crate::native_frame_function::NativeFrameFunction; use crate::native_function::ThisWrapper; use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait}; use crate::vs_array::VsArray; use crate::vs_value::{LoadFunctionResult, Val, ValTrait}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; pub static REDUCE: NativeFrameFunction = NativeFrameFunction { make_frame: || { @@ -50,7 +50,7 @@ impl StackFrameTrait for ReduceFrame { fn step(&mut self) -> FrameStepResult { let array_data = match &self.this { - None => return type_error!("reduce called on non-array"), + None => return Err("reduce called on non-array".to_type_error()), Some(ad) => ad, }; @@ -66,7 +66,9 @@ impl StackFrameTrait for ReduceFrame { FrameStepOk::Continue } Some(value) => match self.reducer.load_function() { - LoadFunctionResult::NotAFunction => return type_error!("reduce fn is not a function"), + LoadFunctionResult::NotAFunction => { + return Err("reduce fn is not a function".to_type_error()) + } LoadFunctionResult::NativeFunction(native_fn) => { self.value = Some(native_fn( ThisWrapper::new(true, &mut Val::Undefined), @@ -91,7 +93,7 @@ impl StackFrameTrait for ReduceFrame { }, }, None => match &self.value { - None => return type_error!("reduce of empty array with no initial value"), + None => return Err("reduce of empty array with no initial value".to_type_error()), Some(value) => FrameStepOk::Pop(CallResult { return_: value.clone(), this: Val::Array(array_data.clone()), diff --git a/valuescript_vm/src/array_higher_functions/array_reduce_right.rs b/valuescript_vm/src/array_higher_functions/array_reduce_right.rs index e97326c..1362939 100644 --- a/valuescript_vm/src/array_higher_functions/array_reduce_right.rs +++ b/valuescript_vm/src/array_higher_functions/array_reduce_right.rs @@ -1,11 +1,11 @@ use std::rc::Rc; +use crate::builtins::type_error_builtin::ToTypeError; use crate::native_frame_function::NativeFrameFunction; use crate::native_function::ThisWrapper; use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait}; use crate::vs_array::VsArray; use crate::vs_value::{LoadFunctionResult, Val, ValTrait}; -use crate::{builtins::type_error_builtin::to_type_error, format_err, type_error}; pub static REDUCE_RIGHT: NativeFrameFunction = NativeFrameFunction { make_frame: || { @@ -56,14 +56,14 @@ impl StackFrameTrait for ReduceRightFrame { fn step(&mut self) -> FrameStepResult { let array_data = match &self.this { - None => return type_error!("reduceRight called on non-array"), + None => return Err("reduceRight called on non-array".to_type_error()), Some(ad) => ad, }; if self.array_i == 0 { match &self.value { None => { - return type_error!("reduceRight of empty array with no initial value"); + return Err("reduceRight of empty array with no initial value".to_type_error()); } Some(value) => { return Ok(FrameStepOk::Pop(CallResult { @@ -88,7 +88,7 @@ impl StackFrameTrait for ReduceRightFrame { } Some(value) => match self.reducer.load_function() { LoadFunctionResult::NotAFunction => { - return format_err!("TpeError: reduceRight fn is not a function") + return Err("reduceRight fn is not a function".to_type_error()) } LoadFunctionResult::NativeFunction(native_fn) => { self.value = Some(native_fn( diff --git a/valuescript_vm/src/array_higher_functions/array_sort.rs b/valuescript_vm/src/array_higher_functions/array_sort.rs index 7957c66..122c26a 100644 --- a/valuescript_vm/src/array_higher_functions/array_sort.rs +++ b/valuescript_vm/src/array_higher_functions/array_sort.rs @@ -1,12 +1,12 @@ use std::rc::Rc; +use crate::builtins::type_error_builtin::ToTypeError; use crate::native_frame_function::NativeFrameFunction; use crate::native_function::ThisWrapper; use crate::stack_frame::FrameStepResult; use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait}; use crate::vs_array::VsArray; -use crate::vs_value::{LoadFunctionResult, Val, ValTrait}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{LoadFunctionResult, ToVal, Val, ValTrait}; pub static SORT: NativeFrameFunction = NativeFrameFunction { make_frame: || { @@ -208,7 +208,7 @@ enum SortTreeNodeData { impl StackFrameTrait for SortFrame { fn write_this(&mut self, const_: bool, this: Val) -> Result<(), Val> { if const_ { - return type_error!("Cannot sort const array"); + return Err("Cannot sort const array".to_type_error()); } self.this = this.as_array_data(); @@ -229,7 +229,7 @@ impl StackFrameTrait for SortFrame { fn step(&mut self) -> FrameStepResult { if !self.started { let array_data = match &mut self.this { - None => return type_error!("array fn called on non-array"), + None => return Err("array fn called on non-array".to_type_error()), Some(ad) => ad, }; @@ -263,7 +263,7 @@ impl StackFrameTrait for SortFrame { SortTreeNodeData::Sorted(vals) => { let mut owned_vals = vec![]; std::mem::swap(&mut owned_vals, vals); - let res = Val::Array(Rc::new(VsArray::from(owned_vals))); + let res = owned_vals.to_val(); FrameStepOk::Pop(CallResult { return_: res.clone(), @@ -274,7 +274,7 @@ impl StackFrameTrait for SortFrame { }, Some((left, right)) => match self.comparator.load_function() { LoadFunctionResult::NotAFunction => { - return type_error!("comparator is not a function"); + return Err("comparator is not a function".to_type_error()); } LoadFunctionResult::NativeFunction(native_fn) => { let res = native_fn( diff --git a/valuescript_vm/src/bigint_methods.rs b/valuescript_vm/src/bigint_methods.rs index e4e049b..8c0cb95 100644 --- a/valuescript_vm/src/bigint_methods.rs +++ b/valuescript_vm/src/bigint_methods.rs @@ -1,12 +1,10 @@ -use std::rc::Rc; - use num_bigint::BigInt; use crate::{ - format_err, + builtins::error_builtin::ToError, native_function::{NativeFunction, ThisWrapper}, todo_fn::TODO, - vs_value::{Val, ValTrait}, + vs_value::{ToValString, Val, ValTrait}, }; pub fn op_sub_bigint(_bigint: &BigInt, subscript: &Val) -> Val { @@ -23,12 +21,12 @@ static TO_STRING: NativeFunction = NativeFunction { Ok(match this.get() { Val::BigInt(_) => match params.get(0) { Some(_) => { - return format_err!("TODO: toString with radix"); + return Err("TODO: toString with radix".to_error()); } - None => Val::String(Rc::new(this.get().val_to_string())), + None => this.get().to_val_string(), }, - _ => return format_err!("TODO: bigint indirection"), + _ => return Err("TODO: bigint indirection".to_error()), }) }, }; @@ -37,7 +35,7 @@ static VALUE_OF: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { Val::BigInt(bigint) => Val::BigInt(bigint.clone()), - _ => return format_err!("TODO: bigint indirection"), + _ => return Err("TODO: bigint indirection".to_error()), }) }, }; diff --git a/valuescript_vm/src/builtins/array_builtin.rs b/valuescript_vm/src/builtins/array_builtin.rs index 3634619..c17225f 100644 --- a/valuescript_vm/src/builtins/array_builtin.rs +++ b/valuescript_vm/src/builtins/array_builtin.rs @@ -4,18 +4,18 @@ use num_bigint::BigInt; use crate::{ builtins::range_error_builtin::to_range_error, - builtins::type_error_builtin::to_type_error, - format_err, native_function::{NativeFunction, ThisWrapper}, operations::op_sub, - range_error, type_error, + range_error, vs_array::VsArray, vs_class::VsClass, vs_object::VsObject, - vs_value::{LoadFunctionResult, Val, VsType}, + vs_value::{LoadFunctionResult, ToVal, ToValString, Val, VsType}, ValTrait, }; +use super::type_error_builtin::ToTypeError; + pub struct ArrayBuiltin {} pub static ARRAY_BUILTIN: ArrayBuiltin = ArrayBuiltin {}; @@ -37,7 +37,7 @@ impl ValTrait for ArrayBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new("function Array() { [native code] }".to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -75,7 +75,7 @@ impl ValTrait for ArrayBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Array builtin") + Err("Cannot assign to subscript of Array builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -106,36 +106,31 @@ static IS_ARRAY: NativeFunction = NativeFunction { static FROM: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { let first_param = match params.get(0) { - None => return type_error!("undefined is not iterable"), + None => return Err("undefined is not iterable".to_type_error()), Some(p) => p, }; if params.len() > 1 { - return format_err!("TODO: Using Array.from with a map function"); + return Err(format!("TODO: Using Array.from with a map function").to_val()); } Ok(match first_param { Val::Array(arr) => Val::Array(arr.clone()), - Val::String(s) => Val::Array(Rc::new(VsArray::from( - s.chars() - .map(|c| Val::String(Rc::new(c.to_string()))) - .collect(), - ))), - Val::Void | Val::Undefined | Val::Null => return type_error!("items is not iterable"), + Val::String(s) => s.chars().map(|c| c.to_val()).collect::>().to_val(), + Val::Void | Val::Undefined | Val::Null => { + return Err("items is not iterable".to_type_error()) + } Val::Bool(..) | Val::Number(..) | Val::BigInt(..) | Val::Symbol(..) => { - Val::Array(Rc::new(VsArray::new())) + VsArray::new().to_val() } Val::Object(..) | Val::Function(..) | Val::Class(..) | Val::Static(..) | Val::Custom(..) => { - let len = op_sub( - first_param.clone(), - Val::String(Rc::new("length".to_string())), - ) - .map_err(|e| e.val_to_string()) - .unwrap() // TODO: Exception - .to_number(); + let len = op_sub(first_param.clone(), "length".to_val()) + .map_err(|e| e.val_to_string()) + .unwrap() // TODO: Exception + .to_number(); if len.is_sign_negative() || len.is_nan() { - return Ok(Val::Array(Rc::new(VsArray::new()))); + return Ok(VsArray::new().to_val()); } if len.is_infinite() { @@ -156,7 +151,7 @@ static FROM: NativeFunction = NativeFunction { ); } - Val::Array(Rc::new(VsArray::from(arr))) + VsArray::from(arr).to_val() } }) }, @@ -164,13 +159,13 @@ static FROM: NativeFunction = NativeFunction { static OF: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { - Ok(Val::Array(Rc::new(VsArray::from(params)))) + Ok(VsArray::from(params).to_val()) }, }; fn to_array(_: ThisWrapper, params: Vec) -> Result { if params.len() != 1 { - return Ok(Val::Array(Rc::new(VsArray::from(params)))); + return Ok(VsArray::from(params).to_val()); } Ok(match params[0] { @@ -187,8 +182,8 @@ fn to_array(_: ThisWrapper, params: Vec) -> Result { arr.push(Val::Void); } - Val::Array(Rc::new(VsArray::from(arr))) + VsArray::from(arr).to_val() } - _ => Val::Array(Rc::new(VsArray::from(params))), + _ => VsArray::from(params).to_val(), }) } diff --git a/valuescript_vm/src/builtins/boolean_builtin.rs b/valuescript_vm/src/builtins/boolean_builtin.rs index e161dd7..000401e 100644 --- a/valuescript_vm/src/builtins/boolean_builtin.rs +++ b/valuescript_vm/src/builtins/boolean_builtin.rs @@ -3,16 +3,16 @@ use std::rc::Rc; use num_bigint::BigInt; use crate::{ - builtins::type_error_builtin::to_type_error, native_function::ThisWrapper, - type_error, vs_array::VsArray, vs_class::VsClass, vs_object::VsObject, - vs_value::{LoadFunctionResult, Val, VsType}, + vs_value::{LoadFunctionResult, ToValString, Val, VsType}, ValTrait, }; +use super::type_error_builtin::ToTypeError; + pub struct BooleanBuiltin {} pub static BOOLEAN_BUILTIN: BooleanBuiltin = BooleanBuiltin {}; @@ -34,7 +34,7 @@ impl ValTrait for BooleanBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new("function Boolean() { [native code] }".to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -67,7 +67,7 @@ impl ValTrait for BooleanBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Boolean builtin") + Err("Cannot assign to subscript of Boolean builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { diff --git a/valuescript_vm/src/builtins/debug_builtin.rs b/valuescript_vm/src/builtins/debug_builtin.rs index a0c2dde..cede229 100644 --- a/valuescript_vm/src/builtins/debug_builtin.rs +++ b/valuescript_vm/src/builtins/debug_builtin.rs @@ -6,8 +6,9 @@ use crate::native_function::{NativeFunction, ThisWrapper}; use crate::vs_array::VsArray; use crate::vs_class::VsClass; use crate::vs_object::VsObject; -use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{LoadFunctionResult, ToValString, Val, ValTrait, VsType}; + +use super::type_error_builtin::ToTypeError; pub struct DebugBuiltin {} @@ -30,7 +31,7 @@ impl ValTrait for DebugBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new(self.val_to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -69,7 +70,7 @@ impl ValTrait for DebugBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Debug builtin") + Err("Cannot assign to subscript of Debug builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { diff --git a/valuescript_vm/src/builtins/error_builtin.rs b/valuescript_vm/src/builtins/error_builtin.rs index 12257ea..186a79e 100644 --- a/valuescript_vm/src/builtins/error_builtin.rs +++ b/valuescript_vm/src/builtins/error_builtin.rs @@ -3,9 +3,8 @@ use std::{collections::BTreeMap, rc::Rc}; use num_bigint::BigInt; use crate::native_function::ThisWrapper; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{ToVal, ToValString}; use crate::{ - format_val, native_function::NativeFunction, operations::{op_sub, op_submov}, vs_array::VsArray, @@ -15,6 +14,8 @@ use crate::{ ValTrait, }; +use super::type_error_builtin::ToTypeError; + pub struct ErrorBuiltin {} pub static ERROR_BUILTIN: ErrorBuiltin = ErrorBuiltin {}; @@ -36,7 +37,7 @@ impl ValTrait for ErrorBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new("function Error() { [native code] }".to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -64,7 +65,15 @@ impl ValTrait for ErrorBuiltin { } fn load_function(&self) -> LoadFunctionResult { - LoadFunctionResult::NativeFunction(to_error) + LoadFunctionResult::NativeFunction(|_: ThisWrapper, params: Vec| -> Result { + Ok( + match params.get(0) { + Some(param) => param.to_val_string(), + None => "".to_val(), + } + .to_error(), + ) + }) } fn sub(&self, _key: Val) -> Result { @@ -72,7 +81,7 @@ impl ValTrait for ErrorBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Error builtin") + Err("Cannot assign to subscript of Error builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -88,44 +97,44 @@ impl ValTrait for ErrorBuiltin { } } -#[macro_export] -macro_rules! error { - ($fmt:expr $(, $($arg:expr),*)?) => {{ - let formatted_string = format!($fmt $(, $($arg),*)?); - Err(to_error( - ThisWrapper::new(true, &mut Val::Undefined), - vec![Val::String(Rc::new(formatted_string))], - ).unwrap()) - }}; +pub trait ToError { + fn to_error(self) -> Val; } -pub fn to_error(_: ThisWrapper, params: Vec) -> Result { - Ok(Val::Object(Rc::new(VsObject { - string_map: BTreeMap::from([( - "message".to_string(), - Val::String(Rc::new(match params.get(0) { - Some(param) => param.val_to_string(), - None => "".to_string(), - })), - )]), - symbol_map: Default::default(), - prototype: Some(make_error_prototype()), - }))) +impl ToError for Val { + fn to_error(self) -> Val { + VsObject { + string_map: BTreeMap::from([("message".to_string(), self.to_val_string())]), + symbol_map: Default::default(), + prototype: Some(make_error_prototype()), + } + .to_val() + } +} + +impl ToError for String { + fn to_error(self) -> Val { + self.to_val().to_error() + } +} + +impl ToError for &str { + fn to_error(self) -> Val { + self.to_string().to_error() + } } // TODO: Static? (Rc -> Arc?) fn make_error_prototype() -> Val { - Val::Object(Rc::new(VsObject { + VsObject { string_map: BTreeMap::from([ - ( - "name".to_string(), - Val::String(Rc::new("Error".to_string())), - ), - ("toString".to_string(), Val::Static(&ERROR_TO_STRING)), + ("name".to_string(), "Error".to_val()), + ("toString".to_string(), ERROR_TO_STRING.to_val()), ]), symbol_map: Default::default(), prototype: None, - })) + } + .to_val() } static SET_MESSAGE: NativeFunction = NativeFunction { @@ -135,11 +144,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction { None => "".to_string(), }; - op_submov( - this.get_mut()?, - format_val!("message"), - format_val!("{}", message), - )?; + op_submov(this.get_mut()?, "message".to_val(), message.to_val())?; Ok(Val::Undefined) }, @@ -147,7 +152,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction { static ERROR_TO_STRING: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { - let message = op_sub(this.get().clone(), format_val!("message"))?; - Ok(format_val!("Error({})", message)) // TODO: Fixes needed here (and other errors) + let message = op_sub(this.get().clone(), "message".to_val())?; + Ok(format!("Error({})", message).to_val()) // TODO: Fixes needed here (and other errors) }, }; diff --git a/valuescript_vm/src/builtins/math_builtin.rs b/valuescript_vm/src/builtins/math_builtin.rs index 684e277..252d669 100644 --- a/valuescript_vm/src/builtins/math_builtin.rs +++ b/valuescript_vm/src/builtins/math_builtin.rs @@ -7,8 +7,9 @@ use crate::operations::to_u32; use crate::vs_array::VsArray; use crate::vs_class::VsClass; use crate::vs_object::VsObject; -use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{LoadFunctionResult, ToValString, Val, ValTrait, VsType}; + +use super::type_error_builtin::ToTypeError; pub struct MathBuiltin {} @@ -31,7 +32,7 @@ impl ValTrait for MathBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new(self.val_to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -114,7 +115,7 @@ impl ValTrait for MathBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Math builtin") + Err("Cannot assign to subscript of Math builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { diff --git a/valuescript_vm/src/builtins/number_builtin.rs b/valuescript_vm/src/builtins/number_builtin.rs index 4ab387f..201dced 100644 --- a/valuescript_vm/src/builtins/number_builtin.rs +++ b/valuescript_vm/src/builtins/number_builtin.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use num_bigint::BigInt; use crate::native_function::ThisWrapper; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::ToValString; use crate::{ native_function::NativeFunction, vs_array::VsArray, @@ -13,6 +13,8 @@ use crate::{ ValTrait, }; +use super::type_error_builtin::ToTypeError; + pub struct NumberBuiltin {} pub static NUMBER_BUILTIN: NumberBuiltin = NumberBuiltin {}; @@ -34,7 +36,7 @@ impl ValTrait for NumberBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new("function Number() { [native code] }".to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -83,7 +85,7 @@ impl ValTrait for NumberBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Number builtin") + Err("Cannot assign to subscript of Number builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { diff --git a/valuescript_vm/src/builtins/range_error_builtin.rs b/valuescript_vm/src/builtins/range_error_builtin.rs index 486ef4f..4409d54 100644 --- a/valuescript_vm/src/builtins/range_error_builtin.rs +++ b/valuescript_vm/src/builtins/range_error_builtin.rs @@ -3,9 +3,8 @@ use std::{collections::BTreeMap, rc::Rc}; use num_bigint::BigInt; use crate::native_function::ThisWrapper; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{ToVal, ToValString}; use crate::{ - format_val, native_function::NativeFunction, operations::{op_sub, op_submov}, vs_array::VsArray, @@ -15,6 +14,8 @@ use crate::{ ValTrait, }; +use super::type_error_builtin::ToTypeError; + pub struct RangeErrorBuiltin {} pub static RANGE_ERROR_BUILTIN: RangeErrorBuiltin = RangeErrorBuiltin {}; @@ -36,9 +37,7 @@ impl ValTrait for RangeErrorBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new( - "function RangeError() { [native code] }".to_string(), - )) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -74,7 +73,7 @@ impl ValTrait for RangeErrorBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of RangeError builtin") + Err("Cannot assign to subscript of RangeError builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -91,32 +90,33 @@ impl ValTrait for RangeErrorBuiltin { } pub fn to_range_error(_: ThisWrapper, params: Vec) -> Result { - Ok(Val::Object(Rc::new(VsObject { - string_map: BTreeMap::from([( - "message".to_string(), - Val::String(Rc::new(match params.get(0) { - Some(param) => param.val_to_string(), - None => "".to_string(), - })), - )]), - symbol_map: Default::default(), - prototype: Some(make_range_error_prototype()), - }))) + Ok( + VsObject { + string_map: BTreeMap::from([( + "message".to_string(), + match params.get(0) { + Some(param) => param.to_val_string(), + None => "".to_val(), + }, + )]), + symbol_map: Default::default(), + prototype: Some(make_range_error_prototype()), + } + .to_val(), + ) } // TODO: Static? (Rc -> Arc?) fn make_range_error_prototype() -> Val { - Val::Object(Rc::new(VsObject { + VsObject { string_map: BTreeMap::from([ - ( - "name".to_string(), - Val::String(Rc::new("RangeError".to_string())), - ), + ("name".to_string(), "RangeError".to_val()), ("toString".to_string(), Val::Static(&RANGE_ERROR_TO_STRING)), ]), symbol_map: Default::default(), prototype: None, - })) + } + .to_val() } static SET_MESSAGE: NativeFunction = NativeFunction { @@ -126,11 +126,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction { None => "".to_string(), }; - op_submov( - this.get_mut()?, - format_val!("message"), - format_val!("{}", message), - )?; + op_submov(this.get_mut()?, "message".to_val(), message.to_val())?; Ok(Val::Undefined) }, @@ -138,8 +134,8 @@ static SET_MESSAGE: NativeFunction = NativeFunction { static RANGE_ERROR_TO_STRING: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { - let message = op_sub(this.get().clone(), format_val!("message"))?; - Ok(format_val!("RangeError({})", message)) + let message = op_sub(this.get().clone(), "message".to_val())?; + Ok(format!("RangeError({})", message).to_val()) }, }; @@ -149,7 +145,7 @@ macro_rules! range_error { let formatted_string = format!($fmt $(, $($arg),*)?); Err(to_range_error( ThisWrapper::new(true, &mut Val::Undefined), - vec![Val::String(Rc::new(formatted_string))], + vec![formatted_string.to_val()], ).unwrap()) }}; } diff --git a/valuescript_vm/src/builtins/string_builtin.rs b/valuescript_vm/src/builtins/string_builtin.rs index 54aa18d..0069ee4 100644 --- a/valuescript_vm/src/builtins/string_builtin.rs +++ b/valuescript_vm/src/builtins/string_builtin.rs @@ -3,8 +3,8 @@ use std::rc::Rc; use num_bigint::BigInt; use crate::native_function::ThisWrapper; +use crate::vs_value::{ToVal, ToValString}; use crate::{builtins::range_error_builtin::to_range_error, range_error}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; use crate::{ native_function::NativeFunction, vs_array::VsArray, @@ -14,6 +14,8 @@ use crate::{ ValTrait, }; +use super::type_error_builtin::ToTypeError; + pub struct StringBuiltin {} pub static STRING_BUILTIN: StringBuiltin = StringBuiltin {}; @@ -35,7 +37,7 @@ impl ValTrait for StringBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new("function String() { [native code] }".to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -76,7 +78,7 @@ impl ValTrait for StringBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of String builtin") + Err("Cannot assign to subscript of String builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -107,14 +109,14 @@ static FROM_CODE_POINT: NativeFunction = NativeFunction { result.push(char); } - Ok(Val::String(Rc::new(result))) + Ok(result.to_val()) }, }; fn to_string(_: ThisWrapper, params: Vec) -> Result { Ok(if let Some(value) = params.get(0) { - Val::String(Rc::new(value.val_to_string())) + value.to_val_string() } else { - Val::String(Rc::new("".to_string())) + "".to_val() }) } diff --git a/valuescript_vm/src/builtins/symbol_builtin.rs b/valuescript_vm/src/builtins/symbol_builtin.rs index 67df85d..f7ebf62 100644 --- a/valuescript_vm/src/builtins/symbol_builtin.rs +++ b/valuescript_vm/src/builtins/symbol_builtin.rs @@ -3,17 +3,16 @@ use std::rc::Rc; use num_bigint::BigInt; use crate::{ - builtins::type_error_builtin::to_type_error, - native_function::ThisWrapper, - type_error, vs_array::VsArray, vs_class::VsClass, vs_object::VsObject, vs_symbol::VsSymbol, - vs_value::{LoadFunctionResult, Val, VsType}, + vs_value::{LoadFunctionResult, ToValString, Val, VsType}, ValTrait, }; +use super::type_error_builtin::ToTypeError; + pub struct SymbolBuiltin {} pub static SYMBOL_BUILTIN: SymbolBuiltin = SymbolBuiltin {}; @@ -35,7 +34,7 @@ impl ValTrait for SymbolBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new("[object Symbol]".to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -71,7 +70,7 @@ impl ValTrait for SymbolBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Symbol builtin") + Err("Cannot assign to subscript of Symbol builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { diff --git a/valuescript_vm/src/builtins/type_error_builtin.rs b/valuescript_vm/src/builtins/type_error_builtin.rs index 25abec3..c97ebce 100644 --- a/valuescript_vm/src/builtins/type_error_builtin.rs +++ b/valuescript_vm/src/builtins/type_error_builtin.rs @@ -3,9 +3,8 @@ use std::{collections::BTreeMap, rc::Rc}; use num_bigint::BigInt; use crate::native_function::ThisWrapper; -use crate::type_error; +use crate::vs_value::{ToVal, ToValString}; use crate::{ - format_val, native_function::NativeFunction, operations::{op_sub, op_submov}, vs_array::VsArray, @@ -36,9 +35,7 @@ impl ValTrait for TypeErrorBuiltin { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new( - "function TypeError() { [native code] }".to_string(), - )) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -66,7 +63,15 @@ impl ValTrait for TypeErrorBuiltin { } fn load_function(&self) -> LoadFunctionResult { - LoadFunctionResult::NativeFunction(to_type_error) + LoadFunctionResult::NativeFunction(|_: ThisWrapper, params: Vec| -> Result { + Ok( + match params.get(0) { + Some(param) => param.to_val_string(), + None => "".to_val(), + } + .to_type_error(), + ) + }) } fn sub(&self, _key: Val) -> Result { @@ -74,7 +79,7 @@ impl ValTrait for TypeErrorBuiltin { } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of TypeError builtin") + Err("Cannot assign to subscript of TypeError builtin".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -90,33 +95,17 @@ impl ValTrait for TypeErrorBuiltin { } } -pub fn to_type_error(_: ThisWrapper, params: Vec) -> Result { - Ok(Val::Object(Rc::new(VsObject { - string_map: BTreeMap::from([( - "message".to_string(), - Val::String(Rc::new(match params.get(0) { - Some(param) => param.val_to_string(), - None => "".to_string(), - })), - )]), - symbol_map: Default::default(), - prototype: Some(make_type_error_prototype()), - }))) -} - // TODO: Static? (Rc -> Arc?) fn make_type_error_prototype() -> Val { - Val::Object(Rc::new(VsObject { + VsObject { string_map: BTreeMap::from([ - ( - "name".to_string(), - Val::String(Rc::new("TypeError".to_string())), - ), - ("toString".to_string(), Val::Static(&TYPE_ERROR_TO_STRING)), + ("name".to_string(), "TypeError".to_val()), + ("toString".to_string(), TYPE_ERROR_TO_STRING.to_val()), ]), symbol_map: Default::default(), prototype: None, - })) + } + .to_val() } static SET_MESSAGE: NativeFunction = NativeFunction { @@ -126,11 +115,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction { None => "".to_string(), }; - op_submov( - this.get_mut()?, - format_val!("message"), - format_val!("{}", message), - )?; + op_submov(this.get_mut()?, "message".to_val(), message.to_val())?; Ok(Val::Undefined) }, @@ -138,18 +123,34 @@ static SET_MESSAGE: NativeFunction = NativeFunction { static TYPE_ERROR_TO_STRING: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { - let message = op_sub(this.get().clone(), format_val!("message"))?; - Ok(format_val!("TypeError({})", message)) + let message = op_sub(this.get().clone(), "message".to_val())?; + Ok(format!("TypeError({})", message).to_val()) }, }; -#[macro_export] -macro_rules! type_error { - ($fmt:expr $(, $($arg:expr),*)?) => {{ - let formatted_string = format!($fmt $(, $($arg),*)?); - Err(to_type_error( - ThisWrapper::new(true, &mut Val::Undefined), - vec![Val::String(Rc::new(formatted_string))], - ).unwrap()) - }}; +pub trait ToTypeError { + fn to_type_error(self) -> Val; +} + +impl ToTypeError for &str { + fn to_type_error(self) -> Val { + self.to_string().to_type_error() + } +} + +impl ToTypeError for String { + fn to_type_error(self) -> Val { + self.to_val().to_type_error() + } +} + +impl ToTypeError for Val { + fn to_type_error(self) -> Val { + VsObject { + string_map: BTreeMap::from([("message".to_string(), self)]), + symbol_map: Default::default(), + prototype: Some(make_type_error_prototype()), + } + .to_val() + } } diff --git a/valuescript_vm/src/bytecode_decoder.rs b/valuescript_vm/src/bytecode_decoder.rs index 9c763c7..2b766da 100644 --- a/valuescript_vm/src/bytecode_decoder.rs +++ b/valuescript_vm/src/bytecode_decoder.rs @@ -6,12 +6,12 @@ use num_bigint::Sign; use valuescript_common::InstructionByte; use crate::builtins::BUILTIN_VALS; -use crate::vs_array::VsArray; use crate::vs_class::VsClass; use crate::vs_function::VsFunction; use crate::vs_object::VsObject; use crate::vs_pointer::VsPointer; use crate::vs_symbol::VsSymbol; +use crate::vs_value::ToVal; use crate::vs_value::Val; use crate::vs_value::ValTrait; @@ -100,9 +100,9 @@ impl BytecodeDecoder { BytecodeType::Null => Val::Null, BytecodeType::False => Val::Bool(false), BytecodeType::True => Val::Bool(true), - BytecodeType::SignedByte => Val::Number(self.decode_signed_byte() as f64), - BytecodeType::Number => Val::Number(self.decode_number()), - BytecodeType::String => Val::String(Rc::new(self.decode_string())), + BytecodeType::SignedByte => (self.decode_signed_byte() as f64).to_val(), + BytecodeType::Number => self.decode_number().to_val(), + BytecodeType::String => self.decode_string().to_val(), BytecodeType::Array => { let mut vals: Vec = Vec::new(); @@ -112,7 +112,7 @@ impl BytecodeDecoder { self.decode_type(); // End (TODO: assert) - Val::Array(Rc::new(VsArray::from(vals))) + vals.to_val() } BytecodeType::Object => { let mut string_map: BTreeMap = BTreeMap::new(); @@ -131,11 +131,12 @@ impl BytecodeDecoder { self.decode_type(); // End (TODO: assert) - Val::Object(Rc::new(VsObject { + VsObject { string_map, symbol_map, prototype: None, - })) + } + .to_val() } BytecodeType::Function => self.decode_function_header(), BytecodeType::Pointer => self.decode_pointer(), @@ -144,11 +145,12 @@ impl BytecodeDecoder { val => val, }, BytecodeType::Builtin => Val::Static(BUILTIN_VALS[self.decode_varsize_uint()]), - BytecodeType::Class => Val::Class(Rc::new(VsClass { + BytecodeType::Class => VsClass { constructor: self.decode_val(registers), instance_prototype: self.decode_val(registers), - })), - BytecodeType::BigInt => Val::BigInt(self.decode_bigint()), + } + .to_val(), + BytecodeType::BigInt => self.decode_bigint().to_val(), BytecodeType::Unrecognized => panic!("Unrecognized bytecode type at {}", self.pos - 1), }; } @@ -249,7 +251,7 @@ impl BytecodeDecoder { } } - return VsPointer::new(&self.data, pos); + VsPointer::new(&self.data, pos).to_val() } pub fn decode_function_header(&mut self) -> Val { @@ -257,13 +259,14 @@ impl BytecodeDecoder { let register_count = self.decode_byte() as usize; let parameter_count = self.decode_byte() as usize; - return Val::Function(Rc::new(VsFunction { + return VsFunction { bytecode: self.data.clone(), - register_count: register_count, - parameter_count: parameter_count, + register_count, + parameter_count, start: self.pos, binds: Vec::new(), - })); + } + .to_val(); } pub fn decode_instruction(&mut self) -> InstructionByte { diff --git a/valuescript_vm/src/bytecode_stack_frame.rs b/valuescript_vm/src/bytecode_stack_frame.rs index af3d98e..81df4e2 100644 --- a/valuescript_vm/src/bytecode_stack_frame.rs +++ b/valuescript_vm/src/bytecode_stack_frame.rs @@ -1,8 +1,6 @@ -use std::rc::Rc; - use valuescript_common::InstructionByte; -use crate::builtins::type_error_builtin::to_type_error; +use crate::builtins::type_error_builtin::ToTypeError; use crate::bytecode_decoder::BytecodeDecoder; use crate::bytecode_decoder::BytecodeType; use crate::native_function::ThisWrapper; @@ -10,8 +8,8 @@ use crate::operations; use crate::stack_frame::FrameStepOk; use crate::stack_frame::FrameStepResult; use crate::stack_frame::{CallResult, StackFrame, StackFrameTrait}; -use crate::type_error; use crate::vs_object::VsObject; +use crate::vs_value::ToVal; use crate::vs_value::{LoadFunctionResult, Val, ValTrait}; pub struct BytecodeStackFrame { @@ -371,15 +369,16 @@ impl StackFrameTrait for BytecodeStackFrame { let class = match self.decoder.decode_val(&self.registers).as_class_data() { Some(class) => class, None => { - return type_error!("value is not a constructor"); + return Err("value is not a constructor".to_type_error()); } }; - let mut instance = Val::Object(Rc::new(VsObject { + let mut instance = VsObject { string_map: Default::default(), symbol_map: Default::default(), prototype: Some(class.instance_prototype.clone()), - })); + } + .to_val(); match class.constructor { Val::Void => { @@ -456,7 +455,7 @@ impl StackFrameTrait for BytecodeStackFrame { RequireMutableThis => { if self.const_this { - return type_error!("Cannot mutate this because it is const"); + return Err("Cannot mutate this because it is const".to_type_error()); } } }; diff --git a/valuescript_vm/src/lib.rs b/valuescript_vm/src/lib.rs index e7ee94f..8f8f1a6 100644 --- a/valuescript_vm/src/lib.rs +++ b/valuescript_vm/src/lib.rs @@ -5,7 +5,6 @@ mod bytecode_decoder; mod bytecode_stack_frame; mod first_stack_frame; mod helpers; -mod macros; mod native_frame_function; mod native_function; mod number_methods; diff --git a/valuescript_vm/src/macros.rs b/valuescript_vm/src/macros.rs deleted file mode 100644 index e7be48c..0000000 --- a/valuescript_vm/src/macros.rs +++ /dev/null @@ -1,17 +0,0 @@ -#[macro_export] -macro_rules! format_err { - ($fmt:expr $(, $($arg:expr),*)?) => {{ - let formatted_string = format!($fmt $(, $($arg),*)?); - - // TODO: This should be a proper error type - Err(Val::String(Rc::new(formatted_string))) - }}; -} - -#[macro_export] -macro_rules! format_val { - ($fmt:expr $(, $($arg:expr),*)?) => {{ - let formatted_string = format!($fmt $(, $($arg),*)?); - Val::String(Rc::new(formatted_string)) - }}; -} diff --git a/valuescript_vm/src/native_frame_function.rs b/valuescript_vm/src/native_frame_function.rs index 3d01458..d136399 100644 --- a/valuescript_vm/src/native_frame_function.rs +++ b/valuescript_vm/src/native_frame_function.rs @@ -2,14 +2,13 @@ use std::rc::Rc; use num_bigint::BigInt; -use crate::format_err; -use crate::native_function::ThisWrapper; +use crate::builtins::error_builtin::ToError; +use crate::builtins::type_error_builtin::ToTypeError; use crate::stack_frame::StackFrame; use crate::vs_array::VsArray; use crate::vs_class::VsClass; use crate::vs_object::VsObject; -use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{LoadFunctionResult, ToValString, Val, ValTrait, VsType}; pub struct NativeFrameFunction { pub make_frame: fn() -> StackFrame, @@ -32,7 +31,7 @@ impl ValTrait for NativeFrameFunction { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new(self.val_to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -63,11 +62,11 @@ impl ValTrait for NativeFrameFunction { } fn sub(&self, _key: Val) -> Result { - format_err!("TODO: Subscript native function") + Err("TODO: Subscript native function".to_error()) } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of native function") + Err("Cannot assign to subscript of native function".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { diff --git a/valuescript_vm/src/native_function.rs b/valuescript_vm/src/native_function.rs index 5385933..bda2cc0 100644 --- a/valuescript_vm/src/native_function.rs +++ b/valuescript_vm/src/native_function.rs @@ -2,12 +2,12 @@ use std::rc::Rc; use num_bigint::BigInt; -use crate::format_err; +use crate::builtins::error_builtin::ToError; +use crate::builtins::type_error_builtin::ToTypeError; use crate::vs_array::VsArray; use crate::vs_class::VsClass; use crate::vs_object::VsObject; -use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{LoadFunctionResult, ToVal, ToValString, Val, ValTrait, VsType}; pub struct ThisWrapper<'a> { const_: bool, @@ -25,7 +25,7 @@ impl<'a> ThisWrapper<'a> { pub fn get_mut(&mut self) -> Result<&mut Val, Val> { if self.const_ { - return type_error!("Cannot mutate this because it is const"); + return Err("Cannot mutate this because it is const".to_type_error()); } Ok(self.this) @@ -53,7 +53,7 @@ impl ValTrait for NativeFunction { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new(self.val_to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -84,11 +84,11 @@ impl ValTrait for NativeFunction { } fn sub(&self, _key: Val) -> Result { - format_err!("TODO: Subscript native function") + Err("TODO: Subscript native function".to_error()) } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of native function") + Err("Cannot assign to subscript of native function".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -103,3 +103,9 @@ impl ValTrait for NativeFunction { "function() { [native code] }".into() } } + +impl ToVal for &'static NativeFunction { + fn to_val(self) -> Val { + Val::Static(self) + } +} diff --git a/valuescript_vm/src/number_methods.rs b/valuescript_vm/src/number_methods.rs index eb80528..b173422 100644 --- a/valuescript_vm/src/number_methods.rs +++ b/valuescript_vm/src/number_methods.rs @@ -1,9 +1,8 @@ -use std::rc::Rc; - +use crate::builtins::error_builtin::ToError; use crate::native_function::ThisWrapper; +use crate::vs_value::{ToVal, ToValString}; use crate::{builtins::range_error_builtin::to_range_error, range_error}; use crate::{ - format_err, format_val, native_function::NativeFunction, todo_fn::TODO, vs_value::{Val, ValTrait}, @@ -26,16 +25,19 @@ static TO_FIXED: NativeFunction = NativeFunction { Ok(match this.get() { Val::Number(number) => { if number.is_infinite() { - return Ok(if number.is_sign_positive() { - Val::String(Rc::new("Infinity".to_string())) - } else { - Val::String(Rc::new("-Infinity".to_string())) - }); + return Ok( + if number.is_sign_positive() { + "Infinity" + } else { + "-Infinity" + } + .to_val(), + ); } let mut precision = match params.get(0) { Some(p) => p.to_number(), - _ => return Ok(Val::String(Rc::new(this.get().val_to_string()))), + _ => return Ok(this.get().to_val_string()), }; precision = f64::floor(precision); @@ -44,9 +46,9 @@ static TO_FIXED: NativeFunction = NativeFunction { return range_error!("precision must be between 1 and 100"); } - format_val!("{:.*}", precision as usize, number) + format!("{:.*}", precision as usize, number).to_val() } - _ => return format_err!("TODO: number indirection"), + _ => return Err(format!("TODO: number indirection").to_val()), }) }, }; @@ -67,7 +69,7 @@ static TO_EXPONENTIAL: NativeFunction = NativeFunction { } None => format_exponential(*number, None), }, - _ => return format_err!("number indirection"), + _ => return Err("number indirection".to_error()), }) }, }; @@ -75,8 +77,8 @@ static TO_EXPONENTIAL: NativeFunction = NativeFunction { static TODO_LOCALE: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { match this.get() { - Val::Number(_number) => return format_err!("TODO: locale"), - _ => return format_err!("number indirection"), + Val::Number(_number) => return Err("TODO: locale".to_error()), + _ => return Err("number indirection".to_error()), } }, }; @@ -86,12 +88,12 @@ static TO_STRING: NativeFunction = NativeFunction { Ok(match this.get() { Val::Number(_) => match params.get(0) { Some(_) => { - return format_err!("TODO: toString with radix"); + return Err("TODO: toString with radix".to_error()); } - None => Val::String(Rc::new(this.get().val_to_string())), + None => this.get().to_val_string(), }, - _ => return format_err!("number indirection"), + _ => return Err("number indirection".to_error()), }) }, }; @@ -100,7 +102,7 @@ static VALUE_OF: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { Val::Number(number) => Val::Number(*number), - _ => return format_err!("number indirection"), + _ => return Err("number indirection".to_error()), }) }, }; @@ -108,10 +110,11 @@ static VALUE_OF: NativeFunction = NativeFunction { fn format_exponential(number: f64, precision: Option) -> Val { if number.is_infinite() { return if number.is_sign_positive() { - Val::String(Rc::new("Infinity".to_string())) + "Infinity" } else { - Val::String(Rc::new("-Infinity".to_string())) - }; + "-Infinity" + } + .to_val(); } let exp_format = match precision { @@ -125,7 +128,7 @@ fn format_exponential(number: f64, precision: Option) -> Val { let exponent = match parts.next() { Some(e) => e, - None => return Val::String(Rc::new(exp_format)), + None => return exp_format.to_val(), }; let string = if exponent.starts_with('-') { @@ -134,5 +137,5 @@ fn format_exponential(number: f64, precision: Option) -> Val { format!("{}e+{}", mantissa, exponent) }; - Val::String(Rc::new(string)) + string.to_val() } diff --git a/valuescript_vm/src/operations.rs b/valuescript_vm/src/operations.rs index ab8a4a5..658899f 100644 --- a/valuescript_vm/src/operations.rs +++ b/valuescript_vm/src/operations.rs @@ -4,17 +4,17 @@ use num_bigint::Sign; use num_traits::ToPrimitive; use crate::bigint_methods::op_sub_bigint; -use crate::format_err; -use crate::format_val; +use crate::builtins::error_builtin::ToError; +use crate::builtins::type_error_builtin::ToTypeError; use crate::native_function::NativeFunction; use crate::native_function::ThisWrapper; use crate::number_methods::op_sub_number; use crate::string_methods::op_sub_string; +use crate::vs_value::ToVal; use crate::vs_value::Val; use crate::vs_value::ValTrait; use crate::vs_value::VsType; use crate::{builtins::range_error_builtin::to_range_error, range_error}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; pub fn op_plus(left: Val, right: Val) -> Result { let left_prim = left.to_primitive(); @@ -24,21 +24,19 @@ pub fn op_plus(left: Val, right: Val) -> Result { let right_type = right_prim.typeof_(); if left_type == VsType::String || right_type == VsType::String { - return Ok(Val::String(Rc::new( - left_prim.val_to_string() + &right_prim.val_to_string(), - ))); + return Ok((left_prim.val_to_string() + &right_prim.val_to_string()).to_val()); } if left_type == VsType::BigInt || right_type == VsType::BigInt { if left_type != right_type { - return type_error!("Cannot mix BigInt and other types"); + return Err("Cannot mix BigInt and other types".to_type_error()); } match (left_prim.as_bigint_data(), right_prim.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => { return Ok(Val::BigInt(left_bigint + right_bigint)); } - _ => return format_err!("TODO"), + _ => return Err("TODO".to_error()), } } @@ -55,7 +53,9 @@ pub fn op_unary_plus(input: Val) -> Val { pub fn op_minus(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint - right_bigint)), - (Some(_), None) | (None, Some(_)) => return type_error!("Cannot mix BigInt with other types"), + (Some(_), None) | (None, Some(_)) => { + return Err("Cannot mix BigInt with other types".to_type_error()) + } _ => Ok(Val::Number(left.to_number() - right.to_number())), } } @@ -70,9 +70,7 @@ pub fn op_unary_minus(input: Val) -> Val { pub fn op_mul(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint * right_bigint)), - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => Ok(Val::Number(left.to_number() * right.to_number())), } } @@ -80,9 +78,7 @@ pub fn op_mul(left: Val, right: Val) -> Result { pub fn op_div(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint / right_bigint)), - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => Ok(Val::Number(left.to_number() / right.to_number())), } } @@ -90,9 +86,7 @@ pub fn op_div(left: Val, right: Val) -> Result { pub fn op_mod(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint % right_bigint)), - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => Ok(Val::Number(left.to_number() % right.to_number())), } } @@ -111,9 +105,7 @@ pub fn op_exp(left: Val, right: Val) -> Result { Ok(Val::BigInt(left_bigint.pow(exp))) } - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => Ok(Val::Number(left.to_number().powf(right.to_number()))), } } @@ -126,7 +118,7 @@ pub fn op_eq(left: Val, right: Val) -> Result { (Val::Number(left_number), Val::Number(right_number)) => left_number == right_number, (Val::String(left_string), Val::String(right_string)) => left_string == right_string, (Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint == right_bigint, - _ => return format_err!("TODO"), + _ => return Err("TODO".to_error()), })) } @@ -138,7 +130,7 @@ pub fn op_ne(left: Val, right: Val) -> Result { (Val::Number(left_number), Val::Number(right_number)) => left_number != right_number, (Val::String(left_string), Val::String(right_string)) => left_string != right_string, (Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint != right_bigint, - _ => return format_err!("TODO"), + _ => return Err("TODO".to_error()), })) } @@ -154,7 +146,7 @@ pub fn op_triple_eq_impl(left: Val, right: Val) -> Result { if left.typeof_() != right.typeof_() { false } else { - return format_err!("TODO"); + return Err("TODO".to_error()); } } }) @@ -194,7 +186,7 @@ pub fn op_less(left: Val, right: Val) -> Result { if left.typeof_() == VsType::Undefined || right.typeof_() == VsType::Undefined { false } else { - return format_err!("TODO"); + return Err("TODO".to_error()); } } })) @@ -208,7 +200,7 @@ pub fn op_less_eq(left: Val, right: Val) -> Result { (Val::Number(left_number), Val::Number(right_number)) => left_number <= right_number, (Val::String(left_string), Val::String(right_string)) => left_string <= right_string, (Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint <= right_bigint, - _ => return format_err!("TODO"), + _ => return Err("TODO".to_type_error()), })) } @@ -220,7 +212,7 @@ pub fn op_greater(left: Val, right: Val) -> Result { (Val::Number(left_number), Val::Number(right_number)) => left_number > right_number, (Val::String(left_string), Val::String(right_string)) => left_string > right_string, (Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint > right_bigint, - _ => return format_err!("TODO"), + _ => return Err("TODO".to_error()), })) } @@ -232,7 +224,7 @@ pub fn op_greater_eq(left: Val, right: Val) -> Result { (Val::Number(left_number), Val::Number(right_number)) => left_number >= right_number, (Val::String(left_string), Val::String(right_string)) => left_string >= right_string, (Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint >= right_bigint, - _ => return format_err!("TODO"), + _ => return Err("TODO".to_type_error()), })) } @@ -271,9 +263,7 @@ pub fn to_u32(x: f64) -> u32 { pub fn op_bit_and(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint & right_bigint)), - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => { let res_i32 = to_i32(left.to_number()) & to_i32(right.to_number()); Ok(Val::Number(res_i32 as f64)) @@ -284,9 +274,7 @@ pub fn op_bit_and(left: Val, right: Val) -> Result { pub fn op_bit_or(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint | right_bigint)), - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => { let res_i32 = to_i32(left.to_number()) | to_i32(right.to_number()); Ok(Val::Number(res_i32 as f64)) @@ -307,9 +295,7 @@ pub fn op_bit_not(input: Val) -> Val { pub fn op_bit_xor(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint ^ right_bigint)), - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => { let res_i32 = to_i32(left.to_number()) ^ to_i32(right.to_number()); Ok(Val::Number(res_i32 as f64)) @@ -322,9 +308,7 @@ pub fn op_left_shift(left: Val, right: Val) -> Result { (Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt( left_bigint << right_bigint.to_i64().expect("TODO"), )), - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => { let res_i32 = to_i32(left.to_number()) << (to_u32(right.to_number()) & 0x1f); Ok(Val::Number(res_i32 as f64)) @@ -335,12 +319,10 @@ pub fn op_left_shift(left: Val, right: Val) -> Result { pub fn op_right_shift(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { (Some(left_bigint), Some(right_bigint)) => { - let right_i64 = right_bigint.to_i64().ok_or(format_val!("TODO"))?; + let right_i64 = right_bigint.to_i64().ok_or("TODO".to_val())?; Ok(Val::BigInt(left_bigint >> right_i64)) } - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => { let res_i32 = to_i32(left.to_number()) >> (to_u32(right.to_number()) & 0x1f); Ok(Val::Number(res_i32 as f64)) @@ -350,12 +332,8 @@ pub fn op_right_shift(left: Val, right: Val) -> Result { pub fn op_right_shift_unsigned(left: Val, right: Val) -> Result { match (left.as_bigint_data(), right.as_bigint_data()) { - (Some(_), Some(_)) => { - type_error!("BigInts don't support unsigned right shift") - } - (Some(_), None) | (None, Some(_)) => { - type_error!("Cannot mix BigInt with other types") - } + (Some(_), Some(_)) => Err("BigInts don't support unsigned right shift".to_type_error()), + (Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()), _ => { let res_u32 = to_u32(left.to_number()) >> (to_u32(right.to_number()) & 0x1f); Ok(Val::Number(res_u32 as f64)) @@ -366,34 +344,35 @@ pub fn op_right_shift_unsigned(left: Val, right: Val) -> Result { pub fn op_typeof(input: Val) -> Val { use VsType::*; - return Val::String(Rc::new(match input.typeof_() { - Undefined => "undefined".to_string(), - Null => "object".to_string(), - Bool => "boolean".to_string(), - Number => "number".to_string(), - BigInt => "bigint".to_string(), - Symbol => "symbol".to_string(), - String => "string".to_string(), - Array => "object".to_string(), - Object => "object".to_string(), - Function => "function".to_string(), - Class => "function".to_string(), - })); + match input.typeof_() { + Undefined => "undefined", + Null => "object", + Bool => "boolean", + Number => "number", + BigInt => "bigint", + Symbol => "symbol", + String => "string", + Array => "object", + Object => "object", + Function => "function", + Class => "function", + } + .to_val() } pub fn op_instance_of(_left: Val, _right: Val) -> Result { - format_err!("TODO: op_instance_of") + Err("TODO: op_instance_of".to_error()) } pub fn op_in(_left: Val, _right: Val) -> Result { - format_err!("TODO: op_in") + Err("TODO: op_in".to_error()) } pub fn op_sub(left: Val, right: Val) -> Result { return match left { - Val::Void => format_err!("Internal: Shouldn't happen"), // TODO: Internal errors - Val::Undefined => type_error!("Cannot subscript undefined"), - Val::Null => type_error!("Cannot subscript null"), + Val::Void => Err("Internal: Shouldn't happen".to_error()), // TODO: Internal errors + Val::Undefined => Err("Cannot subscript undefined".to_type_error()), + Val::Null => Err("Cannot subscript null".to_type_error()), Val::Bool(_) => Ok(match right.val_to_string().as_str() { "toString" => Val::Static(&BOOL_TO_STRING), "valueOf" => Val::Static(&BOOL_VALUE_OF), @@ -437,18 +416,18 @@ pub fn op_sub(left: Val, right: Val) -> Result { pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val> { match target { - Val::Void => format_err!("Internal: Shouldn't happen"), // TODO: Internal errors - Val::Undefined => type_error!("Cannot assign to subscript of undefined"), - Val::Null => type_error!("Cannot assign to subscript of null"), - Val::Bool(_) => type_error!("Cannot assign to subscript of bool"), - Val::Number(_) => type_error!("Cannot assign to subscript of number"), - Val::BigInt(_) => type_error!("Cannot assign to subscript of bigint"), - Val::Symbol(_) => type_error!("Cannot assign to subscript of symbol"), - Val::String(_) => type_error!("Cannot assign to subscript of string"), + Val::Void => Err("Internal: Shouldn't happen".to_error()), // TODO: Internal errors + Val::Undefined => Err("Cannot assign to subscript of undefined".to_type_error()), + Val::Null => Err("Cannot assign to subscript of null".to_type_error()), + Val::Bool(_) => Err("Cannot assign to subscript of bool".to_type_error()), + Val::Number(_) => Err("Cannot assign to subscript of number".to_type_error()), + Val::BigInt(_) => Err("Cannot assign to subscript of bigint".to_type_error()), + Val::Symbol(_) => Err("Cannot assign to subscript of symbol".to_type_error()), + Val::String(_) => Err("Cannot assign to subscript of string".to_type_error()), Val::Array(array_data) => { let subscript_index = match subscript.to_index() { // TODO: Internal errors - None => return format_err!("TODO: non-uint array subscript assignment"), + None => return Err("TODO: non-uint array subscript assignment".to_type_error()), Some(i) => i, }; @@ -458,7 +437,7 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val array_data_mut.elements[subscript_index] = value; } else { if subscript_index - array_data_mut.elements.len() > 100 { - return format_err!("TODO: Sparse arrays"); + return Err("TODO: Sparse arrays".to_type_error()); } while subscript_index > array_data_mut.elements.len() { @@ -483,18 +462,18 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val Ok(()) } - Val::Function(_) => format_err!("TODO: function subscript assignment"), - Val::Class(_) => format_err!("Cannot assign to subscript of class"), - Val::Static(_) => format_err!("Cannot assign to subscript of static value"), - Val::Custom(_) => format_err!("TODO: Assign to subscript of custom value"), + Val::Function(_) => Err("TODO: function subscript assignment".to_type_error()), + Val::Class(_) => Err("Cannot assign to subscript of class".to_type_error()), + Val::Static(_) => Err("Cannot assign to subscript of static value".to_type_error()), + Val::Custom(_) => Err("TODO: Assign to subscript of custom value".to_type_error()), } } static BOOL_TO_STRING: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { - Val::Bool(b) => Val::String(Rc::new(b.to_string())), - _ => return format_err!("bool indirection"), + Val::Bool(b) => b.to_string().to_val(), + _ => return Err("bool indirection".to_type_error()), }) }, }; @@ -503,7 +482,7 @@ static BOOL_VALUE_OF: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { Val::Bool(b) => Val::Bool(*b), - _ => return format_err!("bool indirection"), + _ => return Err("bool indirection".to_type_error()), }) }, }; diff --git a/valuescript_vm/src/string_methods.rs b/valuescript_vm/src/string_methods.rs index a7d8475..b4ad5e0 100644 --- a/valuescript_vm/src/string_methods.rs +++ b/valuescript_vm/src/string_methods.rs @@ -1,11 +1,10 @@ use std::{rc::Rc, str::Chars}; use crate::{ - format_err, + builtins::error_builtin::ToError, helpers::{to_wrapping_index, to_wrapping_index_clamped}, native_function::{NativeFunction, ThisWrapper}, - vs_array::VsArray, - vs_value::Val, + vs_value::{ToVal, Val}, ValTrait, }; @@ -30,8 +29,8 @@ pub fn op_sub_string(string_data: &Rc, subscript: &Val) -> Val { } match unicode_at(string_bytes, string_bytes.len(), right_index) { - Some(char) => Val::String(Rc::new(char.to_string())), - None => Val::String(Rc::new(String::from(""))), + Some(char) => char.to_string().to_val(), + None => "".to_val(), } } @@ -96,11 +95,11 @@ static AT: NativeFunction = NativeFunction { }; match unicode_at(string_bytes, string_bytes.len(), index) { - Some(char) => Val::String(Rc::new(char.to_string())), - None => Val::String(Rc::new(String::from(""))), + Some(char) => char.to_string().to_val(), + None => "".to_val(), } } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -124,7 +123,7 @@ static CODE_POINT_AT: NativeFunction = NativeFunction { None => Val::Undefined, } } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -139,9 +138,9 @@ static CONCAT: NativeFunction = NativeFunction { result.push_str(param.val_to_string().as_str()); } - Val::String(Rc::new(result)) + result.to_val() } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -184,7 +183,7 @@ static ENDS_WITH: NativeFunction = NativeFunction { Val::Bool(true) } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -216,7 +215,7 @@ static INCLUDES: NativeFunction = NativeFunction { None => Val::Bool(false), } } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -248,7 +247,7 @@ static INDEX_OF: NativeFunction = NativeFunction { None => Val::Number(-1.0), } } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -280,7 +279,7 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction { None => Val::Number(-1.0), } } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -290,9 +289,9 @@ static TODO_LOCALE: NativeFunction = NativeFunction { // TODO: Ok(...) match this.get() { Val::String(_string_data) => { - return format_err!("TODO: locale"); + return Err("TODO: locale".to_error()); } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), } }, }; @@ -302,9 +301,9 @@ static TODO_REGEXES: NativeFunction = NativeFunction { // TODO: Ok(...) match this.get() { Val::String(_string_data) => { - return format_err!("TODO: regexes"); + return Err("TODO: regexes".to_error()); } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), } }, }; @@ -315,9 +314,9 @@ static NORMALIZE: NativeFunction = NativeFunction { match this.get() { Val::String(_string_data) => { // Consider https://docs.rs/unicode-normalization/latest/unicode_normalization/ - return format_err!("TODO: normalize"); + return Err("TODO: normalize".to_error()); } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), } }, }; @@ -369,9 +368,9 @@ static PAD_END: NativeFunction = NativeFunction { } } - Val::String(Rc::new(string)) + string.to_val() } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -425,9 +424,9 @@ static PAD_START: NativeFunction = NativeFunction { prefix.push_str(string_data); - Val::String(Rc::new(prefix)) + prefix.to_val() } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -450,9 +449,9 @@ static REPEAT: NativeFunction = NativeFunction { result.push_str(string_data); } - Val::String(Rc::new(result)) + result.to_val() } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -484,9 +483,9 @@ static SLICE: NativeFunction = NativeFunction { } } - Val::String(Rc::new(new_string)) + new_string.to_val() } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -512,19 +511,19 @@ static SPLIT: NativeFunction = NativeFunction { let mut result = Vec::::new(); if limit == 0 { - return Ok(Val::Array(Rc::new(VsArray::from(result)))); + return Ok(result.to_val()); } if separator.is_empty() { for c in string_data.chars() { - result.push(Val::String(Rc::new(c.to_string()))); + result.push(c.to_val()); if result.len() == limit { break; } } - return Ok(Val::Array(Rc::new(VsArray::from(result)))); + return Ok(result.to_val()); } let mut part = String::new(); @@ -534,7 +533,7 @@ static SPLIT: NativeFunction = NativeFunction { if match_chars(&mut str_chars, &separator) { let mut new_part = String::new(); std::mem::swap(&mut new_part, &mut part); - result.push(Val::String(Rc::new(new_part))); + result.push(new_part.to_val()); if result.len() == limit { break; @@ -543,16 +542,16 @@ static SPLIT: NativeFunction = NativeFunction { match str_chars.next() { Some(c) => part.push(c), None => { - result.push(Val::String(Rc::new(part))); + result.push(part.to_val()); break; } } } } - Val::Array(Rc::new(VsArray::from(result))) + result.to_val() } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -593,7 +592,7 @@ static STARTS_WITH: NativeFunction = NativeFunction { Val::Bool(true) } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -634,9 +633,9 @@ static SUBSTRING: NativeFunction = NativeFunction { } } - Val::String(Rc::new(new_string)) + new_string.to_val() } - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -644,11 +643,8 @@ static SUBSTRING: NativeFunction = NativeFunction { static TO_LOWER_CASE: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { - Val::String(string_data) => { - let lowercased_string = string_data.to_lowercase(); - Val::String(Rc::new(lowercased_string)) - } - _ => return format_err!("string indirection"), + Val::String(string_data) => string_data.to_lowercase().to_val(), + _ => return Err("string indirection".to_error()), }) }, }; @@ -657,7 +653,7 @@ static TO_STRING: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { Val::String(string_data) => Val::String(string_data.clone()), - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; @@ -665,11 +661,8 @@ static TO_STRING: NativeFunction = NativeFunction { static TO_UPPER_CASE: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { - Val::String(string_data) => { - let uppercased_string = string_data.to_uppercase(); - Val::String(Rc::new(uppercased_string)) - } - _ => return format_err!("string indirection"), + Val::String(string_data) => string_data.to_uppercase().to_val(), + _ => return Err("string indirection".to_error()), }) }, }; @@ -677,11 +670,8 @@ static TO_UPPER_CASE: NativeFunction = NativeFunction { static TRIM: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { - Val::String(string_data) => { - let trimmed_string = string_data.trim(); - Val::String(Rc::new(trimmed_string.to_owned())) - } - _ => return format_err!("string indirection"), + Val::String(string_data) => string_data.trim().to_val(), + _ => return Err("string indirection".to_error()), }) }, }; @@ -689,11 +679,8 @@ static TRIM: NativeFunction = NativeFunction { static TRIM_END: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { - Val::String(string_data) => { - let trimmed_string = string_data.trim_end(); - Val::String(Rc::new(trimmed_string.to_owned())) - } - _ => return format_err!("string indirection"), + Val::String(string_data) => string_data.trim_end().to_val(), + _ => return Err("string indirection".to_error()), }) }, }; @@ -701,11 +688,8 @@ static TRIM_END: NativeFunction = NativeFunction { static TRIM_START: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { - Val::String(string_data) => { - let trimmed_string = string_data.trim_start(); - Val::String(Rc::new(trimmed_string.to_owned())) - } - _ => return format_err!("string indirection"), + Val::String(string_data) => string_data.trim_start().to_val(), + _ => return Err("string indirection".to_error()), }) }, }; @@ -714,7 +698,7 @@ static VALUE_OF: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { Ok(match this.get() { Val::String(string_data) => Val::String(string_data.clone()), - _ => return format_err!("string indirection"), + _ => return Err("string indirection".to_error()), }) }, }; diff --git a/valuescript_vm/src/todo_fn.rs b/valuescript_vm/src/todo_fn.rs index 5b04ecc..8e56297 100644 --- a/valuescript_vm/src/todo_fn.rs +++ b/valuescript_vm/src/todo_fn.rs @@ -1,16 +1,9 @@ -use std::rc::Rc; - use crate::{ - format_err, + builtins::error_builtin::ToError, native_function::{NativeFunction, ThisWrapper}, vs_value::Val, }; pub static TODO: NativeFunction = NativeFunction { - fn_: |this: ThisWrapper, _params: Vec| -> Result { - match this.get() { - Val::Number(_number) => return format_err!("TODO: locale"), - _ => return format_err!("number indirection"), - } - }, + fn_: |_: ThisWrapper, _params: Vec| -> Result { Err("TODO".to_error()) }, }; diff --git a/valuescript_vm/src/virtual_machine.rs b/valuescript_vm/src/virtual_machine.rs index 22caced..9ce3382 100644 --- a/valuescript_vm/src/virtual_machine.rs +++ b/valuescript_vm/src/virtual_machine.rs @@ -1,10 +1,8 @@ use std::rc::Rc; -use crate::builtins::error_builtin::to_error; +use crate::builtins::error_builtin::ToError; use crate::bytecode_decoder::BytecodeDecoder; -use crate::error; use crate::first_stack_frame::FirstStackFrame; -use crate::native_function::ThisWrapper; use crate::stack_frame::FrameStepOk; use crate::stack_frame::StackFrame; use crate::vs_value::{LoadFunctionResult, Val, ValTrait}; @@ -52,7 +50,7 @@ impl VirtualMachine { } } - error!("step limit reached") + Err("step limit reached".to_error()) } None => { while self.stack.len() > 0 { diff --git a/valuescript_vm/src/vs_array.rs b/valuescript_vm/src/vs_array.rs index d233a79..b2afb3c 100644 --- a/valuescript_vm/src/vs_array.rs +++ b/valuescript_vm/src/vs_array.rs @@ -8,14 +8,15 @@ use crate::array_higher_functions::{ array_flat_map::FLAT_MAP, array_map::MAP, array_reduce::REDUCE, array_reduce_right::REDUCE_RIGHT, array_some::SOME, array_sort::SORT, }; -use crate::format_err; +use crate::builtins::error_builtin::ToError; +use crate::builtins::type_error_builtin::ToTypeError; use crate::helpers::{to_wrapping_index, to_wrapping_index_clamped}; use crate::native_function::{NativeFunction, ThisWrapper}; use crate::operations::op_triple_eq_impl; +use crate::todo_fn::TODO; use crate::vs_class::VsClass; use crate::vs_object::VsObject; -use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType}; -use crate::{builtins::type_error_builtin::to_type_error, type_error}; +use crate::vs_value::{LoadFunctionResult, ToVal, ToValString, Val, ValTrait, VsType}; #[derive(Clone, Debug)] pub struct VsArray { @@ -47,6 +48,12 @@ impl VsArray { } } +impl ToVal for VsArray { + fn to_val(self) -> Val { + Val::Array(Rc::new(self)) + } +} + pub struct ArrayPrototype {} static ARRAY_PROTOTYPE: ArrayPrototype = ArrayPrototype {}; @@ -68,7 +75,7 @@ impl ValTrait for ArrayPrototype { false } fn to_primitive(&self) -> Val { - Val::String(Rc::new("".to_string())) + self.to_val_string() } fn is_truthy(&self) -> bool { true @@ -116,7 +123,7 @@ impl ValTrait for ArrayPrototype { "includes" => &INCLUDES, "indexOf" => &INDEX_OF, "join" => &JOIN, - "keys" => &KEYS, + "keys" => &TODO, "lastIndexOf" => &LAST_INDEX_OF, "map" => &MAP, "pop" => &POP, @@ -129,16 +136,16 @@ impl ValTrait for ArrayPrototype { "some" => &SOME, "sort" => &SORT, "splice" => &SPLICE, - "toLocaleString" => &TO_LOCALE_STRING, + "toLocaleString" => &TODO, "toString" => &TO_STRING, "unshift" => &UNSHIFT, - "values" => &VALUES, + "values" => &TODO, _ => return Ok(Val::Undefined), })) } fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { - type_error!("Cannot assign to subscript of Array.prototype") + Err("Cannot assign to subscript of Array.prototype".to_type_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -161,7 +168,7 @@ static AT: NativeFunction = NativeFunction { None => Val::Undefined, Some(i) => array_data.elements[i].clone(), }, - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -185,9 +192,9 @@ static CONCAT: NativeFunction = NativeFunction { } } - Val::Array(Rc::new(new_array)) + new_array.to_val() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -202,7 +209,7 @@ static COPY_WITHIN: NativeFunction = NativeFunction { let ulen = array_data_mut.elements.len(); if ulen > isize::MAX as usize { - return format_err!("TODO: array len exceeds isize"); + return Err("TODO: array len exceeds isize".to_error()); } let mut target = match params.get(0) { @@ -261,7 +268,7 @@ static COPY_WITHIN: NativeFunction = NativeFunction { this.clone() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -269,8 +276,8 @@ static COPY_WITHIN: NativeFunction = NativeFunction { static ENTRIES: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { match this.get() { - Val::Array(_array_data) => return format_err!("TODO: iterators"), - _ => return format_err!("array indirection"), + Val::Array(_array_data) => return Err("TODO: iterators".to_error()), + _ => return Err("array indirection".to_error()), }; }, }; @@ -302,7 +309,7 @@ static FILL: NativeFunction = NativeFunction { this.clone() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -312,7 +319,7 @@ static FLAT: NativeFunction = NativeFunction { Ok(match this.get() { Val::Array(array_data) => { if params.len() > 0 { - return format_err!("TODO: .flat depth parameter"); + return Err("TODO: .flat depth parameter".to_error()); } let mut new_elems = Vec::::new(); @@ -330,9 +337,9 @@ static FLAT: NativeFunction = NativeFunction { } } - Val::Array(Rc::new(VsArray::from(new_elems))) + new_elems.to_val() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -355,7 +362,7 @@ static INCLUDES: NativeFunction = NativeFunction { Val::Bool(false) } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -378,7 +385,7 @@ static INDEX_OF: NativeFunction = NativeFunction { Val::Number(-1.0) } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -388,11 +395,11 @@ static JOIN: NativeFunction = NativeFunction { Ok(match this.get() { Val::Array(vals) => { if vals.elements.len() == 0 { - return Ok(Val::String(Rc::new("".to_string()))); + return Ok("".to_val()); } if vals.elements.len() == 1 { - return Ok(Val::String(Rc::new(vals.elements[0].val_to_string()))); + return Ok(vals.elements[0].to_val_string()); } let separator = params.get(0).unwrap_or(&Val::Undefined); @@ -416,25 +423,13 @@ static JOIN: NativeFunction = NativeFunction { }; } - Val::String(Rc::new(res)) + res.to_val() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; -static KEYS: NativeFunction = NativeFunction { - fn_: |this: ThisWrapper, _params: Vec| -> Result { - // TODO: Ok(...) - match this.get() { - Val::Array(_array_data) => { - return format_err!("TODO: KEYS"); - } - _ => return format_err!("array indirection"), - }; - }, -}; - static LAST_INDEX_OF: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, params: Vec| -> Result { Ok(match this.get() { @@ -453,7 +448,7 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction { Val::Number(-1_f64) } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -479,7 +474,7 @@ static POP: NativeFunction = NativeFunction { _ => removed_el, } } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -498,7 +493,7 @@ static PUSH: NativeFunction = NativeFunction { Val::Number(array_data_mut.elements.len() as f64) } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -527,7 +522,7 @@ static REVERSE: NativeFunction = NativeFunction { this.clone() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -546,7 +541,7 @@ static SHIFT: NativeFunction = NativeFunction { array_data_mut.elements.remove(0) } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -571,9 +566,9 @@ static SLICE: NativeFunction = NativeFunction { new_elems.push(array_data.elements[i as usize].clone()); } - Val::Array(Rc::new(VsArray::from(new_elems))) + new_elems.to_val() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; @@ -650,29 +645,17 @@ static SPLICE: NativeFunction = NativeFunction { } } - Val::Array(Rc::new(VsArray::from(deleted_elements))) + deleted_elements.to_val() } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; -static TO_LOCALE_STRING: NativeFunction = NativeFunction { - fn_: |this: ThisWrapper, _params: Vec| -> Result { - // TODO: Ok(...) - match this.get() { - Val::Array(_array_data) => { - return format_err!("TODO: TO_LOCALE_STRING"); - } - _ => return format_err!("array indirection"), - }; - }, -}; - // TODO: Share this? (JS doesn't?) static TO_STRING: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { - Ok(Val::String(Rc::new(this.get().val_to_string()))) + Ok(this.get().to_val_string()) }, }; @@ -693,19 +676,7 @@ static UNSHIFT: NativeFunction = NativeFunction { Val::Number(array_data_mut.elements.len() as f64) } - _ => return format_err!("array indirection"), + _ => return Err("array indirection".to_error()), }) }, }; - -static VALUES: NativeFunction = NativeFunction { - fn_: |this: ThisWrapper, _params: Vec| -> Result { - // TODO: Ok(...) - match this.get() { - Val::Array(_array_data) => { - return format_err!("TODO: VALUES"); - } - _ => return format_err!("array indirection"), - }; - }, -}; diff --git a/valuescript_vm/src/vs_class.rs b/valuescript_vm/src/vs_class.rs index 6d11e7f..9eceda6 100644 --- a/valuescript_vm/src/vs_class.rs +++ b/valuescript_vm/src/vs_class.rs @@ -1,3 +1,7 @@ +use std::rc::Rc; + +use crate::vs_value::ToVal; + use super::vs_value::Val; #[derive(Debug)] @@ -7,3 +11,9 @@ pub struct VsClass { } impl VsClass {} + +impl ToVal for VsClass { + fn to_val(self) -> Val { + Val::Class(Rc::new(self)) + } +} diff --git a/valuescript_vm/src/vs_function.rs b/valuescript_vm/src/vs_function.rs index e936035..c5f7e95 100644 --- a/valuescript_vm/src/vs_function.rs +++ b/valuescript_vm/src/vs_function.rs @@ -1,5 +1,7 @@ use std::rc::Rc; +use crate::vs_value::ToVal; + use super::bytecode_decoder::BytecodeDecoder; use super::bytecode_stack_frame::BytecodeStackFrame; use super::stack_frame::StackFrame; @@ -60,3 +62,9 @@ impl VsFunction { }); } } + +impl ToVal for VsFunction { + fn to_val(self) -> Val { + Val::Function(Rc::new(self)) + } +} diff --git a/valuescript_vm/src/vs_object.rs b/valuescript_vm/src/vs_object.rs index 45a5c96..87f0509 100644 --- a/valuescript_vm/src/vs_object.rs +++ b/valuescript_vm/src/vs_object.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; +use std::rc::Rc; use crate::vs_symbol::VsSymbol; +use crate::vs_value::ToVal; use super::operations::op_sub; use super::vs_value::{Val, ValTrait}; @@ -32,3 +34,9 @@ impl VsObject { } } } + +impl ToVal for VsObject { + fn to_val(self) -> Val { + Val::Object(Rc::new(self)) + } +} diff --git a/valuescript_vm/src/vs_pointer.rs b/valuescript_vm/src/vs_pointer.rs index 8c52d60..6ecf9b5 100644 --- a/valuescript_vm/src/vs_pointer.rs +++ b/valuescript_vm/src/vs_pointer.rs @@ -3,7 +3,8 @@ use std::rc::Rc; use num_bigint::BigInt; -use crate::format_err; +use crate::builtins::error_builtin::ToError; +use crate::vs_value::ToVal; use super::bytecode_decoder::{BytecodeDecoder, BytecodeType}; use super::vs_array::VsArray; @@ -18,12 +19,12 @@ pub struct VsPointer { } impl VsPointer { - pub fn new(bytecode: &Rc>, pos: usize) -> Val { - return Val::Custom(Rc::new(VsPointer { + pub fn new(bytecode: &Rc>, pos: usize) -> VsPointer { + VsPointer { bytecode: bytecode.clone(), pos, resolved: RefCell::new(None), - })); + } } fn resolve(&self) -> Val { @@ -146,7 +147,7 @@ impl ValTrait for VsPointer { } fn submov(&mut self, _subscript: Val, _value: Val) -> Result<(), Val> { - format_err!("TODO: Probably an exception, but might be possible") + Err("TODO: Probably an exception, but might be possible".to_error()) } fn next(&mut self) -> LoadFunctionResult { @@ -161,3 +162,9 @@ impl ValTrait for VsPointer { self.resolve().codify() } } + +impl ToVal for VsPointer { + fn to_val(self) -> Val { + Val::Custom(Rc::new(self)) + } +} diff --git a/valuescript_vm/src/vs_value.rs b/valuescript_vm/src/vs_value.rs index 9fe61cf..abce682 100644 --- a/valuescript_vm/src/vs_value.rs +++ b/valuescript_vm/src/vs_value.rs @@ -6,8 +6,7 @@ use num_bigint::BigInt; use num_traits::cast::ToPrimitive; use num_traits::Zero; -use crate::format_val; -use crate::native_function::ThisWrapper; +use crate::native_function::{NativeFunction, ThisWrapper}; use crate::operations::{op_sub, op_submov}; use crate::stack_frame::StackFrame; use crate::vs_array::VsArray; @@ -55,6 +54,37 @@ pub enum LoadFunctionResult { NativeFunction(fn(this: ThisWrapper, params: Vec) -> Result), } +pub trait ToLoadFunctionResult { + fn to_load_function_result(self) -> LoadFunctionResult; +} + +impl ToLoadFunctionResult for StackFrame { + fn to_load_function_result(self) -> LoadFunctionResult { + LoadFunctionResult::StackFrame(self) + } +} + +impl ToLoadFunctionResult for fn(this: ThisWrapper, params: Vec) -> Result { + fn to_load_function_result(self) -> LoadFunctionResult { + LoadFunctionResult::NativeFunction(self) + } +} + +impl ToLoadFunctionResult for NativeFunction { + fn to_load_function_result(self) -> LoadFunctionResult { + self.fn_.to_load_function_result() + } +} + +impl From for LoadFunctionResult +where + T: ToLoadFunctionResult, +{ + fn from(value: T) -> Self { + value.to_load_function_result() + } +} + pub trait ValTrait { fn typeof_(&self) -> VsType; fn val_to_string(&self) -> String; @@ -238,10 +268,10 @@ impl ValTrait for Val { fn to_primitive(&self) -> Val { if self.is_primitive() { - return self.clone(); + self.clone() + } else { + self.to_val_string() } - - return Val::String(Rc::new(self.val_to_string())); } fn is_truthy(&self) -> bool { @@ -290,7 +320,7 @@ impl ValTrait for Val { use Val::*; return match self { - Function(f) => Some(Val::Function(Rc::new(f.bind(params)))), + Function(f) => Some(f.bind(params).to_val()), Custom(val) => val.bind(params), _ => None, @@ -368,7 +398,7 @@ impl ValTrait for Val { match self { // TODO: iterator _ => { - let next_fn = op_sub(self.clone(), Val::String(Rc::new("next".into()))); + let next_fn = op_sub(self.clone(), "next".to_val()); match next_fn { Ok(next_fn) => next_fn.load_function(), @@ -416,7 +446,7 @@ impl ValTrait for Val { let mut res = String::new(); if let Some(proto) = &object.prototype { - match op_sub(proto.clone(), format_val!("name")) { + match op_sub(proto.clone(), "name".to_val()) { Ok(name) => { if name.typeof_() == VsType::String { res += format!("{}", name.val_to_string()).as_str(); @@ -459,6 +489,71 @@ impl ValTrait for Val { } } +pub trait ToValString { + fn to_val_string(&self) -> Val; +} + +impl ToValString for T { + fn to_val_string(&self) -> Val { + Val::String(Rc::new(self.val_to_string())) + } +} + +pub trait ToVal { + fn to_val(self) -> Val; +} + +impl From for Val +where + T: ToVal, +{ + fn from(value: T) -> Val { + value.to_val() + } +} + +impl ToVal for char { + fn to_val(self) -> Val { + self.to_string().to_val() + } +} + +impl ToVal for &str { + fn to_val(self) -> Val { + Val::String(Rc::new(self.to_string())) + } +} + +impl ToVal for String { + fn to_val(self) -> Val { + Val::String(Rc::new(self)) + } +} + +impl ToVal for f64 { + fn to_val(self) -> Val { + Val::Number(self) + } +} + +impl ToVal for bool { + fn to_val(self) -> Val { + Val::Bool(self) + } +} + +impl ToVal for BigInt { + fn to_val(self) -> Val { + Val::BigInt(self) + } +} + +impl ToVal for Vec { + fn to_val(self) -> Val { + Val::Array(Rc::new(VsArray::from(self))) + } +} + impl std::fmt::Display for Val { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -493,7 +588,7 @@ impl std::fmt::Display for Val { } Val::Object(object) => { if let Some(proto) = &object.prototype { - match op_sub(proto.clone(), format_val!("name")) { + match op_sub(proto.clone(), "name".to_val()) { Ok(name) => { if name.typeof_() == VsType::String { write!(f, "{} ", name.val_to_string())?; diff --git a/valuescript_wasm/src/lib.rs b/valuescript_wasm/src/lib.rs index 37778a2..3eb7bc1 100644 --- a/valuescript_wasm/src/lib.rs +++ b/valuescript_wasm/src/lib.rs @@ -1,7 +1,4 @@ -use std::{ - collections::{BTreeMap, HashMap}, - rc::Rc, -}; +use std::collections::{BTreeMap, HashMap}; use wasm_bindgen::prelude::*; @@ -10,8 +7,9 @@ use valuescript_compiler::{ CompileResult, Diagnostic, ResolvedPath, }; use valuescript_vm::{ - vs_array::VsArray, vs_object::VsObject, vs_value::Val, LoadFunctionResult, ValTrait, - VirtualMachine, + vs_object::VsObject, + vs_value::{ToVal, Val}, + LoadFunctionResult, ValTrait, VirtualMachine, }; // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global @@ -161,51 +159,58 @@ fn parse_args(args: &str) -> Result, Val> { let arr = match value { Value::Array(arr) => arr, - _ => return Err(Val::String(Rc::new("Expected array".into()))), + _ => return Err("Expected array".to_val()), }; let mut result = Vec::::new(); for arg in arr.values { - result.push(value_to_val(arg)?); + result.push(arg.try_to_val()?); } Ok(result) } -fn value_to_val(value: Value) -> Result { - Ok(match value { - Value::Undefined => Val::Undefined, - Value::Null => Val::Null, - Value::Bool(b) => Val::Bool(b), - Value::Number(n) => Val::Number(n), - Value::BigInt(n) => Val::BigInt(n), - Value::String(s) => Val::String(Rc::new(s)), - Value::Array(arr) => { - let mut result = Vec::::new(); - - for value in arr.values { - result.push(value_to_val(value)?); - } - - Val::Array(Rc::new(VsArray::from(result))) - } - Value::Object(obj) => { - let mut string_map = BTreeMap::::new(); - - for (key, value) in obj.properties { - string_map.insert(value_to_val(key)?.val_to_string(), value_to_val(value)?); - } - - Val::Object(Rc::new(VsObject { - string_map, - symbol_map: Default::default(), - prototype: None, - })) - } - - Value::Void | Value::Register(..) | Value::Pointer(..) | Value::Builtin(..) => { - return Err(Val::String(Rc::new("Invalid argument".into()))); - } - }) +pub trait TryToVal { + fn try_to_val(self) -> Result; +} + +impl TryToVal for Value { + fn try_to_val(self) -> Result { + Ok(match self { + Value::Undefined => Val::Undefined, + Value::Null => Val::Null, + Value::Bool(b) => b.to_val(), + Value::Number(n) => n.to_val(), + Value::BigInt(n) => n.to_val(), + Value::String(s) => s.to_val(), + Value::Array(arr) => { + let mut result = Vec::::new(); + + for value in arr.values { + result.push(value.try_to_val()?); + } + + result.to_val() + } + Value::Object(obj) => { + let mut string_map = BTreeMap::::new(); + + for (key, value) in obj.properties { + string_map.insert(key.try_to_val()?.val_to_string(), value.try_to_val()?); + } + + VsObject { + string_map, + symbol_map: Default::default(), + prototype: None, + } + .to_val() + } + + Value::Void | Value::Register(..) | Value::Pointer(..) | Value::Builtin(..) => { + return Err("Invalid argument".to_val()); + } + }) + } }