-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Pipe operator #5425
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 #5425
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--TEST-- | ||
Test that a pipe operator displays as a pipe operator when outputting syntax. | ||
--FILE-- | ||
<?php | ||
|
||
function _test(int $a): int { | ||
return $a + 1; | ||
} | ||
|
||
try { | ||
assert((5 |> '_test') == 99); | ||
} catch (AssertionError $e) { | ||
print $e->getMessage(); | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
assert(5 |> \_test == 99) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--TEST-- | ||
Pipe operator accepts by-reference functions | ||
--FILE-- | ||
<?php | ||
|
||
function _modify(int &$a): string { | ||
$a += 1; | ||
return "foo"; | ||
} | ||
|
||
//try { | ||
$a = 5; | ||
$res1 = $a |> '_modify'; | ||
|
||
var_dump($res1); | ||
var_dump($a); | ||
?> | ||
--EXPECT-- | ||
string(3) "foo" | ||
int(6) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--TEST-- | ||
Pipe operator chains | ||
--FILE-- | ||
<?php | ||
|
||
function _test1(int $a): int { | ||
return $a + 1; | ||
} | ||
|
||
function _test2(int $a): int { | ||
return $a * 2; | ||
} | ||
|
||
$res1 = 5 |> '_test1' |> '_test2'; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(12) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--TEST-- | ||
Pipe operator throws normally on missing function | ||
--FILE-- | ||
<?php | ||
|
||
try { | ||
$res1 = 5 |> '_test'; | ||
} | ||
catch (Throwable $e) { | ||
printf("Expected %s thrown, got %s", Error::class, get_class($e)); | ||
} | ||
|
||
?> | ||
--EXPECT-- | ||
Expected Error thrown, got Error |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--TEST-- | ||
Pipe operator handles all callable styles | ||
--FILE-- | ||
<?php | ||
|
||
function _add(int $x, int $y): int { | ||
return $x + $y; | ||
} | ||
|
||
function _area(int $x, int $y): int { | ||
return $x * $y; | ||
} | ||
|
||
class _Test | ||
{ | ||
public function message(string $which): string | ||
{ | ||
if ($which == 1) { | ||
return "Hello"; | ||
} | ||
else if ($which == 2) { | ||
return "Goodbye"; | ||
} | ||
else { | ||
return "World"; | ||
} | ||
} | ||
} | ||
|
||
$test = new _Test(); | ||
|
||
$add3 = fn($x) => _add($x, 3); | ||
|
||
$res1 = 2 | ||
|> [$test, 'message'] | ||
|> 'strlen' | ||
|> $add3 | ||
|> fn($x) => _area($x, 2) | ||
; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(20) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--TEST-- | ||
Pipe operator accepts optional-parameter functions | ||
--FILE-- | ||
<?php | ||
|
||
function _test(int $a, int $b = 3) { | ||
return $a + $b; | ||
} | ||
|
||
$res1 = 5 |> '_test'; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(8) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
--TEST-- | ||
Pipe binds lower than addition | ||
--FILE-- | ||
<?php | ||
|
||
function _test1(int $a): int { | ||
return $a + 1; | ||
} | ||
|
||
$bad_func = null; | ||
|
||
$res1 = 5 + 2 |> '_test1'; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(8) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
--TEST-- | ||
Pipe binds lower than coalesce | ||
--FILE-- | ||
<?php | ||
|
||
function _test1(int $a): int { | ||
return $a * 2; | ||
} | ||
|
||
$bad_func = null; | ||
|
||
$res1 = 5 |> $bad_func ?? '_test1'; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(10) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Pipe binds lower than ternary | ||
--FILE-- | ||
<?php | ||
|
||
function _test1(int $a): int { | ||
return $a + 1; | ||
} | ||
|
||
function _test2(int $a): int { | ||
return $a * 2; | ||
} | ||
|
||
$bad_func = null; | ||
|
||
$res1 = 5 |> $bad_func ? '_test1' : '_test2'; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(10) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--TEST-- | ||
Pipe operator supports built-in functions | ||
--FILE-- | ||
<?php | ||
|
||
$res1 = "Hello" |> 'strlen'; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(5) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--TEST-- | ||
Pipe operator supports user-defined functions | ||
--FILE-- | ||
<?php | ||
|
||
function _test(int $a): int { | ||
return $a + 1; | ||
} | ||
|
||
$res1 = 5 |> '_test'; | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(6) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Pipe operator fails on multi-parameter functions | ||
--FILE-- | ||
<?php | ||
|
||
function _test(int $a, int $b) { | ||
return $a + $b; | ||
} | ||
|
||
|
||
try { | ||
$res1 = 5 |> '_test'; | ||
} | ||
catch (Throwable $e) { | ||
printf("Expected %s thrown, got %s", ArgumentCountError::class, get_class($e)); | ||
} | ||
|
||
|
||
?> | ||
--EXPECT-- | ||
Expected ArgumentCountError thrown, got ArgumentCountError |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--TEST-- | ||
Pipe operator respects types | ||
--FILE-- | ||
<?php | ||
|
||
function _test(int $a, int $b) { | ||
return $a + $b; | ||
} | ||
|
||
try { | ||
$res1 = "Hello" |> '_test'; | ||
var_dump($res1); | ||
} | ||
catch (Throwable $e) { | ||
printf("Expected %s thrown, got %s", TypeError::class, get_class($e)); | ||
} | ||
|
||
?> | ||
--EXPECT-- | ||
Expected TypeError thrown, got TypeError |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Pipe operator fails void return chaining in strict mode | ||
--FILE-- | ||
<?php | ||
declare(strict_types=1); | ||
|
||
function nonReturnFunction($bar): void {} | ||
|
||
try { | ||
$result = "Hello World" | ||
|> 'nonReturnFunction' | ||
|> 'strlen'; | ||
var_dump($result); | ||
} | ||
catch (Throwable $e) { | ||
printf("Expected %s thrown, got %s", TypeError::class, get_class($e)); | ||
} | ||
|
||
?> | ||
--EXPECT-- | ||
Expected TypeError thrown, got TypeError |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Pipe operator chains saved as a closure | ||
--FILE-- | ||
<?php | ||
|
||
function _test1(int $a): int { | ||
return $a + 1; | ||
} | ||
|
||
function _test2(int $a): int { | ||
return $a * 2; | ||
} | ||
|
||
$func = fn($x) => $x |> '_test1' |> '_test2'; | ||
|
||
$res1 = $func(5); | ||
|
||
var_dump($res1); | ||
?> | ||
--EXPECT-- | ||
int(12) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); | |
%precedence T_DOUBLE_ARROW | ||
%precedence T_YIELD_FROM | ||
%precedence '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL | ||
%left T_PIPE | ||
%left '?' ':' | ||
%right T_COALESCE | ||
%left T_BOOLEAN_OR | ||
|
@@ -231,6 +232,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); | |
%token T_COALESCE "'??'" | ||
%token T_POW "'**'" | ||
%token T_POW_EQUAL "'**='" | ||
%token T_PIPE "|>" | ||
%token T_BAD_CHARACTER "invalid character" | ||
|
||
/* Token used to force a parse error from the lexer */ | ||
|
@@ -1114,6 +1116,8 @@ 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 | ||
{ $$ = zend_ast_create(ZEND_AST_CALL, $3, zend_ast_create_list(1, ZEND_AST_ARG_LIST, $1) ); $$->attr = ZEND_CALL_SYNTAX_PIPE; } | ||
Crell marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+1119
to
+1120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nikic Is there something we could/should do with
Was trying to think of how we can make it as helpful as possible for debuggers, profilers, etc to have accurate line numbers. |
||
| expr '<' expr | ||
{ $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER, $1, $3); } | ||
| expr T_IS_SMALLER_OR_EQUAL expr | ||
|
Uh oh!
There was an error while loading. Please reload this page.