Refine this processing.
This commit is contained in:
parent
d30c0c2242
commit
2fcb1e510c
@ -1,6 +1,15 @@
|
|||||||
Rhai Release Notes
|
Rhai Release Notes
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
Version 1.15.0
|
||||||
|
==============
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Expressions involving `this` should now run slightly faster due to a dedicated `AST` node `ThisPtr`.
|
||||||
|
|
||||||
|
|
||||||
Version 1.14.0
|
Version 1.14.0
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
@ -139,13 +139,7 @@ impl Engine {
|
|||||||
|
|
||||||
let index = match expr {
|
let index = match expr {
|
||||||
// Check if the variable is `this`
|
// Check if the variable is `this`
|
||||||
Expr::ThisPtr(..) => {
|
Expr::ThisPtr(..) => unreachable!("Expr::ThisPtr should have been handled outside"),
|
||||||
return if let Some(this_ptr) = this_ptr {
|
|
||||||
Ok(this_ptr.into())
|
|
||||||
} else {
|
|
||||||
Err(ERR::ErrorUnboundThis(expr.position()).into())
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_ if global.always_search_scope => 0,
|
_ if global.always_search_scope => 0,
|
||||||
|
|
||||||
|
@ -1288,14 +1288,32 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call with blank scope
|
// Call with blank scope
|
||||||
if num_args > 0 || !curry.is_empty() {
|
|
||||||
// If the first argument is a variable, and there is no curried arguments,
|
|
||||||
// convert to method-call style in order to leverage potential &mut first argument and
|
|
||||||
// avoid cloning the value
|
|
||||||
if curry.is_empty() && first_arg.map_or(false, |expr| expr.is_variable_access(false)) {
|
|
||||||
let first_expr = first_arg.unwrap();
|
|
||||||
|
|
||||||
self.track_operation(global, first_expr.position())?;
|
// If the first argument is a variable, and there are no curried arguments,
|
||||||
|
// convert to method-call style in order to leverage potential &mut first argument
|
||||||
|
// and avoid cloning the value.
|
||||||
|
match first_arg {
|
||||||
|
Some(_first_expr @ Expr::ThisPtr(pos))
|
||||||
|
if curry.is_empty() && this_ptr.as_ref().map_or(false, |v| !v.is_shared()) =>
|
||||||
|
{
|
||||||
|
// Turn it into a method call only if the object is not shared
|
||||||
|
self.track_operation(global, *pos)?;
|
||||||
|
|
||||||
|
#[cfg(feature = "debugging")]
|
||||||
|
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), _first_expr)?;
|
||||||
|
|
||||||
|
// func(x, ...) -> x.func(...)
|
||||||
|
for expr in args_expr {
|
||||||
|
let (value, ..) =
|
||||||
|
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
|
||||||
|
arg_values.push(value.flatten());
|
||||||
|
}
|
||||||
|
|
||||||
|
is_ref_mut = true;
|
||||||
|
args.push(this_ptr.unwrap());
|
||||||
|
}
|
||||||
|
Some(first_expr @ Expr::Variable(.., pos)) if curry.is_empty() => {
|
||||||
|
self.track_operation(global, *pos)?;
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;
|
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;
|
||||||
@ -1322,7 +1340,8 @@ impl Engine {
|
|||||||
let obj_ref = target.take_ref().expect("ref");
|
let obj_ref = target.take_ref().expect("ref");
|
||||||
args.push(obj_ref);
|
args.push(obj_ref);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
_ => {
|
||||||
// func(..., ...)
|
// func(..., ...)
|
||||||
for expr in first_arg.into_iter().chain(args_expr.iter()) {
|
for expr in first_arg.into_iter().chain(args_expr.iter()) {
|
||||||
let (value, ..) =
|
let (value, ..) =
|
||||||
@ -1331,9 +1350,9 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
args.extend(curry.iter_mut());
|
args.extend(curry.iter_mut());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
args.extend(arg_values.iter_mut());
|
args.extend(arg_values.iter_mut());
|
||||||
}
|
|
||||||
|
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
global, caches, None, name, op_token, hashes, &mut args, is_ref_mut, false, pos,
|
global, caches, None, name, op_token, hashes, &mut args, is_ref_mut, false, pos,
|
||||||
@ -1359,18 +1378,29 @@ impl Engine {
|
|||||||
let args = &mut FnArgsVec::with_capacity(args_expr.len());
|
let args = &mut FnArgsVec::with_capacity(args_expr.len());
|
||||||
let mut first_arg_value = None;
|
let mut first_arg_value = None;
|
||||||
|
|
||||||
if !args_expr.is_empty() {
|
// See if the first argument is a variable.
|
||||||
// See if the first argument is a variable (not namespace-qualified).
|
// If so, convert to method-call style in order to leverage potential
|
||||||
// If so, convert to method-call style in order to leverage potential &mut first argument
|
// &mut first argument and avoid cloning the value.
|
||||||
// and avoid cloning the value
|
match args_expr.get(0) {
|
||||||
if !args_expr.is_empty() && args_expr[0].is_variable_access(true) {
|
Some(_first_expr @ Expr::ThisPtr(pos))
|
||||||
// Get target reference to first argument
|
if this_ptr.as_ref().map_or(false, |v| v.is_shared()) =>
|
||||||
let first_arg = &args_expr[0];
|
{
|
||||||
|
self.track_operation(global, *pos)?;
|
||||||
self.track_operation(global, first_arg.position())?;
|
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_arg)?;
|
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), _first_expr)?;
|
||||||
|
|
||||||
|
// Turn it into a method call only if the object is not shared
|
||||||
|
let (first, rest) = arg_values.split_first_mut().unwrap();
|
||||||
|
first_arg_value = Some(first);
|
||||||
|
args.push(this_ptr.unwrap());
|
||||||
|
args.extend(rest.iter_mut());
|
||||||
|
}
|
||||||
|
Some(first_expr @ Expr::Variable(.., pos)) => {
|
||||||
|
self.track_operation(global, *pos)?;
|
||||||
|
|
||||||
|
#[cfg(feature = "debugging")]
|
||||||
|
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;
|
||||||
|
|
||||||
// func(x, ...) -> x.func(...)
|
// func(x, ...) -> x.func(...)
|
||||||
arg_values.push(Dynamic::UNIT);
|
arg_values.push(Dynamic::UNIT);
|
||||||
@ -1381,14 +1411,9 @@ impl Engine {
|
|||||||
arg_values.push(value.flatten());
|
arg_values.push(value.flatten());
|
||||||
}
|
}
|
||||||
|
|
||||||
let target = self.search_scope_only(global, caches, scope, this_ptr, first_arg)?;
|
let target = self.search_namespace(global, caches, scope, this_ptr, first_expr)?;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
if target.is_shared() || target.is_temp_value() {
|
||||||
let target_is_shared = target.is_shared();
|
|
||||||
#[cfg(feature = "no_closure")]
|
|
||||||
let target_is_shared = false;
|
|
||||||
|
|
||||||
if target_is_shared || target.is_temp_value() {
|
|
||||||
arg_values[0] = target.take_or_clone().flatten();
|
arg_values[0] = target.take_or_clone().flatten();
|
||||||
args.extend(arg_values.iter_mut());
|
args.extend(arg_values.iter_mut());
|
||||||
} else {
|
} else {
|
||||||
@ -1399,7 +1424,8 @@ impl Engine {
|
|||||||
args.push(obj_ref);
|
args.push(obj_ref);
|
||||||
args.extend(rest.iter_mut());
|
args.extend(rest.iter_mut());
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
Some(_) => {
|
||||||
// func(..., ...) or func(mod::x, ...)
|
// func(..., ...) or func(mod::x, ...)
|
||||||
for expr in args_expr {
|
for expr in args_expr {
|
||||||
let (value, ..) =
|
let (value, ..) =
|
||||||
@ -1408,6 +1434,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
args.extend(arg_values.iter_mut());
|
args.extend(arg_values.iter_mut());
|
||||||
}
|
}
|
||||||
|
None => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for the root namespace
|
// Search for the root namespace
|
||||||
|
Loading…
Reference in New Issue
Block a user