From bc89575eae255f4964776f3ab63354b899ab0a76 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Fri, 26 May 2023 13:17:31 +1000 Subject: [PATCH] Replace val_to_string with to_string (via fmt::Display) --- .../src/expression_compiler.rs | 2 +- .../src/array_higher_functions/array_sort.rs | 2 +- valuescript_vm/src/bigint_methods.rs | 4 +- valuescript_vm/src/builtins/array_builtin.rs | 17 ++- .../src/builtins/boolean_builtin.rs | 11 +- valuescript_vm/src/builtins/debug_builtin.rs | 12 +- valuescript_vm/src/builtins/error_builtin.rs | 14 +- valuescript_vm/src/builtins/math_builtin.rs | 12 +- valuescript_vm/src/builtins/number_builtin.rs | 16 ++- .../src/builtins/range_error_builtin.rs | 14 +- valuescript_vm/src/builtins/string_builtin.rs | 12 +- valuescript_vm/src/builtins/symbol_builtin.rs | 13 +- .../src/builtins/type_error_builtin.rs | 14 +- valuescript_vm/src/bytecode_decoder.rs | 3 +- valuescript_vm/src/native_frame_function.rs | 10 +- valuescript_vm/src/native_function.rs | 10 +- valuescript_vm/src/number_methods.rs | 2 +- valuescript_vm/src/operations.rs | 10 +- valuescript_vm/src/string_methods.rs | 20 +-- valuescript_vm/src/vs_array.rs | 32 +++-- valuescript_vm/src/vs_object.rs | 6 +- valuescript_vm/src/vs_pointer.rs | 11 +- valuescript_vm/src/vs_value.rs | 135 +++++++++--------- valuescript_wasm/src/lib.rs | 2 +- 24 files changed, 217 insertions(+), 167 deletions(-) diff --git a/valuescript_compiler/src/expression_compiler.rs b/valuescript_compiler/src/expression_compiler.rs index a315dfd..8e24251 100644 --- a/valuescript_compiler/src/expression_compiler.rs +++ b/valuescript_compiler/src/expression_compiler.rs @@ -345,7 +345,7 @@ impl<'a> ExpressionCompiler<'a> { self .fnc - .allocate_numbered_reg(&format!("_couldnt_mutate_{}_", ident.sym.to_string())) + .allocate_numbered_reg(&format!("_couldnt_mutate_{}_", ident.sym)) } pub fn assign_expression( diff --git a/valuescript_vm/src/array_higher_functions/array_sort.rs b/valuescript_vm/src/array_higher_functions/array_sort.rs index 122c26a..afbef0b 100644 --- a/valuescript_vm/src/array_higher_functions/array_sort.rs +++ b/valuescript_vm/src/array_higher_functions/array_sort.rs @@ -239,7 +239,7 @@ impl StackFrameTrait for SortFrame { array_data_mut .elements - .sort_by(|a, b| a.val_to_string().cmp(&b.val_to_string())); + .sort_by(|a, b| a.to_string().cmp(&b.to_string())); return Ok(FrameStepOk::Pop(CallResult { return_: Val::Array(array_data.clone()), diff --git a/valuescript_vm/src/bigint_methods.rs b/valuescript_vm/src/bigint_methods.rs index 8c0cb95..fd92a1b 100644 --- a/valuescript_vm/src/bigint_methods.rs +++ b/valuescript_vm/src/bigint_methods.rs @@ -4,11 +4,11 @@ use crate::{ builtins::error_builtin::ToError, native_function::{NativeFunction, ThisWrapper}, todo_fn::TODO, - vs_value::{ToValString, Val, ValTrait}, + vs_value::{ToValString, Val}, }; pub fn op_sub_bigint(_bigint: &BigInt, subscript: &Val) -> Val { - match subscript.val_to_string().as_str() { + match subscript.to_string().as_str() { "toLocaleString" => Val::Static(&TODO), "toString" => Val::Static(&TO_STRING), "valueOf" => Val::Static(&VALUE_OF), diff --git a/valuescript_vm/src/builtins/array_builtin.rs b/valuescript_vm/src/builtins/array_builtin.rs index 2c86b05..92dd670 100644 --- a/valuescript_vm/src/builtins/array_builtin.rs +++ b/valuescript_vm/src/builtins/array_builtin.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::{fmt, rc::Rc}; use num_bigint::BigInt; @@ -24,9 +24,6 @@ impl ValTrait for ArrayBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "function Array() { [native code] }".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -66,7 +63,7 @@ impl ValTrait for ArrayBuiltin { } fn sub(&self, key: Val) -> Result { - Ok(Val::Static(match key.val_to_string().as_str() { + Ok(Val::Static(match key.to_string().as_str() { "isArray" => &IS_ARRAY, "from" => &FROM, "of" => &OF, @@ -91,6 +88,12 @@ impl ValTrait for ArrayBuiltin { } } +impl fmt::Display for ArrayBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function Array() {{ [native code] }}") + } +} + static IS_ARRAY: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { Ok(match params.get(0) { @@ -125,7 +128,7 @@ static FROM: NativeFunction = NativeFunction { } Val::Object(..) | Val::Function(..) | Val::Class(..) | Val::Static(..) | Val::Custom(..) => { let len = op_sub(first_param.clone(), "length".to_val()) - .map_err(|e| e.val_to_string()) + .map_err(|e| e.to_string()) .unwrap() // TODO: Exception .to_number(); @@ -146,7 +149,7 @@ static FROM: NativeFunction = NativeFunction { for i in 0..len { arr.push( op_sub(first_param.clone(), Val::Number(i as f64)) - .map_err(|e| e.val_to_string()) + .map_err(|e| e.to_string()) .unwrap(), // TODO: Exception ); } diff --git a/valuescript_vm/src/builtins/boolean_builtin.rs b/valuescript_vm/src/builtins/boolean_builtin.rs index 9a064af..ce98738 100644 --- a/valuescript_vm/src/builtins/boolean_builtin.rs +++ b/valuescript_vm/src/builtins/boolean_builtin.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::{fmt, rc::Rc}; use num_bigint::BigInt; @@ -21,9 +21,6 @@ impl ValTrait for BooleanBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "function Boolean() { [native code] }".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -83,6 +80,12 @@ impl ValTrait for BooleanBuiltin { } } +impl fmt::Display for BooleanBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function Boolean() {{ [native code] }}") + } +} + fn to_boolean(_: ThisWrapper, params: Vec) -> Result { Ok(if let Some(value) = params.get(0) { Val::Bool(value.is_truthy()) diff --git a/valuescript_vm/src/builtins/debug_builtin.rs b/valuescript_vm/src/builtins/debug_builtin.rs index 8d42ca7..fd6f911 100644 --- a/valuescript_vm/src/builtins/debug_builtin.rs +++ b/valuescript_vm/src/builtins/debug_builtin.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -18,9 +19,6 @@ impl ValTrait for DebugBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "[object Debug]".to_string() - } fn to_number(&self) -> f64 { f64::NAN } @@ -62,7 +60,7 @@ impl ValTrait for DebugBuiltin { } fn sub(&self, key: Val) -> Result { - Ok(match key.val_to_string().as_str() { + Ok(match key.to_string().as_str() { "log" => Val::Static(&LOG), _ => Val::Undefined, @@ -86,6 +84,12 @@ impl ValTrait for DebugBuiltin { } } +impl fmt::Display for DebugBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[object Debug]") + } +} + static LOG: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { for p in params { diff --git a/valuescript_vm/src/builtins/error_builtin.rs b/valuescript_vm/src/builtins/error_builtin.rs index b299db9..863a18f 100644 --- a/valuescript_vm/src/builtins/error_builtin.rs +++ b/valuescript_vm/src/builtins/error_builtin.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::{collections::BTreeMap, rc::Rc}; use num_bigint::BigInt; @@ -24,9 +25,6 @@ impl ValTrait for ErrorBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "function Error() { [native code] }".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -97,6 +95,12 @@ impl ValTrait for ErrorBuiltin { } } +impl fmt::Display for ErrorBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function Error() {{ [native code] }}") + } +} + pub trait ToError { fn to_error(self) -> Val; } @@ -140,7 +144,7 @@ fn make_error_prototype() -> Val { static SET_MESSAGE: NativeFunction = NativeFunction { fn_: |mut this: ThisWrapper, params: Vec| -> Result { let message = match params.get(0) { - Some(param) => param.val_to_string(), + Some(param) => param.to_string(), None => "".to_string(), }; @@ -153,6 +157,6 @@ static SET_MESSAGE: NativeFunction = NativeFunction { static ERROR_TO_STRING: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, _params: Vec| -> Result { let message = op_sub(this.get().clone(), "message".to_val())?; - Ok(format!("Error({})", message.val_to_string()).to_val()) // TODO: Fixes needed here (and other errors) + 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 21d1f83..f0e8dc4 100644 --- a/valuescript_vm/src/builtins/math_builtin.rs +++ b/valuescript_vm/src/builtins/math_builtin.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -19,9 +20,6 @@ impl ValTrait for MathBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "[object Math]".to_string() - } fn to_number(&self) -> f64 { f64::NAN } @@ -63,7 +61,7 @@ impl ValTrait for MathBuiltin { } fn sub(&self, key: Val) -> Result { - Ok(match key.val_to_string().as_str() { + Ok(match key.to_string().as_str() { "E" => Val::Number(std::f64::consts::E), "LN10" => Val::Number(std::f64::consts::LN_10), "LN2" => Val::Number(std::f64::consts::LN_2), @@ -131,6 +129,12 @@ impl ValTrait for MathBuiltin { } } +impl fmt::Display for MathBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[object Math]") + } +} + fn param_to_number(param: Option<&Val>) -> f64 { match param { None => f64::NAN, diff --git a/valuescript_vm/src/builtins/number_builtin.rs b/valuescript_vm/src/builtins/number_builtin.rs index 7a3b063..c125fd6 100644 --- a/valuescript_vm/src/builtins/number_builtin.rs +++ b/valuescript_vm/src/builtins/number_builtin.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -23,9 +24,6 @@ impl ValTrait for NumberBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "function Number() { [native code] }".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -65,7 +63,7 @@ impl ValTrait for NumberBuiltin { } fn sub(&self, key: Val) -> Result { - Ok(match key.val_to_string().as_str() { + Ok(match key.to_string().as_str() { "EPSILON" => Val::Number(core::f64::EPSILON), "MAX_VALUE" => Val::Number(core::f64::MAX), "MAX_SAFE_INTEGER" => Val::Number(2f64.powi(53) - 1f64), @@ -101,6 +99,12 @@ impl ValTrait for NumberBuiltin { } } +impl fmt::Display for NumberBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function Number() {{ [native code] }}") + } +} + pub static IS_FINITE: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { Ok(if let Some(value) = params.get(0) { @@ -157,7 +161,7 @@ static IS_SAFE_INTEGER: NativeFunction = NativeFunction { pub static PARSE_FLOAT: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { Ok(if let Some(value) = params.get(0) { - let string_value = value.val_to_string().trim().to_string(); + let string_value = value.to_string().trim().to_string(); match string_value.parse::() { Ok(number) => Val::Number(number), @@ -172,7 +176,7 @@ pub static PARSE_FLOAT: NativeFunction = NativeFunction { pub static PARSE_INT: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { Ok(if let Some(value) = params.get(0) { - let string_value = value.val_to_string().trim_start().to_string(); + let string_value = value.to_string().trim_start().to_string(); let radix = params.get(1).and_then(|v| v.to_index()).unwrap_or(10); if radix < 2 || radix > 36 { diff --git a/valuescript_vm/src/builtins/range_error_builtin.rs b/valuescript_vm/src/builtins/range_error_builtin.rs index b53acab..6181a14 100644 --- a/valuescript_vm/src/builtins/range_error_builtin.rs +++ b/valuescript_vm/src/builtins/range_error_builtin.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::{collections::BTreeMap, rc::Rc}; use num_bigint::BigInt; @@ -24,9 +25,6 @@ impl ValTrait for RangeErrorBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "function RangeError() { [native code] }".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -89,6 +87,12 @@ impl ValTrait for RangeErrorBuiltin { } } +impl fmt::Display for RangeErrorBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function RangeError() {{ [native code] }}") + } +} + pub fn to_range_error(_: ThisWrapper, params: Vec) -> Result { Ok( VsObject { @@ -122,7 +126,7 @@ fn make_range_error_prototype() -> Val { static SET_MESSAGE: NativeFunction = NativeFunction { fn_: |mut this: ThisWrapper, params: Vec| -> Result { let message = match params.get(0) { - Some(param) => param.val_to_string(), + Some(param) => param.to_string(), None => "".to_string(), }; @@ -135,7 +139,7 @@ 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(), "message".to_val())?; - Ok(format!("RangeError({})", message.val_to_string()).to_val()) + Ok(format!("RangeError({})", message).to_val()) }, }; diff --git a/valuescript_vm/src/builtins/string_builtin.rs b/valuescript_vm/src/builtins/string_builtin.rs index 1832180..6606ca6 100644 --- a/valuescript_vm/src/builtins/string_builtin.rs +++ b/valuescript_vm/src/builtins/string_builtin.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -24,9 +25,6 @@ impl ValTrait for StringBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "function String() { [native code] }".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -69,7 +67,7 @@ impl ValTrait for StringBuiltin { // Not supported: fromCharCode. // See charAt etc in string_methods.rs. - Ok(match key.val_to_string().as_str() { + Ok(match key.to_string().as_str() { "fromCodePoint" => Val::Static(&FROM_CODE_POINT), // "fromCharCode" => Val::Static(&FROM_CHAR_CODE), // "raw" => Val::Static(&RAW), // TODO @@ -94,6 +92,12 @@ impl ValTrait for StringBuiltin { } } +impl fmt::Display for StringBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function String() {{ [native code] }}") + } +} + static FROM_CODE_POINT: NativeFunction = NativeFunction { fn_: |_this: ThisWrapper, params: Vec| -> Result { let mut result = String::new(); diff --git a/valuescript_vm/src/builtins/symbol_builtin.rs b/valuescript_vm/src/builtins/symbol_builtin.rs index 92de415..5b501a2 100644 --- a/valuescript_vm/src/builtins/symbol_builtin.rs +++ b/valuescript_vm/src/builtins/symbol_builtin.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::{fmt, rc::Rc}; use num_bigint::BigInt; @@ -21,9 +21,6 @@ impl ValTrait for SymbolBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "[object Symbol]".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -63,7 +60,7 @@ impl ValTrait for SymbolBuiltin { } fn sub(&self, key: Val) -> Result { - Ok(match key.val_to_string().as_str() { + Ok(match key.to_string().as_str() { "iterator" => Val::Symbol(VsSymbol::ITERATOR), _ => Val::Undefined, }) @@ -85,3 +82,9 @@ impl ValTrait for SymbolBuiltin { "Symbol".into() } } + +impl fmt::Display for SymbolBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[object Symbol]") + } +} diff --git a/valuescript_vm/src/builtins/type_error_builtin.rs b/valuescript_vm/src/builtins/type_error_builtin.rs index 4b5fbd5..77deb4d 100644 --- a/valuescript_vm/src/builtins/type_error_builtin.rs +++ b/valuescript_vm/src/builtins/type_error_builtin.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::{collections::BTreeMap, rc::Rc}; use num_bigint::BigInt; @@ -22,9 +23,6 @@ impl ValTrait for TypeErrorBuiltin { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "function TypeError() { [native code] }".to_string() - } fn to_number(&self) -> f64 { core::f64::NAN } @@ -95,6 +93,12 @@ impl ValTrait for TypeErrorBuiltin { } } +impl fmt::Display for TypeErrorBuiltin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function TypeError() {{ [native code] }}") + } +} + // TODO: Static? (Rc -> Arc?) fn make_type_error_prototype() -> Val { VsObject { @@ -111,7 +115,7 @@ fn make_type_error_prototype() -> Val { static SET_MESSAGE: NativeFunction = NativeFunction { fn_: |mut this: ThisWrapper, params: Vec| -> Result { let message = match params.get(0) { - Some(param) => param.val_to_string(), + Some(param) => param.to_string(), None => "".to_string(), }; @@ -124,7 +128,7 @@ 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(), "message".to_val())?; - Ok(format!("TypeError({})", message.val_to_string()).to_val()) + Ok(format!("TypeError({})", message).to_val()) }, }; diff --git a/valuescript_vm/src/bytecode_decoder.rs b/valuescript_vm/src/bytecode_decoder.rs index 2b766da..99dcd66 100644 --- a/valuescript_vm/src/bytecode_decoder.rs +++ b/valuescript_vm/src/bytecode_decoder.rs @@ -13,7 +13,6 @@ 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; pub struct BytecodeDecoder { // TODO: Enable borrow usage to avoid the rc overhead @@ -125,7 +124,7 @@ impl BytecodeDecoder { match key { Val::String(string) => string_map.insert(string.to_string(), value), Val::Symbol(symbol) => symbol_map.insert(symbol, value), - key => string_map.insert(key.val_to_string(), value), + key => string_map.insert(key.to_string(), value), }; } diff --git a/valuescript_vm/src/native_frame_function.rs b/valuescript_vm/src/native_frame_function.rs index e8c2839..fbbdac4 100644 --- a/valuescript_vm/src/native_frame_function.rs +++ b/valuescript_vm/src/native_frame_function.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -18,9 +19,6 @@ impl ValTrait for NativeFrameFunction { fn typeof_(&self) -> VsType { VsType::Function } - fn val_to_string(&self) -> String { - "function() { [native code] }".to_string() - } fn to_number(&self) -> f64 { f64::NAN } @@ -81,3 +79,9 @@ impl ValTrait for NativeFrameFunction { "function() { [native code] }".into() } } + +impl fmt::Display for NativeFrameFunction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function() {{ [native code] }}") + } +} diff --git a/valuescript_vm/src/native_function.rs b/valuescript_vm/src/native_function.rs index 7a62347..fe20d18 100644 --- a/valuescript_vm/src/native_function.rs +++ b/valuescript_vm/src/native_function.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -40,9 +41,6 @@ impl ValTrait for NativeFunction { fn typeof_(&self) -> VsType { VsType::Function } - fn val_to_string(&self) -> String { - "function() { [native code] }".to_string() - } fn to_number(&self) -> f64 { f64::NAN } @@ -104,6 +102,12 @@ impl ValTrait for NativeFunction { } } +impl fmt::Display for NativeFunction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "function() {{ [native code] }}") + } +} + 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 b173422..215b1e9 100644 --- a/valuescript_vm/src/number_methods.rs +++ b/valuescript_vm/src/number_methods.rs @@ -9,7 +9,7 @@ use crate::{ }; pub fn op_sub_number(_number: f64, subscript: &Val) -> Val { - match subscript.val_to_string().as_str() { + match subscript.to_string().as_str() { "toExponential" => Val::Static(&TO_EXPONENTIAL), "toFixed" => Val::Static(&TO_FIXED), "toLocaleString" => Val::Static(&TODO_LOCALE), diff --git a/valuescript_vm/src/operations.rs b/valuescript_vm/src/operations.rs index 658899f..a2c1af6 100644 --- a/valuescript_vm/src/operations.rs +++ b/valuescript_vm/src/operations.rs @@ -24,7 +24,7 @@ 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((left_prim.val_to_string() + &right_prim.val_to_string()).to_val()); + return Ok((left_prim.to_string() + &right_prim.to_string()).to_val()); } if left_type == VsType::BigInt || right_type == VsType::BigInt { @@ -373,7 +373,7 @@ pub fn op_sub(left: Val, right: Val) -> Result { 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() { + Val::Bool(_) => Ok(match right.to_string().as_str() { "toString" => Val::Static(&BOOL_TO_STRING), "valueOf" => Val::Static(&BOOL_VALUE_OF), _ => Val::Undefined, @@ -385,9 +385,9 @@ pub fn op_sub(left: Val, right: Val) -> Result { Val::Array(array_data) => { let right_index = match right.to_index() { None => { - // FIXME: Inefficient val_to_string() that gets duplicated + // FIXME: Inefficient to_string() that gets duplicated // when subscripting the object - if right.val_to_string() == "length" { + if right.to_string() == "length" { return Ok(Val::Number(array_data.elements.len() as f64)); } @@ -457,7 +457,7 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val Val::Symbol(symbol) => object_data_mut.symbol_map.insert(symbol, value), _ => object_data_mut .string_map - .insert(subscript.val_to_string(), value), + .insert(subscript.to_string(), value), }; Ok(()) diff --git a/valuescript_vm/src/string_methods.rs b/valuescript_vm/src/string_methods.rs index b4ad5e0..287670d 100644 --- a/valuescript_vm/src/string_methods.rs +++ b/valuescript_vm/src/string_methods.rs @@ -11,7 +11,7 @@ use crate::{ pub fn op_sub_string(string_data: &Rc, subscript: &Val) -> Val { let right_index = match subscript.to_index() { None => { - let method = subscript.val_to_string(); + let method = subscript.to_string(); let method_str = method.as_str(); return match method_str { @@ -135,7 +135,7 @@ static CONCAT: NativeFunction = NativeFunction { let mut result = string_data.as_str().to_string(); for param in params { - result.push_str(param.val_to_string().as_str()); + result.push_str(param.to_string().as_str()); } result.to_val() @@ -152,7 +152,7 @@ static ENDS_WITH: NativeFunction = NativeFunction { let string_bytes = string_data.as_bytes(); let search_string = match params.get(0) { - Some(s) => s.val_to_string(), + Some(s) => s.to_string(), _ => return Ok(Val::Bool(false)), }; @@ -195,7 +195,7 @@ static INCLUDES: NativeFunction = NativeFunction { let string_bytes = string_data.as_bytes(); let search_string = match params.get(0) { - Some(s) => s.val_to_string(), + Some(s) => s.to_string(), _ => return Ok(Val::Bool(false)), }; @@ -227,7 +227,7 @@ static INDEX_OF: NativeFunction = NativeFunction { let string_bytes = string_data.as_bytes(); let search_string = match params.get(0) { - Some(s) => s.val_to_string(), + Some(s) => s.to_string(), _ => return Ok(Val::Number(-1.0)), }; @@ -259,7 +259,7 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction { let string_bytes = string_data.as_bytes(); let search_string = match params.get(0) { - Some(s) => s.val_to_string(), + Some(s) => s.to_string(), _ => return Ok(Val::Number(-1.0)), }; @@ -341,7 +341,7 @@ static PAD_END: NativeFunction = NativeFunction { let mut string = string_data.to_string(); let pad_string = match params.get(1) { - Some(s) => s.val_to_string(), + Some(s) => s.to_string(), _ => " ".to_string(), }; @@ -393,7 +393,7 @@ static PAD_START: NativeFunction = NativeFunction { } let pad_string = match params.get(1) { - Some(s) => s.val_to_string(), + Some(s) => s.to_string(), _ => " ".to_string(), }; @@ -495,7 +495,7 @@ static SPLIT: NativeFunction = NativeFunction { Ok(match this.get() { Val::String(string_data) => { let separator = match params.get(0) { - Some(s) => s.val_to_string(), // TODO: Regexes + Some(s) => s.to_string(), // TODO: Regexes None => return Ok(Val::String(string_data.clone())), }; @@ -563,7 +563,7 @@ static STARTS_WITH: NativeFunction = NativeFunction { let string_bytes = string_data.as_bytes(); let search_string = match params.get(0) { - Some(s) => s.val_to_string(), + Some(s) => s.to_string(), _ => return Ok(Val::Bool(false)), }; diff --git a/valuescript_vm/src/vs_array.rs b/valuescript_vm/src/vs_array.rs index eebb328..f30fb53 100644 --- a/valuescript_vm/src/vs_array.rs +++ b/valuescript_vm/src/vs_array.rs @@ -1,4 +1,5 @@ use std::cmp::{max, min}; +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -62,9 +63,6 @@ impl ValTrait for ArrayPrototype { fn typeof_(&self) -> VsType { VsType::Object } - fn val_to_string(&self) -> String { - "".to_string() - } fn to_number(&self) -> f64 { 0_f64 } @@ -106,7 +104,7 @@ impl ValTrait for ArrayPrototype { } fn sub(&self, key: Val) -> Result { - Ok(Val::Static(match key.val_to_string().as_str() { + Ok(Val::Static(match key.to_string().as_str() { "at" => &AT, "concat" => &CONCAT, "copyWithin" => ©_WITHIN, @@ -161,6 +159,12 @@ impl ValTrait for ArrayPrototype { } } +impl fmt::Display for ArrayPrototype { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + Ok(()) + } +} + static AT: NativeFunction = NativeFunction { fn_: |this: ThisWrapper, params: Vec| -> Result { Ok(match this.get() { @@ -352,7 +356,7 @@ static INCLUDES: NativeFunction = NativeFunction { for elem in &array_data.elements { let is_eq = op_triple_eq_impl(elem.clone(), search_param.clone()) - .map_err(|e| e.val_to_string()) + .map_err(|e| e.to_string()) .unwrap(); // TODO: Exception if is_eq { @@ -375,7 +379,7 @@ static INDEX_OF: NativeFunction = NativeFunction { for i in 0..array_data.elements.len() { let is_eq = op_triple_eq_impl(array_data.elements[i].clone(), search_param.clone()) - .map_err(|e| e.val_to_string()) + .map_err(|e| e.to_string()) .unwrap(); // TODO: Exception if is_eq { @@ -402,23 +406,21 @@ static JOIN: NativeFunction = NativeFunction { return Ok(vals.elements[0].to_val_string()); } - let separator = params.get(0).unwrap_or(&Val::Undefined); - - let separator_str = match separator.typeof_() { - VsType::Undefined => ",".to_string(), - _ => separator.val_to_string(), + let separator = match params.get(0) { + None => ",".to_string(), + Some(v) => v.to_string(), }; let mut iter = vals.elements.iter(); - let mut res = iter.next().unwrap().val_to_string(); + let mut res = iter.next().unwrap().to_string(); for val in iter { - res += &separator_str; + res += &separator; match val.typeof_() { VsType::Undefined => {} _ => { - res += &val.val_to_string(); + res += &val.to_string(); } }; } @@ -438,7 +440,7 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction { for i in (0..array_data.elements.len()).rev() { let is_eq = op_triple_eq_impl(array_data.elements[i].clone(), search_param.clone()) - .map_err(|e| e.val_to_string()) + .map_err(|e| e.to_string()) .unwrap(); // TODO: Exception if is_eq { diff --git a/valuescript_vm/src/vs_object.rs b/valuescript_vm/src/vs_object.rs index 87f0509..0258168 100644 --- a/valuescript_vm/src/vs_object.rs +++ b/valuescript_vm/src/vs_object.rs @@ -5,7 +5,7 @@ use crate::vs_symbol::VsSymbol; use crate::vs_value::ToVal; use super::operations::op_sub; -use super::vs_value::{Val, ValTrait}; +use super::vs_value::Val; #[derive(Clone, Default, Debug)] pub struct VsObject { @@ -19,7 +19,7 @@ impl VsObject { let val = match &key { Val::String(string) => self.string_map.get(&**string), Val::Symbol(symbol) => self.symbol_map.get(symbol), - _ => self.string_map.get(&key.val_to_string()), + _ => self.string_map.get(&key.to_string()), }; if let Some(val) = val { @@ -28,7 +28,7 @@ impl VsObject { match &self.prototype { Some(prototype) => op_sub(prototype.clone(), key) - .map_err(|e| e.val_to_string()) + .map_err(|e| e.to_string()) .unwrap(), // TODO: Exception None => Val::Undefined, } diff --git a/valuescript_vm/src/vs_pointer.rs b/valuescript_vm/src/vs_pointer.rs index 5d6f0cc..586368b 100644 --- a/valuescript_vm/src/vs_pointer.rs +++ b/valuescript_vm/src/vs_pointer.rs @@ -1,4 +1,5 @@ use std::cell::RefCell; +use std::fmt; use std::rc::Rc; use num_bigint::BigInt; @@ -78,10 +79,6 @@ impl ValTrait for VsPointer { }; } - fn val_to_string(&self) -> String { - return self.resolve().val_to_string(); - } - fn to_number(&self) -> f64 { return self.resolve().to_number(); } @@ -163,6 +160,12 @@ impl ValTrait for VsPointer { } } +impl fmt::Display for VsPointer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.resolve().fmt(f) + } +} + 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 5a23574..0e20188 100644 --- a/valuescript_vm/src/vs_value.rs +++ b/valuescript_vm/src/vs_value.rs @@ -85,9 +85,8 @@ where } } -pub trait ValTrait { +pub trait ValTrait: fmt::Display { fn typeof_(&self) -> VsType; - fn val_to_string(&self) -> String; fn to_number(&self) -> f64; fn to_index(&self) -> Option; fn is_primitive(&self) -> bool; @@ -143,59 +142,6 @@ impl ValTrait for Val { }; } - fn val_to_string(&self) -> String { - use Val::*; - - return match self { - Void => "".to_string(), - Undefined => "undefined".to_string(), - Null => "null".to_string(), - Bool(b) => b.to_string(), - Number(x) => { - if x.is_infinite() { - if x.is_sign_positive() { - "Infinity".to_string() - } else { - "-Infinity".to_string() - } - } else { - x.to_string() - } - } // TODO: Match js's number string format - BigInt(x) => x.to_string(), - Symbol(s) => format!("Symbol(Symbol.{})", symbol_to_name(s.clone())), - String(s) => s.to_string(), - Array(vals) => { - if vals.elements.len() == 0 { - "".to_string() - } else if vals.elements.len() == 1 { - vals.elements[0].val_to_string() - } else { - let mut iter = vals.elements.iter(); - let mut res = iter.next().unwrap().val_to_string(); - - for val in iter { - res += ","; - - match val.typeof_() { - VsType::Undefined => {} - _ => { - res += &val.val_to_string(); - } - }; - } - - res - } - } - Object(_) => "[object Object]".to_string(), - Function(_) => "[function]".to_string(), - Class(_) => "[class]".to_string(), - Static(val) => val.val_to_string(), - Custom(val) => val.val_to_string(), - }; - } - fn to_number(&self) -> f64 { use Val::*; @@ -417,9 +363,9 @@ impl ValTrait for Val { Val::Void => "".into(), Val::Undefined => "undefined".into(), Val::Null => "null".into(), - Val::Bool(_) => self.val_to_string(), - Val::Number(_) => self.val_to_string(), - Val::BigInt(_) => self.val_to_string() + "n", + Val::Bool(_) => self.to_string(), + Val::Number(_) => self.to_string(), + Val::BigInt(_) => self.to_string() + "n", Val::Symbol(s) => format!("Symbol.{}", symbol_to_name(s.clone())), Val::String(str) => stringify_string(str), Val::Array(vals) => { @@ -449,7 +395,7 @@ impl ValTrait for Val { match op_sub(proto.clone(), "name".to_val()) { Ok(name) => { if name.typeof_() == VsType::String { - res += format!("{}", name.val_to_string()).as_str(); + res += &name.to_string(); } } Err(_) => {} @@ -489,13 +435,68 @@ impl ValTrait for Val { } } +impl fmt::Display for Val { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use Val::*; + + match self { + Void => Ok(()), + Undefined => write!(f, "undefined"), + Null => write!(f, "null"), + Bool(b) => b.fmt(f), + Number(x) => { + if x.is_infinite() { + if x.is_sign_positive() { + write!(f, "Infinity") + } else { + write!(f, "-Infinity") + } + } else { + x.fmt(f) + } + } // TODO: Match js's number string format + BigInt(x) => x.fmt(f), + Symbol(s) => write!(f, "Symbol(Symbol.{})", symbol_to_name(s.clone())), + String(s) => s.fmt(f), + Array(vals) => { + if vals.elements.len() == 0 { + Ok(()) + } else if vals.elements.len() == 1 { + vals.elements[0].fmt(f) + } else { + let mut iter = vals.elements.iter(); + iter.next().unwrap().fmt(f)?; + + for val in iter { + write!(f, ",")?; + + match val.typeof_() { + VsType::Undefined => {} + _ => { + val.fmt(f)?; + } + }; + } + + Ok(()) + } + } + Object(_) => write!(f, "[object Object]"), + Function(_) => write!(f, "[function]"), + Class(_) => write!(f, "[class]"), + Static(val) => val.fmt(f), + Custom(val) => val.fmt(f), + } + } +} + 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())) + Val::String(Rc::new(self.to_string())) } } @@ -570,9 +571,9 @@ impl<'a> std::fmt::Display for PrettyVal<'a> { Val::Void => write!(f, "void"), Val::Undefined => write!(f, "\x1b[90mundefined\x1b[39m"), Val::Null => write!(f, "\x1b[1mnull\x1b[22m"), - Val::Bool(_) => write!(f, "\x1b[33m{}\x1b[39m", self.val.val_to_string()), - Val::Number(_) => write!(f, "\x1b[33m{}\x1b[39m", self.val.val_to_string()), - Val::BigInt(_) => write!(f, "\x1b[33m{}n\x1b[39m", self.val.val_to_string()), + Val::Bool(_) => write!(f, "\x1b[33m{}\x1b[39m", self.val), + Val::Number(_) => write!(f, "\x1b[33m{}\x1b[39m", self.val), + Val::BigInt(_) => write!(f, "\x1b[33m{}n\x1b[39m", self.val), Val::Symbol(_) => write!(f, "\x1b[32m{}\x1b[39m", self.val.codify()), Val::String(_) => write!(f, "\x1b[32m{}\x1b[39m", self.val.codify()), Val::Array(array) => { @@ -580,7 +581,7 @@ impl<'a> std::fmt::Display for PrettyVal<'a> { return write!(f, "[]"); } - write!(f, "[ ").expect("Failed to write"); + write!(f, "[ ")?; let mut first = true; @@ -588,10 +589,10 @@ impl<'a> std::fmt::Display for PrettyVal<'a> { if first { first = false; } else { - write!(f, ", ").expect("Failed to write"); + write!(f, ", ")?; } - write!(f, "{}", elem.pretty()).expect("Failed to write"); + write!(f, "{}", elem.pretty())?; } write!(f, " ]") @@ -601,7 +602,7 @@ impl<'a> std::fmt::Display for PrettyVal<'a> { match op_sub(proto.clone(), "name".to_val()) { Ok(name) => { if name.typeof_() == VsType::String { - write!(f, "{} ", name.val_to_string())?; + write!(f, "{} ", name)?; } } Err(_) => {} diff --git a/valuescript_wasm/src/lib.rs b/valuescript_wasm/src/lib.rs index 3eb7bc1..b01fb5d 100644 --- a/valuescript_wasm/src/lib.rs +++ b/valuescript_wasm/src/lib.rs @@ -197,7 +197,7 @@ impl TryToVal for Value { 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()?); + string_map.insert(key.try_to_val()?.to_string(), value.try_to_val()?); } VsObject {