Use macro auto_restore!.
This commit is contained in:
parent
58769dbb52
commit
de0707f64f
@ -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 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
|
Deprecated API's
|
||||||
----------------
|
----------------
|
||||||
@ -25,7 +26,7 @@ Speed improvements
|
|||||||
------------------
|
------------------
|
||||||
|
|
||||||
* The functions registration mechanism is revamped to take advantage of constant generics, among others.
|
* 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
|
Net features
|
||||||
------------
|
------------
|
||||||
|
@ -117,7 +117,7 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
|||||||
|
|
||||||
/// Register a custom function.
|
/// Register a custom function.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn with_fn<A, const N: usize, const C: bool, R: Variant + Clone, const L: bool>(
|
pub fn with_fn<A: 'static, const N: usize, const C: bool, R: Variant + Clone, const L: bool>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl AsRef<str> + Into<Identifier>,
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
method: impl RegisterNativeFunction<A, N, C, R, L>,
|
method: impl RegisterNativeFunction<A, N, C, R, L>,
|
||||||
|
@ -3,10 +3,8 @@
|
|||||||
|
|
||||||
use crate::eval::{Caches, GlobalRuntimeState};
|
use crate::eval::{Caches, GlobalRuntimeState};
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::types::RestoreOnDrop;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
reify, Dynamic, Engine, FuncArgs, Position, RhaiResult, RhaiResultOf, Scope, StaticVec, AST,
|
Dynamic, Engine, FuncArgs, Position, RhaiResult, RhaiResultOf, Scope, StaticVec, AST, ERR,
|
||||||
ERR,
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -241,9 +239,7 @@ impl Engine {
|
|||||||
|
|
||||||
let result = if options.eval_ast && !statements.is_empty() {
|
let result = if options.eval_ast && !statements.is_empty() {
|
||||||
let orig_scope_len = scope.len();
|
let orig_scope_len = scope.len();
|
||||||
let scope = &mut *RestoreOnDrop::lock_if(rewind_scope, scope, move |s| {
|
auto_restore!(scope; rewind_scope => move |s| { s.rewind(orig_scope_len); });
|
||||||
s.rewind(orig_scope_len);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.eval_global_statements(global, caches, scope, statements)
|
self.eval_global_statements(global, caches, scope, statements)
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,8 +7,8 @@ use crate::parser::ParseResult;
|
|||||||
use crate::tokenizer::{is_valid_identifier, Token, NO_TOKEN};
|
use crate::tokenizer::{is_valid_identifier, Token, NO_TOKEN};
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
reify, Dynamic, Engine, EvalContext, Identifier, ImmutableString, LexError, Position,
|
Dynamic, Engine, EvalContext, Identifier, ImmutableString, LexError, Position, RhaiResult,
|
||||||
RhaiResult, StaticVec,
|
StaticVec,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
@ -185,7 +185,7 @@ impl Engine {
|
|||||||
/// This method will be removed in the next major version.
|
/// This method will be removed in the next major version.
|
||||||
#[deprecated(since = "1.9.1", note = "use `register_fn` instead")]
|
#[deprecated(since = "1.9.1", note = "use `register_fn` instead")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_result_fn<A, const N: usize, const C: bool, R: Variant + Clone>(
|
pub fn register_result_fn<A: 'static, const N: usize, const C: bool, R: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl AsRef<str> + Into<Identifier>,
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
func: impl RegisterNativeFunction<A, N, C, R, true>,
|
func: impl RegisterNativeFunction<A, N, C, R, true>,
|
||||||
@ -514,7 +514,7 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
|||||||
/// This method will be removed in the next major version.
|
/// This method will be removed in the next major version.
|
||||||
#[deprecated(since = "1.9.1", note = "use `with_fn` instead")]
|
#[deprecated(since = "1.9.1", note = "use `with_fn` instead")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn with_result_fn<S, A, const N: usize, const C: bool, R, F>(
|
pub fn with_result_fn<S, A: 'static, const N: usize, const C: bool, R, F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: S,
|
name: S,
|
||||||
method: F,
|
method: F,
|
||||||
|
@ -5,7 +5,7 @@ use crate::func::native::locked_write;
|
|||||||
use crate::parser::ParseState;
|
use crate::parser::ParseState;
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
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")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
@ -57,7 +57,7 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn register_fn<
|
pub fn register_fn<
|
||||||
A,
|
A: 'static,
|
||||||
const N: usize,
|
const N: usize,
|
||||||
const C: bool,
|
const C: bool,
|
||||||
R: Variant + Clone,
|
R: Variant + Clone,
|
||||||
|
@ -6,7 +6,7 @@ use crate::ast::{ASTFlags, Expr, OpAssignment};
|
|||||||
use crate::config::hashing::SusLock;
|
use crate::config::hashing::SusLock;
|
||||||
use crate::engine::{FN_IDX_GET, FN_IDX_SET};
|
use crate::engine::{FN_IDX_GET, FN_IDX_SET};
|
||||||
use crate::tokenizer::NO_TOKEN;
|
use crate::tokenizer::NO_TOKEN;
|
||||||
use crate::types::{dynamic::Union, RestoreOnDrop};
|
use crate::types::dynamic::Union;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, Dynamic, Engine, FnArgsVec, Position, RhaiResult, RhaiResultOf, Scope, ERR,
|
calc_fn_hash, Dynamic, Engine, FnArgsVec, Position, RhaiResult, RhaiResultOf, Scope, ERR,
|
||||||
};
|
};
|
||||||
@ -68,9 +68,7 @@ impl Engine {
|
|||||||
idx: &mut Dynamic,
|
idx: &mut Dynamic,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> RhaiResultOf<Dynamic> {
|
) -> RhaiResultOf<Dynamic> {
|
||||||
let orig_level = global.level;
|
auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
global.level += 1;
|
|
||||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
|
||||||
|
|
||||||
let hash = hash_idx().0;
|
let hash = hash_idx().0;
|
||||||
let args = &mut [target, idx];
|
let args = &mut [target, idx];
|
||||||
@ -91,9 +89,7 @@ impl Engine {
|
|||||||
is_ref_mut: bool,
|
is_ref_mut: bool,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||||
let orig_level = global.level;
|
auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
global.level += 1;
|
|
||||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
|
||||||
|
|
||||||
let hash = hash_idx().1;
|
let hash = hash_idx().1;
|
||||||
let args = &mut [target, idx, new_val];
|
let args = &mut [target, idx, new_val];
|
||||||
@ -688,10 +684,7 @@ impl Engine {
|
|||||||
let reset =
|
let reset =
|
||||||
self.run_debugger_with_reset(global, caches, scope, this_ptr, rhs)?;
|
self.run_debugger_with_reset(global, caches, scope, this_ptr, rhs)?;
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let global =
|
auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset));
|
||||||
&mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
|
|
||||||
g.debugger_mut().reset_status(reset)
|
|
||||||
});
|
|
||||||
|
|
||||||
let crate::ast::FnCallExpr {
|
let crate::ast::FnCallExpr {
|
||||||
name, hashes, args, ..
|
name, hashes, args, ..
|
||||||
@ -699,8 +692,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Truncate the index values upon exit
|
// Truncate the index values upon exit
|
||||||
let offset = idx_values.len() - args.len();
|
let offset = idx_values.len() - args.len();
|
||||||
let idx_values =
|
auto_restore!(idx_values => move |v| v.truncate(offset));
|
||||||
&mut *RestoreOnDrop::lock(idx_values, move |v| v.truncate(offset));
|
|
||||||
|
|
||||||
let call_args = &mut idx_values[offset..];
|
let call_args = &mut idx_values[offset..];
|
||||||
let arg1_pos = args.get(0).map_or(Position::NONE, Expr::position);
|
let arg1_pos = args.get(0).map_or(Position::NONE, Expr::position);
|
||||||
@ -862,11 +854,7 @@ impl Engine {
|
|||||||
global, caches, scope, this_ptr, _node,
|
global, caches, scope, this_ptr, _node,
|
||||||
)?;
|
)?;
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let global = &mut *RestoreOnDrop::lock_if(
|
auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset));
|
||||||
reset.is_some(),
|
|
||||||
global,
|
|
||||||
move |g| g.debugger_mut().reset_status(reset),
|
|
||||||
);
|
|
||||||
|
|
||||||
let crate::ast::FnCallExpr {
|
let crate::ast::FnCallExpr {
|
||||||
name, hashes, args, ..
|
name, hashes, args, ..
|
||||||
@ -874,9 +862,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Truncate the index values upon exit
|
// Truncate the index values upon exit
|
||||||
let offset = idx_values.len() - args.len();
|
let offset = idx_values.len() - args.len();
|
||||||
let idx_values = &mut *RestoreOnDrop::lock(idx_values, move |v| {
|
auto_restore!(idx_values => move |v| v.truncate(offset));
|
||||||
v.truncate(offset)
|
|
||||||
});
|
|
||||||
|
|
||||||
let call_args = &mut idx_values[offset..];
|
let call_args = &mut idx_values[offset..];
|
||||||
let arg1_pos = args.get(0).map_or(Position::NONE, Expr::position);
|
let arg1_pos = args.get(0).map_or(Position::NONE, Expr::position);
|
||||||
@ -987,11 +973,7 @@ impl Engine {
|
|||||||
global, caches, scope, this_ptr, _node,
|
global, caches, scope, this_ptr, _node,
|
||||||
)?;
|
)?;
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let global = &mut *RestoreOnDrop::lock_if(
|
auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset));
|
||||||
reset.is_some(),
|
|
||||||
global,
|
|
||||||
move |g| g.debugger_mut().reset_status(reset),
|
|
||||||
);
|
|
||||||
|
|
||||||
let crate::ast::FnCallExpr {
|
let crate::ast::FnCallExpr {
|
||||||
name, hashes, args, ..
|
name, hashes, args, ..
|
||||||
@ -999,10 +981,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Truncate the index values upon exit
|
// Truncate the index values upon exit
|
||||||
let offset = idx_values.len() - args.len();
|
let offset = idx_values.len() - args.len();
|
||||||
let idx_values =
|
auto_restore!(idx_values => move |v| v.truncate(offset));
|
||||||
&mut *RestoreOnDrop::lock(idx_values, move |v| {
|
|
||||||
v.truncate(offset)
|
|
||||||
});
|
|
||||||
|
|
||||||
let call_args = &mut idx_values[offset..];
|
let call_args = &mut idx_values[offset..];
|
||||||
let pos1 = args.get(0).map_or(Position::NONE, Expr::position);
|
let pos1 = args.get(0).map_or(Position::NONE, Expr::position);
|
||||||
|
@ -234,10 +234,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
|
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let global =
|
auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset));
|
||||||
&mut *crate::types::RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
|
|
||||||
g.debugger_mut().reset_status(reset)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.track_operation(global, expr.position())?;
|
self.track_operation(global, expr.position())?;
|
||||||
|
|
||||||
@ -268,10 +265,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
|
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let global =
|
auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset));
|
||||||
&mut *crate::types::RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
|
|
||||||
g.debugger_mut().reset_status(reset)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.track_operation(global, expr.position())?;
|
self.track_operation(global, expr.position())?;
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ use crate::ast::{
|
|||||||
};
|
};
|
||||||
use crate::func::{get_builtin_op_assignment_fn, get_hasher};
|
use crate::func::{get_builtin_op_assignment_fn, get_hasher};
|
||||||
use crate::types::dynamic::{AccessMode, Union};
|
use crate::types::dynamic::{AccessMode, Union};
|
||||||
use crate::types::RestoreOnDrop;
|
|
||||||
use crate::{Dynamic, Engine, RhaiResult, RhaiResultOf, Scope, ERR, INT};
|
use crate::{Dynamic, Engine, RhaiResult, RhaiResultOf, Scope, ERR, INT};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -43,9 +42,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Restore scope at end of block if necessary
|
// Restore scope at end of block if necessary
|
||||||
let orig_scope_len = scope.len();
|
let orig_scope_len = scope.len();
|
||||||
let scope = &mut *RestoreOnDrop::lock_if(restore_orig_state, scope, move |s| {
|
auto_restore!(scope; restore_orig_state => move |s| { s.rewind(orig_scope_len); });
|
||||||
s.rewind(orig_scope_len);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Restore global state at end of block if necessary
|
// Restore global state at end of block if necessary
|
||||||
let orig_always_search_scope = global.always_search_scope;
|
let orig_always_search_scope = global.always_search_scope;
|
||||||
@ -56,7 +53,7 @@ impl Engine {
|
|||||||
global.scope_level += 1;
|
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;
|
g.scope_level -= 1;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -69,9 +66,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Pop new function resolution caches at end of block
|
// Pop new function resolution caches at end of block
|
||||||
let orig_fn_resolution_caches_len = caches.fn_resolution_caches_len();
|
let orig_fn_resolution_caches_len = caches.fn_resolution_caches_len();
|
||||||
let caches = &mut *RestoreOnDrop::lock(caches, move |c| {
|
auto_restore!(caches => move |c| c.rewind_fn_resolution_caches(orig_fn_resolution_caches_len));
|
||||||
c.rewind_fn_resolution_caches(orig_fn_resolution_caches_len)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Run the statements
|
// Run the statements
|
||||||
statements.iter().try_fold(Dynamic::UNIT, |_, stmt| {
|
statements.iter().try_fold(Dynamic::UNIT, |_, stmt| {
|
||||||
@ -147,13 +142,10 @@ impl Engine {
|
|||||||
{
|
{
|
||||||
// Built-in found
|
// Built-in found
|
||||||
let op = op_assign_token.literal_syntax();
|
let op = op_assign_token.literal_syntax();
|
||||||
|
auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
let orig_level = global.level;
|
|
||||||
global.level += 1;
|
|
||||||
let global = &*RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
|
||||||
|
|
||||||
let context = if ctx {
|
let context = if ctx {
|
||||||
Some((self, op, None, global, *op_pos).into())
|
Some((self, op, None, &*global, *op_pos).into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -212,9 +204,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, stmt)?;
|
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, stmt)?;
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let global = &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
|
auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset));
|
||||||
g.debugger_mut().reset_status(reset)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Coded this way for better branch prediction.
|
// Coded this way for better branch prediction.
|
||||||
// Popular branches are lifted out of the `match` statement into their own branches.
|
// 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
|
// Restore scope at end of statement
|
||||||
let orig_scope_len = scope.len();
|
let orig_scope_len = scope.len();
|
||||||
let scope = &mut *RestoreOnDrop::lock(scope, move |s| {
|
auto_restore!(scope => move |s| { s.rewind(orig_scope_len); });
|
||||||
s.rewind(orig_scope_len);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add the loop variables
|
// Add the loop variables
|
||||||
let counter_index = if counter.is_empty() {
|
let counter_index = if counter.is_empty() {
|
||||||
usize::MAX
|
usize::MAX
|
||||||
@ -657,10 +644,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Restore scope at end of block
|
// Restore scope at end of block
|
||||||
let orig_scope_len = scope.len();
|
let orig_scope_len = scope.len();
|
||||||
let scope =
|
auto_restore!(scope; !catch_var.is_empty() => move |s| { s.rewind(orig_scope_len); });
|
||||||
&mut *RestoreOnDrop::lock_if(!catch_var.is_empty(), scope, move |s| {
|
|
||||||
s.rewind(orig_scope_len);
|
|
||||||
});
|
|
||||||
|
|
||||||
if !catch_var.is_empty() {
|
if !catch_var.is_empty() {
|
||||||
scope.push(catch_var.name.clone(), err_value);
|
scope.push(catch_var.name.clone(), err_value);
|
||||||
|
@ -9,7 +9,6 @@ use crate::engine::{
|
|||||||
};
|
};
|
||||||
use crate::eval::{Caches, FnResolutionCacheEntry, GlobalRuntimeState};
|
use crate::eval::{Caches, FnResolutionCacheEntry, GlobalRuntimeState};
|
||||||
use crate::tokenizer::{is_valid_function_name, Token, NO_TOKEN};
|
use crate::tokenizer::{is_valid_function_name, Token, NO_TOKEN};
|
||||||
use crate::types::RestoreOnDrop;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString,
|
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString,
|
||||||
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, ERR,
|
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, ERR,
|
||||||
@ -381,9 +380,7 @@ impl Engine {
|
|||||||
// Clone the first argument
|
// Clone the first argument
|
||||||
backup.change_first_arg_to_copy(args);
|
backup.change_first_arg_to_copy(args);
|
||||||
}
|
}
|
||||||
|
auto_restore!(args; swap => move |a| backup.restore_first_arg(a));
|
||||||
let args =
|
|
||||||
&mut *RestoreOnDrop::lock_if(swap, args, move |a| backup.restore_first_arg(a));
|
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
if self.is_debugger_registered() {
|
if self.is_debugger_registered() {
|
||||||
@ -583,9 +580,7 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
ensure_no_data_race(fn_name, _args, is_ref_mut)?;
|
ensure_no_data_race(fn_name, _args, is_ref_mut)?;
|
||||||
|
|
||||||
let orig_level = global.level;
|
auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
global.level += 1;
|
|
||||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
|
||||||
|
|
||||||
// These may be redirected from method style calls.
|
// These may be redirected from method style calls.
|
||||||
if hashes.is_native_only() {
|
if hashes.is_native_only() {
|
||||||
@ -664,7 +659,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let orig_source = mem::replace(&mut global.source, source.clone());
|
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 {
|
return if _is_method_call {
|
||||||
// Method call of script function - map first argument to `this`
|
// Method call of script function - map first argument to `this`
|
||||||
@ -684,9 +679,7 @@ impl Engine {
|
|||||||
backup.change_first_arg_to_copy(_args);
|
backup.change_first_arg_to_copy(_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = &mut *RestoreOnDrop::lock_if(swap, _args, move |a| {
|
auto_restore!(args = _args; swap => move |a| backup.restore_first_arg(a));
|
||||||
backup.restore_first_arg(a)
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut this = Dynamic::NULL;
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
@ -732,9 +725,7 @@ impl Engine {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
let global = &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
|
auto_restore!(global; reset.is_some() => move |g| g.debugger_mut().reset_status(reset));
|
||||||
g.debugger_mut().reset_status(reset)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.eval_expr(global, caches, scope, this_ptr, arg_expr)
|
self.eval_expr(global, caches, scope, this_ptr, arg_expr)
|
||||||
.map(|r| (r, arg_expr.start_position()))
|
.map(|r| (r, arg_expr.start_position()))
|
||||||
@ -1370,9 +1361,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let orig_level = global.level;
|
auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
global.level += 1;
|
|
||||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
|
||||||
|
|
||||||
match func {
|
match func {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
@ -1382,7 +1371,7 @@ impl Engine {
|
|||||||
let mut this = Dynamic::NULL;
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
|
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(
|
self.call_script_fn(
|
||||||
global, caches, new_scope, &mut this, fn_def, &mut args, true, pos,
|
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])
|
get_builtin_binary_op_fn(op_token.clone(), operands[0], operands[1])
|
||||||
{
|
{
|
||||||
// Built-in found
|
// Built-in found
|
||||||
let orig_level = global.level;
|
auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
global.level += 1;
|
|
||||||
let global = &*RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
|
||||||
|
|
||||||
let context = if ctx {
|
let context = if ctx {
|
||||||
Some((self, name.as_str(), None, global, pos).into())
|
Some((self, name.as_str(), None, &*global, pos).into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -136,7 +136,7 @@ impl CallableFunction {
|
|||||||
Self::Script(..) => false,
|
Self::Script(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Is there a [`NativeCallContext`] parameter?
|
/// Is there a [`NativeCallContext`][crate::NativeCallContext] parameter?
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn has_context(&self) -> bool {
|
pub fn has_context(&self) -> bool {
|
||||||
|
@ -12,7 +12,7 @@ use std::prelude::v1::*;
|
|||||||
/// Trait to create a Rust closure from a script.
|
/// Trait to create a Rust closure from a script.
|
||||||
///
|
///
|
||||||
/// Not available under `no_function`.
|
/// Not available under `no_function`.
|
||||||
pub trait Func<ARGS, RET> {
|
pub trait Func<A, R> {
|
||||||
/// The closure's output type.
|
/// The closure's output type.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
@ -91,14 +91,14 @@ macro_rules! def_anonymous_fn {
|
|||||||
impl<$($par: Variant + Clone,)* RET: Variant + Clone> Func<($($par,)*), RET> for Engine
|
impl<$($par: Variant + Clone,)* RET: Variant + Clone> Func<($($par,)*), RET> for Engine
|
||||||
{
|
{
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
type Output = Box<dyn Fn($($par),*) -> RhaiResultOf<RET> + Send + Sync>;
|
type Output = Box<dyn Fn($($par,)*) -> RhaiResultOf<RET> + Send + Sync>;
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
type Output = Box<dyn Fn($($par),*) -> RhaiResultOf<RET>>;
|
type Output = Box<dyn Fn($($par,)*) -> RhaiResultOf<RET>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
||||||
let fn_name: SmartString = entry_point.into();
|
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]
|
#[inline]
|
||||||
|
@ -7,8 +7,8 @@ use crate::plugin::PluginFunction;
|
|||||||
use crate::tokenizer::{is_valid_function_name, Token, TokenizeState, NO_TOKEN};
|
use crate::tokenizer::{is_valid_function_name, Token, TokenizeState, NO_TOKEN};
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, reify, Dynamic, Engine, EvalContext, FuncArgs, Position, RhaiResult,
|
calc_fn_hash, Dynamic, Engine, EvalContext, FuncArgs, Position, RhaiResult, RhaiResultOf,
|
||||||
RhaiResultOf, StaticVec, VarDefInfo, ERR,
|
StaticVec, VarDefInfo, ERR,
|
||||||
};
|
};
|
||||||
use std::any::{type_name, TypeId};
|
use std::any::{type_name, TypeId};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
|
@ -9,7 +9,7 @@ use super::call::FnCallArgs;
|
|||||||
use super::callable_function::CallableFunction;
|
use super::callable_function::CallableFunction;
|
||||||
use super::native::{SendSync, Shared};
|
use super::native::{SendSync, Shared};
|
||||||
use crate::types::dynamic::{DynamicWriteLock, Variant};
|
use crate::types::dynamic::{DynamicWriteLock, Variant};
|
||||||
use crate::{reify, Dynamic, Identifier, NativeCallContext, RhaiResultOf};
|
use crate::{Dynamic, Identifier, NativeCallContext, RhaiResultOf};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
@ -70,44 +70,61 @@ pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
|
|||||||
///
|
///
|
||||||
/// # Type Parameters
|
/// # Type Parameters
|
||||||
///
|
///
|
||||||
/// * `ARGS` - a tuple containing parameter types, with `&mut T` represented by `Mut<T>`.
|
/// * `A` - a tuple containing parameter types, with `&mut T` represented by `Mut<T>`.
|
||||||
/// * `NUM` - a constant generic containing the number of parameters, must be consistent with `ARGS`.
|
/// * `N` - 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.
|
/// * `X` - 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.
|
/// * `R` - 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<T, Box<EvalAltResult>>`).
|
/// * `F` - a constant boolean generic indicating whether the function is fallible (i.e. returns `Result<T, Box<EvalAltResult>>`).
|
||||||
pub trait RegisterNativeFunction<ARGS, const NUM: usize, const CTX: bool, RET, const FALL: bool> {
|
pub trait RegisterNativeFunction<
|
||||||
|
A: 'static,
|
||||||
|
const N: usize,
|
||||||
|
const X: bool,
|
||||||
|
R: 'static,
|
||||||
|
const F: bool,
|
||||||
|
>
|
||||||
|
{
|
||||||
/// Convert this function into a [`CallableFunction`].
|
/// Convert this function into a [`CallableFunction`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn into_callable_function(self, name: Identifier, no_const: bool) -> CallableFunction;
|
fn into_callable_function(self, name: Identifier, no_const: bool) -> CallableFunction;
|
||||||
/// Get the type ID's of this function's parameters.
|
/// Get the type ID's of this function's parameters.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn param_types() -> [TypeId; NUM];
|
fn param_types() -> [TypeId; N];
|
||||||
/// Get the number of parameters for this function.
|
/// Get the number of parameters for this function.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn num_params() -> usize {
|
fn num_params() -> usize {
|
||||||
NUM
|
N
|
||||||
}
|
}
|
||||||
/// Is there a [`NativeCallContext`] parameter for this function?
|
/// Is there a [`NativeCallContext`] parameter for this function?
|
||||||
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn has_context() -> bool;
|
fn has_context() -> bool {
|
||||||
|
X
|
||||||
|
}
|
||||||
/// _(metadata)_ Get the type names of this function's parameters.
|
/// _(metadata)_ Get the type names of this function's parameters.
|
||||||
/// Exported under the `metadata` feature only.
|
/// Exported under the `metadata` feature only.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
#[must_use]
|
#[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.
|
/// _(metadata)_ Get the type ID of this function's return value.
|
||||||
/// Exported under the `metadata` feature only.
|
/// Exported under the `metadata` feature only.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn return_type() -> TypeId;
|
fn return_type() -> TypeId {
|
||||||
|
if F {
|
||||||
|
TypeId::of::<RhaiResultOf<R>>()
|
||||||
|
} else {
|
||||||
|
TypeId::of::<R>()
|
||||||
|
}
|
||||||
|
}
|
||||||
/// _(metadata)_ Get the type name of this function's return value.
|
/// _(metadata)_ Get the type name of this function's return value.
|
||||||
/// Exported under the `metadata` feature only.
|
/// Exported under the `metadata` feature only.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn return_type_name() -> &'static str {
|
fn return_type_name() -> &'static str {
|
||||||
type_name::<RET>()
|
type_name::<R>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,9 +160,7 @@ macro_rules! def_register {
|
|||||||
RET: Variant + Clone,
|
RET: Variant + Clone,
|
||||||
> RegisterNativeFunction<($($mark,)*), $n, false, RET, false> for FN {
|
> RegisterNativeFunction<($($mark,)*), $n, false, RET, false> for FN {
|
||||||
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
|
#[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 param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
|
||||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
|
|
||||||
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
||||||
CallableFunction::$abi(Shared::new(move |_, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Shared::new(move |_, args: &mut FnCallArgs| {
|
||||||
// The arguments are assumed to be of the correct number and types!
|
// The arguments are assumed to be of the correct number and types!
|
||||||
@ -169,9 +184,7 @@ macro_rules! def_register {
|
|||||||
RET: Variant + Clone,
|
RET: Variant + Clone,
|
||||||
> RegisterNativeFunction<($($mark,)*), $n, true, RET, false> for FN {
|
> RegisterNativeFunction<($($mark,)*), $n, true, RET, false> for FN {
|
||||||
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
|
#[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 param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
|
||||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
|
|
||||||
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
||||||
CallableFunction::$abi(Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
|
||||||
let ctx = ctx.unwrap();
|
let ctx = ctx.unwrap();
|
||||||
@ -197,9 +210,7 @@ macro_rules! def_register {
|
|||||||
RET: Variant + Clone
|
RET: Variant + Clone
|
||||||
> RegisterNativeFunction<($($mark,)*), $n, false, RET, true> for FN {
|
> RegisterNativeFunction<($($mark,)*), $n, false, RET, true> for FN {
|
||||||
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
|
#[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 param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
|
||||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
|
|
||||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::<RhaiResultOf<RET>>() }
|
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::<RhaiResultOf<RET>>() }
|
||||||
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
||||||
CallableFunction::$abi(Shared::new(move |_, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Shared::new(move |_, args: &mut FnCallArgs| {
|
||||||
@ -221,9 +232,7 @@ macro_rules! def_register {
|
|||||||
RET: Variant + Clone
|
RET: Variant + Clone
|
||||||
> RegisterNativeFunction<($($mark,)*), $n, true, RET, true> for FN {
|
> RegisterNativeFunction<($($mark,)*), $n, true, RET, true> for FN {
|
||||||
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
|
#[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 param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
|
||||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
|
|
||||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::<RhaiResultOf<RET>>() }
|
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::<RhaiResultOf<RET>>() }
|
||||||
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
|
||||||
CallableFunction::$abi(Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
|
||||||
|
@ -85,6 +85,11 @@ extern crate no_std_compat as std;
|
|||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
// Internal modules
|
// Internal modules
|
||||||
|
#[macro_use]
|
||||||
|
mod reify;
|
||||||
|
#[macro_use]
|
||||||
|
mod types;
|
||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
mod ast;
|
mod ast;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
@ -95,10 +100,8 @@ mod module;
|
|||||||
mod optimizer;
|
mod optimizer;
|
||||||
pub mod packages;
|
pub mod packages;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod reify;
|
|
||||||
mod tests;
|
mod tests;
|
||||||
mod tokenizer;
|
mod tokenizer;
|
||||||
mod types;
|
|
||||||
|
|
||||||
/// Error encountered when parsing a script.
|
/// Error encountered when parsing a script.
|
||||||
type PERR = ParseErrorType;
|
type PERR = ParseErrorType;
|
||||||
|
@ -1237,7 +1237,7 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash));
|
/// assert!(module.contains_fn(hash));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_native_fn<A, const N: usize, const C: bool, T, F>(
|
pub fn set_native_fn<A: 'static, const N: usize, const C: bool, T, F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl AsRef<str> + Into<Identifier>,
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
func: F,
|
func: F,
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
/// * `reify!(`_variable_ or _expression_`,|`_temp-variable_`: `_type_`|` _code_ `)`
|
/// * `reify!(`_variable_ or _expression_`,|`_temp-variable_`: `_type_`|` _code_ `)`
|
||||||
/// * `reify!(`_variable_ or _expression_ `=>` `Option<`_type_`>` `)`
|
/// * `reify!(`_variable_ or _expression_ `=>` `Option<`_type_`>` `)`
|
||||||
/// * `reify!(`_variable_ or _expression_ `=>` _type_ `)`
|
/// * `reify!(`_variable_ or _expression_ `=>` _type_ `)`
|
||||||
#[macro_export]
|
|
||||||
macro_rules! reify {
|
macro_rules! reify {
|
||||||
($old:ident, |$new:ident : $t:ty| $code:expr, || $fallback:expr) => {{
|
($old:ident, |$new:ident : $t:ty| $code:expr, || $fallback:expr) => {{
|
||||||
#[allow(clippy::redundant_else)]
|
#[allow(clippy::redundant_else)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Collection of custom types.
|
//! Collection of custom types.
|
||||||
|
|
||||||
use crate::Identifier;
|
use crate::Identifier;
|
||||||
use std::{any::type_name, collections::BTreeMap, fmt};
|
use std::{any::type_name, collections::BTreeMap};
|
||||||
|
|
||||||
/// _(internals)_ Information for a custom type.
|
/// _(internals)_ Information for a custom type.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
@ -13,18 +13,9 @@ pub struct CustomTypeInfo {
|
|||||||
|
|
||||||
/// _(internals)_ A collection of custom types.
|
/// _(internals)_ A collection of custom types.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
#[derive(Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct CustomTypesCollection(BTreeMap<Identifier, CustomTypeInfo>);
|
pub struct CustomTypesCollection(BTreeMap<Identifier, CustomTypeInfo>);
|
||||||
|
|
||||||
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 {
|
impl Default for CustomTypesCollection {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@ -50,7 +41,7 @@ impl CustomTypesCollection {
|
|||||||
}
|
}
|
||||||
/// Register a custom type.
|
/// Register a custom type.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn add_type<T>(&mut self, name: &str) {
|
pub fn add_type<T>(&mut self, name: impl Into<Identifier>) {
|
||||||
self.add_raw(
|
self.add_raw(
|
||||||
type_name::<T>(),
|
type_name::<T>(),
|
||||||
CustomTypeInfo {
|
CustomTypeInfo {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Helper module which defines the [`Dynamic`] data type.
|
//! 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")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -4,8 +4,8 @@ use crate::eval::GlobalRuntimeState;
|
|||||||
use crate::tokenizer::is_valid_function_name;
|
use crate::tokenizer::is_valid_function_name;
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
reify, Dynamic, Engine, FuncArgs, ImmutableString, NativeCallContext, Position, RhaiError,
|
Dynamic, Engine, FuncArgs, ImmutableString, NativeCallContext, Position, RhaiError, RhaiResult,
|
||||||
RhaiResult, RhaiResultOf, StaticVec, AST, ERR,
|
RhaiResultOf, StaticVec, AST, ERR,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
//! Module defining Rhai data types.
|
//! Module defining Rhai data types.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod restore;
|
||||||
|
|
||||||
pub mod bloom_filter;
|
pub mod bloom_filter;
|
||||||
pub mod custom_types;
|
pub mod custom_types;
|
||||||
pub mod dynamic;
|
pub mod dynamic;
|
||||||
@ -11,7 +14,6 @@ pub mod interner;
|
|||||||
pub mod parse_error;
|
pub mod parse_error;
|
||||||
pub mod position;
|
pub mod position;
|
||||||
pub mod position_none;
|
pub mod position_none;
|
||||||
pub mod restore;
|
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
pub mod variant;
|
pub mod variant;
|
||||||
|
|
||||||
|
@ -4,6 +4,36 @@ use std::ops::{Deref, DerefMut};
|
|||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
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.
|
/// Run custom restoration logic upon the end of scope.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct RestoreOnDrop<'a, T: ?Sized, R: FnOnce(&mut T)> {
|
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> {
|
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
|
/// Create a new [`RestoreOnDrop`] that locks a mutable reference and runs restoration logic at
|
||||||
/// the end of scope.
|
/// 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> {
|
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Drop for RestoreOnDrop<'a, T, R> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(restore) = self.restore.take() {
|
self.restore.take().unwrap()(self.value);
|
||||||
restore(self.value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user