Skip to content

Commit 9fa1d13

Browse files
committed
Implement match expression
RFC: https://wiki.php.net/rfc/match_expression_v2 Closes GH-5371.
1 parent c60d0dc commit 9fa1d13

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2442
-619
lines changed

UPGRADING

+2
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ PHP 8.0 UPGRADE NOTES
571571
. Added support for constructor property promotion (declaring properties in
572572
the constructor signature).
573573
RFC: https://wiki.php.net/rfc/constructor_promotion
574+
. Added support for `match` expression.
575+
RFC: https://wiki.php.net/rfc/match_expression_v2
574576

575577
- Date:
576578
. Added DateTime::createFromInterface() and

Zend/tests/match/001.phpt

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Basic match expression functionality test
3+
--FILE--
4+
<?php
5+
6+
function wordify($x) {
7+
return match ($x) {
8+
0 => 'Zero',
9+
1 => 'One',
10+
2 => 'Two',
11+
3 => 'Three',
12+
4 => 'Four',
13+
5 => 'Five',
14+
6 => 'Six',
15+
7 => 'Seven',
16+
8 => 'Eight',
17+
9 => 'Nine',
18+
};
19+
}
20+
21+
for ($i = 0; $i <= 9; $i++) {
22+
print wordify($i) . "\n";
23+
}
24+
25+
?>
26+
--EXPECT--
27+
Zero
28+
One
29+
Two
30+
Three
31+
Four
32+
Five
33+
Six
34+
Seven
35+
Eight
36+
Nine

Zend/tests/match/002.phpt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Match expression omit trailing comma
3+
--FILE--
4+
<?php
5+
6+
function print_bool($bool) {
7+
echo match ($bool) {
8+
true => "true\n",
9+
false => "false\n"
10+
};
11+
}
12+
13+
print_bool(true);
14+
print_bool(false);
15+
16+
?>
17+
--EXPECT--
18+
true
19+
false

Zend/tests/match/003.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Match expression default case
3+
--FILE--
4+
<?php
5+
6+
function get_value($i) {
7+
return match ($i) {
8+
1 => 1,
9+
2 => 2,
10+
default => 'default',
11+
};
12+
}
13+
14+
echo get_value(0) . "\n";
15+
echo get_value(1) . "\n";
16+
echo get_value(2) . "\n";
17+
echo get_value(3) . "\n";
18+
19+
?>
20+
--EXPECT--
21+
default
22+
1
23+
2
24+
default

Zend/tests/match/004.phpt

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Match expression with true as expression
3+
--FILE--
4+
<?php
5+
6+
function get_range($i) {
7+
return match (true) {
8+
$i >= 50 => '50+',
9+
$i >= 40 => '40-50',
10+
$i >= 30 => '30-40',
11+
$i >= 20 => '20-30',
12+
$i >= 10 => '10-20',
13+
default => '0-10',
14+
};
15+
}
16+
17+
echo get_range(22) . "\n";
18+
echo get_range(0) . "\n";
19+
echo get_range(59) . "\n";
20+
echo get_range(13) . "\n";
21+
echo get_range(39) . "\n";
22+
echo get_range(40) . "\n";
23+
24+
?>
25+
--EXPECT--
26+
20-30
27+
0-10
28+
50+
29+
10-20
30+
30-40
31+
40-50

Zend/tests/match/005.phpt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Match expression discarding result
3+
--FILE--
4+
<?php
5+
6+
match (1) {
7+
1 => print "Executed\n",
8+
};
9+
10+
?>
11+
--EXPECT--
12+
Executed

Zend/tests/match/006.phpt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Match expression with no cases
3+
--FILE--
4+
<?php
5+
6+
$x = match (true) {};
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type bool in %s
11+
Stack trace:
12+
#0 {main}
13+
thrown in %s on line %d

Zend/tests/match/007.phpt

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Match expression exception on unhandled case
3+
--FILE--
4+
<?php
5+
6+
function get_value($i) {
7+
return match ($i) {
8+
1 => 1,
9+
2 => 2,
10+
};
11+
}
12+
13+
echo get_value(1) . "\n";
14+
echo get_value(2) . "\n";
15+
echo get_value(3) . "\n";
16+
17+
?>
18+
--EXPECTF--
19+
1
20+
2
21+
22+
Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type int in %s
23+
Stack trace:
24+
#0 %s: get_value(3)
25+
#1 {main}
26+
thrown in %s on line %d

Zend/tests/match/008.phpt

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Match expression multiple conditions per case
3+
--FILE--
4+
<?php
5+
6+
function is_working_day($day) {
7+
return match ($day) {
8+
1, 7 => false,
9+
2, 3, 4, 5, 6 => true,
10+
};
11+
}
12+
13+
for ($i = 1; $i <= 7; $i++) {
14+
var_dump(is_working_day($i));
15+
}
16+
17+
?>
18+
--EXPECT--
19+
bool(false)
20+
bool(true)
21+
bool(true)
22+
bool(true)
23+
bool(true)
24+
bool(true)
25+
bool(false)

Zend/tests/match/009.phpt

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Pretty printing for match expression
3+
--FILE--
4+
<?php
5+
6+
assert((function () {
7+
match ('foo') {
8+
'foo', 'bar' => false,
9+
'baz' => 'a',
10+
default => 'b',
11+
};
12+
})());
13+
14+
?>
15+
--EXPECTF--
16+
Warning: assert(): assert(function () {
17+
match ('foo') {
18+
'foo', 'bar' => false,
19+
'baz' => 'a',
20+
default => 'b',
21+
};
22+
}()) failed in %s on line %d

Zend/tests/match/011.phpt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Implicit break in match expression
3+
--FILE--
4+
<?php
5+
6+
function dump_and_return($string) {
7+
var_dump($string);
8+
return $string;
9+
}
10+
11+
var_dump(match ('foo') {
12+
'foo' => dump_and_return('foo'),
13+
'bar' => dump_and_return('bar'),
14+
});
15+
16+
?>
17+
--EXPECT--
18+
string(3) "foo"
19+
string(3) "foo"

Zend/tests/match/012.phpt

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Strict comparison in match expression
3+
--FILE--
4+
<?php
5+
6+
function wrong() {
7+
throw new Exception();
8+
}
9+
10+
var_dump(match (0) {
11+
null => wrong(),
12+
false => wrong(),
13+
0.0 => wrong(),
14+
[] => wrong(),
15+
'' => wrong(),
16+
0 => 'int',
17+
});
18+
19+
function get_value() {
20+
return 0;
21+
}
22+
23+
var_dump(match (get_value()) {
24+
null => wrong(),
25+
false => wrong(),
26+
0.0 => wrong(),
27+
[] => wrong(),
28+
'' => wrong(),
29+
0 => 'int',
30+
default => 'default',
31+
});
32+
33+
?>
34+
--EXPECT--
35+
string(3) "int"
36+
string(3) "int"

Zend/tests/match/017.phpt

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
--TEST--
2+
Test strict comparison with match expression jump table
3+
--FILE--
4+
<?php
5+
6+
function wrong() {
7+
throw new Exception();
8+
}
9+
10+
function test_int($char) {
11+
return match ($char) {
12+
0 => wrong(),
13+
1 => wrong(),
14+
2 => wrong(),
15+
3 => wrong(),
16+
4 => wrong(),
17+
5 => wrong(),
18+
6 => wrong(),
19+
7 => wrong(),
20+
8 => wrong(),
21+
9 => wrong(),
22+
default => 'Not matched',
23+
};
24+
}
25+
26+
foreach (range(0, 9) as $int) {
27+
var_dump((string) $int);
28+
var_dump(test_int((string) $int));
29+
}
30+
31+
function test_string($int) {
32+
return match ($int) {
33+
'0' => wrong(),
34+
'1' => wrong(),
35+
'2' => wrong(),
36+
'3' => wrong(),
37+
'4' => wrong(),
38+
'5' => wrong(),
39+
'6' => wrong(),
40+
'7' => wrong(),
41+
'8' => wrong(),
42+
'9' => wrong(),
43+
default => 'Not matched',
44+
};
45+
}
46+
47+
foreach (range(0, 9) as $int) {
48+
var_dump($int);
49+
var_dump(test_string($int));
50+
}
51+
52+
--EXPECT--
53+
string(1) "0"
54+
string(11) "Not matched"
55+
string(1) "1"
56+
string(11) "Not matched"
57+
string(1) "2"
58+
string(11) "Not matched"
59+
string(1) "3"
60+
string(11) "Not matched"
61+
string(1) "4"
62+
string(11) "Not matched"
63+
string(1) "5"
64+
string(11) "Not matched"
65+
string(1) "6"
66+
string(11) "Not matched"
67+
string(1) "7"
68+
string(11) "Not matched"
69+
string(1) "8"
70+
string(11) "Not matched"
71+
string(1) "9"
72+
string(11) "Not matched"
73+
int(0)
74+
string(11) "Not matched"
75+
int(1)
76+
string(11) "Not matched"
77+
int(2)
78+
string(11) "Not matched"
79+
int(3)
80+
string(11) "Not matched"
81+
int(4)
82+
string(11) "Not matched"
83+
int(5)
84+
string(11) "Not matched"
85+
int(6)
86+
string(11) "Not matched"
87+
int(7)
88+
string(11) "Not matched"
89+
int(8)
90+
string(11) "Not matched"
91+
int(9)
92+
string(11) "Not matched"

Zend/tests/match/023.phpt

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Test match strict comparison with true expression
3+
--FILE--
4+
<?php
5+
6+
function wrong() {
7+
throw new Exception();
8+
}
9+
10+
echo match (true) {
11+
'truthy' => wrong(),
12+
['truthy'] => wrong(),
13+
new stdClass() => wrong(),
14+
1 => wrong(),
15+
1.0 => wrong(),
16+
true => "true\n",
17+
};
18+
19+
--EXPECT--
20+
true

0 commit comments

Comments
 (0)