Use eval_statements_block when at global.
This commit is contained in:
parent
f388d22c0f
commit
a76bed2f46
@ -1712,7 +1712,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Statement block
|
// Statement block
|
||||||
Expr::Stmt(x, _) => {
|
Expr::Stmt(x, _) => {
|
||||||
self.eval_stmt_block(scope, mods, state, lib, this_ptr, x.as_ref(), level)
|
self.eval_stmt_block(scope, mods, state, lib, this_ptr, x.as_ref(), true, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
// lhs[idx_expr]
|
// lhs[idx_expr]
|
||||||
@ -1856,45 +1856,49 @@ impl Engine {
|
|||||||
lib: &[&Module],
|
lib: &[&Module],
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
statements: impl IntoIterator<Item = &'a Stmt>,
|
statements: impl IntoIterator<Item = &'a Stmt>,
|
||||||
|
restore: bool,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut has_imports = false;
|
let mut _has_imports = false;
|
||||||
let prev_always_search = state.always_search;
|
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;
|
|
||||||
|
|
||||||
let result = statements
|
if restore {
|
||||||
.into_iter()
|
state.scope_level += 1;
|
||||||
.try_fold(Default::default(), |_, stmt| {
|
|
||||||
match stmt {
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Stmt::Import(_, _, _) => {
|
|
||||||
// When imports list is modified, clear the functions lookup cache
|
|
||||||
if has_imports {
|
|
||||||
state.functions_caches.last_mut().map(|c| c.clear());
|
|
||||||
} else {
|
|
||||||
state.functions_caches.push(Default::default());
|
|
||||||
}
|
|
||||||
has_imports = true;
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
self.eval_stmt(scope, mods, state, lib, this_ptr, stmt, level)
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.rewind(prev_scope_len);
|
|
||||||
if has_imports {
|
|
||||||
// If imports list is modified, pop the functions lookup cache
|
|
||||||
state.functions_caches.pop();
|
|
||||||
}
|
}
|
||||||
mods.truncate(prev_mods_len);
|
|
||||||
state.scope_level -= 1;
|
|
||||||
|
|
||||||
// The impact of new local variables goes away at the end of a block
|
let result = statements.into_iter().try_fold(Dynamic::UNIT, |_, stmt| {
|
||||||
// because any new variables introduced will go out of scope
|
#[cfg(not(feature = "no_module"))]
|
||||||
state.always_search = prev_always_search;
|
match stmt {
|
||||||
|
Stmt::Import(_, _, _) => {
|
||||||
|
// When imports list is modified, clear the functions lookup cache
|
||||||
|
if _has_imports {
|
||||||
|
state.functions_caches.last_mut().map(|c| c.clear());
|
||||||
|
} else if restore {
|
||||||
|
state.functions_caches.push(Default::default());
|
||||||
|
_has_imports = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.eval_stmt(scope, mods, state, lib, this_ptr, stmt, level)
|
||||||
|
});
|
||||||
|
|
||||||
|
if restore {
|
||||||
|
scope.rewind(prev_scope_len);
|
||||||
|
if _has_imports {
|
||||||
|
// If imports list is modified, pop the functions lookup cache
|
||||||
|
state.functions_caches.pop();
|
||||||
|
}
|
||||||
|
mods.truncate(prev_mods_len);
|
||||||
|
state.scope_level -= 1;
|
||||||
|
|
||||||
|
// The impact of new local variables goes away at the end of a block
|
||||||
|
// because any new variables introduced will go out of scope
|
||||||
|
state.always_search = prev_always_search;
|
||||||
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -2088,7 +2092,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Block scope
|
// Block scope
|
||||||
Stmt::Block(statements, _) => {
|
Stmt::Block(statements, _) => {
|
||||||
self.eval_stmt_block(scope, mods, state, lib, this_ptr, statements, level)
|
self.eval_stmt_block(scope, mods, state, lib, this_ptr, statements, true, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If statement
|
// If statement
|
||||||
|
@ -1533,7 +1533,9 @@ impl Engine {
|
|||||||
resolver: ast.resolver(),
|
resolver: ast.resolver(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
self.eval_statements_raw(scope, mods, state, ast.statements(), &[ast.lib()], level)
|
let statements = ast.statements();
|
||||||
|
let lib = &[ast.lib()];
|
||||||
|
self.eval_global_statements(scope, mods, state, statements, lib, level)
|
||||||
}
|
}
|
||||||
/// Evaluate a file, but throw away the result and only return error (if any).
|
/// Evaluate a file, but throw away the result and only return error (if any).
|
||||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||||
@ -1602,7 +1604,9 @@ impl Engine {
|
|||||||
resolver: ast.resolver(),
|
resolver: ast.resolver(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
self.eval_statements_raw(scope, mods, state, ast.statements(), &[ast.lib()], 0)?;
|
let statements = ast.statements();
|
||||||
|
let lib = &[ast.lib()];
|
||||||
|
self.eval_global_statements(scope, mods, state, statements, lib, 0)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
/// Call a script function defined in an [`AST`] with multiple arguments.
|
/// Call a script function defined in an [`AST`] with multiple arguments.
|
||||||
|
@ -768,10 +768,10 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a list of statements with an empty state and no `this` pointer.
|
/// Evaluate a list of statements with no `this` pointer.
|
||||||
/// This is commonly used to evaluate a list of statements in an [`AST`] or a script function body.
|
/// This is commonly used to evaluate a list of statements in an [`AST`] or a script function body.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn eval_statements_raw<'a>(
|
pub(crate) fn eval_global_statements<'a>(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
mods: &mut Imports,
|
mods: &mut Imports,
|
||||||
@ -780,11 +780,7 @@ impl Engine {
|
|||||||
lib: &[&Module],
|
lib: &[&Module],
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
statements
|
self.eval_stmt_block(scope, mods, state, lib, &mut None, statements, false, level)
|
||||||
.into_iter()
|
|
||||||
.try_fold(Dynamic::UNIT, |_, stmt| {
|
|
||||||
self.eval_stmt(scope, mods, state, lib, &mut None, stmt, level)
|
|
||||||
})
|
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
EvalAltResult::Return(out, _) => Ok(out),
|
EvalAltResult::Return(out, _) => Ok(out),
|
||||||
EvalAltResult::LoopBreak(_, _) => {
|
EvalAltResult::LoopBreak(_, _) => {
|
||||||
@ -826,14 +822,14 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the AST
|
// Evaluate the AST
|
||||||
let mut new_state = State {
|
let new_state = &mut State {
|
||||||
source: state.source.clone(),
|
source: state.source.clone(),
|
||||||
operations: state.operations,
|
operations: state.operations,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
self.eval_statements_raw(scope, mods, &mut new_state, ast.statements(), lib, level);
|
self.eval_global_statements(scope, mods, new_state, ast.statements(), lib, level);
|
||||||
|
|
||||||
state.operations = new_state.operations;
|
state.operations = new_state.operations;
|
||||||
result
|
result
|
||||||
|
@ -4,14 +4,7 @@ use rhai::{Engine, EvalAltResult, LexError, ParseErrorType, RegisterFn, Scope, I
|
|||||||
fn test_eval() -> Result<(), Box<EvalAltResult>> {
|
fn test_eval() -> Result<(), Box<EvalAltResult>> {
|
||||||
let engine = Engine::new();
|
let engine = Engine::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(engine.eval::<INT>(r#"eval("40 + 2")"#)?, 42);
|
||||||
engine.eval::<INT>(
|
|
||||||
r#"
|
|
||||||
eval("40 + 2")
|
|
||||||
"#
|
|
||||||
)?,
|
|
||||||
42
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -62,7 +55,7 @@ fn test_eval_function() -> Result<(), Box<EvalAltResult>> {
|
|||||||
script += "x + y";
|
script += "x + y";
|
||||||
|
|
||||||
eval(script) + x + y
|
eval(script) + x + y
|
||||||
"#
|
"#
|
||||||
)?,
|
)?,
|
||||||
84
|
84
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user