Fix bang function calls under no_closure.

This commit is contained in:
Stephen Chung 2021-11-11 21:47:35 +08:00
parent 5685ca8411
commit 774fd7514e
2 changed files with 21 additions and 38 deletions

View File

@ -8,6 +8,7 @@ Bug fixes
--------- ---------
* Printing of integral floating-point numbers is fixed (used to only prints `0.0`). * Printing of integral floating-point numbers is fixed (used to only prints `0.0`).
* `func!()` calls now work properly under `no_closure`.
Version 1.1.2 Version 1.1.2

View File

@ -108,7 +108,6 @@ pub fn ensure_no_data_race(
args: &FnCallArgs, args: &FnCallArgs,
is_method_call: bool, is_method_call: bool,
) -> Result<(), Box<EvalAltResult>> { ) -> Result<(), Box<EvalAltResult>> {
#[cfg(not(feature = "no_closure"))]
if let Some((n, _)) = args if let Some((n, _)) = args
.iter() .iter()
.enumerate() .enumerate()
@ -245,18 +244,16 @@ impl Engine {
} }
}) })
} else { } else {
let (first, second) = args let (first_arg, rest_args) =
.split_first() args.split_first().expect("has two arguments");
.expect("op-assignment has two arguments");
get_builtin_op_assignment_fn(fn_name, *first, second[0]).map( get_builtin_op_assignment_fn(fn_name, *first_arg, rest_args[0])
|f| FnResolutionCacheEntry { .map(|f| FnResolutionCacheEntry {
func: CallableFunction::from_method( func: CallableFunction::from_method(
Box::new(f) as Box<FnAny> Box::new(f) as Box<FnAny>
), ),
source: None, source: None,
}, })
)
} }
.map(Box::new) .map(Box::new)
}); });
@ -645,7 +642,7 @@ impl Engine {
is_ref_mut: bool, is_ref_mut: bool,
is_method_call: bool, is_method_call: bool,
pos: Position, pos: Position,
_capture_scope: Option<Scope>, captured_scope: Option<Scope>,
_level: usize, _level: usize,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> { ) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
fn no_method_err(name: &str, pos: Position) -> Result<(Dynamic, bool), Box<EvalAltResult>> { fn no_method_err(name: &str, pos: Position) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
@ -727,27 +724,11 @@ impl Engine {
return Ok((Dynamic::UNIT, false)); return Ok((Dynamic::UNIT, false));
} }
let scope = &mut Scope::new(); let mut scope = captured_scope.unwrap_or_else(|| Scope::new());
// Move captured variables into scope
#[cfg(not(feature = "no_closure"))]
if !func.externals.is_empty() {
if let Some(captured) = _capture_scope {
captured
.into_iter()
.filter(|(name, _, _)| func.externals.contains(name.as_ref()))
.for_each(|(name, value, _)| {
// Consume the scope values.
scope.push_dynamic(name, value);
})
}
}
let result = if _is_method_call { let result = if _is_method_call {
// Method call of script function - map first argument to `this` // Method call of script function - map first argument to `this`
let (first, rest) = args let (first_arg, rest_args) = args.split_first_mut().expect("has arguments");
.split_first_mut()
.expect("method call has first parameter");
let orig_source = state.source.take(); let orig_source = state.source.take();
state.source = source; state.source = source;
@ -755,13 +736,13 @@ impl Engine {
let level = _level + 1; let level = _level + 1;
let result = self.call_script_fn( let result = self.call_script_fn(
scope, &mut scope,
mods, mods,
state, state,
lib, lib,
&mut Some(*first), &mut Some(*first_arg),
func, func,
rest, rest_args,
pos, pos,
level, level,
); );
@ -787,8 +768,9 @@ impl Engine {
let level = _level + 1; let level = _level + 1;
let result = let result = self.call_script_fn(
self.call_script_fn(scope, mods, state, lib, &mut None, func, args, pos, level); &mut scope, mods, state, lib, &mut None, func, args, pos, level,
);
// Restore the original source // Restore the original source
state.source = orig_source; state.source = orig_source;
@ -1263,15 +1245,17 @@ impl Engine {
// avoid cloning the value // avoid cloning the value
if curry.is_empty() && !args_expr.is_empty() && args_expr[0].is_variable_access(false) { if curry.is_empty() && !args_expr.is_empty() && args_expr[0].is_variable_access(false) {
// func(x, ...) -> x.func(...) // func(x, ...) -> x.func(...)
for index in 1..args_expr.len() { let (first_expr, rest_expr) = args_expr.split_first().expect("has arguments");
for index in 0..rest_expr.len() {
let (value, _) = self.get_arg_value( let (value, _) = self.get_arg_value(
scope, mods, state, lib, this_ptr, level, args_expr, constants, index, scope, mods, state, lib, this_ptr, level, rest_expr, constants, index,
)?; )?;
arg_values.push(value.flatten()); arg_values.push(value.flatten());
} }
let (mut target, _pos) = let (mut target, _pos) =
self.search_namespace(scope, mods, state, lib, this_ptr, &args_expr[0])?; self.search_namespace(scope, mods, state, lib, this_ptr, first_expr)?;
if target.as_ref().is_read_only() { if target.as_ref().is_read_only() {
target = target.into_owned(); target = target.into_owned();
@ -1370,9 +1354,7 @@ impl Engine {
args.extend(arg_values.iter_mut()); args.extend(arg_values.iter_mut());
} else { } else {
// Turn it into a method call only if the object is not shared and not a simple value // Turn it into a method call only if the object is not shared and not a simple value
let (first, rest) = arg_values let (first, rest) = arg_values.split_first_mut().expect("has arguments");
.split_first_mut()
.expect("arguments list is not empty");
first_arg_value = Some(first); first_arg_value = Some(first);
let obj_ref = target.take_ref().expect("`target` is reference"); let obj_ref = target.take_ref().expect("`target` is reference");
args.push(obj_ref); args.push(obj_ref);