Allow closures in parse expressions.

This commit is contained in:
Stephen Chung 2022-12-06 21:41:38 +08:00
parent e2bd0705b1
commit 90998f4f14
3 changed files with 22 additions and 4 deletions

View File

@ -9,6 +9,7 @@ Bug fixes
* Integer numbers that are too large to deserialize into `INT` now fall back to `Decimal` or `FLOAT` instead of silently truncating. * Integer numbers that are too large to deserialize into `INT` now fall back to `Decimal` or `FLOAT` instead of silently truncating.
* Parsing deeply-nested closures (e.g. `||{||{||{||{||{||{||{...}}}}}}}`) no longer panics but will be confined to the nesting limit. * Parsing deeply-nested closures (e.g. `||{||{||{||{||{||{||{...}}}}}}}`) no longer panics but will be confined to the nesting limit.
* Closures containing a single expression are now allowed in `Engine::eval_expression` etc.
Breaking API changes Breaking API changes
-------------------- --------------------

View File

@ -3845,8 +3845,6 @@ impl Engine {
let mut functions = StraightHashMap::default(); let mut functions = StraightHashMap::default();
let options = self.options & !LangOptions::STMT_EXPR & !LangOptions::LOOP_EXPR; let options = self.options & !LangOptions::STMT_EXPR & !LangOptions::LOOP_EXPR;
#[cfg(not(feature = "no_function"))]
let options = options & !LangOptions::ANON_FN;
let mut settings = ParseSettings { let mut settings = ParseSettings {
level: 0, level: 0,
@ -3861,6 +3859,7 @@ impl Engine {
let expr = self.parse_expr(&mut input, state, &mut functions, settings)?; let expr = self.parse_expr(&mut input, state, &mut functions, settings)?;
#[cfg(feature = "no_function")]
assert!(functions.is_empty()); assert!(functions.is_empty());
match input.peek().expect(NEVER_ENDS) { match input.peek().expect(NEVER_ENDS) {
@ -3877,7 +3876,7 @@ impl Engine {
state.scope, state.scope,
statements, statements,
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
StaticVec::new_const(), functions.into_iter().map(|(.., v)| v).collect(),
_optimization_level, _optimization_level,
)); ));
@ -3885,7 +3884,7 @@ impl Engine {
return Ok(AST::new( return Ok(AST::new(
statements, statements,
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
crate::Module::new(), functions.into_iter().map(|(.., v)| v).collect(),
)); ));
} }

View File

@ -16,6 +16,24 @@ fn test_expressions() -> Result<(), Box<EvalAltResult>> {
engine.eval_expression_with_scope::<INT>(&mut scope, "if x > 0 { 42 } else { 123 }")?, engine.eval_expression_with_scope::<INT>(&mut scope, "if x > 0 { 42 } else { 123 }")?,
42 42
); );
#[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))]
#[cfg(not(feature = "no_function"))]
{
assert_eq!(
engine.eval_expression_with_scope::<INT>(
&mut scope,
"[1, 2, 3, 4].map(|x| x * x).reduce(|a, v| a + v, 0)"
)?,
30
);
assert!(engine
.eval_expression_with_scope::<INT>(
&mut scope,
"[1, 2, 3, 4].map(|x| { let r = 2; x * r }).reduce(|a, v| a + v, 0)"
)
.is_err());
}
assert!(engine assert!(engine
.eval_expression_with_scope::<INT>(&mut scope, "if x > 0 { let y = 42; y } else { 123 }") .eval_expression_with_scope::<INT>(&mut scope, "if x > 0 { let y = 42; y } else { 123 }")
.is_err()); .is_err());