diff --git a/src/engine.rs b/src/engine.rs index 36d7fc71..f1d9eecd 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -153,8 +153,8 @@ impl Engine<'_> { ); // Evaluate + // Convert return statement to return value return match self.eval_stmt(&mut scope, &fn_def.body) { - // Convert return statement to return value Err(EvalAltResult::Return(x, _)) => Ok(x), other => other, }; @@ -985,10 +985,11 @@ impl Engine<'_> { Stmt::Expr(expr) => { let result = self.eval_expr(scope, expr)?; - Ok(match expr.as_ref() { + Ok(if !matches!(expr.as_ref(), Expr::Assignment(_, _, _)) { + result + } else { // If it is an assignment, erase the result at the root - Expr::Assignment(_, _, _) => ().into_dynamic(), - _ => result, + ().into_dynamic() }) } @@ -1032,9 +1033,9 @@ impl Engine<'_> { Ok(guard_val) => { if *guard_val { match self.eval_stmt(scope, body) { + Ok(_) => (), Err(EvalAltResult::LoopBreak) => return Ok(().into_dynamic()), Err(x) => return Err(x), - _ => (), } } else { return Ok(().into_dynamic()); @@ -1047,9 +1048,9 @@ impl Engine<'_> { // Loop statement Stmt::Loop(body) => loop { match self.eval_stmt(scope, body) { + Ok(_) => (), Err(EvalAltResult::LoopBreak) => return Ok(().into_dynamic()), Err(x) => return Err(x), - _ => (), } }, @@ -1066,9 +1067,9 @@ impl Engine<'_> { *scope.get_mut(name, idx) = a; match self.eval_stmt(scope, body) { + Ok(_) => (), Err(EvalAltResult::LoopBreak) => break, Err(x) => return Err(x), - _ => (), } } scope.pop(); diff --git a/src/optimize.rs b/src/optimize.rs index f2352afa..6013ea01 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -50,16 +50,15 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { let pos = expr.position(); let expr = optimize_expr(*expr, state); - match expr { - Expr::False(_) | Expr::True(_) => Stmt::Noop(stmt1.position()), - expr => { - let stmt = Stmt::Expr(Box::new(expr)); + if matches!(expr, Expr::False(_) | Expr::True(_)) { + Stmt::Noop(stmt1.position()) + } else { + let stmt = Stmt::Expr(Box::new(expr)); - if preserve_result { - Stmt::Block(vec![stmt, *stmt1], pos) - } else { - stmt - } + if preserve_result { + Stmt::Block(vec![stmt, *stmt1], pos) + } else { + stmt } } } @@ -136,10 +135,7 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { // Remove all raw expression statements that are pure except for the very last statement let last_stmt = if preserve_result { result.pop() } else { None }; - result.retain(|stmt| match stmt { - Stmt::Expr(expr) if expr.is_pure() => false, - _ => true, - }); + result.retain(|stmt| !matches!(stmt, Stmt::Expr(expr) if expr.is_pure())); if let Some(stmt) = last_stmt { result.push(stmt); @@ -154,7 +150,6 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { match expr { Stmt::Let(_, None, _) => removed = true, Stmt::Let(_, Some(val_expr), _) if val_expr.is_pure() => removed = true, - _ => { result.push(expr); break; @@ -402,10 +397,7 @@ pub(crate) fn optimize(statements: Vec, scope: &Scope) -> Vec { let last_stmt = result.pop(); // Remove all pure statements at top level - result.retain(|stmt| match stmt { - Stmt::Expr(expr) if expr.is_pure() => false, - _ => true, - }); + result.retain(|stmt| !matches!(stmt, Stmt::Expr(expr) if expr.is_pure())); if let Some(stmt) = last_stmt { result.push(stmt); // Add back the last statement diff --git a/src/parser.rs b/src/parser.rs index daebaf13..e1b8d9da 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -229,24 +229,15 @@ pub enum Stmt { impl Stmt { pub fn is_noop(&self) -> bool { - match self { - Stmt::Noop(_) => true, - _ => false, - } + matches!(self, Stmt::Noop(_)) } pub fn is_op(&self) -> bool { - match self { - Stmt::Noop(_) => false, - _ => true, - } + !matches!(self, Stmt::Noop(_)) } pub fn is_var(&self) -> bool { - match self { - Stmt::Let(_, _, _) => true, - _ => false, - } + matches!(self, Stmt::Let(_, _, _)) } pub fn position(&self) -> Position { @@ -334,7 +325,7 @@ impl Expr { match self { Expr::Array(expressions, _) => expressions.iter().all(Expr::is_pure), Expr::And(x, y) | Expr::Or(x, y) | Expr::Index(x, y, _) => x.is_pure() && y.is_pure(), - expr => expr.is_constant() || expr.is_variable(), + expr => expr.is_constant() || matches!(expr, Expr::Variable(_, _)), } } @@ -355,20 +346,6 @@ impl Expr { _ => false, } } - - pub fn is_variable(&self) -> bool { - match self { - Expr::Variable(_, _) => true, - _ => false, - } - } - - pub fn is_property(&self) -> bool { - match self { - Expr::Property(_, _) => true, - _ => false, - } - } } #[derive(Debug, PartialEq, Clone)] @@ -1629,13 +1606,13 @@ fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result { + Expr::Index(idx_lhs, _, _) if matches!(idx_lhs.as_ref(), &Expr::Variable(_, _)) => { assert!(is_top, "property expected but gets variable"); None } #[cfg(not(feature = "no_index"))] - Expr::Index(idx_lhs, _, _) if idx_lhs.is_property() => { + Expr::Index(idx_lhs, _, _) if matches!(idx_lhs.as_ref(), &Expr::Property(_, _)) => { assert!(!is_top, "variable expected but gets property"); None } @@ -1655,7 +1632,13 @@ fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result + if matches!(idx_lhs.as_ref(), &Expr::Variable(_, _)) && is_top => + { + valid_assignment_chain(dot_rhs, false) + } + #[cfg(not(feature = "no_index"))] + Expr::Index(idx_lhs, _, _) + if matches!(idx_lhs.as_ref(), &Expr::Property(_, _)) && !is_top => { valid_assignment_chain(dot_rhs, false) } @@ -1865,9 +1848,10 @@ fn parse_if<'a>(input: &mut Peekable>) -> Result { input.next(); - let else_body = match input.peek() { - Some(&(Token::If, _)) => parse_if(input)?, - _ => parse_block(input)?, + let else_body = if matches!(input.peek(), Some(&(Token::If, _))) { + parse_if(input)? + } else { + parse_block(input)? }; Ok(Stmt::IfElse( @@ -1934,25 +1918,24 @@ fn parse_var<'a>( None => return Err(ParseError::new(PERR::VarExpectsIdentifier, Position::eof())), }; - match input.peek() { - Some(&(Token::Equals, _)) => { - input.next(); - let init_value = parse_expr(input)?; + if matches!(input.peek(), Some(&(Token::Equals, _))) { + input.next(); + let init_value = parse_expr(input)?; - match var_type { - VariableType::Normal => Ok(Stmt::Let(name, Some(Box::new(init_value)), pos)), + match var_type { + VariableType::Normal => Ok(Stmt::Let(name, Some(Box::new(init_value)), pos)), - VariableType::Constant if init_value.is_constant() => { - Ok(Stmt::Const(name, Box::new(init_value), pos)) - } - // Constants require a constant expression - VariableType::Constant => Err(ParseError( - PERR::ForbiddenConstantExpr(name.to_string()), - init_value.position(), - )), + VariableType::Constant if init_value.is_constant() => { + Ok(Stmt::Const(name, Box::new(init_value), pos)) } + // Constants require a constant expression + VariableType::Constant => Err(ParseError( + PERR::ForbiddenConstantExpr(name.to_string()), + init_value.position(), + )), } - _ => Ok(Stmt::Let(name, None, pos)), + } else { + Ok(Stmt::Let(name, None, pos)) } } @@ -2072,11 +2055,10 @@ fn parse_fn<'a>(input: &mut Peekable>) -> Result { - input.next(); - } - _ => loop { + if matches!(input.peek(), Some(&(Token::RightParen, _))) { + input.next(); + } else { + loop { match input.next() { Some((Token::RightParen, _)) => break, Some((Token::Comma, _)) => (), @@ -2100,7 +2082,7 @@ fn parse_fn<'a>(input: &mut Peekable>) -> Result