diff --git a/kalk/src/integration_testing.rs b/kalk/src/integration_testing.rs index 7be5725..d4649a3 100644 --- a/kalk/src/integration_testing.rs +++ b/kalk/src/integration_testing.rs @@ -42,6 +42,7 @@ mod tests { } #[test_case("basics")] + #[test_case("comparisons")] #[test_case("comprehensions")] #[test_case("derivation")] #[test_case("functions")] diff --git a/kalk/src/kalk_value/mod.rs b/kalk/src/kalk_value/mod.rs index b714ebb..3d2bea8 100644 --- a/kalk/src/kalk_value/mod.rs +++ b/kalk/src/kalk_value/mod.rs @@ -928,6 +928,9 @@ impl KalkValue { && (imaginary.clone() - imaginary_rhs.clone()).abs() < ACCEPTABLE_COMPARISON_MARGIN, ), + (KalkValue::Boolean(boolean), KalkValue::Boolean(boolean_rhs)) => { + KalkValue::Boolean(boolean == boolean_rhs) + } (KalkValue::Matrix(rows), KalkValue::Matrix(rows_rhs)) => { let mut matrices_are_equal = true; for (row, row_rhs) in rows.iter().zip(rows_rhs) { @@ -969,6 +972,9 @@ impl KalkValue { || (imaginary.clone() - imaginary_rhs.clone()).abs() > ACCEPTABLE_COMPARISON_MARGIN, ), + (KalkValue::Boolean(boolean), KalkValue::Boolean(boolean_rhs)) => { + KalkValue::Boolean(boolean != boolean_rhs) + } (KalkValue::Vector(_), KalkValue::Vector(_)) | (KalkValue::Matrix(_), KalkValue::Matrix(_)) => { if let KalkValue::Boolean(boolean) = self.eq_without_unit(rhs) { @@ -1001,7 +1007,7 @@ impl KalkValue { match (self, rhs) { (KalkValue::Number(real, _, _), KalkValue::Number(real_rhs, _, _)) => { - KalkValue::Boolean(real.clone() - real_rhs.clone() < ACCEPTABLE_COMPARISON_MARGIN) + KalkValue::Boolean(real.clone() - real_rhs.clone() < -ACCEPTABLE_COMPARISON_MARGIN) } _ => KalkValue::nan(), } diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index 5444cce..e944a02 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -352,7 +352,7 @@ fn parse_or(context: &mut Context) -> Result { } fn parse_and(context: &mut Context) -> Result { - let left = parse_equality(context)?; + let left = parse_comparison(context)?; if match_token(context, TokenKind::And) { let op = advance(context).kind; @@ -364,7 +364,7 @@ fn parse_and(context: &mut Context) -> Result { Ok(left) } -fn parse_equality(context: &mut Context) -> Result { +fn parse_comparison(context: &mut Context) -> Result { let mut left = parse_to(context)?; // Equality check @@ -380,10 +380,36 @@ fn parse_equality(context: &mut Context) -> Result { let right = if op == TokenKind::Equals && match_token(context, TokenKind::OpenBrace) { parse_piecewise(context)? } else { - parse_to(context)? + parse_comparison(context)? }; - left = Expr::Binary(Box::new(left), op, Box::new(right)); + left = match right { + Expr::Binary( + inner_left, + inner_op + @ + (TokenKind::Equals + | TokenKind::NotEquals + | TokenKind::GreaterThan + | TokenKind::LessThan + | TokenKind::GreaterOrEquals + | TokenKind::LessOrEquals), + inner_right, + ) => Expr::Binary( + Box::new(Expr::Binary( + Box::new(left), + op, + Box::new(*inner_left.clone()), + )), + TokenKind::And, + Box::new(Expr::Binary( + Box::new(*inner_left), + inner_op, + Box::new(*inner_right), + )), + ), + _ => Expr::Binary(Box::new(left), op, Box::new(right)), + } } Ok(left) diff --git a/tests/comparisons.kalker b/tests/comparisons.kalker new file mode 100644 index 0000000..7ad0944 --- /dev/null +++ b/tests/comparisons.kalker @@ -0,0 +1,13 @@ +x = 2 +true = (1 = 1) +false = (1 != 1) + +(x > 2) = false and +(x < 2) = false and +(x = 2) = true and +(x >= 2) = true and +(x <= 2) = true and +(1 < x < 2) = false and +(x < 3 < 4) = true and +(1 > x > 2) = false and +(x > 3 > 4) = false \ No newline at end of file