-
Notifications
You must be signed in to change notification settings - Fork 7.8k
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
Pipe operator #17118
base: master
Are you sure you want to change the base?
Pipe operator #17118
Conversation
2f0e83c
to
0f8b8b5
Compare
Oh, nice. You're implementing your own RFCs now? 👍🏻 |
Well, with help. :-) |
Add test to check behaviour of prefer-by-ref parameters
Puts ZEND_AST_PIPE above comparison operators, and below math operators.
@@ -71,6 +71,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); | |||
%left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG | |||
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP | |||
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL | |||
%left T_PIPE |
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.
Looking at ast.phpt
, I wonder if T_PIPE
should move once more to sit between .
and T_SL (<<
).
It appears to be more useful for:
"foo" . $a |> bar(...) . "baz"
to mean:
"foo" . bar($a) . "baz"
instead of currently:
(bar(...) . "baz")("foo" . $a)
which is semantic non-sense. This would be reasonably consistent with the intention of https://wiki.php.net/rfc/concatenation_precedence.
Keeping T_PIPE
below +
makes sense to me, since with function composition, applying +
to a callable is a well-defined operation.
It really is a mess that the two sides of |>
have very different semantics, making it hard to find a single obviously correct position in the precedence list. And I don't have a strong opinion regarding making this suggested change. The correct solution is “use pipe only in an assignment, not in other expressions”.
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.
I don't have a strong opinion here. In practice I agree, one should not be writing "interesting" expressions with pipes in them. The most complex anyone SHOULD be doing is with + for composition (next RFC), and then parens may be a good idea anyway.
Anyone else have an opinion to argue?
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.
Looks like it gets messy quickly and an optimal precedence may not exist. I agree with Tim.
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.
the two sides of
|>
have very different semantics, making it hard to find a single obviously correct position in the precedence list
Yes. When considering the LHS, |>
is more useful with a lower precedence, but when considering the RHS, a higher precedence would be better.
Can we use expr T_PIPE expr %prec PIPE
to change the precedence of this rule, so that it reduces earlier after T_PIPE?
e.g. with the following change:
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 7c4183ef736..845b187e489 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -81,6 +81,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%precedence '~' T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right T_POW
%precedence T_CLONE
+%precedence PIPE
/* Resolve danging else conflict */
%precedence T_NOELSE
@@ -1280,7 +1281,7 @@ expr:
{ $$ = zend_ast_create_binary_op(ZEND_IS_EQUAL, $1, $3); }
| expr T_IS_NOT_EQUAL expr
{ $$ = zend_ast_create_binary_op(ZEND_IS_NOT_EQUAL, $1, $3); }
- | expr T_PIPE expr
+ | expr T_PIPE expr %prec PIPE
{ $$ = zend_ast_create(ZEND_AST_PIPE, $1, $3); }
| expr '<' expr
{ $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER, $1, $3); }
The input
1 + $a |> bar(...) + 2;
is parsed as
((1 + $a) |> bar(...)) + 2;
I'm not a parser expert and I don't understand the full implications of this, however, so this may be a bad idea.
The correct solution is “use pipe only in an assignment, not in other expressions”.
I agree.
Still WIP.
cf: https://wiki.php.net/rfc/pipe-operator-v3