Make NativeFunction use exceptions (panics not converted though)

This commit is contained in:
Andrew Morris
2023-03-21 12:07:04 +11:00
parent 79534a8d38
commit a59b577cd3
19 changed files with 335 additions and 323 deletions

View File

@@ -91,7 +91,7 @@ impl StackFrameTrait for ArrayMappingFrame {
Val::Number(array_i as f64),
Val::Array(array_data.clone()),
],
),
)?,
) {
None => Ok(FrameStepOk::Continue),
Some(val) => Ok(FrameStepOk::Pop(CallResult {

View File

@@ -77,7 +77,7 @@ impl StackFrameTrait for ReduceFrame {
Val::Number(array_i as f64),
Val::Array(array_data.clone()),
],
));
)?);
return Ok(FrameStepOk::Continue);
}

View File

@@ -99,7 +99,7 @@ impl StackFrameTrait for ReduceRightFrame {
Val::Number(array_i as f64),
Val::Array(array_data.clone()),
],
));
)?);
return Ok(FrameStepOk::Continue);
}

View File

@@ -270,7 +270,7 @@ impl StackFrameTrait for SortFrame {
std::panic!("Not implemented: exception: 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(&mut Val::Undefined, vec![left, right])?.to_number();
let should_swap = match res.is_nan() {
true => false,

View File

@@ -18,8 +18,8 @@ pub fn op_sub_bigint(_bigint: &BigInt, subscript: &Val) -> Val {
}
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::BigInt(_) => match params.get(0) {
Some(_) => {
panic!("TODO: toString with radix");
@@ -28,15 +28,15 @@ static TO_STRING: NativeFunction = NativeFunction {
None => Val::String(Rc::new(this.val_to_string())),
},
_ => panic!("TODO: exceptions/bigint indirection"),
}
})
},
};
static VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::BigInt(bigint) => Val::BigInt(bigint.clone()),
_ => panic!("TODO: exceptions/bigint indirection"),
}
})
},
};

View File

@@ -84,19 +84,19 @@ impl ValTrait for ArrayBuiltin {
}
static IS_ARRAY: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
match params.get(0) {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match params.get(0) {
None => Val::Bool(false),
Some(p) => match p.as_array_data() {
None => Val::Bool(false),
Some(_) => Val::Bool(true),
},
}
})
},
};
static FROM: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let first_param = match params.get(0) {
None => panic!("TODO: Exceptions (TypeError: undefined is not iterable)"),
Some(p) => p,
@@ -106,7 +106,7 @@ static FROM: NativeFunction = NativeFunction {
panic!("TODO: Using Array.from with a map function");
}
match first_param {
Ok(match first_param {
Val::Array(arr) => Val::Array(arr.clone()),
Val::String(s) => Val::Array(Rc::new(VsArray::from(
s.chars()
@@ -127,7 +127,7 @@ static FROM: NativeFunction = NativeFunction {
.to_number();
if len.is_sign_negative() || len.is_nan() {
return Val::Array(Rc::new(VsArray::new()));
return Ok(Val::Array(Rc::new(VsArray::new())));
}
if len.is_infinite() {
@@ -150,20 +150,22 @@ static FROM: NativeFunction = NativeFunction {
Val::Array(Rc::new(VsArray::from(arr)))
}
}
})
},
};
static OF: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val { Val::Array(Rc::new(VsArray::from(params))) },
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(Val::Array(Rc::new(VsArray::from(params))))
},
};
fn to_array(_: &mut Val, params: Vec<Val>) -> Val {
fn to_array(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
if params.len() != 1 {
return Val::Array(Rc::new(VsArray::from(params)));
return Ok(Val::Array(Rc::new(VsArray::from(params))));
}
match params[0] {
Ok(match params[0] {
Val::Number(number) => {
if number.is_sign_negative() || number != number.floor() {
panic!("TODO: Exceptions (RangeError: Invalid array length)")
@@ -180,5 +182,5 @@ fn to_array(_: &mut Val, params: Vec<Val>) -> Val {
Val::Array(Rc::new(VsArray::from(arr)))
}
_ => Val::Array(Rc::new(VsArray::from(params))),
}
})
}

View File

@@ -76,10 +76,10 @@ impl ValTrait for BooleanBuiltin {
}
}
fn to_boolean(_: &mut Val, params: Vec<Val>) -> Val {
if let Some(value) = params.get(0) {
fn to_boolean(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
Val::Bool(value.is_truthy())
} else {
Val::Bool(false)
}
})
}

View File

@@ -81,11 +81,11 @@ impl ValTrait for DebugBuiltin {
}
static LOG: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
for p in params {
println!("Debug.log: {}", p);
}
return Val::Undefined;
Ok(Val::Undefined)
},
};

View File

@@ -133,246 +133,246 @@ fn param_to_number(param: Option<&Val>) -> f64 {
}
static ABS: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.abs());
Ok(Val::Number(x.abs()))
},
};
static ACOS: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.acos());
Ok(Val::Number(x.acos()))
},
};
static ACOSH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.acosh());
Ok(Val::Number(x.acosh()))
},
};
static ASIN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.asin());
Ok(Val::Number(x.asin()))
},
};
static ASINH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.sinh());
Ok(Val::Number(x.sinh()))
},
};
static ATAN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.atan());
Ok(Val::Number(x.atan()))
},
};
static ATAN2: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
return Val::Number(x.atan2(y));
Ok(Val::Number(x.atan2(y)))
},
};
static ATANH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.atanh());
Ok(Val::Number(x.atanh()))
},
};
static CBRT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.cbrt());
Ok(Val::Number(x.cbrt()))
},
};
static CEIL: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.ceil());
Ok(Val::Number(x.ceil()))
},
};
static CLZ32: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(to_u32(x).leading_zeros() as f64);
Ok(Val::Number(to_u32(x).leading_zeros() as f64))
},
};
static COS: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.cos());
Ok(Val::Number(x.cos()))
},
};
static COSH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.cosh());
Ok(Val::Number(x.cosh()))
},
};
static EXP: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.exp());
Ok(Val::Number(x.exp()))
},
};
static EXPM1: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.exp_m1());
Ok(Val::Number(x.exp_m1()))
},
};
static FLOOR: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.floor());
Ok(Val::Number(x.floor()))
},
};
static FROUND: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x as f32 as f64);
Ok(Val::Number(x as f32 as f64))
},
};
static HYPOT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
return Val::Number(x.hypot(y));
Ok(Val::Number(x.hypot(y)))
},
};
static IMUL: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
return Val::Number((to_u32(x) * to_u32(y)) as i32 as f64);
Ok(Val::Number((to_u32(x) * to_u32(y)) as i32 as f64))
},
};
static LOG: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.ln());
Ok(Val::Number(x.ln()))
},
};
static LOG10: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.log10());
Ok(Val::Number(x.log10()))
},
};
static LOG1P: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.ln_1p());
Ok(Val::Number(x.ln_1p()))
},
};
static LOG2: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.log2());
Ok(Val::Number(x.log2()))
},
};
static MAX: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
return Val::Number(x.max(y));
Ok(Val::Number(x.max(y)))
},
};
static MIN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
return Val::Number(x.min(y));
Ok(Val::Number(x.min(y)))
},
};
static POW: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
let y = param_to_number(params.get(1));
return Val::Number(x.powf(y));
Ok(Val::Number(x.powf(y)))
},
};
static ROUND: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.round());
Ok(Val::Number(x.round()))
},
};
static SIGN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.signum());
Ok(Val::Number(x.signum()))
},
};
static SIN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.sin());
Ok(Val::Number(x.sin()))
},
};
static SINH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.sinh());
Ok(Val::Number(x.sinh()))
},
};
static SQRT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.sqrt());
Ok(Val::Number(x.sqrt()))
},
};
static TAN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.tan());
Ok(Val::Number(x.tan()))
},
};
static TANH: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.tanh());
Ok(Val::Number(x.tanh()))
},
};
static TRUNC: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let x = param_to_number(params.get(0));
return Val::Number(x.trunc());
Ok(Val::Number(x.trunc()))
},
};

View File

@@ -94,46 +94,46 @@ impl ValTrait for NumberBuiltin {
}
pub static IS_FINITE: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
if let Some(value) = params.get(0) {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
let number = value.to_number();
Val::Bool(number.is_finite())
} else {
Val::Bool(false)
}
})
},
};
static IS_INTEGER: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let num = match params.get(0) {
Some(n) => n.to_number(),
None => return Val::Bool(false),
None => return Ok(Val::Bool(false)),
};
let is_finite = num.is_finite();
let is_integer = num.floor() == num;
Val::Bool(is_finite && is_integer)
Ok(Val::Bool(is_finite && is_integer))
},
};
pub static IS_NAN: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
if let Some(value) = params.get(0) {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
let number = value.to_number();
Val::Bool(number.is_nan())
} else {
Val::Bool(false)
}
})
},
};
static IS_SAFE_INTEGER: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let num = match params.get(0) {
Some(n) => n.to_number(),
None => return Val::Bool(false),
None => return Ok(Val::Bool(false)),
};
let is_finite = num.is_finite();
@@ -142,13 +142,13 @@ static IS_SAFE_INTEGER: NativeFunction = NativeFunction {
let max_safe_integer = 2f64.powi(53) - 1f64;
let in_safe_range = min_safe_integer <= num && num <= max_safe_integer;
Val::Bool(is_finite && is_integer && in_safe_range)
Ok(Val::Bool(is_finite && is_integer && in_safe_range))
},
};
pub static PARSE_FLOAT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
if let Some(value) = params.get(0) {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
let string_value = value.val_to_string().trim().to_string();
match string_value.parse::<f64>() {
@@ -157,18 +157,18 @@ pub static PARSE_FLOAT: NativeFunction = NativeFunction {
}
} else {
Val::Number(core::f64::NAN)
}
})
},
};
pub static PARSE_INT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
if let Some(value) = params.get(0) {
fn_: |_this: &mut Val, 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);
if radix < 2 || radix > 36 {
return Val::Number(core::f64::NAN);
return Ok(Val::Number(core::f64::NAN));
}
let (is_negative, string_value) = if string_value.starts_with('-') {
@@ -191,14 +191,14 @@ pub static PARSE_INT: NativeFunction = NativeFunction {
}
} else {
Val::Number(core::f64::NAN)
}
})
},
};
fn to_number(_: &mut Val, params: Vec<Val>) -> Val {
if let Some(value) = params.get(0) {
fn to_number(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
Val::Number(value.to_number())
} else {
Val::Number(0.0)
}
})
}

View File

@@ -86,7 +86,7 @@ impl ValTrait for StringBuiltin {
}
static FROM_CODE_POINT: NativeFunction = NativeFunction {
fn_: |_this: &mut Val, params: Vec<Val>| -> Val {
fn_: |_this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
let mut result = String::new();
for param in params {
@@ -100,14 +100,14 @@ static FROM_CODE_POINT: NativeFunction = NativeFunction {
result.push(char);
}
Val::String(Rc::new(result))
Ok(Val::String(Rc::new(result)))
},
};
fn to_string(_: &mut Val, params: Vec<Val>) -> Val {
if let Some(value) = params.get(0) {
fn to_string(_: &mut Val, params: Vec<Val>) -> Result<Val, Val> {
Ok(if let Some(value) = params.get(0) {
Val::String(Rc::new(value.val_to_string()))
} else {
Val::String(Rc::new("".to_string()))
}
})
}

View File

@@ -178,7 +178,7 @@ 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(&mut Val::Undefined, self.decode_parameters())?;
match self.decoder.decode_register_index() {
Some(return_target) => {
@@ -308,9 +308,9 @@ impl StackFrameTrait for BytecodeStackFrame {
let res = match &mut obj {
ThisArg::Register(reg_i) => {
native_fn(self.registers.get_mut(reg_i.clone()).unwrap(), params)
native_fn(self.registers.get_mut(reg_i.clone()).unwrap(), params)?
}
ThisArg::Val(val) => native_fn(val, params),
ThisArg::Val(val) => native_fn(val, params)?,
};
match self.decoder.decode_register_index() {
@@ -379,7 +379,7 @@ impl StackFrameTrait for BytecodeStackFrame {
return Ok(FrameStepOk::Push(new_frame));
}
LoadFunctionResult::NativeFunction(native_fn) => {
native_fn(&mut instance, self.decode_parameters());
native_fn(&mut instance, self.decode_parameters())?;
match self.decoder.decode_register_index() {
Some(target) => {

View File

@@ -8,7 +8,7 @@ use super::vs_object::VsObject;
use super::vs_value::{LoadFunctionResult, Val, ValTrait, VsType};
pub struct NativeFunction {
pub fn_: fn(this: &mut Val, params: Vec<Val>) -> Val,
pub fn_: fn(this: &mut Val, params: Vec<Val>) -> Result<Val, Val>,
}
impl ValTrait for NativeFunction {

View File

@@ -19,20 +19,20 @@ pub fn op_sub_number(_number: f64, subscript: &Val) -> Val {
}
static TO_FIXED: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
match this {
Val::Number(number) => {
if number.is_infinite() {
return if number.is_sign_positive() {
return Ok(if number.is_sign_positive() {
Val::String(Rc::new("Infinity".to_string()))
} else {
Val::String(Rc::new("-Infinity".to_string()))
};
});
}
let mut precision = match params.get(0) {
Some(p) => p.to_number(),
_ => return Val::String(Rc::new(this.val_to_string())),
_ => return Ok(Val::String(Rc::new(this.val_to_string()))),
};
precision = f64::floor(precision);
@@ -41,7 +41,10 @@ static TO_FIXED: NativeFunction = NativeFunction {
panic!("TODO: exceptions: RangeError: precision must be between 1 and 100");
}
Val::String(Rc::new(format!("{:.*}", precision as usize, number)))
Ok(Val::String(Rc::new(format!(
"{:.*}",
precision as usize, number
))))
}
_ => panic!("TODO: exceptions/number indirection"),
}
@@ -49,7 +52,7 @@ static TO_FIXED: NativeFunction = NativeFunction {
};
static TO_EXPONENTIAL: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
match this {
Val::Number(number) => match params.get(0) {
Some(p) => {
@@ -60,9 +63,9 @@ static TO_EXPONENTIAL: NativeFunction = NativeFunction {
panic!("TODO: exceptions: RangeError: precision must be between 0 and 100");
}
format_exponential(*number, Some(precision as usize))
Ok(format_exponential(*number, Some(precision as usize)))
}
None => format_exponential(*number, None),
None => Ok(format_exponential(*number, None)),
},
_ => panic!("TODO: exceptions/number indirection"),
}
@@ -70,7 +73,7 @@ static TO_EXPONENTIAL: NativeFunction = NativeFunction {
};
static TODO_LOCALE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
match this {
Val::Number(_number) => panic!("TODO: locale"),
_ => panic!("TODO: exceptions/number indirection"),
@@ -79,8 +82,8 @@ static TODO_LOCALE: NativeFunction = NativeFunction {
};
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Number(_) => match params.get(0) {
Some(_) => {
panic!("TODO: toString with radix");
@@ -89,16 +92,16 @@ static TO_STRING: NativeFunction = NativeFunction {
None => Val::String(Rc::new(this.val_to_string())),
},
_ => panic!("TODO: exceptions/number indirection"),
}
})
},
};
static VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Number(number) => Val::Number(*number),
_ => panic!("TODO: exceptions/number indirection"),
}
})
},
};

View File

@@ -497,19 +497,19 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val
}
static BOOL_TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _args: Vec<Val>| -> Val {
match &this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match &this {
Val::Bool(b) => Val::String(Rc::new(b.to_string())),
_ => std::panic!("TODO: Exceptions/bool indirection"),
}
})
},
};
static BOOL_VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _args: Vec<Val>| -> Val {
match &this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match &this {
Val::Bool(b) => Val::Bool(*b),
_ => std::panic!("TODO: Exceptions/bool indirection"),
}
})
},
};

View File

@@ -84,13 +84,13 @@ pub fn get_string_method(method: &str) -> Val {
}
static AT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
let index = match to_wrapping_index(params.get(0), string_bytes.len()) {
None => return Val::Undefined,
None => return Ok(Val::Undefined),
Some(i) => i,
};
@@ -100,22 +100,22 @@ static AT: NativeFunction = NativeFunction {
}
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static CODE_POINT_AT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
let index = match params.get(0) {
Some(i) => match i.to_index() {
None => return Val::Undefined,
None => return Ok(Val::Undefined),
Some(i) => i,
},
_ => return Val::Undefined,
_ => return Ok(Val::Undefined),
};
match code_point_at(string_bytes, string_bytes.len(), index) {
@@ -124,13 +124,13 @@ static CODE_POINT_AT: NativeFunction = NativeFunction {
}
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static CONCAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let mut result = string_data.as_str().to_string();
@@ -141,25 +141,25 @@ static CONCAT: NativeFunction = NativeFunction {
Val::String(Rc::new(result))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static ENDS_WITH: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
let search_string = match params.get(0) {
Some(s) => s.val_to_string(),
_ => return Val::Bool(false),
_ => return Ok(Val::Bool(false)),
};
let end_pos = match params.get(1) {
Some(p) => match p.to_index() {
// FIXME: Using to_index for end_pos is not quite right (eg -1 should be 0)
None => return Val::Bool(false),
None => return Ok(Val::Bool(false)),
Some(i) => std::cmp::min(i, string_bytes.len()),
},
_ => string_bytes.len(),
@@ -170,33 +170,33 @@ static ENDS_WITH: NativeFunction = NativeFunction {
let search_length = search_bytes.len();
if search_length > end_pos {
return Val::Bool(false);
return Ok(Val::Bool(false));
}
let start_index = end_pos - search_length;
for i in 0..search_length {
if string_bytes[start_index + i] != search_bytes[i] {
return Val::Bool(false);
return Ok(Val::Bool(false));
}
}
Val::Bool(true)
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static INCLUDES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
let search_string = match params.get(0) {
Some(s) => s.val_to_string(),
_ => return Val::Bool(false),
_ => return Ok(Val::Bool(false)),
};
let search_bytes = search_string.as_bytes();
@@ -205,7 +205,7 @@ static INCLUDES: NativeFunction = NativeFunction {
Some(p) => match p.to_index() {
// FIXME: to_index isn't quite right here
Some(i) => i,
None => return Val::Bool(false),
None => return Ok(Val::Bool(false)),
},
_ => 0,
};
@@ -216,19 +216,19 @@ static INCLUDES: NativeFunction = NativeFunction {
}
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
let search_string = match params.get(0) {
Some(s) => s.val_to_string(),
_ => return Val::Number(-1.0),
_ => return Ok(Val::Number(-1.0)),
};
let search_bytes = search_string.as_bytes();
@@ -237,7 +237,7 @@ static INDEX_OF: NativeFunction = NativeFunction {
Some(p) => match p.to_index() {
// FIXME: to_index isn't quite right here
Some(i) => i,
None => return Val::Number(-1.0),
None => return Ok(Val::Number(-1.0)),
},
_ => 0,
};
@@ -248,19 +248,19 @@ static INDEX_OF: NativeFunction = NativeFunction {
}
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static LAST_INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
let search_string = match params.get(0) {
Some(s) => s.val_to_string(),
_ => return Val::Number(-1.0),
_ => return Ok(Val::Number(-1.0)),
};
let search_bytes = search_string.as_bytes();
@@ -269,7 +269,7 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
Some(p) => match p.to_index() {
// FIXME: to_index isn't quite right here
Some(i) => i,
None => return Val::Number(-1.0),
None => return Ok(Val::Number(-1.0)),
},
_ => 0,
};
@@ -280,12 +280,13 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
}
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static TODO_LOCALE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
Val::String(_string_data) => {
panic!("TODO: locale");
@@ -296,7 +297,8 @@ static TODO_LOCALE: NativeFunction = NativeFunction {
};
static TODO_REGEXES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
Val::String(_string_data) => {
panic!("TODO: regexes");
@@ -307,7 +309,8 @@ static TODO_REGEXES: NativeFunction = NativeFunction {
};
static NORMALIZE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
Val::String(_string_data) => {
// Consider https://docs.rs/unicode-normalization/latest/unicode_normalization/
@@ -320,19 +323,19 @@ 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>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let target_length = match params.get(0) {
Some(p) => match p.to_index() {
Some(i) => i,
None => return Val::String(string_data.clone()),
None => return Ok(Val::String(string_data.clone())),
},
_ => return Val::String(string_data.clone()),
_ => return Ok(Val::String(string_data.clone())),
};
if target_length <= string_data.as_bytes().len() {
return Val::String(string_data.clone());
return Ok(Val::String(string_data.clone()));
}
let mut string = string_data.to_string();
@@ -368,25 +371,25 @@ static PAD_END: NativeFunction = NativeFunction {
Val::String(Rc::new(string))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
// 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>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let target_length = match params.get(0) {
Some(p) => match p.to_index() {
Some(i) => i,
None => return Val::String(string_data.clone()),
None => return Ok(Val::String(string_data.clone())),
},
_ => return Val::String(string_data.clone()),
_ => return Ok(Val::String(string_data.clone())),
};
if target_length <= string_data.as_bytes().len() {
return Val::String(string_data.clone());
return Ok(Val::String(string_data.clone()));
}
let pad_string = match params.get(1) {
@@ -424,20 +427,20 @@ static PAD_START: NativeFunction = NativeFunction {
Val::String(Rc::new(prefix))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static REPEAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let count = match params.get(0) {
Some(p) => match p.to_index() {
Some(i) => i,
None => return Val::String(string_data.clone()),
None => return Ok(Val::String(string_data.clone())),
},
_ => return Val::String(string_data.clone()),
_ => return Ok(Val::String(string_data.clone())),
};
let mut result = String::new();
@@ -449,13 +452,13 @@ static REPEAT: NativeFunction = NativeFunction {
Val::String(Rc::new(result))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static SLICE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -483,17 +486,17 @@ static SLICE: NativeFunction = NativeFunction {
Val::String(Rc::new(new_string))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static SPLIT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let separator = match params.get(0) {
Some(s) => s.val_to_string(), // TODO: Regexes
None => return Val::String(string_data.clone()),
None => return Ok(Val::String(string_data.clone())),
};
let limit = match params.get(1) {
@@ -508,7 +511,7 @@ static SPLIT: NativeFunction = NativeFunction {
let mut result = Vec::<Val>::new();
if limit == 0 {
return Val::Array(Rc::new(VsArray::from(result)));
return Ok(Val::Array(Rc::new(VsArray::from(result))));
}
if separator.is_empty() {
@@ -520,7 +523,7 @@ static SPLIT: NativeFunction = NativeFunction {
}
}
return Val::Array(Rc::new(VsArray::from(result)));
return Ok(Val::Array(Rc::new(VsArray::from(result))));
}
let mut part = String::new();
@@ -549,25 +552,25 @@ static SPLIT: NativeFunction = NativeFunction {
Val::Array(Rc::new(VsArray::from(result)))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static STARTS_WITH: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
let search_string = match params.get(0) {
Some(s) => s.val_to_string(),
_ => return Val::Bool(false),
_ => return Ok(Val::Bool(false)),
};
let pos = match params.get(1) {
Some(p) => match p.to_index() {
// FIXME: Using to_index is not quite right
None => return Val::Bool(false),
None => return Ok(Val::Bool(false)),
Some(i) => std::cmp::min(i, string_bytes.len()),
},
_ => 0,
@@ -578,25 +581,25 @@ static STARTS_WITH: NativeFunction = NativeFunction {
let search_length = search_bytes.len();
if search_length > string_bytes.len() - pos {
return Val::Bool(false);
return Ok(Val::Bool(false));
}
for i in 0..search_length {
if string_bytes[pos + i] != search_bytes[i] {
return Val::Bool(false);
return Ok(Val::Bool(false));
}
}
Val::Bool(true)
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static SUBSTRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let string_bytes = string_data.as_bytes();
@@ -633,85 +636,85 @@ static SUBSTRING: NativeFunction = NativeFunction {
Val::String(Rc::new(new_string))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static TO_LOWER_CASE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let lowercased_string = string_data.to_lowercase();
Val::String(Rc::new(lowercased_string))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => Val::String(string_data.clone()),
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static TO_UPPER_CASE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let uppercased_string = string_data.to_uppercase();
Val::String(Rc::new(uppercased_string))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static TRIM: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let trimmed_string = string_data.trim();
Val::String(Rc::new(trimmed_string.to_owned()))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static TRIM_END: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let trimmed_string = string_data.trim_end();
Val::String(Rc::new(trimmed_string.to_owned()))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static TRIM_START: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => {
let trimmed_string = string_data.trim_start();
Val::String(Rc::new(trimmed_string.to_owned()))
}
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};
static VALUE_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::String(string_data) => Val::String(string_data.clone()),
_ => panic!("TODO: exceptions/string indirection"),
}
})
},
};

View File

@@ -1,7 +1,7 @@
use crate::{native_function::NativeFunction, vs_value::Val};
pub static TODO: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
match this {
Val::Number(_number) => panic!("TODO: locale"),
_ => panic!("TODO: exceptions/number indirection"),

View File

@@ -153,20 +153,20 @@ impl ValTrait for ArrayPrototype {
}
static AT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
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(),
},
_ => std::panic!("TODO: Exceptions/array indirection"),
}
})
},
};
static CONCAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let mut new_array = array_data.as_ref().clone();
@@ -183,16 +183,16 @@ static CONCAT: NativeFunction = NativeFunction {
}
}
return Val::Array(Rc::new(new_array));
Val::Array(Rc::new(new_array))
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static COPY_WITHIN: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
let ulen = array_data_mut.elements.len();
@@ -222,7 +222,7 @@ static COPY_WITHIN: NativeFunction = NativeFunction {
let copy_len = end - start;
if copy_len <= 0 {
return this.clone();
return Ok(this.clone());
}
if target <= start || target >= end {
@@ -255,15 +255,15 @@ static COPY_WITHIN: NativeFunction = NativeFunction {
}
}
return this.clone();
this.clone()
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static ENTRIES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
match this {
Val::Array(_array_data) => {
std::panic!("Not implemented: ENTRIES");
@@ -274,8 +274,8 @@ static ENTRIES: NativeFunction = NativeFunction {
};
static FILL: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
let len = array_data_mut.elements.len();
@@ -296,16 +296,16 @@ static FILL: NativeFunction = NativeFunction {
array_data_mut.elements[i as usize] = fill_val.clone();
}
return this.clone();
this.clone()
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static FLAT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
if params.len() > 0 {
std::panic!("Not implemented: .flat depth parameter");
@@ -326,16 +326,16 @@ static FLAT: NativeFunction = NativeFunction {
}
}
return Val::Array(Rc::new(VsArray::from(new_elems)));
Val::Array(Rc::new(VsArray::from(new_elems)))
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static INCLUDES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let search_param = params.get(0).unwrap_or(&Val::Undefined).clone();
@@ -345,20 +345,20 @@ static INCLUDES: NativeFunction = NativeFunction {
.unwrap(); // TODO: Exception
if is_eq {
return Val::Bool(true);
return Ok(Val::Bool(true));
}
}
return Val::Bool(false);
Val::Bool(false)
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let search_param = params.get(0).unwrap_or(&Val::Undefined).clone();
@@ -368,27 +368,27 @@ static INDEX_OF: NativeFunction = NativeFunction {
.unwrap(); // TODO: Exception
if is_eq {
return Val::Number(i as f64);
return Ok(Val::Number(i as f64));
}
}
return Val::Number(-1_f64);
Val::Number(-1.0)
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static JOIN: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(vals) => {
if vals.elements.len() == 0 {
return Val::String(Rc::new("".to_string()));
return Ok(Val::String(Rc::new("".to_string())));
}
if vals.elements.len() == 1 {
return Val::String(Rc::new(vals.elements[0].val_to_string()));
return Ok(Val::String(Rc::new(vals.elements[0].val_to_string())));
}
let separator = params.get(0).unwrap_or(&Val::Undefined);
@@ -412,15 +412,16 @@ static JOIN: NativeFunction = NativeFunction {
};
}
return Val::String(Rc::new(res));
Val::String(Rc::new(res))
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static KEYS: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
Val::Array(_array_data) => {
std::panic!("Not implemented: KEYS");
@@ -431,8 +432,8 @@ static KEYS: NativeFunction = NativeFunction {
};
static LAST_INDEX_OF: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let search_param = params.get(0).unwrap_or(&Val::Undefined).clone();
@@ -442,23 +443,23 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
.unwrap(); // TODO: Exception
if is_eq {
return Val::Number(i as f64);
return Ok(Val::Number(i as f64));
}
}
return Val::Number(-1_f64);
Val::Number(-1_f64)
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static POP: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
if array_data.elements.len() == 0 {
return Val::Undefined;
return Ok(Val::Undefined);
}
let array_data_mut = Rc::make_mut(array_data);
@@ -467,19 +468,19 @@ static POP: NativeFunction = NativeFunction {
.elements
.remove(array_data_mut.elements.len() - 1);
return match removed_el {
match removed_el {
Val::Void => Val::Undefined,
_ => removed_el,
};
}
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static PUSH: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
@@ -487,21 +488,21 @@ static PUSH: NativeFunction = NativeFunction {
array_data_mut.elements.push(p);
}
return Val::Number(array_data_mut.elements.len() as f64);
Val::Number(array_data_mut.elements.len() as f64)
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static REVERSE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
if array_data.elements.len() == 0 {
// Treating this as an edge case because rust protects us from
// underflow when computing last below.
return this.clone();
return Ok(this.clone());
}
let array_data_mut = Rc::make_mut(array_data);
@@ -514,33 +515,33 @@ static REVERSE: NativeFunction = NativeFunction {
array_data_mut.elements[last - i] = tmp;
}
return this.clone();
this.clone()
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static SHIFT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
if array_data.elements.len() == 0 {
return Val::Undefined;
return Ok(Val::Undefined);
}
let array_data_mut = Rc::make_mut(array_data);
return array_data_mut.elements.remove(0);
array_data_mut.elements.remove(0)
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static SLICE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let mut new_elems = Vec::<Val>::new();
@@ -558,16 +559,16 @@ static SLICE: NativeFunction = NativeFunction {
new_elems.push(array_data.elements[i as usize].clone());
}
return Val::Array(Rc::new(VsArray::from(new_elems)));
Val::Array(Rc::new(VsArray::from(new_elems)))
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static SPLICE: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
let len = array_data_mut.elements.len();
@@ -635,15 +636,16 @@ static SPLICE: NativeFunction = NativeFunction {
}
}
return Val::Array(Rc::new(VsArray::from(deleted_elements)));
Val::Array(Rc::new(VsArray::from(deleted_elements)))
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static TO_LOCALE_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
Val::Array(_array_data) => {
std::panic!("Not implemented: TO_LOCALE_STRING");
@@ -653,15 +655,16 @@ static TO_LOCALE_STRING: NativeFunction = NativeFunction {
},
};
// TODO: Share this? (JS doesn't?)
static TO_STRING: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
return Val::String(Rc::new(this.val_to_string()));
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
Ok(Val::String(Rc::new(this.val_to_string())))
},
};
static UNSHIFT: NativeFunction = NativeFunction {
fn_: |this: &mut Val, params: Vec<Val>| -> Val {
match this {
fn_: |this: &mut Val, params: Vec<Val>| -> Result<Val, Val> {
Ok(match this {
Val::Array(array_data) => {
let array_data_mut = Rc::make_mut(array_data);
@@ -672,15 +675,16 @@ static UNSHIFT: NativeFunction = NativeFunction {
i += 1;
}
return Val::Number(array_data_mut.elements.len() as f64);
Val::Number(array_data_mut.elements.len() as f64)
}
_ => std::panic!("TODO: Exceptions/array indirection"),
};
})
},
};
static VALUES: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
fn_: |this: &mut Val, _params: Vec<Val>| -> Result<Val, Val> {
// TODO: Ok(...)
match this {
Val::Array(_array_data) => {
std::panic!("Not implemented: VALUES");

View File

@@ -46,7 +46,7 @@ pub enum VsType {
pub enum LoadFunctionResult {
NotAFunction,
StackFrame(StackFrame),
NativeFunction(fn(this: &mut Val, params: Vec<Val>) -> Val),
NativeFunction(fn(this: &mut Val, params: Vec<Val>) -> Result<Val, Val>),
}
pub trait ValTrait {