From 3c1a9a99b73789afcb659012e5608abe13503116 Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Thu, 28 May 2020 01:48:46 -0400 Subject: [PATCH] properly evaluate equality between lists --- src/value/ops.rs | 83 +++++++++++++++++++++++++++++++++++++++++++---- tests/equality.rs | 10 ++++++ 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/value/ops.rs b/src/value/ops.rs index 6b71dc5..5d63d97 100644 --- a/src/value/ops.rs +++ b/src/value/ops.rs @@ -8,14 +8,22 @@ use crate::unit::{Unit, UNIT_CONVERSION_TABLE}; use crate::value::Value; impl Value { - pub fn equals(self, mut other: Value, span: Span) -> SassResult> { + pub fn equals(mut self, mut other: Value, span: Span) -> SassResult> { + 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 { other = other.eval(span)?.node + } else if let Self::UnaryOp(..) = other { + other = other.eval(span)?.node } let precedence = Op::Equal.precedence(); Ok(Value::bool(match self { + // todo: why don't we eval the other? Self::String(s1, ..) => match other { Self::String(s2, ..) => s1 == s2, _ => false, @@ -53,14 +61,38 @@ impl Value { .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, }) .span(span)) } - pub fn not_equals(self, mut other: Value, span: Span) -> SassResult> { + pub fn not_equals(mut self, mut other: Value, span: Span) -> SassResult> { + 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 { other = other.eval(span)?.node + } else if let Self::UnaryOp(..) = other { + other = other.eval(span)?.node } let precedence = Op::Equal.precedence(); @@ -103,6 +135,23 @@ impl Value { .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, }) .span(span)) @@ -159,6 +208,8 @@ impl Value { pub fn cmp(self, mut other: Self, op: Op, span: Span) -> SassResult> { if let Self::Paren(..) = other { other = other.eval(span)?.node + } else if let Self::UnaryOp(..) = other { + other = other.eval(span)?.node } let precedence = op.precedence(); let ordering = match self { @@ -247,12 +298,17 @@ impl Value { .span(span)) } - pub fn add(self, mut other: Self, span: Span) -> SassResult { + pub fn add(mut self, mut other: Self, span: Span) -> SassResult { if let Self::Paren(..) = other { other = other.eval(span)?.node } else if let Self::UnaryOp(..) = other { 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(); Ok(match self { Self::Map(..) | Self::Function(..) => { @@ -392,10 +448,15 @@ impl Value { }) } - pub fn sub(self, mut other: Self, span: Span) -> SassResult { + pub fn sub(mut self, mut other: Self, span: Span) -> SassResult { if let Self::Paren(..) = other { 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(); Ok(match self { Self::Null => { @@ -521,10 +582,15 @@ impl Value { }) } - pub fn mul(self, mut other: Self, span: Span) -> SassResult { + pub fn mul(mut self, mut other: Self, span: Span) -> SassResult { if let Self::Paren(..) = other { 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(); Ok(match self { Self::Null => todo!(), @@ -593,7 +659,12 @@ impl Value { }) } - pub fn div(self, other: Self, span: Span) -> SassResult { + pub fn div(mut self, other: Self, span: Span) -> SassResult { + 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(); Ok(match self { Self::Null => todo!(), diff --git a/tests/equality.rs b/tests/equality.rs index 8bce6c3..d6fb7d9 100644 --- a/tests/equality.rs +++ b/tests/equality.rs @@ -48,3 +48,13 @@ test!( "a {\n color: 1rem==1;\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" +);