summaryrefslogtreecommitdiffstats
path: root/source/slang/check.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-07-08 16:44:48 -0700
committerTim Foley <tfoley@nvidia.com>2017-07-08 18:22:25 -0700
commit836a9985ac8540c2c9b27fd438ce757dc6884b9b (patch)
tree0459e9e079653e105cd682c0f6facf9a67d56ffb /source/slang/check.cpp
parentf69bc6cdb10aab2d1b202668cb7ecbcc0ddf33f2 (diff)
Try to emit expressions with minimal parentheses
When emitting code it is easy to be overly defensive and emit tons of extra parentheses. In some cases these are just annoying, and make the output more cluttered than it needs to be. In other cases, though, being over-aggressive here can actually break things when a downstream compiler has more stringent requirements (e.g., doesn't allow a general expression for the function in a call expression, but only a particular set of atomic/postfix expressions). This wasn't as bad when we weren't parsing function bodies in user code, but now that we *are* it becomes important to not emit bad parentheses and screw up their code. At the same time, though, we don't want to fail to output them and silently break code. A nice property today is that we preserve parentheses in the input code, so hopefully we don't ever break operator precedence. The code already had an approach to avoid *some* parens, by tracking an "outer precedence" and only emitting parens for an expression if they were needed relative to this outer precedence. That approach doesn't handle associativity, and so it doesn't work for things like chains of postfix operators. The new approach basically tracks *two* outer precedence levels: one on the left, and one on the right. When recursing into a sub-expression of an op (e.g., the `A` in `A + B`) on of the precdence levels for the recursive call will come from the outer environment, and the other from the operation itself (e.g., `A` has `(X, +)` as its left/right precdence, where `X` is whatever was to the left of `A + B`, while `B` gets `(+,Y)`). One more piece of the puzzle is that an operator like `+` actually exposes *two* precedence levels: one for the left-hand side and one for the right-hand, so that if both `A` and `B` are themselves uses of `+`, `A` won't get parens, but `B` will. Finally, when we have an un-checked application of an operator (which our AST stores as something like a function-call node), we do a little lookup step to find the corresponding operator and its precedence (while for things that actually got resolved we *know* the precedence.
Diffstat (limited to 'source/slang/check.cpp')
0 files changed, 0 insertions, 0 deletions