Add boolean short-circuiting.

This commit is contained in:
Natalie Weizenbaum 2017-02-03 17:37:54 -08:00
parent b32e5f96ce
commit 79261fee8e
5 changed files with 29 additions and 17 deletions

View File

@ -13,6 +13,8 @@
* Properly handle placeholder selectors in selector pseudos.
* Properly short-circuit the `or` and `and` operators.
* Support `--$variable`.
* Don't consider unitless numbers equal to numbers with units.

View File

@ -235,12 +235,6 @@ abstract class Value {
Value singleEquals(Value other) =>
new SassString("${toCssString()}=${other.toCssString()}");
/// The SassScript `or` operation.
Value or(Value other) => this;
/// The SassScript `and` operation.
Value and(Value other) => other;
/// The SassScript `>` operation.
SassBoolean greaterThan(Value other) =>
throw new SassScriptException('Undefined operation "$this > $other".');

View File

@ -31,9 +31,5 @@ class SassBoolean extends Value {
SassBoolean assertBoolean([String name]) => this;
Value or(Value other) => value ? this : other;
Value and(Value other) => value ? other : this;
Value unaryNot() => value ? sassFalse : sassTrue;
}

View File

@ -20,9 +20,5 @@ class SassNull extends Value {
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor) => visitor.visitNull(this);
Value or(Value other) => other;
Value and(Value other) => this;
Value unaryNot() => sassTrue;
}

View File

@ -964,33 +964,55 @@ class _PerformVisitor
Value visitBinaryOperationExpression(BinaryOperationExpression node) {
return _addExceptionSpan(node.span, () {
var left = node.left.accept(this);
var right = node.right.accept(this);
switch (node.operator) {
case BinaryOperator.singleEquals:
var right = node.right.accept(this);
return left.singleEquals(right);
case BinaryOperator.or:
return left.or(right);
return left.isTruthy ? left : node.right.accept(this);
case BinaryOperator.and:
return left.and(right);
return left.isTruthy ? node.right.accept(this) : left;
case BinaryOperator.equals:
var right = node.right.accept(this);
return new SassBoolean(left == right);
case BinaryOperator.notEquals:
var right = node.right.accept(this);
return new SassBoolean(left != right);
case BinaryOperator.greaterThan:
var right = node.right.accept(this);
return left.greaterThan(right);
case BinaryOperator.greaterThanOrEquals:
var right = node.right.accept(this);
return left.greaterThanOrEquals(right);
case BinaryOperator.lessThan:
var right = node.right.accept(this);
return left.lessThan(right);
case BinaryOperator.lessThanOrEquals:
var right = node.right.accept(this);
return left.lessThanOrEquals(right);
case BinaryOperator.plus:
var right = node.right.accept(this);
return left.plus(right);
case BinaryOperator.minus:
var right = node.right.accept(this);
return left.minus(right);
case BinaryOperator.times:
var right = node.right.accept(this);
return left.times(right);
case BinaryOperator.dividedBy:
var right = node.right.accept(this);
var result = left.dividedBy(right);
if (node.allowsSlash && left is SassNumber && right is SassNumber) {
var leftSlash = left.asSlash ?? _toCss(left, node.left.span);
@ -1000,7 +1022,9 @@ class _PerformVisitor
return result;
}
break;
case BinaryOperator.modulo:
var right = node.right.accept(this);
return left.modulo(right);
default:
return null;