Convert function calls to method calls to use &mut first argument.
This commit is contained in:
@@ -630,6 +630,14 @@ impl<T: Variant + Clone> From<Vec<T>> for Dynamic {
|
||||
)))
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
impl<T: Variant + Clone> From<&[T]> for Dynamic {
|
||||
fn from(value: &[T]) -> Self {
|
||||
Self(Union::Array(Box::new(
|
||||
value.iter().cloned().map(Dynamic::from).collect(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
impl<T: Variant + Clone> From<HashMap<String, T>> for Dynamic {
|
||||
fn from(value: HashMap<String, T>) -> Self {
|
||||
|
@@ -1550,14 +1550,8 @@ impl Engine {
|
||||
let ((name, native, pos), _, hash, args_expr, def_val) = x.as_ref();
|
||||
let def_val = def_val.as_ref();
|
||||
|
||||
let mut arg_values = args_expr
|
||||
.iter()
|
||||
.map(|expr| self.eval_expr(scope, state, lib, expr, level))
|
||||
.collect::<Result<StaticVec<_>, _>>()?;
|
||||
|
||||
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
||||
|
||||
if name == KEYWORD_EVAL && args.len() == 1 && args.get(0).is::<ImmutableString>() {
|
||||
// Handle eval
|
||||
if name == KEYWORD_EVAL && args_expr.len() == 1 {
|
||||
let hash_fn =
|
||||
calc_fn_hash(empty(), name, 1, once(TypeId::of::<ImmutableString>()));
|
||||
|
||||
@@ -1567,7 +1561,8 @@ impl Engine {
|
||||
let pos = args_expr.get(0).position();
|
||||
|
||||
// Evaluate the text string as a script
|
||||
let result = self.eval_script_expr(scope, state, lib, args.pop(), pos);
|
||||
let script = self.eval_expr(scope, state, lib, args_expr.get(0), level)?;
|
||||
let result = self.eval_script_expr(scope, state, lib, &script, pos);
|
||||
|
||||
if scope.len() != prev_len {
|
||||
// IMPORTANT! If the eval defines new variables in the current scope,
|
||||
@@ -1580,6 +1575,46 @@ impl Engine {
|
||||
}
|
||||
|
||||
// Normal function call - except for eval (handled above)
|
||||
let mut arg_values: StaticVec<Dynamic>;
|
||||
let mut args: StaticVec<_>;
|
||||
|
||||
if args_expr.is_empty() {
|
||||
// No arguments
|
||||
args = Default::default();
|
||||
} else {
|
||||
// See if the first argument is a variable, if so, convert to method-call style
|
||||
// in order to leverage potential &mut first argument and avoid cloning the value
|
||||
match args_expr.get(0) {
|
||||
// func(x, ...) -> x.func(...)
|
||||
lhs @ Expr::Variable(_) => {
|
||||
arg_values = args_expr
|
||||
.iter()
|
||||
.skip(1)
|
||||
.map(|expr| self.eval_expr(scope, state, lib, expr, level))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
let (target, _, typ, pos) = search_scope(scope, state, lhs)?;
|
||||
self.inc_operations(state, pos)?;
|
||||
|
||||
match typ {
|
||||
ScopeEntryType::Module => unreachable!(),
|
||||
ScopeEntryType::Constant | ScopeEntryType::Normal => (),
|
||||
}
|
||||
|
||||
args = once(target).chain(arg_values.iter_mut()).collect();
|
||||
}
|
||||
// func(..., ...)
|
||||
_ => {
|
||||
arg_values = args_expr
|
||||
.iter()
|
||||
.map(|expr| self.eval_expr(scope, state, lib, expr, level))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
args = arg_values.iter_mut().collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let args = args.as_mut();
|
||||
self.exec_fn_call(
|
||||
state, lib, name, *native, *hash, args, false, def_val, *pos, level,
|
||||
@@ -2012,8 +2047,8 @@ fn run_builtin_binary_op(
|
||||
}
|
||||
|
||||
if args_type == TypeId::of::<INT>() {
|
||||
let x = x.downcast_ref::<INT>().unwrap().clone();
|
||||
let y = y.downcast_ref::<INT>().unwrap().clone();
|
||||
let x = *x.downcast_ref::<INT>().unwrap();
|
||||
let y = *y.downcast_ref::<INT>().unwrap();
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
match op {
|
||||
@@ -2054,8 +2089,8 @@ fn run_builtin_binary_op(
|
||||
_ => (),
|
||||
}
|
||||
} else if args_type == TypeId::of::<bool>() {
|
||||
let x = x.downcast_ref::<bool>().unwrap().clone();
|
||||
let y = y.downcast_ref::<bool>().unwrap().clone();
|
||||
let x = *x.downcast_ref::<bool>().unwrap();
|
||||
let y = *y.downcast_ref::<bool>().unwrap();
|
||||
|
||||
match op {
|
||||
"&" => return Ok(Some((x && y).into())),
|
||||
@@ -2079,8 +2114,8 @@ fn run_builtin_binary_op(
|
||||
_ => (),
|
||||
}
|
||||
} else if args_type == TypeId::of::<char>() {
|
||||
let x = x.downcast_ref::<char>().unwrap().clone();
|
||||
let y = y.downcast_ref::<char>().unwrap().clone();
|
||||
let x = *x.downcast_ref::<char>().unwrap();
|
||||
let y = *y.downcast_ref::<char>().unwrap();
|
||||
|
||||
match op {
|
||||
"==" => return Ok(Some((x == y).into())),
|
||||
@@ -2102,8 +2137,8 @@ fn run_builtin_binary_op(
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
if args_type == TypeId::of::<FLOAT>() {
|
||||
let x = x.downcast_ref::<FLOAT>().unwrap().clone();
|
||||
let y = y.downcast_ref::<FLOAT>().unwrap().clone();
|
||||
let x = *x.downcast_ref::<FLOAT>().unwrap();
|
||||
let y = *y.downcast_ref::<FLOAT>().unwrap();
|
||||
|
||||
match op {
|
||||
"+" => return Ok(Some((x + y).into())),
|
||||
@@ -2142,7 +2177,7 @@ fn run_builtin_op_assignment(
|
||||
|
||||
if args_type == TypeId::of::<INT>() {
|
||||
let x = x.downcast_mut::<INT>().unwrap();
|
||||
let y = y.downcast_ref::<INT>().unwrap().clone();
|
||||
let y = *y.downcast_ref::<INT>().unwrap();
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
match op {
|
||||
@@ -2178,7 +2213,7 @@ fn run_builtin_op_assignment(
|
||||
}
|
||||
} else if args_type == TypeId::of::<bool>() {
|
||||
let x = x.downcast_mut::<bool>().unwrap();
|
||||
let y = y.downcast_ref::<bool>().unwrap().clone();
|
||||
let y = *y.downcast_ref::<bool>().unwrap();
|
||||
|
||||
match op {
|
||||
"&=" => return Ok(Some(*x = *x && y)),
|
||||
@@ -2199,7 +2234,7 @@ fn run_builtin_op_assignment(
|
||||
{
|
||||
if args_type == TypeId::of::<FLOAT>() {
|
||||
let x = x.downcast_mut::<FLOAT>().unwrap();
|
||||
let y = y.downcast_ref::<FLOAT>().unwrap().clone();
|
||||
let y = *y.downcast_ref::<FLOAT>().unwrap();
|
||||
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x += y)),
|
||||
|
@@ -1044,6 +1044,9 @@ mod stat {
|
||||
|
||||
/// Module resolution service that serves modules added into it.
|
||||
///
|
||||
/// `StaticModuleResolver` is a smart pointer to a `HashMap<String, Module>`.
|
||||
/// It can simply be treated as `&HashMap<String, Module>`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@@ -101,22 +101,22 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
{
|
||||
lib.set_fn_2("+", |x: ImmutableString, y: Array| Ok(format!("{}{:?}", x, y)));
|
||||
lib.set_fn_2_mut("+", |x: &mut ImmutableString, y: Array| Ok(format!("{}{:?}", x, y)));
|
||||
lib.set_fn_2_mut("+", |x: &mut Array, y: ImmutableString| Ok(format!("{:?}{}", x, y)));
|
||||
}
|
||||
|
||||
lib.set_fn_1("len", |s: ImmutableString| Ok(s.chars().count() as INT));
|
||||
lib.set_fn_2(
|
||||
lib.set_fn_1_mut("len", |s: &mut ImmutableString| Ok(s.chars().count() as INT));
|
||||
lib.set_fn_2_mut(
|
||||
"contains",
|
||||
|s: ImmutableString, ch: char| Ok(s.contains(ch)),
|
||||
|s: &mut ImmutableString, ch: char| Ok(s.contains(ch)),
|
||||
);
|
||||
lib.set_fn_2(
|
||||
lib.set_fn_2_mut(
|
||||
"contains",
|
||||
|s: ImmutableString, find: ImmutableString| Ok(s.contains(find.as_str())),
|
||||
|s: &mut ImmutableString, find: ImmutableString| Ok(s.contains(find.as_str())),
|
||||
);
|
||||
lib.set_fn_3(
|
||||
lib.set_fn_3_mut(
|
||||
"index_of",
|
||||
|s: ImmutableString, ch: char, start: INT| {
|
||||
|s: &mut ImmutableString, ch: char, start: INT| {
|
||||
let start = if start < 0 {
|
||||
0
|
||||
} else if (start as usize) >= s.chars().count() {
|
||||
@@ -131,17 +131,17 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
||||
.unwrap_or(-1 as INT))
|
||||
},
|
||||
);
|
||||
lib.set_fn_2(
|
||||
lib.set_fn_2_mut(
|
||||
"index_of",
|
||||
|s: ImmutableString, ch: char| {
|
||||
|s: &mut ImmutableString, ch: char| {
|
||||
Ok(s.find(ch)
|
||||
.map(|index| s[0..index].chars().count() as INT)
|
||||
.unwrap_or(-1 as INT))
|
||||
},
|
||||
);
|
||||
lib.set_fn_3(
|
||||
lib.set_fn_3_mut(
|
||||
"index_of",
|
||||
|s: ImmutableString, find: ImmutableString, start: INT| {
|
||||
|s: &mut ImmutableString, find: ImmutableString, start: INT| {
|
||||
let start = if start < 0 {
|
||||
0
|
||||
} else if (start as usize) >= s.chars().count() {
|
||||
@@ -156,9 +156,9 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
||||
.unwrap_or(-1 as INT))
|
||||
},
|
||||
);
|
||||
lib.set_fn_2(
|
||||
lib.set_fn_2_mut(
|
||||
"index_of",
|
||||
|s: ImmutableString, find: ImmutableString| {
|
||||
|s: &mut ImmutableString, find: ImmutableString| {
|
||||
Ok(s.find(find.as_str())
|
||||
.map(|index| s[0..index].chars().count() as INT)
|
||||
.unwrap_or(-1 as INT))
|
||||
|
Reference in New Issue
Block a user