Fix number equality.

This commit is contained in:
Natalie Weizenbaum 2016-10-18 14:26:52 -07:00
parent 45becee133
commit 286b24afca
3 changed files with 34 additions and 12 deletions

View File

@ -269,6 +269,14 @@ abstract class Value {
Value dividedBy(Value other) => Value dividedBy(Value other) =>
new SassString("${toCssString()}/${other.toCssString()}"); new SassString("${toCssString()}/${other.toCssString()}");
/// The SassScript `==` operation.
///
/// For the most part, this is the same as the Dart `==` operation, which is
/// used as equivalence for map keys. However, [SassNumber]s with units are
/// SassScript-`==` to the same unitless numbers, but they not Dart `==`. This
/// ensures that map-key equality is transitive.
SassBoolean equals(Value other) => new SassBoolean(this == other);
/// The SassScript unary `+` operation. /// The SassScript unary `+` operation.
Value unaryPlus() => new SassString("+${toCssString()}"); Value unaryPlus() => new SassString("+${toCssString()}");

View File

@ -392,32 +392,28 @@ class SassNumber extends Value {
SassBoolean greaterThan(Value other) { SassBoolean greaterThan(Value other) {
if (other is SassNumber) { if (other is SassNumber) {
return new SassBoolean( return new SassBoolean(_coerceUnits(other, fuzzyGreaterThan));
_coerceUnits(other, (num1, num2) => fuzzyGreaterThan(num1, num2)));
} }
throw new SassScriptException('Undefined operation "$this > $other".'); throw new SassScriptException('Undefined operation "$this > $other".');
} }
SassBoolean greaterThanOrEquals(Value other) { SassBoolean greaterThanOrEquals(Value other) {
if (other is SassNumber) { if (other is SassNumber) {
return new SassBoolean(_coerceUnits( return new SassBoolean(_coerceUnits(other, fuzzyGreaterThanOrEquals));
other, (num1, num2) => fuzzyGreaterThanOrEquals(num1, num2)));
} }
throw new SassScriptException('Undefined operation "$this >= $other".'); throw new SassScriptException('Undefined operation "$this >= $other".');
} }
SassBoolean lessThan(Value other) { SassBoolean lessThan(Value other) {
if (other is SassNumber) { if (other is SassNumber) {
return new SassBoolean( return new SassBoolean(_coerceUnits(other, fuzzyLessThan));
_coerceUnits(other, (num1, num2) => fuzzyLessThan(num1, num2)));
} }
throw new SassScriptException('Undefined operation "$this < $other".'); throw new SassScriptException('Undefined operation "$this < $other".');
} }
SassBoolean lessThanOrEquals(Value other) { SassBoolean lessThanOrEquals(Value other) {
if (other is SassNumber) { if (other is SassNumber) {
return new SassBoolean(_coerceUnits( return new SassBoolean(_coerceUnits(other, fuzzyLessThanOrEquals));
other, (num1, num2) => fuzzyLessThanOrEquals(num1, num2)));
} }
throw new SassScriptException('Undefined operation "$this <= $other".'); throw new SassScriptException('Undefined operation "$this <= $other".');
} }
@ -464,6 +460,18 @@ class SassNumber extends Value {
throw new SassScriptException('Undefined operation "$this / $other".'); throw new SassScriptException('Undefined operation "$this / $other".');
} }
SassBoolean equals(Value other) {
if (other is SassNumber) {
try {
return new SassBoolean(_coerceUnits(other, fuzzyEquals));
} on SassScriptException {
return sassFalse;
}
} else {
return sassFalse;
}
}
Value unaryPlus() => this; Value unaryPlus() => this;
Value unaryMinus() => new SassNumber(-value); Value unaryMinus() => new SassNumber(-value);
@ -593,9 +601,15 @@ class SassNumber extends Value {
} }
bool operator ==(other) => bool operator ==(other) =>
other is SassNumber && fuzzyEquals(value, other.value); other is SassNumber &&
fuzzyEquals(value, other.value) &&
listEquals(numeratorUnits, other.numeratorUnits) &&
listEquals(denominatorUnits, other.denominatorUnits);
int get hashCode => fuzzyHashCode(value); int get hashCode =>
fuzzyHashCode(value) ^
listHash(numeratorUnits) ^
listHash(denominatorUnits);
/// Throws a [SassScriptException] with the given [message]. /// Throws a [SassScriptException] with the given [message].
SassScriptException _exception(String message, [String name]) => SassScriptException _exception(String message, [String name]) =>

View File

@ -662,9 +662,9 @@ class _PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
case BinaryOperator.and: case BinaryOperator.and:
return left.and(right); return left.and(right);
case BinaryOperator.equals: case BinaryOperator.equals:
return new SassBoolean(left == right); return left.equals(right);
case BinaryOperator.notEquals: case BinaryOperator.notEquals:
return new SassBoolean(left != right); return left.equals(right).unaryNot();
case BinaryOperator.greaterThan: case BinaryOperator.greaterThan:
return left.greaterThan(right); return left.greaterThan(right);
case BinaryOperator.greaterThanOrEquals: case BinaryOperator.greaterThanOrEquals: