mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
Replace val_to_string with to_string (via fmt::Display)
This commit is contained in:
@@ -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()),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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())
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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]")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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] }}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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)),
|
||||
};
|
||||
|
||||
|
||||
@@ -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" => ©_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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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(_) => {}
|
||||
|
||||
Reference in New Issue
Block a user