-
Notifications
You must be signed in to change notification settings - Fork 601
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
boolean operator short-circuiting #713
Conversation
When I tried this before in #538 I apparently ended up needing to teach the parser to parse the Off the top of my head I don't remember why that was needed, and maybe something else you did here made that not necessary for this version, but just wanted to point it out in case it matters because it seems like all of the test cases here only test one operation at a time. (My PR seems to only test the single-operation cases also, so I guess I must've run out of time to work on it just after dealing with whatever problem that parser change was supposed to be solving. 🤔 ) |
This actually came out of some work to sort out and audit |
dc88dcc
to
144fdb5
Compare
Add a complete test of all 2 and 3 part boolean expressions including unknowns. |
Ah yes, I think I remember what I was dithering about in that other PR now: The intuition from some other languages is that the terms evaluate from left to right and evaluation stops as soon as they reach a term that is sufficient to decide the answer. HCL has two extra oddities that I was pondering different ways to represent:
I had been debating with myself whether to try to find some way to preserve the left-to-right behavior that folks would probably be expecting or whether to make it fully symmetrical so that e.g. The associativity fiddling was part of my experiments with different approaches to that question, but I agree that some answers to that question don't require anything special to happen in the parser. The approach you've proposed here seems like it's one of the shapes that doesn't require a specific parse tree shape. |
For completeness I took the full truth-table test and ran it against |
7bda92a
to
355e88a
Compare
Something which my initial attempt missed was the complete handling of diagnostics. There's two real reasons to need short-circuiting in HCL, to account for We had all the The updated signature is not as tidy (and far removed from the initial prototype in 538), but allows us to keep the diagnostics paired with the path taken through the expression:
Another option would be to return an indication of which side was taken and allow the caller to pick the diagnostics, but while it would have fewer arguments to handle, it seems less flexible and not really any more clear. |
I would note that this is attempting to converge with the same behavior implemented by conditional expressions, but ends up being somewhat convoluted because |
FWIW I had considered that too, and had decided against it because the AST nodes in Messing with the associativity of the operators was a concession I allowed myself because it seemed like an existing caller trying to do a tree walk and visit every node would still get a reasonable answer -- no new AST node types, just a different tree shape -- but adding entirely new AST nodes is potentially more risky because any third-party type switch over all of them would not cover it. Perhaps it's worth doing anyway since I do agree that it's a cleaner design looking forward. I dunno. 🤷♂️ |
Ah yes, exhaustive type switching is always a hazard in these things 🤦♂️ Well, I'd prefer to not think about that unless I have to, and even if the |
Implement short-circuiting logic for boolean binary operators
355e88a
to
4192658
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@hashicorp/team-ip-compliance, can you give this a review so we can proceed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for the changes.
Taking inspiration from #538, this continues the effort to allow short-circuiting of boolean operators. I don't think we need to switch the operators to right-associative for short-circuiting to work like the previous PR, as I think the problem with the prior PR was that the decision to short-circuit requires both lhs and rhs values because short-circuiting happens in both directions for either operator. My guess was that the explicit switch to right-associative made some rhs short-circuits work, but it still doesn't work both ways.
Given that HCL already evaluates boolean operations like so, it appears the associative-ness is OK:
and same with distributive identities with implied order:
(maybe that's just restating the same thing, but I figure I'd type it out ;)).
Since single boolean operators are fully associative,
foo && (bar && baz)
is equivalent to(foo && bar) && baz
, when both&&
and||
are present operator precedence takes care of the rest. An example being:which is correct because
&&
has precedence over||
.The full ability to short-circuit also allows us to handle all the unknown cases (as previously described in hashicorp/terraform#31078), filling out the truth tables in their entirety:
&&
true
false
unknown
true
true
false
unknown
false
false
false
false
unknown
unknown
false
unknown
||
true
false
unknown
true
true
true
true
false
true
false
unknown
unknown
true
unknown
unknown