From 12696eeed4dc9104428cd7dde9b0bf53ad8fba9e Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 19 Mar 2026 16:13:31 +0800 Subject: [PATCH] =?UTF-8?q?test(type):=20=E6=B7=BB=E5=8A=A0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=A3=B0=E6=98=8E=E7=9B=B8=E5=85=B3=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加可调用类型、数组类型、对象类型和可迭代类型的测试 - 添加标量类型声明包括整数、字符串、浮点数和布尔值的测试 - 添加空类型合并操作符 ?? 和 ??= 的语法测试 - 添加魔术方法包括 __clone、__serialize 和 __unserialize 的测试 - 在编译器基础类中增加对 callable 和 iterable 类型的支持 --- src/Php/CompilerBase.php | 5 ++ tests/aot/magic_methods/misc.phpt | 69 ++++++++++++++++ tests/aot/null-coalescing.phpt | 128 ++++++++++++++++++++++++++++++ tests/aot/type_decl/001.phpt | 52 ++++++++++++ tests/aot/type_decl/002.phpt | 64 +++++++++++++++ tests/aot/type_decl/003.phpt | 31 ++++++++ 6 files changed, 349 insertions(+) create mode 100644 tests/aot/magic_methods/misc.phpt create mode 100644 tests/aot/null-coalescing.phpt create mode 100644 tests/aot/type_decl/001.phpt create mode 100644 tests/aot/type_decl/002.phpt create mode 100644 tests/aot/type_decl/003.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 6034396b..66df03a9 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1778,6 +1778,11 @@ class CompilerBase extends \PhpAot\Core\Translator case 'void': $this->fatalError($param, 'Cannot use `void` as a parameter type.'); // no break + // callable 类型,可以是字符串、数组、对象 + // 1) 'foo' 函数名称字符串, 2) [ $obj, 'bar' ] 对象方法数组, 3) Closure 对象, 4) [ 'class', 'staticMethod'] 类名+静态方法数组 + case 'callable': + // iterable 类型,可以是数组或者对象 + case 'iterable': case 'mixed': return self::TYPE_VAR; case 'self': diff --git a/tests/aot/magic_methods/misc.phpt b/tests/aot/magic_methods/misc.phpt new file mode 100644 index 00000000..fe55bd63 --- /dev/null +++ b/tests/aot/magic_methods/misc.phpt @@ -0,0 +1,69 @@ +--TEST-- +Magic Methods - __get, __set, __call, __invoke etc. +--FILE-- +x *= 2; + $this->y *= 2; + } + + public function getX(): float { + return $this->x; + } + + public function getY(): float { + return $this->y; + } +} + +class SerializableClass { + public function __construct( + public string $name, + public int $value + ) {} + + // __serialize and __unserialize (PHP 7.4+) + public function __serialize(): array { + return [ + 'name' => strtoupper($this->name), + 'value' => $this->value * 2, + ]; + } + + public function __unserialize(array $data): void { + $this->name = strtolower($data['name']); + $this->value = $data['value'] / 2; + } +} + +function main() { + // Test __clone + $point1 = new Point(5.0, 10.0); + $point2 = clone $point1; + var_dump($point1->getX()); + var_dump($point2->getX()); + var_dump($point1->getY()); + var_dump($point2->getY()); + + // Test __serialize and __unserialize + $obj = new SerializableClass('Test', 100); + $serialized = serialize($obj); + $unserialized = unserialize($serialized); + var_dump($unserialized->name); + var_dump($unserialized->value); +} +?> +--EXPECT-- +float(5) +float(10) +float(10) +float(20) +string(4) "test" +int(100) \ No newline at end of file diff --git a/tests/aot/null-coalescing.phpt b/tests/aot/null-coalescing.phpt new file mode 100644 index 00000000..bc326332 --- /dev/null +++ b/tests/aot/null-coalescing.phpt @@ -0,0 +1,128 @@ +--TEST-- +Null Coalescing Operators - ?? and ??= syntax +--FILE-- +settings[$key] ??= $default; + } + + public function get(string $key): mixed { + return $this->settings[$key] ?? null; + } + + public function getAll(): array { + return $this->settings; + } +} + +// Test with array access +function test_array_coalesce(array $data, string $key) { + return $data[$key] ?? 'not set'; +} + +// Test with nested arrays +function test_nested_coalesce(array $data) { + return $data['user']['profile']['name'] ?? 'Anonymous'; +} + +// Test in expressions +function test_expression($value) { + $result = ($value ?? 0) * 2; + return $result; +} + +function main() { + // Test basic coalescing + var_dump(test_basic_coalesce(null)); + var_dump(test_basic_coalesce('exists')); + var_dump(test_basic_coalesce(0)); + var_dump(test_basic_coalesce(false)); + var_dump(test_basic_coalesce('')); + + // Test chained coalescing + var_dump(test_chained_coalesce(null, null, 'third')); + var_dump(test_chained_coalesce(null, 'second', 'third')); + var_dump(test_chained_coalesce('first', 'second', 'third')); + var_dump(test_chained_coalesce(null, null, null)); + + // Test null coalescing assignment + $config = new Config(); + $config->setDefault('debug', false); + $config->setDefault('timeout', 30); + $config->setDefault('debug', true); // Should not override + var_dump($config->getAll()); + + // Test array coalescing + $arr1 = ['name' => 'John']; + $arr2 = []; + var_dump(test_array_coalesce($arr1, 'name')); + var_dump(test_array_coalesce($arr1, 'age')); + var_dump(test_array_coalesce($arr2, 'name')); + + // Test nested coalescing + $data1 = ['user' => ['profile' => ['name' => 'Alice']]]; + $data2 = ['user' => []]; + $data3 = []; + var_dump(test_nested_coalesce($data1)); + var_dump(test_nested_coalesce($data2)); + var_dump(test_nested_coalesce($data3)); + + // Test in expressions + var_dump(test_expression(null)); + var_dump(test_expression(5)); + var_dump(test_expression(0)); + + // Test complex scenario + $options = [ + 'limit' => null, + 'offset' => 10, + ]; + + $limit = $options['limit'] ?? 100; + $offset = $options['offset'] ?? 0; + + var_dump($limit); + var_dump($offset); +} +?> +--EXPECT-- +string(7) "default" +string(6) "exists" +int(0) +bool(false) +string(0) "" +string(5) "third" +string(6) "second" +string(5) "first" +string(8) "all null" +array(2) { + ["debug"]=> + bool(false) + ["timeout"]=> + int(30) +} +string(4) "John" +string(7) "not set" +string(7) "not set" +string(5) "Alice" +string(9) "Anonymous" +string(9) "Anonymous" +int(0) +int(10) +int(0) +int(100) +int(10) diff --git a/tests/aot/type_decl/001.phpt b/tests/aot/type_decl/001.phpt new file mode 100644 index 00000000..f7279222 --- /dev/null +++ b/tests/aot/type_decl/001.phpt @@ -0,0 +1,52 @@ +--TEST-- +Type Declarations - Strict and weak typing modes +--FILE-- + $x * 2, 5)); + var_dump(apply_callable('abs', -10)); + + // Test array type + var_dump(process_array([1, 2, 3])); + var_dump(process_array([])); + + // Test object type + $testObj = new TestClass(); + var_dump(get_class_name($testObj)); +} +?> +--EXPECT-- +int(10) +int(10) +int(3) +int(0) +string(9) "TestClass" diff --git a/tests/aot/type_decl/002.phpt b/tests/aot/type_decl/002.phpt new file mode 100644 index 00000000..9fb1631d --- /dev/null +++ b/tests/aot/type_decl/002.phpt @@ -0,0 +1,64 @@ +--TEST-- +Type Declarations - Strict and weak typing modes +--FILE-- + +--EXPECT-- +int(15) +int(4) +string(13) "Hello, World!" +string(5) "Empty" +float(10) +float(0.020000000000000004) +bool(false) +bool(true) +string(12) "Hello, Alice" +NULL \ No newline at end of file diff --git a/tests/aot/type_decl/003.phpt b/tests/aot/type_decl/003.phpt new file mode 100644 index 00000000..505b2808 --- /dev/null +++ b/tests/aot/type_decl/003.phpt @@ -0,0 +1,31 @@ +--TEST-- +Type Declarations - Strict and weak typing modes +--FILE-- +getMessage() . "\n"; + } +} +?> +--EXPECT-- +int(15) +Strict mode enabled