Make FuncInfo a struct.

This commit is contained in:
Stephen Chung 2020-11-04 14:37:46 +08:00
parent b390586bcc
commit a5d22ddd45
2 changed files with 101 additions and 62 deletions

View File

@ -1661,8 +1661,8 @@ impl Engine {
let lib = if cfg!(not(feature = "no_function")) { let lib = if cfg!(not(feature = "no_function")) {
ast.lib() ast.lib()
.iter_fn() .iter_fn()
.filter(|(_, _, _, _, f)| f.is_script()) .filter(|f| f.func.is_script())
.map(|(_, _, _, _, f)| f.get_fn_def().clone()) .map(|f| f.func.get_fn_def().clone())
.collect() .collect()
} else { } else {
Default::default() Default::default()

View File

@ -37,13 +37,20 @@ use crate::stdlib::{
vec::Vec, vec::Vec,
}; };
pub type FuncInfo = ( /// Data structure containing a single registered function.
String, #[derive(Debug, Clone)]
FnAccess, pub struct FuncInfo {
usize, /// Function instance.
Option<StaticVec<TypeId>>, pub func: CallableFunction,
CallableFunction, /// Function access mode.
); pub access: FnAccess,
/// Function name.
pub name: String,
/// Number of parameters.
pub params: usize,
/// Parameter types (if applicable).
pub types: Option<StaticVec<TypeId>>,
}
/// An imported module, which may contain variables, sub-modules, /// An imported module, which may contain variables, sub-modules,
/// external Rust functions, and script-defined functions. /// external Rust functions, and script-defined functions.
@ -91,7 +98,7 @@ impl fmt::Debug for Module {
.join(", "), .join(", "),
self.functions self.functions
.values() .values()
.map(|(_, _, _, _, f)| f.to_string()) .map(|FuncInfo { func, .. }| func.to_string())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "), .join(", "),
) )
@ -290,13 +297,13 @@ impl Module {
let hash_script = calc_script_fn_hash(empty(), &fn_def.name, num_params); let hash_script = calc_script_fn_hash(empty(), &fn_def.name, num_params);
self.functions.insert( self.functions.insert(
hash_script, hash_script,
( FuncInfo {
fn_def.name.to_string(), name: fn_def.name.to_string(),
fn_def.access, access: fn_def.access,
num_params, params: num_params,
None, types: None,
fn_def.into(), func: fn_def.into(),
), },
); );
self.indexed = false; self.indexed = false;
hash_script hash_script
@ -313,12 +320,19 @@ impl Module {
) -> Option<&Shared<ScriptFnDef>> { ) -> Option<&Shared<ScriptFnDef>> {
self.functions self.functions
.values() .values()
.find(|(fn_name, access, num, _, _)| { .find(
(!public_only || *access == FnAccess::Public) |FuncInfo {
&& *num == num_params name: fn_name,
&& fn_name == name access,
}) params,
.map(|(_, _, _, _, f)| f.get_shared_fn_def()) ..
}| {
(!public_only || *access == FnAccess::Public)
&& *params == num_params
&& fn_name == name
},
)
.map(|FuncInfo { func, .. }| func.get_shared_fn_def())
} }
/// Does a sub-module exist in the module? /// Does a sub-module exist in the module?
@ -414,7 +428,7 @@ impl Module {
} else if public_only { } else if public_only {
self.functions self.functions
.get(&hash_fn) .get(&hash_fn)
.map(|(_, access, _, _, _)| access.is_public()) .map(|FuncInfo { access, .. }| access.is_public())
.unwrap_or(false) .unwrap_or(false)
} else { } else {
self.functions.contains_key(&hash_fn) self.functions.contains_key(&hash_fn)
@ -453,7 +467,13 @@ impl Module {
self.functions.insert( self.functions.insert(
hash_fn, hash_fn,
(name, access, params.len(), Some(params), func.into()), FuncInfo {
name,
access,
params: params.len(),
types: Some(params),
func: func.into(),
},
); );
self.indexed = false; self.indexed = false;
@ -1091,9 +1111,9 @@ impl Module {
} else { } else {
self.functions self.functions
.get(&hash_fn) .get(&hash_fn)
.and_then(|(_, access, _, _, f)| match access { .and_then(|FuncInfo { access, func, .. }| match access {
_ if !public_only => Some(f), _ if !public_only => Some(func),
FnAccess::Public => Some(f), FnAccess::Public => Some(func),
FnAccess::Private => None, FnAccess::Private => None,
}) })
} }
@ -1194,7 +1214,7 @@ impl Module {
other other
.functions .functions
.iter() .iter()
.filter(|(_, (_, _, _, _, v))| match v { .filter(|(_, FuncInfo { func, .. })| match func {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
CallableFunction::Script(f) => { CallableFunction::Script(f) => {
_filter(f.access, f.name.as_str(), f.params.len()) _filter(f.access, f.name.as_str(), f.params.len())
@ -1218,10 +1238,11 @@ impl Module {
&mut self, &mut self,
mut filter: impl FnMut(FnAccess, &str, usize) -> bool, mut filter: impl FnMut(FnAccess, &str, usize) -> bool,
) -> &mut Self { ) -> &mut Self {
self.functions.retain(|_, (_, _, _, _, v)| match v { self.functions
CallableFunction::Script(f) => filter(f.access, f.name.as_str(), f.params.len()), .retain(|_, FuncInfo { func, .. }| match func {
_ => true, CallableFunction::Script(f) => filter(f.access, f.name.as_str(), f.params.len()),
}); _ => true,
});
self.all_functions.clear(); self.all_functions.clear();
self.all_variables.clear(); self.all_variables.clear();
@ -1266,7 +1287,7 @@ impl Module {
) -> impl Iterator<Item = (FnAccess, &str, usize, Shared<ScriptFnDef>)> + 'a { ) -> impl Iterator<Item = (FnAccess, &str, usize, Shared<ScriptFnDef>)> + 'a {
self.functions self.functions
.values() .values()
.map(|(_, _, _, _, f)| f) .map(|f| &f.func)
.filter(|f| f.is_script()) .filter(|f| f.is_script())
.map(CallableFunction::get_shared_fn_def) .map(CallableFunction::get_shared_fn_def)
.map(|f| { .map(|f| {
@ -1285,10 +1306,14 @@ impl Module {
#[cfg(not(feature = "internals"))] #[cfg(not(feature = "internals"))]
#[inline(always)] #[inline(always)]
pub fn iter_script_fn_info(&self) -> impl Iterator<Item = (FnAccess, &str, usize)> { pub fn iter_script_fn_info(&self) -> impl Iterator<Item = (FnAccess, &str, usize)> {
self.functions self.functions.values().filter(|f| f.func.is_script()).map(
.values() |FuncInfo {
.filter(|(_, _, _, _, f)| f.is_script()) name,
.map(|(name, access, num_params, _, _)| (*access, name.as_str(), *num_params)) access,
params,
..
}| (*access, name.as_str(), *params),
)
} }
/// Get an iterator over all script-defined functions in the module. /// Get an iterator over all script-defined functions in the module.
@ -1401,31 +1426,45 @@ impl Module {
module module
.functions .functions
.iter() .iter()
.filter(|(_, (_, access, _, _, _))| access.is_public()) .filter(|(_, FuncInfo { access, .. })| access.is_public())
.for_each(|(&_hash, (name, _, _num_params, params, func))| { .for_each(
if let Some(params) = params { |(
// Qualified Rust functions are indexed in two steps: &_hash,
// 1) Calculate a hash in a similar manner to script-defined functions, FuncInfo {
// i.e. qualifiers + function name + number of arguments. name,
let hash_qualified_script = params,
calc_script_fn_hash(qualifiers.iter().cloned(), name, params.len()); types,
// 2) Calculate a second hash with no qualifiers, empty function name, func,
// and the actual list of argument `TypeId`'.s ..
let hash_fn_args = calc_native_fn_hash(empty(), "", params.iter().cloned()); },
// 3) The final hash is the XOR of the two hashes. )| {
let hash_qualified_fn = hash_qualified_script ^ hash_fn_args; if let Some(param_types) = types {
assert_eq!(*params, param_types.len());
functions.push((hash_qualified_fn, func.clone())); // Qualified Rust functions are indexed in two steps:
} else if cfg!(not(feature = "no_function")) { // 1) Calculate a hash in a similar manner to script-defined functions,
let hash_qualified_script = if qualifiers.is_empty() { // i.e. qualifiers + function name + number of arguments.
_hash let hash_qualified_script =
} else { calc_script_fn_hash(qualifiers.iter().cloned(), name, *params);
// Qualifiers + function name + number of arguments. // 2) Calculate a second hash with no qualifiers, empty function name,
calc_script_fn_hash(qualifiers.iter().map(|&v| v), &name, *_num_params) // and the actual list of argument `TypeId`'.s
}; let hash_fn_args =
functions.push((hash_qualified_script, func.clone())); calc_native_fn_hash(empty(), "", param_types.iter().cloned());
} // 3) The final hash is the XOR of the two hashes.
}); let hash_qualified_fn = hash_qualified_script ^ hash_fn_args;
functions.push((hash_qualified_fn, func.clone()));
} else if cfg!(not(feature = "no_function")) {
let hash_qualified_script = if qualifiers.is_empty() {
_hash
} else {
// Qualifiers + function name + number of arguments.
calc_script_fn_hash(qualifiers.iter().map(|&v| v), &name, *params)
};
functions.push((hash_qualified_script, func.clone()));
}
},
);
} }
if !self.indexed { if !self.indexed {