Add comparison operators

This commit is contained in:
Richard Feldman 2019-06-23 19:09:07 -04:00
parent e7f792cf1d
commit 15a87b64a3
4 changed files with 71 additions and 2 deletions

View file

@ -259,6 +259,34 @@ fn eval_operator(left_expr: &Evaluated, op: Operator, right_expr: &Evaluated) ->
// Equals
(_, Equals, _) => eq(left_expr, right_expr),
// LessThan
(Int(left_num), LessThan, Int(right_num)) => bool_variant(left_num < right_num),
(Frac(left_num), LessThan, Frac(right_num)) => bool_variant(left_num < right_num),
(Int(_), LessThan, Frac(_)) => EvalError(TypeMismatch("tried check Frac < Int. Explicitly convert them to the same type first!".to_string())),
(Frac(_), LessThan, Int(_)) => EvalError(TypeMismatch("tried check Int < Frac. Explicitly convert them to the same type first!".to_string())),
(_, LessThan, _) => EvalError(TypeMismatch("tried to check if one non-number < another non-number".to_string())),
// LessThanOrEq
(Int(left_num), LessThanOrEq, Int(right_num)) => bool_variant(left_num <= right_num),
(Frac(left_num), LessThanOrEq, Frac(right_num)) => bool_variant(left_num <= right_num),
(Int(_), LessThanOrEq, Frac(_)) => EvalError(TypeMismatch("tried check Frac <= Int. Explicitly convert them to the same type first!".to_string())),
(Frac(_), LessThanOrEq, Int(_)) => EvalError(TypeMismatch("tried check Int <= Frac. Explicitly convert them to the same type first!".to_string())),
(_, LessThanOrEq, _) => EvalError(TypeMismatch("tried to check if one non-number <= another non-number".to_string())),
// GreaterThan
(Int(left_num), GreaterThan, Int(right_num)) => bool_variant(left_num > right_num),
(Frac(left_num), GreaterThan, Frac(right_num)) => bool_variant(left_num > right_num),
(Int(_), GreaterThan, Frac(_)) => EvalError(TypeMismatch("tried check Frac > Int. Explicitly convert them to the same type first!".to_string())),
(Frac(_), GreaterThan, Int(_)) => EvalError(TypeMismatch("tried check Int > Frac. Explicitly convert them to the same type first!".to_string())),
(_, GreaterThan, _) => EvalError(TypeMismatch("tried to check if one non-number > another non-number".to_string())),
// GreaterThanOrEq
(Int(left_num), GreaterThanOrEq, Int(right_num)) => bool_variant(left_num >= right_num),
(Frac(left_num), GreaterThanOrEq, Frac(right_num)) => bool_variant(left_num >= right_num),
(Int(_), GreaterThanOrEq, Frac(_)) => EvalError(TypeMismatch("tried check Frac >= Int. Explicitly convert them to the same type first!".to_string())),
(Frac(_), GreaterThanOrEq, Int(_)) => EvalError(TypeMismatch("tried check Int >= Frac. Explicitly convert them to the same type first!".to_string())),
(_, GreaterThanOrEq, _) => EvalError(TypeMismatch("tried to check if one non-number >= another non-number".to_string())),
// Plus
(Int(left_num), Plus, Int(right_num)) => Int(left_num + right_num),
(Frac(left_num), Plus, Frac(right_num)) => Frac(left_num + right_num),

View file

@ -44,5 +44,6 @@ pub enum Pattern {
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Operator {
Plus, Minus, Star, Slash, DoubleSlash, Equals,
Plus, Minus, Star, Slash, DoubleSlash,
Equals, LessThan, GreaterThan, LessThanOrEq, GreaterThanOrEq
}

View file

@ -339,11 +339,15 @@ where I: Stream<Item = char, Position = IndentablePosition>,
I::Error: ParseError<I::Item, I::Range, I::Position>
{
choice((
string("==").map(|_| Operator::Equals),
attempt(string("==")).map(|_| Operator::Equals),
attempt(string("<=")).map(|_| Operator::LessThanOrEq),
attempt(string(">=")).map(|_| Operator::GreaterThanOrEq),
char('+').map(|_| Operator::Plus),
char('-').map(|_| Operator::Minus),
char('*').map(|_| Operator::Star),
char('/').map(|_| Operator::Slash),
char('<').map(|_| Operator::LessThan),
char('>').map(|_| Operator::GreaterThan),
))
}

View file

@ -288,6 +288,42 @@ mod test_parse {
);
}
#[test]
fn comparison_operators() {
assert_eq!(
parse_standalone("x >= 0"),
Ok((Operator(
Box::new(Var("x".to_string())),
GreaterThanOrEq,
Box::new(Int(0))
), ""))
);
assert_eq!(
parse_standalone("x > 0"),
Ok((Operator(
Box::new(Var("x".to_string())),
GreaterThan,
Box::new(Int(0))
), ""))
);
assert_eq!(
parse_standalone("x <= 0"),
Ok((Operator(
Box::new(Var("x".to_string())),
LessThanOrEq,
Box::new(Int(0))
), ""))
);
assert_eq!(
parse_standalone("x < 0"),
Ok((Operator(
Box::new(Var("x".to_string())),
LessThan,
Box::new(Int(0))
), ""))
);
}
#[test]
fn single_operator() {