Skip to content

feat: make break, continue and return be an expression #17647

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

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: specify only specific use-cases for early instructions
  • Loading branch information
xepozz committed Apr 25, 2025
commit bf1bccc3cee05e4d71bc17d271b44a881b543f8f
24 changes: 17 additions & 7 deletions Zend/zend_language_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> group_use_declaration inline_use_declarations inline_use_declaration
%type <ast> mixed_group_use_declaration use_declaration unprefixed_use_declaration
%type <ast> unprefixed_use_declarations const_decl inner_statement
%type <ast> expr optional_expr while_statement for_statement foreach_variable
%type <ast> expr optional_expr while_statement for_statement foreach_variable early_return
%type <ast> foreach_statement declare_statement finally_statement unset_variable variable
%type <ast> extends_from parameter optional_type_without_static argument global_var
%type <ast> static_var class_statement trait_adaptation trait_precedence trait_alias
Expand Down Expand Up @@ -511,6 +511,9 @@ statement:
{ $$ = zend_ast_create(ZEND_AST_FOR, $3, $5, $7, $9); }
| T_SWITCH '(' expr ')' switch_case_list
{ $$ = zend_ast_create(ZEND_AST_SWITCH, $3, $5); }
| T_BREAK optional_expr ';' { $$ = zend_ast_create(ZEND_AST_BREAK, $2); }
| T_CONTINUE optional_expr ';' { $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); }
| T_RETURN optional_expr ';' { $$ = zend_ast_create(ZEND_AST_RETURN, $2); }
| T_GLOBAL global_var_list ';' { $$ = $2; }
| T_STATIC static_var_list ';' { $$ = $2; }
| T_ECHO echo_expr_list ';' { $$ = $2; }
Expand Down Expand Up @@ -1297,8 +1300,12 @@ expr:
{ $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); }
| expr '?' ':' expr
{ $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }
| expr '?' ':' early_return
{ $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }
| expr T_COALESCE expr
{ $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); }
| expr T_COALESCE early_return
{ $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); }
| internal_functions_in_yacc { $$ = $1; }
| T_INT_CAST expr { $$ = zend_ast_create_cast(IS_LONG, $2); }
| T_DOUBLE_CAST expr { $$ = zend_ast_create_cast(IS_DOUBLE, $2); }
Expand All @@ -1320,12 +1327,6 @@ expr:
| T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
| T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
| T_YIELD_FROM expr { $$ = zend_ast_create(ZEND_AST_YIELD_FROM, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
| T_CONTINUE { $$ = zend_ast_create(ZEND_AST_CONTINUE, NULL); }
| T_CONTINUE expr { $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); }
| T_BREAK { $$ = zend_ast_create(ZEND_AST_BREAK, NULL); }
| T_BREAK expr { $$ = zend_ast_create(ZEND_AST_BREAK, $2); }
| T_RETURN { $$ = zend_ast_create(ZEND_AST_RETURN, NULL); }
| T_RETURN expr { $$ = zend_ast_create(ZEND_AST_RETURN, $2); }
| T_THROW expr { $$ = zend_ast_create(ZEND_AST_THROW, $2); }
| inline_function { $$ = $1; }
| attributes inline_function { $$ = zend_ast_with_attributes($2, $1); }
Expand All @@ -1335,6 +1336,15 @@ expr:
| match { $$ = $1; }
;

early_return:
T_RETURN { $$ = zend_ast_create(ZEND_AST_RETURN, NULL); }
| T_RETURN expr { $$ = zend_ast_create(ZEND_AST_RETURN, $2); }
| T_BREAK { $$ = zend_ast_create(ZEND_AST_BREAK, NULL); }
| T_BREAK expr { $$ = zend_ast_create(ZEND_AST_BREAK, $2); }
| T_CONTINUE { $$ = zend_ast_create(ZEND_AST_CONTINUE, NULL); }
| T_CONTINUE expr { $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); }
;


inline_function:
function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type
Expand Down
4 changes: 1 addition & 3 deletions tests/lang/early-return/001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ Early break
function test($a,$b) {
$b ?? return 0;
$a ?: return 1;
$c = $a <= 0 ? return "negative" : $a*2;

return 2;
}
echo test(1, null);
echo test(0, 1);
echo test(-1, 1);
echo test(3, 1);
?>
--EXPECT--
01negative2
012
2 changes: 1 addition & 1 deletion tests/lang/early-return/003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ echo PHP_EOL;
function test2(int $v, int $stop) {
while (true) {
$v-- ?: return $v;
$stop === $v ? return $v : continue;
$stop !== $v ?: return $v;
}
return 'never here';
}
Expand Down
30 changes: 30 additions & 0 deletions tests/lang/early-return/early-return1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
Memory leaks
--FILE--
<?php
function test($input = null, $fallback = 'fallback') {
$return = $input ?: return $fallback;
var_dump($return);
}
function test2($input = null, $fallback = 'fallback') {
$return = $input ?? return $fallback;
var_dump($return);
}

echo test('hello');
echo test(false, 'false');
echo test(null, 'null');

echo PHP_EOL;

echo test2('world');
echo test2(false, 'false');
echo test2(null, 'null');

?>
--EXPECT--
string(5) "hello"
falsenull
string(5) "world"
bool(false)
null
62 changes: 0 additions & 62 deletions tests/lang/early-return/match.phpt

This file was deleted.

15 changes: 0 additions & 15 deletions tests/lang/early-return/memory_leaks.phpt

This file was deleted.

7 changes: 1 addition & 6 deletions tests/lang/loops/break_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ for($i = 5; $i >= 0; $i--) {
}
echo $i;
}
echo PHP_EOL;

// new way break
for($i = 5; $i >= 0; $i--) {
$i < 3 ? break : null;
echo $i;
}
echo PHP_EOL;
for($i = 5; $i >= 0; $i--) {
$i > 3 ?: break;
Expand All @@ -34,6 +30,5 @@ for($i = 5; $i >= 0; $i--) {
--EXPECTF--
543210
543
543
54
54321
7 changes: 1 addition & 6 deletions tests/lang/loops/continue_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ for($i = 5; $i >= 0; $i--) {
}
echo $i;
}
echo PHP_EOL;

// new way continue
for($i = 5; $i >= 0; $i--) {
$i < 3 ? continue : null;
echo $i;
}
echo PHP_EOL;
for($i = 5; $i >= 0; $i--) {
$i > 3 ?: continue;
Expand All @@ -34,6 +30,5 @@ for($i = 5; $i >= 0; $i--) {
--EXPECT--
543210
543
543
54
54321
Loading