Speed up FnPtr::call when there is a linked scripted function.
This commit is contained in:
parent
91f149270a
commit
1f815f995f
@ -158,7 +158,10 @@ impl Engine {
|
|||||||
if let Some(fn_def) = global.lib.iter().flat_map(|m| m.iter_script_fn()).find_map(
|
if let Some(fn_def) = global.lib.iter().flat_map(|m| m.iter_script_fn()).find_map(
|
||||||
|(_, _, f, _, func)| if f == v.3.as_str() { Some(func) } else { None },
|
|(_, _, f, _, func)| if f == v.3.as_str() { Some(func) } else { None },
|
||||||
) {
|
) {
|
||||||
let val: Dynamic = crate::FnPtr::from(fn_def.clone()).into();
|
let mut fn_ptr =
|
||||||
|
crate::FnPtr::new_unchecked(v.3.clone(), crate::StaticVec::new_const());
|
||||||
|
fn_ptr.set_fn_def(Some(fn_def.clone()));
|
||||||
|
let val: Dynamic = fn_ptr.into();
|
||||||
return Ok(val.into());
|
return Ok(val.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,6 +761,7 @@ impl Engine {
|
|||||||
// Linked to scripted function?
|
// Linked to scripted function?
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
if let Some(fn_def) = fn_ptr.fn_def() {
|
if let Some(fn_def) = fn_ptr.fn_def() {
|
||||||
|
if fn_def.params.len() == args.len() {
|
||||||
let mut this_ptr = Dynamic::NULL;
|
let mut this_ptr = Dynamic::NULL;
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -776,6 +777,7 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
.map(|v| (v, false));
|
.map(|v| (v, false));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
let is_anon = fn_ptr.is_anonymous();
|
let is_anon = fn_ptr.is_anonymous();
|
||||||
@ -827,7 +829,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
#[cfg(feature = "no_function")]
|
#[cfg(feature = "no_function")]
|
||||||
let (fn_name, is_anon, fn_curry) = {
|
let (fn_name, is_anon, fn_curry) = {
|
||||||
let (fn_name, fn_curry, fn_def) = fn_ptr.take_data();
|
let (fn_name, fn_curry) = fn_ptr.take_data();
|
||||||
(fn_name, false, fn_curry)
|
(fn_name, false, fn_curry)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -843,6 +845,7 @@ impl Engine {
|
|||||||
// Linked to scripted function?
|
// Linked to scripted function?
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
if let Some(fn_def) = fn_def {
|
if let Some(fn_def) = fn_def {
|
||||||
|
if fn_def.params.len() == args.len() {
|
||||||
// Check for data race.
|
// Check for data race.
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
ensure_no_data_race(&fn_def.name, args, false)?;
|
ensure_no_data_race(&fn_def.name, args, false)?;
|
||||||
@ -860,6 +863,7 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
.map(|v| (v, false));
|
.map(|v| (v, false));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add the first argument with the object pointer
|
// Add the first argument with the object pointer
|
||||||
args.insert(0, target.as_mut());
|
args.insert(0, target.as_mut());
|
||||||
@ -895,26 +899,14 @@ impl Engine {
|
|||||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, fn_call_pos));
|
return Err(self.make_type_mismatch_err::<FnPtr>(typ, fn_call_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_ptr = target.read_lock::<FnPtr>().expect("`FnPtr`");
|
let mut fn_ptr = target.read_lock::<FnPtr>().expect("`FnPtr`").clone();
|
||||||
|
|
||||||
// Curry call
|
// Append the new curried arguments to the existing list.
|
||||||
Ok((
|
call_args.iter_mut().map(mem::take).for_each(|value| {
|
||||||
if call_args.is_empty() {
|
fn_ptr.add_curry(value);
|
||||||
fn_ptr.clone()
|
});
|
||||||
} else {
|
|
||||||
FnPtr::new_unchecked(
|
Ok((fn_ptr.into(), false))
|
||||||
fn_ptr.fn_name_raw().clone(),
|
|
||||||
fn_ptr
|
|
||||||
.curry()
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.chain(call_args.iter_mut().map(mem::take))
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
false,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle is_shared()
|
// Handle is_shared()
|
||||||
@ -1045,7 +1037,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
#[cfg(feature = "no_function")]
|
#[cfg(feature = "no_function")]
|
||||||
let (fn_name, is_anon, fn_curry) = {
|
let (fn_name, is_anon, fn_curry) = {
|
||||||
let (fn_name, fn_curry, fn_def) = fn_ptr.take_data();
|
let (fn_name, fn_curry) = fn_ptr.take_data();
|
||||||
(fn_name, false, fn_curry)
|
(fn_name, false, fn_curry)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1054,6 +1046,7 @@ impl Engine {
|
|||||||
// Linked to scripted function?
|
// Linked to scripted function?
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
if let Some(fn_def) = fn_def {
|
if let Some(fn_def) = fn_def {
|
||||||
|
if fn_def.params.len() == curry.len() + a_expr.len() {
|
||||||
// Evaluate arguments
|
// Evaluate arguments
|
||||||
let mut arg_values = curry
|
let mut arg_values = curry
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -1064,7 +1057,6 @@ impl Engine {
|
|||||||
}))
|
}))
|
||||||
.collect::<RhaiResultOf<FnArgsVec<_>>>()?;
|
.collect::<RhaiResultOf<FnArgsVec<_>>>()?;
|
||||||
let args = &mut arg_values.iter_mut().collect::<FnArgsVec<_>>();
|
let args = &mut arg_values.iter_mut().collect::<FnArgsVec<_>>();
|
||||||
|
|
||||||
let mut this_ptr = Dynamic::NULL;
|
let mut this_ptr = Dynamic::NULL;
|
||||||
|
|
||||||
return self.call_script_fn(
|
return self.call_script_fn(
|
||||||
@ -1078,6 +1070,7 @@ impl Engine {
|
|||||||
pos,
|
pos,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect function name
|
// Redirect function name
|
||||||
redirected = fn_name;
|
redirected = fn_name;
|
||||||
|
@ -422,15 +422,15 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
is_ref_mut: bool,
|
is_ref_mut: bool,
|
||||||
is_method_call: bool,
|
is_method_call: bool,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let mut global = &mut self.global.clone();
|
let global = &mut self.global.clone();
|
||||||
|
global.level += 1;
|
||||||
|
|
||||||
let caches = &mut Caches::new();
|
let caches = &mut Caches::new();
|
||||||
|
|
||||||
let fn_name = fn_name.as_ref();
|
let fn_name = fn_name.as_ref();
|
||||||
let op_token = Token::lookup_symbol_from_syntax(fn_name).unwrap_or(NO_TOKEN);
|
let op_token = Token::lookup_symbol_from_syntax(fn_name).unwrap_or(NO_TOKEN);
|
||||||
let args_len = args.len();
|
let args_len = args.len();
|
||||||
|
|
||||||
global.level += 1;
|
|
||||||
|
|
||||||
if native_only {
|
if native_only {
|
||||||
return self
|
return self
|
||||||
.engine()
|
.engine()
|
||||||
|
@ -24,6 +24,49 @@ def_package! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Make a call to a function pointer.
|
||||||
|
///
|
||||||
|
/// If the function pointer is linked to a scripted function definition, use the appropriate number
|
||||||
|
/// of arguments to call it directly (one version attaches an extra numeric argument).
|
||||||
|
fn make_dual_arity_fn_ptr_call<const N: usize>(
|
||||||
|
fn_name: &str,
|
||||||
|
fn_ptr: &FnPtr,
|
||||||
|
ctx: &NativeCallContext,
|
||||||
|
items: [Dynamic; N],
|
||||||
|
number: usize,
|
||||||
|
) -> RhaiResult {
|
||||||
|
let arity = fn_ptr.fn_def().map(|f| f.params.len()).unwrap_or(0);
|
||||||
|
|
||||||
|
if arity == N {
|
||||||
|
fn_ptr.call_raw(&ctx, None, items)
|
||||||
|
} else if arity == N + 1 {
|
||||||
|
let mut items2 = crate::StaticVec::new_const();
|
||||||
|
items2.extend(IntoIterator::into_iter(items));
|
||||||
|
items2.push((number as INT).into());
|
||||||
|
fn_ptr.call_raw(&ctx, None, items2)
|
||||||
|
} else {
|
||||||
|
fn_ptr
|
||||||
|
.call_raw(&ctx, None, items.clone())
|
||||||
|
.or_else(|err| match *err {
|
||||||
|
ERR::ErrorFunctionNotFound(sig, ..) if sig.starts_with(fn_ptr.fn_name()) => {
|
||||||
|
let mut items2 = crate::StaticVec::new_const();
|
||||||
|
items2.extend(IntoIterator::into_iter(items));
|
||||||
|
items2.push((number as INT).into());
|
||||||
|
fn_ptr.call_raw(&ctx, None, items2)
|
||||||
|
}
|
||||||
|
_ => Err(err),
|
||||||
|
})
|
||||||
|
.map_err(|err| {
|
||||||
|
Box::new(ERR::ErrorInFunctionCall(
|
||||||
|
fn_name.to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
|
err,
|
||||||
|
Position::NONE,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod array_functions {
|
pub mod array_functions {
|
||||||
/// Number of elements in the array.
|
/// Number of elements in the array.
|
||||||
@ -658,26 +701,13 @@ pub mod array_functions {
|
|||||||
let mut ar = Array::with_capacity(array.len());
|
let mut ar = Array::with_capacity(array.len());
|
||||||
|
|
||||||
for (i, item) in array.into_iter().enumerate() {
|
for (i, item) in array.into_iter().enumerate() {
|
||||||
ar.push(
|
ar.push(make_dual_arity_fn_ptr_call(
|
||||||
mapper
|
"map",
|
||||||
.call_raw(&ctx, None, [item.clone()])
|
&mapper,
|
||||||
.or_else(|err| match *err {
|
&ctx,
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
[item],
|
||||||
if fn_sig.starts_with(mapper.fn_name()) =>
|
i,
|
||||||
{
|
)?);
|
||||||
mapper.call_raw(&ctx, None, [item, (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"map".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ar)
|
Ok(ar)
|
||||||
@ -748,24 +778,7 @@ pub mod array_functions {
|
|||||||
let mut ar = Array::new();
|
let mut ar = Array::new();
|
||||||
|
|
||||||
for (i, item) in array.into_iter().enumerate() {
|
for (i, item) in array.into_iter().enumerate() {
|
||||||
if filter
|
if make_dual_arity_fn_ptr_call("filter", &filter, &ctx, [item.clone()], i)?
|
||||||
.call_raw(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
|
||||||
{
|
|
||||||
filter.call_raw(&ctx, None, [item.clone(), (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"filter".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
@ -1058,24 +1071,7 @@ pub mod array_functions {
|
|||||||
let (start, ..) = calc_offset_len(array.len(), start, 0);
|
let (start, ..) = calc_offset_len(array.len(), start, 0);
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate().skip(start) {
|
for (i, item) in array.iter().enumerate().skip(start) {
|
||||||
if filter
|
if make_dual_arity_fn_ptr_call("index_of", &filter, &ctx, [item.clone()], i)?
|
||||||
.call_raw(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
|
||||||
{
|
|
||||||
filter.call_raw(&ctx, None, [item.clone(), (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"index_of".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
@ -1157,24 +1153,7 @@ pub mod array_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if filter
|
if make_dual_arity_fn_ptr_call("some", &filter, &ctx, [item.clone()], i)?
|
||||||
.call_raw(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
|
||||||
{
|
|
||||||
filter.call_raw(&ctx, None, [item.clone(), (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"some".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
@ -1244,24 +1223,7 @@ pub mod array_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if !filter
|
if !make_dual_arity_fn_ptr_call("all", &filter, &ctx, [item.clone()], i)?
|
||||||
.call_raw(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
|
||||||
{
|
|
||||||
filter.call_raw(&ctx, None, [item.clone(), (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"all".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
@ -1482,32 +1444,12 @@ pub mod array_functions {
|
|||||||
return Ok(initial);
|
return Ok(initial);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = initial;
|
array
|
||||||
|
.iter()
|
||||||
for (i, item) in array.iter().enumerate() {
|
.enumerate()
|
||||||
let item = item.clone();
|
.try_fold(initial, |result, (i, item)| {
|
||||||
|
make_dual_arity_fn_ptr_call("reduce", &reducer, &ctx, [result, item.clone()], i)
|
||||||
result = reducer
|
|
||||||
.call_raw(&ctx, None, [result.clone(), item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(reducer.fn_name()) =>
|
|
||||||
{
|
|
||||||
reducer.call_raw(&ctx, None, [result, item, (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
})
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"reduce".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
/// Reduce an array by iterating through all elements while applying a function named by `reducer`.
|
/// Reduce an array by iterating through all elements while applying a function named by `reducer`.
|
||||||
///
|
///
|
||||||
@ -1643,33 +1585,13 @@ pub mod array_functions {
|
|||||||
return Ok(initial);
|
return Ok(initial);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = initial;
|
array
|
||||||
let len = array.len();
|
.iter()
|
||||||
|
.rev()
|
||||||
for (i, item) in array.iter().rev().enumerate() {
|
.enumerate()
|
||||||
let item = item.clone();
|
.try_fold(initial, |result, (i, item)| {
|
||||||
|
make_dual_arity_fn_ptr_call("reduce_rev", &reducer, &ctx, [result, item.clone()], array.len() - 1 - i)
|
||||||
result = reducer
|
|
||||||
.call_raw(&ctx, None, [result.clone(), item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(reducer.fn_name()) =>
|
|
||||||
{
|
|
||||||
reducer.call_raw(&ctx, None, [result, item, ((len - 1 - i) as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
})
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"reduce_rev".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
/// Reduce an array by iterating through all elements, in _reverse_ order,
|
/// Reduce an array by iterating through all elements, in _reverse_ order,
|
||||||
/// while applying a function named by `reducer`.
|
/// while applying a function named by `reducer`.
|
||||||
@ -1928,24 +1850,7 @@ pub mod array_functions {
|
|||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
|
|
||||||
while x < array.len() {
|
while x < array.len() {
|
||||||
if filter
|
if make_dual_arity_fn_ptr_call("drain", &filter, &ctx, [array[x].clone()], i)?
|
||||||
.call_raw(&ctx, None, [array[x].clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
|
||||||
{
|
|
||||||
filter.call_raw(&ctx, None, [array[x].clone(), (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"drain".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
@ -2124,24 +2029,7 @@ pub mod array_functions {
|
|||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
|
|
||||||
while x < array.len() {
|
while x < array.len() {
|
||||||
if filter
|
if make_dual_arity_fn_ptr_call("retain", &filter, &ctx, [array[x].clone()], i)?
|
||||||
.call_raw(&ctx, None, [array[x].clone()])
|
|
||||||
.or_else(|err| match *err {
|
|
||||||
ERR::ErrorFunctionNotFound(fn_sig, ..)
|
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
|
||||||
{
|
|
||||||
filter.call_raw(&ctx, None, [array[x].clone(), (i as INT).into()])
|
|
||||||
}
|
|
||||||
_ => Err(err),
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
Box::new(ERR::ErrorInFunctionCall(
|
|
||||||
"retain".to_string(),
|
|
||||||
ctx.source().unwrap_or("").to_string(),
|
|
||||||
err,
|
|
||||||
Position::NONE,
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
|
@ -3798,7 +3798,8 @@ impl Engine {
|
|||||||
comments: Box::default(),
|
comments: Box::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let fn_ptr = crate::FnPtr::from(script.clone());
|
let mut fn_ptr = crate::FnPtr::new_unchecked(fn_name, StaticVec::new_const());
|
||||||
|
fn_ptr.set_fn_def(Some(script.clone()));
|
||||||
let expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), settings.pos);
|
let expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), settings.pos);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
//! The `FnPtr` type.
|
//! The `FnPtr` type.
|
||||||
|
|
||||||
use crate::eval::GlobalRuntimeState;
|
use crate::eval::{Caches, GlobalRuntimeState};
|
||||||
use crate::tokenizer::is_valid_function_name;
|
use crate::tokenizer::is_valid_function_name;
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
Dynamic, Engine, FuncArgs, ImmutableString, NativeCallContext, Position, RhaiError, RhaiResult,
|
Dynamic, Engine, FnArgsVec, FuncArgs, ImmutableString, NativeCallContext, Position, RhaiError,
|
||||||
RhaiResultOf, StaticVec, AST, ERR,
|
RhaiResult, RhaiResultOf, StaticVec, AST, ERR,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -266,21 +266,45 @@ impl FnPtr {
|
|||||||
let mut args_data;
|
let mut args_data;
|
||||||
|
|
||||||
if self.is_curried() {
|
if self.is_curried() {
|
||||||
args_data = StaticVec::with_capacity(self.curry().len() + arg_values.len());
|
args_data = FnArgsVec::with_capacity(self.curry().len() + arg_values.len());
|
||||||
args_data.extend(self.curry().iter().cloned());
|
args_data.extend(self.curry().iter().cloned());
|
||||||
args_data.extend(arg_values.iter_mut().map(mem::take));
|
args_data.extend(arg_values.iter_mut().map(mem::take));
|
||||||
arg_values = &mut *args_data;
|
arg_values = &mut *args_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_method = this_ptr.is_some();
|
let args = &mut StaticVec::with_capacity(arg_values.len() + 1);
|
||||||
|
|
||||||
let mut args = StaticVec::with_capacity(arg_values.len() + 1);
|
|
||||||
if let Some(obj) = this_ptr {
|
|
||||||
args.push(obj);
|
|
||||||
}
|
|
||||||
args.extend(arg_values.iter_mut());
|
args.extend(arg_values.iter_mut());
|
||||||
|
|
||||||
context.call_fn_raw(self.fn_name(), is_method, is_method, &mut args)
|
// Linked to scripted function?
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
if let Some(fn_def) = self.fn_def() {
|
||||||
|
if fn_def.params.len() == args.len() {
|
||||||
|
let global = &mut context.global_runtime_state().clone();
|
||||||
|
global.level += 1;
|
||||||
|
|
||||||
|
let caches = &mut Caches::new();
|
||||||
|
let mut null_ptr = Dynamic::NULL;
|
||||||
|
|
||||||
|
return context.engine().call_script_fn(
|
||||||
|
global,
|
||||||
|
caches,
|
||||||
|
&mut crate::Scope::new(),
|
||||||
|
this_ptr.unwrap_or(&mut null_ptr),
|
||||||
|
&fn_def,
|
||||||
|
args,
|
||||||
|
true,
|
||||||
|
context.position(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_method = this_ptr.is_some();
|
||||||
|
|
||||||
|
if let Some(obj) = this_ptr {
|
||||||
|
args.insert(0, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.call_fn_raw(self.fn_name(), is_method, is_method, args)
|
||||||
}
|
}
|
||||||
/// Get a reference to the linked [`ScriptFnDef`][crate::ast::ScriptFnDef].
|
/// Get a reference to the linked [`ScriptFnDef`][crate::ast::ScriptFnDef].
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
@ -289,6 +313,15 @@ impl FnPtr {
|
|||||||
pub(crate) fn fn_def(&self) -> Option<&crate::Shared<crate::ast::ScriptFnDef>> {
|
pub(crate) fn fn_def(&self) -> Option<&crate::Shared<crate::ast::ScriptFnDef>> {
|
||||||
self.fn_def.as_ref()
|
self.fn_def.as_ref()
|
||||||
}
|
}
|
||||||
|
/// Set a reference to the linked [`ScriptFnDef`][crate::ast::ScriptFnDef].
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn set_fn_def(
|
||||||
|
&mut self,
|
||||||
|
value: Option<impl Into<crate::Shared<crate::ast::ScriptFnDef>>>,
|
||||||
|
) {
|
||||||
|
self.fn_def = value.map(Into::into);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for FnPtr {
|
impl fmt::Display for FnPtr {
|
||||||
|
Loading…
Reference in New Issue
Block a user