Make native functions const aware

This commit is contained in:
Andrew Morris
2023-04-04 00:13:04 +10:00
parent de3f247337
commit e54abc981f
23 changed files with 273 additions and 192 deletions

View File

@@ -1,5 +1,6 @@
use std::rc::Rc;
use crate::native_function::ThisWrapper;
use crate::stack_frame::FrameStepResult;
use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait};
use crate::vs_array::VsArray;
@@ -86,7 +87,7 @@ impl StackFrameTrait for ArrayMappingFrame {
array_i,
el,
native_fn(
&mut self.this_arg.clone(),
ThisWrapper::new(false, &mut self.this_arg.clone()),
vec![
el.clone(),
Val::Number(array_i as f64),

View File

@@ -1,6 +1,7 @@
use std::rc::Rc;
use crate::native_frame_function::NativeFrameFunction;
use crate::native_function::ThisWrapper;
use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait};
use crate::vs_array::VsArray;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
@@ -67,7 +68,7 @@ impl StackFrameTrait for ReduceFrame {
LoadFunctionResult::NotAFunction => return type_error!("reduce fn is not a function"),
LoadFunctionResult::NativeFunction(native_fn) => {
self.value = Some(native_fn(
&mut Val::Undefined,
ThisWrapper::new(true, &mut Val::Undefined),
vec![
value.clone(),
el.clone(),

View File

@@ -1,6 +1,7 @@
use std::rc::Rc;
use crate::native_frame_function::NativeFrameFunction;
use crate::native_function::ThisWrapper;
use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait};
use crate::vs_array::VsArray;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
@@ -89,7 +90,7 @@ impl StackFrameTrait for ReduceRightFrame {
}
LoadFunctionResult::NativeFunction(native_fn) => {
self.value = Some(native_fn(
&mut Val::Undefined,
ThisWrapper::new(true, &mut Val::Undefined),
vec![
value.clone(),
el.clone(),

View File

@@ -1,6 +1,7 @@
use std::rc::Rc;
use crate::native_frame_function::NativeFrameFunction;
use crate::native_function::ThisWrapper;
use crate::stack_frame::FrameStepResult;
use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait};
use crate::vs_array::VsArray;
@@ -271,7 +272,11 @@ impl StackFrameTrait for SortFrame {
return type_error!("comparator is not a function");
}
LoadFunctionResult::NativeFunction(native_fn) => {
let res = native_fn(&mut Val::Undefined, vec![left, right])?.to_number();
let res = native_fn(
ThisWrapper::new(true, &mut Val::Undefined),
vec![left, right],
)?
.to_number();
let should_swap = match res.is_nan() {
true => false,

View File

@@ -4,7 +4,7 @@ use num_bigint::BigInt;
use crate::{
format_err,
native_function::NativeFunction,
native_function::{NativeFunction, ThisWrapper},
todo_fn::TODO,
vs_value::{Val, ValTrait},
};
@@ -19,14 +19,14 @@ pub fn op_sub_bigint(_bigint: &BigInt, subscript: &Val) -> Val {
}
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::BigInt(_) => match params.get(0) {
Some(_) => {
return format_err!("TODO: toString with radix");
}
None => Val::String(Rc::new(this.val_to_string())),
None => Val::String(Rc::new(this.get().val_to_string())),
},
_ => return format_err!("TODO: bigint indirection"),
})
@@ -34,8 +34,8 @@ static TO_STRING: NativeFunction = NativeFunction {
};
static VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::BigInt(bigint) => Val::BigInt(bigint.clone()),
_ => return format_err!("TODO: bigint indirection"),
})

View File

@@ -6,7 +6,7 @@ use crate::{
builtins::range_error_builtin::to_range_error,
builtins::type_error_builtin::to_type_error,
format_err,
native_function::NativeFunction,
native_function::{NativeFunction, ThisWrapper},
operations::op_sub,
range_error, type_error,
vs_array::VsArray,
@@ -88,7 +88,7 @@ impl ValTrait for ArrayBuiltin {
}
static IS_ARRAY: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match params.get(0) {
None => Val::Bool(false),
Some(p) => match p.as_array_data() {
@@ -100,7 +100,7 @@ static IS_ARRAY: NativeFunction = NativeFunction {
};
static FROM: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let first_param = match params.get(0) {
None => return type_error!("undefined is not iterable"),
Some(p) => p,
@@ -157,12 +157,12 @@ static FROM: NativeFunction = NativeFunction {
};
static OF: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(Val::Array(Rc::new(VsArray::from(params))))
},
};
fn to_array(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
fn to_array(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
if params.len() != 1 {
return Ok(Val::Array(Rc::new(VsArray::from(params))));
}

View File

@@ -4,6 +4,7 @@ use num_bigint::BigInt;
use crate::{
builtins::type_error_builtin::to_type_error,
native_function::ThisWrapper,
type_error,
vs_array::VsArray,
vs_class::VsClass,
@@ -78,7 +79,7 @@ impl ValTrait for BooleanBuiltin {
}
}
fn to_boolean(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
fn to_boolean(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
Val::Bool(value.is_truthy())
} else {

View File

@@ -2,7 +2,7 @@ use std::rc::Rc;
use num_bigint::BigInt;
use crate::native_function::NativeFunction;
use crate::native_function::{NativeFunction, ThisWrapper};
use crate::vs_array::VsArray;
use crate::vs_class::VsClass;
use crate::vs_object::VsObject;
@@ -82,7 +82,7 @@ impl ValTrait for DebugBuiltin {
}
static LOG: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
for p in params {
println!("Debug.log: {}", p);
}

View File

@@ -2,6 +2,7 @@ use std::{collections::BTreeMap, rc::Rc};
use num_bigint::BigInt;
use crate::native_function::ThisWrapper;
use crate::{builtins::type_error_builtin::to_type_error, type_error};
use crate::{
format_val,
@@ -83,7 +84,7 @@ impl ValTrait for ErrorBuiltin {
}
}
fn to_error(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
fn to_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
Ok(Val::Object(Rc::new(VsObject {
string_map: BTreeMap::from([(
"message".to_string(),
@@ -111,21 +112,25 @@ fn make_error_prototype() -> Val {
}
static SET_MESSAGE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let message = match params.get(0) {
Some(param) => param.val_to_string(),
None => "".to_string(),
};
op_submov(this, format_val!("message"), format_val!("{}", message))?;
op_submov(
this.get_mut()?,
format_val!("message"),
format_val!("{}", message),
)?;
Ok(Val::Undefined)
},
};
static ERROR_TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
let message = op_sub(this.clone(), format_val!("message"))?;
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
let message = op_sub(this.get().clone(), format_val!("message"))?;
Ok(format_val!("Error({})", message)) // TODO: Fixes needed here (and other errors)
},
};

View File

@@ -2,7 +2,7 @@ use std::rc::Rc;
use num_bigint::BigInt;
use crate::native_function::NativeFunction;
use crate::native_function::{NativeFunction, ThisWrapper};
use crate::operations::to_u32;
use crate::vs_array::VsArray;
use crate::vs_class::VsClass;
@@ -134,49 +134,49 @@ fn param_to_number(param: Option<&Val>) -> f64 {
}
static ABS: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.abs()))
},
};
static ACOS: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.acos()))
},
};
static ACOSH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.acosh()))
},
};
static ASIN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.asin()))
},
};
static ASINH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.sinh()))
},
};
static ATAN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.atan()))
},
};
static ATAN2: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
@@ -185,77 +185,77 @@ static ATAN2: NativeFunction = NativeFunction {
};
static ATANH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.atanh()))
},
};
static CBRT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.cbrt()))
},
};
static CEIL: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.ceil()))
},
};
static CLZ32: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(to_u32(x).leading_zeros() as f64))
},
};
static COS: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.cos()))
},
};
static COSH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.cosh()))
},
};
static EXP: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.exp()))
},
};
static EXPM1: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.exp_m1()))
},
};
static FLOOR: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.floor()))
},
};
static FROUND: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x as f32 as f64))
},
};
static HYPOT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
Ok(Val::Number(x.hypot(y)))
@@ -263,7 +263,7 @@ static HYPOT: NativeFunction = NativeFunction {
};
static IMUL: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
Ok(Val::Number((to_u32(x) * to_u32(y)) as i32 as f64))
@@ -271,35 +271,35 @@ static IMUL: NativeFunction = NativeFunction {
};
static LOG: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.ln()))
},
};
static LOG10: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.log10()))
},
};
static LOG1P: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.ln_1p()))
},
};
static LOG2: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.log2()))
},
};
static MAX: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
Ok(Val::Number(x.max(y)))
@@ -307,7 +307,7 @@ static MAX: NativeFunction = NativeFunction {
};
static MIN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
Ok(Val::Number(x.min(y)))
@@ -315,7 +315,7 @@ static MIN: NativeFunction = NativeFunction {
};
static POW: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
Ok(Val::Number(x.powf(y)))
@@ -323,56 +323,56 @@ static POW: NativeFunction = NativeFunction {
};
static ROUND: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.round()))
},
};
static SIGN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.signum()))
},
};
static SIN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.sin()))
},
};
static SINH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.sinh()))
},
};
static SQRT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.sqrt()))
},
};
static TAN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.tan()))
},
};
static TANH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.tanh()))
},
};
static TRUNC: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
Ok(Val::Number(x.trunc()))
},

View File

@@ -2,6 +2,7 @@ use std::rc::Rc;
use num_bigint::BigInt;
use crate::native_function::ThisWrapper;
use crate::{builtins::type_error_builtin::to_type_error, type_error};
use crate::{
native_function::NativeFunction,
@@ -95,7 +96,7 @@ impl ValTrait for NumberBuiltin {
}
pub static IS_FINITE: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
let number = value.to_number();
Val::Bool(number.is_finite())
@@ -106,7 +107,7 @@ pub static IS_FINITE: NativeFunction = NativeFunction {
};
static IS_INTEGER: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let num = match params.get(0) {
Some(n) => n.to_number(),
None => return Ok(Val::Bool(false)),
@@ -120,7 +121,7 @@ static IS_INTEGER: NativeFunction = NativeFunction {
};
pub static IS_NAN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
let number = value.to_number();
Val::Bool(number.is_nan())
@@ -131,7 +132,7 @@ pub static IS_NAN: NativeFunction = NativeFunction {
};
static IS_SAFE_INTEGER: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let num = match params.get(0) {
Some(n) => n.to_number(),
None => return Ok(Val::Bool(false)),
@@ -148,7 +149,7 @@ static IS_SAFE_INTEGER: NativeFunction = NativeFunction {
};
pub static PARSE_FLOAT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
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();
@@ -163,7 +164,7 @@ pub static PARSE_FLOAT: NativeFunction = NativeFunction {
};
pub static PARSE_INT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
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 radix = params.get(1).and_then(|v| v.to_index()).unwrap_or(10);
@@ -196,7 +197,7 @@ pub static PARSE_INT: NativeFunction = NativeFunction {
},
};
fn to_number(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
fn to_number(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
Val::Number(value.to_number())
} else {

View File

@@ -2,6 +2,7 @@ use std::{collections::BTreeMap, rc::Rc};
use num_bigint::BigInt;
use crate::native_function::ThisWrapper;
use crate::{builtins::type_error_builtin::to_type_error, type_error};
use crate::{
format_val,
@@ -85,7 +86,7 @@ impl ValTrait for RangeErrorBuiltin {
}
}
pub fn to_range_error(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
pub fn to_range_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
Ok(Val::Object(Rc::new(VsObject {
string_map: BTreeMap::from([(
"message".to_string(),
@@ -113,21 +114,25 @@ fn make_range_error_prototype() -> Val {
}
static SET_MESSAGE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let message = match params.get(0) {
Some(param) => param.val_to_string(),
None => "".to_string(),
};
op_submov(this, format_val!("message"), format_val!("{}", message))?;
op_submov(
this.get_mut()?,
format_val!("message"),
format_val!("{}", message),
)?;
Ok(Val::Undefined)
},
};
static RANGE_ERROR_TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
let message = op_sub(this.clone(), format_val!("message"))?;
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
let message = op_sub(this.get().clone(), format_val!("message"))?;
Ok(format_val!("RangeError({})", message))
},
};
@@ -135,10 +140,10 @@ static RANGE_ERROR_TO_STRING: NativeFunction = NativeFunction {
#[macro_export]
macro_rules! range_error {
($fmt:expr $(, $($arg:expr),*)?) => {{
let mut this = Val::Undefined;
let formatted_string = format!($fmt $(, $($arg),*)?);
Err(to_range_error(
&mut this, vec![Val::String(Rc::new(formatted_string))]
ThisWrapper::new(true, &mut Val::Undefined),
vec![Val::String(Rc::new(formatted_string))],
).unwrap())
}};
}

View File

@@ -2,6 +2,7 @@ use std::rc::Rc;
use num_bigint::BigInt;
use crate::native_function::ThisWrapper;
use crate::{builtins::range_error_builtin::to_range_error, range_error};
use crate::{builtins::type_error_builtin::to_type_error, type_error};
use crate::{
@@ -88,7 +89,7 @@ impl ValTrait for StringBuiltin {
}
static FROM_CODE_POINT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let mut result = String::new();
for param in params {
@@ -106,7 +107,7 @@ static FROM_CODE_POINT: NativeFunction = NativeFunction {
},
};
fn to_string(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
fn to_string(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
Val::String(Rc::new(value.val_to_string()))
} else {

View File

@@ -2,6 +2,7 @@ use std::{collections::BTreeMap, rc::Rc};
use num_bigint::BigInt;
use crate::native_function::ThisWrapper;
use crate::type_error;
use crate::{
format_val,
@@ -85,7 +86,7 @@ impl ValTrait for TypeErrorBuiltin {
}
}
pub fn to_type_error(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
pub fn to_type_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
Ok(Val::Object(Rc::new(VsObject {
string_map: BTreeMap::from([(
"message".to_string(),
@@ -113,21 +114,25 @@ fn make_type_error_prototype() -> Val {
}
static SET_MESSAGE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let message = match params.get(0) {
Some(param) => param.val_to_string(),
None => "".to_string(),
};
op_submov(this, format_val!("message"), format_val!("{}", message))?;
op_submov(
this.get_mut()?,
format_val!("message"),
format_val!("{}", message),
)?;
Ok(Val::Undefined)
},
};
static TYPE_ERROR_TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
let message = op_sub(this.clone(), format_val!("message"))?;
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
let message = op_sub(this.get().clone(), format_val!("message"))?;
Ok(format_val!("TypeError({})", message))
},
};
@@ -135,10 +140,10 @@ static TYPE_ERROR_TO_STRING: NativeFunction = NativeFunction {
#[macro_export]
macro_rules! type_error {
($fmt:expr $(, $($arg:expr),*)?) => {{
let mut this = Val::Undefined;
let formatted_string = format!($fmt $(, $($arg),*)?);
Err(to_type_error(
&mut this, vec![Val::String(Rc::new(formatted_string))]
ThisWrapper::new(true, &mut Val::Undefined),
vec![Val::String(Rc::new(formatted_string))],
).unwrap())
}};
}

View File

@@ -5,6 +5,7 @@ use valuescript_common::InstructionByte;
use crate::builtins::type_error_builtin::to_type_error;
use crate::bytecode_decoder::BytecodeDecoder;
use crate::bytecode_decoder::BytecodeType;
use crate::native_function::ThisWrapper;
use crate::operations;
use crate::stack_frame::FrameStepOk;
use crate::stack_frame::FrameStepResult;
@@ -187,7 +188,10 @@ impl StackFrameTrait for BytecodeStackFrame {
return Ok(FrameStepOk::Push(new_frame));
}
LoadFunctionResult::NativeFunction(native_fn) => {
let res = native_fn(&mut Val::Undefined, self.decode_parameters())?;
let res = native_fn(
ThisWrapper::new(true, &mut Val::Undefined),
self.decode_parameters(),
)?;
match self.decoder.decode_register_index() {
Some(return_target) => {
@@ -316,10 +320,11 @@ impl StackFrameTrait for BytecodeStackFrame {
let params = self.decode_parameters();
let res = match &mut obj {
ThisArg::Register(reg_i) => {
native_fn(self.registers.get_mut(reg_i.clone()).unwrap(), params)?
}
ThisArg::Val(val) => native_fn(val, params)?,
ThisArg::Register(reg_i) => native_fn(
ThisWrapper::new(false, self.registers.get_mut(reg_i.clone()).unwrap()),
params,
)?,
ThisArg::Val(val) => native_fn(ThisWrapper::new(true, val), params)?,
};
match self.decoder.decode_register_index() {
@@ -389,7 +394,10 @@ impl StackFrameTrait for BytecodeStackFrame {
return Ok(FrameStepOk::Push(new_frame));
}
LoadFunctionResult::NativeFunction(native_fn) => {
native_fn(&mut instance, self.decode_parameters())?;
native_fn(
ThisWrapper::new(false, &mut instance),
self.decode_parameters(),
)?;
match self.decoder.decode_register_index() {
Some(target) => {

View File

@@ -3,6 +3,7 @@ use std::rc::Rc;
use num_bigint::BigInt;
use crate::format_err;
use crate::native_function::ThisWrapper;
use crate::stack_frame::StackFrame;
use crate::vs_array::VsArray;
use crate::vs_class::VsClass;

View File

@@ -9,8 +9,31 @@ use crate::vs_object::VsObject;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType};
use crate::{builtins::type_error_builtin::to_type_error, type_error};
pub struct ThisWrapper<'a> {
const_: bool,
this: &'a mut Val,
}
impl<'a> ThisWrapper<'a> {
pub fn new(const_: bool, this: &'a mut Val) -> ThisWrapper<'a> {
ThisWrapper { const_, this }
}
pub fn get(&self) -> &Val {
self.this
}
pub fn get_mut(&mut self) -> Result<&mut Val, Val> {
if self.const_ {
return type_error!("Cannot mutate this because it is const");
}
Ok(self.this)
}
}
pub struct NativeFunction {
pub fn_: fn(this: &mut Val, params: Vec<Val>) -> Result<Val, Val>,
pub fn_: fn(this: ThisWrapper, params: Vec<Val>) -> Result<Val, Val>,
}
impl ValTrait for NativeFunction {

View File

@@ -1,5 +1,6 @@
use std::rc::Rc;
use crate::native_function::ThisWrapper;
use crate::{builtins::range_error_builtin::to_range_error, range_error};
use crate::{
format_err, format_val,
@@ -21,8 +22,8 @@ pub fn op_sub_number(_number: f64, subscript: &Val) -> Val {
}
static TO_FIXED: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Number(number) => {
if number.is_infinite() {
return Ok(if number.is_sign_positive() {
@@ -34,7 +35,7 @@ static TO_FIXED: NativeFunction = NativeFunction {
let mut precision = match params.get(0) {
Some(p) => p.to_number(),
_ => return Ok(Val::String(Rc::new(this.val_to_string()))),
_ => return Ok(Val::String(Rc::new(this.get().val_to_string()))),
};
precision = f64::floor(precision);
@@ -51,8 +52,8 @@ static TO_FIXED: NativeFunction = NativeFunction {
};
static TO_EXPONENTIAL: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Number(number) => match params.get(0) {
Some(p) => {
let mut precision = p.to_number();
@@ -72,8 +73,8 @@ static TO_EXPONENTIAL: NativeFunction = NativeFunction {
};
static TODO_LOCALE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
match this.get() {
Val::Number(_number) => return format_err!("TODO: locale"),
_ => return format_err!("number indirection"),
}
@@ -81,14 +82,14 @@ static TODO_LOCALE: NativeFunction = NativeFunction {
};
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Number(_) => match params.get(0) {
Some(_) => {
return format_err!("TODO: toString with radix");
}
None => Val::String(Rc::new(this.val_to_string())),
None => Val::String(Rc::new(this.get().val_to_string())),
},
_ => return format_err!("number indirection"),
})
@@ -96,8 +97,8 @@ static TO_STRING: NativeFunction = NativeFunction {
};
static VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Number(number) => Val::Number(*number),
_ => return format_err!("number indirection"),
})

View File

@@ -7,6 +7,7 @@ use crate::bigint_methods::op_sub_bigint;
use crate::format_err;
use crate::format_val;
use crate::native_function::NativeFunction;
use crate::native_function::ThisWrapper;
use crate::number_methods::op_sub_number;
use crate::string_methods::op_sub_string;
use crate::vs_value::Val;
@@ -480,8 +481,8 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val
}
static BOOL_TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match &this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Bool(b) => Val::String(Rc::new(b.to_string())),
_ => return format_err!("bool indirection"),
})
@@ -489,8 +490,8 @@ static BOOL_TO_STRING: NativeFunction = NativeFunction {
};
static BOOL_VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match &this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Bool(b) => Val::Bool(*b),
_ => return format_err!("bool indirection"),
})

View File

@@ -3,7 +3,7 @@ use std::{rc::Rc, str::Chars};
use crate::{
format_err,
helpers::{to_wrapping_index, to_wrapping_index_clamped},
native_function::NativeFunction,
native_function::{NativeFunction, ThisWrapper},
vs_array::VsArray,
vs_value::Val,
ValTrait,
@@ -85,8 +85,8 @@ pub fn get_string_method(method: &str) -> Val {
}
static AT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -106,8 +106,8 @@ static AT: NativeFunction = NativeFunction {
};
static CODE_POINT_AT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -130,8 +130,8 @@ static CODE_POINT_AT: NativeFunction = NativeFunction {
};
static CONCAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let mut result = string_data.as_str().to_string();
@@ -147,8 +147,8 @@ static CONCAT: NativeFunction = NativeFunction {
};
static ENDS_WITH: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -190,8 +190,8 @@ static ENDS_WITH: NativeFunction = NativeFunction {
};
static INCLUDES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -222,8 +222,8 @@ static INCLUDES: NativeFunction = NativeFunction {
};
static INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -254,8 +254,8 @@ static INDEX_OF: NativeFunction = NativeFunction {
};
static LAST_INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -286,9 +286,9 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
};
static TODO_LOCALE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
match this.get() {
Val::String(_string_data) => {
return format_err!("TODO: locale");
}
@@ -298,9 +298,9 @@ static TODO_LOCALE: NativeFunction = NativeFunction {
};
static TODO_REGEXES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
match this.get() {
Val::String(_string_data) => {
return format_err!("TODO: regexes");
}
@@ -310,9 +310,9 @@ static TODO_REGEXES: NativeFunction = NativeFunction {
};
static NORMALIZE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
match this.get() {
Val::String(_string_data) => {
// Consider https://docs.rs/unicode-normalization/latest/unicode_normalization/
return format_err!("TODO: normalize");
@@ -324,8 +324,8 @@ static NORMALIZE: NativeFunction = NativeFunction {
// TODO: JS has some locale-specific behavior, not sure yet how we should deal with that
static PAD_END: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let target_length = match params.get(0) {
Some(p) => match p.to_index() {
@@ -378,8 +378,8 @@ static PAD_END: NativeFunction = NativeFunction {
// TODO: JS has some locale-specific behavior, not sure yet how we should deal with that
static PAD_START: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let target_length = match params.get(0) {
Some(p) => match p.to_index() {
@@ -433,8 +433,8 @@ static PAD_START: NativeFunction = NativeFunction {
};
static REPEAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let count = match params.get(0) {
Some(p) => match p.to_index() {
@@ -458,8 +458,8 @@ static REPEAT: NativeFunction = NativeFunction {
};
static SLICE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -492,8 +492,8 @@ static SLICE: NativeFunction = NativeFunction {
};
static SPLIT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let separator = match params.get(0) {
Some(s) => s.val_to_string(), // TODO: Regexes
@@ -558,8 +558,8 @@ static SPLIT: NativeFunction = NativeFunction {
};
static STARTS_WITH: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -599,8 +599,8 @@ static STARTS_WITH: NativeFunction = NativeFunction {
};
static SUBSTRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -642,8 +642,8 @@ static SUBSTRING: NativeFunction = NativeFunction {
};
static TO_LOWER_CASE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let lowercased_string = string_data.to_lowercase();
Val::String(Rc::new(lowercased_string))
@@ -654,8 +654,8 @@ static TO_LOWER_CASE: NativeFunction = NativeFunction {
};
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => Val::String(string_data.clone()),
_ => return format_err!("string indirection"),
})
@@ -663,8 +663,8 @@ static TO_STRING: NativeFunction = NativeFunction {
};
static TO_UPPER_CASE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let uppercased_string = string_data.to_uppercase();
Val::String(Rc::new(uppercased_string))
@@ -675,8 +675,8 @@ static TO_UPPER_CASE: NativeFunction = NativeFunction {
};
static TRIM: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let trimmed_string = string_data.trim();
Val::String(Rc::new(trimmed_string.to_owned()))
@@ -687,8 +687,8 @@ static TRIM: NativeFunction = NativeFunction {
};
static TRIM_END: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let trimmed_string = string_data.trim_end();
Val::String(Rc::new(trimmed_string.to_owned()))
@@ -699,8 +699,8 @@ static TRIM_END: NativeFunction = NativeFunction {
};
static TRIM_START: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => {
let trimmed_string = string_data.trim_start();
Val::String(Rc::new(trimmed_string.to_owned()))
@@ -711,8 +711,8 @@ static TRIM_START: NativeFunction = NativeFunction {
};
static VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::String(string_data) => Val::String(string_data.clone()),
_ => return format_err!("string indirection"),
})

View File

@@ -1,10 +1,14 @@
use std::rc::Rc;
use crate::{format_err, native_function::NativeFunction, vs_value::Val};
use crate::{
format_err,
native_function::{NativeFunction, ThisWrapper},
vs_value::Val,
};
pub static TODO: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
match this.get() {
Val::Number(_number) => return format_err!("TODO: locale"),
_ => return format_err!("number indirection"),
}

View File

@@ -10,7 +10,7 @@ use crate::array_higher_functions::{
};
use crate::format_err;
use crate::helpers::{to_wrapping_index, to_wrapping_index_clamped};
use crate::native_function::NativeFunction;
use crate::native_function::{NativeFunction, ThisWrapper};
use crate::operations::op_triple_eq_impl;
use crate::vs_class::VsClass;
use crate::vs_object::VsObject;
@@ -149,8 +149,8 @@ impl ValTrait for ArrayPrototype {
}
static AT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(array_data) => match to_wrapping_index(params.get(0), array_data.elements.len()) {
None => Val::Undefined,
Some(i) => array_data.elements[i].clone(),
@@ -161,8 +161,8 @@ static AT: NativeFunction = NativeFunction {
};
static CONCAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(array_data) => {
let mut new_array = array_data.as_ref().clone();
@@ -187,7 +187,9 @@ static CONCAT: NativeFunction = NativeFunction {
};
static COPY_WITHIN: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
@@ -259,8 +261,8 @@ static COPY_WITHIN: NativeFunction = NativeFunction {
};
static ENTRIES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
match this {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
match this.get() {
Val::Array(_array_data) => return format_err!("TODO: iterators"),
_ => return format_err!("array indirection"),
};
@@ -268,7 +270,9 @@ static ENTRIES: NativeFunction = NativeFunction {
};
static FILL: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
@@ -298,8 +302,8 @@ static FILL: NativeFunction = NativeFunction {
};
static FLAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(array_data) => {
if params.len() > 0 {
return format_err!("TODO: .flat depth parameter");
@@ -328,8 +332,8 @@ static FLAT: NativeFunction = NativeFunction {
};
static INCLUDES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(array_data) => {
let search_param = params.get(0).unwrap_or(&Val::Undefined).clone();
@@ -351,8 +355,8 @@ static INCLUDES: NativeFunction = NativeFunction {
};
static INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(array_data) => {
let search_param = params.get(0).unwrap_or(&Val::Undefined).clone();
@@ -374,8 +378,8 @@ static INDEX_OF: NativeFunction = NativeFunction {
};
static JOIN: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(vals) => {
if vals.elements.len() == 0 {
return Ok(Val::String(Rc::new("".to_string())));
@@ -414,9 +418,9 @@ static JOIN: NativeFunction = NativeFunction {
};
static KEYS: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
match this.get() {
Val::Array(_array_data) => {
return format_err!("TODO: KEYS");
}
@@ -426,8 +430,8 @@ static KEYS: NativeFunction = NativeFunction {
};
static LAST_INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(array_data) => {
let search_param = params.get(0).unwrap_or(&Val::Undefined).clone();
@@ -449,7 +453,9 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
};
static POP: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
if array_data.elements.len() == 0 {
@@ -473,7 +479,9 @@ static POP: NativeFunction = NativeFunction {
};
static PUSH: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
@@ -490,7 +498,9 @@ static PUSH: NativeFunction = NativeFunction {
};
static REVERSE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
if array_data.elements.len() == 0 {
@@ -517,7 +527,9 @@ static REVERSE: NativeFunction = NativeFunction {
};
static SHIFT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
if array_data.elements.len() == 0 {
@@ -534,8 +546,8 @@ static SHIFT: NativeFunction = NativeFunction {
};
static SLICE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this.get() {
Val::Array(array_data) => {
let mut new_elems = Vec::<Val>::new();
@@ -561,7 +573,9 @@ static SLICE: NativeFunction = NativeFunction {
};
static SPLICE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
@@ -638,9 +652,9 @@ static SPLICE: NativeFunction = NativeFunction {
};
static TO_LOCALE_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
match this.get() {
Val::Array(_array_data) => {
return format_err!("TODO: TO_LOCALE_STRING");
}
@@ -651,13 +665,15 @@ static TO_LOCALE_STRING: NativeFunction = NativeFunction {
// TODO: Share this? (JS doesn't?)
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(Val::String(Rc::new(this.val_to_string())))
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
Ok(Val::String(Rc::new(this.get().val_to_string())))
},
};
static UNSHIFT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
fn_: |mut this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
let this = this.get_mut()?;
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
@@ -677,9 +693,9 @@ static UNSHIFT: NativeFunction = NativeFunction {
};
static VALUES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
match this.get() {
Val::Array(_array_data) => {
return format_err!("TODO: VALUES");
}

View File

@@ -7,6 +7,7 @@ use num_traits::cast::ToPrimitive;
use num_traits::Zero;
use crate::format_val;
use crate::native_function::ThisWrapper;
use crate::operations::{op_sub, op_submov};
use crate::stack_frame::StackFrame;
use crate::vs_array::VsArray;
@@ -48,7 +49,7 @@ pub enum VsType {
pub enum LoadFunctionResult {
NotAFunction,
StackFrame(StackFrame),
NativeFunction(fn(this: &mut Val, params: Vec<Val>) -> Result<Val, Val>),
NativeFunction(fn(this: ThisWrapper, params: Vec<Val>) -> Result<Val, Val>),
}
pub trait ValTrait {