From f406fc0ac0c870d3b2df0c7d265a2ad858825e6d Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 25 Sep 2020 19:07:24 +0800 Subject: [PATCH] Fix function calls. --- src/fn_call.rs | 105 +++++++++++++++++++++++++++------------------- tests/modules.rs | 2 +- tests/packages.rs | 9 ++-- 3 files changed, 69 insertions(+), 47 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index c40d352f..1aeaa473 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -221,6 +221,7 @@ impl Engine { let func = self .global_module .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)); if let Some(func) = func { @@ -439,9 +440,9 @@ impl Engine { // First check script-defined functions 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 - //|| 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) // Then check packages || self.packages.contains_fn(hash_script, pub_only) @@ -522,58 +523,76 @@ impl Engine { .into() } - // Normal script function call + // Script-like function found #[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) => { - // Get scripted function - let func = lib + // Get function + let func = self + .global_module .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)) - .unwrap() - .get_fn_def(); + .unwrap(); - let scope = &mut Scope::new(); - let mods = &mut Imports::new(); + if func.is_script() { + let func = func.get_fn_def(); - // Add captured variables into scope - #[cfg(not(feature = "no_closure"))] - if let Some(captured) = _capture { - add_captured_variables_into_scope(&func.externals, captured, scope); - } + let scope = &mut Scope::new(); + let mods = &mut Imports::new(); - 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, + // Add captured variables into scope + #[cfg(not(feature = "no_closure"))] + if let Some(captured) = _capture { + add_captured_variables_into_scope(&func.externals, captured, scope); + } + + 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, 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)) + hash_script, + args, + is_ref, + pub_only, + def_val, + ) + } } // Normal native function call diff --git a/tests/modules.rs b/tests/modules.rs index e3475584..b0134594 100644 --- a/tests/modules.rs +++ b/tests/modules.rs @@ -262,7 +262,7 @@ fn test_module_from_ast() -> Result<(), Box> { 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(); resolver2.insert("testing", module); diff --git a/tests/packages.rs b/tests/packages.rs index 6e871496..b0235b6b 100644 --- a/tests/packages.rs +++ b/tests/packages.rs @@ -34,12 +34,15 @@ fn test_packages() -> Result<(), Box> { #[test] fn test_packages_with_script() -> Result<(), Box> { let mut engine = Engine::new(); - let ast = engine.compile("fn foo(x) { x + 1 }")?; - let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?; + 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, false, &engine)?; engine.load_package(module); - assert_eq!(engine.eval::("foo(41)")?, 42); + let module = Module::eval_ast_as_new(Scope::new(), &ast, true, &engine)?; + engine.load_package(module); + assert_eq!(engine.eval::("bar(40)")?, 42); + Ok(()) }