-
Notifications
You must be signed in to change notification settings - Fork 225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic numeric expresion handling #86
Conversation
fwiw. I use catching objective-c exceptions in Sourcery to recover from Stencil KVC resolution failures (in daemon mode) |
You use this, right? |
@djbe not having much luck with testing this. Am I doing something wrong?
diff --git a/Tests/StencilTests/VariableSpec.swift b/Tests/StencilTests/VariableSpec.swift
index d66dc1a..0723c40 100644
--- a/Tests/StencilTests/VariableSpec.swift
+++ b/Tests/StencilTests/VariableSpec.swift
@@ -19,16 +19,18 @@ fileprivate struct Article {
func testVariable() {
- describe("Variable") {
- let context = Context(dictionary: [
- "name": "Kyle",
- "contacts": ["Katie", "Carlton"],
- "profiles": [
- "github": "kylef",
- ],
- "article": Article(author: Person(name: "Kyle"))
- ])
+ let context = Context(dictionary: [
+ "name": "Kyle",
+ "contacts": ["Katie", "Carlton"],
+ "profiles": [
+ "github": "kylef",
+ ],
+ "article": Article(author: Person(name: "Kyle")),
+ "x": 5,
+ "y": 10,
+ ])
+ describe("Variable") {
#if os(OSX)
context["object"] = Object()
#endif
@@ -115,4 +117,18 @@ func testVariable() {
}
#endif
}
+
+ describe("CompoundVariable") {
+ $0.it("can resolve a literal expression") {
+ let variable = CompoundVariable("1 + 2")
+ let result = try variable.resolve(context) as? String
+ try expect(result) == "3"
+ }
+
+ $0.it("can resolve a variable expression") {
+ let variable = CompoundVariable("x + y")
+ let result = try variable.resolve(context) as? String
+ try expect(result) == "15"
+ }
+ }
} |
052fba2
to
5c241d9
Compare
@kylef I've added some tests that should show how it works. Edit: Apparently, the linux Foundation port does not implement NSExpression yet. We could use a typealias to only enable CompoundVariable on macOS: #if os(Linux)
typealias VariableType = Variable
#else
typealias VariableType = CompoundVariable
#endif |
Would like to hereby +1 this :) 👍 |
I don't know, I'm still not sure which is better.
|
I feel Linux support is a better thing to have for project like Stencil than having a very powerful expressions engine under the hood 🤷♂️ |
If we ever implement this, we should use a library such as Expression. The mechanism for triggering an expression "parse" could be taken from this PR, and we'd need to provide expression with our own symbol lookup function (which it supports). |
Stencil has boolean expression handling, but numeric ones. Instead of writing my own ridiculously complex expression parser, there exists this little gem of a Foundation class called
NSExpression
, so I just used that.Small problem is that, while it accepts an
object
parameter, this is quite limited, as it won't know how to handlemyArray.count
becausemyArray
isn't Key-Value compliant forcount
, and all object leaves must be number values. That's why I rolled my own resolver using Stencil's existing system.There is a small gotcha with this whole system: if
NSExpression
fails parsing an expression, it throws an Objective-C exception, which Swift can't catch. There are solutions for this, such as http://stackoverflow.com/questions/32758811/catching-nsexception-in-swift, but they would require a small bit of objective-c code.I've just made a quick implementation to throw the idea out there. It currently works for examples such as
{{ (myArray.count + 5) / 3 - 1 }}
, which is already really cool.