implement > < >= <=

This commit is contained in:
ConnorSkees 2020-03-30 10:42:13 -04:00
parent 211a57ebdb
commit 2ce639e9be
3 changed files with 126 additions and 2 deletions

View File

@ -1,10 +1,11 @@
use std::fmt::{self, Display, Write};
use std::iter::Iterator;
use std::cmp::Ordering;
use crate::color::Color;
use crate::common::{Brackets, ListSeparator, Op, QuoteKind};
use crate::error::SassResult;
use crate::unit::Unit;
use crate::unit::{Unit, UNIT_CONVERSION_TABLE};
pub(crate) use number::Number;
mod number;
@ -183,7 +184,22 @@ impl Value {
Op::Mul => *lhs * *rhs,
Op::Div => *lhs / *rhs,
Op::Rem => *lhs % *rhs,
_ => Ok(Self::BinaryOp(lhs, op, rhs)),
Op::GreaterThan => match lhs.cmp(&rhs, op)? {
Ordering::Greater => Ok(Self::True),
Ordering::Less | Ordering::Equal=> Ok(Self::False),
},
Op::GreaterThanEqual => match lhs.cmp(&rhs, op)? {
Ordering::Greater | Ordering::Equal => Ok(Self::True),
Ordering::Less => Ok(Self::False),
},
Op::LessThan => match lhs.cmp(&rhs, op)? {
Ordering::Less => Ok(Self::True),
Ordering::Greater | Ordering::Equal=> Ok(Self::False),
},
Op::LessThanEqual => match lhs.cmp(&rhs, op)? {
Ordering::Less | Ordering::Equal => Ok(Self::True),
Ordering::Greater => Ok(Self::False),
},
},
Self::Paren(v) => v.eval(),
Self::UnaryOp(op, val) => match op {
@ -194,4 +210,27 @@ impl Value {
_ => Ok(self),
}
}
pub fn cmp(&self, other: &Self, op: Op) -> SassResult<Ordering> {
Ok(match self {
Self::Dimension(num, ref unit) => match other {
Self::Dimension(num2, unit2) => {
if !unit.comparable(&unit2) {
return Err(format!("Incompatible units {} and {}.", unit2, unit).into());
}
if unit == unit2 {
num.cmp(num2)
} else if unit == &Unit::None {
num.cmp(num2)
} else if unit2 == &Unit::None {
num.cmp(num2)
} else {
num.cmp(&(num2.clone() * UNIT_CONVERSION_TABLE[&unit.to_string()][&unit2.to_string()].clone()))
}
}
_ => return Err(format!("Undefined operation \"{} {} {}\".", self, op, other).into()),
},
_ => return Err(format!("Undefined operation \"{} {} {}\".", self, op, other).into())
})
}
}

View File

@ -188,6 +188,26 @@ impl Value {
return Err("expected \"=\".".into());
}
}
q @ '>' | q @ '<' => {
toks.next();
let op = if toks.peek().unwrap().kind == '=' {
toks.next();
match q {
'>' => Op::GreaterThanEqual,
'<' => Op::LessThanEqual,
_ => unreachable!()
}
} else {
match q {
'>' => Op::GreaterThan,
'<' => Op::LessThan,
_ => unreachable!()
}
};
devour_whitespace(toks);
let right = Self::from_tokens(toks, scope, super_selector)?;
Ok(Value::BinaryOp(Box::new(left), op, Box::new(right)))
}
'!' => {
toks.next();
if toks.peek().unwrap().kind == '=' {

65
tests/ordering.rs Normal file
View File

@ -0,0 +1,65 @@
#![cfg(test)]
#[macro_use]
mod macros;
test!(
greater_than_or_equal_is_greater,
"a {\n color: 2 >= 1;\n}\n",
"a {\n color: true;\n}\n"
);
test!(
greater_than_or_equal_is_equal,
"a {\n color: 1 >= 1;\n}\n",
"a {\n color: true;\n}\n"
);
test!(
greater_than_or_equal_is_less,
"a {\n color: 0 >= 1;\n}\n",
"a {\n color: false;\n}\n"
);
test!(
greater_than_is_greater,
"a {\n color: 2 > 1;\n}\n",
"a {\n color: true;\n}\n"
);
test!(
greater_than_is_equal,
"a {\n color: 1 > 1;\n}\n",
"a {\n color: false;\n}\n"
);
test!(
greater_than_is_less,
"a {\n color: 0 > 1;\n}\n",
"a {\n color: false;\n}\n"
);
test!(
less_than_or_equal_is_greater,
"a {\n color: 2 <= 1;\n}\n",
"a {\n color: false;\n}\n"
);
test!(
less_than_or_equal_is_equal,
"a {\n color: 1 <= 1;\n}\n",
"a {\n color: true;\n}\n"
);
test!(
less_than_or_equal_is_less,
"a {\n color: 0 <= 1;\n}\n",
"a {\n color: true;\n}\n"
);
test!(
less_than_is_greater,
"a {\n color: 2 < 1;\n}\n",
"a {\n color: false;\n}\n"
);
test!(
less_than_is_equal,
"a {\n color: 1 < 1;\n}\n",
"a {\n color: false;\n}\n"
);
test!(
less_than_is_less,
"a {\n color: 0 < 1;\n}\n",
"a {\n color: true;\n}\n"
);