Use matches! macro.
This commit is contained in:
parent
6e076c409d
commit
01cf777961
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user