From b00d635820ec67662c7ff87985c9e7cb6cb9ecb5 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Thu, 23 May 2024 12:29:56 -0400 Subject: [PATCH] Handle logical comparisons --- src/eval.rs | 12 ++++++++++++ src/parse.rs | 10 +++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/eval.rs b/src/eval.rs index 0ebfcb2..52fabae 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -105,9 +105,21 @@ impl ExprVisitor> for InterpreterRunner<'_> right: &Expr, ) -> Result { 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( diff --git a/src/parse.rs b/src/parse.rs index e5e3c56..63c3436 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -272,7 +272,7 @@ fn parse_expression>(iter: &mut Peekable) -> Result } fn parse_assignment>(iter: &mut Peekable) -> Result { - 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>(iter: &mut Peekable) -> Result } } +fn parse_or>(iter: &mut Peekable) -> Result { + parse_binary(iter, &[TokenKind::Or], parse_and) +} + +fn parse_and>(iter: &mut Peekable) -> Result { + parse_binary(iter, &[TokenKind::And], parse_equality) +} + fn parse_equality>(iter: &mut Peekable) -> Result { parse_binary( iter,