diff --git a/ChangeLog.md b/ChangeLog.md index a2b75c5d..7b907256 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,15 @@ XP Compiler ChangeLog ## ?.?.? / ????-??-?? +## 9.3.2 / 2024-11-02 + +* Fixed empty match expressions and match expressions with default + case only in PHP 7 + (@thekid) +* Added tests verifying closures are supported in constant expressions + https://wiki.php.net/rfc/closures_in_const_expr + (@thekid) + ## 9.3.1 / 2024-10-05 * Fixed `private(set)` not being implicitely marked as *final*, see diff --git a/src/main/php/lang/ast/emit/MatchAsTernaries.class.php b/src/main/php/lang/ast/emit/MatchAsTernaries.class.php index 6d6da1df..9e82693d 100755 --- a/src/main/php/lang/ast/emit/MatchAsTernaries.class.php +++ b/src/main/php/lang/ast/emit/MatchAsTernaries.class.php @@ -30,9 +30,12 @@ protected function emitMatch($result, $match) { } } + // Match without cases => create something that will never match + $b || $result->out->write('===NAN?:'); + // Emit IIFE for raising an error until we have throw expressions if (null === $match->default) { - $result->out->write('function() use('.$t.') { throw new \\Error("Unhandled match value of type ".gettype('.$t.')); })('); + $result->out->write('(function() use('.$t.') { throw new \\Error("Unhandled match value of type ".gettype('.$t.')); })()'); } else { $this->emitAsExpression($result, $match->default); } diff --git a/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php b/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php index 81cb042b..299374a0 100755 --- a/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php @@ -86,6 +86,19 @@ public function run($arg) { Assert::equals($expected, $r); } + #[Test] + public function match_with_default_only() { + $r= $this->run('class %T { + public function run() { + return match (true) { + default => "Test", + }; + } + }'); + + Assert::equals('Test', $r); + } + #[Test, Values([[200, 'OK'], [302, 'Redirect'], [404, 'Error #404']])] public function match_with_multiple_cases($input, $expected) { $r= $this->run('class %T { @@ -154,6 +167,17 @@ public function run($arg) { Assert::equals('10+ items', $r); } + #[Test, Expect(class: Throwable::class, message: '/Unhandled match (value of type .+|case .+)/')] + public function empty_match() { + $r= $this->run('class %T { + public function run() { + return match (true) { }; + } + }'); + + Assert::equals('Test', $r); + } + #[Test, Expect(class: Throwable::class, message: '/Unhandled match (value of type .+|case .+)/')] public function unhandled_match() { $this->run('class %T {