properly evaluate equality between lists

This commit is contained in:
ConnorSkees 2020-05-28 01:48:46 -04:00
parent 0bc6445ebf
commit 3c1a9a99b7
2 changed files with 87 additions and 6 deletions

View File

@ -8,14 +8,22 @@ use crate::unit::{Unit, UNIT_CONVERSION_TABLE};
use crate::value::Value; use crate::value::Value;
impl Value { impl Value {
pub fn equals(self, mut other: Value, span: Span) -> SassResult<Spanned<Value>> { pub fn equals(mut self, mut other: Value, span: Span) -> SassResult<Spanned<Value>> {
if let Self::Paren(..) = self {
self = self.eval(span)?.node
} else if let Self::UnaryOp(..) = self {
self = self.eval(span)?.node
}
if let Self::Paren(..) = other { if let Self::Paren(..) = other {
other = other.eval(span)?.node other = other.eval(span)?.node
} else if let Self::UnaryOp(..) = other {
other = other.eval(span)?.node
} }
let precedence = Op::Equal.precedence(); let precedence = Op::Equal.precedence();
Ok(Value::bool(match self { Ok(Value::bool(match self {
// todo: why don't we eval the other?
Self::String(s1, ..) => match other { Self::String(s1, ..) => match other {
Self::String(s2, ..) => s1 == s2, Self::String(s2, ..) => s1 == s2,
_ => false, _ => false,
@ -53,14 +61,38 @@ impl Value {
.eval(span); .eval(span);
} }
} }
Self::List(list1, sep1, brackets1) => match other.eval(span)?.node {
Self::List(list2, sep2, brackets2) => {
if sep1 != sep2 || brackets1 != brackets2 || list1.len() != list2.len() {
false
} else {
let mut equals = true;
for (a, b) in list1.into_iter().zip(list2) {
if !a.equals(b, span)?.node.is_true(span)? {
equals = false;
break;
}
}
equals
}
}
_ => false,
}
s => s == other.eval(span)?.node, s => s == other.eval(span)?.node,
}) })
.span(span)) .span(span))
} }
pub fn not_equals(self, mut other: Value, span: Span) -> SassResult<Spanned<Value>> { pub fn not_equals(mut self, mut other: Value, span: Span) -> SassResult<Spanned<Value>> {
if let Self::Paren(..) = self {
self = self.eval(span)?.node
} else if let Self::UnaryOp(..) = self {
self = self.eval(span)?.node
}
if let Self::Paren(..) = other { if let Self::Paren(..) = other {
other = other.eval(span)?.node other = other.eval(span)?.node
} else if let Self::UnaryOp(..) = other {
other = other.eval(span)?.node
} }
let precedence = Op::Equal.precedence(); let precedence = Op::Equal.precedence();
@ -103,6 +135,23 @@ impl Value {
.eval(span); .eval(span);
} }
} }
Self::List(list1, sep1, brackets1) => match other.eval(span)?.node {
Self::List(list2, sep2, brackets2) => {
if sep1 != sep2 || brackets1 != brackets2 || list1.len() != list2.len() {
true
} else {
let mut equals = false;
for (a, b) in list1.into_iter().zip(list2) {
if a.not_equals(b, span)?.node.is_true(span)? {
equals = true;
break;
}
}
equals
}
}
_ => true,
}
s => s != other.eval(span)?.node, s => s != other.eval(span)?.node,
}) })
.span(span)) .span(span))
@ -159,6 +208,8 @@ impl Value {
pub fn cmp(self, mut other: Self, op: Op, span: Span) -> SassResult<Spanned<Value>> { pub fn cmp(self, mut other: Self, op: Op, span: Span) -> SassResult<Spanned<Value>> {
if let Self::Paren(..) = other { if let Self::Paren(..) = other {
other = other.eval(span)?.node other = other.eval(span)?.node
} else if let Self::UnaryOp(..) = other {
other = other.eval(span)?.node
} }
let precedence = op.precedence(); let precedence = op.precedence();
let ordering = match self { let ordering = match self {
@ -247,12 +298,17 @@ impl Value {
.span(span)) .span(span))
} }
pub fn add(self, mut other: Self, span: Span) -> SassResult<Self> { pub fn add(mut self, mut other: Self, span: Span) -> SassResult<Self> {
if let Self::Paren(..) = other { if let Self::Paren(..) = other {
other = other.eval(span)?.node other = other.eval(span)?.node
} else if let Self::UnaryOp(..) = other { } else if let Self::UnaryOp(..) = other {
other = other.eval(span)?.node other = other.eval(span)?.node
} }
if let Self::Paren(..) = self {
self = self.eval(span)?.node
} else if let Self::UnaryOp(..) = self {
self = self.eval(span)?.node
}
let precedence = Op::Plus.precedence(); let precedence = Op::Plus.precedence();
Ok(match self { Ok(match self {
Self::Map(..) | Self::Function(..) => { Self::Map(..) | Self::Function(..) => {
@ -392,10 +448,15 @@ impl Value {
}) })
} }
pub fn sub(self, mut other: Self, span: Span) -> SassResult<Self> { pub fn sub(mut self, mut other: Self, span: Span) -> SassResult<Self> {
if let Self::Paren(..) = other { if let Self::Paren(..) = other {
other = other.eval(span)?.node other = other.eval(span)?.node
} }
if let Self::Paren(..) = self {
self = self.eval(span)?.node
} else if let Self::UnaryOp(..) = self {
self = self.eval(span)?.node
}
let precedence = Op::Mul.precedence(); let precedence = Op::Mul.precedence();
Ok(match self { Ok(match self {
Self::Null => { Self::Null => {
@ -521,10 +582,15 @@ impl Value {
}) })
} }
pub fn mul(self, mut other: Self, span: Span) -> SassResult<Self> { pub fn mul(mut self, mut other: Self, span: Span) -> SassResult<Self> {
if let Self::Paren(..) = other { if let Self::Paren(..) = other {
other = other.eval(span)?.node other = other.eval(span)?.node
} }
if let Self::Paren(..) = self {
self = self.eval(span)?.node
} else if let Self::UnaryOp(..) = self {
self = self.eval(span)?.node
}
let precedence = Op::Mul.precedence(); let precedence = Op::Mul.precedence();
Ok(match self { Ok(match self {
Self::Null => todo!(), Self::Null => todo!(),
@ -593,7 +659,12 @@ impl Value {
}) })
} }
pub fn div(self, other: Self, span: Span) -> SassResult<Self> { pub fn div(mut self, other: Self, span: Span) -> SassResult<Self> {
if let Self::Paren(..) = self {
self = self.eval(span)?.node
} else if let Self::UnaryOp(..) = self {
self = self.eval(span)?.node
}
let precedence = Op::Div.precedence(); let precedence = Op::Div.precedence();
Ok(match self { Ok(match self {
Self::Null => todo!(), Self::Null => todo!(),

View File

@ -48,3 +48,13 @@ test!(
"a {\n color: 1rem==1;\n}\n", "a {\n color: 1rem==1;\n}\n",
"a {\n color: false;\n}\n" "a {\n color: false;\n}\n"
); );
test!(
different_quoting_inside_list_eq,
"a {\n color: ("foo",) == (foo,);\n}\n",
"a {\n color: true;\n}\n"
);
test!(
different_quoting_inside_list_ne,
"a {\n color: ("foo",) != (foo,);\n}\n",
"a {\n color: false;\n}\n"
);