Simplify macro system and update doc comments.

This commit is contained in:
Stephen Chung
2020-09-30 22:55:40 +08:00
parent e526b53b42
commit a04ed02b54
10 changed files with 174 additions and 196 deletions

View File

@@ -7,118 +7,12 @@ use crate::engine::Engine;
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
use crate::module::Module;
use crate::parser::FnAccess;
use crate::plugin::Plugin;
use crate::r#unsafe::unsafe_cast_box;
use crate::result::EvalAltResult;
use crate::utils::ImmutableString;
use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String};
/// A trait to register custom plugins with the `Engine`.
///
/// A plugin consists of a number of functions. All functions will be registered with the engine.
pub trait RegisterPlugin<PL: crate::plugin::Plugin> {
/// Allow extensions of the engine's behavior.
///
/// This can include importing modules, registering functions to the global name space, and
/// more.
///
/// # Example
///
/// ```
/// # #[cfg(not(feature = "no_float"))]
/// use rhai::FLOAT as NUMBER;
/// # #[cfg(feature = "no_float")]
/// use rhai::INT as NUMBER;
/// # #[cfg(not(feature = "no_module"))]
/// use rhai::{Module, ModuleResolver, RegisterFn, RegisterPlugin};
/// # #[cfg(not(feature = "no_module"))]
/// use rhai::plugin::*;
/// # #[cfg(not(feature = "no_module"))]
/// use rhai::module_resolvers::*;
///
/// // A function we want to expose to Rhai.
/// #[derive(Copy, Clone)]
/// struct DistanceFunction();
///
/// # #[cfg(not(feature = "no_module"))]
/// impl PluginFunction for DistanceFunction {
/// fn is_method_call(&self) -> bool { false }
/// fn is_varadic(&self) -> bool { false }
///
/// fn call(&self, args: &mut[&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
/// let x1: NUMBER = std::mem::take(args[0]).clone().cast::<NUMBER>();
/// let y1: NUMBER = std::mem::take(args[1]).clone().cast::<NUMBER>();
/// let x2: NUMBER = std::mem::take(args[2]).clone().cast::<NUMBER>();
/// let y2: NUMBER = std::mem::take(args[3]).clone().cast::<NUMBER>();
/// # #[cfg(not(feature = "no_float"))]
/// let square_sum = (y2 - y1).abs().powf(2.0) + (x2 -x1).abs().powf(2.0);
/// # #[cfg(feature = "no_float")]
/// let square_sum = (y2 - y1).abs().pow(2) + (x2 -x1).abs().pow(2);
/// Ok(Dynamic::from(square_sum))
/// }
///
/// fn clone_boxed(&self) -> Box<dyn PluginFunction> {
/// Box::new(DistanceFunction())
/// }
///
/// fn input_types(&self) -> Box<[std::any::TypeId]> {
/// vec![std::any::TypeId::of::<NUMBER>(),
/// std::any::TypeId::of::<NUMBER>(),
/// std::any::TypeId::of::<NUMBER>(),
/// std::any::TypeId::of::<NUMBER>()].into_boxed_slice()
/// }
/// }
///
/// // A simple custom plugin. This should not usually be done with hand-written code.
/// #[derive(Copy, Clone)]
/// pub struct AdvancedMathPlugin();
///
/// # #[cfg(not(feature = "no_module"))]
/// impl Plugin for AdvancedMathPlugin {
/// fn register_contents(self, engine: &mut Engine) {
/// // Plugins are allowed to have side-effects on the engine.
/// engine.register_fn("get_mystic_number", || { 42 as NUMBER });
///
/// // Main purpose: create a module to expose the functions to Rhai.
/// //
/// // This is currently a hack. There needs to be a better API here for "plugin"
/// // modules.
/// let mut m = Module::new();
/// m.set_fn("euclidean_distance".to_string(), FnAccess::Public,
/// &[std::any::TypeId::of::<NUMBER>(),
/// std::any::TypeId::of::<NUMBER>(),
/// std::any::TypeId::of::<NUMBER>(),
/// std::any::TypeId::of::<NUMBER>()],
/// DistanceFunction().into());
/// let mut r = StaticModuleResolver::new();
/// r.insert("Math::Advanced".to_string(), m);
/// engine.set_module_resolver(Some(r));
/// }
/// }
///
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
///
/// # #[cfg(not(feature = "no_module"))] {
/// let mut engine = Engine::new();
/// engine.register_plugin(AdvancedMathPlugin());
///
/// # #[cfg(feature = "no_float")]
/// assert_eq!(engine.eval::<NUMBER>(
/// r#"import "Math::Advanced" as math;
/// let x = math::euclidean_distance(0, 1, 0, get_mystic_number()); x"#)?, 1681);
/// # #[cfg(not(feature = "no_float"))]
/// assert_eq!(engine.eval::<NUMBER>(
/// r#"import "Math::Advanced" as math;
/// let x = math::euclidean_distance(0.0, 1.0, 0.0, get_mystic_number()); x"#)?, 1681.0);
/// # } // end cfg
/// # Ok(())
/// # }
/// ```
fn register_plugin(&mut self, plugin: PL);
}
/// Trait to register custom functions with the `Engine`.
pub trait RegisterFn<FN, ARGS, RET> {
/// Register a custom function with the `Engine`.
@@ -223,12 +117,6 @@ pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
}
}
impl<PL: Plugin> RegisterPlugin<PL> for Engine {
fn register_plugin(&mut self, plugin: PL) {
plugin.register_contents(self);
}
}
/// This macro creates a closure wrapping a registered function.
macro_rules! make_func {
($fn:ident : $map:expr ; $($par:ident => $let:stmt => $convert:expr => $arg:expr),*) => {