feat(if): Support equatable operator

This commit is contained in:
Kyle Fuller
2016-11-28 17:51:17 +00:00
parent 111306fb60
commit e989317929
5 changed files with 86 additions and 1 deletions

View File

@@ -20,7 +20,8 @@
- Variable lookup now supports introspection of Swift types. You can now lookup - Variable lookup now supports introspection of Swift types. You can now lookup
values of Swift structures and classes inside a Context. values of Swift structures and classes inside a Context.
- If tags can now use prefix and infix operators such as `not`, `and` and `or`. - If tags can now use prefix and infix operators such as `not`, `and`, `or` and
`==`.
```html+django ```html+django
{% if one or two and not three %} {% if one or two and not three %}

View File

@@ -134,6 +134,42 @@ final class AndExpression: Expression, InfixOperator, CustomStringConvertible {
} }
final class EqualityExpression: Expression, InfixOperator, CustomStringConvertible {
let lhs: Expression
let rhs: Expression
init(lhs: Expression, rhs: Expression) {
self.lhs = lhs
self.rhs = rhs
}
var description: String {
return "(\(lhs) == \(rhs))"
}
func evaluate(context: Context) throws -> Bool {
if let lhs = lhs as? VariableExpression, let rhs = rhs as? VariableExpression {
let lhsValue = try lhs.variable.resolve(context)
let rhsValue = try rhs.variable.resolve(context)
if let lhs = lhsValue, let rhs = rhsValue {
if let lhs = toNumber(value: lhs), let rhs = toNumber(value: rhs) {
return lhs == rhs
} else if let lhs = lhsValue as? String, let rhs = rhsValue as? String {
return lhs == rhs
} else if let lhs = lhsValue as? Bool, let rhs = rhsValue as? Bool {
return lhs == rhs
}
} else if lhsValue == nil && rhsValue == nil {
return true
}
}
return false
}
}
func toNumber(value: Any) -> Float80? { func toNumber(value: Any) -> Float80? {
if let value = value as? Float { if let value = value as? Float {
return Float80(value) return Float80(value)

View File

@@ -17,6 +17,7 @@ let operators: [Operator] = [
.infix("or", 6, OrExpression.self), .infix("or", 6, OrExpression.self),
.infix("and", 7, AndExpression.self), .infix("and", 7, AndExpression.self),
.prefix("not", 8, NotExpression.self), .prefix("not", 8, NotExpression.self),
.infix("==", 10, EqualityExpression.self),
] ]

View File

@@ -154,6 +154,42 @@ func testExpressions() {
} }
} }
$0.describe("equality expression") {
let expression = try! parseExpression(components: ["lhs", "==", "rhs"])
$0.it("evaluates to true with equal lhs/rhs") {
try expect(expression.evaluate(context: Context(dictionary: ["lhs": "a", "rhs": "a"]))).to.beTrue()
}
$0.it("evaluates to false with non equal lhs/rhs") {
print(expression)
}
$0.it("evaluates to true with nils") {
try expect(expression.evaluate(context: Context(dictionary: [:]))).to.beTrue()
}
$0.it("evaluates to true with numbers") {
try expect(expression.evaluate(context: Context(dictionary: ["lhs": 1, "rhs": 1.0]))).to.beTrue()
}
$0.it("evaluates to false with non equal numbers") {
try expect(expression.evaluate(context: Context(dictionary: ["lhs": 1, "rhs": 1.1]))).to.beFalse()
}
$0.it("evaluates to true with booleans") {
try expect(expression.evaluate(context: Context(dictionary: ["lhs": true, "rhs": true]))).to.beTrue()
}
$0.it("evaluates to false with falsy booleans") {
try expect(expression.evaluate(context: Context(dictionary: ["lhs": true, "rhs": false]))).to.beFalse()
}
$0.it("evaluates to false with different types") {
try expect(expression.evaluate(context: Context(dictionary: ["lhs": true, "rhs": 1]))).to.beFalse()
}
}
$0.describe("multiple expression") { $0.describe("multiple expression") {
let expression = try! parseExpression(components: ["one", "or", "two", "and", "not", "three"]) let expression = try! parseExpression(components: ["one", "or", "two", "and", "not", "three"])

View File

@@ -95,6 +95,17 @@ Will be treated as:
one or (two and three) one or (two and three)
``==`` operator
"""""""""""""""
.. code-block:: html+django
{% if value == other_value %}
value is equal to other_value
{% endif %}
.. note:: The equality operator only supports numerical, string and boolean types.
``ifnot`` ``ifnot``
~~~~~~~~~ ~~~~~~~~~