Skip to content

Commit

Permalink
add modulo (%) infix operator (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
fananek authored Feb 12, 2021
1 parent a2784a9 commit a9b2f07
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
2 changes: 2 additions & 0 deletions Sources/LeafKit/Exports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ extension Character {
.minus,
.star,
.forwardSlash,
.percent,
.equals,
.exclamation,
.lessThan,
Expand Down Expand Up @@ -101,6 +102,7 @@ extension Character {
static let minus = "-".first!
static let star = "*".first!
static let forwardSlash = "/".first!
static let percent = "%".first!
static let equals = "=".first!
static let exclamation = "!".first!
static let lessThan = "<".first!
Expand Down
4 changes: 2 additions & 2 deletions Sources/LeafKit/LeafLexer/LeafParameterTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public enum LeafOperator: String, Equatable, CustomStringConvertible, CaseIterab

internal static let precedenceMap: [(check: ((LeafOperator) -> Bool), infixed: Bool)] = [
(check: { $0 == .not }, infixed: false), // unaryNot
(check: { $0 == .multiply || $0 == .divide }, infixed: true), // Mult/Div
(check: { $0 == .multiply || $0 == .divide || $0 == .modulo }, infixed: true), // Mult/Div/Mod
(check: { $0 == .plus || $0 == .minus }, infixed: true), // Plus/Minus
(check: { $0 == .greater || $0 == .greaterOrEqual }, infixed: true), // >, >=
(check: { $0 == .lesser || $0 == .lesserOrEqual }, infixed: true), // <, <=
Expand All @@ -146,7 +146,7 @@ public enum LeafOperator: String, Equatable, CustomStringConvertible, CaseIterab
lesserOrEqual, and, or, plus, minus, divide,
multiply, modulo, assignment, nilCoalesce,
scopeMember, subOpen],
"unavailable" : [modulo, assignment, nilCoalesce, evaluate, scopeRoot,
"unavailable" : [assignment, nilCoalesce, evaluate, scopeRoot,
scopeMember, subOpen, subClose]
]
}
Expand Down
28 changes: 26 additions & 2 deletions Sources/LeafKit/LeafSerialize/ParameterResolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,10 @@ internal struct ParameterResolver {
return try multiply(lhs: lhs, rhs: rhs)
case .divide:
return try divide(lhs: lhs, rhs: rhs)
case .modulo:
return try modulo(lhs: lhs, rhs: rhs)
case .assignment: throw "Future feature"
case .nilCoalesce: throw "Future feature"
case .modulo: throw "Future feature"
case .evaluate: throw "Future feature"
case .scopeRoot: throw "Future feature"
case .scopeMember: throw "Future feature"
Expand Down Expand Up @@ -303,7 +304,30 @@ internal struct ParameterResolver {
let l = load()
return try divide(lhs: l, rhs: rhs)
case .data, .array, .string, .dictionary, .bool:
throw "unable to multiply this type `\(lhs)`"
throw "unable to divide this type `\(lhs)`"
}
}

private func modulo(lhs: LeafData, rhs: LeafData) throws -> LeafData {
switch lhs.storage {
case .optional(_, _): throw "Optional unwrapping not possible yet"
case .int(let i):
// if either is double, be double
if case .double(let d) = rhs.storage {
let product = Double(i).truncatingRemainder(dividingBy: d)
return .double(product)
} else {
let rhs = rhs.int ?? 0
return .int(i % rhs)
}
case .double(let d):
let rhs = rhs.double ?? 0
return .double(d.truncatingRemainder(dividingBy: rhs))
case .lazy(let load, _, _):
let l = load()
return try modulo(lhs: l, rhs: rhs)
case .data, .array, .string, .dictionary, .bool:
throw "unable to apply modulo on this type `\(lhs)`"
}
}

Expand Down
20 changes: 20 additions & 0 deletions Tests/LeafKitTests/GHTests/VaporLeafKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,24 @@ final class GHLeafKitIssuesTest: XCTestCase {
let page = try! TestRenderer(sources: .singleSource(test)).render(path: "a", context: ["challenges":["","",""]]).wait()
XCTAssertEqual(page.string, expected)
}

/// https://github.com/vapor/leaf-kit/issues/87
func testGH87() {
do {
let template = """
#if(2 % 2 == 0):hi#endif #if(0 == 4 % 2):there#endif
"""
let expected = "hi there"
try XCTAssertEqual(render(template, ["a": "a"]), expected)
}

// test with double values
do {
let template = """
#if(5.0 % 2.0 == 1.0):hi#endif #if(4.0 % 2.0 == 0.0):there#endif
"""
let expected = "hi there"
try XCTAssertEqual(render(template, ["a": "a"]), expected)
}
}
}

0 comments on commit a9b2f07

Please sign in to comment.