From 32266d07f61b6888d439de6b2c7d9a5a617c49f2 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Fri, 24 May 2024 10:42:23 -0400 Subject: [PATCH] Allow eq eq comparison between strings --- src/eval.rs | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 6ec7c59..a39bfec 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,4 +1,7 @@ -use std::fmt::{self, Display, Formatter}; +use std::{ + fmt::{self, Display, Formatter}, + rc::Rc, +}; use crate::{ ast::{Expr, ExprVisitor, LiteralValue, Stmt, StmtVisitor}, @@ -120,7 +123,12 @@ impl ExprVisitor> for InterpreterRunner<'_> // 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::Plus => evaluate_arithmetic_or_string_operation( + (left_operand, right_operand), + operator, + |left, right| EvaluatedValue::Number(left + right), + |left, right| EvaluatedValue::String((left.to_string() + right.as_ref()).into()), + ), TokenKind::Minus => evaluate_binary_arithmetic( (left_operand, right_operand), @@ -164,16 +172,18 @@ impl ExprVisitor> for InterpreterRunner<'_> |left_value, right_value| EvaluatedValue::Boolean(left_value <= right_value), ), - TokenKind::EqualEqual => evaluate_binary_arithmetic( + TokenKind::EqualEqual => evaluate_arithmetic_or_string_operation( (left_operand, right_operand), operator, |left_value, right_value| EvaluatedValue::Boolean(left_value == right_value), + |left_value, right_value| EvaluatedValue::Boolean(left_value == right_value), ), - TokenKind::BangEqual => evaluate_binary_arithmetic( + TokenKind::BangEqual => evaluate_arithmetic_or_string_operation( (left_operand, right_operand), operator, |left_value, right_value| EvaluatedValue::Boolean(left_value != right_value), + |left_value, right_value| EvaluatedValue::Boolean(left_value != right_value), ), _ => unreachable!( @@ -287,18 +297,22 @@ fn convert_arithmetic_operands( } } -fn evaluate_addition( +fn evaluate_arithmetic_or_string_operation< + F: FnOnce(f64, f64) -> EvaluatedValue, + G: FnOnce(Rc, Rc) -> EvaluatedValue, +>( (left, right): (EvaluatedValue, EvaluatedValue), operator: &Token, + make_number_output: F, + make_string_output: G, ) -> Result { match (left, right) { (EvaluatedValue::Number(left_value), EvaluatedValue::Number(right_value)) => { - Ok(EvaluatedValue::Number(left_value + right_value)) + Ok(make_number_output(left_value, right_value)) } (EvaluatedValue::String(left_value), EvaluatedValue::String(right_value)) => { - let concatted = left_value.to_string() + right_value.as_ref(); - Ok(EvaluatedValue::String(concatted.into())) + Ok(make_string_output(left_value, right_value)) } // TODO: we could improve this error (and others) to include the types