Replace val_to_string with to_string (via fmt::Display)

This commit is contained in:
Andrew Morris
2023-05-26 13:17:31 +10:00
parent 3cfe1a6527
commit bc89575eae
24 changed files with 217 additions and 167 deletions

View File

@@ -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()),

View File

@@ -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),

View File

@@ -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<Val, Val> {
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<Val>| -> Result<Val, Val> {
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
);
}

View File

@@ -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<Val>) -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
Val::Bool(value.is_truthy())

View File

@@ -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<Val, Val> {
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<Val>| -> Result<Val, Val> {
for p in params {

View File

@@ -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<Val>| -> Result<Val, Val> {
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<Val>| -> Result<Val, Val> {
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)
},
};

View File

@@ -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<Val, Val> {
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,

View File

@@ -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<Val, Val> {
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<Val>| -> Result<Val, Val> {
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<Val>| -> Result<Val, Val> {
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::<f64>() {
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<Val>| -> Result<Val, Val> {
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 {

View File

@@ -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<Val>) -> Result<Val, Val> {
Ok(
VsObject {
@@ -122,7 +126,7 @@ fn make_range_error_prototype() -> Val {
static SET_MESSAGE: NativeFunction = NativeFunction {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
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<Val>| -> Result<Val, Val> {
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())
},
};

View File

@@ -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<Val>| -> Result<Val, Val> {
let mut result = String::new();

View File

@@ -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<Val, Val> {
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]")
}
}

View File

@@ -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<Val>| -> Result<Val, Val> {
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<Val>| -> Result<Val, Val> {
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())
},
};

View File

@@ -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),
};
}

View File

@@ -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] }}")
}
}

View File

@@ -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)

View File

@@ -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),

View File

@@ -24,7 +24,7 @@ pub fn op_plus(left: Val, right: Val) -> Result<Val, Val> {
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, Val> {
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, Val> {
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(())

View File

@@ -11,7 +11,7 @@ use crate::{
pub fn op_sub_string(string_data: &Rc<String>, 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)),
};

View File

@@ -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<Val, Val> {
Ok(Val::Static(match key.val_to_string().as_str() {
Ok(Val::Static(match key.to_string().as_str() {
"at" => &AT,
"concat" => &CONCAT,
"copyWithin" => &COPY_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<Val>| -> Result<Val, Val> {
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 {

View File

@@ -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,
}

View File

@@ -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))

View File

@@ -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<usize>;
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<T: ValTrait> 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(_) => {}