Use matches! macro.

This commit is contained in:
Stephen Chung 2020-03-14 23:41:15 +08:00
parent 6e076c409d
commit 01cf777961
3 changed files with 54 additions and 79 deletions

View File

@ -153,8 +153,8 @@ impl Engine<'_> {
); );
// Evaluate // Evaluate
// Convert return statement to return value
return match self.eval_stmt(&mut scope, &fn_def.body) { return match self.eval_stmt(&mut scope, &fn_def.body) {
// Convert return statement to return value
Err(EvalAltResult::Return(x, _)) => Ok(x), Err(EvalAltResult::Return(x, _)) => Ok(x),
other => other, other => other,
}; };
@ -985,10 +985,11 @@ impl Engine<'_> {
Stmt::Expr(expr) => { Stmt::Expr(expr) => {
let result = self.eval_expr(scope, 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 // If it is an assignment, erase the result at the root
Expr::Assignment(_, _, _) => ().into_dynamic(), ().into_dynamic()
_ => result,
}) })
} }
@ -1032,9 +1033,9 @@ impl Engine<'_> {
Ok(guard_val) => { Ok(guard_val) => {
if *guard_val { if *guard_val {
match self.eval_stmt(scope, body) { match self.eval_stmt(scope, body) {
Ok(_) => (),
Err(EvalAltResult::LoopBreak) => return Ok(().into_dynamic()), Err(EvalAltResult::LoopBreak) => return Ok(().into_dynamic()),
Err(x) => return Err(x), Err(x) => return Err(x),
_ => (),
} }
} else { } else {
return Ok(().into_dynamic()); return Ok(().into_dynamic());
@ -1047,9 +1048,9 @@ impl Engine<'_> {
// Loop statement // Loop statement
Stmt::Loop(body) => loop { Stmt::Loop(body) => loop {
match self.eval_stmt(scope, body) { match self.eval_stmt(scope, body) {
Ok(_) => (),
Err(EvalAltResult::LoopBreak) => return Ok(().into_dynamic()), Err(EvalAltResult::LoopBreak) => return Ok(().into_dynamic()),
Err(x) => return Err(x), Err(x) => return Err(x),
_ => (),
} }
}, },
@ -1066,9 +1067,9 @@ impl Engine<'_> {
*scope.get_mut(name, idx) = a; *scope.get_mut(name, idx) = a;
match self.eval_stmt(scope, body) { match self.eval_stmt(scope, body) {
Ok(_) => (),
Err(EvalAltResult::LoopBreak) => break, Err(EvalAltResult::LoopBreak) => break,
Err(x) => return Err(x), Err(x) => return Err(x),
_ => (),
} }
} }
scope.pop(); scope.pop();

View File

@ -50,16 +50,15 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt {
let pos = expr.position(); let pos = expr.position();
let expr = optimize_expr(*expr, state); let expr = optimize_expr(*expr, state);
match expr { if matches!(expr, Expr::False(_) | Expr::True(_)) {
Expr::False(_) | Expr::True(_) => Stmt::Noop(stmt1.position()), Stmt::Noop(stmt1.position())
expr => { } else {
let stmt = Stmt::Expr(Box::new(expr)); let stmt = Stmt::Expr(Box::new(expr));
if preserve_result { if preserve_result {
Stmt::Block(vec![stmt, *stmt1], pos) Stmt::Block(vec![stmt, *stmt1], pos)
} else { } else {
stmt 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 // Remove all raw expression statements that are pure except for the very last statement
let last_stmt = if preserve_result { result.pop() } else { None }; let last_stmt = if preserve_result { result.pop() } else { None };
result.retain(|stmt| match stmt { result.retain(|stmt| !matches!(stmt, Stmt::Expr(expr) if expr.is_pure()));
Stmt::Expr(expr) if expr.is_pure() => false,
_ => true,
});
if let Some(stmt) = last_stmt { if let Some(stmt) = last_stmt {
result.push(stmt); result.push(stmt);
@ -154,7 +150,6 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt {
match expr { match expr {
Stmt::Let(_, None, _) => removed = true, Stmt::Let(_, None, _) => removed = true,
Stmt::Let(_, Some(val_expr), _) if val_expr.is_pure() => removed = true, Stmt::Let(_, Some(val_expr), _) if val_expr.is_pure() => removed = true,
_ => { _ => {
result.push(expr); result.push(expr);
break; break;
@ -402,10 +397,7 @@ pub(crate) fn optimize(statements: Vec<Stmt>, scope: &Scope) -> Vec<Stmt> {
let last_stmt = result.pop(); let last_stmt = result.pop();
// Remove all pure statements at top level // Remove all pure statements at top level
result.retain(|stmt| match stmt { result.retain(|stmt| !matches!(stmt, Stmt::Expr(expr) if expr.is_pure()));
Stmt::Expr(expr) if expr.is_pure() => false,
_ => true,
});
if let Some(stmt) = last_stmt { if let Some(stmt) = last_stmt {
result.push(stmt); // Add back the last statement result.push(stmt); // Add back the last statement

View File

@ -229,24 +229,15 @@ pub enum Stmt {
impl Stmt { impl Stmt {
pub fn is_noop(&self) -> bool { pub fn is_noop(&self) -> bool {
match self { matches!(self, Stmt::Noop(_))
Stmt::Noop(_) => true,
_ => false,
}
} }
pub fn is_op(&self) -> bool { pub fn is_op(&self) -> bool {
match self { !matches!(self, Stmt::Noop(_))
Stmt::Noop(_) => false,
_ => true,
}
} }
pub fn is_var(&self) -> bool { pub fn is_var(&self) -> bool {
match self { matches!(self, Stmt::Let(_, _, _))
Stmt::Let(_, _, _) => true,
_ => false,
}
} }
pub fn position(&self) -> Position { pub fn position(&self) -> Position {
@ -334,7 +325,7 @@ impl Expr {
match self { match self {
Expr::Array(expressions, _) => expressions.iter().all(Expr::is_pure), 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::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, _ => 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)] #[derive(Debug, PartialEq, Clone)]
@ -1629,13 +1606,13 @@ fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result<Expr, ParseEr
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Index(idx_lhs, _, _) if idx_lhs.is_variable() => { Expr::Index(idx_lhs, _, _) if matches!(idx_lhs.as_ref(), &Expr::Variable(_, _)) => {
assert!(is_top, "property expected but gets variable"); assert!(is_top, "property expected but gets variable");
None None
} }
#[cfg(not(feature = "no_index"))] #[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"); assert!(!is_top, "variable expected but gets property");
None None
} }
@ -1655,7 +1632,13 @@ fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result<Expr, ParseEr
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Index(idx_lhs, _, _) Expr::Index(idx_lhs, _, _)
if (idx_lhs.is_variable() && is_top) || (idx_lhs.is_property() && !is_top) => 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) valid_assignment_chain(dot_rhs, false)
} }
@ -1865,9 +1848,10 @@ fn parse_if<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, ParseEr
Some(&(Token::Else, _)) => { Some(&(Token::Else, _)) => {
input.next(); input.next();
let else_body = match input.peek() { let else_body = if matches!(input.peek(), Some(&(Token::If, _))) {
Some(&(Token::If, _)) => parse_if(input)?, parse_if(input)?
_ => parse_block(input)?, } else {
parse_block(input)?
}; };
Ok(Stmt::IfElse( Ok(Stmt::IfElse(
@ -1934,25 +1918,24 @@ fn parse_var<'a>(
None => return Err(ParseError::new(PERR::VarExpectsIdentifier, Position::eof())), None => return Err(ParseError::new(PERR::VarExpectsIdentifier, Position::eof())),
}; };
match input.peek() { if matches!(input.peek(), Some(&(Token::Equals, _))) {
Some(&(Token::Equals, _)) => { input.next();
input.next(); let init_value = parse_expr(input)?;
let init_value = parse_expr(input)?;
match var_type { match var_type {
VariableType::Normal => Ok(Stmt::Let(name, Some(Box::new(init_value)), pos)), VariableType::Normal => Ok(Stmt::Let(name, Some(Box::new(init_value)), pos)),
VariableType::Constant if init_value.is_constant() => { VariableType::Constant if init_value.is_constant() => {
Ok(Stmt::Const(name, Box::new(init_value), pos)) 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(),
)),
} }
// 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<TokenIterator<'a>>) -> Result<FnDef, ParseE
let mut params = Vec::new(); let mut params = Vec::new();
match input.peek() { if matches!(input.peek(), Some(&(Token::RightParen, _))) {
Some(&(Token::RightParen, _)) => { input.next();
input.next(); } else {
} loop {
_ => loop {
match input.next() { match input.next() {
Some((Token::RightParen, _)) => break, Some((Token::RightParen, _)) => break,
Some((Token::Comma, _)) => (), Some((Token::Comma, _)) => (),
@ -2100,7 +2082,7 @@ fn parse_fn<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<FnDef, ParseE
)) ))
} }
} }
}, }
} }
let body = parse_block(input)?; let body = parse_block(input)?;