-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
docs: Clarify associativity of operators. #9170
Merged
Merged
Changes from 3 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
4639dfd
docs: Clarify associativity of operators.
elenakrittik dfe197b
misc: Add missing (?) comma.
elenakrittik 4da643f
docs: Move associativity note to the top of the section.
elenakrittik 82a8fe2
Add associativity table column.
elenakrittik 8948e3f
Add missed associativity for `await`.
elenakrittik 5d1fe64
Remove the table
elenakrittik 63ddb01
Remove the table
elenakrittik 897bff3
Remove the table
elenakrittik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Binary operators use a table (
get_rule()
), which does not provide the ability to specify associativity. Unary and ternary operators callparse_precedence()
in place, so we need to check their associativity. It looks like the ternary operator is right-associative: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.
Found the sources:
Was able to confirm your observation about ternary operator, but i got really confused when i tried to determine associativity of unary operators. First of all, there is no code (or at least i think so) explicitly handling associativity, only precedence. But even then, it doesn't look like precedence is considered for unary operators because both
-1 + 1
(lower precedence than unary-
) and-1 ** 1
(higher precedence than-
) are parsed the same ((-1) + 1
and(-1) ** 1
accordingly), so i'm not sure what exactly precedence does in this case. And in general, i struggle to understand what "associativity" even means in case of unary operators, because parsing them the way it's done right now is the only way that makes sense to me (-1 + 1
==-(1 + 1)
? this would be unreasonable; neither it's possible to chain unary ops like binary ops). I'm absolutely lost on the theoretical part here 🤷But anyway, back from crying into others' jackets. I tested all unary operators with two cases (
<unary op> <expr> <binary op with higher precedence> <expr>
and the same with lower precedence binary op) and in all cases it results in(<unary op> <expr>) <binary op> (<expr>)
, so from what i know this means all unary ops are left-associative as well?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.
TLDR: I think we can just write that all binary operators in GDScript are left-associative, the ternary operator is right-associative, and leave out the unary operators.
Indeed, in the case of unary operations, the definition of associativity is not obvious. I see two approaches: 1. the binding strength between operators and operands, 2. the order of code execution.
Different operators have different binding strengths. If there are operators with equal precedence to the left and right of the operand, then the order is determined using associativity. The following options are possible:
(... infix operand) infix ...
... infix (operand infix ...)
(... infix operand) postfix
... infix (operand postfix)
(prefix operand) infix ...
prefix (operand infix ...)
(prefix operand) postfix
prefix (operand postfix)
Some similar operators are grouped, have the same precedence and associativity:
+
and-
,*
and/
. But unary operators are too different, so have different precedence. GDScript does not have prefix/postfix increment/decrement operators (++
and--
), they would be a good example to illustrate. So we simply don't have a case where associativity is important for different unary operators.And the same unary operator cannot appear on both the left and right (unlike infix binary operators): prefix operators are always located on the left, and postfix operators on the right.
1 + 2 + 3
is valid, but~x~
is invalid.If we consider associativity not as the binding strength, but as the order of code execution, then there are several nuances:
--x
is-(-x)
), and postfix operators left-associative (a[x][y]
is(a[x])[y]
).Finally, in some cases, operators can be non-associative, such as chain comparisons in Python.