New syntax for package definition.

This commit is contained in:
Stephen Chung 2022-02-10 12:33:48 +08:00
parent 1c89c6be4f
commit d1a97be9e3
18 changed files with 60 additions and 22 deletions

View File

@ -37,6 +37,7 @@ New features
* `Engine::set_fail_on_invalid_map_property` is added to control whether to raise an error (new `EvalAltResult::ErrorPropertyNotFound`) when invalid properties are accessed on object maps. * `Engine::set_fail_on_invalid_map_property` is added to control whether to raise an error (new `EvalAltResult::ErrorPropertyNotFound`) when invalid properties are accessed on object maps.
* `Engine::set_allow_shadowing` is added to allow/disallow variables _shadowing_, with new errors `EvalAltResult::ErrorVariableExists` and `ParseErrorType::VariableExists`. * `Engine::set_allow_shadowing` is added to allow/disallow variables _shadowing_, with new errors `EvalAltResult::ErrorVariableExists` and `ParseErrorType::VariableExists`.
* `Engine::on_def_var` allows registering a closure which can decide whether a variable definition is allow to continue, or should fail with an error. * `Engine::on_def_var` allows registering a closure which can decide whether a variable definition is allow to continue, or should fail with an error.
* A new syntax for defining custom packages is introduced that removes the need to specify the Rhai crate name (internally uses the `$crate` meta variable).
Enhancements Enhancements
------------ ------------
@ -50,6 +51,7 @@ Enhancements
* `Expr::start_position` is added to give the beginning of the expression (not the operator's position). * `Expr::start_position` is added to give the beginning of the expression (not the operator's position).
* `StmtBlock` and `Stmt::Block` now keep the position of the closing `}` as well. * `StmtBlock` and `Stmt::Block` now keep the position of the closing `}` as well.
* `EvalAltResult::unwrap_inner` is added to access the base error inside multiple layers of wrappings (e.g. `EvalAltResult::ErrorInFunction`). * `EvalAltResult::unwrap_inner` is added to access the base error inside multiple layers of wrappings (e.g. `EvalAltResult::ErrorInFunction`).
* Yet another new syntax is introduced for `def_package!` that further simplifies the old syntax.
REPL tool changes REPL tool changes
----------------- -----------------

View File

@ -190,7 +190,7 @@ macro_rules! reg_functions {
def_package! { def_package! {
/// Basic arithmetic package. /// Basic arithmetic package.
crate::ArithmeticPackage => |lib| { pub ArithmeticPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "int", int_functions); combine_with_exported_module!(lib, "int", int_functions);

View File

@ -13,7 +13,7 @@ use std::{any::TypeId, cmp::Ordering, mem};
def_package! { def_package! {
/// Package of basic array utilities. /// Package of basic array utilities.
crate::BasicArrayPackage => |lib| { pub BasicArrayPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "array", array_functions); combine_with_exported_module!(lib, "array", array_functions);

View File

@ -8,7 +8,7 @@ use std::prelude::v1::*;
def_package! { def_package! {
/// Package of basic bit-field utilities. /// Package of basic bit-field utilities.
crate::BitFieldPackage => |lib| { pub BitFieldPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "bit_field", bit_field_functions); combine_with_exported_module!(lib, "bit_field", bit_field_functions);

View File

@ -20,7 +20,7 @@ const FLOAT_BYTES: usize = mem::size_of::<FLOAT>();
def_package! { def_package! {
/// Package of basic BLOB utilities. /// Package of basic BLOB utilities.
crate::BasicBlobPackage => |lib| { pub BasicBlobPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "blob", blob_functions); combine_with_exported_module!(lib, "blob", blob_functions);

View File

@ -16,7 +16,7 @@ use crate::Map;
def_package! { def_package! {
/// Package of basic debugging utilities. /// Package of basic debugging utilities.
crate::DebuggingPackage => |lib| { pub DebuggingPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "debugging", debugging_functions); combine_with_exported_module!(lib, "debugging", debugging_functions);

View File

@ -5,7 +5,7 @@ use std::prelude::v1::*;
def_package! { def_package! {
/// Package of basic function pointer utilities. /// Package of basic function pointer utilities.
crate::BasicFnPackage => |lib| { pub BasicFnPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions); combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);

View File

@ -299,7 +299,7 @@ macro_rules! reg_range {
def_package! { def_package! {
/// Package of basic range iterators /// Package of basic range iterators
crate::BasicIteratorPackage => |lib| { pub BasicIteratorPackage(lib) {
lib.standard = true; lib.standard = true;
reg_range!(lib | "range" => INT); reg_range!(lib | "range" => INT);

View File

@ -7,7 +7,7 @@ use std::prelude::v1::*;
def_package! { def_package! {
/// Package of core language features. /// Package of core language features.
crate::LanguageCorePackage => |lib| { pub LanguageCorePackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "core", core_functions); combine_with_exported_module!(lib, "core", core_functions);

View File

@ -37,7 +37,7 @@ macro_rules! reg_functions {
def_package! { def_package! {
/// Package of basic logic operators. /// Package of basic logic operators.
crate::LogicPackage => |lib| { pub LogicPackage(lib) {
lib.standard = true; lib.standard = true;
#[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i32"))]

View File

@ -11,7 +11,7 @@ use crate::Array;
def_package! { def_package! {
/// Package of basic object map utilities. /// Package of basic object map utilities.
crate::BasicMapPackage => |lib| { pub BasicMapPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "map", map_functions); combine_with_exported_module!(lib, "map", map_functions);

View File

@ -53,7 +53,7 @@ macro_rules! reg_functions {
def_package! { def_package! {
/// Basic mathematical package. /// Basic mathematical package.
crate::BasicMathPackage => |lib| { pub BasicMathPackage(lib) {
lib.standard = true; lib.standard = true;
// Integer functions // Integer functions

View File

@ -67,16 +67,52 @@ pub trait Package {
/// ///
/// fn add(x: i64, y: i64) -> Result<i64, Box<EvalAltResult>> { Ok(x + y) } /// fn add(x: i64, y: i64) -> Result<i64, Box<EvalAltResult>> { Ok(x + y) }
/// ///
/// def_package!(rhai:MyPackage:"My super-duper package", module, /// def_package! {
/// { /// /// My super-duper package.
/// // Load a binary function with all value parameters. /// pub MyPackage(module) {
/// module.set_native_fn("my_add", add); /// // Load a binary function with all value parameters.
/// }); /// module.set_native_fn("my_add", add);
/// }
/// }
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! def_package { macro_rules! def_package {
($($(#[$outer:meta])* $mod:vis $package:ident($lib:ident) $block:block)+) => { $(
$(#[$outer])*
$mod struct $package($crate::Shared<$crate::Module>);
impl $crate::packages::Package for $package {
fn as_shared_module(&self) -> $crate::Shared<$crate::Module> {
self.0.clone()
}
fn init($lib: &mut $crate::Module) {
$block
}
}
impl Default for $package {
fn default() -> Self {
Self::new()
}
}
impl $package {
pub fn new() -> Self {
let mut module = $crate::Module::new();
<Self as $crate::packages::Package>::init(&mut module);
module.build_index();
Self(module.into())
}
}
)* };
($($(#[$outer:meta])* $root:ident :: $package:ident => | $lib:ident | $block:block)+) => { $( ($($(#[$outer:meta])* $root:ident :: $package:ident => | $lib:ident | $block:block)+) => { $(
$(#[$outer])* $(#[$outer])*
/// # Deprecated
///
/// This old syntax of `def_package!` is deprecated. Use the new syntax instead.
///
/// This syntax will be removed in the next major version.
#[deprecated(since = "1.5.0", note = "this is an old syntax of `def_package!` and is deprecated; use the new syntax of `def_package!` instead")]
pub struct $package($root::Shared<$root::Module>); pub struct $package($root::Shared<$root::Module>);
impl $root::packages::Package for $package { impl $root::packages::Package for $package {
@ -104,7 +140,6 @@ macro_rules! def_package {
} }
)* }; )* };
($root:ident : $package:ident : $comment:expr , $lib:ident , $block:stmt) => { ($root:ident : $package:ident : $comment:expr , $lib:ident , $block:stmt) => {
#[deprecated(since = "1.4.0", note = "this is an old syntax of `def_package!` and is deprecated; use the new syntax of `def_package!` instead")]
#[doc=$comment] #[doc=$comment]
/// ///
/// # Deprecated /// # Deprecated
@ -112,6 +147,7 @@ macro_rules! def_package {
/// This old syntax of `def_package!` is deprecated. Use the new syntax instead. /// This old syntax of `def_package!` is deprecated. Use the new syntax instead.
/// ///
/// This syntax will be removed in the next major version. /// This syntax will be removed in the next major version.
#[deprecated(since = "1.4.0", note = "this is an old syntax of `def_package!` and is deprecated; use the new syntax of `def_package!` instead")]
pub struct $package($root::Shared<$root::Module>); pub struct $package($root::Shared<$root::Module>);
impl $root::packages::Package for $package { impl $root::packages::Package for $package {

View File

@ -14,7 +14,7 @@ def_package! {
/// * [`BasicIteratorPackage`][super::BasicIteratorPackage] /// * [`BasicIteratorPackage`][super::BasicIteratorPackage]
/// * [`BasicFnPackage`][super::BasicFnPackage] /// * [`BasicFnPackage`][super::BasicFnPackage]
/// * [`DebuggingPackage`][super::DebuggingPackage] /// * [`DebuggingPackage`][super::DebuggingPackage]
crate::CorePackage => |lib| { pub CorePackage(lib) {
lib.standard = true; lib.standard = true;
super::LanguageCorePackage::init(lib); super::LanguageCorePackage::init(lib);

View File

@ -17,7 +17,7 @@ def_package! {
/// * [`BasicMapPackage`][super::BasicMapPackage] /// * [`BasicMapPackage`][super::BasicMapPackage]
/// * [`BasicTimePackage`][super::BasicTimePackage] /// * [`BasicTimePackage`][super::BasicTimePackage]
/// * [`MoreStringPackage`][super::MoreStringPackage] /// * [`MoreStringPackage`][super::MoreStringPackage]
crate::StandardPackage => |lib| { pub StandardPackage(lib) {
lib.standard = true; lib.standard = true;
super::CorePackage::init(lib); super::CorePackage::init(lib);

View File

@ -15,7 +15,7 @@ pub const FUNC_TO_DEBUG: &str = "to_debug";
def_package! { def_package! {
/// Package of basic string utilities (e.g. printing) /// Package of basic string utilities (e.g. printing)
crate::BasicStringPackage => |lib| { pub BasicStringPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "print_debug", print_debug_functions); combine_with_exported_module!(lib, "print_debug", print_debug_functions);

View File

@ -8,7 +8,7 @@ use super::string_basic::{print_with_func, FUNC_TO_STRING};
def_package! { def_package! {
/// Package of additional string utilities over [`BasicStringPackage`][super::BasicStringPackage] /// Package of additional string utilities over [`BasicStringPackage`][super::BasicStringPackage]
crate::MoreStringPackage => |lib| { pub MoreStringPackage(lib) {
lib.standard = true; lib.standard = true;
combine_with_exported_module!(lib, "string", string_functions); combine_with_exported_module!(lib, "string", string_functions);

View File

@ -15,7 +15,7 @@ use instant::{Duration, Instant};
def_package! { def_package! {
/// Package of basic timing utilities. /// Package of basic timing utilities.
crate::BasicTimePackage => |lib| { pub BasicTimePackage(lib) {
lib.standard = true; lib.standard = true;
// Register date/time functions // Register date/time functions