refactor(tests): replace native_types and complex_types with Type constants

- Replaced all occurrences of native_types::type_* with Type::* constants
- Replaced all occurrences of complex_types::type_* with Type::* constants
- Updated ExtensionProvider annotation to use ExtensionProvider::Keyword
- Modified std array, vector, map, ordered_map, bigfloat, bigint, decimal tests
- Updated stream, array multidimensional, unsafe pointer, and type mismatch tests
- Changed camel case keyword extension to use Type::Any constant
- Updated documentation to reflect Type::* constant usage instead of type_* constants
pull/17/head
韩天峰 1 month ago
parent 431817dee3
commit 492116d3c0
  1. 2
      .github/copilot-instructions.md
  2. 4
      README.md
  3. 2
      composer.json
  4. 4
      composer.lock
  5. 2
      docs/COMPILE_TIME_FUNCTIONS.md
  6. 22
      docs/PATENT_01_CPP_TEMPLATE_TYPED_CONTAINER.md
  7. 81
      docs/STD_CONTAINERS.md
  8. 2
      examples/array-loop/main.php
  9. 2
      examples/array-loop/std-array.php
  10. 2
      examples/stdmap.php
  11. 10
      src/Parser/MethodCallTrait.php
  12. 56
      src/Parser/StdContainerTrait.php
  13. 5
      src/Parser/UniversalMethodCall.php
  14. 46
      src/Preprocessor.php
  15. 98
      src/gen_stub.php
  16. 44
      src/polyfills.php
  17. 2
      tests/compiler/keyword_extension/001.phpt
  18. 15
      tests/compiler/keyword_extension/camel.phpt
  19. 2
      tests/compiler/std-array/001.phpt
  20. 2
      tests/compiler/std-array/002.phpt
  21. 2
      tests/compiler/std-array/003.phpt
  22. 4
      tests/compiler/std-array/004.phpt
  23. 8
      tests/compiler/std-array/005.phpt
  24. 4
      tests/compiler/std-array/007.phpt
  25. 4
      tests/compiler/std-array/008.phpt
  26. 2
      tests/compiler/std-array/009.phpt
  27. 4
      tests/compiler/std-array/010.phpt
  28. 2
      tests/compiler/std-array/011.phpt
  29. 2
      tests/compiler/std-array/012.phpt
  30. 2
      tests/compiler/std-bigfloat/001.phpt
  31. 2
      tests/compiler/std-bigint/001.phpt
  32. 2
      tests/compiler/std-bigint/002.phpt
  33. 2
      tests/compiler/std-bigint/003.phpt
  34. 2
      tests/compiler/std-bigint/004.phpt
  35. 2
      tests/compiler/std-decimal/001.phpt
  36. 2
      tests/compiler/std-map/001.phpt
  37. 4
      tests/compiler/std-map/002.phpt
  38. 8
      tests/compiler/std-map/003.phpt
  39. 2
      tests/compiler/std-map/004.phpt
  40. 4
      tests/compiler/std-map/005.phpt
  41. 4
      tests/compiler/std-map/006.phpt
  42. 2
      tests/compiler/std-map/007.phpt
  43. 4
      tests/compiler/std-map/008.phpt
  44. 2
      tests/compiler/std-map/009.phpt
  45. 2
      tests/compiler/std-map/010.phpt
  46. 2
      tests/compiler/std-ordered-map/001.phpt
  47. 4
      tests/compiler/std-ordered-map/002.phpt
  48. 8
      tests/compiler/std-ordered-map/003.phpt
  49. 4
      tests/compiler/std-ordered-map/004.phpt
  50. 4
      tests/compiler/std-ordered-map/005.phpt
  51. 4
      tests/compiler/std-ordered-map/006.phpt
  52. 2
      tests/compiler/std-ordered-map/007.phpt
  53. 4
      tests/compiler/std-ordered-map/008.phpt
  54. 2
      tests/compiler/std-ordered-map/009.phpt
  55. 2
      tests/compiler/std-ordered-map/010.phpt
  56. 2
      tests/compiler/std-stream/001.phpt
  57. 4
      tests/compiler/std-vector/001.phpt
  58. 8
      tests/compiler/std-vector/002.phpt
  59. 4
      tests/compiler/std-vector/006.phpt
  60. 4
      tests/compiler/std-vector/007.phpt
  61. 2
      tests/compiler/std-vector/010.phpt
  62. 4
      tests/compiler/std-vector/011.phpt
  63. 2
      tests/compiler/std-vector/012.phpt
  64. 2
      tests/compiler/std-vector/013.phpt
  65. 4
      tests/compiler/std-vector/014.phpt
  66. 2
      tests/compiler/stream_method/extension.phpt
  67. 6
      tests/compiler/universal_method/universal_method_extension.phpt
  68. 4
      tests/compiler/universal_method/universal_method_extension_camel.phpt
  69. 6
      tests/compiler/universal_method/universal_method_extension_chain.phpt
  70. 2
      tests/compiler/universal_method/universal_method_internal.phpt

@ -13,7 +13,7 @@ TypePHP is a PHP native compilation project. Its `tpc` command is TypePHP Compil
## Setup and build commands ## Setup and build commands
The repo expects PHP 8.2+, GCC 9+ with C++17, CMake 3.24+, and a compiled `swoole/phpx` dependency. Install PHP dependencies with: The repo expects PHP 8.4+, GCC 9+ with C++17, CMake 3.24+, and a compiled `swoole/phpx` dependency. Install PHP dependencies with:
```bash ```bash
composer install composer install

@ -1,5 +1,5 @@
# 依赖 # 依赖
- 需要 PHP-8.2 以上版本 - 编译器需要 PHP 8.4 以上版本;生成的扩展仍可面向 PHP 8.2~8.5
- 需要 GCC-9 以上版本,支持 C++17 标准 - 需要 GCC-9 以上版本,支持 C++17 标准
- 需要 CMake-3.24 以上版本 - 需要 CMake-3.24 以上版本
- 需要高精度数学库:`GMP`、`MPFR`、`libmpdec` - 需要高精度数学库:`GMP`、`MPFR`、`libmpdec`
@ -47,4 +47,4 @@ vim /etc/ld.so.conf.d/swoole.conf
``` ```
/home/swoole/workspace/projects/phpx/lib /home/swoole/workspace/projects/phpx/lib
/opt/php-8.4/lib/ /opt/php-8.4/lib/
``` ```

@ -1,6 +1,6 @@
{ {
"require": { "require": {
"php": ">=8.2 <8.6", "php": ">=8.4 <8.6",
"nikic/php-parser": "5.6.1", "nikic/php-parser": "5.6.1",
"league/climate": "^3.10", "league/climate": "^3.10",
"marcj/topsort": "^2.0", "marcj/topsort": "^2.0",

4
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "41bca06c5ece84cfb4ed396385b10988", "content-hash": "72caced27fd0c3469dae5d4f4db591d0",
"packages": [ "packages": [
{ {
"name": "ajaxray/ansikit", "name": "ajaxray/ansikit",
@ -4876,7 +4876,7 @@
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": ">=8.2 <8.6" "php": ">=8.4 <8.6"
}, },
"platform-dev": {}, "platform-dev": {},
"plugin-api-version": "2.9.0" "plugin-api-version": "2.9.0"

@ -74,7 +74,7 @@
## 不计入本文清单的机制 ## 不计入本文清单的机制
- `$array->any()` 是 universal method,映射到 PHP `array_any()`,不是 `any()` 编译期函数。 - `$array->any()` 是 universal method,映射到 PHP `array_any()`,不是 `any()` 编译期函数。
- `native_types::type_*`、`complex_types::type_*` 是编译期类型描述常量,不是函数。 - `Type::*` 是编译期类型描述常量,不是函数。
- keyword extension method 是用户自定义扩展方法机制,不属于固定内置编译期函数清单。 - keyword extension method 是用户自定义扩展方法机制,不属于固定内置编译期函数清单。
## 实现约束 ## 实现约束

@ -103,10 +103,10 @@ Swoole-Compiler 是一种 PHP AOT 编译器。它将 PHP 源文件解析为抽
本发明在动态语言中定义一组强类型容器构造语法,例如: 本发明在动态语言中定义一组强类型容器构造语法,例如:
```php ```php
$a = std::array(native_types::type_int, 100); $a = std::array(Type::Int, 100);
$v = std::vector(native_types::type_float); $v = std::vector(Type::Float);
$m = std::ordered_map(complex_types::type_str, native_types::type_int); $m = std::ordered_map(Type::String, Type::Int);
$h = std::map(native_types::type_int, User::class); $h = std::map(Type::Int, User::class);
``` ```
编译器在 AOT 阶段识别这些构造表达式,生成容器元信息,并将其转换为 C++ 模版实例: 编译器在 AOT 阶段识别这些构造表达式,生成容器元信息,并将其转换为 C++ 模版实例:
@ -204,7 +204,7 @@ typeId:根据上述字段生成的类型标识。
例如: 例如:
```php ```php
$b = std::array(std::array(native_types::type_int, 3), 2); $b = std::array(std::array(Type::Int, 3), 2);
``` ```
对应元信息可以表示为: 对应元信息可以表示为:
@ -225,8 +225,8 @@ typeId=自动分配的整数
示例: 示例:
```php ```php
$a = std::array(native_types::type_int, 3); $a = std::array(Type::Int, 3);
$b = std::array(std::array(native_types::type_int, 3), 2); $b = std::array(std::array(Type::Int, 3), 2);
$a = $b[1]; $a = $b[1];
``` ```
@ -252,8 +252,8 @@ a = b[php::safeIndex(php::toInt(1L), 2)];
第一类,左值为强类型容器且右值为完全相同强类型容器: 第一类,左值为强类型容器且右值为完全相同强类型容器:
```php ```php
$a = std::vector(native_types::type_int); $a = std::vector(Type::Int);
$b = std::vector(native_types::type_int); $b = std::vector(Type::Int);
$a = $b; $a = $b;
``` ```
@ -344,13 +344,13 @@ for (auto it = v.begin(); it != v.end(); ++it) {
```php ```php
function update(UnsafePtr $ptr): void function update(UnsafePtr $ptr): void
{ {
$v = std::unsafe_cast(std::vector(native_types::type_int), $ptr); $v = std::unsafe_cast(std::vector(Type::Int), $ptr);
$v[0] = 100; $v[0] = 100;
} }
function main(): void function main(): void
{ {
$v = std::vector(native_types::type_int, 1); $v = std::vector(Type::Int, 1);
update($v); update($v);
} }
``` ```

@ -102,7 +102,7 @@ Swoole AOT 提供 `std` 容器,用来表达“这个容器的结构和元素
```php ```php
function main(): void function main(): void
{ {
$array = std::array(native_types::type_int, 100); $array = std::array(Type::Int, 100);
$array[0] = 123; $array[0] = 123;
$array[99] = 456; $array[99] = 456;
@ -125,7 +125,7 @@ function main(): void
function main(): void function main(): void
{ {
$matrix = std::array( $matrix = std::array(
std::array(native_types::type_int, 4), std::array(Type::Int, 4),
3 3
); );
@ -141,8 +141,8 @@ function main(): void
```php ```php
function main(): void function main(): void
{ {
$a = std::array(native_types::type_int, 3); $a = std::array(Type::Int, 3);
$b = std::array(std::array(native_types::type_int, 3), 2); $b = std::array(std::array(Type::Int, 3), 2);
$b[1][0] = 10; $b[1][0] = 10;
$b[1][1] = 20; $b[1][1] = 20;
@ -159,7 +159,7 @@ function main(): void
```php ```php
function main(): void function main(): void
{ {
$vector = std::vector(native_types::type_int); $vector = std::vector(Type::Int);
$vector[] = 1; $vector[] = 1;
$vector[] = 2; $vector[] = 2;
@ -173,7 +173,7 @@ function main(): void
也可以指定初始长度: 也可以指定初始长度:
```php ```php
$vector = std::vector(native_types::type_float, 1024); $vector = std::vector(Type::Float, 1024);
``` ```
特点: 特点:
@ -187,8 +187,8 @@ $vector = std::vector(native_types::type_float, 1024);
同类型 vector 可以 copy: 同类型 vector 可以 copy:
```php ```php
$a = std::vector(native_types::type_int); $a = std::vector(Type::Int);
$b = std::vector(native_types::type_int); $b = std::vector(Type::Int);
$b[] = 10; $b[] = 10;
$b[] = 20; $b[] = 20;
@ -204,8 +204,8 @@ $a = $b; // 允许,类型完全一致,执行容器 copy
function main(): void function main(): void
{ {
$map = std::ordered_map( $map = std::ordered_map(
complex_types::type_str, Type::String,
native_types::type_int Type::Int
); );
$map["a"] = 1; $map["a"] = 1;
@ -225,7 +225,7 @@ function main(): void
示例: 示例:
```php ```php
$map = std::ordered_map(native_types::type_int, native_types::type_float); $map = std::ordered_map(Type::Int, Type::Float);
$map[10] = 1.25; $map[10] = 1.25;
$map[20] = 3.5; $map[20] = 3.5;
@ -234,8 +234,8 @@ $map[20] = 3.5;
同类型 ordered_map 可以 copy: 同类型 ordered_map 可以 copy:
```php ```php
$a = std::ordered_map(native_types::type_int, native_types::type_int); $a = std::ordered_map(Type::Int, Type::Int);
$b = std::ordered_map(native_types::type_int, native_types::type_int); $b = std::ordered_map(Type::Int, Type::Int);
$b[10] = 100; $b[10] = 100;
$a = $b; $a = $b;
@ -249,8 +249,8 @@ $a = $b;
function main(): void function main(): void
{ {
$map = std::map( $map = std::map(
native_types::type_int, Type::Int,
native_types::type_int Type::Int
); );
$map[100] = 1; $map[100] = 1;
@ -270,8 +270,8 @@ function main(): void
同类型 map 可以 copy: 同类型 map 可以 copy:
```php ```php
$a = std::map(native_types::type_int, native_types::type_int); $a = std::map(Type::Int, Type::Int);
$b = std::map(native_types::type_int, native_types::type_int); $b = std::map(Type::Int, Type::Int);
$b[1] = 42; $b[1] = 42;
$a = $b; $a = $b;
@ -279,23 +279,18 @@ $a = $b;
## 支持的元素类型 ## 支持的元素类型
基础类型: 类型符号
```php ```php
native_types::type_int Type::Int
native_types::type_float Type::Float
native_types::type_bool Type::Bool
``` Type::String
Type::Array
复杂类型: Type::Object
Type::Any
```php Type::Stream
complex_types::type_string Type::Box
complex_types::type_str
complex_types::type_array
complex_types::type_object
complex_types::type_any
complex_types::type_var
``` ```
也可以使用类名作为 value 类型: 也可以使用类名作为 value 类型:
@ -307,7 +302,7 @@ class User
$vector = std::vector(User::class); $vector = std::vector(User::class);
$array = std::array(User::class, 10); $array = std::array(User::class, 10);
$map = std::ordered_map(complex_types::type_str, User::class); $map = std::ordered_map(Type::String, User::class);
``` ```
类类型容器会在写入时检查对象类型,避免错误对象混入。 类类型容器会在写入时检查对象类型,避免错误对象混入。
@ -319,7 +314,7 @@ $map = std::ordered_map(complex_types::type_str, User::class);
```php ```php
function main(): void function main(): void
{ {
$vector = std::vector(native_types::type_int); $vector = std::vector(Type::Int);
$vector[] = 1; $vector[] = 1;
$vector[] = 2; $vector[] = 2;
@ -332,8 +327,8 @@ function main(): void
如果左值本身是同类型 std 容器,则执行容器 copy,而不是转 PHP Array: 如果左值本身是同类型 std 容器,则执行容器 copy,而不是转 PHP Array:
```php ```php
$a = std::vector(native_types::type_int); $a = std::vector(Type::Int);
$b = std::vector(native_types::type_int); $b = std::vector(Type::Int);
$a = $b; // std::vector copy $a = $b; // std::vector copy
``` ```
@ -341,8 +336,8 @@ $a = $b; // std::vector copy
如果类型不同,则不允许 copy: 如果类型不同,则不允许 copy:
```php ```php
$a = std::vector(native_types::type_int); $a = std::vector(Type::Int);
$b = std::vector(native_types::type_float); $b = std::vector(Type::Float);
$a = $b; // 编译失败 $a = $b; // 编译失败
``` ```
@ -357,7 +352,7 @@ $a = $b; // 编译失败
function update(UnsafePtr $ptr): void function update(UnsafePtr $ptr): void
{ {
$vector = std::unsafe_cast( $vector = std::unsafe_cast(
std::vector(native_types::type_int), std::vector(Type::Int),
$ptr $ptr
); );
@ -366,7 +361,7 @@ function update(UnsafePtr $ptr): void
function main(): void function main(): void
{ {
$vector = std::vector(native_types::type_int, 1); $vector = std::vector(Type::Int, 1);
update($vector); // 编译器自动转为 UnsafePtr box update($vector); // 编译器自动转为 UnsafePtr box
} }
``` ```
@ -404,7 +399,7 @@ std 容器则不同。编译器在解析代码时记录容器元信息:
例如: 例如:
```php ```php
$vector = std::vector(native_types::type_int); $vector = std::vector(Type::Int);
``` ```
可以生成类似: 可以生成类似:
@ -416,7 +411,7 @@ php::StdVector<php::Int> vector;
再例如: 再例如:
```php ```php
$array = std::array(std::array(native_types::type_int, 3), 2); $array = std::array(std::array(Type::Int, 3), 2);
``` ```
可以生成类似: 可以生成类似:
@ -506,7 +501,7 @@ function main(int $argc, array $argv): void
$u = (int)$argv[2]; $u = (int)$argv[2];
echo "u: $u\n"; echo "u: $u\n";
$r = rand(0, 10000); $r = rand(0, 10000);
$a = std::array(native_types::type_int, 10000); $a = std::array(Type::Int, 10000);
$begin = microtime(true); $begin = microtime(true);
for ($i = 0; $i < 10000; $i++) { for ($i = 0; $i < 10000; $i++) {

@ -7,7 +7,7 @@ function main(int $argc, array $argv): void
$u = (int)$argv[2]; $u = (int)$argv[2];
echo "u: $u\n"; echo "u: $u\n";
$r = rand(0, 10000); $r = rand(0, 10000);
$a = std::array(native_types::type_int, 10000); $a = std::array(Type::Int, 10000);
$begin = microtime(true); $begin = microtime(true);
for ($i = 0; $i < 10000; $i++) { for ($i = 0; $i < 10000; $i++) {

@ -4,7 +4,7 @@ use native_types;
function main() function main()
{ {
$array = std::array(std::array(std::array(native_types::type_int, 13), 16), 19); $array = std::array(std::array(std::array(Type::Int, 13), 16), 19);
$index = 9; $index = 9;
$index2 = 5; $index2 = 5;
$array[$index2][$index][0] = 2026; $array[$index2][$index][0] = 2026;

@ -11,7 +11,7 @@ class Foo {
function main() function main()
{ {
$map = std::map(complex_types::type_str, Foo::class); $map = std::map(Type::String, Foo::class);
$map["a"] = new Foo("a", 1); $map["a"] = new Foo("a", 1);
$map["b"] = new Foo("b", 2); $map["b"] = new Foo("b", 2);
var_dump($map); var_dump($map);

@ -328,7 +328,15 @@ trait MethodCallTrait
} }
return $this->genToConvertCall($object, $methodName, $receiverType); return $this->genToConvertCall($object, $methodName, $receiverType);
} }
// __ keyword extensions // A provider targeting Type::Any only applies when
// the receiver's static type is actually mixed/any.
if ($receiverType === Type::VAR) {
$anyExtension = $this->findExtensionMethod(Type::VAR, $methodName);
if ($anyExtension) {
return $this->parseUniversalMethodCall($expr, $object, $methodName, $anyExtension, $this->isVarExpr($expr->var));
}
}
// ExtensionProvider::Keyword extensions apply to every receiver type.
$kwExt = $this->findKeywordExtensionMethod($methodName); $kwExt = $this->findKeywordExtensionMethod($methodName);
if ($kwExt) { if ($kwExt) {
return $this->parseUniversalMethodCall($expr, $object, $methodName, $kwExt, $this->isVarExpr($expr->var)); return $this->parseUniversalMethodCall($expr, $object, $methodName, $kwExt, $this->isVarExpr($expr->var));

@ -469,19 +469,17 @@ trait StdContainerTrait
protected function parseStdNativeType(NodeAbstract $expr, string $owner): string protected function parseStdNativeType(NodeAbstract $expr, string $owner): string
{ {
if (!$this->isClassConstFetch($expr)) { if (!$this->isClassConstFetch($expr) || !$this->isNameExpr($expr->class) || !$this->isIdExpr($expr->name)
$this->fatalError($expr, "{$owner} expects a native_types class constant"); || strcasecmp(ltrim($expr->class->toString(), '\\'), 'Type') !== 0) {
}
if (!$this->isNameExpr($expr->class) || !$this->isIdExpr($expr->name) || strtolower($expr->class->toString()) !== 'native_types') {
$this->fatalError($expr, "An incorrect `{$owner}` definition"); $this->fatalError($expr, "An incorrect `{$owner}` definition");
} }
return match (strtolower($expr->name->name)) { return match ($expr->name->name) {
'type_int' => Type::INT, 'Int' => Type::INT,
'type_float' => Type::FLOAT, 'Float' => Type::FLOAT,
'type_bool' => Type::BOOL, 'Bool' => Type::BOOL,
'type_bigint' => Type::BIGINT, 'BigInt' => Type::BIGINT,
'type_bigfloat' => Type::BIGFLOAT, 'BigFloat' => Type::BIGFLOAT,
'type_decimal' => Type::DECIMAL, 'Decimal' => Type::DECIMAL,
default => $this->fatalError($expr, "An incorrect `{$owner}` definition"), default => $this->fatalError($expr, "An incorrect `{$owner}` definition"),
}; };
} }
@ -489,24 +487,22 @@ trait StdContainerTrait
protected function parseStdValueTypeInfo(NodeAbstract $expr, string $owner): array protected function parseStdValueTypeInfo(NodeAbstract $expr, string $owner): array
{ {
if (!$this->isClassConstFetch($expr)) { if (!$this->isClassConstFetch($expr)) {
$this->fatalError($expr, "{$owner} expects a native_types or complex_types class constant"); $this->fatalError($expr, "{$owner} expects a Type constant or ClassName::class");
} }
if (!$this->isNameExpr($expr->class) || !$this->isIdExpr($expr->name)) { if (!$this->isNameExpr($expr->class) || !$this->isIdExpr($expr->name)) {
$this->fatalError($expr, "An incorrect `{$owner}` definition"); $this->fatalError($expr, "An incorrect `{$owner}` definition");
} }
$className = strtolower($expr->class->toString()); $className = ltrim($expr->class->toString(), '\\');
if ($className === 'native_types') { if (strcasecmp($className, 'Type') === 0) {
return ['type' => $this->parseStdNativeType($expr, $owner), 'class' => null];
}
if ($className === 'complex_types') {
return [ return [
'type' => match (strtolower($expr->name->name)) { 'type' => match ($expr->name->name) {
'type_str', 'type_string' => Type::STR, 'Int', 'Float', 'Bool', 'BigInt', 'BigFloat', 'Decimal' => $this->parseStdNativeType($expr, $owner),
'type_array' => Type::ARRAY, 'String' => Type::STR,
'type_object' => Type::OBJECT, 'Array' => Type::ARRAY,
'type_any', 'type_var', 'type_variant' => Type::VAR, 'Object' => Type::OBJECT,
'type_stream' => Type::STREAM, 'Any' => Type::VAR,
'type_box' => Type::BOX, 'Stream' => Type::STREAM,
'Box' => Type::BOX,
default => $this->fatalError($expr, "An incorrect `{$owner}` definition"), default => $this->fatalError($expr, "An incorrect `{$owner}` definition"),
}, },
'class' => null, 'class' => null,
@ -634,17 +630,17 @@ trait StdContainerTrait
protected function parseStdMapKeyType(NodeAbstract $expr, string $owner): string protected function parseStdMapKeyType(NodeAbstract $expr, string $owner): string
{ {
if (!$this->isClassConstFetch($expr) || !$this->isNameExpr($expr->class) || !$this->isIdExpr($expr->name)) { if (!$this->isClassConstFetch($expr) || !$this->isNameExpr($expr->class) || !$this->isIdExpr($expr->name)) {
$this->fatalError($expr, "{$owner} expects a native_types or complex_types class constant"); $this->fatalError($expr, "{$owner} expects Type::Int or Type::String");
} }
$className = strtolower($expr->class->toString()); $className = ltrim($expr->class->toString(), '\\');
$constName = strtolower($expr->name->name); $constName = $expr->name->name;
if ($className === 'native_types' && $constName === 'type_int') { if (strcasecmp($className, 'Type') === 0 && $constName === 'Int') {
return Type::INT; return Type::INT;
} }
if ($className === 'complex_types' && in_array($constName, ['type_string', 'type_str'], true)) { if (strcasecmp($className, 'Type') === 0 && $constName === 'String') {
return Type::STR; return Type::STR;
} }
$this->fatalError($expr, "{$owner} key only supports native_types::type_int, complex_types::type_string or complex_types::type_str"); $this->fatalError($expr, "{$owner} key only supports Type::Int or Type::String");
} }
protected function getStdMapDecl(string $containerType, string $keyType, string $valueType): string protected function getStdMapDecl(string $containerType, string $keyType, string $valueType): string

@ -387,6 +387,9 @@ trait UniversalMethodCall
private function extensionReceiverMatchesTarget($receiver, string $target): bool private function extensionReceiverMatchesTarget($receiver, string $target): bool
{ {
if ($target === '*') {
return $receiver->type === Type::VAR;
}
$builtinTargets = [ $builtinTargets = [
Type::VAR, Type::INT, Type::FLOAT, Type::BOOL, Type::STR, Type::VAR, Type::INT, Type::FLOAT, Type::BOOL, Type::STR,
Type::ARRAY, Type::OBJECT, Type::STREAM, Type::BIGINT, Type::ARRAY, Type::OBJECT, Type::STREAM, Type::BIGINT,
@ -478,7 +481,7 @@ trait UniversalMethodCall
*/ */
protected function findKeywordExtensionMethod(string $method): ?array protected function findKeywordExtensionMethod(string $method): ?array
{ {
return $this->findProviderExtension(Type::VAR, $method); return $this->findProviderExtension('*', $method);
} }
/** /**

@ -635,37 +635,33 @@ class Preprocessor extends CompilerBase
if ($value instanceof Node\Expr\ClassConstFetch if ($value instanceof Node\Expr\ClassConstFetch
&& $this->isNameExpr($value->class) && $this->isNameExpr($value->class)
&& $this->isIdExpr($value->name)) { && $this->isIdExpr($value->name)) {
$class = strtolower(ltrim($value->class->toString(), '\\')); $class = ltrim($value->class->toString(), '\\');
$constant = strtolower($value->name->toString()); $constant = $value->name->toString();
if ($constant === 'class') { if (strtolower($constant) === 'class') {
return $this->getNamespacedClassName($value->class->toString()); return $this->getNamespacedClassName($value->class->toString());
} }
$targets = [ $targets = [
'native_types' => [ 'Int' => Type::INT,
'type_int' => Type::INT, 'Float' => Type::FLOAT,
'type_float' => Type::FLOAT, 'Bool' => Type::BOOL,
'type_bool' => Type::BOOL, 'BigInt' => Type::BIGINT,
'type_bigint' => Type::BIGINT, 'BigFloat' => Type::BIGFLOAT,
'type_bigfloat' => Type::BIGFLOAT, 'Decimal' => Type::DECIMAL,
'type_decimal' => Type::DECIMAL, 'String' => Type::STR,
], 'Array' => Type::ARRAY,
'complex_types' => [ 'Object' => Type::OBJECT,
'type_any' => Type::VAR, 'Any' => Type::VAR,
'type_var' => Type::VAR, 'Stream' => Type::STREAM,
'type_variant' => Type::VAR, 'Box' => Type::BOX,
'type_str' => Type::STR,
'type_string' => Type::STR,
'type_array' => Type::ARRAY,
'type_object' => Type::OBJECT,
'type_stream' => Type::STREAM,
'type_box' => Type::BOX,
],
]; ];
if (isset($targets[$class][$constant])) { if (strcasecmp($class, 'Type') === 0 && isset($targets[$constant])) {
return $targets[$class][$constant]; return $targets[$constant];
}
if (strcasecmp($class, 'ExtensionProvider') === 0 && $constant === 'Keyword') {
return '*';
} }
} }
$this->fatalError($errorNode, 'ExtensionProvider target must use native_types, complex_types, or ClassName::class'); $this->fatalError($errorNode, 'ExtensionProvider target must be Type::*, ExtensionProvider::Keyword, or ClassName::class');
} }
protected function buildLiteralArrayInitPlan(Node\Expr\Array_ $defaultNode): ArrayInitPlan protected function buildLiteralArrayInitPlan(Node\Expr\Array_ $defaultNode): ArrayInitPlan

@ -186,15 +186,15 @@ class Context {
} }
class ArrayType extends SimpleType { class ArrayType extends SimpleType {
private /* readonly */ Type $keyType; private /* readonly */ StubType $keyType;
private /* readonly */ Type $valueType; private /* readonly */ StubType $valueType;
public static function createGenericArray(): self public static function createGenericArray(): self
{ {
return new ArrayType(Type::fromString("int|string"), Type::fromString("mixed|ref")); return new ArrayType(StubType::fromString("int|string"), StubType::fromString("mixed|ref"));
} }
public function __construct(Type $keyType, Type $valueType) public function __construct(StubType $keyType, StubType $valueType)
{ {
parent::__construct("array", true); parent::__construct("array", true);
@ -217,8 +217,8 @@ class ArrayType extends SimpleType {
return false; return false;
} }
return Type::equals($this->keyType, $other->keyType) && return StubType::equals($this->keyType, $other->keyType) &&
Type::equals($this->valueType, $other->valueType); StubType::equals($this->valueType, $other->valueType);
} }
} }
@ -299,7 +299,7 @@ class SimpleType {
$matches = []; $matches = [];
$isArray = preg_match("/(.*)\s*\[\s*\]/", $typeString, $matches); $isArray = preg_match("/(.*)\s*\[\s*\]/", $typeString, $matches);
if ($isArray) { if ($isArray) {
return new ArrayType(Type::fromString("int"), Type::fromString($matches[1])); return new ArrayType(StubType::fromString("int"), StubType::fromString($matches[1]));
} }
$matches = []; $matches = [];
@ -309,7 +309,7 @@ class SimpleType {
throw new Exception("array<> type hint must have both a key and a value"); throw new Exception("array<> type hint must have both a key and a value");
} }
return new ArrayType(Type::fromString($matches[1]), Type::fromString($matches[3])); return new ArrayType(StubType::fromString($matches[1]), StubType::fromString($matches[3]));
} }
return new SimpleType($typeString, false); return new SimpleType($typeString, false);
@ -521,27 +521,27 @@ class SimpleType {
} }
} }
// Instances of Type are immutable and do not need to be cloned // Instances of StubType are immutable and do not need to be cloned
// when held by an object that is cloned // when held by an object that is cloned
class Type { class StubType {
/** @var SimpleType[] */ /** @var SimpleType[] */
public /* readonly */ array $types; public /* readonly */ array $types;
public /* readonly */ bool $isIntersection; public /* readonly */ bool $isIntersection;
public static function fromNode(Node $node): Type { public static function fromNode(Node $node): StubType {
if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) {
$nestedTypeObjects = array_map(['Type', 'fromNode'], $node->types); $nestedTypeObjects = array_map(['StubType', 'fromNode'], $node->types);
$types = []; $types = [];
foreach ($nestedTypeObjects as $typeObject) { foreach ($nestedTypeObjects as $typeObject) {
array_push($types, ...$typeObject->types); array_push($types, ...$typeObject->types);
} }
return new Type($types, ($node instanceof Node\IntersectionType)); return new StubType($types, ($node instanceof Node\IntersectionType));
} }
if ($node instanceof Node\NullableType) { if ($node instanceof Node\NullableType) {
return new Type( return new StubType(
[ [
...Type::fromNode($node->type)->types, ...StubType::fromNode($node->type)->types,
SimpleType::null(), SimpleType::null(),
], ],
false false
@ -549,7 +549,7 @@ class Type {
} }
if ($node instanceof Node\Identifier && $node->toLowerString() === "iterable") { if ($node instanceof Node\Identifier && $node->toLowerString() === "iterable") {
return new Type( return new StubType(
[ [
SimpleType::fromString("Traversable"), SimpleType::fromString("Traversable"),
ArrayType::createGenericArray(), ArrayType::createGenericArray(),
@ -558,7 +558,7 @@ class Type {
); );
} }
return new Type([SimpleType::fromNode($node)], false); return new StubType([SimpleType::fromNode($node)], false);
} }
public static function fromString(string $typeString): self { public static function fromString(string $typeString): self {
@ -596,7 +596,7 @@ class Type {
} }
} }
return new Type($simpleTypes, $isIntersection); return new StubType($simpleTypes, $isIntersection);
} }
/** /**
@ -706,7 +706,7 @@ class Type {
return $typeElement; return $typeElement;
} }
public static function equals(?Type $a, ?Type $b): bool { public static function equals(?StubType $a, ?StubType $b): bool {
if ($a === null || $b === null) { if ($a === null || $b === null) {
return $a === $b; return $a === $b;
} }
@ -776,8 +776,8 @@ class ArgInfo {
public /* readonly */ string $name; public /* readonly */ string $name;
public /* readonly */ string $sendBy; public /* readonly */ string $sendBy;
public /* readonly */ bool $isVariadic; public /* readonly */ bool $isVariadic;
public ?Type $type; public ?StubType $type;
private /* readonly */ ?Type $phpDocType; private /* readonly */ ?StubType $phpDocType;
public ?string $defaultValue; public ?string $defaultValue;
/** @var AttributeInfo[] */ /** @var AttributeInfo[] */
public array $attributes; public array $attributes;
@ -789,8 +789,8 @@ class ArgInfo {
string $name, string $name,
string $sendBy, string $sendBy,
bool $isVariadic, bool $isVariadic,
?Type $type, ?StubType $type,
?Type $phpDocType, ?StubType $phpDocType,
?string $defaultValue, ?string $defaultValue,
array $attributes array $attributes
) { ) {
@ -807,11 +807,11 @@ class ArgInfo {
return $this->name === $other->name return $this->name === $other->name
&& $this->sendBy === $other->sendBy && $this->sendBy === $other->sendBy
&& $this->isVariadic === $other->isVariadic && $this->isVariadic === $other->isVariadic
&& Type::equals($this->type, $other->type) && StubType::equals($this->type, $other->type)
&& $this->defaultValue === $other->defaultValue; && $this->defaultValue === $other->defaultValue;
} }
public function getMethodSynopsisType(): Type { public function getMethodSynopsisType(): StubType {
if ($this->type) { if ($this->type) {
return $this->type; return $this->type;
} }
@ -1116,15 +1116,15 @@ class ReturnInfo {
private /* readonly */ bool $byRef; private /* readonly */ bool $byRef;
// NOT readonly - gets removed when discarding info for older PHP versions // NOT readonly - gets removed when discarding info for older PHP versions
public ?Type $type; public ?StubType $type;
public /* readonly */ ?Type $phpDocType; public /* readonly */ ?StubType $phpDocType;
public /* readonly */ bool $tentativeReturnType; public /* readonly */ bool $tentativeReturnType;
public /* readonly */ string $refcount; public /* readonly */ string $refcount;
public function __construct( public function __construct(
bool $byRef, bool $byRef,
?Type $type, ?StubType $type,
?Type $phpDocType, ?StubType $phpDocType,
bool $tentativeReturnType, bool $tentativeReturnType,
?string $refcount ?string $refcount
) { ) {
@ -1137,11 +1137,11 @@ class ReturnInfo {
public function equalsApartFromPhpDocAndRefcount(ReturnInfo $other): bool { public function equalsApartFromPhpDocAndRefcount(ReturnInfo $other): bool {
return $this->byRef === $other->byRef return $this->byRef === $other->byRef
&& Type::equals($this->type, $other->type) && StubType::equals($this->type, $other->type)
&& $this->tentativeReturnType === $other->tentativeReturnType; && $this->tentativeReturnType === $other->tentativeReturnType;
} }
public function getMethodSynopsisType(): ?Type { public function getMethodSynopsisType(): ?StubType {
return $this->type ?? $this->phpDocType; return $this->type ?? $this->phpDocType;
} }
@ -2513,8 +2513,8 @@ class EvaluatedValue
abstract class VariableLike abstract class VariableLike
{ {
protected int $flags; protected int $flags;
public ?Type $type; public ?StubType $type;
public /* readonly */ ?Type $phpDocType; public /* readonly */ ?StubType $phpDocType;
private /* readonly */ ?string $link; private /* readonly */ ?string $link;
protected ?int $phpVersionIdMinimumCompatibility; protected ?int $phpVersionIdMinimumCompatibility;
/** @var AttributeInfo[] */ /** @var AttributeInfo[] */
@ -2526,8 +2526,8 @@ abstract class VariableLike
*/ */
public function __construct( public function __construct(
int $flags, int $flags,
?Type $type, ?StubType $type,
?Type $phpDocType, ?StubType $phpDocType,
?string $link, ?string $link,
?int $phpVersionIdMinimumCompatibility, ?int $phpVersionIdMinimumCompatibility,
array $attributes, array $attributes,
@ -2684,8 +2684,8 @@ class ConstInfo extends VariableLike
int $flags, int $flags,
Expr $value, Expr $value,
?string $valueString, ?string $valueString,
?Type $type, ?StubType $type,
?Type $phpDocType, ?StubType $phpDocType,
bool $isDeprecated, bool $isDeprecated,
?string $cond, ?string $cond,
?string $cValue, ?string $cValue,
@ -3212,8 +3212,8 @@ class PropertyInfo extends VariableLike
PropertyName $name, PropertyName $name,
int $classFlags, int $classFlags,
int $flags, int $flags,
?Type $type, ?StubType $type,
?Type $phpDocType, ?StubType $phpDocType,
?Expr $defaultValue, ?Expr $defaultValue,
?string $defaultValueString, ?string $defaultValueString,
bool $isDocReadonly, bool $isDocReadonly,
@ -5018,11 +5018,11 @@ function parseFunctionLike(
throw new Exception("Only the last parameter can be variadic"); throw new Exception("Only the last parameter can be variadic");
} }
$type = $param->type ? Type::fromNode($param->type) : null; $type = $param->type ? StubType::fromNode($param->type) : null;
if ($type === null && !isset($docParamTypes[$varName])) { if ($type === null && !isset($docParamTypes[$varName])) {
$defaultParamType = getMagicMethodDefaultParamType($name, $i); $defaultParamType = getMagicMethodDefaultParamType($name, $i);
if ($defaultParamType !== null) { if ($defaultParamType !== null) {
$type = Type::fromString($defaultParamType); $type = StubType::fromString($defaultParamType);
} else { } else {
$docParamTypes[$varName] = 'mixed'; $docParamTypes[$varName] = 'mixed';
} }
@ -5052,7 +5052,7 @@ function parseFunctionLike(
$sendBy, $sendBy,
$param->variadic, $param->variadic,
$type, $type,
isset($docParamTypes[$varName]) ? Type::fromString($docParamTypes[$varName]) : null, isset($docParamTypes[$varName]) ? StubType::fromString($docParamTypes[$varName]) : null,
$defaultValue, $defaultValue,
AttributeInfo::createFromGroups($param->attrGroups) AttributeInfo::createFromGroups($param->attrGroups)
); );
@ -5072,8 +5072,8 @@ function parseFunctionLike(
$return = new ReturnInfo( $return = new ReturnInfo(
$func->returnsByRef(), $func->returnsByRef(),
$returnType ? Type::fromNode($returnType) : null, $returnType ? StubType::fromNode($returnType) : null,
$docReturnType ? Type::fromString($docReturnType) : null, $docReturnType ? StubType::fromString($docReturnType) : null,
$tentativeReturnType, $tentativeReturnType,
$refcount $refcount
); );
@ -5163,8 +5163,8 @@ function parseConstLike(
} }
} }
$constType = $type ? Type::fromNode($type) : null; $constType = $type ? StubType::fromNode($type) : null;
$constPhpDocType = $phpDocType ? Type::fromString($phpDocType) : null; $constPhpDocType = $phpDocType ? StubType::fromString($phpDocType) : null;
if ($const->value instanceof Expr\ConstFetch && if ($const->value instanceof Expr\ConstFetch &&
$const->value->name->toLowerString() === "null" && $const->value->name->toLowerString() === "null" &&
@ -5225,9 +5225,9 @@ function parseProperty(
} }
} }
$propertyType = $type ? Type::fromNode($type) : null; $propertyType = $type ? StubType::fromNode($type) : null;
if ($propertyType === null && !$phpDocType) { if ($propertyType === null && !$phpDocType) {
$propertyType = Type::fromString("mixed"); $propertyType = StubType::fromString("mixed");
} }
if ($property->default instanceof Expr\ConstFetch && if ($property->default instanceof Expr\ConstFetch &&
@ -5245,7 +5245,7 @@ function parseProperty(
$classFlags, $classFlags,
$flags, $flags,
$propertyType, $propertyType,
$phpDocType ? Type::fromString($phpDocType) : null, $phpDocType ? StubType::fromString($phpDocType) : null,
$property->default, $property->default,
$property->default ? $prettyPrinter->prettyPrintExpr($property->default) : null, $property->default ? $prettyPrinter->prettyPrintExpr($property->default) : null,
$isDocReadonly, $isDocReadonly,

@ -9,32 +9,36 @@
#[Attribute(Attribute::TARGET_CLASS)] #[Attribute(Attribute::TARGET_CLASS)]
final readonly class ExtensionProvider final readonly class ExtensionProvider
{ {
public const string Keyword = '*';
public function __construct(public string $target) public function __construct(public string $target)
{ {
} }
} }
class native_types /**
* Public compile-time type symbols shared by extension providers and std containers.
* This root class is deliberately distinct from the compiler-internal TypePhp\Type.
*/
final class Type
{ {
public const type_int = 'int'; public const string Int = 'int';
public const type_float = 'float'; public const string Float = 'float';
public const type_bool = 'bool'; public const string Bool = 'bool';
public const type_bigint = 'bigint'; public const string BigInt = 'bigint';
public const type_bigfloat = 'bigfloat'; public const string BigFloat = 'bigfloat';
public const type_decimal = 'decimal'; public const string Decimal = 'decimal';
public const string String = 'string';
public const string Array = 'array';
public const string Object = 'object';
public const string Any = 'any';
public const string Stream = 'stream';
public const string Box = 'box';
} }
class complex_types /** @deprecated Compiler directive retained independently of public type symbols. */
class native_types
{ {
public const type_any = 'any';
public const type_var = 'any';
public const type_variant = 'any';
public const type_str = 'string';
public const type_string = 'string';
public const type_array = 'array';
public const type_object = 'object';
public const type_stream = 'stream';
public const type_box = 'box';
} }
class std class std
@ -101,7 +105,13 @@ function any(mixed $var): mixed
return $var; return $var;
} }
/**
* @throws Exception
*/
function objval(mixed $var, string $className): mixed function objval(mixed $var, string $className): mixed
{ {
if (!$var instanceof $className) {
throw new \Exception("Invalid object type: " . get_class($var) . " expected " . $className);
}
return $var; return $var;
} }

@ -5,7 +5,7 @@ Keyword ExtensionProvider method with snake_case name
declare(strict_types=1); declare(strict_types=1);
use native_types; use native_types;
#[ExtensionProvider(complex_types::type_any)] #[ExtensionProvider(ExtensionProvider::Keyword)]
final class KeywordExtensions final class KeywordExtensions
{ {
public static function var_dump(mixed $var): void public static function var_dump(mixed $var): void

@ -6,7 +6,7 @@ Keyword ExtensionProvider method with lowerCamelCase name
declare(strict_types=1); declare(strict_types=1);
use native_types; use native_types;
#[ExtensionProvider(complex_types::type_any)] #[ExtensionProvider(ExtensionProvider::Keyword)]
final class KeywordExtensions final class KeywordExtensions
{ {
public static function inspectValue(mixed $value, string $prefix): void public static function inspectValue(mixed $value, string $prefix): void
@ -15,11 +15,24 @@ final class KeywordExtensions
} }
} }
#[ExtensionProvider(Type::Any)]
final class AnyExtensions
{
public static function dynamicType(mixed $value): string
{
return get_debug_type($value);
}
}
function main(): void function main(): void
{ {
$value = 42; $value = 42;
$value->inspectValue('number'); $value->inspectValue('number');
$dynamic = $value->toAny();
echo $dynamic->dynamicType(), "\n";
} }
?> ?>
--EXPECT-- --EXPECT--
number:42 number:42
int

@ -3,7 +3,7 @@ std array: 001
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$array = std::array(native_types::type_int, 100); $array = std::array(Type::Int, 100);
$array[99] = 2026; $array[99] = 2026;
var_dump($array[99]); var_dump($array[99]);
var_dump($array[10]); var_dump($array[10]);

@ -3,7 +3,7 @@ std array: 002
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$array = std::array(std::array(std::array(native_types::type_int, 13), 16), 19); $array = std::array(std::array(std::array(Type::Int, 13), 16), 19);
$index = 9; $index = 9;
$index2 = 5; $index2 = 5;
$array[$index2][$index][0] = 2026; $array[$index2][$index][0] = 2026;

@ -3,7 +3,7 @@ std array: 003
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$array = std::array(std::array(std::array(native_types::type_int, 13), 16), 19); $array = std::array(std::array(std::array(Type::Int, 13), 16), 19);
$index = 9; $index = 9;
$index2 = 5; $index2 = 5;
$array[$index2][$index][0] = 2026; $array[$index2][$index][0] = 2026;

@ -3,14 +3,14 @@ std array: 004
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$array = std::array(native_types::type_float, 100); $array = std::array(Type::Float, 100);
$array[99] = 2026.22; $array[99] = 2026.22;
$array[33] = 3.1415; $array[33] = 3.1415;
var_dump($array[99] == 2026.22); var_dump($array[99] == 2026.22);
var_dump($array[33] == 3.1415); var_dump($array[33] == 3.1415);
var_dump($array[11] == 0); var_dump($array[11] == 0);
$array2 = std::array(native_types::type_bool, 100); $array2 = std::array(Type::Bool, 100);
$array2[99] = 2026.22; $array2[99] = 2026.22;
$array2[33] = ""; $array2[33] = "";
var_dump($array2[99] === true); var_dump($array2[99] === true);

@ -15,23 +15,23 @@ class StdArrayComplexValue
} }
function main() { function main() {
$strings = std::array(complex_types::type_string, 2); $strings = std::array(Type::String, 2);
$strings[0] = 321; $strings[0] = 321;
var_dump($strings[0]); var_dump($strings[0]);
$arrays = std::array(complex_types::type_array, 2); $arrays = std::array(Type::Array, 2);
$arrays[0] = ["name" => "array", "value" => 64]; $arrays[0] = ["name" => "array", "value" => 64];
$array = $arrays[0]; $array = $arrays[0];
var_dump($array["name"]); var_dump($array["name"]);
var_dump($array["value"]); var_dump($array["value"]);
$objects = std::array(complex_types::type_object, 2); $objects = std::array(Type::Object, 2);
$objects[0] = new StdArrayComplexValue(28); $objects[0] = new StdArrayComplexValue(28);
var_dump($objects[0] instanceof StdArrayComplexValue); var_dump($objects[0] instanceof StdArrayComplexValue);
$object = $objects[0]->toObject(StdArrayComplexValue::class); $object = $objects[0]->toObject(StdArrayComplexValue::class);
var_dump($object->getValue()); var_dump($object->getValue());
$variants = std::array(complex_types::type_any, 2); $variants = std::array(Type::Any, 2);
$variants[0] = 123; $variants[0] = 123;
$variants[1] = "variant"; $variants[1] = "variant";
var_dump($variants[0]); var_dump($variants[0]);

@ -4,13 +4,13 @@ std array: unsafe_cast
<?php <?php
function std_array_unsafe_ptr_update($source): void function std_array_unsafe_ptr_update($source): void
{ {
$array = $source->toStdArray(native_types::type_int, 3); $array = $source->toStdArray(Type::Int, 3);
var_dump($array[1]); var_dump($array[1]);
$array[2] = 9; $array[2] = 9;
} }
function main() { function main() {
$array = std::array(native_types::type_int, 3); $array = std::array(Type::Int, 3);
$array[0] = 1; $array[0] = 1;
$array[1] = 7; $array[1] = 7;
$array[2] = 3; $array[2] = 3;

@ -4,11 +4,11 @@ std array: unsafe_cast type mismatch
<?php <?php
function std_array_unsafe_ptr_type_mismatch($source): void function std_array_unsafe_ptr_type_mismatch($source): void
{ {
$array = $source->toStdArray(native_types::type_float, 3); $array = $source->toStdArray(Type::Float, 3);
} }
function main() { function main() {
$array = std::array(native_types::type_int, 3); $array = std::array(Type::Int, 3);
try { try {
std_array_unsafe_ptr_type_mismatch($array); std_array_unsafe_ptr_type_mismatch($array);
} catch (TypeError $e) { } catch (TypeError $e) {

@ -3,7 +3,7 @@ std array: assign to PHP array
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$array = std::array(native_types::type_int, 3); $array = std::array(Type::Int, 3);
$array[0] = 10; $array[0] = 10;
$array[1] = 20; $array[1] = 20;
$array[2] = 30; $array[2] = 30;

@ -3,8 +3,8 @@ std array: nested same type copy
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$a = std::array(native_types::type_int, 3); $a = std::array(Type::Int, 3);
$b = std::array(std::array(native_types::type_int, 3), 2); $b = std::array(std::array(Type::Int, 3), 2);
$b[1][0] = 10; $b[1][0] = 10;
$b[1][1] = 20; $b[1][1] = 20;

@ -3,7 +3,7 @@ std array: unset
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$a = std::array(native_types::type_int, 30); $a = std::array(Type::Int, 30);
$a[11] = 99; $a[11] = 99;
var_dump($a[11]); var_dump($a[11]);
unset($a[11]); unset($a[11]);

@ -3,7 +3,7 @@ std array: foreach
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$a = std::array(native_types::type_int, 5); $a = std::array(Type::Int, 5);
foreach($a as $k => $item) { foreach($a as $k => $item) {
$a[$k] = random_int(1, 1000); $a[$k] = random_int(1, 1000);
} }

@ -4,7 +4,7 @@ std bigfloat: vector push_back and read
<?php <?php
function main() { function main() {
$v = std::vector(native_types::type_bigfloat); $v = std::vector(Type::BigFloat);
$v[] = 3.14; $v[] = 3.14;
$v[] = 2.71; $v[] = 2.71;
$v[] = 100; $v[] = 100;

@ -4,7 +4,7 @@ std bigint: vector push_back and read
<?php <?php
function main() { function main() {
$v = std::vector(native_types::type_bigint); $v = std::vector(Type::BigInt);
$v[] = 99; $v[] = 99;
$v[] = 88; $v[] = 88;
$v[] = 77; $v[] = 77;

@ -4,7 +4,7 @@ std bigint: map set/get
<?php <?php
function main() { function main() {
$m = std::map(native_types::type_int, native_types::type_bigint); $m = std::map(Type::Int, Type::BigInt);
$m[1] = 100; $m[1] = 100;
$m[2] = 200; $m[2] = 200;
$m[3] = 300; $m[3] = 300;

@ -4,7 +4,7 @@ std bigint: array write/read
<?php <?php
function main() { function main() {
$a = std::array(native_types::type_bigint, 5); $a = std::array(Type::BigInt, 5);
$a[0] = 42; $a[0] = 42;
$a[1] = 84; $a[1] = 84;
$a[2] = 126; $a[2] = 126;

@ -4,7 +4,7 @@ std bigint: foreach
<?php <?php
function main() { function main() {
$v = std::vector(native_types::type_bigint); $v = std::vector(Type::BigInt);
$v[] = 10; $v[] = 10;
$v[] = 20; $v[] = 20;
$v[] = 30; $v[] = 30;

@ -4,7 +4,7 @@ std decimal: vector push_back and read
<?php <?php
function main() { function main() {
$v = std::vector(native_types::type_decimal); $v = std::vector(Type::Decimal);
$v[] = 3.14; $v[] = 3.14;
$v[] = 2.5; $v[] = 2.5;
$v[] = 100; $v[] = 100;

@ -3,7 +3,7 @@ std map: 001
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::map(native_types::type_int, native_types::type_int); $map = std::map(Type::Int, Type::Int);
$map[10] = 32; $map[10] = 32;
$map[10] += 10; $map[10] += 10;
$map[20] = 7; $map[20] = 7;

@ -3,7 +3,7 @@ std map: string key
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::map(complex_types::type_string, native_types::type_float); $map = std::map(Type::String, Type::Float);
$map["alpha"] = 1.5; $map["alpha"] = 1.5;
$map["beta"] = 2.5; $map["beta"] = 2.5;
$map["beta"] += 0.25; $map["beta"] += 0.25;
@ -13,7 +13,7 @@ function main() {
var_dump($map["beta"] == 2.75); var_dump($map["beta"] == 2.75);
var_dump(count($map)); var_dump(count($map));
$map2 = std::map(complex_types::type_str, native_types::type_int); $map2 = std::map(Type::String, Type::Int);
$map2["answer"] = 42; $map2["answer"] = 42;
var_dump($map2["answer"]); var_dump($map2["answer"]);
} }

@ -15,23 +15,23 @@ class StdMapComplexValue
} }
function main() { function main() {
$strings = std::map(native_types::type_int, complex_types::type_string); $strings = std::map(Type::Int, Type::String);
$strings[1] = 789; $strings[1] = 789;
var_dump($strings[1]); var_dump($strings[1]);
$arrays = std::map(complex_types::type_string, complex_types::type_array); $arrays = std::map(Type::String, Type::Array);
$arrays["item"] = ["name" => "unordered", "value" => 168]; $arrays["item"] = ["name" => "unordered", "value" => 168];
$array = $arrays["item"]; $array = $arrays["item"];
var_dump($array["name"]); var_dump($array["name"]);
var_dump($array["value"]); var_dump($array["value"]);
$objects = std::map(native_types::type_int, complex_types::type_object); $objects = std::map(Type::Int, Type::Object);
$objects[2] = new StdMapComplexValue(21); $objects[2] = new StdMapComplexValue(21);
var_dump($objects[2] instanceof StdMapComplexValue); var_dump($objects[2] instanceof StdMapComplexValue);
$object = $objects[2]->toObject(StdMapComplexValue::class); $object = $objects[2]->toObject(StdMapComplexValue::class);
var_dump($object->getValue()); var_dump($object->getValue());
$variants = std::map(native_types::type_int, complex_types::type_var); $variants = std::map(Type::Int, Type::Any);
$variants[3] = false; $variants[3] = false;
$variants[4] = "variant"; $variants[4] = "variant";
var_dump($variants[3]); var_dump($variants[3]);

@ -24,7 +24,7 @@ function std_map_class_value_mixed(mixed $value): mixed
} }
function main() { function main() {
$map = std::map(complex_types::type_str, StdMapClassValue::class); $map = std::map(Type::String, StdMapClassValue::class);
$map["a"] = new StdMapClassValue(1); $map["a"] = new StdMapClassValue(1);
var_dump($map["a"]->getValue()); var_dump($map["a"]->getValue());

@ -4,13 +4,13 @@ std map: unsafe_cast
<?php <?php
function std_map_unsafe_ptr_update($source): void function std_map_unsafe_ptr_update($source): void
{ {
$map = $source->toStdMap(native_types::type_int, native_types::type_int); $map = $source->toStdMap(Type::Int, Type::Int);
var_dump($map[2]); var_dump($map[2]);
$map[3] = 9; $map[3] = 9;
} }
function main() { function main() {
$map = std::map(native_types::type_int, native_types::type_int); $map = std::map(Type::Int, Type::Int);
$map[1] = 1; $map[1] = 1;
$map[2] = 7; $map[2] = 7;
$map[3] = 3; $map[3] = 3;

@ -4,11 +4,11 @@ std map: unsafe_cast type mismatch
<?php <?php
function std_map_unsafe_ptr_type_mismatch($source): void function std_map_unsafe_ptr_type_mismatch($source): void
{ {
$map = $source->toStdMap(native_types::type_int, native_types::type_float); $map = $source->toStdMap(Type::Int, Type::Float);
} }
function main() { function main() {
$map = std::map(native_types::type_int, native_types::type_int); $map = std::map(Type::Int, Type::Int);
try { try {
std_map_unsafe_ptr_type_mismatch($map); std_map_unsafe_ptr_type_mismatch($map);
} catch (TypeError $e) { } catch (TypeError $e) {

@ -3,7 +3,7 @@ std map: assign to PHP array
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::map(native_types::type_int, native_types::type_int); $map = std::map(Type::Int, Type::Int);
$map[10] = 100; $map[10] = 100;
$map[20] = 200; $map[20] = 200;

@ -3,8 +3,8 @@ std map: same type copy
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$a = std::map(native_types::type_int, native_types::type_int); $a = std::map(Type::Int, Type::Int);
$b = std::map(native_types::type_int, native_types::type_int); $b = std::map(Type::Int, Type::Int);
$b[10] = 100; $b[10] = 100;
$b[20] = 200; $b[20] = 200;

@ -3,7 +3,7 @@ std map: unset
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::map(complex_types::type_string, native_types::type_int); $map = std::map(Type::String, Type::Int);
$map["alpha"] = 10; $map["alpha"] = 10;
$map["beta"] = 20; $map["beta"] = 20;

@ -3,7 +3,7 @@ std map: unset
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::map(complex_types::type_string, native_types::type_int); $map = std::map(Type::String, Type::Int);
$map["alpha"] = 10; $map["alpha"] = 10;
$map["beta"] = 20; $map["beta"] = 20;
$map["gamma"] = 30; $map["gamma"] = 30;

@ -3,7 +3,7 @@ std ordered_map: 001
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::ordered_map(native_types::type_int, native_types::type_float); $map = std::ordered_map(Type::Int, Type::Float);
$map[10] = 1.25; $map[10] = 1.25;
$map[10] += 0.75; $map[10] += 0.75;
$map[11] = 3.5; $map[11] = 3.5;

@ -3,7 +3,7 @@ std ordered_map: string key
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::ordered_map(complex_types::type_string, native_types::type_int); $map = std::ordered_map(Type::String, Type::Int);
$map["alpha"] = 10; $map["alpha"] = 10;
$map["beta"] = 20; $map["beta"] = 20;
$map["beta"] += 22; $map["beta"] += 22;
@ -13,7 +13,7 @@ function main() {
var_dump($map["beta"]); var_dump($map["beta"]);
var_dump(count($map)); var_dump(count($map));
$map2 = std::ordered_map(complex_types::type_str, native_types::type_float); $map2 = std::ordered_map(Type::String, Type::Float);
$map2["pi"] = 3.14; $map2["pi"] = 3.14;
var_dump($map2["pi"] == 3.14); var_dump($map2["pi"] == 3.14);
} }

@ -15,23 +15,23 @@ class StdMapComplexValue
} }
function main() { function main() {
$strings = std::ordered_map(native_types::type_int, complex_types::type_str); $strings = std::ordered_map(Type::Int, Type::String);
$strings[1] = 456; $strings[1] = 456;
var_dump($strings[1]); var_dump($strings[1]);
$arrays = std::ordered_map(native_types::type_int, complex_types::type_array); $arrays = std::ordered_map(Type::Int, Type::Array);
$arrays[2] = ["name" => "map", "value" => 84]; $arrays[2] = ["name" => "map", "value" => 84];
$array = $arrays[2]; $array = $arrays[2];
var_dump($array["name"]); var_dump($array["name"]);
var_dump($array["value"]); var_dump($array["value"]);
$objects = std::ordered_map(complex_types::type_string, complex_types::type_object); $objects = std::ordered_map(Type::String, Type::Object);
$objects["item"] = new StdMapComplexValue(14); $objects["item"] = new StdMapComplexValue(14);
var_dump($objects["item"] instanceof StdMapComplexValue); var_dump($objects["item"] instanceof StdMapComplexValue);
$object = $objects["item"]->toObject(StdMapComplexValue::class); $object = $objects["item"]->toObject(StdMapComplexValue::class);
var_dump($object->getValue()); var_dump($object->getValue());
$variants = std::ordered_map(native_types::type_int, complex_types::type_any); $variants = std::ordered_map(Type::Int, Type::Any);
$variants[3] = 12.5; $variants[3] = 12.5;
$variants[4] = "any"; $variants[4] = "any";
var_dump($variants[3]); var_dump($variants[3]);

@ -28,7 +28,7 @@ function std_container_class_value_mixed(mixed $value): mixed
} }
function main() { function main() {
$map = std::ordered_map(complex_types::type_str, StdContainerClassValue::class); $map = std::ordered_map(Type::String, StdContainerClassValue::class);
$map["a"] = new StdContainerClassValue(1); $map["a"] = new StdContainerClassValue(1);
$item = $map["a"]; $item = $map["a"];
var_dump($item->getValue()); var_dump($item->getValue());
@ -41,7 +41,7 @@ function main() {
$array[0] = new StdContainerClassValue(3); $array[0] = new StdContainerClassValue(3);
var_dump($array[0]->getValue()); var_dump($array[0]->getValue());
$unordered = std::map(native_types::type_int, StdContainerClassValue::class); $unordered = std::map(Type::Int, StdContainerClassValue::class);
$unordered[1] = std_container_class_value_mixed(new StdContainerClassValue(4)); $unordered[1] = std_container_class_value_mixed(new StdContainerClassValue(4));
var_dump($unordered[1]->getValue()); var_dump($unordered[1]->getValue());

@ -4,7 +4,7 @@ std ordered_map: unsafe_cast
<?php <?php
function std_map_unsafe_ptr_update($source): void function std_map_unsafe_ptr_update($source): void
{ {
$map = $source->toStdOrderedMap(complex_types::type_str, native_types::type_int); $map = $source->toStdOrderedMap(Type::String, Type::Int);
var_dump($map["b"]); var_dump($map["b"]);
$map["c"] = 9; $map["c"] = 9;
@ -15,7 +15,7 @@ function std_map_unsafe_ptr_update($source): void
} }
function main() { function main() {
$map = std::ordered_map(complex_types::type_str, native_types::type_int); $map = std::ordered_map(Type::String, Type::Int);
$map["a"] = 1; $map["a"] = 1;
$map["b"] = 7; $map["b"] = 7;
$map["c"] = 3; $map["c"] = 3;

@ -4,11 +4,11 @@ std ordered_map: unsafe_cast type mismatch
<?php <?php
function std_map_unsafe_ptr_type_mismatch($source): void function std_map_unsafe_ptr_type_mismatch($source): void
{ {
$map = $source->toStdMap(complex_types::type_str, native_types::type_float); $map = $source->toStdMap(Type::String, Type::Float);
} }
function main() { function main() {
$map = std::ordered_map(complex_types::type_str, native_types::type_int); $map = std::ordered_map(Type::String, Type::Int);
try { try {
std_map_unsafe_ptr_type_mismatch($map); std_map_unsafe_ptr_type_mismatch($map);
} catch (TypeError $e) { } catch (TypeError $e) {

@ -3,7 +3,7 @@ std ordered_map: assign to PHP array
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::ordered_map(native_types::type_int, native_types::type_int); $map = std::ordered_map(Type::Int, Type::Int);
$map[10] = 100; $map[10] = 100;
$map[20] = 200; $map[20] = 200;

@ -3,8 +3,8 @@ std ordered_map: same type copy
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$a = std::ordered_map(native_types::type_int, native_types::type_int); $a = std::ordered_map(Type::Int, Type::Int);
$b = std::ordered_map(native_types::type_int, native_types::type_int); $b = std::ordered_map(Type::Int, Type::Int);
$b[10] = 100; $b[10] = 100;
$b[20] = 200; $b[20] = 200;

@ -3,7 +3,7 @@ std ordered_map: unset
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::ordered_map(complex_types::type_string, native_types::type_int); $map = std::ordered_map(Type::String, Type::Int);
$map["alpha"] = 10; $map["alpha"] = 10;
$map["beta"] = 20; $map["beta"] = 20;
var_dump($map); var_dump($map);

@ -3,7 +3,7 @@ std ordered_map: unset
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$map = std::ordered_map(complex_types::type_string, native_types::type_int); $map = std::ordered_map(Type::String, Type::Int);
$map["alpha"] = 10; $map["alpha"] = 10;
$map["beta"] = 20; $map["beta"] = 20;
$map["gamma"] = 30; $map["gamma"] = 30;

@ -4,7 +4,7 @@ std stream: vector push_back and use
<?php <?php
function main() { function main() {
$v = std::vector(complex_types::type_stream); $v = std::vector(Type::Stream);
$tmpfile = tempnam(sys_get_temp_dir(), 'aot'); $tmpfile = tempnam(sys_get_temp_dir(), 'aot');
$fp = fopen($tmpfile, 'w+'); $fp = fopen($tmpfile, 'w+');

@ -3,7 +3,7 @@ std vector: 001
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$vector = std::vector(native_types::type_int); $vector = std::vector(Type::Int);
$vector[] = 1; $vector[] = 1;
$vector[] = 2; $vector[] = 2;
$vector[1] += 40; $vector[1] += 40;
@ -12,7 +12,7 @@ function main() {
var_dump($vector[1]); var_dump($vector[1]);
var_dump(count($vector)); var_dump(count($vector));
$floatVector = std::vector(native_types::type_float, 2); $floatVector = std::vector(Type::Float, 2);
$floatVector[0] = 3.14; $floatVector[0] = 3.14;
var_dump($floatVector[0] == 3.14); var_dump($floatVector[0] == 3.14);
var_dump($floatVector[1] == 0.0); var_dump($floatVector[1] == 0.0);

@ -15,23 +15,23 @@ class StdVectorComplexValue
} }
function main() { function main() {
$strings = std::vector(complex_types::type_string); $strings = std::vector(Type::String);
$strings[] = 123; $strings[] = 123;
var_dump($strings[0]); var_dump($strings[0]);
$arrays = std::vector(complex_types::type_array); $arrays = std::vector(Type::Array);
$arrays[] = ["name" => "vector", "value" => 42]; $arrays[] = ["name" => "vector", "value" => 42];
$array = $arrays[0]; $array = $arrays[0];
var_dump($array["name"]); var_dump($array["name"]);
var_dump($array["value"]); var_dump($array["value"]);
$objects = std::vector(complex_types::type_object); $objects = std::vector(Type::Object);
$objects[] = new StdVectorComplexValue(7); $objects[] = new StdVectorComplexValue(7);
var_dump($objects[0] instanceof StdVectorComplexValue); var_dump($objects[0] instanceof StdVectorComplexValue);
$object = $objects[0]->toObject(StdVectorComplexValue::class); $object = $objects[0]->toObject(StdVectorComplexValue::class);
var_dump($object->getValue()); var_dump($object->getValue());
$variants = std::vector(complex_types::type_variant); $variants = std::vector(Type::Any);
$variants[] = 99; $variants[] = 99;
$variants[] = "mixed"; $variants[] = "mixed";
var_dump($variants[0]); var_dump($variants[0]);

@ -4,13 +4,13 @@ std vector: unsafe_cast
<?php <?php
function std_vector_unsafe_ptr_update($source): void function std_vector_unsafe_ptr_update($source): void
{ {
$vector = $source->toStdVector(native_types::type_int); $vector = $source->toStdVector(Type::Int);
var_dump($vector[1]); var_dump($vector[1]);
$vector[2] = 9; $vector[2] = 9;
} }
function main() { function main() {
$vector = std::vector(native_types::type_int, 3); $vector = std::vector(Type::Int, 3);
$vector[0] = 1; $vector[0] = 1;
$vector[1] = 7; $vector[1] = 7;
$vector[2] = 3; $vector[2] = 3;

@ -4,11 +4,11 @@ std vector: unsafe_cast type mismatch
<?php <?php
function std_vector_unsafe_ptr_type_mismatch($source): void function std_vector_unsafe_ptr_type_mismatch($source): void
{ {
$vector = $source->toStdVector(native_types::type_float); $vector = $source->toStdVector(Type::Float);
} }
function main() { function main() {
$vector = std::vector(native_types::type_int, 3); $vector = std::vector(Type::Int, 3);
try { try {
std_vector_unsafe_ptr_type_mismatch($vector); std_vector_unsafe_ptr_type_mismatch($vector);
} catch (TypeError $e) { } catch (TypeError $e) {

@ -3,7 +3,7 @@ std vector: assign to PHP array
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$vector = std::vector(native_types::type_int); $vector = std::vector(Type::Int);
$vector[] = 10; $vector[] = 10;
$vector[] = 20; $vector[] = 20;

@ -3,8 +3,8 @@ std vector: same type copy
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$a = std::vector(native_types::type_int); $a = std::vector(Type::Int);
$b = std::vector(native_types::type_int); $b = std::vector(Type::Int);
$b[] = 10; $b[] = 10;
$b[] = 20; $b[] = 20;

@ -3,7 +3,7 @@ std vector: unset
--FILE-- --FILE--
<?php <?php
function main() { function main() {
$a = std::vector(native_types::type_int); $a = std::vector(Type::Int);
$a[] = 99; $a[] = 99;
$a[] = 88; $a[] = 88;
$a[] = 77; $a[] = 77;

@ -4,7 +4,7 @@ std vector: foreach
<?php <?php
use native_types; use native_types;
function main() { function main() {
$a = std::vector(native_types::type_int); $a = std::vector(Type::Int);
$n = 5; $n = 5;
while($n--){ while($n--){
$a[] = random_int(1, 1000); $a[] = random_int(1, 1000);

@ -39,11 +39,11 @@ function main() {
$array[0] = std_container_interface_mixed(new StdContainerInterfaceImpl(3)); $array[0] = std_container_interface_mixed(new StdContainerInterfaceImpl(3));
var_dump($array[0]->getValue()); var_dump($array[0]->getValue());
$map = std::map(complex_types::type_str, StdContainerInterfaceValue::class); $map = std::map(Type::String, StdContainerInterfaceValue::class);
$map["item"] = std_container_interface_mixed(new StdContainerInterfaceImpl(4)); $map["item"] = std_container_interface_mixed(new StdContainerInterfaceImpl(4));
var_dump($map["item"]->getValue()); var_dump($map["item"]->getValue());
$ordered = std::ordered_map(complex_types::type_str, StdContainerInterfaceValue::class); $ordered = std::ordered_map(Type::String, StdContainerInterfaceValue::class);
$ordered["item"] = std_container_interface_mixed(new StdContainerInterfaceImpl(5)); $ordered["item"] = std_container_interface_mixed(new StdContainerInterfaceImpl(5));
var_dump($ordered["item"]->getValue()); var_dump($ordered["item"]->getValue());

@ -3,7 +3,7 @@ stream extension method support
--FILE-- --FILE--
<?php <?php
#[ExtensionProvider(complex_types::type_stream)] #[ExtensionProvider(Type::Stream)]
final class StreamExtensions final class StreamExtensions
{ {
public static function readChunk(stream $stream, int $size): string public static function readChunk(stream $stream, int $size): string

@ -5,7 +5,7 @@ Universal methods provided by ExtensionProvider classes
use native_types; use native_types;
#[ExtensionProvider(native_types::type_int)] #[ExtensionProvider(Type::Int)]
final class IntExtensions final class IntExtensions
{ {
public static function to_bytes(int $int, string $unit = 'Kb'): string public static function to_bytes(int $int, string $unit = 'Kb'): string
@ -14,7 +14,7 @@ final class IntExtensions
} }
} }
#[ExtensionProvider(complex_types::type_array)] #[ExtensionProvider(Type::Array)]
final class ArrayExtensions final class ArrayExtensions
{ {
public static function get_first_element(array $array): mixed public static function get_first_element(array $array): mixed
@ -23,7 +23,7 @@ final class ArrayExtensions
} }
} }
#[ExtensionProvider(complex_types::type_string)] #[ExtensionProvider(Type::String)]
final class StringExtensions final class StringExtensions
{ {
public static function shout(string $str): string public static function shout(string $str): string

@ -5,7 +5,7 @@ Universal ExtensionProvider methods use their declared names
use native_types; use native_types;
#[ExtensionProvider(native_types::type_int)] #[ExtensionProvider(Type::Int)]
final class IntExtensions final class IntExtensions
{ {
public static function toBytes(int $value): string public static function toBytes(int $value): string
@ -14,7 +14,7 @@ final class IntExtensions
} }
} }
#[ExtensionProvider(complex_types::type_array)] #[ExtensionProvider(Type::Array)]
final class ArrayExtensions final class ArrayExtensions
{ {
public static function getFirstElement(array $value): mixed public static function getFirstElement(array $value): mixed

@ -5,7 +5,7 @@ ExtensionProvider method chaining with typed returns
use native_types; use native_types;
#[ExtensionProvider(native_types::type_int)] #[ExtensionProvider(Type::Int)]
final class IntExtensions final class IntExtensions
{ {
public static function to_words(int $int): string public static function to_words(int $int): string
@ -15,7 +15,7 @@ final class IntExtensions
} }
} }
#[ExtensionProvider(complex_types::type_string)] #[ExtensionProvider(Type::String)]
final class StringExtensions final class StringExtensions
{ {
public static function double(string $str): string public static function double(string $str): string
@ -34,7 +34,7 @@ final class StringExtensions
} }
} }
#[ExtensionProvider(complex_types::type_array)] #[ExtensionProvider(Type::Array)]
final class ArrayExtensions final class ArrayExtensions
{ {
public static function last(array $arr): mixed public static function last(array $arr): mixed

@ -5,7 +5,7 @@ Universal method provider may wrap a PHP internal function
use native_types; use native_types;
#[ExtensionProvider(complex_types::type_string)] #[ExtensionProvider(Type::String)]
final class StringExtensions final class StringExtensions
{ {
public static function rot13(string $value): string public static function rot13(string $value): string

Loading…
Cancel
Save