Skip to content

Commit 566744f

Browse files
committed
Implement pattern matching
1 parent 1f48715 commit 566744f

Some content is hidden

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

43 files changed

+2152
-571
lines changed

Zend/tests/numeric_literal_separator_002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ Invalid use: trailing underscore
55
100_;
66
?>
77
--EXPECTF--
8-
Parse error: syntax error, unexpected identifier "_" in %s on line %d
8+
Parse error: syntax error, unexpected token "_" in %s on line %d

Zend/tests/numeric_literal_separator_004.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ Invalid use: underscore left of period
55
100_.0;
66
?>
77
--EXPECTF--
8-
Parse error: syntax error, unexpected identifier "_" in %s on line %d
8+
Parse error: syntax error, unexpected token "_" in %s on line %d
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: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
var_dump(10 is $a);
19+
var_dump($a);
20+
21+
var_dump('Hello world' is $a);
22+
var_dump($a);
23+
24+
var_dump(new Box(42) is Box { value: $a });
25+
var_dump($a);
26+
27+
var_dump(new NotBox(43) is Box { value: $a });
28+
var_dump($a);
29+
30+
var_dump(43 is $a @ int);
31+
var_dump($a);
32+
33+
var_dump([] is $a @ string);
34+
var_dump($a);
35+
36+
?>
37+
--EXPECT--
38+
bool(true)
39+
int(10)
40+
bool(true)
41+
string(11) "Hello world"
42+
bool(true)
43+
int(42)
44+
bool(false)
45+
int(42)
46+
bool(true)
47+
int(43)
48+
bool(false)
49+
int(43)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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 or $bar;
17+
} catch (Exception $e) {
18+
echo $e->getMessage(), "\n";
19+
}
20+
21+
// FIXME: This will change once bindings are delayed
22+
var_dump($foo);
23+
var_dump($bar);
24+
25+
?>
26+
--EXPECT--
27+
Here
28+
int(42)
29+
string(3) "bar"
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
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
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
Delayed binding
3+
--FILE--
4+
<?php
5+
6+
class Pair {
7+
public function __construct(public $a, public $b) {}
8+
}
9+
10+
var_dump(new Pair(1, 2) is Pair { a: $a, b: $b });
11+
var_dump($a, $b);
12+
unset($a, $b);
13+
14+
var_dump(new Pair(1, 2) is Pair { a: $a, b: 3 });
15+
var_dump($a, $b);
16+
unset($a, $b);
17+
18+
var_dump(new Pair(new \stdClass(), 2) is Pair { a: $a, b: 2 });
19+
var_dump($a, $b);
20+
unset($a, $b);
21+
22+
var_dump(new Pair(new \stdClass(), 2) is Pair { a: $a, b: 3 });
23+
var_dump($a, $b);
24+
unset($a, $b);
25+
26+
?>
27+
--EXPECTF--
28+
bool(true)
29+
int(1)
30+
int(2)
31+
bool(false)
32+
33+
Warning: Undefined variable $a in %s on line %d
34+
35+
Warning: Undefined variable $b in %s on line %d
36+
NULL
37+
NULL
38+
bool(true)
39+
40+
Warning: Undefined variable $b in %s on line %d
41+
object(stdClass)#2 (0) {
42+
}
43+
NULL
44+
bool(false)
45+
46+
Warning: Undefined variable $a in %s on line %d
47+
48+
Warning: Undefined variable $b in %s on line %d
49+
NULL
50+
NULL

0 commit comments

Comments
 (0)