Expose methods for Engine::register_module.

This commit is contained in:
Stephen Chung
2020-11-16 14:07:48 +08:00
parent cd62104296
commit ef02150afd
13 changed files with 385 additions and 149 deletions

View File

@@ -73,11 +73,13 @@ pub struct Module {
all_variables: HashMap<u64, Dynamic, StraightHasherBuilder>,
/// External Rust functions.
functions: HashMap<u64, FuncInfo, StraightHasherBuilder>,
/// Flattened collection of all external Rust functions, native or scripted,
/// Flattened collection of all external Rust functions, native or scripted.
/// including those in sub-modules.
all_functions: HashMap<u64, CallableFunction, StraightHasherBuilder>,
/// Iterator functions, keyed by the type producing the iterator.
type_iterators: HashMap<TypeId, IteratorFn>,
/// Flattened collection of iterator functions, including those in sub-modules.
all_type_iterators: HashMap<TypeId, IteratorFn>,
/// Is the module indexed?
indexed: bool,
}
@@ -91,6 +93,7 @@ impl Default for Module {
functions: HashMap::with_capacity_and_hasher(64, StraightHasherBuilder),
all_functions: HashMap::with_capacity_and_hasher(256, StraightHasherBuilder),
type_iterators: Default::default(),
all_type_iterators: Default::default(),
indexed: false,
}
}
@@ -181,6 +184,7 @@ impl Module {
&& self.all_variables.is_empty()
&& self.modules.is_empty()
&& self.type_iterators.is_empty()
&& self.all_type_iterators.is_empty()
}
/// Is the module indexed?
@@ -1123,6 +1127,15 @@ impl Module {
}
}
/// Does the particular namespace-qualified function exist in the module?
///
/// The `u64` hash is calculated by the function `crate::calc_native_fn_hash` and must match
/// the hash calculated by `build_index`.
#[inline]
pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool {
self.all_functions.contains_key(&hash_fn)
}
/// Get a namespace-qualified function.
/// Name and Position in `EvalAltResult` are None and must be set afterwards.
///
@@ -1143,6 +1156,7 @@ impl Module {
self.type_iterators.extend(other.type_iterators.into_iter());
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self
}
@@ -1160,6 +1174,7 @@ impl Module {
self.type_iterators.extend(other.type_iterators.into_iter());
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self
}
@@ -1186,6 +1201,7 @@ impl Module {
});
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self
}
@@ -1231,6 +1247,7 @@ impl Module {
self.type_iterators.extend(other.type_iterators.iter());
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self
}
@@ -1250,6 +1267,7 @@ impl Module {
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self
}
@@ -1388,10 +1406,13 @@ impl Module {
// Extra modules left in the scope become sub-modules
let mut func_mods: Imports = Default::default();
mods.into_iter().skip(orig_mods_len).for_each(|(alias, m)| {
func_mods.push(alias.clone(), m.clone());
module.set_sub_module(alias, m);
});
mods.into_iter()
.skip(orig_mods_len)
.filter(|&(_, fixed, _)| !fixed)
.for_each(|(alias, _, m)| {
func_mods.push(alias.clone(), m.clone());
module.set_sub_module(alias, m);
});
// Non-private functions defined become module functions
#[cfg(not(feature = "no_function"))]
@@ -1422,13 +1443,14 @@ impl Module {
fn index_module<'a>(
module: &'a Module,
qualifiers: &mut Vec<&'a str>,
variables: &mut Vec<(u64, Dynamic)>,
functions: &mut Vec<(u64, CallableFunction)>,
variables: &mut HashMap<u64, Dynamic, StraightHasherBuilder>,
functions: &mut HashMap<u64, CallableFunction, StraightHasherBuilder>,
type_iterators: &mut HashMap<TypeId, IteratorFn>,
) {
module.modules.iter().for_each(|(name, m)| {
// Index all the sub-modules first.
qualifiers.push(name);
index_module(m, qualifiers, variables, functions);
index_module(m, qualifiers, variables, functions, type_iterators);
qualifiers.pop();
});
@@ -1436,8 +1458,14 @@ impl Module {
module.variables.iter().for_each(|(var_name, value)| {
// Qualifiers + variable name
let hash_var = calc_script_fn_hash(qualifiers.iter().map(|&v| v), var_name, 0);
variables.push((hash_var, value.clone()));
variables.insert(hash_var, value.clone());
});
// Index type iterators
module.type_iterators.iter().for_each(|(&type_id, func)| {
type_iterators.insert(type_id, func.clone());
});
// Index all Rust functions
module
.functions
@@ -1445,7 +1473,7 @@ impl Module {
.filter(|(_, FuncInfo { access, .. })| access.is_public())
.for_each(
|(
&_hash,
&hash,
FuncInfo {
name,
params,
@@ -1454,6 +1482,12 @@ impl Module {
..
},
)| {
// Flatten all methods so they can be available without namespace qualifiers
#[cfg(not(feature = "no_object"))]
if func.is_method() {
functions.insert(hash, func.clone());
}
if let Some(param_types) = types {
assert_eq!(*params, param_types.len());
@@ -1469,15 +1503,17 @@ impl Module {
// 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()));
functions.insert(hash_qualified_fn, func.clone());
} else if cfg!(not(feature = "no_function")) {
let hash_qualified_script = if qualifiers.is_empty() {
_hash
let hash_qualified_script = if cfg!(feature = "no_object")
&& 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()));
functions.insert(hash_qualified_script, func.clone());
}
},
);
@@ -1485,19 +1521,32 @@ impl Module {
if !self.indexed {
let mut qualifiers = Vec::with_capacity(4);
let mut variables = Vec::with_capacity(16);
let mut functions = Vec::with_capacity(256);
let mut variables = HashMap::with_capacity_and_hasher(16, StraightHasherBuilder);
let mut functions = HashMap::with_capacity_and_hasher(256, StraightHasherBuilder);
let mut type_iterators = HashMap::with_capacity(16);
qualifiers.push("root");
index_module(self, &mut qualifiers, &mut variables, &mut functions);
index_module(
self,
&mut qualifiers,
&mut variables,
&mut functions,
&mut type_iterators,
);
self.all_variables = variables.into_iter().collect();
self.all_functions = functions.into_iter().collect();
self.all_variables = variables;
self.all_functions = functions;
self.all_type_iterators = type_iterators;
self.indexed = true;
}
}
/// Does a type iterator exist in the entire module tree?
pub fn contains_qualified_iter(&self, id: TypeId) -> bool {
self.all_type_iterators.contains_key(&id)
}
/// Does a type iterator exist in the module?
pub fn contains_iter(&self, id: TypeId) -> bool {
self.type_iterators.contains_key(&id)
@@ -1532,6 +1581,11 @@ impl Module {
})
}
/// Get the specified type iterator.
pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.all_type_iterators.get(&id).cloned()
}
/// Get the specified type iterator.
pub(crate) fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.type_iterators.get(&id).cloned()