From 9a1c715aad06d7d6b2d9ec393675eb3aeaa6922b Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 22 Apr 2020 14:55:40 +0800 Subject: [PATCH] Refine package API. --- src/engine.rs | 14 ++-- src/packages/arithmetic.rs | 2 +- src/packages/array_basic.rs | 8 +- src/packages/iter_basic.rs | 2 +- src/packages/logic.rs | 2 +- src/packages/map_basic.rs | 6 +- src/packages/math_basic.rs | 2 +- src/packages/pkg_core.rs | 2 +- src/packages/pkg_std.rs | 2 +- src/packages/string_basic.rs | 2 +- src/packages/string_more.rs | 2 +- src/packages/time_basic.rs | 2 +- src/packages/utils.rs | 137 ++++++++++++++++++++++++++++++++--- 13 files changed, 147 insertions(+), 36 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 9e21f155..f3eb035e 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -597,18 +597,16 @@ impl Engine { let result = func(args, pos)?; // See if the function match print/debug (which requires special processing) - return match fn_name { + return Ok(match fn_name { KEYWORD_PRINT if self.on_print.is_some() => { - self.on_print.as_ref().unwrap()(cast_to_string(&result, pos)?); - Ok(().into()) + self.on_print.as_ref().unwrap()(cast_to_string(&result, pos)?).into() } KEYWORD_DEBUG if self.on_debug.is_some() => { - self.on_debug.as_ref().unwrap()(cast_to_string(&result, pos)?); - Ok(().into()) + self.on_debug.as_ref().unwrap()(cast_to_string(&result, pos)?).into() } - KEYWORD_PRINT | KEYWORD_DEBUG => Ok(().into()), - _ => Ok(result), - }; + KEYWORD_PRINT | KEYWORD_DEBUG => ().into(), + _ => result, + }); } if let Some(prop) = extract_prop_from_getter(fn_name) { diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index 3ccbf5e7..fd7a7a5a 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -272,7 +272,7 @@ macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => { $(reg_binary($lib, $op, $func::<$par>, map);)* }; } -def_package!(ArithmeticPackage:"Basic arithmetic", lib, { +def_package!(crate:ArithmeticPackage:"Basic arithmetic", lib, { // Checked basic arithmetic #[cfg(not(feature = "unchecked"))] { diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index 2c4c342c..71c10e9a 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -37,7 +37,7 @@ macro_rules! reg_tri { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => { } #[cfg(not(feature = "no_index"))] -def_package!(BasicArrayPackage:"Basic array utilities.", lib, { +def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, { reg_op!(lib, "push", push, INT, bool, char, String, Array, ()); reg_tri!(lib, "pad", pad, INT, bool, char, String, Array, ()); reg_tri!(lib, "insert", ins, INT, bool, char, String, Array, ()); @@ -71,7 +71,7 @@ def_package!(BasicArrayPackage:"Basic array utilities.", lib, { reg_unary_mut( lib, "pop", - |list: &mut Array| list.pop().unwrap_or_else(|| Dynamic::from_unit()), + |list: &mut Array| list.pop().unwrap_or_else(|| ().into()), pass, ); reg_unary_mut( @@ -79,7 +79,7 @@ def_package!(BasicArrayPackage:"Basic array utilities.", lib, { "shift", |list: &mut Array| { if !list.is_empty() { - Dynamic::from_unit() + ().into() } else { list.remove(0) } @@ -91,7 +91,7 @@ def_package!(BasicArrayPackage:"Basic array utilities.", lib, { "remove", |list: &mut Array, len: INT| { if len < 0 || (len as usize) >= list.len() { - Dynamic::from_unit() + ().into() } else { list.remove(len as usize) } diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index 830193eb..e554019d 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -75,7 +75,7 @@ where ); } -def_package!(BasicIteratorPackage:"Basic range iterators.", lib, { +def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, { fn get_range(from: T, to: T) -> Range { from..to } diff --git a/src/packages/logic.rs b/src/packages/logic.rs index 934e4f98..f0375dc4 100644 --- a/src/packages/logic.rs +++ b/src/packages/logic.rs @@ -40,7 +40,7 @@ macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => { $(reg_binary($lib, $op, $func::<$par>, map);)* }; } -def_package!(LogicPackage:"Logical operators.", lib, { +def_package!(crate:LogicPackage:"Logical operators.", lib, { reg_op!(lib, "<", lt, INT, char); reg_op!(lib, "<=", lte, INT, char); reg_op!(lib, ">", gt, INT, char); diff --git a/src/packages/map_basic.rs b/src/packages/map_basic.rs index 72f6a698..972fce95 100644 --- a/src/packages/map_basic.rs +++ b/src/packages/map_basic.rs @@ -8,7 +8,7 @@ use crate::parser::INT; fn map_get_keys(map: &mut Map) -> Vec { map.iter() - .map(|(k, _)| Dynamic::from_string(k.to_string())) + .map(|(k, _)| k.to_string().into()) .collect::>() } fn map_get_values(map: &mut Map) -> Vec { @@ -16,7 +16,7 @@ fn map_get_values(map: &mut Map) -> Vec { } #[cfg(not(feature = "no_object"))] -def_package!(BasicMapPackage:"Basic object map utilities.", lib, { +def_package!(crate:BasicMapPackage:"Basic object map utilities.", lib, { reg_binary_mut( lib, "has", @@ -28,7 +28,7 @@ def_package!(BasicMapPackage:"Basic object map utilities.", lib, { reg_binary_mut( lib, "remove", - |x: &mut Map, name: String| x.remove(&name).unwrap_or_else(|| Dynamic::from_unit()), + |x: &mut Map, name: String| x.remove(&name).unwrap_or_else(|| ().into()), map, ); reg_binary_mut( diff --git a/src/packages/math_basic.rs b/src/packages/math_basic.rs index 72b953c0..891d3721 100644 --- a/src/packages/math_basic.rs +++ b/src/packages/math_basic.rs @@ -16,7 +16,7 @@ pub const MAX_INT: INT = i32::MAX; #[cfg(not(feature = "only_i32"))] pub const MAX_INT: INT = i64::MAX; -def_package!(BasicMathPackage:"Basic mathematic functions.", lib, { +def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, { #[cfg(not(feature = "no_float"))] { // Advanced math functions diff --git a/src/packages/pkg_core.rs b/src/packages/pkg_core.rs index 1647cc88..9ceae0d9 100644 --- a/src/packages/pkg_core.rs +++ b/src/packages/pkg_core.rs @@ -5,7 +5,7 @@ use super::string_basic::BasicStringPackage; use crate::def_package; -def_package!(CorePackage:"_Core_ package containing basic facilities.", lib, { +def_package!(crate:CorePackage:"_Core_ package containing basic facilities.", lib, { ArithmeticPackage::init(lib); LogicPackage::init(lib); BasicStringPackage::init(lib); diff --git a/src/packages/pkg_std.rs b/src/packages/pkg_std.rs index 51aa9dc0..cfb022eb 100644 --- a/src/packages/pkg_std.rs +++ b/src/packages/pkg_std.rs @@ -9,7 +9,7 @@ use super::time_basic::BasicTimePackage; use crate::def_package; -def_package!(StandardPackage:"_Standard_ package containing all built-in features.", lib, { +def_package!(crate:StandardPackage:"_Standard_ package containing all built-in features.", lib, { CorePackage::init(lib); BasicMathPackage::init(lib); #[cfg(not(feature = "no_index"))] diff --git a/src/packages/string_basic.rs b/src/packages/string_basic.rs index 9c88a18f..43179f56 100644 --- a/src/packages/string_basic.rs +++ b/src/packages/string_basic.rs @@ -25,7 +25,7 @@ macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => { $(reg_unary_mut($lib, $op, $func::<$par>, map);)* }; } -def_package!(BasicStringPackage:"Basic string utilities, including printing.", lib, { +def_package!(crate:BasicStringPackage:"Basic string utilities, including printing.", lib, { reg_op!(lib, KEYWORD_PRINT, to_string, INT, bool, char); reg_op!(lib, FUNC_TO_STRING, to_string, INT, bool, char); diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index c2a31785..37159bda 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -66,7 +66,7 @@ macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => { $(reg_binary($lib, $op, $func::<$par>, map);)* }; } -def_package!(MoreStringPackage:"Additional string utilities, including string building.", lib, { +def_package!(crate:MoreStringPackage:"Additional string utilities, including string building.", lib, { reg_op!(lib, "+", append, INT, bool, char); reg_binary_mut(lib, "+", |x: &mut String, _: ()| x.clone(), map); diff --git a/src/packages/time_basic.rs b/src/packages/time_basic.rs index 13faad95..6fd591ee 100644 --- a/src/packages/time_basic.rs +++ b/src/packages/time_basic.rs @@ -10,7 +10,7 @@ use crate::token::Position; use crate::stdlib::time::Instant; -def_package!(BasicTimePackage:"Basic timing utilities.", lib, { +def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, { #[cfg(not(feature = "no_std"))] { // Register date/time functions diff --git a/src/packages/utils.rs b/src/packages/utils.rs index 0a0b0106..a638b12e 100644 --- a/src/packages/utils.rs +++ b/src/packages/utils.rs @@ -13,45 +13,49 @@ use crate::stdlib::{any::TypeId, boxed::Box}; /// Functions can be added to the package using a number of helper functions under the `packages` module, /// such as `reg_unary`, `reg_binary_mut`, `reg_trinary_mut` etc. /// -/// ```,ignore +/// # Examples +/// +/// ``` +/// use rhai::Dynamic; /// use rhai::def_package; /// use rhai::packages::reg_binary; /// -/// fn add(x: i64, y: i64) { x + y } +/// fn add(x: i64, y: i64) -> i64 { x + y } /// -/// def_package!(MyPackage:"My super-duper package", lib, +/// def_package!(rhai:MyPackage:"My super-duper package", lib, /// { -/// reg_binary(lib, "my_add", add, |v| Ok(v.into_dynamic())); -/// // ^^^^^^^^^^^^^^^^^^^^ -/// // map into Result +/// reg_binary(lib, "my_add", add, |v, _| Ok(v.into())); +/// // ^^^^^^^^^^^^^^^^^^^ +/// // map into Result> /// }); /// ``` /// /// The above defines a package named 'MyPackage' with a single function named 'my_add'. #[macro_export] macro_rules! def_package { - ($package:ident : $comment:expr , $lib:ident , $block:stmt) => { + ($root:ident : $package:ident : $comment:expr , $lib:ident , $block:stmt) => { #[doc=$comment] - pub struct $package(super::PackageLibrary); + pub struct $package($root::packages::PackageLibrary); - impl crate::packages::Package for $package { + impl $root::packages::Package for $package { fn new() -> Self { - let mut pkg = crate::packages::PackageStore::new(); + let mut pkg = $root::packages::PackageStore::new(); Self::init(&mut pkg); Self(pkg.into()) } - fn get(&self) -> crate::packages::PackageLibrary { + fn get(&self) -> $root::packages::PackageLibrary { self.0.clone() } - fn init($lib: &mut crate::packages::PackageStore) { + fn init($lib: &mut $root::packages::PackageStore) { $block } } }; } +/// Check whether the correct number of arguments is passed to the function. fn check_num_args( name: &str, num_args: usize, @@ -73,6 +77,25 @@ fn check_num_args( /// Add a function with no parameters to the package. /// /// `map_result` is a function that maps the return type of the function to `Result`. +/// +/// # Examples +/// +/// ``` +/// use rhai::Dynamic; +/// use rhai::def_package; +/// use rhai::packages::reg_none; +/// +/// fn get_answer() -> i64 { 42 } +/// +/// def_package!(rhai:MyPackage:"My super-duper package", lib, +/// { +/// reg_none(lib, "my_answer", get_answer, |v, _| Ok(v.into())); +/// // ^^^^^^^^^^^^^^^^^^^ +/// // map into Result> +/// }); +/// ``` +/// +/// The above defines a package named 'MyPackage' with a single function named 'my_add_1'. pub fn reg_none( lib: &mut PackageStore, fn_name: &'static str, @@ -102,6 +125,25 @@ pub fn reg_none( /// Add a function with one parameter to the package. /// /// `map_result` is a function that maps the return type of the function to `Result`. +/// +/// # Examples +/// +/// ``` +/// use rhai::Dynamic; +/// use rhai::def_package; +/// use rhai::packages::reg_unary; +/// +/// fn add_1(x: i64) -> i64 { x + 1 } +/// +/// def_package!(rhai:MyPackage:"My super-duper package", lib, +/// { +/// reg_unary(lib, "my_add_1", add_1, |v, _| Ok(v.into())); +/// // ^^^^^^^^^^^^^^^^^^^ +/// // map into Result> +/// }); +/// ``` +/// +/// The above defines a package named 'MyPackage' with a single function named 'my_add_1'. pub fn reg_unary( lib: &mut PackageStore, fn_name: &'static str, @@ -136,6 +178,32 @@ pub fn reg_unary( /// Add a function with one mutable reference parameter to the package. /// /// `map_result` is a function that maps the return type of the function to `Result`. +/// +/// # Examples +/// +/// ``` +/// use rhai::{Dynamic, EvalAltResult}; +/// use rhai::def_package; +/// use rhai::packages::reg_unary_mut; +/// +/// fn inc(x: &mut i64) -> Result> { +/// if *x == 0 { +/// return Err("boo! zero cannot be incremented!".into()) +/// } +/// *x += 1; +/// Ok(().into()) +/// } +/// +/// def_package!(rhai:MyPackage:"My super-duper package", lib, +/// { +/// reg_unary_mut(lib, "try_inc", inc, |r, _| r); +/// // ^^^^^^^^ +/// // map into Result> +/// }); +/// ``` +/// +/// The above defines a package named 'MyPackage' with a single fallible function named 'try_inc' +/// which takes a first argument of `&mut`, return a `Result>`. pub fn reg_unary_mut( lib: &mut PackageStore, fn_name: &'static str, @@ -207,6 +275,25 @@ pub(crate) fn reg_test<'a, A: Variant + Clone, B: Variant + Clone, X, R>( /// Add a function with two parameters to the package. /// /// `map_result` is a function that maps the return type of the function to `Result`. +/// +/// # Examples +/// +/// ``` +/// use rhai::Dynamic; +/// use rhai::def_package; +/// use rhai::packages::reg_binary; +/// +/// fn add(x: i64, y: i64) -> i64 { x + y } +/// +/// def_package!(rhai:MyPackage:"My super-duper package", lib, +/// { +/// reg_binary(lib, "my_add", add, |v, _| Ok(v.into())); +/// // ^^^^^^^^^^^^^^^^^^^ +/// // map into Result> +/// }); +/// ``` +/// +/// The above defines a package named 'MyPackage' with a single function named 'my_add'. pub fn reg_binary( lib: &mut PackageStore, fn_name: &'static str, @@ -245,6 +332,32 @@ pub fn reg_binary( /// Add a function with two parameters (the first one being a mutable reference) to the package. /// /// `map_result` is a function that maps the return type of the function to `Result`. +/// +/// # Examples +/// +/// ``` +/// use rhai::{Dynamic, EvalAltResult}; +/// use rhai::def_package; +/// use rhai::packages::reg_binary_mut; +/// +/// fn add(x: &mut i64, y: i64) -> Result> { +/// if y == 0 { +/// return Err("boo! cannot add zero!".into()) +/// } +/// *x += y; +/// Ok(().into()) +/// } +/// +/// def_package!(rhai:MyPackage:"My super-duper package", lib, +/// { +/// reg_binary_mut(lib, "try_add", add, |r, _| r); +/// // ^^^^^^^^ +/// // map into Result> +/// }); +/// ``` +/// +/// The above defines a package named 'MyPackage' with a single fallible function named 'try_add' +/// which takes a first argument of `&mut`, return a `Result>`. pub fn reg_binary_mut( lib: &mut PackageStore, fn_name: &'static str,