Allow non-Dynamic in return_raw.
This commit is contained in:
parent
b3bcd7bf79
commit
a82f0fc738
@ -10,12 +10,14 @@ Breaking changes
|
|||||||
* The traits `RegisterFn` and `RegisterResultFn` are removed. `Engine::register_fn` and `Engine::register_result_fn` are now implemented directly on `Engine`.
|
* The traits `RegisterFn` and `RegisterResultFn` are removed. `Engine::register_fn` and `Engine::register_result_fn` are now implemented directly on `Engine`.
|
||||||
* `FnPtr::call_dynamic` now takes `&NativeCallContext` instead of consuming it.
|
* `FnPtr::call_dynamic` now takes `&NativeCallContext` instead of consuming it.
|
||||||
* All `Module::set_fn_XXX` methods are removed, in favor of `Module::set_native_fn`.
|
* All `Module::set_fn_XXX` methods are removed, in favor of `Module::set_native_fn`.
|
||||||
|
* `Array::reduce` and `Array::reduce_rev` now take a `Dynamic` as initial value instead of a function pointer.
|
||||||
* `protected`, `super` are now reserved keywords.
|
* `protected`, `super` are now reserved keywords.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* `Engine::register_result_fn` no longer requires the successful return type to be `Dynamic`. It can now be any type.
|
* `Engine::register_result_fn` no longer requires the successful return type to be `Dynamic`. It can now be any clonable type.
|
||||||
|
* `#[rhai_fn(return_raw)]` can now return `Result<T, Box<EvalAltResult>>` where `T` is any clonable type instead of `Result<Dynamic, Box<EvalAltResult>>`.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.14
|
Version 0.19.14
|
||||||
|
@ -279,7 +279,6 @@ pub struct ExportedFn {
|
|||||||
signature: syn::Signature,
|
signature: syn::Signature,
|
||||||
visibility: syn::Visibility,
|
visibility: syn::Visibility,
|
||||||
pass_context: bool,
|
pass_context: bool,
|
||||||
return_dynamic: bool,
|
|
||||||
mut_receiver: bool,
|
mut_receiver: bool,
|
||||||
params: ExportedFnParams,
|
params: ExportedFnParams,
|
||||||
}
|
}
|
||||||
@ -290,10 +289,6 @@ impl Parse for ExportedFn {
|
|||||||
let entire_span = fn_all.span();
|
let entire_span = fn_all.span();
|
||||||
let str_type_path = syn::parse2::<syn::Path>(quote! { str }).unwrap();
|
let str_type_path = syn::parse2::<syn::Path>(quote! { str }).unwrap();
|
||||||
|
|
||||||
let dynamic_type_path1 = syn::parse2::<syn::Path>(quote! { Dynamic }).unwrap();
|
|
||||||
let dynamic_type_path2 = syn::parse2::<syn::Path>(quote! { rhai::Dynamic }).unwrap();
|
|
||||||
let mut return_dynamic = false;
|
|
||||||
|
|
||||||
let context_type_path1 = syn::parse2::<syn::Path>(quote! { NativeCallContext }).unwrap();
|
let context_type_path1 = syn::parse2::<syn::Path>(quote! { NativeCallContext }).unwrap();
|
||||||
let context_type_path2 =
|
let context_type_path2 =
|
||||||
syn::parse2::<syn::Path>(quote! { rhai::NativeCallContext }).unwrap();
|
syn::parse2::<syn::Path>(quote! { rhai::NativeCallContext }).unwrap();
|
||||||
@ -400,11 +395,6 @@ impl Parse for ExportedFn {
|
|||||||
"Rhai functions cannot return references",
|
"Rhai functions cannot return references",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
syn::Type::Path(p)
|
|
||||||
if p.path == dynamic_type_path1 || p.path == dynamic_type_path2 =>
|
|
||||||
{
|
|
||||||
return_dynamic = true
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,7 +403,6 @@ impl Parse for ExportedFn {
|
|||||||
signature: fn_all.sig,
|
signature: fn_all.sig,
|
||||||
visibility,
|
visibility,
|
||||||
pass_context,
|
pass_context,
|
||||||
return_dynamic,
|
|
||||||
mut_receiver,
|
mut_receiver,
|
||||||
params: Default::default(),
|
params: Default::default(),
|
||||||
})
|
})
|
||||||
@ -520,7 +509,7 @@ impl ExportedFn {
|
|||||||
if params.return_raw.is_some() && self.return_type().is_none() {
|
if params.return_raw.is_some() && self.return_type().is_none() {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
params.return_raw.unwrap(),
|
params.return_raw.unwrap(),
|
||||||
"functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>>",
|
"functions marked with 'return_raw' must return Result<T, Box<EvalAltResult>>",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,13 +645,7 @@ impl ExportedFn {
|
|||||||
if self.params.return_raw.is_some() {
|
if self.params.return_raw.is_some() {
|
||||||
quote_spanned! { return_span =>
|
quote_spanned! { return_span =>
|
||||||
pub #dynamic_signature {
|
pub #dynamic_signature {
|
||||||
#name(#(#arguments),*)
|
#name(#(#arguments),*).map(Dynamic::from)
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if self.return_dynamic {
|
|
||||||
quote_spanned! { return_span =>
|
|
||||||
pub #dynamic_signature {
|
|
||||||
Ok(#name(#(#arguments),*))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -890,18 +873,12 @@ impl ExportedFn {
|
|||||||
.map(|r| r.span())
|
.map(|r| r.span())
|
||||||
.unwrap_or_else(|| proc_macro2::Span::call_site());
|
.unwrap_or_else(|| proc_macro2::Span::call_site());
|
||||||
let return_expr = if !self.params.return_raw.is_some() {
|
let return_expr = if !self.params.return_raw.is_some() {
|
||||||
if self.return_dynamic {
|
|
||||||
quote_spanned! { return_span =>
|
|
||||||
Ok(#sig_name(#(#unpack_exprs),*))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote_spanned! { return_span =>
|
quote_spanned! { return_span =>
|
||||||
Ok(Dynamic::from(#sig_name(#(#unpack_exprs),*)))
|
Ok(Dynamic::from(#sig_name(#(#unpack_exprs),*)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
quote_spanned! { return_span =>
|
quote_spanned! { return_span =>
|
||||||
#sig_name(#(#unpack_exprs),*)
|
#sig_name(#(#unpack_exprs),*).map(Dynamic::from)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -447,7 +447,7 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult {
|
||||||
debug_assert_eq!(args.len(), 0usize,
|
debug_assert_eq!(args.len(), 0usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 0usize);
|
"wrong arg count: {} != {}", args.len(), 0usize);
|
||||||
Ok(return_dynamic())
|
Ok(Dynamic::from(return_dynamic()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_method_call(&self) -> bool { false }
|
fn is_method_call(&self) -> bool { false }
|
||||||
@ -477,7 +477,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn dynamic_result_fn() -> Result<Dynamic, Box<EvalAltResult> > {
|
pub fn dynamic_result_fn() -> Result<Dynamic, Box<EvalAltResult> > {
|
||||||
Ok(return_dynamic())
|
Ok(Dynamic::from(return_dynamic()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>>
|
error: functions marked with 'return_raw' must return Result<T, Box<EvalAltResult>>
|
||||||
--> $DIR/export_fn_raw_noreturn.rs:9:13
|
--> $DIR/export_fn_raw_noreturn.rs:9:13
|
||||||
|
|
|
|
||||||
9 | #[export_fn(return_raw)]
|
9 | #[export_fn(return_raw)]
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
error[E0308]: mismatched types
|
error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied
|
||||||
--> $DIR/export_fn_raw_return.rs:10:8
|
--> $DIR/export_fn_raw_return.rs:10:33
|
||||||
|
|
|
|
||||||
9 | #[export_fn(return_raw)]
|
|
||||||
| ------------------------ expected `Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>` because of return type
|
|
||||||
10 | pub fn test_fn(input: Point) -> bool {
|
10 | pub fn test_fn(input: Point) -> bool {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `bool`
|
| ^^^^ method cannot be called on `bool` due to unsatisfied trait bounds
|
||||||
|
|
|
|
||||||
= note: expected enum `Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>`
|
= note: the following trait bounds were not satisfied:
|
||||||
found type `bool`
|
`bool: std::iter::Iterator`
|
||||||
|
which is required by `&mut bool: std::iter::Iterator`
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>>
|
error: functions marked with 'return_raw' must return Result<T, Box<EvalAltResult>>
|
||||||
--> $DIR/export_mod_raw_noreturn.rs:11:11
|
--> $DIR/export_mod_raw_noreturn.rs:11:11
|
||||||
|
|
|
|
||||||
11 | #[rhai_fn(return_raw)]
|
11 | #[rhai_fn(return_raw)]
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
error[E0308]: mismatched types
|
error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied
|
||||||
--> $DIR/export_mod_raw_return.rs:12:8
|
--> $DIR/export_mod_raw_return.rs:12:33
|
||||||
|
|
|
|
||||||
9 | #[export_module]
|
|
||||||
| ---------------- expected `Result<rhai::Dynamic, std::boxed::Box<EvalAltResult>>` because of return type
|
|
||||||
...
|
|
||||||
12 | pub fn test_fn(input: Point) -> bool {
|
12 | pub fn test_fn(input: Point) -> bool {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `bool`
|
| ^^^^ method cannot be called on `bool` due to unsatisfied trait bounds
|
||||||
|
|
|
|
||||||
= note: expected enum `Result<rhai::Dynamic, std::boxed::Box<EvalAltResult>>`
|
= note: the following trait bounds were not satisfied:
|
||||||
found type `bool`
|
`bool: std::iter::Iterator`
|
||||||
|
which is required by `&mut bool: std::iter::Iterator`
|
||||||
|
@ -6,5 +6,5 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
|||||||
|
|
|
|
||||||
::: $WORKSPACE/src/dynamic.rs
|
::: $WORKSPACE/src/dynamic.rs
|
||||||
|
|
|
|
||||||
| pub fn from<T: Variant + Clone>(value: T) -> Self {
|
| pub fn from<T: Variant + Clone>(mut value: T) -> Self {
|
||||||
| ----- required by this bound in `rhai::Dynamic::from`
|
| ----- required by this bound in `rhai::Dynamic::from`
|
||||||
|
@ -6,5 +6,5 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
|||||||
|
|
|
|
||||||
::: $WORKSPACE/src/dynamic.rs
|
::: $WORKSPACE/src/dynamic.rs
|
||||||
|
|
|
|
||||||
| pub fn from<T: Variant + Clone>(value: T) -> Self {
|
| pub fn from<T: Variant + Clone>(mut value: T) -> Self {
|
||||||
| ----- required by this bound in `rhai::Dynamic::from`
|
| ----- required by this bound in `rhai::Dynamic::from`
|
||||||
|
@ -1303,7 +1303,7 @@ pub struct OpAssignment {
|
|||||||
///
|
///
|
||||||
/// Two separate hashes are pre-calculated because of the following pattern:
|
/// Two separate hashes are pre-calculated because of the following pattern:
|
||||||
///
|
///
|
||||||
/// ```,ignore
|
/// ```ignore
|
||||||
/// func(a, b, c); // Native: func(a, b, c) - 3 parameters
|
/// func(a, b, c); // Native: func(a, b, c) - 3 parameters
|
||||||
/// // Script: func(a, b, c) - 3 parameters
|
/// // Script: func(a, b, c) - 3 parameters
|
||||||
///
|
///
|
||||||
|
@ -833,9 +833,13 @@ impl Dynamic {
|
|||||||
/// assert_eq!(new_result.to_string(), "hello");
|
/// assert_eq!(new_result.to_string(), "hello");
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from<T: Variant + Clone>(value: T) -> Self {
|
pub fn from<T: Variant + Clone>(mut value: T) -> Self {
|
||||||
// Coded this way in order to maximally leverage potentials for dead-code removal.
|
// Coded this way in order to maximally leverage potentials for dead-code removal.
|
||||||
|
|
||||||
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
||||||
|
return unsafe_try_cast::<_, Dynamic>(value).ok().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
||||||
return <dyn Any>::downcast_ref::<INT>(&value)
|
return <dyn Any>::downcast_ref::<INT>(&value)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -884,46 +888,43 @@ impl Dynamic {
|
|||||||
return ().into();
|
return ().into();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut boxed = Box::new(value);
|
value = match unsafe_try_cast::<_, String>(value) {
|
||||||
|
Ok(s) => return (s).into(),
|
||||||
boxed = match unsafe_cast_box::<_, Dynamic>(boxed) {
|
|
||||||
Ok(d) => return *d,
|
|
||||||
Err(val) => val,
|
|
||||||
};
|
|
||||||
boxed = match unsafe_cast_box::<_, String>(boxed) {
|
|
||||||
Ok(s) => return (*s).into(),
|
|
||||||
Err(val) => val,
|
Err(val) => val,
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
{
|
{
|
||||||
boxed = match unsafe_cast_box::<_, Array>(boxed) {
|
value = match unsafe_try_cast::<_, Array>(value) {
|
||||||
Ok(array) => return (*array).into(),
|
Ok(array) => return (array).into(),
|
||||||
Err(val) => val,
|
Err(val) => val,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
{
|
{
|
||||||
boxed = match unsafe_cast_box::<_, Map>(boxed) {
|
value = match unsafe_try_cast::<_, Map>(value) {
|
||||||
Ok(map) => return (*map).into(),
|
Ok(map) => return (map).into(),
|
||||||
Err(val) => val,
|
Err(val) => val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boxed = match unsafe_cast_box::<_, FnPtr>(boxed) {
|
value = match unsafe_try_cast::<_, FnPtr>(value) {
|
||||||
Ok(fn_ptr) => return (*fn_ptr).into(),
|
Ok(fn_ptr) => return (fn_ptr).into(),
|
||||||
Err(val) => val,
|
Err(val) => val,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
{
|
{
|
||||||
boxed = match unsafe_cast_box::<_, Instant>(boxed) {
|
value = match unsafe_try_cast::<_, Instant>(value) {
|
||||||
Ok(timestamp) => return (*timestamp).into(),
|
Ok(timestamp) => return (timestamp).into(),
|
||||||
Err(val) => val,
|
Err(val) => val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self(Union::Variant(Box::new(boxed), AccessMode::ReadWrite))
|
Self(Union::Variant(
|
||||||
|
Box::new(Box::new(value)),
|
||||||
|
AccessMode::ReadWrite,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
/// Turn the [`Dynamic`] value into a shared [`Dynamic`] value backed by an
|
/// Turn the [`Dynamic`] value into a shared [`Dynamic`] value backed by an
|
||||||
/// [`Rc`][std::rc::Rc]`<`[`RefCell`][std::cell::RefCell]`<`[`Dynamic`]`>>` or
|
/// [`Rc`][std::rc::Rc]`<`[`RefCell`][std::cell::RefCell]`<`[`Dynamic`]`>>` or
|
||||||
@ -986,12 +987,12 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
||||||
return unsafe_cast_box::<_, T>(Box::new(self)).ok().map(|v| *v);
|
return unsafe_try_cast::<_, T>(self).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Int(value, _) => unsafe_try_cast(value),
|
Union::Int(value, _) => unsafe_try_cast(value).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -999,7 +1000,7 @@ impl Dynamic {
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Float(value, _) => unsafe_try_cast(*value),
|
Union::Float(value, _) => unsafe_try_cast(*value).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1007,35 +1008,35 @@ impl Dynamic {
|
|||||||
#[cfg(feature = "decimal")]
|
#[cfg(feature = "decimal")]
|
||||||
if TypeId::of::<T>() == TypeId::of::<Decimal>() {
|
if TypeId::of::<T>() == TypeId::of::<Decimal>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Decimal(value, _) => unsafe_try_cast(*value),
|
Union::Decimal(value, _) => unsafe_try_cast(*value).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Bool(value, _) => unsafe_try_cast(value),
|
Union::Bool(value, _) => unsafe_try_cast(value).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Str(value, _) => unsafe_try_cast(value),
|
Union::Str(value, _) => unsafe_try_cast(value).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<String>() {
|
if TypeId::of::<T>() == TypeId::of::<String>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Str(value, _) => unsafe_try_cast(value.into_owned()),
|
Union::Str(value, _) => unsafe_try_cast(value.into_owned()).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<char>() {
|
if TypeId::of::<T>() == TypeId::of::<char>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Char(value, _) => unsafe_try_cast(value),
|
Union::Char(value, _) => unsafe_try_cast(value).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1073,7 +1074,7 @@ impl Dynamic {
|
|||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<()>() {
|
if TypeId::of::<T>() == TypeId::of::<()>() {
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Unit(value, _) => unsafe_try_cast(value),
|
Union::Unit(value, _) => unsafe_try_cast(value).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1047,12 +1047,6 @@ impl Engine {
|
|||||||
|
|
||||||
let val = scope.get_mut_by_index(index);
|
let val = scope.get_mut_by_index(index);
|
||||||
|
|
||||||
// Check for data race - probably not necessary because the only place it should conflict is
|
|
||||||
// in a method call when the object variable is also used as a parameter.
|
|
||||||
// if cfg!(not(feature = "no_closure")) && val.is_locked() {
|
|
||||||
// return EvalAltResult::ErrorDataRace(name.into(), *pos).into();
|
|
||||||
// }
|
|
||||||
|
|
||||||
Ok((val.into(), *pos))
|
Ok((val.into(), *pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1885,9 +1885,8 @@ impl Engine {
|
|||||||
.ok_or_else(|| EvalAltResult::ErrorFunctionNotFound(name.into(), Position::NONE))?;
|
.ok_or_else(|| EvalAltResult::ErrorFunctionNotFound(name.into(), Position::NONE))?;
|
||||||
|
|
||||||
// Check for data race.
|
// Check for data race.
|
||||||
if cfg!(not(feature = "no_closure")) {
|
#[cfg(not(feature = "no_closure"))]
|
||||||
crate::fn_call::ensure_no_data_race(name, args, false)?;
|
crate::fn_call::ensure_no_data_race(name, args, false)?;
|
||||||
}
|
|
||||||
|
|
||||||
self.call_script_fn(
|
self.call_script_fn(
|
||||||
scope,
|
scope,
|
||||||
|
@ -109,7 +109,7 @@ pub fn get_builtin_binary_op_fn(
|
|||||||
return Some(|_, args| {
|
return Some(|_, args| {
|
||||||
let x = args[0].$xx().unwrap() as $base;
|
let x = args[0].$xx().unwrap() as $base;
|
||||||
let y = args[1].$yy().unwrap() as $base;
|
let y = args[1].$yy().unwrap() as $base;
|
||||||
$func(x, y)
|
$func(x, y).map(Into::<Dynamic>::into)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
(from $base:ty => $xx:ident $op:tt $yy:ident) => {
|
(from $base:ty => $xx:ident $op:tt $yy:ident) => {
|
||||||
|
@ -98,10 +98,7 @@ macro_rules! def_anonymous_fn {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
||||||
let fn_name = entry_point.to_string();
|
let fn_name = entry_point.to_string();
|
||||||
|
Box::new(move |$($par),*| self.call_fn(&mut Scope::new(), &ast, &fn_name, ($($par,)*)))
|
||||||
Box::new(move |$($par: $par),*| {
|
|
||||||
self.call_fn(&mut Scope::new(), &ast, &fn_name, ($($par,)*))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Contents of `my_script.rhai`
|
//! ## Contents of `my_script.rhai`
|
||||||
//!
|
//!
|
||||||
//! ```,ignore
|
//! ```ignore
|
||||||
//! /// Brute force factorial function
|
//! /// Brute force factorial function
|
||||||
//! fn factorial(x) {
|
//! fn factorial(x) {
|
||||||
//! if x == 1 { return 1; }
|
//! if x == 1 { return 1; }
|
||||||
@ -24,7 +24,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## The Rust part
|
//! ## The Rust part
|
||||||
//!
|
//!
|
||||||
//! ```,no_run
|
//! ```no_run
|
||||||
//! use rhai::{Engine, EvalAltResult};
|
//! use rhai::{Engine, EvalAltResult};
|
||||||
//!
|
//!
|
||||||
//! fn main() -> Result<(), Box<EvalAltResult>>
|
//! fn main() -> Result<(), Box<EvalAltResult>>
|
||||||
@ -88,7 +88,7 @@ mod token;
|
|||||||
mod r#unsafe;
|
mod r#unsafe;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
type RhaiResult = Result<Dynamic, stdlib::boxed::Box<EvalAltResult>>;
|
type RhaiResult = stdlib::result::Result<Dynamic, stdlib::boxed::Box<EvalAltResult>>;
|
||||||
|
|
||||||
/// The system integer type. It is defined as [`i64`].
|
/// The system integer type. It is defined as [`i64`].
|
||||||
///
|
///
|
||||||
|
@ -24,91 +24,91 @@ macro_rules! gen_arithmetic_functions {
|
|||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
#[rhai_fn(name = "+", return_raw)]
|
#[rhai_fn(name = "+", return_raw)]
|
||||||
pub fn add(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add(x: $arg_type, y: $arg_type) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_add(y).ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y))).map(Dynamic::from)
|
x.checked_add(y).ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x + y))
|
Ok(x + y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "-", return_raw)]
|
#[rhai_fn(name = "-", return_raw)]
|
||||||
pub fn subtract(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract(x: $arg_type, y: $arg_type) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_sub(y).ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y))).map(Dynamic::from)
|
x.checked_sub(y).ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x - y))
|
Ok(x - y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "*", return_raw)]
|
#[rhai_fn(name = "*", return_raw)]
|
||||||
pub fn multiply(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn multiply(x: $arg_type, y: $arg_type) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_mul(y).ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y))).map(Dynamic::from)
|
x.checked_mul(y).ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x * y))
|
Ok(x * y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "/", return_raw)]
|
#[rhai_fn(name = "/", return_raw)]
|
||||||
pub fn divide(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn divide(x: $arg_type, y: $arg_type) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
// Detect division by zero
|
// Detect division by zero
|
||||||
if y == 0 {
|
if y == 0 {
|
||||||
Err(make_err(format!("Division by zero: {} / {}", x, y)))
|
Err(make_err(format!("Division by zero: {} / {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
x.checked_div(y).ok_or_else(|| make_err(format!("Division overflow: {} / {}", x, y))).map(Dynamic::from)
|
x.checked_div(y).ok_or_else(|| make_err(format!("Division overflow: {} / {}", x, y)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x / y))
|
Ok(x / y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "%", return_raw)]
|
#[rhai_fn(name = "%", return_raw)]
|
||||||
pub fn modulo(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn modulo(x: $arg_type, y: $arg_type) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_rem(y).ok_or_else(|| make_err(format!("Modulo division by zero or overflow: {} % {}", x, y))).map(Dynamic::from)
|
x.checked_rem(y).ok_or_else(|| make_err(format!("Modulo division by zero or overflow: {} % {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x % y))
|
Ok(x % y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "**", return_raw)]
|
#[rhai_fn(name = "**", return_raw)]
|
||||||
pub fn power(x: INT, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn power(x: $arg_type, y: INT) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
||||||
Err(make_err(format!("Integer raised to too large an index: {} ~ {}", x, y)))
|
Err(make_err(format!("Integer raised to too large an index: {} ~ {}", x, y)))
|
||||||
} else if y < 0 {
|
} else if y < 0 {
|
||||||
Err(make_err(format!("Integer raised to a negative index: {} ~ {}", x, y)))
|
Err(make_err(format!("Integer raised to a negative index: {} ~ {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
x.checked_pow(y as u32).ok_or_else(|| make_err(format!("Power overflow: {} ~ {}", x, y))).map(Dynamic::from)
|
x.checked_pow(y as u32).ok_or_else(|| make_err(format!("Power overflow: {} ~ {}", x, y)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x.pow(y as u32)))
|
Ok(x.pow(y as u32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "<<", return_raw)]
|
#[rhai_fn(name = "<<", return_raw)]
|
||||||
pub fn shift_left(x: $arg_type, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn shift_left(x: $arg_type, y: INT) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
||||||
Err(make_err(format!("Left-shift by too many bits: {} << {}", x, y)))
|
Err(make_err(format!("Left-shift by too many bits: {} << {}", x, y)))
|
||||||
} else if y < 0 {
|
} else if y < 0 {
|
||||||
Err(make_err(format!("Left-shift by a negative number: {} << {}", x, y)))
|
Err(make_err(format!("Left-shift by a negative number: {} << {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
x.checked_shl(y as u32).ok_or_else(|| make_err(format!("Left-shift by too many bits: {} << {}", x, y))).map(Dynamic::from)
|
x.checked_shl(y as u32).ok_or_else(|| make_err(format!("Left-shift by too many bits: {} << {}", x, y)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x << y))
|
Ok(x << y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = ">>", return_raw)]
|
#[rhai_fn(name = ">>", return_raw)]
|
||||||
pub fn shift_right(x: $arg_type, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn shift_right(x: $arg_type, y: INT) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
||||||
Err(make_err(format!("Right-shift by too many bits: {} >> {}", x, y)))
|
Err(make_err(format!("Right-shift by too many bits: {} >> {}", x, y)))
|
||||||
} else if y < 0 {
|
} else if y < 0 {
|
||||||
Err(make_err(format!("Right-shift by a negative number: {} >> {}", x, y)))
|
Err(make_err(format!("Right-shift by a negative number: {} >> {}", x, y)))
|
||||||
} else {
|
} else {
|
||||||
x.checked_shr(y as u32).ok_or_else(|| make_err(format!("Right-shift by too many bits: {} >> {}", x, y))).map(Dynamic::from)
|
x.checked_shr(y as u32).ok_or_else(|| make_err(format!("Right-shift by too many bits: {} >> {}", x, y)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x >> y))
|
Ok(x >> y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "&")]
|
#[rhai_fn(name = "&")]
|
||||||
@ -136,11 +136,11 @@ macro_rules! gen_signed_functions {
|
|||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
#[rhai_fn(name = "-", return_raw)]
|
#[rhai_fn(name = "-", return_raw)]
|
||||||
pub fn neg(x: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn neg(x: $arg_type) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_neg().ok_or_else(|| make_err(format!("Negation overflow: -{}", x))).map(Dynamic::from)
|
x.checked_neg().ok_or_else(|| make_err(format!("Negation overflow: -{}", x)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(-x))
|
Ok(-x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
@ -148,11 +148,11 @@ macro_rules! gen_signed_functions {
|
|||||||
x
|
x
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn abs(x: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn abs(x: $arg_type) -> Result<$arg_type, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_abs().ok_or_else(|| make_err(format!("Negation overflow: -{}", x))).map(Dynamic::from)
|
x.checked_abs().ok_or_else(|| make_err(format!("Negation overflow: -{}", x)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x.abs()))
|
Ok(x.abs())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn sign(x: $arg_type) -> INT {
|
pub fn sign(x: $arg_type) -> INT {
|
||||||
@ -318,14 +318,14 @@ mod f32_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "**", return_raw)]
|
#[rhai_fn(name = "**", return_raw)]
|
||||||
pub fn pow_f_i(x: f32, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn pow_f_i(x: f32, y: INT) -> Result<f32, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) && y > (i32::MAX as INT) {
|
if cfg!(not(feature = "unchecked")) && y > (i32::MAX as INT) {
|
||||||
Err(make_err(format!(
|
Err(make_err(format!(
|
||||||
"Number raised to too large an index: {} ~ {}",
|
"Number raised to too large an index: {} ~ {}",
|
||||||
x, y
|
x, y
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x.powi(y as i32)))
|
Ok(x.powi(y as i32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,14 +423,14 @@ mod f64_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "**", return_raw)]
|
#[rhai_fn(name = "**", return_raw)]
|
||||||
pub fn pow_f_i(x: FLOAT, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn pow_f_i(x: FLOAT, y: INT) -> Result<FLOAT, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) && y > (i32::MAX as INT) {
|
if cfg!(not(feature = "unchecked")) && y > (i32::MAX as INT) {
|
||||||
Err(make_err(format!(
|
Err(make_err(format!(
|
||||||
"Number raised to too large an index: {} ~ {}",
|
"Number raised to too large an index: {} ~ {}",
|
||||||
x, y
|
x, y
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
Ok(x.powi(y as i32).into())
|
Ok(x.powi(y as i32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,37 +441,37 @@ pub mod decimal_functions {
|
|||||||
use rust_decimal::{prelude::Zero, Decimal};
|
use rust_decimal::{prelude::Zero, Decimal};
|
||||||
|
|
||||||
#[rhai_fn(skip, return_raw)]
|
#[rhai_fn(skip, return_raw)]
|
||||||
pub fn add(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_add(y)
|
x.checked_add(y)
|
||||||
.ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
|
.ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
|
||||||
.map(Into::<Dynamic>::into)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x + y))
|
Ok(x + y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(skip, return_raw)]
|
#[rhai_fn(skip, return_raw)]
|
||||||
pub fn subtract(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_sub(y)
|
x.checked_sub(y)
|
||||||
.ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
|
.ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
|
||||||
.map(Into::<Dynamic>::into)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x - y))
|
Ok(x - y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(skip, return_raw)]
|
#[rhai_fn(skip, return_raw)]
|
||||||
pub fn multiply(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn multiply(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_mul(y)
|
x.checked_mul(y)
|
||||||
.ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
|
.ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
|
||||||
.map(Into::<Dynamic>::into)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x * y))
|
Ok(x * y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(skip, return_raw)]
|
#[rhai_fn(skip, return_raw)]
|
||||||
pub fn divide(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn divide(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
// Detect division by zero
|
// Detect division by zero
|
||||||
if y == Decimal::zero() {
|
if y == Decimal::zero() {
|
||||||
@ -482,11 +482,11 @@ pub mod decimal_functions {
|
|||||||
.map(Into::<Dynamic>::into)
|
.map(Into::<Dynamic>::into)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x / y))
|
Ok(x / y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(skip, return_raw)]
|
#[rhai_fn(skip, return_raw)]
|
||||||
pub fn modulo(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn modulo(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_rem(y)
|
x.checked_rem(y)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
@ -497,7 +497,7 @@ pub mod decimal_functions {
|
|||||||
})
|
})
|
||||||
.map(Into::<Dynamic>::into)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x % y))
|
Ok(x % y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "-")]
|
#[rhai_fn(name = "-")]
|
||||||
|
@ -47,7 +47,7 @@ mod array_functions {
|
|||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
len: INT,
|
len: INT,
|
||||||
item: Dynamic,
|
item: Dynamic,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
// Check if array will be over max size limit
|
// Check if array will be over max size limit
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if _ctx.engine().max_array_size() > 0
|
if _ctx.engine().max_array_size() > 0
|
||||||
@ -62,7 +62,7 @@ mod array_functions {
|
|||||||
array.resize(len as usize, item);
|
array.resize(len as usize, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn pop(array: &mut Array) -> Dynamic {
|
pub fn pop(array: &mut Array) -> Dynamic {
|
||||||
array.pop().unwrap_or_else(|| ().into())
|
array.pop().unwrap_or_else(|| ().into())
|
||||||
@ -169,7 +169,7 @@ mod array_functions {
|
|||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
mapper: FnPtr,
|
mapper: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Array, Box<EvalAltResult>> {
|
||||||
let mut ar = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
let mut ar = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
@ -195,14 +195,14 @@ mod array_functions {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ar.into())
|
Ok(ar)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, pure)]
|
#[rhai_fn(return_raw, pure)]
|
||||||
pub fn filter(
|
pub fn filter(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Array, Box<EvalAltResult>> {
|
||||||
let mut ar = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
let mut ar = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
@ -231,14 +231,14 @@ mod array_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ar.into())
|
Ok(ar)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, pure)]
|
#[rhai_fn(return_raw, pure)]
|
||||||
pub fn contains(
|
pub fn contains(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
value: Dynamic,
|
value: Dynamic,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<bool, Box<EvalAltResult>> {
|
||||||
for item in array.iter_mut() {
|
for item in array.iter_mut() {
|
||||||
if ctx
|
if ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()])
|
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()])
|
||||||
@ -258,18 +258,18 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
return Ok(Dynamic::TRUE);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Dynamic::FALSE)
|
Ok(false)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, pure)]
|
#[rhai_fn(return_raw, pure)]
|
||||||
pub fn index_of(
|
pub fn index_of(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
value: Dynamic,
|
value: Dynamic,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<INT, Box<EvalAltResult>> {
|
||||||
for (i, item) in array.iter_mut().enumerate() {
|
for (i, item) in array.iter_mut().enumerate() {
|
||||||
if ctx
|
if ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()])
|
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()])
|
||||||
@ -289,18 +289,18 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
return Ok((i as INT).into());
|
return Ok(i as INT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((-1 as INT).into())
|
Ok(-1 as INT)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "index_of", return_raw, pure)]
|
#[rhai_fn(name = "index_of", return_raw, pure)]
|
||||||
pub fn index_of_filter(
|
pub fn index_of_filter(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<INT, Box<EvalAltResult>> {
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if filter
|
if filter
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
.call_dynamic(&ctx, None, [item.clone()])
|
||||||
@ -323,18 +323,18 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
return Ok((i as INT).into());
|
return Ok(i as INT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((-1 as INT).into())
|
Ok(-1 as INT)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, pure)]
|
#[rhai_fn(return_raw, pure)]
|
||||||
pub fn some(
|
pub fn some(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<bool, Box<EvalAltResult>> {
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if filter
|
if filter
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
.call_dynamic(&ctx, None, [item.clone()])
|
||||||
@ -357,18 +357,18 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
return Ok(true.into());
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false.into())
|
Ok(false)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, pure)]
|
#[rhai_fn(return_raw, pure)]
|
||||||
pub fn all(
|
pub fn all(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<bool, Box<EvalAltResult>> {
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if !filter
|
if !filter
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
.call_dynamic(&ctx, None, [item.clone()])
|
||||||
@ -391,11 +391,11 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
return Ok(false.into());
|
return Ok(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(true.into())
|
Ok(true)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, pure)]
|
#[rhai_fn(return_raw, pure)]
|
||||||
pub fn reduce(
|
pub fn reduce(
|
||||||
@ -403,7 +403,7 @@ mod array_functions {
|
|||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut result: Dynamic = Dynamic::UNIT;
|
let mut result = Dynamic::UNIT;
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
result = reducer
|
result = reducer
|
||||||
@ -433,16 +433,9 @@ mod array_functions {
|
|||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
initial: FnPtr,
|
initial: Dynamic,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut result = initial.call_dynamic(&ctx, None, []).map_err(|err| {
|
let mut result = initial;
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
||||||
"reduce".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
result = reducer
|
result = reducer
|
||||||
@ -473,7 +466,7 @@ mod array_functions {
|
|||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut result: Dynamic = Dynamic::UNIT;
|
let mut result = Dynamic::UNIT;
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate().rev() {
|
for (i, item) in array.iter().enumerate().rev() {
|
||||||
result = reducer
|
result = reducer
|
||||||
@ -503,16 +496,9 @@ mod array_functions {
|
|||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
initial: FnPtr,
|
initial: Dynamic,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut result = initial.call_dynamic(&ctx, None, []).map_err(|err| {
|
let mut result = initial;
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
||||||
"reduce_rev".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate().rev() {
|
for (i, item) in array.iter().enumerate().rev() {
|
||||||
result = reducer
|
result = reducer
|
||||||
@ -542,7 +528,7 @@ mod array_functions {
|
|||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
comparer: FnPtr,
|
comparer: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
array.sort_by(|x, y| {
|
array.sort_by(|x, y| {
|
||||||
comparer
|
comparer
|
||||||
.call_dynamic(&ctx, None, [x.clone(), y.clone()])
|
.call_dynamic(&ctx, None, [x.clone(), y.clone()])
|
||||||
@ -571,14 +557,14 @@ mod array_functions {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn drain(
|
pub fn drain(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Array, Box<EvalAltResult>> {
|
||||||
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
let mut i = array.len();
|
let mut i = array.len();
|
||||||
@ -611,7 +597,7 @@ mod array_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(drained.into())
|
Ok(drained)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "drain")]
|
#[rhai_fn(name = "drain")]
|
||||||
pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
||||||
@ -638,7 +624,7 @@ mod array_functions {
|
|||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Array, Box<EvalAltResult>> {
|
||||||
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
let mut i = array.len();
|
let mut i = array.len();
|
||||||
@ -671,7 +657,7 @@ mod array_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(drained.into())
|
Ok(drained)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "retain")]
|
#[rhai_fn(name = "retain")]
|
||||||
pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
||||||
@ -701,12 +687,12 @@ mod array_functions {
|
|||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
mut array2: Array,
|
mut array2: Array,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<bool, Box<EvalAltResult>> {
|
||||||
if array.len() != array2.len() {
|
if array.len() != array2.len() {
|
||||||
return Ok(false.into());
|
return Ok(false);
|
||||||
}
|
}
|
||||||
if array.is_empty() {
|
if array.is_empty() {
|
||||||
return Ok(true.into());
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (a1, a2) in array.iter_mut().zip(array2.iter_mut()) {
|
for (a1, a2) in array.iter_mut().zip(array2.iter_mut()) {
|
||||||
@ -728,18 +714,18 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
return Ok(Dynamic::FALSE);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Dynamic::TRUE)
|
Ok(true)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "!=", return_raw, pure)]
|
#[rhai_fn(name = "!=", return_raw, pure)]
|
||||||
pub fn not_equals(
|
pub fn not_equals(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
array: &mut Array,
|
array: &mut Array,
|
||||||
array2: Array,
|
array2: Array,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<bool, Box<EvalAltResult>> {
|
||||||
equals(ctx, array, array2).map(|r| (!r.as_bool().unwrap()).into())
|
equals(ctx, array, array2).map(|r| !r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,12 @@ mod map_functions {
|
|||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
map: &mut Map,
|
map: &mut Map,
|
||||||
mut map2: Map,
|
mut map2: Map,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<bool, Box<EvalAltResult>> {
|
||||||
if map.len() != map2.len() {
|
if map.len() != map2.len() {
|
||||||
return Ok(false.into());
|
return Ok(false);
|
||||||
}
|
}
|
||||||
if map.is_empty() {
|
if map.is_empty() {
|
||||||
return Ok(true.into());
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (m1, v1) in map.iter_mut() {
|
for (m1, v1) in map.iter_mut() {
|
||||||
@ -61,22 +61,22 @@ mod map_functions {
|
|||||||
.map(|v| v.as_bool().unwrap_or(false))?;
|
.map(|v| v.as_bool().unwrap_or(false))?;
|
||||||
|
|
||||||
if !equals {
|
if !equals {
|
||||||
return Ok(false.into());
|
return Ok(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(false.into());
|
return Ok(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(true.into())
|
Ok(true)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "!=", return_raw, pure)]
|
#[rhai_fn(name = "!=", return_raw, pure)]
|
||||||
pub fn not_equals(
|
pub fn not_equals(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
map: &mut Map,
|
map: &mut Map,
|
||||||
map2: Map,
|
map2: Map,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<bool, Box<EvalAltResult>> {
|
||||||
equals(ctx, map, map2).map(|r| (!r.as_bool().unwrap()).into())
|
equals(ctx, map, map2).map(|r| !r)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
@ -113,7 +113,7 @@ def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, {
|
|||||||
#[export_module]
|
#[export_module]
|
||||||
mod int_functions {
|
mod int_functions {
|
||||||
#[rhai_fn(name = "parse_int", return_raw)]
|
#[rhai_fn(name = "parse_int", return_raw)]
|
||||||
pub fn parse_int_radix(s: &str, radix: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn parse_int_radix(s: &str, radix: INT) -> Result<INT, Box<EvalAltResult>> {
|
||||||
if radix < 2 || radix > 36 {
|
if radix < 2 || radix > 36 {
|
||||||
return EvalAltResult::ErrorArithmetic(
|
return EvalAltResult::ErrorArithmetic(
|
||||||
format!("Invalid radix: '{}'", radix),
|
format!("Invalid radix: '{}'", radix),
|
||||||
@ -122,9 +122,7 @@ mod int_functions {
|
|||||||
.into();
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
INT::from_str_radix(s.trim(), radix as u32)
|
INT::from_str_radix(s.trim(), radix as u32).map_err(|err| {
|
||||||
.map(Into::<Dynamic>::into)
|
|
||||||
.map_err(|err| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Error parsing integer number '{}': {}", s, err),
|
format!("Error parsing integer number '{}': {}", s, err),
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
@ -133,7 +131,7 @@ mod int_functions {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "parse_int", return_raw)]
|
#[rhai_fn(name = "parse_int", return_raw)]
|
||||||
pub fn parse_int(s: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn parse_int(s: &str) -> Result<INT, Box<EvalAltResult>> {
|
||||||
parse_int_radix(s, 10)
|
parse_int_radix(s, 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +259,7 @@ mod float_functions {
|
|||||||
x.is_infinite()
|
x.is_infinite()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "to_int", return_raw)]
|
#[rhai_fn(name = "to_int", return_raw)]
|
||||||
pub fn f32_to_int(x: f32) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn f32_to_int(x: f32) -> Result<INT, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f32) {
|
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f32) {
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Integer overflow: to_int({})", x),
|
format!("Integer overflow: to_int({})", x),
|
||||||
@ -269,11 +267,11 @@ mod float_functions {
|
|||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
Ok((x.trunc() as INT).into())
|
Ok(x.trunc() as INT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "to_int", return_raw)]
|
#[rhai_fn(name = "to_int", return_raw)]
|
||||||
pub fn f64_to_int(x: f64) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn f64_to_int(x: f64) -> Result<INT, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f64) {
|
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f64) {
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Integer overflow: to_int({})", x),
|
format!("Integer overflow: to_int({})", x),
|
||||||
@ -281,15 +279,12 @@ mod float_functions {
|
|||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
Ok((x.trunc() as INT).into())
|
Ok(x.trunc() as INT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn parse_float(s: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn parse_float(s: &str) -> Result<f64, Box<EvalAltResult>> {
|
||||||
s.trim()
|
s.trim().parse::<FLOAT>().map_err(|err| {
|
||||||
.parse::<FLOAT>()
|
|
||||||
.map(Into::<Dynamic>::into)
|
|
||||||
.map_err(|err| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Error parsing floating-point number '{}': {}", s, err),
|
format!("Error parsing floating-point number '{}': {}", s, err),
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
@ -327,10 +322,10 @@ mod decimal_functions {
|
|||||||
x.round()
|
x.round()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "round", return_raw)]
|
#[rhai_fn(name = "round", return_raw)]
|
||||||
pub fn round_dp(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn round_dp(x: Decimal, dp: INT) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
||||||
return Ok(x.into());
|
return Ok(x);
|
||||||
}
|
}
|
||||||
if dp < 0 {
|
if dp < 0 {
|
||||||
return Err(make_err(format!(
|
return Err(make_err(format!(
|
||||||
@ -340,13 +335,13 @@ mod decimal_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(x.round_dp(dp as u32).into())
|
Ok(x.round_dp(dp as u32))
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn round_up(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn round_up(x: Decimal, dp: INT) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
||||||
return Ok(x.into());
|
return Ok(x);
|
||||||
}
|
}
|
||||||
if dp < 0 {
|
if dp < 0 {
|
||||||
return Err(make_err(format!(
|
return Err(make_err(format!(
|
||||||
@ -356,16 +351,13 @@ mod decimal_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundUp))
|
||||||
x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundUp)
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn round_down(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn round_down(x: Decimal, dp: INT) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
||||||
return Ok(x.into());
|
return Ok(x);
|
||||||
}
|
}
|
||||||
if dp < 0 {
|
if dp < 0 {
|
||||||
return Err(make_err(format!(
|
return Err(make_err(format!(
|
||||||
@ -375,16 +367,13 @@ mod decimal_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundDown))
|
||||||
x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundDown)
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn round_half_up(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn round_half_up(x: Decimal, dp: INT) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
||||||
return Ok(x.into());
|
return Ok(x);
|
||||||
}
|
}
|
||||||
if dp < 0 {
|
if dp < 0 {
|
||||||
return Err(make_err(format!(
|
return Err(make_err(format!(
|
||||||
@ -394,16 +383,13 @@ mod decimal_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundHalfUp))
|
||||||
x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundHalfUp)
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn round_half_down(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn round_half_down(x: Decimal, dp: INT) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
||||||
return Ok(x.into());
|
return Ok(x);
|
||||||
}
|
}
|
||||||
if dp < 0 {
|
if dp < 0 {
|
||||||
return Err(make_err(format!(
|
return Err(make_err(format!(
|
||||||
@ -413,10 +399,7 @@ mod decimal_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundHalfDown))
|
||||||
x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundHalfDown)
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "int", get = "int")]
|
#[rhai_fn(name = "int", get = "int")]
|
||||||
pub fn int(x: Decimal) -> Decimal {
|
pub fn int(x: Decimal) -> Decimal {
|
||||||
@ -427,10 +410,9 @@ mod decimal_functions {
|
|||||||
x.fract()
|
x.fract()
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn parse_decimal(s: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn parse_decimal(s: &str) -> Result<Decimal, Box<EvalAltResult>> {
|
||||||
Decimal::from_str(s)
|
Decimal::from_str(s)
|
||||||
.or_else(|_| Decimal::from_scientific(s))
|
.or_else(|_| Decimal::from_scientific(s))
|
||||||
.map(Into::<Dynamic>::into)
|
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Error parsing decimal number '{}': {}", s, err),
|
format!("Error parsing decimal number '{}': {}", s, err),
|
||||||
|
@ -235,7 +235,7 @@ mod string_functions {
|
|||||||
string: &mut ImmutableString,
|
string: &mut ImmutableString,
|
||||||
len: INT,
|
len: INT,
|
||||||
character: char,
|
character: char,
|
||||||
) -> Result<Dynamic, Box<crate::EvalAltResult>> {
|
) -> Result<(), Box<crate::EvalAltResult>> {
|
||||||
// Check if string will be over max size limit
|
// Check if string will be over max size limit
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
|
if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
|
||||||
@ -269,7 +269,7 @@ mod string_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "pad", return_raw)]
|
#[rhai_fn(name = "pad", return_raw)]
|
||||||
pub fn pad_with_string(
|
pub fn pad_with_string(
|
||||||
@ -277,7 +277,7 @@ mod string_functions {
|
|||||||
string: &mut ImmutableString,
|
string: &mut ImmutableString,
|
||||||
len: INT,
|
len: INT,
|
||||||
padding: &str,
|
padding: &str,
|
||||||
) -> Result<Dynamic, Box<crate::EvalAltResult>> {
|
) -> Result<(), Box<crate::EvalAltResult>> {
|
||||||
// Check if string will be over max size limit
|
// Check if string will be over max size limit
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
|
if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
|
||||||
@ -318,7 +318,7 @@ mod string_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
@ -143,28 +143,28 @@ mod time_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(return_raw, name = "+")]
|
#[rhai_fn(return_raw, name = "+")]
|
||||||
pub fn add(timestamp: Instant, seconds: FLOAT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add(timestamp: Instant, seconds: FLOAT) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
add_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
add_impl(timestamp, seconds)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "+=")]
|
#[rhai_fn(return_raw, name = "+=")]
|
||||||
pub fn add_assign(
|
pub fn add_assign(
|
||||||
timestamp: &mut Instant,
|
timestamp: &mut Instant,
|
||||||
seconds: FLOAT,
|
seconds: FLOAT,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
*timestamp = add_impl(*timestamp, seconds)?;
|
*timestamp = add_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-")]
|
#[rhai_fn(return_raw, name = "-")]
|
||||||
pub fn subtract(timestamp: Instant, seconds: FLOAT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract(timestamp: Instant, seconds: FLOAT) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
subtract_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
subtract_impl(timestamp, seconds)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-=")]
|
#[rhai_fn(return_raw, name = "-=")]
|
||||||
pub fn subtract_assign(
|
pub fn subtract_assign(
|
||||||
timestamp: &mut Instant,
|
timestamp: &mut Instant,
|
||||||
seconds: FLOAT,
|
seconds: FLOAT,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
*timestamp = subtract_impl(*timestamp, seconds)?;
|
*timestamp = subtract_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,28 +202,25 @@ mod time_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(return_raw, name = "+")]
|
#[rhai_fn(return_raw, name = "+")]
|
||||||
pub fn add(timestamp: Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add(timestamp: Instant, seconds: INT) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
add_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
add_impl(timestamp, seconds)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "+=")]
|
#[rhai_fn(return_raw, name = "+=")]
|
||||||
pub fn add_assign(
|
pub fn add_assign(timestamp: &mut Instant, seconds: INT) -> Result<(), Box<EvalAltResult>> {
|
||||||
timestamp: &mut Instant,
|
|
||||||
seconds: INT,
|
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
*timestamp = add_impl(*timestamp, seconds)?;
|
*timestamp = add_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-")]
|
#[rhai_fn(return_raw, name = "-")]
|
||||||
pub fn subtract(timestamp: Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract(timestamp: Instant, seconds: INT) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
subtract_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
subtract_impl(timestamp, seconds)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-=")]
|
#[rhai_fn(return_raw, name = "-=")]
|
||||||
pub fn subtract_assign(
|
pub fn subtract_assign(
|
||||||
timestamp: &mut Instant,
|
timestamp: &mut Instant,
|
||||||
seconds: INT,
|
seconds: INT,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
*timestamp = subtract_impl(*timestamp, seconds)?;
|
*timestamp = subtract_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "==")]
|
#[rhai_fn(name = "==")]
|
||||||
|
@ -9,7 +9,7 @@ use crate::stdlib::{
|
|||||||
|
|
||||||
/// Cast a type into another type.
|
/// Cast a type into another type.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn unsafe_try_cast<A: Any, B: Any>(a: A) -> Option<B> {
|
pub fn unsafe_try_cast<A: Any, B: Any>(a: A) -> Result<B, A> {
|
||||||
if TypeId::of::<B>() == a.type_id() {
|
if TypeId::of::<B>() == a.type_id() {
|
||||||
// SAFETY: Just checked we have the right type. We explicitly forget the
|
// SAFETY: Just checked we have the right type. We explicitly forget the
|
||||||
// value immediately after moving out, removing any chance of a destructor
|
// value immediately after moving out, removing any chance of a destructor
|
||||||
@ -17,10 +17,10 @@ pub fn unsafe_try_cast<A: Any, B: Any>(a: A) -> Option<B> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let ret: B = ptr::read(&a as *const _ as *const B);
|
let ret: B = ptr::read(&a as *const _ as *const B);
|
||||||
mem::forget(a);
|
mem::forget(a);
|
||||||
Some(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user