Refine function call parameters size.
This commit is contained in:
parent
c4f00afbee
commit
21b989afd5
@ -37,6 +37,7 @@ use crate::stdlib::{
|
|||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fmt, format,
|
fmt, format,
|
||||||
iter::{empty, once},
|
iter::{empty, once},
|
||||||
|
num::NonZeroUsize,
|
||||||
ops::DerefMut,
|
ops::DerefMut,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
@ -250,8 +251,8 @@ impl<'a> Target<'a> {
|
|||||||
Self::LockGuard(_) => (),
|
Self::LockGuard(_) => (),
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Self::StringChar(_, _, ch) => {
|
Self::StringChar(_, _, ch) => {
|
||||||
let new_val = ch.clone();
|
let char_value = ch.clone();
|
||||||
self.set_value((new_val, Position::none()), Position::none())
|
self.set_value((char_value, Position::none()), Position::none())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,10 +285,9 @@ impl<'a> Target<'a> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut chars = s.chars().collect::<StaticVec<_>>();
|
let mut chars = s.chars().collect::<StaticVec<_>>();
|
||||||
let ch = chars[*index];
|
|
||||||
|
|
||||||
// See if changed - if so, update the String
|
// See if changed - if so, update the String
|
||||||
if ch != new_ch {
|
if chars[*index] != new_ch {
|
||||||
chars[*index] = new_ch;
|
chars[*index] = new_ch;
|
||||||
*s = chars.iter().collect::<String>().into();
|
*s = chars.iter().collect::<String>().into();
|
||||||
}
|
}
|
||||||
@ -520,13 +520,13 @@ pub fn search_imports<'s>(
|
|||||||
|
|
||||||
// Qualified - check if the root module is directly indexed
|
// Qualified - check if the root module is directly indexed
|
||||||
let index = if state.always_search {
|
let index = if state.always_search {
|
||||||
None
|
0
|
||||||
} else {
|
} else {
|
||||||
modules.index()
|
modules.index().map_or(0, NonZeroUsize::get)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(if let Some(index) = index {
|
Ok(if index > 0 {
|
||||||
let offset = mods.len() - index.get();
|
let offset = mods.len() - index;
|
||||||
&mods.get(offset).unwrap().1
|
&mods.get(offset).unwrap().1
|
||||||
} else {
|
} else {
|
||||||
mods.iter()
|
mods.iter()
|
||||||
@ -548,13 +548,13 @@ pub fn search_imports_mut<'s>(
|
|||||||
|
|
||||||
// Qualified - check if the root module is directly indexed
|
// Qualified - check if the root module is directly indexed
|
||||||
let index = if state.always_search {
|
let index = if state.always_search {
|
||||||
None
|
0
|
||||||
} else {
|
} else {
|
||||||
modules.index()
|
modules.index().map_or(0, NonZeroUsize::get)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(if let Some(index) = index {
|
Ok(if index > 0 {
|
||||||
let offset = mods.len() - index.get();
|
let offset = mods.len() - index;
|
||||||
&mut mods.get_mut(offset).unwrap().1
|
&mut mods.get_mut(offset).unwrap().1
|
||||||
} else {
|
} else {
|
||||||
mods.iter_mut()
|
mods.iter_mut()
|
||||||
@ -684,19 +684,15 @@ impl Engine {
|
|||||||
// Qualified variable
|
// Qualified variable
|
||||||
((name, pos), Some(modules), hash_var, _) => {
|
((name, pos), Some(modules), hash_var, _) => {
|
||||||
let module = search_imports_mut(mods, state, modules)?;
|
let module = search_imports_mut(mods, state, modules)?;
|
||||||
let target =
|
let target = module.get_qualified_var_mut(*hash_var).map_err(|mut err| {
|
||||||
module
|
match *err {
|
||||||
.get_qualified_var_mut(*hash_var)
|
EvalAltResult::ErrorVariableNotFound(ref mut err_name, _) => {
|
||||||
.map_err(|err| match *err {
|
*err_name = format!("{}{}", modules, name);
|
||||||
EvalAltResult::ErrorVariableNotFound(_, _) => {
|
}
|
||||||
EvalAltResult::ErrorVariableNotFound(
|
_ => (),
|
||||||
format!("{}{}", modules, name),
|
}
|
||||||
*pos,
|
err.fill_position(*pos)
|
||||||
)
|
})?;
|
||||||
.into()
|
|
||||||
}
|
|
||||||
_ => err.fill_position(*pos),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Module variables are constant
|
// Module variables are constant
|
||||||
Ok((target.into(), name, ScopeEntryType::Constant, *pos))
|
Ok((target.into(), name, ScopeEntryType::Constant, *pos))
|
||||||
@ -733,7 +729,11 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if it is directly indexed
|
// Check if it is directly indexed
|
||||||
let index = if state.always_search { None } else { *index };
|
let index = if state.always_search {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
index.map_or(0, NonZeroUsize::get)
|
||||||
|
};
|
||||||
|
|
||||||
// Check the variable resolver, if any
|
// Check the variable resolver, if any
|
||||||
if let Some(ref resolve_var) = self.resolve_var {
|
if let Some(ref resolve_var) = self.resolve_var {
|
||||||
@ -745,15 +745,15 @@ impl Engine {
|
|||||||
this_ptr,
|
this_ptr,
|
||||||
level: 0,
|
level: 0,
|
||||||
};
|
};
|
||||||
if let Some(result) = resolve_var(name, index.map_or(0, |v| v.get()), scope, &context)
|
if let Some(result) =
|
||||||
.map_err(|err| err.fill_position(*pos))?
|
resolve_var(name, index, scope, &context).map_err(|err| err.fill_position(*pos))?
|
||||||
{
|
{
|
||||||
return Ok((result.into(), name, ScopeEntryType::Constant, *pos));
|
return Ok((result.into(), name, ScopeEntryType::Constant, *pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = if let Some(index) = index {
|
let index = if index > 0 {
|
||||||
scope.len() - index.get()
|
scope.len() - index
|
||||||
} else {
|
} else {
|
||||||
// Find the variable in the scope
|
// Find the variable in the scope
|
||||||
scope
|
scope
|
||||||
|
@ -50,10 +50,6 @@ use crate::stdlib::{
|
|||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
use crate::stdlib::{collections::HashSet, string::String};
|
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use num_traits::float::Float;
|
use num_traits::float::Float;
|
||||||
@ -146,29 +142,6 @@ impl Drop for ArgBackup<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add captured variables into scope
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
fn add_captured_variables_into_scope<'s>(
|
|
||||||
externals: &HashSet<String>,
|
|
||||||
captured: Scope<'s>,
|
|
||||||
scope: &mut Scope<'s>,
|
|
||||||
) {
|
|
||||||
captured
|
|
||||||
.into_iter()
|
|
||||||
.filter(|ScopeEntry { name, .. }| externals.contains(name.as_ref()))
|
|
||||||
.for_each(
|
|
||||||
|ScopeEntry {
|
|
||||||
name, typ, value, ..
|
|
||||||
}| {
|
|
||||||
match typ {
|
|
||||||
ScopeEntryType::Normal => scope.push(name, value),
|
|
||||||
ScopeEntryType::Constant => scope.push_constant(name, value),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn ensure_no_data_race(
|
pub fn ensure_no_data_race(
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
@ -483,6 +456,8 @@ impl Engine {
|
|||||||
/// Perform an actual function call, native Rust or scripted, taking care of special functions.
|
/// Perform an actual function call, native Rust or scripted, taking care of special functions.
|
||||||
/// Position in `EvalAltResult` is `None` and must be set afterwards.
|
/// Position in `EvalAltResult` is `None` and must be set afterwards.
|
||||||
///
|
///
|
||||||
|
/// Capture `Scope` is consumed by this function.
|
||||||
|
///
|
||||||
/// ## WARNING
|
/// ## WARNING
|
||||||
///
|
///
|
||||||
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
||||||
@ -498,7 +473,7 @@ impl Engine {
|
|||||||
is_ref: bool,
|
is_ref: bool,
|
||||||
_is_method: bool,
|
_is_method: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
_capture: Option<Scope>,
|
_capture: Option<&mut Scope>, // `Scope` is consumed.
|
||||||
def_val: &Option<Dynamic>,
|
def_val: &Option<Dynamic>,
|
||||||
_level: usize,
|
_level: usize,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
@ -574,10 +549,29 @@ impl Engine {
|
|||||||
let scope = &mut Scope::new();
|
let scope = &mut Scope::new();
|
||||||
let mods = &mut Imports::new();
|
let mods = &mut Imports::new();
|
||||||
|
|
||||||
// Add captured variables into scope
|
// Move captured variables into scope
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
if let Some(captured) = _capture {
|
if let Some(captured) = _capture {
|
||||||
add_captured_variables_into_scope(&func.externals, captured, scope);
|
captured
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|ScopeEntry { name, .. }| {
|
||||||
|
func.externals.contains(name.as_ref())
|
||||||
|
})
|
||||||
|
.for_each(
|
||||||
|
|ScopeEntry {
|
||||||
|
name, typ, value, ..
|
||||||
|
}| {
|
||||||
|
// Consume the scope values.
|
||||||
|
match typ {
|
||||||
|
ScopeEntryType::Normal => {
|
||||||
|
scope.push(name.clone(), mem::take(value))
|
||||||
|
}
|
||||||
|
ScopeEntryType::Constant => {
|
||||||
|
scope.push_constant(name.clone(), mem::take(value))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = if _is_method {
|
let result = if _is_method {
|
||||||
@ -1019,11 +1013,13 @@ impl Engine {
|
|||||||
let mut arg_values: StaticVec<_>;
|
let mut arg_values: StaticVec<_>;
|
||||||
let mut args: StaticVec<_>;
|
let mut args: StaticVec<_>;
|
||||||
let mut is_ref = false;
|
let mut is_ref = false;
|
||||||
let capture = if cfg!(not(feature = "no_closure")) && capture && !scope.is_empty() {
|
let mut capture_scope = if cfg!(not(feature = "no_closure")) && capture && !scope.is_empty()
|
||||||
Some(scope.flatten_clone())
|
{
|
||||||
|
Some(scope.clone_visible())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
let capture = capture_scope.as_mut();
|
||||||
|
|
||||||
if args_expr.is_empty() && curry.is_empty() {
|
if args_expr.is_empty() && curry.is_empty() {
|
||||||
// No arguments
|
// No arguments
|
||||||
@ -1189,20 +1185,12 @@ impl Engine {
|
|||||||
let args = args.as_mut();
|
let args = args.as_mut();
|
||||||
let func = f.get_fn_def();
|
let func = f.get_fn_def();
|
||||||
|
|
||||||
let scope = &mut Scope::new();
|
let new_scope = &mut Scope::new();
|
||||||
let mods = &mut Imports::new();
|
let mods = &mut Imports::new();
|
||||||
|
|
||||||
// Add captured variables into scope
|
self.call_script_fn(
|
||||||
#[cfg(not(feature = "no_closure"))]
|
new_scope, mods, state, lib, &mut None, name, func, args, level,
|
||||||
if _capture && !scope.is_empty() {
|
)
|
||||||
add_captured_variables_into_scope(
|
|
||||||
&func.externals,
|
|
||||||
scope.flatten_clone(),
|
|
||||||
scope,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.call_script_fn(scope, mods, state, lib, &mut None, name, func, args, level)
|
|
||||||
}
|
}
|
||||||
Some(f) if f.is_plugin_fn() => f.get_plugin_fn().call(args.as_mut()),
|
Some(f) if f.is_plugin_fn() => f.get_plugin_fn().call(args.as_mut()),
|
||||||
Some(f) if f.is_native() => {
|
Some(f) if f.is_native() => {
|
||||||
|
@ -420,7 +420,7 @@ impl<'a> Scope<'a> {
|
|||||||
/// Clone the Scope, keeping only the last instances of each variable name.
|
/// Clone the Scope, keeping only the last instances of each variable name.
|
||||||
/// Shadowed variables are omitted in the copy.
|
/// Shadowed variables are omitted in the copy.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn flatten_clone(&self) -> Self {
|
pub(crate) fn clone_visible(&self) -> Self {
|
||||||
let mut entries: Vec<Entry> = Default::default();
|
let mut entries: Vec<Entry> = Default::default();
|
||||||
|
|
||||||
self.0.iter().rev().for_each(|entry| {
|
self.0.iter().rev().for_each(|entry| {
|
||||||
@ -488,6 +488,12 @@ impl<'a> Scope<'a> {
|
|||||||
}| { (name.as_ref(), typ.is_constant(), value) },
|
}| { (name.as_ref(), typ.is_constant(), value) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a mutable iterator to entries in the Scope.
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn iter_mut(&mut self) -> impl Iterator<Item = &mut Entry<'a>> {
|
||||||
|
self.0.iter_mut()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: Into<Cow<'a, str>>> iter::Extend<(K, EntryType, Dynamic)> for Scope<'a> {
|
impl<'a, K: Into<Cow<'a, str>>> iter::Extend<(K, EntryType, Dynamic)> for Scope<'a> {
|
||||||
|
Loading…
Reference in New Issue
Block a user