Add Dynamic parameters to qualified function calls.
This commit is contained in:
parent
6481e19673
commit
42f977862f
@ -1,6 +1,15 @@
|
||||
Rhai Release Notes
|
||||
==================
|
||||
|
||||
Version 1.7.0
|
||||
=============
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Functions with `Dynamic` parameters now work in qualified calls from `import`ed modules.
|
||||
|
||||
|
||||
Version 1.6.0
|
||||
=============
|
||||
|
||||
|
@ -1301,13 +1301,14 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
// Search for the root namespace
|
||||
let module = self
|
||||
.search_imports(global, state, namespace)
|
||||
.ok_or_else(|| ERR::ErrorModuleNotFound(namespace.to_string(), namespace.position()))?;
|
||||
|
||||
// First search in script-defined functions (can override built-in)
|
||||
let func = match module.get_qualified_fn(hash) {
|
||||
// Then search in Rust functions
|
||||
// First search script-defined functions in namespace (can override built-in)
|
||||
let mut func = match module.get_qualified_fn(hash) {
|
||||
// Then search native Rust functions
|
||||
None => {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, pos)?;
|
||||
@ -1320,6 +1321,41 @@ impl Engine {
|
||||
r => r,
|
||||
};
|
||||
|
||||
// Check for `Dynamic` parameters.
|
||||
//
|
||||
// Note - This is done during every function call mismatch without cache,
|
||||
// so hopefully the number of arguments should not be too many
|
||||
// (expected because closures cannot be qualified).
|
||||
if func.is_none() && !args.is_empty() {
|
||||
let num_args = args.len();
|
||||
let max_bitmask = 1usize << usize::min(num_args, MAX_DYNAMIC_PARAMETERS);
|
||||
let mut bitmask = 1usize; // Bitmask of which parameter to replace with `Dynamic`
|
||||
|
||||
// Try all permutations with `Dynamic` wildcards
|
||||
while bitmask < max_bitmask {
|
||||
let hash_params = calc_fn_params_hash(args.iter().enumerate().map(|(i, a)| {
|
||||
let mask = 1usize << (num_args - i - 1);
|
||||
if bitmask & mask != 0 {
|
||||
// Replace with `Dynamic`
|
||||
TypeId::of::<Dynamic>()
|
||||
} else {
|
||||
a.type_id()
|
||||
}
|
||||
}));
|
||||
let hash_qualified_fn = combine_hashes(hash, hash_params);
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, pos)?;
|
||||
|
||||
if let Some(f) = module.get_qualified_fn(hash_qualified_fn) {
|
||||
func = Some(f);
|
||||
break;
|
||||
}
|
||||
|
||||
bitmask += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Clone first argument if the function is not a method after-all
|
||||
if !func.map(|f| f.is_method()).unwrap_or(true) {
|
||||
if let Some(first) = first_arg_value {
|
||||
|
@ -562,3 +562,29 @@ fn test_module_environ() -> Result<(), Box<EvalAltResult>> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_module_dynamic() -> Result<(), Box<EvalAltResult>> {
|
||||
fn test_fn(input: Dynamic, x: INT) -> Result<INT, Box<EvalAltResult>> {
|
||||
let s = input.into_string().unwrap();
|
||||
Ok(s.len() as INT + x)
|
||||
}
|
||||
|
||||
let mut engine = rhai::Engine::new();
|
||||
let mut module = Module::new();
|
||||
module.set_native_fn("test", test_fn);
|
||||
|
||||
let mut static_modules = rhai::module_resolvers::StaticModuleResolver::new();
|
||||
static_modules.insert("test", module);
|
||||
engine.set_module_resolver(static_modules);
|
||||
engine.register_result_fn("test2", test_fn);
|
||||
|
||||
assert_eq!(engine.eval::<INT>(r#"test2("test", 38);"#)?, 42);
|
||||
|
||||
assert_eq!(
|
||||
engine.eval::<INT>(r#"import "test" as test; test::test("test", 38);"#)?,
|
||||
42
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user