Add eval_expression_tree_raw.
This commit is contained in:
parent
b4dbc7619a
commit
dda7bc7b85
@ -13,6 +13,7 @@ Enhancements
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
* `switch` cases can now include multiple values separated by `|`.
|
* `switch` cases can now include multiple values separated by `|`.
|
||||||
|
* `EvalContext::eval_expression_tree_raw` and `Expression::eval_with_context_raw` are added to allow for not rewinding the `Scope` at the end of a statements block.
|
||||||
|
|
||||||
|
|
||||||
Version 1.8.0
|
Version 1.8.0
|
||||||
|
@ -185,6 +185,10 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// Not available under `no_function`.
|
/// Not available under `no_function`.
|
||||||
///
|
///
|
||||||
|
/// # WARNING - Unstable API
|
||||||
|
///
|
||||||
|
/// This API is volatile and may change in the future.
|
||||||
|
///
|
||||||
/// # WARNING - Low Level API
|
/// # WARNING - Low Level API
|
||||||
///
|
///
|
||||||
/// This function is _extremely_ low level.
|
/// This function is _extremely_ low level.
|
||||||
@ -202,6 +206,7 @@ impl Engine {
|
|||||||
/// Do not use the arguments after this call. If they are needed afterwards, clone them _before_
|
/// Do not use the arguments after this call. If they are needed afterwards, clone them _before_
|
||||||
/// calling this function.
|
/// calling this function.
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
|
#[deprecated = "This API is NOT deprecated, but it is considered volatile and may change in the future."]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn call_fn_raw_raw(
|
pub fn call_fn_raw_raw(
|
||||||
&self,
|
&self,
|
||||||
|
@ -74,6 +74,28 @@ impl Expression<'_> {
|
|||||||
pub fn eval_with_context(&self, context: &mut EvalContext) -> RhaiResult {
|
pub fn eval_with_context(&self, context: &mut EvalContext) -> RhaiResult {
|
||||||
context.eval_expression_tree(self)
|
context.eval_expression_tree(self)
|
||||||
}
|
}
|
||||||
|
/// Evaluate this [expression tree][Expression] within an [evaluation context][`EvalContext`].
|
||||||
|
///
|
||||||
|
/// The following option is available:
|
||||||
|
///
|
||||||
|
/// * whether to rewind the [`Scope`] after evaluation if the expression is a [`StmtBlock`][crate::ast::StmtBlock]
|
||||||
|
///
|
||||||
|
/// # WARNING - Unstable API
|
||||||
|
///
|
||||||
|
/// This API is volatile and may change in the future.
|
||||||
|
///
|
||||||
|
/// # WARNING - Low Level API
|
||||||
|
///
|
||||||
|
/// This function is _extremely_ low level. It evaluates an expression from an [`AST`][crate::AST].
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn eval_with_context_raw(
|
||||||
|
&self,
|
||||||
|
context: &mut EvalContext,
|
||||||
|
rewind_scope: bool,
|
||||||
|
) -> RhaiResult {
|
||||||
|
#[allow(deprecated)]
|
||||||
|
context.eval_expression_tree_raw(self, rewind_scope)
|
||||||
|
}
|
||||||
/// Get the value of this expression if it is a variable name or a string constant.
|
/// Get the value of this expression if it is a variable name or a string constant.
|
||||||
///
|
///
|
||||||
/// Returns [`None`] also if the constant is not of the specified type.
|
/// Returns [`None`] also if the constant is not of the specified type.
|
||||||
|
@ -150,6 +150,32 @@ impl<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, '
|
|||||||
#[cfg(not(feature = "no_custom_syntax"))]
|
#[cfg(not(feature = "no_custom_syntax"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval_expression_tree(&mut self, expr: &crate::Expression) -> crate::RhaiResult {
|
pub fn eval_expression_tree(&mut self, expr: &crate::Expression) -> crate::RhaiResult {
|
||||||
|
#[allow(deprecated)]
|
||||||
|
self.eval_expression_tree_raw(expr, true)
|
||||||
|
}
|
||||||
|
/// Evaluate an [expression tree][crate::Expression] within this [evaluation context][`EvalContext`].
|
||||||
|
///
|
||||||
|
/// The following option is available:
|
||||||
|
///
|
||||||
|
/// * whether to rewind the [`Scope`] after evaluation if the expression is a [`StmtBlock`][crate::ast::StmtBlock]
|
||||||
|
///
|
||||||
|
/// # WARNING - Unstable API
|
||||||
|
///
|
||||||
|
/// This API is volatile and may change in the future.
|
||||||
|
///
|
||||||
|
/// # WARNING - Low Level API
|
||||||
|
///
|
||||||
|
/// This function is _extremely_ low level. It evaluates an expression from an [`AST`][crate::AST].
|
||||||
|
#[cfg(not(feature = "no_custom_syntax"))]
|
||||||
|
#[deprecated = "This API is NOT deprecated, but it is considered volatile and may change in the future."]
|
||||||
|
#[inline]
|
||||||
|
pub fn eval_expression_tree_raw(
|
||||||
|
&mut self,
|
||||||
|
expr: &crate::Expression,
|
||||||
|
rewind_scope: bool,
|
||||||
|
) -> crate::RhaiResult {
|
||||||
|
let expr: &crate::ast::Expr = expr;
|
||||||
|
|
||||||
let mut new_caches = Caches::new();
|
let mut new_caches = Caches::new();
|
||||||
|
|
||||||
let caches = match self.caches.as_mut() {
|
let caches = match self.caches.as_mut() {
|
||||||
@ -157,14 +183,26 @@ impl<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, '
|
|||||||
None => &mut new_caches,
|
None => &mut new_caches,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.engine.eval_expr(
|
match expr {
|
||||||
self.scope,
|
crate::Expr::Stmt(statements) => self.engine.eval_stmt_block(
|
||||||
self.global,
|
self.scope,
|
||||||
caches,
|
self.global,
|
||||||
self.lib,
|
caches,
|
||||||
self.this_ptr,
|
self.lib,
|
||||||
expr,
|
self.this_ptr,
|
||||||
self.level,
|
&statements,
|
||||||
)
|
rewind_scope,
|
||||||
|
self.level,
|
||||||
|
),
|
||||||
|
_ => self.engine.eval_expr(
|
||||||
|
self.scope,
|
||||||
|
self.global,
|
||||||
|
caches,
|
||||||
|
self.lib,
|
||||||
|
self.this_ptr,
|
||||||
|
expr,
|
||||||
|
self.level,
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1236,7 +1236,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
|
|||||||
if x.scope_may_be_changed {
|
if x.scope_may_be_changed {
|
||||||
state.propagate_constants = false;
|
state.propagate_constants = false;
|
||||||
}
|
}
|
||||||
x.inputs.iter_mut().for_each(|expr| optimize_expr(expr, state, false));
|
// Do not optimize custom syntax expressions as you won't know how they would be called
|
||||||
}
|
}
|
||||||
|
|
||||||
// All other expressions - skip
|
// All other expressions - skip
|
||||||
|
@ -52,7 +52,13 @@ fn test_custom_syntax() -> Result<(), Box<EvalAltResult>> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.eval_expression_tree(stmt)?;
|
// Do not rewind if the variable is upper-case
|
||||||
|
if var_name.to_uppercase() == var_name {
|
||||||
|
context.eval_expression_tree_raw(stmt, false)?;
|
||||||
|
} else {
|
||||||
|
context.eval_expression_tree(stmt)?;
|
||||||
|
}
|
||||||
|
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
context
|
context
|
||||||
@ -125,6 +131,26 @@ fn test_custom_syntax() -> Result<(), Box<EvalAltResult>> {
|
|||||||
)?,
|
)?,
|
||||||
144
|
144
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(
|
||||||
|
"
|
||||||
|
let foo = 123;
|
||||||
|
exec [x<15] -> { let foo = x; x += 1; } while x < 42;
|
||||||
|
foo
|
||||||
|
"
|
||||||
|
)?,
|
||||||
|
123
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(
|
||||||
|
"
|
||||||
|
let foo = 123;
|
||||||
|
exec [ABC<15] -> { let foo = ABC; ABC += 1; } while ABC < 42;
|
||||||
|
foo
|
||||||
|
"
|
||||||
|
)?,
|
||||||
|
14
|
||||||
|
);
|
||||||
|
|
||||||
// The first symbol must be an identifier
|
// The first symbol must be an identifier
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
Loading…
Reference in New Issue
Block a user