Do not convert a function call into a method call if the object is shared.

This commit is contained in:
Stephen Chung 2020-08-02 13:51:07 +08:00
parent b86c87253b
commit 747c0345f2
2 changed files with 11 additions and 9 deletions

View File

@ -258,7 +258,7 @@ impl Dynamic {
} }
/// Does this `Dynamic` hold a shared data type /// Does this `Dynamic` hold a shared data type
/// instead of one of the support system primitive types? /// instead of one of the supported system primitive types?
pub fn is_shared(&self) -> bool { pub fn is_shared(&self) -> bool {
match self.0 { match self.0 {
#[cfg(not(feature = "no_shared"))] #[cfg(not(feature = "no_shared"))]

View File

@ -906,11 +906,11 @@ impl Engine {
// No arguments // No arguments
args = Default::default(); args = Default::default();
} else { } else {
// See if the first argument is a variable, if so, convert to method-call style // 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 // in order to leverage potential &mut first argument and avoid cloning the value
match args_expr.get(0).unwrap() { match args_expr.get(0).unwrap() {
// func(x, ...) -> x.func(...) // func(x, ...) -> x.func(...)
lhs @ Expr::Variable(_) => { lhs @ Expr::Variable(_) if curry.is_empty() => {
arg_values = args_expr arg_values = args_expr
.iter() .iter()
.skip(1) .skip(1)
@ -922,12 +922,14 @@ impl Engine {
self.inc_operations(state) self.inc_operations(state)
.map_err(|err| err.new_position(pos))?; .map_err(|err| err.new_position(pos))?;
args = once(target) // Turn it into a method call only if the object is not shared
.chain(curry.iter_mut()) args = if target.is_shared() {
.chain(arg_values.iter_mut()) arg_values.insert(0, target.clone_inner_data().unwrap());
.collect(); arg_values.iter_mut().collect()
} else {
is_ref = true; is_ref = true;
once(target).chain(arg_values.iter_mut()).collect()
};
} }
// func(..., ...) // func(..., ...)
_ => { _ => {