diff --git a/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs b/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs index e10fafb..07f43f9 100644 --- a/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs +++ b/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs @@ -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 { diff --git a/valuescript_vm/src/array_higher_functions/array_reduce.rs b/valuescript_vm/src/array_higher_functions/array_reduce.rs index 33aef6a..c7ab548 100644 --- a/valuescript_vm/src/array_higher_functions/array_reduce.rs +++ b/valuescript_vm/src/array_higher_functions/array_reduce.rs @@ -77,7 +77,7 @@ impl StackFrameTrait for ReduceFrame { Val::Number(array_i as f64), Val::Array(array_data.clone()), ], - )); + )?); return Ok(FrameStepOk::Continue); } diff --git a/valuescript_vm/src/array_higher_functions/array_reduce_right.rs b/valuescript_vm/src/array_higher_functions/array_reduce_right.rs index aa66bfa..6cb854f 100644 --- a/valuescript_vm/src/array_higher_functions/array_reduce_right.rs +++ b/valuescript_vm/src/array_higher_functions/array_reduce_right.rs @@ -99,7 +99,7 @@ impl StackFrameTrait for ReduceRightFrame { Val::Number(array_i as f64), Val::Array(array_data.clone()), ], - )); + )?); return Ok(FrameStepOk::Continue); } diff --git a/valuescript_vm/src/array_higher_functions/array_sort.rs b/valuescript_vm/src/array_higher_functions/array_sort.rs index de56ba8..97604bb 100644 --- a/valuescript_vm/src/array_higher_functions/array_sort.rs +++ b/valuescript_vm/src/array_higher_functions/array_sort.rs @@ -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, diff --git a/valuescript_vm/src/bigint_methods.rs b/valuescript_vm/src/bigint_methods.rs index 1f51e60..1f049a1 100644 --- a/valuescript_vm/src/bigint_methods.rs +++ b/valuescript_vm/src/bigint_methods.rs @@ -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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + Ok(match this { Val::BigInt(bigint) => Val::BigInt(bigint.clone()), _ => panic!("TODO: exceptions/bigint indirection"), - } + }) }, }; diff --git a/valuescript_vm/src/builtins/array_builtin.rs b/valuescript_vm/src/builtins/array_builtin.rs index 3543162..e999a3f 100644 --- a/valuescript_vm/src/builtins/array_builtin.rs +++ b/valuescript_vm/src/builtins/array_builtin.rs @@ -84,19 +84,19 @@ impl ValTrait for ArrayBuiltin { } static IS_ARRAY: NativeFunction = NativeFunction { - fn_: |_this: &mut Val, params: Vec| -> Val { - match params.get(0) { + fn_: |_this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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::Array(Rc::new(VsArray::from(params))) }, + fn_: |_this: &mut Val, params: Vec| -> Result { + Ok(Val::Array(Rc::new(VsArray::from(params)))) + }, }; -fn to_array(_: &mut Val, params: Vec) -> Val { +fn to_array(_: &mut Val, params: Vec) -> Result { 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::Array(Rc::new(VsArray::from(arr))) } _ => Val::Array(Rc::new(VsArray::from(params))), - } + }) } diff --git a/valuescript_vm/src/builtins/boolean_builtin.rs b/valuescript_vm/src/builtins/boolean_builtin.rs index 952fd8d..6358d75 100644 --- a/valuescript_vm/src/builtins/boolean_builtin.rs +++ b/valuescript_vm/src/builtins/boolean_builtin.rs @@ -76,10 +76,10 @@ impl ValTrait for BooleanBuiltin { } } -fn to_boolean(_: &mut Val, params: Vec) -> Val { - if let Some(value) = params.get(0) { +fn to_boolean(_: &mut Val, params: Vec) -> Result { + Ok(if let Some(value) = params.get(0) { Val::Bool(value.is_truthy()) } else { Val::Bool(false) - } + }) } diff --git a/valuescript_vm/src/builtins/debug_builtin.rs b/valuescript_vm/src/builtins/debug_builtin.rs index dff6f8e..0892f38 100644 --- a/valuescript_vm/src/builtins/debug_builtin.rs +++ b/valuescript_vm/src/builtins/debug_builtin.rs @@ -81,11 +81,11 @@ impl ValTrait for DebugBuiltin { } static LOG: NativeFunction = NativeFunction { - fn_: |_this: &mut Val, params: Vec| -> Val { + fn_: |_this: &mut Val, params: Vec| -> Result { for p in params { println!("Debug.log: {}", p); } - return Val::Undefined; + Ok(Val::Undefined) }, }; diff --git a/valuescript_vm/src/builtins/math_builtin.rs b/valuescript_vm/src/builtins/math_builtin.rs index a7a4402..ebf0a4d 100644 --- a/valuescript_vm/src/builtins/math_builtin.rs +++ b/valuescript_vm/src/builtins/math_builtin.rs @@ -133,246 +133,246 @@ fn param_to_number(param: Option<&Val>) -> f64 { } static ABS: NativeFunction = NativeFunction { - fn_: |_this: &mut Val, params: Vec| -> Val { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { let x = param_to_number(params.get(0)); - return Val::Number(x.trunc()); + Ok(Val::Number(x.trunc())) }, }; diff --git a/valuescript_vm/src/builtins/number_builtin.rs b/valuescript_vm/src/builtins/number_builtin.rs index a8e54d0..e4af76b 100644 --- a/valuescript_vm/src/builtins/number_builtin.rs +++ b/valuescript_vm/src/builtins/number_builtin.rs @@ -94,46 +94,46 @@ impl ValTrait for NumberBuiltin { } pub static IS_FINITE: NativeFunction = NativeFunction { - fn_: |_this: &mut Val, params: Vec| -> Val { - if let Some(value) = params.get(0) { + fn_: |_this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { - if let Some(value) = params.get(0) { + fn_: |_this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { - if let Some(value) = params.get(0) { + fn_: |_this: &mut Val, params: Vec| -> Result { + Ok(if let Some(value) = params.get(0) { let string_value = value.val_to_string().trim().to_string(); match string_value.parse::() { @@ -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 { - if let Some(value) = params.get(0) { + fn_: |_this: &mut Val, params: Vec| -> Result { + 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 { - if let Some(value) = params.get(0) { +fn to_number(_: &mut Val, params: Vec) -> Result { + Ok(if let Some(value) = params.get(0) { Val::Number(value.to_number()) } else { Val::Number(0.0) - } + }) } diff --git a/valuescript_vm/src/builtins/string_builtin.rs b/valuescript_vm/src/builtins/string_builtin.rs index 6b7e2dc..a5658dc 100644 --- a/valuescript_vm/src/builtins/string_builtin.rs +++ b/valuescript_vm/src/builtins/string_builtin.rs @@ -86,7 +86,7 @@ impl ValTrait for StringBuiltin { } static FROM_CODE_POINT: NativeFunction = NativeFunction { - fn_: |_this: &mut Val, params: Vec| -> Val { + fn_: |_this: &mut Val, params: Vec| -> Result { 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 { - if let Some(value) = params.get(0) { +fn to_string(_: &mut Val, params: Vec) -> Result { + Ok(if let Some(value) = params.get(0) { Val::String(Rc::new(value.val_to_string())) } else { Val::String(Rc::new("".to_string())) - } + }) } diff --git a/valuescript_vm/src/bytecode_stack_frame.rs b/valuescript_vm/src/bytecode_stack_frame.rs index 42b204a..44144e8 100644 --- a/valuescript_vm/src/bytecode_stack_frame.rs +++ b/valuescript_vm/src/bytecode_stack_frame.rs @@ -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) => { diff --git a/valuescript_vm/src/native_function.rs b/valuescript_vm/src/native_function.rs index bca33fd..23104e8 100644 --- a/valuescript_vm/src/native_function.rs +++ b/valuescript_vm/src/native_function.rs @@ -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, + pub fn_: fn(this: &mut Val, params: Vec) -> Result, } impl ValTrait for NativeFunction { diff --git a/valuescript_vm/src/number_methods.rs b/valuescript_vm/src/number_methods.rs index 5fde8d3..ec0bd60 100644 --- a/valuescript_vm/src/number_methods.rs +++ b/valuescript_vm/src/number_methods.rs @@ -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 { + fn_: |this: &mut Val, params: Vec| -> Result { 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 { + fn_: |this: &mut Val, params: Vec| -> Result { 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + Ok(match this { Val::Number(number) => Val::Number(*number), _ => panic!("TODO: exceptions/number indirection"), - } + }) }, }; diff --git a/valuescript_vm/src/operations.rs b/valuescript_vm/src/operations.rs index e39449d..e522cc8 100644 --- a/valuescript_vm/src/operations.rs +++ b/valuescript_vm/src/operations.rs @@ -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 { - match &this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match &this { + fn_: |this: &mut Val, _params: Vec| -> Result { + Ok(match &this { Val::Bool(b) => Val::Bool(*b), _ => std::panic!("TODO: Exceptions/bool indirection"), - } + }) }, }; diff --git a/valuescript_vm/src/string_methods.rs b/valuescript_vm/src/string_methods.rs index 05cbfac..288ede6 100644 --- a/valuescript_vm/src/string_methods.rs +++ b/valuescript_vm/src/string_methods.rs @@ -84,13 +84,13 @@ pub fn get_string_method(method: &str) -> Val { } static AT: NativeFunction = NativeFunction { - fn_: |this: &mut Val, params: Vec| -> Val { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { + // 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { + // 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { + // 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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::::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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + Ok(match this { Val::String(string_data) => Val::String(string_data.clone()), _ => panic!("TODO: exceptions/string indirection"), - } + }) }, }; diff --git a/valuescript_vm/src/todo_fn.rs b/valuescript_vm/src/todo_fn.rs index e46df9c..e5bfe19 100644 --- a/valuescript_vm/src/todo_fn.rs +++ b/valuescript_vm/src/todo_fn.rs @@ -1,7 +1,7 @@ use crate::{native_function::NativeFunction, vs_value::Val}; pub static TODO: NativeFunction = NativeFunction { - fn_: |this: &mut Val, _params: Vec| -> Val { + fn_: |this: &mut Val, _params: Vec| -> Result { match this { Val::Number(_number) => panic!("TODO: locale"), _ => panic!("TODO: exceptions/number indirection"), diff --git a/valuescript_vm/src/vs_array.rs b/valuescript_vm/src/vs_array.rs index ec94633..5c19609 100644 --- a/valuescript_vm/src/vs_array.rs +++ b/valuescript_vm/src/vs_array.rs @@ -153,20 +153,20 @@ impl ValTrait for ArrayPrototype { } static AT: NativeFunction = NativeFunction { - fn_: |this: &mut Val, params: Vec| -> Val { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { + // 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, _params: Vec| -> Result { + 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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + Ok(match this { Val::Array(array_data) => { let mut new_elems = Vec::::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 { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { + // 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 { - return Val::String(Rc::new(this.val_to_string())); + fn_: |this: &mut Val, _params: Vec| -> Result { + Ok(Val::String(Rc::new(this.val_to_string()))) }, }; static UNSHIFT: NativeFunction = NativeFunction { - fn_: |this: &mut Val, params: Vec| -> Val { - match this { + fn_: |this: &mut Val, params: Vec| -> Result { + 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 { + fn_: |this: &mut Val, _params: Vec| -> Result { + // TODO: Ok(...) match this { Val::Array(_array_data) => { std::panic!("Not implemented: VALUES"); diff --git a/valuescript_vm/src/vs_value.rs b/valuescript_vm/src/vs_value.rs index b081b79..0e6a02c 100644 --- a/valuescript_vm/src/vs_value.rs +++ b/valuescript_vm/src/vs_value.rs @@ -46,7 +46,7 @@ pub enum VsType { pub enum LoadFunctionResult { NotAFunction, StackFrame(StackFrame), - NativeFunction(fn(this: &mut Val, params: Vec) -> Val), + NativeFunction(fn(this: &mut Val, params: Vec) -> Result), } pub trait ValTrait {