Fix function calls.

This commit is contained in:
Stephen Chung 2020-09-25 19:07:24 +08:00
parent 599fe846cb
commit f406fc0ac0
3 changed files with 69 additions and 47 deletions

View File

@ -221,6 +221,7 @@ impl Engine {
let func = self let func = self
.global_module .global_module
.get_fn(hash_fn, pub_only) .get_fn(hash_fn, pub_only)
.or_else(|| lib.get_fn(hash_fn, pub_only))
.or_else(|| self.packages.get_fn(hash_fn, pub_only)); .or_else(|| self.packages.get_fn(hash_fn, pub_only));
if let Some(func) = func { if let Some(func) = func {
@ -439,9 +440,9 @@ impl Engine {
// First check script-defined functions // First check script-defined functions
lib.contains_fn(hash_script, pub_only) lib.contains_fn(hash_script, pub_only)
//|| lib.contains_fn(hash_fn, pub_only) || lib.contains_fn(hash_fn, pub_only)
// Then check registered functions // Then check registered functions
//|| self.global_module.contains_fn(hash_script, pub_only) || self.global_module.contains_fn(hash_script, pub_only)
|| self.global_module.contains_fn(hash_fn, pub_only) || self.global_module.contains_fn(hash_fn, pub_only)
// Then check packages // Then check packages
|| self.packages.contains_fn(hash_script, pub_only) || self.packages.contains_fn(hash_script, pub_only)
@ -522,58 +523,76 @@ impl Engine {
.into() .into()
} }
// Normal script function call // Script-like function found
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
_ if lib.contains_fn(hash_script, pub_only) _ if self.global_module.contains_fn(hash_script, pub_only)
|| lib.contains_fn(hash_script, pub_only)
|| self.packages.contains_fn(hash_script, pub_only) => || self.packages.contains_fn(hash_script, pub_only) =>
{ {
// Get scripted function // Get function
let func = lib let func = self
.global_module
.get_fn(hash_script, pub_only) .get_fn(hash_script, pub_only)
.or_else(|| lib.get_fn(hash_script, pub_only))
.or_else(|| self.packages.get_fn(hash_script, pub_only)) .or_else(|| self.packages.get_fn(hash_script, pub_only))
.unwrap() .unwrap();
.get_fn_def();
let scope = &mut Scope::new(); if func.is_script() {
let mods = &mut Imports::new(); let func = func.get_fn_def();
// Add captured variables into scope let scope = &mut Scope::new();
#[cfg(not(feature = "no_closure"))] let mods = &mut Imports::new();
if let Some(captured) = _capture {
add_captured_variables_into_scope(&func.externals, captured, scope);
}
let result = if _is_method { // Add captured variables into scope
// Method call of script function - map first argument to `this` #[cfg(not(feature = "no_closure"))]
let (first, rest) = args.split_first_mut().unwrap(); if let Some(captured) = _capture {
self.call_script_fn( add_captured_variables_into_scope(&func.externals, captured, scope);
scope, }
mods,
let result = if _is_method {
// Method call of script function - map first argument to `this`
let (first, rest) = args.split_first_mut().unwrap();
self.call_script_fn(
scope,
mods,
state,
lib,
&mut Some(*first),
fn_name,
func,
rest,
_level,
)?
} else {
// Normal call of script function - map first argument to `this`
// The first argument is a reference?
let mut backup: ArgBackup = Default::default();
backup.change_first_arg_to_copy(is_ref, args);
let result = self.call_script_fn(
scope, mods, state, lib, &mut None, fn_name, func, args, _level,
);
// Restore the original reference
backup.restore_first_arg(args);
result?
};
Ok((result, false))
} else {
// If it is a native function, redirect it
self.call_native_fn(
state, state,
lib, lib,
&mut Some(*first),
fn_name, fn_name,
func, hash_script,
rest, args,
_level, is_ref,
)? pub_only,
} else { def_val,
// Normal call of script function - map first argument to `this` )
// The first argument is a reference? }
let mut backup: ArgBackup = Default::default();
backup.change_first_arg_to_copy(is_ref, args);
let result = self.call_script_fn(
scope, mods, state, lib, &mut None, fn_name, func, args, _level,
);
// Restore the original reference
backup.restore_first_arg(args);
result?
};
Ok((result, false))
} }
// Normal native function call // Normal native function call

View File

@ -262,7 +262,7 @@ fn test_module_from_ast() -> Result<(), Box<EvalAltResult>> {
engine.set_module_resolver(Some(resolver1)); engine.set_module_resolver(Some(resolver1));
let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?; let module = Module::eval_ast_as_new(Scope::new(), &ast, true, &engine)?;
let mut resolver2 = StaticModuleResolver::new(); let mut resolver2 = StaticModuleResolver::new();
resolver2.insert("testing", module); resolver2.insert("testing", module);

View File

@ -34,12 +34,15 @@ fn test_packages() -> Result<(), Box<EvalAltResult>> {
#[test] #[test]
fn test_packages_with_script() -> Result<(), Box<EvalAltResult>> { fn test_packages_with_script() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new(); let mut engine = Engine::new();
let ast = engine.compile("fn foo(x) { x + 1 }")?; let ast = engine.compile("fn foo(x) { x + 1 } fn bar(x) { foo(x) + 1 }")?;
let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
let module = Module::eval_ast_as_new(Scope::new(), &ast, false, &engine)?;
engine.load_package(module); engine.load_package(module);
assert_eq!(engine.eval::<INT>("foo(41)")?, 42); assert_eq!(engine.eval::<INT>("foo(41)")?, 42);
let module = Module::eval_ast_as_new(Scope::new(), &ast, true, &engine)?;
engine.load_package(module);
assert_eq!(engine.eval::<INT>("bar(40)")?, 42);
Ok(()) Ok(())
} }