Handle logical comparisons

master
Nick Krichevsky 2024-05-23 12:29:56 -04:00
parent 6aa29e25f4
commit b00d635820
2 changed files with 21 additions and 1 deletions

View File

@ -105,9 +105,21 @@ impl ExprVisitor<Result<EvaluatedValue, ScriptError>> for InterpreterRunner<'_>
right: &Expr,
) -> Result<EvaluatedValue, ScriptError> {
let left_operand = self.visit_expr(left)?;
// These operators must be handled first to allow for short circuiting
match operator.kind() {
TokenKind::Or if left_operand.is_truthy() => return Ok(left_operand),
TokenKind::And if !left_operand.is_truthy() => return Ok(left_operand),
_ => {
// fall through, evaluate right operand before continuing
}
}
let right_operand = self.visit_expr(right)?;
match operator.kind() {
// Finish the short circuit; if we get to this point the result will always be right.
TokenKind::Or | TokenKind::And => Ok(right_operand),
TokenKind::Plus => evaluate_addition((left_operand, right_operand), operator),
TokenKind::Minus => evaluate_binary_arithmetic(

View File

@ -272,7 +272,7 @@ fn parse_expression<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result
}
fn parse_assignment<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Expr, ParseError> {
let expr = parse_equality(iter)?;
let expr = parse_or(iter)?;
match (match_token_kind!(iter, TokenKind::Equal), expr) {
(Err(_), expr) => Ok(expr),
@ -292,6 +292,14 @@ fn parse_assignment<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result
}
}
fn parse_or<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Expr, ParseError> {
parse_binary(iter, &[TokenKind::Or], parse_and)
}
fn parse_and<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Expr, ParseError> {
parse_binary(iter, &[TokenKind::And], parse_equality)
}
fn parse_equality<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Expr, ParseError> {
parse_binary(
iter,