Simplify chaining code.
This commit is contained in:
@@ -394,6 +394,7 @@ impl Engine {
|
||||
}
|
||||
|
||||
// Run external function
|
||||
let is_method = func.is_method();
|
||||
let src = source.as_ref().map(|s| s.as_str());
|
||||
let context = (self, name, src, &*global, pos).into();
|
||||
|
||||
@@ -403,13 +404,15 @@ impl Engine {
|
||||
Err(ERR::ErrorNonPureMethodCallOnConstant(name.to_string(), pos).into())
|
||||
} else {
|
||||
f.call(context, args)
|
||||
.and_then(|r| self.check_data_size(r, pos))
|
||||
.map_err(|err| err.fill_position(pos))
|
||||
}
|
||||
} else {
|
||||
func.get_native_fn().unwrap()(context, args)
|
||||
.and_then(|r| self.check_data_size(r, pos))
|
||||
.map_err(|err| err.fill_position(pos))
|
||||
};
|
||||
|
||||
let is_method = func.is_method();
|
||||
|
||||
#[cfg(feature = "debugging")]
|
||||
{
|
||||
use crate::eval::{DebuggerEvent, DebuggerStatus};
|
||||
@@ -440,13 +443,12 @@ impl Engine {
|
||||
global.debugger.rewind_call_stack(orig_call_stack_len);
|
||||
}
|
||||
|
||||
// Check the return value (including data sizes)
|
||||
let result = self.check_return_value(_result, pos)?;
|
||||
let result = _result?;
|
||||
|
||||
// Check the data size of any `&mut` object, which may be changed.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if is_ref_mut && !args.is_empty() {
|
||||
self.check_data_size(args[0], pos)?;
|
||||
self.check_data_size(&*args[0], pos)?;
|
||||
}
|
||||
|
||||
// See if the function match print/debug (which requires special processing)
|
||||
@@ -1189,14 +1191,14 @@ impl Engine {
|
||||
.map(|(value, ..)| arg_values.push(value.flatten()))
|
||||
})?;
|
||||
|
||||
let (mut target, _pos) =
|
||||
let mut target =
|
||||
self.search_namespace(global, caches, scope, this_ptr, first_expr)?;
|
||||
|
||||
if target.is_read_only() {
|
||||
target = target.into_owned();
|
||||
}
|
||||
|
||||
self.track_operation(global, _pos)?;
|
||||
self.track_operation(global, first_expr.position())?;
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let target_is_shared = target.is_shared();
|
||||
@@ -1270,10 +1272,9 @@ impl Engine {
|
||||
|
||||
// Get target reference to first argument
|
||||
let first_arg = &args_expr[0];
|
||||
let (target, _pos) =
|
||||
self.search_scope_only(global, caches, scope, this_ptr, first_arg)?;
|
||||
let target = self.search_scope_only(global, caches, scope, this_ptr, first_arg)?;
|
||||
|
||||
self.track_operation(global, _pos)?;
|
||||
self.track_operation(global, first_arg.position())?;
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let target_is_shared = target.is_shared();
|
||||
@@ -1383,19 +1384,18 @@ impl Engine {
|
||||
Some(f) if f.is_plugin_fn() => {
|
||||
let context = (self, fn_name, module.id(), &*global, pos).into();
|
||||
let f = f.get_plugin_fn().expect("plugin function");
|
||||
let result = if !f.is_pure() && !args.is_empty() && args[0].is_read_only() {
|
||||
if !f.is_pure() && !args.is_empty() && args[0].is_read_only() {
|
||||
Err(ERR::ErrorNonPureMethodCallOnConstant(fn_name.to_string(), pos).into())
|
||||
} else {
|
||||
f.call(context, &mut args)
|
||||
};
|
||||
self.check_return_value(result, pos)
|
||||
.and_then(|r| self.check_data_size(r, pos))
|
||||
}
|
||||
}
|
||||
|
||||
Some(f) if f.is_native() => {
|
||||
let func = f.get_native_fn().expect("native function");
|
||||
let context = (self, fn_name, module.id(), &*global, pos).into();
|
||||
let result = func(context, &mut args);
|
||||
self.check_return_value(result, pos)
|
||||
func(context, &mut args).and_then(|r| self.check_data_size(r, pos))
|
||||
}
|
||||
|
||||
Some(f) => unreachable!("unknown function type: {:?}", f),
|
||||
|
@@ -92,7 +92,7 @@ pub fn get_hasher() -> ahash::AHasher {
|
||||
///
|
||||
/// # Zeros
|
||||
///
|
||||
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||
/// If the hash happens to be zero, it is mapped to `ALT_ZERO_HASH`.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
@@ -107,9 +107,8 @@ pub fn calc_var_hash<'a>(
|
||||
|
||||
// We always skip the first module
|
||||
let iter = modules.into_iter();
|
||||
let len = iter.len();
|
||||
iter.len().hash(s);
|
||||
iter.skip(1).for_each(|m| m.hash(s));
|
||||
len.hash(s);
|
||||
var_name.hash(s);
|
||||
|
||||
match s.finish() {
|
||||
@@ -128,7 +127,7 @@ pub fn calc_var_hash<'a>(
|
||||
///
|
||||
/// # Zeros
|
||||
///
|
||||
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||
/// If the hash happens to be zero, it is mapped to `ALT_ZERO_HASH`.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
@@ -144,9 +143,8 @@ pub fn calc_fn_hash<'a>(
|
||||
|
||||
// We always skip the first module
|
||||
let iter = namespace.into_iter();
|
||||
let len = iter.len();
|
||||
iter.len().hash(s);
|
||||
iter.skip(1).for_each(|m| m.hash(s));
|
||||
len.hash(s);
|
||||
fn_name.hash(s);
|
||||
num.hash(s);
|
||||
|
||||
@@ -162,7 +160,7 @@ pub fn calc_fn_hash<'a>(
|
||||
///
|
||||
/// # Zeros
|
||||
///
|
||||
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||
/// If the hash happens to be zero, it is mapped to `ALT_ZERO_HASH`.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn calc_fn_hash_full(
|
||||
@@ -172,11 +170,10 @@ pub fn calc_fn_hash_full(
|
||||
let s = &mut get_hasher();
|
||||
base.hash(s);
|
||||
let iter = params.into_iter();
|
||||
let len = iter.len();
|
||||
iter.len().hash(s);
|
||||
iter.for_each(|t| {
|
||||
t.hash(s);
|
||||
});
|
||||
len.hash(s);
|
||||
|
||||
match s.finish() {
|
||||
0 => ALT_ZERO_HASH,
|
||||
|
@@ -303,7 +303,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
|
||||
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
||||
|
||||
let result = self._call_fn_raw(fn_name, false, false, false, &mut args)?;
|
||||
let result = self._call_fn_raw(fn_name, &mut args, false, false, false)?;
|
||||
|
||||
let typ = self.engine().map_type_name(result.type_name());
|
||||
|
||||
@@ -328,7 +328,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
|
||||
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
||||
|
||||
let result = self._call_fn_raw(fn_name, true, false, false, &mut args)?;
|
||||
let result = self._call_fn_raw(fn_name, &mut args, true, false, false)?;
|
||||
|
||||
let typ = self.engine().map_type_name(result.type_name());
|
||||
|
||||
@@ -369,7 +369,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
let native_only = native_only && !crate::parser::is_anonymous_fn(name);
|
||||
|
||||
self._call_fn_raw(fn_name, native_only, is_ref_mut, is_method_call, args)
|
||||
self._call_fn_raw(fn_name, args, native_only, is_ref_mut, is_method_call)
|
||||
}
|
||||
/// Call a registered native Rust function inside the call context.
|
||||
///
|
||||
@@ -398,17 +398,17 @@ impl<'a> NativeCallContext<'a> {
|
||||
is_ref_mut: bool,
|
||||
args: &mut [&mut Dynamic],
|
||||
) -> RhaiResult {
|
||||
self._call_fn_raw(fn_name, true, is_ref_mut, false, args)
|
||||
self._call_fn_raw(fn_name, args, true, is_ref_mut, false)
|
||||
}
|
||||
|
||||
/// Call a function (native Rust or scripted) inside the call context.
|
||||
fn _call_fn_raw(
|
||||
&self,
|
||||
fn_name: impl AsRef<str>,
|
||||
args: &mut [&mut Dynamic],
|
||||
native_only: bool,
|
||||
is_ref_mut: bool,
|
||||
is_method_call: bool,
|
||||
args: &mut [&mut Dynamic],
|
||||
) -> RhaiResult {
|
||||
let mut global = &mut self.global.clone();
|
||||
let caches = &mut Caches::new();
|
||||
|
Reference in New Issue
Block a user