Remove public_only parameters.

This commit is contained in:
Stephen Chung 2021-03-17 09:58:08 +08:00
parent 5172ade179
commit 4581943435
6 changed files with 56 additions and 84 deletions

View File

@ -575,6 +575,11 @@ Bug fixes
* Fixes bug that prevents calling functions in closures.
* Fixes bug that erroneously consumes the first argument to a namespace-qualified function call.
Breaking changes
----------------
* `Module::contains_fn` and `Module::get_script_fn` no longer take the `public_only` parameter.
New features
------------

View File

@ -1881,7 +1881,7 @@ impl Engine {
let fn_def = ast
.lib()
.get_script_fn(name, args.len(), false)
.get_script_fn(name, args.len())
.ok_or_else(|| EvalAltResult::ErrorFunctionNotFound(name.into(), Position::NONE))?;
// Check for data race.

View File

@ -124,6 +124,7 @@ pub fn ensure_no_data_race(
impl Engine {
/// Generate the signature for a function call.
#[inline]
fn gen_call_signature(
&self,
namespace: Option<&NamespaceRef>,
@ -176,7 +177,7 @@ impl Engine {
.fn_resolution_cache_mut()
.entry(hash)
.or_insert_with(|| {
let num_args = args.as_ref().map(|a| a.len()).unwrap_or(0);
let num_args = args.as_ref().map_or(0, |a| a.len());
let max_bitmask = if !allow_dynamic {
0
} else {
@ -188,43 +189,37 @@ impl Engine {
let func = lib
.iter()
.find_map(|m| {
m.get_fn(hash, false)
.cloned()
.map(|func| FnResolutionCacheEntry {
func,
source: m.id_raw().cloned(),
m.get_fn(hash).cloned().map(|func| {
let source = m.id_raw().cloned();
FnResolutionCacheEntry { func, source }
})
})
.or_else(|| {
self.global_namespace
.get_fn(hash, false)
.get_fn(hash)
.cloned()
.map(|func| FnResolutionCacheEntry { func, source: None })
})
.or_else(|| {
self.global_modules.iter().find_map(|m| {
m.get_fn(hash, false)
.cloned()
.map(|func| FnResolutionCacheEntry {
func,
source: m.id_raw().cloned(),
m.get_fn(hash).cloned().map(|func| {
let source = m.id_raw().cloned();
FnResolutionCacheEntry { func, source }
})
})
})
.or_else(|| {
mods.get_fn(hash)
.map(|(func, source)| FnResolutionCacheEntry {
func: func.clone(),
source: source.cloned(),
mods.get_fn(hash).map(|(func, source)| {
let func = func.clone();
let source = source.cloned();
FnResolutionCacheEntry { func, source }
})
})
.or_else(|| {
self.global_sub_modules.values().find_map(|m| {
m.get_qualified_fn(hash).cloned().map(|func| {
FnResolutionCacheEntry {
func,
source: m.id_raw().cloned(),
}
let source = m.id_raw().cloned();
FnResolutionCacheEntry { func, source }
})
})
});
@ -235,41 +230,31 @@ impl Engine {
// Stop when all permutations are exhausted
None if bitmask >= max_bitmask => {
return if num_args != 2 {
None
} else if let Some(ref args) = args {
if !is_op_assignment {
if let Some(f) =
get_builtin_binary_op_fn(fn_name, &args[0], &args[1])
{
Some(FnResolutionCacheEntry {
func: CallableFunction::from_method(
Box::new(f) as Box<FnAny>
),
source: None,
})
} else {
None
if num_args != 2 {
return None;
}
return args.and_then(|args| {
if !is_op_assignment {
get_builtin_binary_op_fn(fn_name, &args[0], &args[1]).map(|f| {
let func = CallableFunction::from_method(
Box::new(f) as Box<FnAny>
);
FnResolutionCacheEntry { func, source: None }
})
} else {
let (first, second) = args.split_first().unwrap();
if let Some(f) =
get_builtin_op_assignment_fn(fn_name, *first, second[0])
{
Some(FnResolutionCacheEntry {
func: CallableFunction::from_method(
get_builtin_op_assignment_fn(fn_name, *first, second[0]).map(
|f| {
let func = CallableFunction::from_method(
Box::new(f) as Box<FnAny>
),
source: None,
})
} else {
None
}
}
} else {
None
);
FnResolutionCacheEntry { func, source: None }
},
)
}
});
}
// Try all permutations with `Dynamic` wildcards
@ -612,11 +597,11 @@ impl Engine {
}
// First check script-defined functions
let result = lib.iter().any(|&m| m.contains_fn(hash_script, false))
let result = lib.iter().any(|&m| m.contains_fn(hash_script))
// Then check registered functions
|| self.global_namespace.contains_fn(hash_script, false)
|| self.global_namespace.contains_fn(hash_script)
// Then check packages
|| self.global_modules.iter().any(|m| m.contains_fn(hash_script, false))
|| self.global_modules.iter().any(|m| m.contains_fn(hash_script))
// Then check imported modules
|| mods.map_or(false, |m| m.contains_fn(hash_script))
// Then check sub-modules

View File

@ -513,15 +513,10 @@ impl Module {
&self,
name: &str,
num_params: usize,
public_only: bool,
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
self.functions
.values()
.find(|f| {
(!public_only || f.access == FnAccess::Public)
&& f.params == num_params
&& f.name == name
})
.find(|f| f.params == num_params && f.name == name)
.map(|f| f.func.get_fn_def())
}
@ -616,21 +611,12 @@ impl Module {
///
/// let mut module = Module::new();
/// let hash = module.set_native_fn("calc", || Ok(42_i64));
/// assert!(module.contains_fn(hash, true));
/// assert!(module.contains_fn(hash));
/// ```
#[inline(always)]
pub fn contains_fn(&self, hash_fn: u64, public_only: bool) -> bool {
if public_only {
self.functions
.get(&hash_fn)
.map_or(false, |f| match f.access {
FnAccess::Public => true,
FnAccess::Private => false,
})
} else {
pub fn contains_fn(&self, hash_fn: u64) -> bool {
self.functions.contains_key(&hash_fn)
}
}
/// Update the metadata (parameter names/types and return type) of a registered function.
///
@ -1110,12 +1096,8 @@ impl Module {
///
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
#[inline(always)]
pub(crate) fn get_fn(&self, hash_fn: u64, public_only: bool) -> Option<&CallableFunction> {
self.functions.get(&hash_fn).and_then(|f| match f.access {
_ if !public_only => Some(&f.func),
FnAccess::Public => Some(&f.func),
FnAccess::Private => None,
})
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
self.functions.get(&hash_fn).map(|f| &f.func)
}
/// Does the particular namespace-qualified function exist in the [`Module`]?

View File

@ -139,9 +139,9 @@ fn has_native_fn(state: &State, hash_script: u64, arg_types: &[TypeId]) -> bool
let hash = combine_hashes(hash_script, hash_params);
// First check registered functions
state.engine.global_namespace.contains_fn(hash, false)
state.engine.global_namespace.contains_fn(hash)
// Then check packages
|| state.engine.global_modules.iter().any(|m| m.contains_fn(hash, false))
|| state.engine.global_modules.iter().any(|m| m.contains_fn(hash))
// Then check sub-modules
|| state.engine.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash))
}
@ -774,7 +774,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
=> {
// First search for script-defined functions (can override built-in)
#[cfg(not(feature = "no_function"))]
let has_script_fn = state.lib.iter().any(|&m| m.get_script_fn(x.name.as_ref(), x.args.len(), false).is_some());
let has_script_fn = state.lib.iter().any(|&m| m.get_script_fn(x.name.as_ref(), x.args.len()).is_some());
#[cfg(feature = "no_function")]
let has_script_fn = false;

View File

@ -49,7 +49,7 @@ fn test_module_sub_module() -> Result<(), Box<EvalAltResult>> {
let m2 = m.get_sub_module("universe").unwrap();
assert!(m2.contains_var("answer"));
assert!(m2.contains_fn(hash_inc, false));
assert!(m2.contains_fn(hash_inc));
assert_eq!(m2.get_var_value::<INT>("answer").unwrap(), 41);