Refactor.

This commit is contained in:
Stephen Chung 2020-05-22 21:50:24 +08:00
parent 8d12dc2fc1
commit a743c47345
3 changed files with 83 additions and 55 deletions

View File

@ -175,7 +175,7 @@ macro_rules! def_register {
> RegisterFn<FN, ($($mark,)*), RET> for Engine
{
fn register_fn(&mut self, name: &str, f: FN) {
self.global_module.set_fn(name.to_string(), FnAccess::Public,
self.global_module.set_fn(name, FnAccess::Public,
&[$(TypeId::of::<$par>()),*],
CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $clone),*))
);
@ -192,7 +192,7 @@ macro_rules! def_register {
> RegisterResultFn<FN, ($($mark,)*)> for Engine
{
fn register_result_fn(&mut self, name: &str, f: FN) {
self.global_module.set_fn(name.to_string(), FnAccess::Public,
self.global_module.set_fn(name, FnAccess::Public,
&[$(TypeId::of::<$par>()),*],
CallableFunction::$abi(make_func!(f : map_result ; $($par => $clone),*))
);

View File

@ -3,7 +3,7 @@
use crate::any::{Dynamic, Variant};
use crate::calc_fn_hash;
use crate::engine::{Engine, FunctionsLib};
use crate::fn_native::{CallableFunction as CF, FnCallArgs, IteratorFn};
use crate::fn_native::{CallableFunction, FnCallArgs, IteratorFn};
use crate::parser::{
FnAccess,
FnAccess::{Private, Public},
@ -47,7 +47,7 @@ pub struct Module {
all_variables: HashMap<u64, Dynamic>,
/// External Rust functions.
functions: HashMap<u64, (String, FnAccess, StaticVec<TypeId>, CF)>,
functions: HashMap<u64, (String, FnAccess, StaticVec<TypeId>, CallableFunction)>,
/// Script-defined functions.
fn_lib: FunctionsLib,
@ -57,7 +57,7 @@ pub struct Module {
/// Flattened collection of all external Rust functions, native or scripted,
/// including those in sub-modules.
all_functions: HashMap<u64, CF>,
all_functions: HashMap<u64, CallableFunction>,
}
impl fmt::Debug for Module {
@ -164,7 +164,7 @@ impl Module {
/// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ```
pub fn set_var<K: Into<String>, T: Variant + Clone>(&mut self, name: K, value: T) {
pub fn set_var(&mut self, name: impl Into<String>, value: impl Variant + Clone) {
self.variables.insert(name.into(), Dynamic::from(value));
}
@ -244,7 +244,7 @@ impl Module {
/// module.set_sub_module("question", sub_module);
/// assert!(module.get_sub_module("question").is_some());
/// ```
pub fn set_sub_module<K: Into<String>>(&mut self, name: K, sub_module: Module) {
pub fn set_sub_module(&mut self, name: impl Into<String>, sub_module: Module) {
self.modules.insert(name.into(), sub_module.into());
}
@ -269,7 +269,15 @@ impl Module {
/// Set a Rust function into the module, returning a hash key.
///
/// If there is an existing Rust function of the same hash, it is replaced.
pub fn set_fn(&mut self, name: String, access: FnAccess, params: &[TypeId], func: CF) -> u64 {
pub fn set_fn(
&mut self,
name: impl Into<String>,
access: FnAccess,
params: &[TypeId],
func: CallableFunction,
) -> u64 {
let name = name.into();
let hash_fn = calc_fn_hash(empty(), &name, params.len(), params.iter().cloned());
let params = params.into_iter().cloned().collect();
@ -293,15 +301,20 @@ impl Module {
/// let hash = module.set_fn_0("calc", || Ok(42_i64));
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn set_fn_0<K: Into<String>, T: Variant + Clone>(
pub fn set_fn_0<T: Variant + Clone>(
&mut self,
name: K,
name: impl Into<String>,
#[cfg(not(feature = "sync"))] func: impl Fn() -> FuncReturn<T> + 'static,
#[cfg(feature = "sync")] func: impl Fn() -> FuncReturn<T> + Send + Sync + 'static,
) -> u64 {
let f = move |_: &mut FnCallArgs| func().map(Dynamic::from);
let args = [];
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
self.set_fn(
name,
Public,
&args,
CallableFunction::from_pure(Box::new(f)),
)
}
/// Set a Rust function taking one parameter into the module, returning a hash key.
@ -317,16 +330,21 @@ impl Module {
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn set_fn_1<K: Into<String>, A: Variant + Clone, T: Variant + Clone>(
pub fn set_fn_1<A: Variant + Clone, T: Variant + Clone>(
&mut self,
name: K,
name: impl Into<String>,
#[cfg(not(feature = "sync"))] func: impl Fn(A) -> FuncReturn<T> + 'static,
#[cfg(feature = "sync")] func: impl Fn(A) -> FuncReturn<T> + Send + Sync + 'static,
) -> u64 {
let f =
move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from);
let args = [TypeId::of::<A>()];
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
self.set_fn(
name,
Public,
&args,
CallableFunction::from_pure(Box::new(f)),
)
}
/// Set a Rust function taking one mutable parameter into the module, returning a hash key.
@ -342,9 +360,9 @@ impl Module {
/// let hash = module.set_fn_1_mut("calc", |x: &mut i64| { *x += 1; Ok(*x) });
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn set_fn_1_mut<K: Into<String>, A: Variant + Clone, T: Variant + Clone>(
pub fn set_fn_1_mut<A: Variant + Clone, T: Variant + Clone>(
&mut self,
name: K,
name: impl Into<String>,
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A) -> FuncReturn<T> + 'static,
#[cfg(feature = "sync")] func: impl Fn(&mut A) -> FuncReturn<T> + Send + Sync + 'static,
) -> u64 {
@ -352,7 +370,12 @@ impl Module {
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
};
let args = [TypeId::of::<A>()];
self.set_fn(name.into(), Public, &args, CF::from_method(Box::new(f)))
self.set_fn(
name,
Public,
&args,
CallableFunction::from_method(Box::new(f)),
)
}
/// Set a Rust function taking two parameters into the module, returning a hash key.
@ -370,9 +393,9 @@ impl Module {
/// });
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn set_fn_2<K: Into<String>, A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
pub fn set_fn_2<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
&mut self,
name: K,
name: impl Into<String>,
#[cfg(not(feature = "sync"))] func: impl Fn(A, B) -> FuncReturn<T> + 'static,
#[cfg(feature = "sync")] func: impl Fn(A, B) -> FuncReturn<T> + Send + Sync + 'static,
) -> u64 {
@ -383,7 +406,12 @@ impl Module {
func(a, b).map(Dynamic::from)
};
let args = [TypeId::of::<A>(), TypeId::of::<B>()];
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
self.set_fn(
name,
Public,
&args,
CallableFunction::from_pure(Box::new(f)),
)
}
/// Set a Rust function taking two parameters (the first one mutable) into the module,
@ -400,14 +428,9 @@ impl Module {
/// });
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn set_fn_2_mut<
K: Into<String>,
A: Variant + Clone,
B: Variant + Clone,
T: Variant + Clone,
>(
pub fn set_fn_2_mut<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
&mut self,
name: K,
name: impl Into<String>,
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B) -> FuncReturn<T> + 'static,
#[cfg(feature = "sync")] func: impl Fn(&mut A, B) -> FuncReturn<T> + Send + Sync + 'static,
) -> u64 {
@ -418,7 +441,12 @@ impl Module {
func(a, b).map(Dynamic::from)
};
let args = [TypeId::of::<A>(), TypeId::of::<B>()];
self.set_fn(name.into(), Public, &args, CF::from_method(Box::new(f)))
self.set_fn(
name,
Public,
&args,
CallableFunction::from_method(Box::new(f)),
)
}
/// Set a Rust function taking three parameters into the module, returning a hash key.
@ -437,14 +465,13 @@ impl Module {
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn set_fn_3<
K: Into<String>,
A: Variant + Clone,
B: Variant + Clone,
C: Variant + Clone,
T: Variant + Clone,
>(
&mut self,
name: K,
name: impl Into<String>,
#[cfg(not(feature = "sync"))] func: impl Fn(A, B, C) -> FuncReturn<T> + 'static,
#[cfg(feature = "sync")] func: impl Fn(A, B, C) -> FuncReturn<T> + Send + Sync + 'static,
) -> u64 {
@ -456,7 +483,12 @@ impl Module {
func(a, b, c).map(Dynamic::from)
};
let args = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
self.set_fn(
name,
Public,
&args,
CallableFunction::from_pure(Box::new(f)),
)
}
/// Set a Rust function taking three parameters (the first one mutable) into the module,
@ -476,14 +508,13 @@ impl Module {
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn set_fn_3_mut<
K: Into<String>,
A: Variant + Clone,
B: Variant + Clone,
C: Variant + Clone,
T: Variant + Clone,
>(
&mut self,
name: K,
name: impl Into<String>,
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B, C) -> FuncReturn<T> + 'static,
#[cfg(feature = "sync")] func: impl Fn(&mut A, B, C) -> FuncReturn<T> + Send + Sync + 'static,
) -> u64 {
@ -495,7 +526,12 @@ impl Module {
func(a, b, c).map(Dynamic::from)
};
let args = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
self.set_fn(name.into(), Public, &args, CF::from_method(Box::new(f)))
self.set_fn(
name,
Public,
&args,
CallableFunction::from_method(Box::new(f)),
)
}
/// Get a Rust function.
@ -512,7 +548,7 @@ impl Module {
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
/// assert!(module.get_fn(hash).is_some());
/// ```
pub fn get_fn(&self, hash_fn: u64) -> Option<&CF> {
pub fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
self.functions.get(&hash_fn).map(|(_, _, _, v)| v)
}
@ -524,7 +560,7 @@ impl Module {
&mut self,
name: &str,
hash_fn_native: u64,
) -> Result<&CF, Box<EvalAltResult>> {
) -> Result<&CallableFunction, Box<EvalAltResult>> {
self.all_functions.get(&hash_fn_native).ok_or_else(|| {
Box::new(EvalAltResult::ErrorFunctionNotFound(
name.to_string(),
@ -591,7 +627,7 @@ impl Module {
module: &'a Module,
qualifiers: &mut Vec<&'a str>,
variables: &mut Vec<(u64, Dynamic)>,
functions: &mut Vec<(u64, CF)>,
functions: &mut Vec<(u64, CallableFunction)>,
) {
for (name, m) in &module.modules {
// Index all the sub-modules first.
@ -640,7 +676,7 @@ impl Module {
fn_def.params.len(),
empty(),
);
functions.push((hash_fn_def, CF::Script(fn_def.clone()).into()));
functions.push((hash_fn_def, CallableFunction::Script(fn_def.clone()).into()));
}
}

View File

@ -1,6 +1,6 @@
//! Module containing all built-in _packages_ available to Rhai, plus facilities to define custom packages.
use crate::fn_native::{CallableFunction, IteratorFn};
use crate::fn_native::{CallableFunction, IteratorFn, Shared};
use crate::module::Module;
use crate::utils::StaticVec;
@ -44,35 +44,27 @@ pub trait Package {
fn get(&self) -> PackageLibrary;
}
/// Type which `Rc`-wraps a `Module` to facilitate sharing library instances.
#[cfg(not(feature = "sync"))]
pub type PackageLibrary = Rc<Module>;
/// Type which `Arc`-wraps a `Module` to facilitate sharing library instances.
#[cfg(feature = "sync")]
pub type PackageLibrary = Arc<Module>;
/// A sharable `Module` to facilitate sharing library instances.
pub type PackageLibrary = Shared<Module>;
/// Type containing a collection of `PackageLibrary` instances.
/// All function and type iterator keys in the loaded packages are indexed for fast access.
#[derive(Clone, Default)]
pub(crate) struct PackagesCollection {
/// Collection of `PackageLibrary` instances.
packages: StaticVec<PackageLibrary>,
}
pub(crate) struct PackagesCollection(StaticVec<PackageLibrary>);
impl PackagesCollection {
/// Add a `PackageLibrary` into the `PackagesCollection`.
pub fn push(&mut self, package: PackageLibrary) {
// Later packages override previous ones.
self.packages.insert(0, package);
self.0.insert(0, package);
}
/// Does the specified function hash key exist in the `PackagesCollection`?
pub fn contains_fn(&self, hash: u64) -> bool {
self.packages.iter().any(|p| p.contains_fn(hash))
self.0.iter().any(|p| p.contains_fn(hash))
}
/// Get specified function via its hash key.
pub fn get_fn(&self, hash: u64) -> Option<&CallableFunction> {
self.packages
self.0
.iter()
.map(|p| p.get_fn(hash))
.find(|f| f.is_some())
@ -80,11 +72,11 @@ impl PackagesCollection {
}
/// Does the specified TypeId iterator exist in the `PackagesCollection`?
pub fn contains_iter(&self, id: TypeId) -> bool {
self.packages.iter().any(|p| p.contains_iter(id))
self.0.iter().any(|p| p.contains_iter(id))
}
/// Get the specified TypeId iterator.
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.packages
self.0
.iter()
.map(|p| p.get_iter(id))
.find(|f| f.is_some())