Add Dynamic parameters to qualified function calls.
This commit is contained in:
parent
6481e19673
commit
42f977862f
@ -1,6 +1,15 @@
|
|||||||
Rhai Release Notes
|
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
|
Version 1.6.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -1301,13 +1301,14 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search for the root namespace
|
||||||
let module = self
|
let module = self
|
||||||
.search_imports(global, state, namespace)
|
.search_imports(global, state, namespace)
|
||||||
.ok_or_else(|| ERR::ErrorModuleNotFound(namespace.to_string(), namespace.position()))?;
|
.ok_or_else(|| ERR::ErrorModuleNotFound(namespace.to_string(), namespace.position()))?;
|
||||||
|
|
||||||
// First search in script-defined functions (can override built-in)
|
// First search script-defined functions in namespace (can override built-in)
|
||||||
let func = match module.get_qualified_fn(hash) {
|
let mut func = match module.get_qualified_fn(hash) {
|
||||||
// Then search in Rust functions
|
// Then search native Rust functions
|
||||||
None => {
|
None => {
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
self.inc_operations(&mut global.num_operations, pos)?;
|
self.inc_operations(&mut global.num_operations, pos)?;
|
||||||
@ -1320,6 +1321,41 @@ impl Engine {
|
|||||||
r => r,
|
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
|
// Clone first argument if the function is not a method after-all
|
||||||
if !func.map(|f| f.is_method()).unwrap_or(true) {
|
if !func.map(|f| f.is_method()).unwrap_or(true) {
|
||||||
if let Some(first) = first_arg_value {
|
if let Some(first) = first_arg_value {
|
||||||
|
@ -562,3 +562,29 @@ fn test_module_environ() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
Ok(())
|
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