From de0707f64f28611624ba2ea6dde233d85a9c72e3 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 4 Dec 2022 14:06:54 +0800 Subject: [PATCH] Use macro auto_restore!. --- CHANGELOG.md | 3 ++- src/api/build_type.rs | 2 +- src/api/call_fn.rs | 8 ++---- src/api/custom_syntax.rs | 4 +-- src/api/deprecated.rs | 4 +-- src/api/eval.rs | 2 +- src/api/register.rs | 2 +- src/eval/chaining.rs | 39 +++++++-------------------- src/eval/expr.rs | 10 ++----- src/eval/stmt.rs | 32 ++++++---------------- src/func/call.rs | 31 +++++++-------------- src/func/callable_function.rs | 2 +- src/func/func.rs | 8 +++--- src/func/native.rs | 4 +-- src/func/register.rs | 51 ++++++++++++++++++++--------------- src/lib.rs | 7 +++-- src/module/mod.rs | 2 +- src/reify.rs | 1 - src/types/custom_types.rs | 15 +++-------- src/types/dynamic.rs | 2 +- src/types/fn_ptr.rs | 4 +-- src/types/mod.rs | 4 ++- src/types/restore.rs | 47 +++++++++++++++++++++----------- 23 files changed, 122 insertions(+), 162 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76988274..cb8861ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Breaking API changes -------------------- * The callback for initializing a debugger instance has changed to `Fn(&Engine, Debugger) -> Debugger`. This allows more control over the initial setup of the debugger. +* The internal macro `reify!` is no longer available publicly. Deprecated API's ---------------- @@ -25,7 +26,7 @@ Speed improvements ------------------ * The functions registration mechanism is revamped to take advantage of constant generics, among others. -* This yields a 20% speed improvements on certain real-life, function-call-heavy workloads. +* This yields a 10-20% speed improvements on certain real-life, function-call-heavy workloads. Net features ------------ diff --git a/src/api/build_type.rs b/src/api/build_type.rs index 08b483d0..1edce75b 100644 --- a/src/api/build_type.rs +++ b/src/api/build_type.rs @@ -117,7 +117,7 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> { /// Register a custom function. #[inline(always)] - pub fn with_fn( + pub fn with_fn( &mut self, name: impl AsRef + Into, method: impl RegisterNativeFunction, diff --git a/src/api/call_fn.rs b/src/api/call_fn.rs index a1f0ef7c..d15e7c37 100644 --- a/src/api/call_fn.rs +++ b/src/api/call_fn.rs @@ -3,10 +3,8 @@ use crate::eval::{Caches, GlobalRuntimeState}; use crate::types::dynamic::Variant; -use crate::types::RestoreOnDrop; use crate::{ - reify, Dynamic, Engine, FuncArgs, Position, RhaiResult, RhaiResultOf, Scope, StaticVec, AST, - ERR, + Dynamic, Engine, FuncArgs, Position, RhaiResult, RhaiResultOf, Scope, StaticVec, AST, ERR, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -241,9 +239,7 @@ impl Engine { let result = if options.eval_ast && !statements.is_empty() { let orig_scope_len = scope.len(); - let scope = &mut *RestoreOnDrop::lock_if(rewind_scope, scope, move |s| { - s.rewind(orig_scope_len); - }); + auto_restore!(scope; rewind_scope => move |s| { s.rewind(orig_scope_len); }); self.eval_global_statements(global, caches, scope, statements) } else { diff --git a/src/api/custom_syntax.rs b/src/api/custom_syntax.rs index 07422206..faf9af17 100644 --- a/src/api/custom_syntax.rs +++ b/src/api/custom_syntax.rs @@ -7,8 +7,8 @@ use crate::parser::ParseResult; use crate::tokenizer::{is_valid_identifier, Token, NO_TOKEN}; use crate::types::dynamic::Variant; use crate::{ - reify, Dynamic, Engine, EvalContext, Identifier, ImmutableString, LexError, Position, - RhaiResult, StaticVec, + Dynamic, Engine, EvalContext, Identifier, ImmutableString, LexError, Position, RhaiResult, + StaticVec, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; diff --git a/src/api/deprecated.rs b/src/api/deprecated.rs index b40d936a..4beaca5b 100644 --- a/src/api/deprecated.rs +++ b/src/api/deprecated.rs @@ -185,7 +185,7 @@ impl Engine { /// This method will be removed in the next major version. #[deprecated(since = "1.9.1", note = "use `register_fn` instead")] #[inline(always)] - pub fn register_result_fn( + pub fn register_result_fn( &mut self, name: impl AsRef + Into, func: impl RegisterNativeFunction, @@ -514,7 +514,7 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> { /// This method will be removed in the next major version. #[deprecated(since = "1.9.1", note = "use `with_fn` instead")] #[inline(always)] - pub fn with_result_fn( + pub fn with_result_fn( &mut self, name: S, method: F, diff --git a/src/api/eval.rs b/src/api/eval.rs index f5e1503c..9dbfb17f 100644 --- a/src/api/eval.rs +++ b/src/api/eval.rs @@ -5,7 +5,7 @@ use crate::func::native::locked_write; use crate::parser::ParseState; use crate::types::dynamic::Variant; use crate::{ - reify, Dynamic, Engine, OptimizationLevel, Position, RhaiResult, RhaiResultOf, Scope, AST, ERR, + Dynamic, Engine, OptimizationLevel, Position, RhaiResult, RhaiResultOf, Scope, AST, ERR, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; diff --git a/src/api/register.rs b/src/api/register.rs index 259ca0d7..203740a0 100644 --- a/src/api/register.rs +++ b/src/api/register.rs @@ -57,7 +57,7 @@ impl Engine { /// ``` #[inline] pub fn register_fn< - A, + A: 'static, const N: usize, const C: bool, R: Variant + Clone, diff --git a/src/eval/chaining.rs b/src/eval/chaining.rs index 3b257b57..b7cece39 100644 --- a/src/eval/chaining.rs +++ b/src/eval/chaining.rs @@ -6,7 +6,7 @@ use crate::ast::{ASTFlags, Expr, OpAssignment}; use crate::config::hashing::SusLock; use crate::engine::{FN_IDX_GET, FN_IDX_SET}; use crate::tokenizer::NO_TOKEN; -use crate::types::{dynamic::Union, RestoreOnDrop}; +use crate::types::dynamic::Union; use crate::{ calc_fn_hash, Dynamic, Engine, FnArgsVec, Position, RhaiResult, RhaiResultOf, Scope, ERR, }; @@ -68,9 +68,7 @@ impl Engine { idx: &mut Dynamic, pos: Position, ) -> RhaiResultOf { - let orig_level = global.level; - global.level += 1; - let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level); + auto_restore! { let orig_level = global.level; global.level += 1 } let hash = hash_idx().0; let args = &mut [target, idx]; @@ -91,9 +89,7 @@ impl Engine { is_ref_mut: bool, pos: Position, ) -> RhaiResultOf<(Dynamic, bool)> { - let orig_level = global.level; - global.level += 1; - let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level); + auto_restore! { let orig_level = global.level; global.level += 1 } let hash = hash_idx().1; let args = &mut [target, idx, new_val]; @@ -688,10 +684,7 @@ impl Engine { let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, rhs)?; #[cfg(feature = "debugging")] - let global = - &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| { - g.debugger_mut().reset_status(reset) - }); + auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset)); let crate::ast::FnCallExpr { name, hashes, args, .. @@ -699,8 +692,7 @@ impl Engine { // Truncate the index values upon exit let offset = idx_values.len() - args.len(); - let idx_values = - &mut *RestoreOnDrop::lock(idx_values, move |v| v.truncate(offset)); + auto_restore!(idx_values => move |v| v.truncate(offset)); let call_args = &mut idx_values[offset..]; let arg1_pos = args.get(0).map_or(Position::NONE, Expr::position); @@ -862,11 +854,7 @@ impl Engine { global, caches, scope, this_ptr, _node, )?; #[cfg(feature = "debugging")] - let global = &mut *RestoreOnDrop::lock_if( - reset.is_some(), - global, - move |g| g.debugger_mut().reset_status(reset), - ); + auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset)); let crate::ast::FnCallExpr { name, hashes, args, .. @@ -874,9 +862,7 @@ impl Engine { // Truncate the index values upon exit let offset = idx_values.len() - args.len(); - let idx_values = &mut *RestoreOnDrop::lock(idx_values, move |v| { - v.truncate(offset) - }); + auto_restore!(idx_values => move |v| v.truncate(offset)); let call_args = &mut idx_values[offset..]; let arg1_pos = args.get(0).map_or(Position::NONE, Expr::position); @@ -987,11 +973,7 @@ impl Engine { global, caches, scope, this_ptr, _node, )?; #[cfg(feature = "debugging")] - let global = &mut *RestoreOnDrop::lock_if( - reset.is_some(), - global, - move |g| g.debugger_mut().reset_status(reset), - ); + auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset)); let crate::ast::FnCallExpr { name, hashes, args, .. @@ -999,10 +981,7 @@ impl Engine { // Truncate the index values upon exit let offset = idx_values.len() - args.len(); - let idx_values = - &mut *RestoreOnDrop::lock(idx_values, move |v| { - v.truncate(offset) - }); + auto_restore!(idx_values => move |v| v.truncate(offset)); let call_args = &mut idx_values[offset..]; let pos1 = args.get(0).map_or(Position::NONE, Expr::position); diff --git a/src/eval/expr.rs b/src/eval/expr.rs index 6750c398..4ed0e4ab 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -234,10 +234,7 @@ impl Engine { #[cfg(feature = "debugging")] let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?; #[cfg(feature = "debugging")] - let global = - &mut *crate::types::RestoreOnDrop::lock_if(reset.is_some(), global, move |g| { - g.debugger_mut().reset_status(reset) - }); + auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset)); self.track_operation(global, expr.position())?; @@ -268,10 +265,7 @@ impl Engine { #[cfg(feature = "debugging")] let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?; #[cfg(feature = "debugging")] - let global = - &mut *crate::types::RestoreOnDrop::lock_if(reset.is_some(), global, move |g| { - g.debugger_mut().reset_status(reset) - }); + auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset)); self.track_operation(global, expr.position())?; diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 867aff7d..50c3cc0e 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -7,7 +7,6 @@ use crate::ast::{ }; use crate::func::{get_builtin_op_assignment_fn, get_hasher}; use crate::types::dynamic::{AccessMode, Union}; -use crate::types::RestoreOnDrop; use crate::{Dynamic, Engine, RhaiResult, RhaiResultOf, Scope, ERR, INT}; use std::hash::{Hash, Hasher}; #[cfg(feature = "no_std")] @@ -43,9 +42,7 @@ impl Engine { // Restore scope at end of block if necessary let orig_scope_len = scope.len(); - let scope = &mut *RestoreOnDrop::lock_if(restore_orig_state, scope, move |s| { - s.rewind(orig_scope_len); - }); + auto_restore!(scope; restore_orig_state => move |s| { s.rewind(orig_scope_len); }); // Restore global state at end of block if necessary let orig_always_search_scope = global.always_search_scope; @@ -56,7 +53,7 @@ impl Engine { global.scope_level += 1; } - let global = &mut *RestoreOnDrop::lock_if(restore_orig_state, global, move |g| { + auto_restore!(global; restore_orig_state => move |g| { g.scope_level -= 1; #[cfg(not(feature = "no_module"))] @@ -69,9 +66,7 @@ impl Engine { // Pop new function resolution caches at end of block let orig_fn_resolution_caches_len = caches.fn_resolution_caches_len(); - let caches = &mut *RestoreOnDrop::lock(caches, move |c| { - c.rewind_fn_resolution_caches(orig_fn_resolution_caches_len) - }); + auto_restore!(caches => move |c| c.rewind_fn_resolution_caches(orig_fn_resolution_caches_len)); // Run the statements statements.iter().try_fold(Dynamic::UNIT, |_, stmt| { @@ -147,13 +142,10 @@ impl Engine { { // Built-in found let op = op_assign_token.literal_syntax(); - - let orig_level = global.level; - global.level += 1; - let global = &*RestoreOnDrop::lock(global, move |g| g.level = orig_level); + auto_restore! { let orig_level = global.level; global.level += 1 } let context = if ctx { - Some((self, op, None, global, *op_pos).into()) + Some((self, op, None, &*global, *op_pos).into()) } else { None }; @@ -212,9 +204,7 @@ impl Engine { #[cfg(feature = "debugging")] let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, stmt)?; #[cfg(feature = "debugging")] - let global = &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| { - g.debugger_mut().reset_status(reset) - }); + auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset)); // Coded this way for better branch prediction. // Popular branches are lifted out of the `match` statement into their own branches. @@ -526,10 +516,7 @@ impl Engine { // Restore scope at end of statement let orig_scope_len = scope.len(); - let scope = &mut *RestoreOnDrop::lock(scope, move |s| { - s.rewind(orig_scope_len); - }); - + auto_restore!(scope => move |s| { s.rewind(orig_scope_len); }); // Add the loop variables let counter_index = if counter.is_empty() { usize::MAX @@ -657,10 +644,7 @@ impl Engine { // Restore scope at end of block let orig_scope_len = scope.len(); - let scope = - &mut *RestoreOnDrop::lock_if(!catch_var.is_empty(), scope, move |s| { - s.rewind(orig_scope_len); - }); + auto_restore!(scope; !catch_var.is_empty() => move |s| { s.rewind(orig_scope_len); }); if !catch_var.is_empty() { scope.push(catch_var.name.clone(), err_value); diff --git a/src/func/call.rs b/src/func/call.rs index e5f5adc9..5eb3585f 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -9,7 +9,6 @@ use crate::engine::{ }; use crate::eval::{Caches, FnResolutionCacheEntry, GlobalRuntimeState}; use crate::tokenizer::{is_valid_function_name, Token, NO_TOKEN}; -use crate::types::RestoreOnDrop; use crate::{ calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString, OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, ERR, @@ -381,9 +380,7 @@ impl Engine { // Clone the first argument backup.change_first_arg_to_copy(args); } - - let args = - &mut *RestoreOnDrop::lock_if(swap, args, move |a| backup.restore_first_arg(a)); + auto_restore!(args; swap => move |a| backup.restore_first_arg(a)); #[cfg(feature = "debugging")] if self.is_debugger_registered() { @@ -583,9 +580,7 @@ impl Engine { #[cfg(not(feature = "no_closure"))] ensure_no_data_race(fn_name, _args, is_ref_mut)?; - let orig_level = global.level; - global.level += 1; - let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level); + auto_restore! { let orig_level = global.level; global.level += 1 } // These may be redirected from method style calls. if hashes.is_native_only() { @@ -664,7 +659,7 @@ impl Engine { }; let orig_source = mem::replace(&mut global.source, source.clone()); - let global = &mut *RestoreOnDrop::lock(global, move |g| g.source = orig_source); + auto_restore!(global => move |g| g.source = orig_source); return if _is_method_call { // Method call of script function - map first argument to `this` @@ -684,9 +679,7 @@ impl Engine { backup.change_first_arg_to_copy(_args); } - let args = &mut *RestoreOnDrop::lock_if(swap, _args, move |a| { - backup.restore_first_arg(a) - }); + auto_restore!(args = _args; swap => move |a| backup.restore_first_arg(a)); let mut this = Dynamic::NULL; @@ -732,9 +725,7 @@ impl Engine { }) }); #[cfg(feature = "debugging")] - let global = &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| { - g.debugger_mut().reset_status(reset) - }); + auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset)); self.eval_expr(global, caches, scope, this_ptr, arg_expr) .map(|r| (r, arg_expr.start_position())) @@ -1370,9 +1361,7 @@ impl Engine { } } - let orig_level = global.level; - global.level += 1; - let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level); + auto_restore! { let orig_level = global.level; global.level += 1 } match func { #[cfg(not(feature = "no_function"))] @@ -1382,7 +1371,7 @@ impl Engine { let mut this = Dynamic::NULL; let orig_source = mem::replace(&mut global.source, module.id_raw().cloned()); - let global = &mut *RestoreOnDrop::lock(global, move |g| g.source = orig_source); + auto_restore!(global => move |g| g.source = orig_source); self.call_script_fn( global, caches, new_scope, &mut this, fn_def, &mut args, true, pos, @@ -1534,12 +1523,10 @@ impl Engine { get_builtin_binary_op_fn(op_token.clone(), operands[0], operands[1]) { // Built-in found - let orig_level = global.level; - global.level += 1; - let global = &*RestoreOnDrop::lock(global, move |g| g.level = orig_level); + auto_restore! { let orig_level = global.level; global.level += 1 } let context = if ctx { - Some((self, name.as_str(), None, global, pos).into()) + Some((self, name.as_str(), None, &*global, pos).into()) } else { None }; diff --git a/src/func/callable_function.rs b/src/func/callable_function.rs index d7ed45bf..e3cebc7a 100644 --- a/src/func/callable_function.rs +++ b/src/func/callable_function.rs @@ -136,7 +136,7 @@ impl CallableFunction { Self::Script(..) => false, } } - /// Is there a [`NativeCallContext`] parameter? + /// Is there a [`NativeCallContext`][crate::NativeCallContext] parameter? #[inline] #[must_use] pub fn has_context(&self) -> bool { diff --git a/src/func/func.rs b/src/func/func.rs index 97bcfb04..f3573894 100644 --- a/src/func/func.rs +++ b/src/func/func.rs @@ -12,7 +12,7 @@ use std::prelude::v1::*; /// Trait to create a Rust closure from a script. /// /// Not available under `no_function`. -pub trait Func { +pub trait Func { /// The closure's output type. type Output; @@ -91,14 +91,14 @@ macro_rules! def_anonymous_fn { impl<$($par: Variant + Clone,)* RET: Variant + Clone> Func<($($par,)*), RET> for Engine { #[cfg(feature = "sync")] - type Output = Box RhaiResultOf + Send + Sync>; + type Output = Box RhaiResultOf + Send + Sync>; #[cfg(not(feature = "sync"))] - type Output = Box RhaiResultOf>; + type Output = Box RhaiResultOf>; #[inline] fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output { let fn_name: SmartString = entry_point.into(); - Box::new(move |$($par),*| self.call_fn(&mut Scope::new(), &ast, &fn_name, ($($par,)*))) + Box::new(move |$($par,)*| self.call_fn(&mut Scope::new(), &ast, &fn_name, ($($par,)*))) } #[inline] diff --git a/src/func/native.rs b/src/func/native.rs index 103195b9..4774f4be 100644 --- a/src/func/native.rs +++ b/src/func/native.rs @@ -7,8 +7,8 @@ use crate::plugin::PluginFunction; use crate::tokenizer::{is_valid_function_name, Token, TokenizeState, NO_TOKEN}; use crate::types::dynamic::Variant; use crate::{ - calc_fn_hash, reify, Dynamic, Engine, EvalContext, FuncArgs, Position, RhaiResult, - RhaiResultOf, StaticVec, VarDefInfo, ERR, + calc_fn_hash, Dynamic, Engine, EvalContext, FuncArgs, Position, RhaiResult, RhaiResultOf, + StaticVec, VarDefInfo, ERR, }; use std::any::{type_name, TypeId}; #[cfg(feature = "no_std")] diff --git a/src/func/register.rs b/src/func/register.rs index 1459bf74..e8b99a31 100644 --- a/src/func/register.rs +++ b/src/func/register.rs @@ -9,7 +9,7 @@ use super::call::FnCallArgs; use super::callable_function::CallableFunction; use super::native::{SendSync, Shared}; use crate::types::dynamic::{DynamicWriteLock, Variant}; -use crate::{reify, Dynamic, Identifier, NativeCallContext, RhaiResultOf}; +use crate::{Dynamic, Identifier, NativeCallContext, RhaiResultOf}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ @@ -70,44 +70,61 @@ pub fn by_value(data: &mut Dynamic) -> T { /// /// # Type Parameters /// -/// * `ARGS` - a tuple containing parameter types, with `&mut T` represented by `Mut`. -/// * `NUM` - a constant generic containing the number of parameters, must be consistent with `ARGS`. -/// * `CTX` - a constant boolean generic indicating whether there is a `NativeCallContext` parameter. -/// * `RET` - return type of the function; if the function returns `Result`, it is the unwrapped inner value type. -/// * `FALL` - a constant boolean generic indicating whether the function is fallible (i.e. returns `Result>`). -pub trait RegisterNativeFunction { +/// * `A` - a tuple containing parameter types, with `&mut T` represented by `Mut`. +/// * `N` - a constant generic containing the number of parameters, must be consistent with `ARGS`. +/// * `X` - a constant boolean generic indicating whether there is a `NativeCallContext` parameter. +/// * `R` - return type of the function; if the function returns `Result`, it is the unwrapped inner value type. +/// * `F` - a constant boolean generic indicating whether the function is fallible (i.e. returns `Result>`). +pub trait RegisterNativeFunction< + A: 'static, + const N: usize, + const X: bool, + R: 'static, + const F: bool, +> +{ /// Convert this function into a [`CallableFunction`]. #[must_use] fn into_callable_function(self, name: Identifier, no_const: bool) -> CallableFunction; /// Get the type ID's of this function's parameters. #[must_use] - fn param_types() -> [TypeId; NUM]; + fn param_types() -> [TypeId; N]; /// Get the number of parameters for this function. #[inline(always)] #[must_use] fn num_params() -> usize { - NUM + N } /// Is there a [`NativeCallContext`] parameter for this function? + #[inline(always)] #[must_use] - fn has_context() -> bool; + fn has_context() -> bool { + X + } /// _(metadata)_ Get the type names of this function's parameters. /// Exported under the `metadata` feature only. #[cfg(feature = "metadata")] #[must_use] - fn param_names() -> [&'static str; NUM]; + fn param_names() -> [&'static str; N]; /// _(metadata)_ Get the type ID of this function's return value. /// Exported under the `metadata` feature only. #[cfg(feature = "metadata")] + #[inline(always)] #[must_use] - fn return_type() -> TypeId; + fn return_type() -> TypeId { + if F { + TypeId::of::>() + } else { + TypeId::of::() + } + } /// _(metadata)_ Get the type name of this function's return value. /// Exported under the `metadata` feature only. #[cfg(feature = "metadata")] #[inline(always)] #[must_use] fn return_type_name() -> &'static str { - type_name::() + type_name::() } } @@ -143,9 +160,7 @@ macro_rules! def_register { RET: Variant + Clone, > RegisterNativeFunction<($($mark,)*), $n, false, RET, false> for FN { #[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] } - #[inline(always)] fn has_context() -> bool { false } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] } - #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::() } #[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction { CallableFunction::$abi(Shared::new(move |_, args: &mut FnCallArgs| { // The arguments are assumed to be of the correct number and types! @@ -169,9 +184,7 @@ macro_rules! def_register { RET: Variant + Clone, > RegisterNativeFunction<($($mark,)*), $n, true, RET, false> for FN { #[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] } - #[inline(always)] fn has_context() -> bool { true } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] } - #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::() } #[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction { CallableFunction::$abi(Shared::new(move |ctx: Option, args: &mut FnCallArgs| { let ctx = ctx.unwrap(); @@ -197,9 +210,7 @@ macro_rules! def_register { RET: Variant + Clone > RegisterNativeFunction<($($mark,)*), $n, false, RET, true> for FN { #[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] } - #[inline(always)] fn has_context() -> bool { false } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] } - #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::>() } #[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction { CallableFunction::$abi(Shared::new(move |_, args: &mut FnCallArgs| { @@ -221,9 +232,7 @@ macro_rules! def_register { RET: Variant + Clone > RegisterNativeFunction<($($mark,)*), $n, true, RET, true> for FN { #[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] } - #[inline(always)] fn has_context() -> bool { true } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] } - #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::>() } #[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction { CallableFunction::$abi(Shared::new(move |ctx: Option, args: &mut FnCallArgs| { diff --git a/src/lib.rs b/src/lib.rs index 3f6e73ff..d1b4a30a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,11 @@ extern crate no_std_compat as std; use std::prelude::v1::*; // Internal modules +#[macro_use] +mod reify; +#[macro_use] +mod types; + mod api; mod ast; pub mod config; @@ -95,10 +100,8 @@ mod module; mod optimizer; pub mod packages; mod parser; -mod reify; mod tests; mod tokenizer; -mod types; /// Error encountered when parsing a script. type PERR = ParseErrorType; diff --git a/src/module/mod.rs b/src/module/mod.rs index 76f4ac91..05435d4d 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -1237,7 +1237,7 @@ impl Module { /// assert!(module.contains_fn(hash)); /// ``` #[inline(always)] - pub fn set_native_fn( + pub fn set_native_fn( &mut self, name: impl AsRef + Into, func: F, diff --git a/src/reify.rs b/src/reify.rs index c5e98bb3..90a21a4c 100644 --- a/src/reify.rs +++ b/src/reify.rs @@ -8,7 +8,6 @@ /// * `reify!(`_variable_ or _expression_`,|`_temp-variable_`: `_type_`|` _code_ `)` /// * `reify!(`_variable_ or _expression_ `=>` `Option<`_type_`>` `)` /// * `reify!(`_variable_ or _expression_ `=>` _type_ `)` -#[macro_export] macro_rules! reify { ($old:ident, |$new:ident : $t:ty| $code:expr, || $fallback:expr) => {{ #[allow(clippy::redundant_else)] diff --git a/src/types/custom_types.rs b/src/types/custom_types.rs index 460a4e94..cbed43a3 100644 --- a/src/types/custom_types.rs +++ b/src/types/custom_types.rs @@ -1,7 +1,7 @@ //! Collection of custom types. use crate::Identifier; -use std::{any::type_name, collections::BTreeMap, fmt}; +use std::{any::type_name, collections::BTreeMap}; /// _(internals)_ Information for a custom type. /// Exported under the `internals` feature only. @@ -13,18 +13,9 @@ pub struct CustomTypeInfo { /// _(internals)_ A collection of custom types. /// Exported under the `internals` feature only. -#[derive(Clone, Hash)] +#[derive(Debug, Clone, Hash)] pub struct CustomTypesCollection(BTreeMap); -impl fmt::Debug for CustomTypesCollection { - #[cold] - #[inline(never)] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("CustomTypesCollection ")?; - f.debug_map().entries(self.0.iter()).finish() - } -} - impl Default for CustomTypesCollection { #[inline(always)] fn default() -> Self { @@ -50,7 +41,7 @@ impl CustomTypesCollection { } /// Register a custom type. #[inline(always)] - pub fn add_type(&mut self, name: &str) { + pub fn add_type(&mut self, name: impl Into) { self.add_raw( type_name::(), CustomTypeInfo { diff --git a/src/types/dynamic.rs b/src/types/dynamic.rs index 2ff6c21e..7ac4281c 100644 --- a/src/types/dynamic.rs +++ b/src/types/dynamic.rs @@ -1,6 +1,6 @@ //! Helper module which defines the [`Dynamic`] data type. -use crate::{reify, ExclusiveRange, FnPtr, ImmutableString, InclusiveRange, INT}; +use crate::{ExclusiveRange, FnPtr, ImmutableString, InclusiveRange, INT}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ diff --git a/src/types/fn_ptr.rs b/src/types/fn_ptr.rs index 30454502..d3fe8698 100644 --- a/src/types/fn_ptr.rs +++ b/src/types/fn_ptr.rs @@ -4,8 +4,8 @@ use crate::eval::GlobalRuntimeState; use crate::tokenizer::is_valid_function_name; use crate::types::dynamic::Variant; use crate::{ - reify, Dynamic, Engine, FuncArgs, ImmutableString, NativeCallContext, Position, RhaiError, - RhaiResult, RhaiResultOf, StaticVec, AST, ERR, + Dynamic, Engine, FuncArgs, ImmutableString, NativeCallContext, Position, RhaiError, RhaiResult, + RhaiResultOf, StaticVec, AST, ERR, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; diff --git a/src/types/mod.rs b/src/types/mod.rs index 2a166886..8641bba8 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,5 +1,8 @@ //! Module defining Rhai data types. +#[macro_use] +pub mod restore; + pub mod bloom_filter; pub mod custom_types; pub mod dynamic; @@ -11,7 +14,6 @@ pub mod interner; pub mod parse_error; pub mod position; pub mod position_none; -pub mod restore; pub mod scope; pub mod variant; diff --git a/src/types/restore.rs b/src/types/restore.rs index 6d99848a..d22cc2f7 100644 --- a/src/types/restore.rs +++ b/src/types/restore.rs @@ -4,6 +4,36 @@ use std::ops::{Deref, DerefMut}; #[cfg(feature = "no_std")] use std::prelude::v1::*; +/// Automatically restore state at the end of the scope. +macro_rules! auto_restore { + (let $temp:ident = $var:ident . $prop:ident; $code:stmt) => { + auto_restore!(let $temp = $var.$prop; $code => move |v| v.$prop = $temp); + }; + (let $temp:ident = $var:ident . $prop:ident; $code:stmt => $restore:expr) => { + let $temp = $var.$prop; + $code + auto_restore!($var => $restore); + }; + ($var:ident => $restore: expr) => { + auto_restore!($var = $var => $restore); + }; + ($var:ident = $value:expr => $restore: expr) => { + let $var = &mut *crate::types::RestoreOnDrop::lock($value, $restore); + }; + ($var:ident; $guard:expr => $restore: expr) => { + auto_restore!($var = $var; $guard => $restore); + }; + ($var:ident = $value:expr; $guard:expr => $restore: expr) => { + let mut __rx__; + let $var = if $guard { + __rx__ = crate::types::RestoreOnDrop::lock($value, $restore); + &mut *__rx__ + } else { + &mut *$value + }; + }; +} + /// Run custom restoration logic upon the end of scope. #[must_use] pub struct RestoreOnDrop<'a, T: ?Sized, R: FnOnce(&mut T)> { @@ -12,19 +42,6 @@ pub struct RestoreOnDrop<'a, T: ?Sized, R: FnOnce(&mut T)> { } impl<'a, T: ?Sized, R: FnOnce(&mut T)> RestoreOnDrop<'a, T, R> { - /// Create a new [`RestoreOnDrop`] that locks a mutable reference and runs restoration logic at - /// the end of scope only when `need_restore` is `true`. - /// - /// Beware that the end of scope means the end of its lifetime, not necessarily waiting until - /// the current block scope is exited. - #[inline(always)] - pub fn lock_if(need_restore: bool, value: &'a mut T, restore: R) -> Self { - Self { - value, - restore: if need_restore { Some(restore) } else { None }, - } - } - /// Create a new [`RestoreOnDrop`] that locks a mutable reference and runs restoration logic at /// the end of scope. /// @@ -42,9 +59,7 @@ impl<'a, T: ?Sized, R: FnOnce(&mut T)> RestoreOnDrop<'a, T, R> { impl<'a, T: ?Sized, R: FnOnce(&mut T)> Drop for RestoreOnDrop<'a, T, R> { #[inline(always)] fn drop(&mut self) { - if let Some(restore) = self.restore.take() { - restore(self.value); - } + self.restore.take().unwrap()(self.value); } }