Skip to content

Commit 8c25a23

Browse files
committed
Implement pattern matching
1 parent e95b298 commit 8c25a23

Some content is hidden

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

42 files changed

+2187
-570
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
And pattern
3+
--FILE--
4+
<?php
5+
6+
interface A {}
7+
interface B {}
8+
interface C {}
9+
class Foo implements A, B {}
10+
11+
var_dump(1 is int & 1);
12+
var_dump(2 is int & (1|2));
13+
var_dump(3 is float & 1);
14+
var_dump(4 is int & float);
15+
var_dump([] is [] & [...]);
16+
var_dump('foo' is string & 'bar');
17+
var_dump(new Foo() is A&B);
18+
var_dump(new Foo() is (A&C));
19+
20+
?>
21+
--EXPECT--
22+
bool(true)
23+
bool(true)
24+
bool(false)
25+
bool(false)
26+
bool(true)
27+
bool(false)
28+
bool(true)
29+
bool(false)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Array pattern
3+
--FILE--
4+
<?php
5+
6+
var_dump([] is []);
7+
var_dump(42 is []);
8+
var_dump('foo' is []);
9+
var_dump([42] is [42]);
10+
var_dump([42] is []);
11+
var_dump([42] is [43]);
12+
var_dump([42] is ['0' => 42]);
13+
var_dump([42, 43] is [42]);
14+
var_dump([42, 43] is [42, ...]);
15+
var_dump([42] is [$a]);
16+
var_dump($a);
17+
18+
?>
19+
--EXPECT--
20+
bool(true)
21+
bool(false)
22+
bool(false)
23+
bool(true)
24+
bool(false)
25+
bool(false)
26+
bool(true)
27+
bool(false)
28+
bool(true)
29+
bool(true)
30+
int(42)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Array pattern with mixed implicit and explicit keys
3+
--FILE--
4+
<?php
5+
6+
var_dump([] is ['foo', 1 => 'bar']);
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Must not mix implicit and explicit array keys in array pattern in %s on line %d
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
Object pattern matching
3+
--FILE--
4+
<?php
5+
6+
$o = new stdClass();
7+
8+
try {
9+
var_dump($o is self {});
10+
} catch (Throwable $e) {
11+
echo $e->getMessage(), "\n";
12+
}
13+
14+
try {
15+
var_dump($o is parent {});
16+
} catch (Throwable $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
20+
try {
21+
var_dump($o is static {});
22+
} catch (Throwable $e) {
23+
echo $e->getMessage(), "\n";
24+
}
25+
26+
class C {
27+
public static function test($o) {
28+
try {
29+
var_dump($o is parent {});
30+
} catch (Throwable $e) {
31+
echo $e->getMessage(), "\n";
32+
}
33+
}
34+
}
35+
36+
C::test($o);
37+
38+
?>
39+
--EXPECT--
40+
Cannot access "self" when no class scope is active
41+
Cannot access "parent" when no class scope is active
42+
Cannot access "static" when no class scope is active
43+
Cannot access "parent" when current class scope has no parent
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
--TEST--
2+
Binding pattern
3+
--FILE--
4+
<?php
5+
6+
class Box {
7+
public function __construct(
8+
public $value,
9+
) {}
10+
}
11+
12+
class NotBox {
13+
public function __construct(
14+
public $value,
15+
) {}
16+
}
17+
18+
class Many {
19+
public function __construct(
20+
public $a = 1,
21+
public $b = 2,
22+
public $c = 3,
23+
public $d = 4,
24+
public $e = 5,
25+
public $f = 6,
26+
public $g = 7,
27+
public $h = 8,
28+
public $i = 9,
29+
public $j = 10,
30+
) {}
31+
}
32+
33+
var_dump(10 is $a);
34+
var_dump($a);
35+
36+
var_dump('Hello world' is $a);
37+
var_dump($a);
38+
39+
var_dump(new Box(42) is Box { value: $a });
40+
var_dump($a);
41+
42+
var_dump(new NotBox(43) is Box { value: $a });
43+
var_dump($a);
44+
45+
var_dump(43 is $a @ int);
46+
var_dump($a);
47+
48+
var_dump([] is $a @ string);
49+
var_dump($a);
50+
51+
var_dump(new Many() is Many { $a, $b, $c, $d });
52+
var_dump($a, $b, $c, $d, isset($e));
53+
54+
var_dump(new Many() is Many { $a, $b, $c, $d, $e, $f, $g, $h, $i, $j });
55+
var_dump($a, $b, $c, $d, $e, $f, $g, $h, $i, $j);
56+
57+
?>
58+
--EXPECT--
59+
bool(true)
60+
int(10)
61+
bool(true)
62+
string(11) "Hello world"
63+
bool(true)
64+
int(42)
65+
bool(false)
66+
int(42)
67+
bool(true)
68+
int(43)
69+
bool(false)
70+
int(43)
71+
bool(true)
72+
int(1)
73+
int(2)
74+
int(3)
75+
int(4)
76+
bool(false)
77+
bool(true)
78+
int(1)
79+
int(2)
80+
int(3)
81+
int(4)
82+
int(5)
83+
int(6)
84+
int(7)
85+
int(8)
86+
int(9)
87+
int(10)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Object pattern matching destructor
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
public function __destruct() {
8+
throw new Exception('Here');
9+
}
10+
}
11+
12+
$foo = new Foo();
13+
$bar = 'bar';
14+
15+
try {
16+
42 is $foo & $bar;
17+
} catch (Exception $e) {
18+
echo $e->getMessage(), "\n";
19+
}
20+
21+
var_dump($foo);
22+
var_dump($bar);
23+
24+
?>
25+
--EXPECT--
26+
Here
27+
int(42)
28+
int(42)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Must not bind to variables in | pattern
3+
--FILE--
4+
<?php
5+
var_dump(42 is $foo|$bar);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Must not bind to variables inside | pattern in %s on line %d
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Must not bind to variables in | pattern
3+
--FILE--
4+
<?php
5+
var_dump(42 is 42|(43 & $bar));
6+
?>
7+
--EXPECTF--
8+
Fatal error: Must not bind to variables inside | pattern in %s on line %d
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
Class constant pattern
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
const A = 'a';
8+
private const B = 'b';
9+
10+
public static function test() {
11+
var_dump('b' is self::B);
12+
var_dump('c' is self::B);
13+
}
14+
}
15+
enum Bar {
16+
case A;
17+
}
18+
19+
var_dump('a' is Foo::A);
20+
var_dump('b' is Foo::A);
21+
try {
22+
var_dump('a' is Foo::B);
23+
} catch (Error $e) {
24+
echo $e->getMessage(), "\n";
25+
}
26+
try {
27+
var_dump('a' is Foo::C);
28+
} catch (Error $e) {
29+
echo $e->getMessage(), "\n";
30+
}
31+
Foo::test();
32+
var_dump(Bar::A is Bar::A);
33+
var_dump('foo' is Bar::A);
34+
35+
?>
36+
--EXPECT--
37+
bool(true)
38+
bool(false)
39+
Cannot access private constant Foo::B
40+
Undefined constant Foo::C
41+
bool(true)
42+
bool(false)
43+
bool(true)
44+
bool(false)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Nested compound patterns require parentheses
3+
--FILE--
4+
<?php
5+
var_dump(42 is Foo|Bar&Baz);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Nested compound pattern must be parenthesized in %s on line %d

0 commit comments

Comments
 (0)