From a04ed02b547b0d90ed18d382bc7a8b1bc9d59b3c Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 30 Sep 2020 22:55:40 +0800 Subject: [PATCH] Simplify macro system and update doc comments. --- Cargo.toml | 5 +- codegen/Cargo.toml | 2 +- codegen/src/function.rs | 4 +- codegen/src/lib.rs | 115 ++++++++++++++++++++++++++++++++--- codegen/src/test/function.rs | 14 ++--- codegen/src/test/module.rs | 62 +++++++++---------- src/fn_native.rs | 4 +- src/fn_register.rs | 112 ---------------------------------- src/lib.rs | 2 +- src/plugin.rs | 50 +++++++-------- 10 files changed, 174 insertions(+), 196 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0def9306..1103a7c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,11 +6,11 @@ members = [ [package] name = "rhai" -version = "0.18.3" +version = "0.19.0" edition = "2018" authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"] description = "Embedded scripting for Rust" -homepage = "https://github.com/jonathandturner/rhai" +homepage = "https://schungx.github.io/rhai" repository = "https://github.com/jonathandturner/rhai" readme = "README.md" license = "MIT OR Apache-2.0" @@ -27,7 +27,6 @@ smallvec = { version = "1.4.2", default-features = false } rhai_codegen = { version = "0.1", path = "codegen" } [features] -#default = ["unchecked", "sync", "no_optimize", "no_float", "only_i32", "no_index", "no_object", "no_function", "no_module"] default = [] unchecked = [] # unchecked arithmetic sync = [] # restrict to only types that implement Send + Sync diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 97a62e06..e8cc0ee5 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2018" authors = ["jhwgh1968"] description = "Proceducral macro support package for Rhai, a scripting language for Rust" -homepage = "https://github.com/jonathandturner/rhai" +homepage = "https://schungx.github.io/rhai/plugins/index.html" repository = "https://github.com/jonathandturner/rhai" license = "MIT OR Apache-2.0" diff --git a/codegen/src/function.rs b/codegen/src/function.rs index 47427ee8..173bb0b2 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -628,7 +628,7 @@ impl ExportedFn { arg_type.span()=> &mut args[0usize].write_lock::<#arg_type>().unwrap()); unpack_stmts.push( syn::parse2::(quote! { - let #var: &mut _ = #downcast_span; + let #var = #downcast_span; }) .unwrap(), ); @@ -757,7 +757,7 @@ impl ExportedFn { } fn is_method_call(&self) -> bool { #is_method_call } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(#type_name()) } fn input_types(&self) -> Box<[TypeId]> { new_vec![#(#input_type_exprs),*].into_boxed_slice() diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 5da8e1b4..abd92df5 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -1,17 +1,14 @@ +//! This crate contains procedural macros to make creating Rhai plugin-modules much easier. //! -//! This crate contains procedural macros to make creating Rhai modules much easier. -//! -//! # Exporting a Macro to Rhai +//! # Export an Entire Rust Module to a Rhai Module //! //! ``` //! use rhai::{EvalAltResult, FLOAT}; //! use rhai::plugin::*; //! use rhai::module_resolvers::*; //! -//! #[rhai::export_module] -//! pub mod advanced_math { -//! use rhai::FLOAT; -//! +//! #[export_module] +//! mod advanced_math { //! pub const MYSTIC_NUMBER: FLOAT = 42.0 as FLOAT; //! //! pub fn euclidean_distance(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT { @@ -35,15 +32,15 @@ //! } //! ``` //! -//! # Exporting a Function to a Rhai Module +//! # Export a Rust Function to a Rhai Module //! //! ``` //! use rhai::{EvalAltResult, FLOAT, Module, RegisterFn}; //! use rhai::plugin::*; //! use rhai::module_resolvers::*; //! -//! #[rhai::export_fn] -//! pub fn distance_function(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT { +//! #[export_fn] +//! fn distance_function(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT { //! ((y2 - y1).abs().powf(2.0) + (x2 -x1).abs().powf(2.0)).sqrt() //! } //! @@ -105,6 +102,18 @@ mod rhai_module; #[cfg(test)] mod test; +/// Attribute, when put on a Rust function, turns it into a _plugin function_. +/// +/// # Usage +/// +/// ```no_run +/// use rhai::plugin::*; +/// +/// #[export_fn] +/// fn my_plugin_function(...) { +/// ... +/// } +/// ``` #[proc_macro_attribute] pub fn export_fn( args: proc_macro::TokenStream, @@ -125,6 +134,18 @@ pub fn export_fn( proc_macro::TokenStream::from(output) } +/// Attribute, when put on a Rust module, turns it into a _plugin module_. +/// +/// # Usage +/// +/// ```no_run +/// use rhai::plugin::*; +/// +/// #[export_module] +/// mod my_plugin_module { +/// ... +/// } +/// ``` #[proc_macro_attribute] pub fn export_module( args: proc_macro::TokenStream, @@ -143,6 +164,20 @@ pub fn export_module( proc_macro::TokenStream::from(tokens) } +/// Macro to generate a Rhai `Module` from a _plugin module_. +/// +/// # Usage +/// +/// ```no_run +/// use rhai::plugin::*; +/// +/// #[export_module] +/// mod my_plugin_module { +/// ... +/// } +/// +/// let module = exported_module!(my_plugin_module); +/// ``` #[proc_macro] pub fn exported_module(module_path: proc_macro::TokenStream) -> proc_macro::TokenStream { let module_path = parse_macro_input!(module_path as syn::Path); @@ -152,6 +187,34 @@ pub fn exported_module(module_path: proc_macro::TokenStream) -> proc_macro::Toke proc_macro::TokenStream::from(tokens) } +/// Macro to combine a _plugin module_ into an existing module. +/// +/// Functions and variables in the plugin module overrides any existing similarly-named +/// functions and variables in the target module. +/// +/// This call is intended to be used within the `def_package!` macro to define a custom +/// package based on a plugin module. +/// +/// All sub-modules, if any, in the plugin module are _flattened_ and their functions/variables +/// registered at the top level because packages require so. +/// +/// The text string name in the second parameter can be anything and is reserved for future use; +/// it is recommended to be an ID string that uniquely identifies the plugin module. +/// +/// # Usage +/// +/// ```no_run +/// use rhai::plugin::*; +/// +/// #[export_module] +/// mod my_plugin_module { +/// ... +/// } +/// +/// let mut module = Module::new(); +/// +/// combine_with_exported_module!(&mut module, "my_plugin_module_ID", my_plugin_module); +/// ``` #[proc_macro] pub fn combine_with_exported_module(args: proc_macro::TokenStream) -> proc_macro::TokenStream { let (module_expr, _export_name, module_path) = match crate::register::parse_register_macro(args) @@ -165,6 +228,22 @@ pub fn combine_with_exported_module(args: proc_macro::TokenStream) -> proc_macro proc_macro::TokenStream::from(tokens) } +/// Macro to register a _plugin function_ into an `Engine`. +/// +/// # Usage +/// +/// ```no_run +/// use rhai::plugin::*; +/// +/// #[export_fn] +/// fn my_plugin_function(...) { +/// ... +/// } +/// +/// let mut engine = Engine::new(); +/// +/// register_exported_fn!(engine, "calc", my_plugin_function); +/// ``` #[proc_macro] pub fn register_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream { let (engine_expr, export_name, rust_modpath) = match crate::register::parse_register_macro(args) @@ -179,6 +258,22 @@ pub fn register_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenS proc_macro::TokenStream::from(tokens) } +/// Macro to register a _plugin function_ into a Rhai `Module`. +/// +/// # Usage +/// +/// ```no_run +/// use rhai::plugin::*; +/// +/// #[export_fn] +/// fn my_plugin_function(...) { +/// ... +/// } +/// +/// let mut module = Module::new(); +/// +/// set_exported_fn!(module, "calc", my_plugin_function); +/// ``` #[proc_macro] pub fn set_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream { let (module_expr, export_name, rust_modpath) = match crate::register::parse_register_macro(args) diff --git a/codegen/src/test/function.rs b/codegen/src/test/function.rs index 2641417a..f028c0b5 100644 --- a/codegen/src/test/function.rs +++ b/codegen/src/test/function.rs @@ -283,7 +283,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(Token()) } fn input_types(&self) -> Box<[TypeId]> { new_vec![].into_boxed_slice() @@ -328,7 +328,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(Token()) } fn input_types(&self) -> Box<[TypeId]> { new_vec![TypeId::of::()].into_boxed_slice() @@ -369,7 +369,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(MyType()) } fn input_types(&self) -> Box<[TypeId]> { new_vec![TypeId::of::()].into_boxed_slice() @@ -404,7 +404,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(Token()) } fn input_types(&self) -> Box<[TypeId]> { new_vec![TypeId::of::(), @@ -446,12 +446,12 @@ mod generate_tests { debug_assert_eq!(args.len(), 2usize, "wrong arg count: {} != {}", args.len(), 2usize); let arg1 = mem::take(args[1usize]).cast::(); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0, arg1))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(Token()) } fn input_types(&self) -> Box<[TypeId]> { new_vec![TypeId::of::(), @@ -498,7 +498,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(Token()) } fn input_types(&self) -> Box<[TypeId]> { new_vec![TypeId::of::()].into_boxed_slice() diff --git a/codegen/src/test/module.rs b/codegen/src/test/module.rs index dbb2d023..fac3becd 100644 --- a/codegen/src/test/module.rs +++ b/codegen/src/test/module.rs @@ -311,7 +311,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(get_mystic_number_token()) } @@ -374,7 +374,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(add_one_to_token()) } @@ -451,7 +451,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(add_one_to_token()) } @@ -480,7 +480,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(add_n_to_token()) } @@ -546,7 +546,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(add_together_token()) } @@ -619,7 +619,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(add_together_token()) } @@ -859,7 +859,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(get_mystic_number_token()) } @@ -953,7 +953,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(print_out_to_token()) } @@ -1017,7 +1017,7 @@ mod generate_tests { } fn is_method_call(&self) -> bool { false } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(print_out_to_token()) } @@ -1076,12 +1076,12 @@ mod generate_tests { ) -> Result> { debug_assert_eq!(args.len(), 1usize, "wrong arg count: {} != {}", args.len(), 1usize); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(increment_token()) } @@ -1143,12 +1143,12 @@ mod generate_tests { ) -> Result> { debug_assert_eq!(args.len(), 1usize, "wrong arg count: {} != {}", args.len(), 1usize); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(increment_token()) } @@ -1230,12 +1230,12 @@ mod generate_tests { ) -> Result> { debug_assert_eq!(args.len(), 1usize, "wrong arg count: {} != {}", args.len(), 1usize); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(increment_token()) } @@ -1315,12 +1315,12 @@ mod generate_tests { ) -> Result> { debug_assert_eq!(args.len(), 1usize, "wrong arg count: {} != {}", args.len(), 1usize); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(int_foo_token()) } @@ -1381,12 +1381,12 @@ mod generate_tests { ) -> Result> { debug_assert_eq!(args.len(), 1usize, "wrong arg count: {} != {}", args.len(), 1usize); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(int_foo_token()) } @@ -1448,12 +1448,12 @@ mod generate_tests { debug_assert_eq!(args.len(), 2usize, "wrong arg count: {} != {}", args.len(), 2usize); let arg1 = mem::take(args[1usize]).cast::(); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0, arg1))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(int_foo_token()) } @@ -1519,12 +1519,12 @@ mod generate_tests { debug_assert_eq!(args.len(), 2usize, "wrong arg count: {} != {}", args.len(), 2usize); let arg1 = mem::take(args[1usize]).cast::(); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0, arg1))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(int_foo_token()) } @@ -1586,12 +1586,12 @@ mod generate_tests { debug_assert_eq!(args.len(), 2usize, "wrong arg count: {} != {}", args.len(), 2usize); let arg1 = mem::take(args[1usize]).cast::(); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(get_by_index(arg0, arg1))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(get_by_index_token()) } @@ -1658,12 +1658,12 @@ mod generate_tests { debug_assert_eq!(args.len(), 2usize, "wrong arg count: {} != {}", args.len(), 2usize); let arg1 = mem::take(args[1usize]).cast::(); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(get_by_index(arg0, arg1))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(get_by_index_token()) } @@ -1728,12 +1728,12 @@ mod generate_tests { "wrong arg count: {} != {}", args.len(), 3usize); let arg1 = mem::take(args[1usize]).cast::(); let arg2 = mem::take(args[2usize]).cast::(); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(set_by_index(arg0, arg1, arg2))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(set_by_index_token()) } @@ -1804,12 +1804,12 @@ mod generate_tests { "wrong arg count: {} != {}", args.len(), 3usize); let arg1 = mem::take(args[1usize]).cast::(); let arg2 = mem::take(args[2usize]).cast::(); - let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(set_by_index(arg0, arg1, arg2))) } fn is_method_call(&self) -> bool { true } - fn is_varadic(&self) -> bool { false } + fn is_variadic(&self) -> bool { false } fn clone_boxed(&self) -> Box { Box::new(set_by_index_token()) } diff --git a/src/fn_native.rs b/src/fn_native.rs index 390fa340..cf2ae263 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -221,7 +221,7 @@ pub enum CallableFunction { Method(Shared), /// An iterator function. Iterator(IteratorFn), - /// A plugin-defined function, + /// A plugin function, Plugin(Shared), /// A script-defined function. #[cfg(not(feature = "no_function"))] @@ -300,7 +300,7 @@ impl CallableFunction { Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => false, } } - /// Is this a plugin-defined function? + /// Is this a plugin function? pub fn is_plugin_fn(&self) -> bool { match self { Self::Plugin(_) => true, diff --git a/src/fn_register.rs b/src/fn_register.rs index b6b7b896..5c519d4c 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -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 { - /// 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> { - /// let x1: NUMBER = std::mem::take(args[0]).clone().cast::(); - /// let y1: NUMBER = std::mem::take(args[1]).clone().cast::(); - /// let x2: NUMBER = std::mem::take(args[2]).clone().cast::(); - /// let y2: NUMBER = std::mem::take(args[3]).clone().cast::(); - /// # #[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 { - /// Box::new(DistanceFunction()) - /// } - /// - /// fn input_types(&self) -> Box<[std::any::TypeId]> { - /// vec![std::any::TypeId::of::(), - /// std::any::TypeId::of::(), - /// std::any::TypeId::of::(), - /// std::any::TypeId::of::()].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::(), - /// std::any::TypeId::of::(), - /// std::any::TypeId::of::(), - /// std::any::TypeId::of::()], - /// DistanceFunction().into()); - /// let mut r = StaticModuleResolver::new(); - /// r.insert("Math::Advanced".to_string(), m); - /// engine.set_module_resolver(Some(r)); - /// } - /// } - /// - /// - /// # fn main() -> Result<(), Box> { - /// - /// # #[cfg(not(feature = "no_module"))] { - /// let mut engine = Engine::new(); - /// engine.register_plugin(AdvancedMathPlugin()); - /// - /// # #[cfg(feature = "no_float")] - /// assert_eq!(engine.eval::( - /// 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::( - /// 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 { /// Register a custom function with the `Engine`. @@ -223,12 +117,6 @@ pub fn by_value(data: &mut Dynamic) -> T { } } -impl RegisterPlugin 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),*) => { diff --git a/src/lib.rs b/src/lib.rs index e88cf7e2..13536be4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,7 +86,7 @@ pub use any::Dynamic; pub use engine::Engine; pub use error::{ParseError, ParseErrorType}; pub use fn_native::{FnPtr, IteratorFn}; -pub use fn_register::{RegisterFn, RegisterPlugin, RegisterResultFn}; +pub use fn_register::{RegisterFn, RegisterResultFn}; pub use module::Module; pub use parser::{ImmutableString, AST, INT}; pub use result::EvalAltResult; diff --git a/src/plugin.rs b/src/plugin.rs index e6e4e956..f82056ea 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,42 +1,38 @@ -//! Module defining plugins in Rhai for use by plugin authors. +//! Module defining macros for developing _plugins_. -pub use crate::{ - fn_native::CallableFunction, stdlib::any::TypeId, stdlib::boxed::Box, stdlib::format, - stdlib::mem, stdlib::string::ToString, stdlib::vec as new_vec, stdlib::vec::Vec, Dynamic, - Engine, EvalAltResult, FnAccess, ImmutableString, Module, RegisterResultFn, -}; +pub use crate::any::Dynamic; +pub use crate::engine::Engine; +pub use crate::fn_native::CallableFunction; +pub use crate::fn_register::{RegisterFn, RegisterResultFn}; +pub use crate::module::Module; +pub use crate::parser::FnAccess; +pub use crate::result::EvalAltResult; +pub use crate::utils::ImmutableString; + +pub use crate::stdlib::{any::TypeId, boxed::Box, format, mem, vec as new_vec}; #[cfg(not(features = "no_module"))] pub use rhai_codegen::*; #[cfg(features = "no_module")] pub use rhai_codegen::{export_fn, register_exported_fn}; -#[cfg(features = "sync")] -/// Represents an externally-written plugin for the Rhai interpreter. +/// Trait implemented by a _plugin function_. +/// This trait should not be used directly. /// -/// This trait should not be used directly. Use the `#[plugin]` procedural attribute instead. -pub trait Plugin: Send { - fn register_contents(self, engine: &mut Engine); -} - -#[cfg(not(features = "sync"))] -/// Represents an externally-written plugin for the Rhai interpreter. -/// -/// This trait should not be used directly. Use the `#[plugin]` procedural attribute instead. -pub trait Plugin: Send + Sync { - fn register_contents(self, engine: &mut Engine); -} - -/// Represents a function that is statically defined within a plugin. -/// -/// This trait should not be used directly. Use the `#[plugin]` procedural attribute instead. +/// Use the `#[export_module]` and `#[export_fn]` procedural attributes instead. pub trait PluginFunction { - fn is_method_call(&self) -> bool; - fn is_varadic(&self) -> bool; - + /// Call the plugin function with the arguments provided. fn call(&self, args: &mut [&mut Dynamic]) -> Result>; + /// Is this plugin function a method? + fn is_method_call(&self) -> bool; + + /// Is this plugin function variadic? + fn is_variadic(&self) -> bool; + + /// Convert a plugin function into a boxed trait object. fn clone_boxed(&self) -> Box; + /// Return a boxed slice of type ID's of the function's parameters. fn input_types(&self) -> Box<[TypeId]>; }