Fix function call optimizations.
This commit is contained in:
parent
d56634cac7
commit
1798d4d6a0
@ -698,7 +698,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If it is a 2-operand operator, see if it is built in
|
// If it is a 2-operand operator, see if it is built in
|
||||||
if native_only && args.len() == 2 && args[0].type_id() == args[1].type_id() {
|
if !is_ref && native_only && args.len() == 2 && args[0].type_id() == args[1].type_id() {
|
||||||
match run_builtin_binary_op(fn_name, args[0], args[1])? {
|
match run_builtin_binary_op(fn_name, args[0], args[1])? {
|
||||||
Some(v) => return Ok((v, false)),
|
Some(v) => return Ok((v, false)),
|
||||||
None => (),
|
None => (),
|
||||||
@ -1327,7 +1327,7 @@ impl Engine {
|
|||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
self.inc_operations(state, rhs.position())?;
|
self.inc_operations(state, rhs.position())?;
|
||||||
|
|
||||||
let mut lhs_value = self.eval_expr(scope, state, lhs, level)?;
|
let lhs_value = self.eval_expr(scope, state, lhs, level)?;
|
||||||
let rhs_value = self.eval_expr(scope, state, rhs, level)?;
|
let rhs_value = self.eval_expr(scope, state, rhs, level)?;
|
||||||
|
|
||||||
match rhs_value {
|
match rhs_value {
|
||||||
@ -1338,17 +1338,17 @@ impl Engine {
|
|||||||
|
|
||||||
// Call the `==` operator to compare each value
|
// Call the `==` operator to compare each value
|
||||||
for value in rhs_value.iter_mut() {
|
for value in rhs_value.iter_mut() {
|
||||||
let args = &mut [&mut lhs_value, value];
|
let args = &mut [&mut lhs_value.clone(), value];
|
||||||
let def_value = Some(&def_value);
|
let def_value = Some(&def_value);
|
||||||
let pos = rhs.position();
|
let pos = rhs.position();
|
||||||
|
|
||||||
// Qualifiers (none) + function name + argument `TypeId`'s.
|
// Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
|
||||||
let hash_fn =
|
let hash_fn =
|
||||||
calc_fn_hash(empty(), op, args.len(), args.iter().map(|a| a.type_id()));
|
calc_fn_hash(empty(), op, args.len(), args.iter().map(|a| a.type_id()));
|
||||||
let hashes = (hash_fn, 0);
|
let hashes = (hash_fn, 0);
|
||||||
|
|
||||||
let (r, _) = self
|
let (r, _) = self
|
||||||
.call_fn_raw(None, state, op, hashes, args, true, def_value, pos, level)?;
|
.call_fn_raw(None, state, op, hashes, args, false, def_value, pos, level)?;
|
||||||
if r.as_bool().unwrap_or(false) {
|
if r.as_bool().unwrap_or(false) {
|
||||||
return Ok(true.into());
|
return Ok(true.into());
|
||||||
}
|
}
|
||||||
|
@ -110,18 +110,18 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Call a registered function
|
/// Call a registered function
|
||||||
fn call_fn(
|
fn call_fn_with_constant_arguments(
|
||||||
state: &State,
|
state: &State,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
args: &mut FnCallArgs,
|
arg_values: &mut [Dynamic],
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
let hash_fn = calc_fn_hash(
|
let hash_fn = calc_fn_hash(
|
||||||
empty(),
|
empty(),
|
||||||
fn_name,
|
fn_name,
|
||||||
args.len(),
|
arg_values.len(),
|
||||||
args.iter().map(|a| a.type_id()),
|
arg_values.iter().map(|a| a.type_id()),
|
||||||
);
|
);
|
||||||
|
|
||||||
state
|
state
|
||||||
@ -131,8 +131,8 @@ fn call_fn(
|
|||||||
&mut EngineState::new(&Default::default()),
|
&mut EngineState::new(&Default::default()),
|
||||||
fn_name,
|
fn_name,
|
||||||
(hash_fn, 0),
|
(hash_fn, 0),
|
||||||
args,
|
arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(),
|
||||||
true,
|
false,
|
||||||
None,
|
None,
|
||||||
pos,
|
pos,
|
||||||
0,
|
0,
|
||||||
@ -556,24 +556,24 @@ fn optimize_expr<'a>(expr: Expr, state: &mut State<'a>) -> Expr {
|
|||||||
let ((name, native_only, pos), _, _, args, def_value) = x.as_mut();
|
let ((name, native_only, pos), _, _, args, def_value) = x.as_mut();
|
||||||
|
|
||||||
// First search in script-defined functions (can override built-in)
|
// First search in script-defined functions (can override built-in)
|
||||||
if !*native_only && state.fn_lib.iter().find(|(id, len)| *id == name && *len == args.len()).is_some() {
|
// Cater for both normal function call style and method call style (one additional arguments)
|
||||||
|
if !*native_only && state.fn_lib.iter().find(|(id, len)| *id == name && (*len == args.len() || *len == args.len() + 1)).is_some() {
|
||||||
// A script-defined function overrides the built-in function - do not make the call
|
// A script-defined function overrides the built-in function - do not make the call
|
||||||
x.3 = x.3.into_iter().map(|a| optimize_expr(a, state)).collect();
|
x.3 = x.3.into_iter().map(|a| optimize_expr(a, state)).collect();
|
||||||
return Expr::FnCall(x);
|
return Expr::FnCall(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut arg_values: StaticVec<_> = args.iter().map(Expr::get_constant_value).collect();
|
let mut arg_values: StaticVec<_> = args.iter().map(Expr::get_constant_value).collect();
|
||||||
let mut call_args: StaticVec<_> = arg_values.iter_mut().collect();
|
|
||||||
|
|
||||||
// Save the typename of the first argument if it is `type_of()`
|
// Save the typename of the first argument if it is `type_of()`
|
||||||
// This is to avoid `call_args` being passed into the closure
|
// This is to avoid `call_args` being passed into the closure
|
||||||
let arg_for_type_of = if name == KEYWORD_TYPE_OF && call_args.len() == 1 {
|
let arg_for_type_of = if name == KEYWORD_TYPE_OF && arg_values.len() == 1 {
|
||||||
state.engine.map_type_name(call_args[0].type_name())
|
state.engine.map_type_name(arg_values[0].type_name())
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
call_fn(&state, name, call_args.as_mut(), *pos).ok()
|
call_fn_with_constant_arguments(&state, name, arg_values.as_mut(), *pos).ok()
|
||||||
.and_then(|result|
|
.and_then(|result|
|
||||||
result.or_else(|| {
|
result.or_else(|| {
|
||||||
if !arg_for_type_of.is_empty() {
|
if !arg_for_type_of.is_empty() {
|
||||||
|
Loading…
Reference in New Issue
Block a user