Minor housekeeping.
This commit is contained in:
parent
2f5ce2fe5b
commit
73f10b8adc
@ -77,8 +77,8 @@ impl Engine {
|
|||||||
.into()
|
.into()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments
|
/// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments and the
|
||||||
/// and the following options:
|
/// following options:
|
||||||
///
|
///
|
||||||
/// * whether to evaluate the [`AST`] to load necessary modules before calling the function
|
/// * whether to evaluate the [`AST`] to load necessary modules before calling the function
|
||||||
/// * whether to rewind the [`Scope`] after the function call
|
/// * whether to rewind the [`Scope`] after the function call
|
||||||
@ -95,8 +95,8 @@ impl Engine {
|
|||||||
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
||||||
/// This is to avoid unnecessarily cloning the arguments.
|
/// This is to avoid unnecessarily cloning the arguments.
|
||||||
///
|
///
|
||||||
/// Do not use the arguments after this call. If they are needed afterwards,
|
/// Do not use the arguments after this call. If they are needed afterwards, clone them _before_
|
||||||
/// clone them _before_ calling this function.
|
/// calling this function.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -85,6 +85,7 @@ impl Expression<'_> {
|
|||||||
self.0.position()
|
self.0.position()
|
||||||
}
|
}
|
||||||
/// Get the value of this expression if it is a literal constant.
|
/// Get the value of this expression if it is a literal constant.
|
||||||
|
///
|
||||||
/// Supports [`INT`][crate::INT], [`FLOAT`][crate::FLOAT], `()`, `char`, `bool` and
|
/// Supports [`INT`][crate::INT], [`FLOAT`][crate::FLOAT], `()`, `char`, `bool` and
|
||||||
/// [`ImmutableString`][crate::ImmutableString].
|
/// [`ImmutableString`][crate::ImmutableString].
|
||||||
///
|
///
|
||||||
|
@ -34,8 +34,9 @@ impl Engine {
|
|||||||
/// ## Constants Propagation
|
/// ## Constants Propagation
|
||||||
///
|
///
|
||||||
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
||||||
/// the scope are propagated throughout the script _including_ functions. This allows functions
|
/// the scope are propagated throughout the script _including_ functions.
|
||||||
/// to be optimized based on dynamic global constants.
|
///
|
||||||
|
/// This allows functions to be optimized based on dynamic global constants.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -72,8 +72,9 @@ impl Engine {
|
|||||||
/// ## Constants Propagation
|
/// ## Constants Propagation
|
||||||
///
|
///
|
||||||
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
||||||
/// the scope are propagated throughout the script _including_ functions. This allows functions
|
/// the scope are propagated throughout the script _including_ functions.
|
||||||
/// to be optimized based on dynamic global constants.
|
///
|
||||||
|
/// This allows functions to be optimized based on dynamic global constants.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -134,8 +135,9 @@ impl Engine {
|
|||||||
/// ## Constants Propagation
|
/// ## Constants Propagation
|
||||||
///
|
///
|
||||||
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
||||||
/// the scope are propagated throughout the script _including_ functions. This allows functions
|
/// the scope are propagated throughout the script _including_ functions.
|
||||||
/// to be optimized based on dynamic global constants.
|
///
|
||||||
|
/// This allows functions to be optimized based on dynamic global constants.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -176,8 +178,9 @@ impl Engine {
|
|||||||
/// ## Constants Propagation
|
/// ## Constants Propagation
|
||||||
///
|
///
|
||||||
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
/// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
|
||||||
/// the scope are propagated throughout the script _including_ functions. This allows functions
|
/// the scope are propagated throughout the script _including_ functions.
|
||||||
/// to be optimized based on dynamic global constants.
|
///
|
||||||
|
/// This allows functions to be optimized based on dynamic global constants.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn run_file_with_scope(
|
pub fn run_file_with_scope(
|
||||||
&self,
|
&self,
|
||||||
|
@ -82,21 +82,26 @@ impl Engine {
|
|||||||
pub const fn optimization_level(&self) -> crate::OptimizationLevel {
|
pub const fn optimization_level(&self) -> crate::OptimizationLevel {
|
||||||
self.optimization_level
|
self.optimization_level
|
||||||
}
|
}
|
||||||
/// Optimize the [`AST`][crate::AST] with constants defined in an external Scope. An optimized
|
/// Optimize the [`AST`][crate::AST] with constants defined in an external Scope.
|
||||||
/// copy of the [`AST`][crate::AST] is returned while the original [`AST`][crate::AST] is consumed.
|
/// An optimized copy of the [`AST`][crate::AST] is returned while the original [`AST`][crate::AST]
|
||||||
|
/// is consumed.
|
||||||
///
|
///
|
||||||
/// Not available under `no_optimize`.
|
/// Not available under `no_optimize`.
|
||||||
///
|
///
|
||||||
/// Although optimization is performed by default during compilation, sometimes it is necessary
|
/// Although optimization is performed by default during compilation, sometimes it is necessary
|
||||||
/// to _re_-optimize an [`AST`][crate::AST]. For example, when working with constants that are
|
/// to _re_-optimize an [`AST`][crate::AST].
|
||||||
/// passed in via an external scope, it will be more efficient to optimize the
|
///
|
||||||
/// [`AST`][crate::AST] once again to take advantage of the new constants.
|
/// For example, when working with constants that are passed in via an external scope, it will
|
||||||
|
/// be more efficient to optimize the [`AST`][crate::AST] once again to take advantage of the
|
||||||
|
/// new constants.
|
||||||
///
|
///
|
||||||
/// With this method, it is no longer necessary to recompile a large script. The script
|
/// With this method, it is no longer necessary to recompile a large script. The script
|
||||||
/// [`AST`][crate::AST] can be compiled just once. Before evaluation, constants are passed into
|
/// [`AST`][crate::AST] can be compiled just once.
|
||||||
/// the [`Engine`] via an external scope (i.e. with
|
///
|
||||||
/// [`Scope::push_constant`][crate::Scope::push_constant]). Then, the [`AST`][crate::AST] is
|
/// Before evaluation, constants are passed into the [`Engine`] via an external scope (i.e. with
|
||||||
/// cloned and the copy re-optimized before running.
|
/// [`Scope::push_constant`][crate::Scope::push_constant]).
|
||||||
|
///
|
||||||
|
/// Then, the [`AST`][crate::AST] is cloned and the copy re-optimized before running.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn optimize_ast(
|
pub fn optimize_ast(
|
||||||
@ -148,8 +153,8 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// The following will raise an error during parsing because the `if` keyword is disabled
|
/// The following will raise an error during parsing because the `if` keyword is disabled and is
|
||||||
/// and is recognized as a reserved symbol!
|
/// recognized as a reserved symbol!
|
||||||
///
|
///
|
||||||
/// ```rust,should_panic
|
/// ```rust,should_panic
|
||||||
/// # fn main() -> Result<(), rhai::ParseError> {
|
/// # fn main() -> Result<(), rhai::ParseError> {
|
||||||
|
@ -57,7 +57,7 @@ impl Engine {
|
|||||||
/// Is `if`-expression allowed?
|
/// Is `if`-expression allowed?
|
||||||
/// Default is `true`.
|
/// Default is `true`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn allow_if_expression(&self) -> bool {
|
pub const fn allow_if_expression(&self) -> bool {
|
||||||
self.options.allow_if_expr
|
self.options.allow_if_expr
|
||||||
}
|
}
|
||||||
/// Set whether `if`-expression is allowed.
|
/// Set whether `if`-expression is allowed.
|
||||||
@ -68,7 +68,7 @@ impl Engine {
|
|||||||
/// Is `switch` expression allowed?
|
/// Is `switch` expression allowed?
|
||||||
/// Default is `true`.
|
/// Default is `true`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn allow_switch_expression(&self) -> bool {
|
pub const fn allow_switch_expression(&self) -> bool {
|
||||||
self.options.allow_switch_expr
|
self.options.allow_switch_expr
|
||||||
}
|
}
|
||||||
/// Set whether `switch` expression is allowed.
|
/// Set whether `switch` expression is allowed.
|
||||||
@ -79,7 +79,7 @@ impl Engine {
|
|||||||
/// Is statement-expression allowed?
|
/// Is statement-expression allowed?
|
||||||
/// Default is `true`.
|
/// Default is `true`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn allow_statement_expression(&self) -> bool {
|
pub const fn allow_statement_expression(&self) -> bool {
|
||||||
self.options.allow_stmt_expr
|
self.options.allow_stmt_expr
|
||||||
}
|
}
|
||||||
/// Set whether statement-expression is allowed.
|
/// Set whether statement-expression is allowed.
|
||||||
@ -93,7 +93,7 @@ impl Engine {
|
|||||||
/// Not available under `no_function`.
|
/// Not available under `no_function`.
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn allow_anonymous_fn(&self) -> bool {
|
pub const fn allow_anonymous_fn(&self) -> bool {
|
||||||
self.options.allow_anonymous_fn
|
self.options.allow_anonymous_fn
|
||||||
}
|
}
|
||||||
/// Set whether anonymous function is allowed.
|
/// Set whether anonymous function is allowed.
|
||||||
@ -107,7 +107,7 @@ impl Engine {
|
|||||||
/// Is looping allowed?
|
/// Is looping allowed?
|
||||||
/// Default is `true`.
|
/// Default is `true`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn allow_looping(&self) -> bool {
|
pub const fn allow_looping(&self) -> bool {
|
||||||
self.options.allow_looping
|
self.options.allow_looping
|
||||||
}
|
}
|
||||||
/// Set whether looping is allowed.
|
/// Set whether looping is allowed.
|
||||||
@ -118,7 +118,7 @@ impl Engine {
|
|||||||
/// Is variables shadowing allowed?
|
/// Is variables shadowing allowed?
|
||||||
/// Default is `true`.
|
/// Default is `true`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn allow_shadowing(&self) -> bool {
|
pub const fn allow_shadowing(&self) -> bool {
|
||||||
self.options.allow_shadowing
|
self.options.allow_shadowing
|
||||||
}
|
}
|
||||||
/// Set whether variables shadowing is allowed.
|
/// Set whether variables shadowing is allowed.
|
||||||
@ -129,7 +129,7 @@ impl Engine {
|
|||||||
/// Is strict variables mode enabled?
|
/// Is strict variables mode enabled?
|
||||||
/// Default is `false`.
|
/// Default is `false`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn strict_variables(&self) -> bool {
|
pub const fn strict_variables(&self) -> bool {
|
||||||
self.options.strict_var
|
self.options.strict_var
|
||||||
}
|
}
|
||||||
/// Set whether strict variables mode is enabled.
|
/// Set whether strict variables mode is enabled.
|
||||||
@ -143,7 +143,7 @@ impl Engine {
|
|||||||
/// Not available under `no_object`.
|
/// Not available under `no_object`.
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn fail_on_invalid_map_property(&self) -> bool {
|
pub const fn fail_on_invalid_map_property(&self) -> bool {
|
||||||
self.options.fail_on_invalid_map_property
|
self.options.fail_on_invalid_map_property
|
||||||
}
|
}
|
||||||
/// Set whether to raise error if an object map property does not exist.
|
/// Set whether to raise error if an object map property does not exist.
|
||||||
|
@ -84,8 +84,8 @@ pub struct ScriptFnMetadata<'a> {
|
|||||||
///
|
///
|
||||||
/// Line doc-comments are kept in one string slice per line without the termination line-break.
|
/// Line doc-comments are kept in one string slice per line without the termination line-break.
|
||||||
///
|
///
|
||||||
/// Leading white-spaces are stripped, and each string slice always starts with the corresponding
|
/// Leading white-spaces are stripped, and each string slice always starts with the
|
||||||
/// doc-comment leader: `///` or `/**`.
|
/// corresponding doc-comment leader: `///` or `/**`.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
pub comments: Vec<&'a str>,
|
pub comments: Vec<&'a str>,
|
||||||
/// Function access mode.
|
/// Function access mode.
|
||||||
|
@ -621,8 +621,8 @@ impl Stmt {
|
|||||||
}
|
}
|
||||||
/// Does this statement's behavior depend on its containing block?
|
/// Does this statement's behavior depend on its containing block?
|
||||||
///
|
///
|
||||||
/// A statement that depends on its containing block behaves differently when promoted
|
/// A statement that depends on its containing block behaves differently when promoted to an
|
||||||
/// to an upper block.
|
/// upper block.
|
||||||
///
|
///
|
||||||
/// Currently only variable definitions (i.e. `let` and `const`), `import`/`export` statements,
|
/// Currently only variable definitions (i.e. `let` and `const`), `import`/`export` statements,
|
||||||
/// and `eval` calls (which may in turn call define variables) fall under this category.
|
/// and `eval` calls (which may in turn call define variables) fall under this category.
|
||||||
|
@ -187,9 +187,9 @@ impl Engine {
|
|||||||
self.call_indexer_set(
|
self.call_indexer_set(
|
||||||
global, state, lib, target, idx, new_val, is_ref_mut, level,
|
global, state, lib, target, idx, new_val, is_ref_mut, level,
|
||||||
)
|
)
|
||||||
.or_else(|idx_err| match *idx_err {
|
.or_else(|e| match *e {
|
||||||
ERR::ErrorIndexingType(..) => Ok((Dynamic::UNIT, false)),
|
ERR::ErrorIndexingType(..) => Ok((Dynamic::UNIT, false)),
|
||||||
_ => Err(idx_err),
|
_ => Err(e),
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,28 +333,25 @@ impl Engine {
|
|||||||
self.call_indexer_get(
|
self.call_indexer_get(
|
||||||
global, state, lib, target, &mut prop, level,
|
global, state, lib, target, &mut prop, level,
|
||||||
)
|
)
|
||||||
.map_err(
|
.map_err(|e| {
|
||||||
|idx_err| match *idx_err {
|
match *e {
|
||||||
ERR::ErrorIndexingType(..) => err,
|
ERR::ErrorIndexingType(..) => err,
|
||||||
_ => idx_err,
|
_ => e,
|
||||||
},
|
}
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.eval_op_assignment(
|
{
|
||||||
global,
|
let orig_val = &mut (&mut orig_val).into();
|
||||||
state,
|
|
||||||
lib,
|
self.eval_op_assignment(
|
||||||
op_info,
|
global, state, lib, op_info, op_pos, orig_val, root, new_val,
|
||||||
op_pos,
|
level,
|
||||||
&mut (&mut orig_val).into(),
|
)
|
||||||
root,
|
.map_err(|err| err.fill_position(new_pos))?;
|
||||||
new_val,
|
}
|
||||||
level,
|
|
||||||
)
|
|
||||||
.map_err(|err| err.fill_position(new_pos))?;
|
|
||||||
|
|
||||||
new_val = orig_val;
|
new_val = orig_val;
|
||||||
}
|
}
|
||||||
@ -373,12 +370,10 @@ impl Engine {
|
|||||||
self.call_indexer_set(
|
self.call_indexer_set(
|
||||||
global, state, lib, target, idx, new_val, is_ref_mut, level,
|
global, state, lib, target, idx, new_val, is_ref_mut, level,
|
||||||
)
|
)
|
||||||
.map_err(
|
.map_err(|e| match *e {
|
||||||
|idx_err| match *idx_err {
|
ERR::ErrorIndexingType(..) => err,
|
||||||
ERR::ErrorIndexingType(..) => err,
|
_ => e,
|
||||||
_ => idx_err,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
})
|
})
|
||||||
@ -403,11 +398,9 @@ impl Engine {
|
|||||||
self.call_indexer_get(
|
self.call_indexer_get(
|
||||||
global, state, lib, target, &mut prop, level,
|
global, state, lib, target, &mut prop, level,
|
||||||
)
|
)
|
||||||
.map_err(|idx_err| {
|
.map_err(|e| match *e {
|
||||||
match *idx_err {
|
ERR::ErrorIndexingType(..) => err,
|
||||||
ERR::ErrorIndexingType(..) => err,
|
_ => e,
|
||||||
_ => idx_err,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
@ -502,39 +495,28 @@ impl Engine {
|
|||||||
global, state, lib, target, &mut prop, level,
|
global, state, lib, target, &mut prop, level,
|
||||||
)
|
)
|
||||||
.map_err(
|
.map_err(
|
||||||
|idx_err| match *idx_err {
|
|e| match *e {
|
||||||
ERR::ErrorIndexingType(..) => err,
|
ERR::ErrorIndexingType(..) => err,
|
||||||
_ => idx_err,
|
_ => e,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let val = &mut val;
|
let val = &mut (&mut val).into();
|
||||||
|
|
||||||
let (result, may_be_changed) = self
|
let (result, may_be_changed) = self
|
||||||
.eval_dot_index_chain_helper(
|
.eval_dot_index_chain_helper(
|
||||||
global,
|
global, state, lib, this_ptr, val, root, rhs, &x.rhs,
|
||||||
state,
|
*term, idx_values, rhs_chain, level, new_val,
|
||||||
lib,
|
|
||||||
this_ptr,
|
|
||||||
&mut val.into(),
|
|
||||||
root,
|
|
||||||
rhs,
|
|
||||||
&x.rhs,
|
|
||||||
*term,
|
|
||||||
idx_values,
|
|
||||||
rhs_chain,
|
|
||||||
level,
|
|
||||||
new_val,
|
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*x_pos))?;
|
.map_err(|err| err.fill_position(*x_pos))?;
|
||||||
|
|
||||||
// Feed the value back via a setter just in case it has been updated
|
// Feed the value back via a setter just in case it has been updated
|
||||||
if may_be_changed {
|
if may_be_changed {
|
||||||
// Re-use args because the first &mut parameter will not be consumed
|
// Re-use args because the first &mut parameter will not be consumed
|
||||||
let mut arg_values = [target.as_mut(), val];
|
let mut arg_values = [target.as_mut(), val.as_mut()];
|
||||||
let args = &mut arg_values;
|
let args = &mut arg_values;
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
None, global, state, lib, setter, hash_set, args,
|
None, global, state, lib, setter, hash_set, args,
|
||||||
@ -550,13 +532,13 @@ impl Engine {
|
|||||||
global, state, lib, target, idx, new_val,
|
global, state, lib, target, idx, new_val,
|
||||||
is_ref_mut, level,
|
is_ref_mut, level,
|
||||||
)
|
)
|
||||||
.or_else(|idx_err| match *idx_err {
|
.or_else(|e| match *e {
|
||||||
// If there is no setter, no need to feed it
|
// If there is no setter, no need to feed it
|
||||||
// back because the property is read-only
|
// back because the property is read-only
|
||||||
ERR::ErrorIndexingType(..) => {
|
ERR::ErrorIndexingType(..) => {
|
||||||
Ok((Dynamic::UNIT, false))
|
Ok((Dynamic::UNIT, false))
|
||||||
}
|
}
|
||||||
_ => Err(idx_err),
|
_ => Err(e),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
@ -584,11 +566,11 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
global.debugger.reset_status(reset_debugger);
|
global.debugger.reset_status(reset_debugger);
|
||||||
|
|
||||||
let val = &mut result?.0;
|
let (val, _) = &mut result?;
|
||||||
let target = &mut val.into();
|
let val = &mut val.into();
|
||||||
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
global, state, lib, this_ptr, target, root, rhs, &x.rhs, *term,
|
global, state, lib, this_ptr, val, root, rhs, &x.rhs, *term,
|
||||||
idx_values, rhs_chain, level, new_val,
|
idx_values, rhs_chain, level, new_val,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(pos))
|
.map_err(|err| err.fill_position(pos))
|
||||||
|
@ -419,17 +419,13 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
let val_sizes = Self::calc_data_sizes(&value, true);
|
let delta = Self::calc_data_sizes(&value, true);
|
||||||
|
|
||||||
*map.get_mut(key).unwrap() = value;
|
*map.get_mut(key).unwrap() = value;
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if self.has_data_size_limit() {
|
if self.has_data_size_limit() {
|
||||||
sizes = (
|
sizes = (sizes.0 + delta.0, sizes.1 + delta.1, sizes.2 + delta.2);
|
||||||
sizes.0 + val_sizes.0,
|
|
||||||
sizes.1 + val_sizes.1,
|
|
||||||
sizes.2 + val_sizes.2,
|
|
||||||
);
|
|
||||||
self.raise_err_if_over_data_size_limit(sizes, value_expr.position())?;
|
self.raise_err_if_over_data_size_limit(sizes, value_expr.position())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,10 @@ pub type GlobalConstants =
|
|||||||
// # Implementation Notes
|
// # Implementation Notes
|
||||||
//
|
//
|
||||||
// This implementation for imported [modules][crate::Module] splits the module names from the shared
|
// This implementation for imported [modules][crate::Module] splits the module names from the shared
|
||||||
// modules to improve data locality. Most usage will be looking up a particular key from the list
|
// modules to improve data locality.
|
||||||
// and then getting the module that corresponds to that key.
|
//
|
||||||
|
// Most usage will be looking up a particular key from the list and then getting the module that
|
||||||
|
// corresponds to that key.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GlobalRuntimeState<'a> {
|
pub struct GlobalRuntimeState<'a> {
|
||||||
/// Stack of module names.
|
/// Stack of module names.
|
||||||
@ -103,7 +105,8 @@ impl GlobalRuntimeState<'_> {
|
|||||||
pub fn get_shared_import(&self, index: usize) -> Option<crate::Shared<crate::Module>> {
|
pub fn get_shared_import(&self, index: usize) -> Option<crate::Shared<crate::Module>> {
|
||||||
self.modules.get(index).cloned()
|
self.modules.get(index).cloned()
|
||||||
}
|
}
|
||||||
/// Get a mutable reference to the globally-imported [crate::Module][crate::Module] at a particular index.
|
/// Get a mutable reference to the globally-imported [crate::Module][crate::Module] at a
|
||||||
|
/// particular index.
|
||||||
///
|
///
|
||||||
/// Not available under `no_module`.
|
/// Not available under `no_module`.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -190,7 +193,8 @@ impl GlobalRuntimeState<'_> {
|
|||||||
) -> impl Iterator<Item = (&Identifier, &crate::Shared<crate::Module>)> {
|
) -> impl Iterator<Item = (&Identifier, &crate::Shared<crate::Module>)> {
|
||||||
self.keys.iter().zip(self.modules.iter())
|
self.keys.iter().zip(self.modules.iter())
|
||||||
}
|
}
|
||||||
/// Does the specified function hash key exist in the stack of globally-imported [modules][crate::Module]?
|
/// Does the specified function hash key exist in the stack of globally-imported
|
||||||
|
/// [modules][crate::Module]?
|
||||||
///
|
///
|
||||||
/// Not available under `no_module`.
|
/// Not available under `no_module`.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -200,7 +204,8 @@ impl GlobalRuntimeState<'_> {
|
|||||||
pub fn contains_qualified_fn(&self, hash: u64) -> bool {
|
pub fn contains_qualified_fn(&self, hash: u64) -> bool {
|
||||||
self.modules.iter().any(|m| m.contains_qualified_fn(hash))
|
self.modules.iter().any(|m| m.contains_qualified_fn(hash))
|
||||||
}
|
}
|
||||||
/// Get the specified function via its hash key from the stack of globally-imported [modules][crate::Module].
|
/// Get the specified function via its hash key from the stack of globally-imported
|
||||||
|
/// [modules][crate::Module].
|
||||||
///
|
///
|
||||||
/// Not available under `no_module`.
|
/// Not available under `no_module`.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
@ -257,16 +257,11 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
self.inc_operations(&mut global.num_operations, pos)?;
|
self.inc_operations(&mut global.num_operations, pos)?;
|
||||||
|
|
||||||
|
let root = (var_name, pos);
|
||||||
|
let lhs_ptr = &mut lhs_ptr;
|
||||||
|
|
||||||
self.eval_op_assignment(
|
self.eval_op_assignment(
|
||||||
global,
|
global, state, lib, *op_info, *op_pos, lhs_ptr, root, rhs_val, level,
|
||||||
state,
|
|
||||||
lib,
|
|
||||||
*op_info,
|
|
||||||
*op_pos,
|
|
||||||
&mut lhs_ptr,
|
|
||||||
(var_name, pos),
|
|
||||||
rhs_val,
|
|
||||||
level,
|
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(rhs.start_position()))
|
.map_err(|err| err.fill_position(rhs.start_position()))
|
||||||
.map(|_| Dynamic::UNIT)
|
.map(|_| Dynamic::UNIT)
|
||||||
@ -392,8 +387,8 @@ impl Engine {
|
|||||||
let hash = hasher.finish();
|
let hash = hasher.finish();
|
||||||
|
|
||||||
// First check hashes
|
// First check hashes
|
||||||
if let Some(t) = cases.get(&hash) {
|
if let Some(case_block) = cases.get(&hash) {
|
||||||
let cond_result = t
|
let cond_result = case_block
|
||||||
.condition
|
.condition
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|cond| {
|
.map(|cond| {
|
||||||
@ -410,7 +405,7 @@ impl Engine {
|
|||||||
.unwrap_or(Ok(true));
|
.unwrap_or(Ok(true));
|
||||||
|
|
||||||
match cond_result {
|
match cond_result {
|
||||||
Ok(true) => Ok(Some(&t.statements)),
|
Ok(true) => Ok(Some(&case_block.statements)),
|
||||||
Ok(false) => Ok(None),
|
Ok(false) => Ok(None),
|
||||||
_ => cond_result.map(|_| None),
|
_ => cond_result.map(|_| None),
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ use std::prelude::v1::*;
|
|||||||
|
|
||||||
/// Trait that parses arguments to a function call.
|
/// Trait that parses arguments to a function call.
|
||||||
///
|
///
|
||||||
/// Any data type can implement this trait in order to pass arguments to [`Engine::call_fn`][crate::Engine::call_fn].
|
/// Any data type can implement this trait in order to pass arguments to
|
||||||
|
/// [`Engine::call_fn`][crate::Engine::call_fn].
|
||||||
pub trait FuncArgs {
|
pub trait FuncArgs {
|
||||||
/// Parse function call arguments into a container.
|
/// Parse function call arguments into a container.
|
||||||
///
|
///
|
||||||
@ -65,8 +66,7 @@ impl<T: Variant + Clone> FuncArgs for Vec<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Macro to implement [`FuncArgs`] for tuples of standard types (each can be
|
/// Macro to implement [`FuncArgs`] for tuples of standard types (each can be converted into a [`Dynamic`]).
|
||||||
/// converted into a [`Dynamic`]).
|
|
||||||
macro_rules! impl_args {
|
macro_rules! impl_args {
|
||||||
($($p:ident),*) => {
|
($($p:ident),*) => {
|
||||||
impl<$($p: Variant + Clone),*> FuncArgs for ($($p,)*)
|
impl<$($p: Variant + Clone),*> FuncArgs for ($($p,)*)
|
||||||
|
@ -340,7 +340,8 @@ impl Engine {
|
|||||||
/// Function call arguments be _consumed_ when the function requires them to be passed by value.
|
/// Function call arguments be _consumed_ when the function requires them to be passed by value.
|
||||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
/// All function arguments not in the first position are always passed by value and thus consumed.
|
||||||
///
|
///
|
||||||
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
|
/// **DO NOT** reuse the argument values unless for the first `&mut` argument -
|
||||||
|
/// all others are silently replaced by `()`!
|
||||||
pub(crate) fn call_native_fn(
|
pub(crate) fn call_native_fn(
|
||||||
&self,
|
&self,
|
||||||
global: &mut GlobalRuntimeState,
|
global: &mut GlobalRuntimeState,
|
||||||
@ -591,10 +592,11 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// # WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
/// Function call arguments may be _consumed_ when the function requires them to be passed by
|
||||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
/// value. All function arguments not in the first position are always passed by value and thus consumed.
|
||||||
///
|
///
|
||||||
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
|
/// **DO NOT** reuse the argument values unless for the first `&mut` argument -
|
||||||
|
/// all others are silently replaced by `()`!
|
||||||
pub(crate) fn exec_fn_call(
|
pub(crate) fn exec_fn_call(
|
||||||
&self,
|
&self,
|
||||||
scope: Option<&mut Scope>,
|
scope: Option<&mut Scope>,
|
||||||
@ -1301,8 +1303,8 @@ impl Engine {
|
|||||||
// No arguments
|
// No arguments
|
||||||
} else {
|
} else {
|
||||||
// See if the first argument is a variable (not namespace-qualified).
|
// See if the first argument is a variable (not namespace-qualified).
|
||||||
// If so, convert to method-call style in order to leverage potential
|
// If so, convert to method-call style in order to leverage potential &mut first argument
|
||||||
// &mut first argument and avoid cloning the value
|
// and avoid cloning the value
|
||||||
if !args_expr.is_empty() && args_expr[0].is_variable_access(true) {
|
if !args_expr.is_empty() && args_expr[0].is_variable_access(true) {
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(scope, global, state, lib, this_ptr, &args_expr[0], level)?;
|
self.run_debugger(scope, global, state, lib, this_ptr, &args_expr[0], level)?;
|
||||||
|
@ -339,8 +339,8 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Does this [`Dynamic`] hold a variant data type
|
/// Does this [`Dynamic`] hold a variant data type instead of one of the supported system
|
||||||
/// instead of one of the supported system primitive types?
|
/// primitive types?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn is_variant(&self) -> bool {
|
pub const fn is_variant(&self) -> bool {
|
||||||
@ -360,8 +360,7 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
/// Is the value held by this [`Dynamic`] a particular type?
|
/// Is the value held by this [`Dynamic`] a particular type?
|
||||||
///
|
///
|
||||||
/// If the [`Dynamic`] is a shared variant checking is performed on
|
/// If the [`Dynamic`] is a shared variant checking is performed on top of its internal value.
|
||||||
/// top of its internal value.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is<T: Any + Clone>(&self) -> bool {
|
pub fn is<T: Any + Clone>(&self) -> bool {
|
||||||
@ -1072,11 +1071,14 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
/// Is this [`Dynamic`] read-only?
|
/// Is this [`Dynamic`] read-only?
|
||||||
///
|
///
|
||||||
/// Constant [`Dynamic`] values are read-only. If a [`&mut Dynamic`][Dynamic] to such a constant
|
/// Constant [`Dynamic`] values are read-only.
|
||||||
/// is passed to a Rust function, the function can use this information to return an error of
|
///
|
||||||
/// [`ErrorAssignmentToConstant`][crate::EvalAltResult::ErrorAssignmentToConstant]
|
/// If a [`&mut Dynamic`][Dynamic] to such a constant is passed to a Rust function, the function
|
||||||
/// if its value is going to be modified. This safe-guards constant values from being modified
|
/// can use this information to return an error of
|
||||||
/// from within Rust functions.
|
/// [`ErrorAssignmentToConstant`][crate::EvalAltResult::ErrorAssignmentToConstant] if its value
|
||||||
|
/// is going to be modified.
|
||||||
|
///
|
||||||
|
/// This safe-guards constant values from being modified from within Rust functions.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_read_only(&self) -> bool {
|
pub fn is_read_only(&self) -> bool {
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
@ -1138,15 +1140,16 @@ impl Dynamic {
|
|||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
///
|
///
|
||||||
/// Beware that you need to pass in an [`Array`][crate::Array] type for it to be recognized as an [`Array`][crate::Array].
|
/// Beware that you need to pass in an [`Array`][crate::Array] type for it to be recognized as
|
||||||
/// A [`Vec<T>`][Vec] does not get automatically converted to an [`Array`][crate::Array], but
|
/// an [`Array`][crate::Array]. A [`Vec<T>`][Vec] does not get automatically converted to an
|
||||||
/// will be a custom type instead (stored as a trait object). Use `Into<Dynamic>` to convert a
|
/// [`Array`][crate::Array], but will be a custom type instead (stored as a trait object). Use
|
||||||
/// [`Vec<T>`][Vec] into a [`Dynamic`] as an [`Array`][crate::Array] value.
|
/// `Into<Dynamic>` to convert a [`Vec<T>`][Vec] into a [`Dynamic`] as an
|
||||||
|
/// [`Array`][crate::Array] value.
|
||||||
///
|
///
|
||||||
/// Similarly, passing in a [`HashMap<String, T>`][std::collections::HashMap] or
|
/// Similarly, passing in a [`HashMap<String, T>`][std::collections::HashMap] or
|
||||||
/// [`BTreeMap<String, T>`][std::collections::BTreeMap] will not get a [`Map`][crate::Map]
|
/// [`BTreeMap<String, T>`][std::collections::BTreeMap] will not get a [`Map`][crate::Map] but a
|
||||||
/// but a custom type. Again, use `Into<Dynamic>` to get a [`Dynamic`] with a
|
/// custom type. Again, use `Into<Dynamic>` to get a [`Dynamic`] with a [`Map`][crate::Map]
|
||||||
/// [`Map`][crate::Map] value.
|
/// value.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user