Restore previous always_search when exiting block.

This commit is contained in:
Stephen Chung 2020-11-21 12:25:39 +08:00
parent 6069a4cf55
commit 17cd305af7
2 changed files with 35 additions and 8 deletions

View File

@ -1714,7 +1714,7 @@ impl Engine {
// Statement block // Statement block
Expr::Stmt(x, _) => { Expr::Stmt(x, _) => {
self.eval_statements(scope, mods, state, lib, this_ptr, x.as_ref(), level) self.eval_stmt_block(scope, mods, state, lib, this_ptr, x.as_ref(), level)
} }
// lhs[idx_expr] // lhs[idx_expr]
@ -1848,8 +1848,8 @@ impl Engine {
.map_err(|err| err.fill_position(expr.position())) .map_err(|err| err.fill_position(expr.position()))
} }
/// Evaluate a list of statements. /// Evaluate a statements block.
pub(crate) fn eval_statements<'a>( pub(crate) fn eval_stmt_block<'a>(
&self, &self,
scope: &mut Scope, scope: &mut Scope,
mods: &mut Imports, mods: &mut Imports,
@ -1859,6 +1859,7 @@ impl Engine {
statements: impl IntoIterator<Item = &'a Stmt>, statements: impl IntoIterator<Item = &'a Stmt>,
level: usize, level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
let prev_always_search = state.always_search;
let prev_scope_len = scope.len(); let prev_scope_len = scope.len();
let prev_mods_len = mods.len(); let prev_mods_len = mods.len();
state.scope_level += 1; state.scope_level += 1;
@ -1873,16 +1874,15 @@ impl Engine {
mods.truncate(prev_mods_len); mods.truncate(prev_mods_len);
state.scope_level -= 1; state.scope_level -= 1;
// The impact of an eval statement goes away at the end of a block // The impact of new local variables goes away at the end of a block
// because any new variables introduced will go out of scope // because any new variables introduced will go out of scope
state.always_search = false; state.always_search = prev_always_search;
result result
} }
/// Evaluate a statement. /// Evaluate a statement.
/// ///
///
/// # Safety /// # Safety
/// ///
/// This method uses some unsafe code, mainly for avoiding cloning of local variable names via /// This method uses some unsafe code, mainly for avoiding cloning of local variable names via
@ -2062,7 +2062,7 @@ impl Engine {
// Block scope // Block scope
Stmt::Block(statements, _) => { Stmt::Block(statements, _) => {
self.eval_statements(scope, mods, state, lib, this_ptr, statements, level) self.eval_stmt_block(scope, mods, state, lib, this_ptr, statements, level)
} }
// If statement // If statement

View File

@ -8,7 +8,7 @@ fn test_eval() -> Result<(), Box<EvalAltResult>> {
engine.eval::<INT>( engine.eval::<INT>(
r#" r#"
eval("40 + 2") eval("40 + 2")
"# "#
)?, )?,
42 42
); );
@ -16,6 +16,33 @@ fn test_eval() -> Result<(), Box<EvalAltResult>> {
Ok(()) Ok(())
} }
#[test]
fn test_eval_blocks() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert_eq!(
engine.eval::<INT>(
r#"
let x = 999;
eval("let x = x + 123");
let y = if x > 0 {
eval("let x = 42");
x
} else {
0
};
x + y
"#
)?,
1164
);
Ok(())
}
#[test] #[test]
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
fn test_eval_function() -> Result<(), Box<EvalAltResult>> { fn test_eval_function() -> Result<(), Box<EvalAltResult>> {