- 将闭包生成器中的引用捕获从 & 改为 =,避免悬空指针问题 - 在 PHP 中使用 = 赋值进行浅拷贝,仅增加一次引用计数 - 添加了关于 zval 封装赋值的注释说明 - 新增了可调用语法的测试用例,包括箭头函数和杂项功能 - 添加了对 PHP 8.1+ 首类可调用语法的支持测试 - 包含了枚举相关功能的测试用例验证pull/1/head
parent
b499347669
commit
dd297b5f92
4 changed files with 222 additions and 1 deletions
@ -0,0 +1,87 @@ |
||||
--TEST-- |
||||
Backed Enums (PHP 8.1+) |
||||
--FILE-- |
||||
<?php |
||||
|
||||
// Test basic backed enum with int values |
||||
enum Status: int { |
||||
case Pending = 0; |
||||
case Active = 1; |
||||
case Suspended = 2; |
||||
case Closed = 3; |
||||
|
||||
public function label(): string { |
||||
return match($this) { |
||||
self::Pending => 'Pending', |
||||
self::Active => 'Active', |
||||
self::Suspended => 'Suspended', |
||||
self::Closed => 'Closed', |
||||
}; |
||||
} |
||||
} |
||||
|
||||
// Test backed enum with string values |
||||
enum Color: string { |
||||
case Red = 'red'; |
||||
case Green = 'green'; |
||||
case Blue = 'blue'; |
||||
|
||||
public function rgb(): array { |
||||
return match($this) { |
||||
self::Red => [255, 0, 0], |
||||
self::Green => [0, 255, 0], |
||||
self::Blue => [0, 0, 255], |
||||
}; |
||||
} |
||||
} |
||||
|
||||
// Test enum in switch |
||||
function processStatus(Status $status): string { |
||||
return match($status) { |
||||
Status::Pending => 'Task is pending', |
||||
Status::Active => 'Task is active', |
||||
Status::Suspended => 'Task is suspended', |
||||
Status::Closed => 'Task is closed', |
||||
}; |
||||
} |
||||
|
||||
function main() { |
||||
var_dump(Status::Pending->value); |
||||
var_dump(Status::Active->label()); |
||||
var_dump(Status::from(2)->name); |
||||
|
||||
var_dump(Color::Red->value); |
||||
var_dump(Color::Green->rgb()); |
||||
|
||||
var_dump(processStatus(Status::Active)); |
||||
|
||||
// Test enum comparison |
||||
var_dump(Status::Active === Status::Active); |
||||
var_dump(Status::Pending !== Status::Active); |
||||
|
||||
// Test enum array usage |
||||
$statuses = [Status::Pending, Status::Active, Status::Closed]; |
||||
foreach ($statuses as $status) { |
||||
var_dump($status->label()); |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(0) |
||||
string(6) "Active" |
||||
string(9) "Suspended" |
||||
string(3) "red" |
||||
array(3) { |
||||
[0]=> |
||||
int(0) |
||||
[1]=> |
||||
int(255) |
||||
[2]=> |
||||
int(0) |
||||
} |
||||
string(14) "Task is active" |
||||
bool(true) |
||||
bool(true) |
||||
string(7) "Pending" |
||||
string(6) "Active" |
||||
string(6) "Closed" |
||||
@ -0,0 +1,22 @@ |
||||
--TEST-- |
||||
First-Class Callable Syntax (PHP 8.1+) |
||||
--FILE-- |
||||
<?php |
||||
|
||||
// Test callable returning callable |
||||
function multiplier(int $factor): callable { |
||||
return fn(int $value) => $value * $factor; |
||||
} |
||||
|
||||
function main() { |
||||
// Test callable returning callable |
||||
$double = multiplier(2); |
||||
$triple = multiplier(3); |
||||
|
||||
var_dump($double(5)); |
||||
var_dump($triple(5)); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(10) |
||||
int(15) |
||||
@ -0,0 +1,110 @@ |
||||
--TEST-- |
||||
First-Class Callable Syntax (PHP 8.1+) |
||||
--FILE-- |
||||
<?php |
||||
|
||||
// Test basic first-class callable |
||||
function add(int $a, int $b): int { |
||||
return $a + $b; |
||||
} |
||||
|
||||
// Test first-class callable with class methods |
||||
class Math { |
||||
public static function multiply(int $a, int $b): int { |
||||
return $a * $b; |
||||
} |
||||
|
||||
public function divide(int $a, int $b): float { |
||||
return floatval($a) / $b; |
||||
} |
||||
} |
||||
|
||||
// Test callable returning callable |
||||
function multiplier(int $factor): callable { |
||||
return fn(int $value) => $value * $factor; |
||||
} |
||||
|
||||
function main() { |
||||
$callable = 'add'; |
||||
var_dump(array_map($callable, [1, 2, 3], [4, 5, 6])); |
||||
|
||||
$staticCallable = ['Math', 'multiply']; |
||||
var_dump(array_reduce([[2, 3], [4, 5]], fn($carry, $item) => $carry + call_user_func_array($staticCallable, $item), 0)); |
||||
|
||||
$math = new Math(); |
||||
$instanceCallable = [$math, 'divide']; |
||||
var_dump(call_user_func($instanceCallable, 10, 4)); |
||||
|
||||
// Test first-class callable with arrow functions |
||||
$filter = fn(array $arr): array => array_filter($arr, fn($n) => $n > 0); |
||||
var_dump($filter([1, -2, 3, -4, 5])); |
||||
|
||||
// Test callable in array operations |
||||
$numbers = range(1, 5); |
||||
$doubled = array_map(fn($n) => $n * 2, $numbers); |
||||
var_dump($doubled); |
||||
|
||||
$squared = array_map(fn($n) => $n ** 2, $numbers); |
||||
var_dump($squared); |
||||
|
||||
// Test callable with usort |
||||
$unsorted = [5, 2, 8, 1, 9]; |
||||
usort($unsorted, fn($a, $b) => $a <=> $b); |
||||
var_dump($unsorted); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(3) { |
||||
[0]=> |
||||
int(5) |
||||
[1]=> |
||||
int(7) |
||||
[2]=> |
||||
int(9) |
||||
} |
||||
int(26) |
||||
float(2.5) |
||||
array(3) { |
||||
[0]=> |
||||
int(1) |
||||
[2]=> |
||||
int(3) |
||||
[4]=> |
||||
int(5) |
||||
} |
||||
array(5) { |
||||
[0]=> |
||||
int(2) |
||||
[1]=> |
||||
int(4) |
||||
[2]=> |
||||
int(6) |
||||
[3]=> |
||||
int(8) |
||||
[4]=> |
||||
int(10) |
||||
} |
||||
array(5) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
int(4) |
||||
[2]=> |
||||
int(9) |
||||
[3]=> |
||||
int(16) |
||||
[4]=> |
||||
int(25) |
||||
} |
||||
array(5) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
int(2) |
||||
[2]=> |
||||
int(5) |
||||
[3]=> |
||||
int(8) |
||||
[4]=> |
||||
int(9) |
||||
} |
||||
Loading…
Reference in new issue