Closed nicklockwood closed 6 years ago
Hi @nicklockwood,
Thanks very much for your contribution! I'm really grateful that you're experimenting with the framework. π
Parentheses nesting is a really tricky topic, but fortunately there is a solution to that. Instead of simply providing Keyword("(")
and Keyword(")")
keywords, you can use the OpenKeyword("(")
and CloseKeyword(")")
for adding some extra semantics to the framework that you are using (
and )
as nested pairs.
In your example:
let foo = Function<Double>(Keyword("foo") + OpenKeyword("(") + Variable<Double>("lhs") + Keyword(",") + Variable<Double>("rhs") + CloseKeyword(")")) { arguments, _, _ in
guard let lhs = arguments["lhs"] as? Double,
let rhs = arguments["rhs"] as? Double else { return nil }
return lhs - rhs
}
let bar = Function<Double>(Keyword("bar") + OpenKeyword("(") + Variable<Double>("value") + CloseKeyword(")")) { arguments, _, _ in
guard let value = arguments["value"] as? Double else { return nil }
return value - 2
}
This will provide the expected output for print(interpreter.evaluate("foo(5, 6 + bar(6))") as? Double ?? "nil")
, which is -5.0
.
In order to debug expressions like these, I suggest using the context
argument of the expression. It's a mutable instance, which contains a debugInfo
field that may give you a deeper understanding of how the framework interpreted your expression.
let context = Context()
let result = interpreter.evaluate("foo(5, 6 + bar(6))", context: context)
print(context.debugInfo)
This is going to provide the following output:
[
"bar(6)":
Eval.ExpressionInfo(input: "bar(6)", output: 4.0, pattern: "bar ( {value} )", variables: ["value": 6.0]),
"6 + bar(6)":
Eval.ExpressionInfo(input: "6 + bar(6)", output: 10.0, pattern: "{lhs} + {rhs}", variables: ["rhs": 4.0, "lhs": 6.0]),
"foo(5, 6 + bar(6))":
Eval.ExpressionInfo(input: "foo(5, 6 + bar(6))", output: -5.0, pattern: "foo ( {lhs} , {rhs} )", variables: ["rhs": 10.0, "lhs": 5.0])
]
Here you can see, that first, it interprets bar(6)
as the deepest argument. Then, it proceeds with 6 + bar(6)
, and finally, the whole expression, which provides the expected output. You can also inspect the output and the variables used in each step.
For future reference, I also wrote a few lines about this phenomenon here, in the Use OpenKeyword and CloseKeyword for embedding parentheses
section.
I hope it answers your question! Let me know if you have anything else in your mind.
Keep up the good stuff! π Cheers, Laszlo
@tevelee thanks, that makes sense π
With the following configuration, Eval is producing nil for the 4th expression. I'm not sure how to dig further into where the bug lies, but it's possibly confused by the nested function calls?