Skip to content

[RFC] Implement match blocks #11933

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

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
21 changes: 21 additions & 0 deletions Zend/tests/block_expr/coalesce.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
Coalesce block
--FILE--
<?php
$x = null;
$y = $x ?? {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is

$x = {
  echo "test\n";
  null
};

also possible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not in this PR. Please read the RFC, the rationale is explained there. https://wiki.php.net/rfc/match_blocks#why_not_language-level_blocks

echo "Executed\n";
42
};
var_dump($y);

$x = 42;
$y = $x ?? {
echo "Never executed\n";
};
var_dump($y);
?>
--EXPECT--
Executed
int(42)
int(42)
21 changes: 21 additions & 0 deletions Zend/tests/block_expr/coalesce_assign.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
Coalesce assignment block
--FILE--
<?php
$x = null;
$x ??= {
echo "Executed\n";
42
};
var_dump($x);

$x = 42;
$x ??= {
echo "Never executed\n";
};
var_dump($x);
?>
--EXPECT--
Executed
int(42)
int(42)
10 changes: 10 additions & 0 deletions Zend/tests/match/block_arg_return.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
Match expression block must not use return
--FILE--
<?php
foo(match (1) {
1 => { return; }
});
?>
--EXPECTF--
Fatal error: Match expression whose result is used must not contain return, break, continue or goto in %s on line %d
35 changes: 35 additions & 0 deletions Zend/tests/match/block_basic.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
Basic match blocks
--FILE--
<?php
function foo() {
echo "foo()\n";
}

function bar() {
return 3;
}

function test($value) {
var_dump(match ($value) {
1 => { 1 },
2 => {
$x = 2;
$x
},
3 => {
foo();
bar()
},
});
}

test(1);
test(2);
test(3);
?>
--EXPECT--
int(1)
int(2)
foo()
int(3)
10 changes: 10 additions & 0 deletions Zend/tests/match/block_expr_break_escape.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
Match expression block must not use break
--FILE--
<?php
var_dump(match ($value) {
1 => { break; },
});
?>
--EXPECTF--
Fatal error: Match expression whose result is used must not contain return, break, continue or goto in %s on line %d
17 changes: 17 additions & 0 deletions Zend/tests/match/block_expr_break_no_escape.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
Match expression block may use break if block is not escaped
--FILE--
<?php
var_dump(match (1) {
1 => {
foreach ([1, 2, 3] as $value) {
echo $value, "\n";
break;
}
42
},
});
?>
--EXPECT--
1
int(42)
13 changes: 13 additions & 0 deletions Zend/tests/match/block_expr_goto_escape.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Match expression block must not use goto
--FILE--
<?php
var_dump(match (1) {
1 => {
goto after;
},
});
after:
?>
--EXPECTF--
Fatal error: Match expression whose result is used must not contain return, break, continue or goto in %s on line %d
14 changes: 14 additions & 0 deletions Zend/tests/match/block_expr_goto_into.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
May not goto into match expression block
--FILE--
<?php
goto in;
var_dump(match (1) {
1 => {
in:
42
},
});
?>
--EXPECTF--
Fatal error: 'goto' into loop or switch statement is disallowed in %s on line %d
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message should mention “match”.

20 changes: 20 additions & 0 deletions Zend/tests/match/block_expr_no_result.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Match expression block must return a value
--FILE--
<?php
function test() {
var_dump(match (1) {
1 => {
echo "Not returning anything\n";
},
});
}
try {
test();
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Not returning anything
NULL
10 changes: 10 additions & 0 deletions Zend/tests/match/block_expr_return.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
Match expression block must not use return
--FILE--
<?php
var_dump(match ($value) {
1 => { return; },
});
?>
--EXPECTF--
Fatal error: Match expression whose result is used must not contain return, break, continue or goto in %s on line %d
20 changes: 20 additions & 0 deletions Zend/tests/match/block_expr_throw.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Throwing match expression block must clean up live-vars
--FILE--
<?php

function throw_($value) {
var_dump([new \stdClass] + match ($value) {
1 => { throw new Exception('Exception with live var'); },
});
}

try {
throw_(1);
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}

?>
--EXPECT--
Exception with live var
16 changes: 16 additions & 0 deletions Zend/tests/match/block_stmt_break_escape.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
Match statement block may break out of block
--FILE--
<?php
match (1) {
1 => {
echo "Before break\n";
break;
echo "After break\n";
},
};
echo "After match\n";
?>
--EXPECT--
Before break
After match
17 changes: 17 additions & 0 deletions Zend/tests/match/block_stmt_continue_escape.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
Match statement block may continue out of block, with a warning
--FILE--
<?php
match (1) {
1 => {
echo "Before continue\n";
continue;
echo "After continue\n";
},
};
echo "After match\n";
?>
--EXPECTF--
Warning: "continue" targeting switch is equivalent to "break" in %s on line %d
Before continue
After match
17 changes: 17 additions & 0 deletions Zend/tests/match/block_stmt_goto_escape.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
May escape match statement block with goto
--FILE--
<?php
match (1) {
1 => {
echo "Before goto\n";
goto after;
echo "After goto\n";
},
};
after:
echo "After match\n";
?>
--EXPECT--
Before goto
After match
14 changes: 14 additions & 0 deletions Zend/tests/match/block_stmt_goto_into.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
May not goto into match statement block
--FILE--
<?php
goto in;
match (1) {
1 => {
in:
echo "Inside match block\n";
},
};
?>
--EXPECTF--
Fatal error: 'goto' into loop or switch statement is disallowed in %s on line %d
11 changes: 11 additions & 0 deletions Zend/tests/match/block_stmt_with_result.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
Match statement block must not return a value
--FILE--
<?php
match (1) {
1 => { new stdClass },
};
?>
===DONE===
--EXPECT--
===DONE===
1 change: 1 addition & 0 deletions Zend/zend_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ enum _zend_ast_kind {
ZEND_AST_ATTRIBUTE,
ZEND_AST_MATCH,
ZEND_AST_MATCH_ARM,
ZEND_AST_BLOCK_EXPR,
ZEND_AST_NAMED_ARG,

/* 3 child nodes */
Expand Down
Loading