refactor(aot): 重构标准容器实现将unordered_map重命名为ordered_map

- 将StdUnorderedMap重命名为StdOrderedMap并在所有相关文件中更新引用
- 修改polyfills.php中std::unordered_map为std::ordered_map,std::map为std::unordered_map
- 更新文档中关于标准容器的命名和功能描述
- 修复所有测试文件中关于容器类型的断言和期望值
- 调整编译器内部类型标识符从TYPE_STD_UNORDERED_MAP到TYPE_STD_ORDERED_MAP
- 修改解析器中对标准容器类型的判断和处理逻辑
- 更新单元测试中的类型检查和声明获取方法
pull/3/head
韩天峰 2 months ago
parent 18b4bf4ed6
commit b3e489d334
  1. 14
      docs/PATENT_01_CPP_TEMPLATE_TYPED_CONTAINER.md
  2. 32
      docs/STD_CONTAINERS.md
  3. 20
      phpunit/src/TraitsTest.php
  4. 6
      src/Php/CompilerBase.php
  5. 8
      src/Php/Parser/AssignOpTrait.php
  6. 26
      src/Php/Parser/StdContainerTrait.php
  7. 4
      src/polyfills.php
  8. 16
      tests/aot/std-map/001.phpt
  9. 24
      tests/aot/std-map/002.phpt
  10. 36
      tests/aot/std-map/003.phpt
  11. 45
      tests/aot/std-map/004.phpt
  12. 22
      tests/aot/std-map/005.phpt
  13. 4
      tests/aot/std-map/006.phpt
  14. 4
      tests/aot/std-map/009.phpt
  15. 12
      tests/aot/std-map/010.phpt
  16. 19
      tests/aot/std-unordered-map/001.phpt
  17. 25
      tests/aot/std-unordered-map/002.phpt
  18. 48
      tests/aot/std-unordered-map/003.phpt
  19. 44
      tests/aot/std-unordered-map/004.phpt
  20. 24
      tests/aot/std-unordered-map/005.phpt
  21. 20
      tests/aot/std-unordered-map/006.phpt
  22. 21
      tests/aot/std-unordered-map/007.phpt
  23. 25
      tests/aot/std-unordered-map/008.phpt
  24. 24
      tests/aot/std-unordered-map/009.phpt
  25. 32
      tests/aot/std-unordered-map/010.phpt

@ -105,8 +105,8 @@ Swoole-Compiler 是一种 PHP AOT 编译器。它将 PHP 源文件解析为抽
```php
$a = std::array(native_types::type_int, 100);
$v = std::vector(native_types::type_float);
$m = std::map(complex_types::type_str, native_types::type_int);
$h = std::unordered_map(native_types::type_int, User::class);
$m = std::ordered_map(complex_types::type_str, native_types::type_int);
$h = std::map(native_types::type_int, User::class);
```
编译器在 AOT 阶段识别这些构造表达式,生成容器元信息,并将其转换为 C++ 模版实例:
@ -114,8 +114,8 @@ $h = std::unordered_map(native_types::type_int, User::class);
```cpp
php::StdArray<php::Int, 100> a{};
php::StdVector<php::Float> v{};
php::StdMap<php::Str, php::Int> m{};
php::StdUnorderedMap<php::Int, php::Object> h{};
php::StdOrderedMap<php::Str, php::Int> m{};
php::StdMap<php::Int, php::Object> h{};
```
编译器后续在下标访问、赋值、遍历、函数传参和类型转换时均使用该元信息进行静态检查和代码生成。
@ -191,11 +191,11 @@ PHP 扩展或二进制程序
容器元信息至少包括以下字段:
```text
kind:容器种类,例如 array、vector、map、unordered_map;
kind:容器种类,例如 array、vector、map、ordered_map;
decl:目标 C++ 模版声明;
type:value 的 C++ 类型;
class:value 为对象时的类名;
keyType:map 或 unordered_map 的 key 类型;
keyType:map 或 ordered_map 的 key 类型;
sizes:std::array 的维度数组;
bytes:std::array 的预计内存大小;
typeId:根据上述字段生成的类型标识。
@ -399,7 +399,7 @@ uint32_t type_id;
本发明不限于 PHP 语言,也可用于 Python、JavaScript、Ruby 等动态语言的 AOT 编译器。只要动态语言编译器能够识别强类型容器声明,并生成 C++、Rust、Go 或其他静态语言目标代码,均可采用类似技术方案。
本发明中的 C++ 模版容器也不限于 `StdArray`、`StdVector`、`StdMap`、`StdUnorderedMap`,可扩展为队列、集合、环形缓冲区、矩阵、张量等强类型容器。
本发明中的 C++ 模版容器也不限于 `StdArray`、`StdVector`、`StdOrderedMap`、`StdMap`,可扩展为队列、集合、环形缓冲区、矩阵、张量等强类型容器。
## 9. 保密说明

@ -90,8 +90,8 @@ Swoole AOT 提供 `std` 容器,用来表达“这个容器的结构和元素
- `std::array`
- `std::vector`
- `std::ordered_map`
- `std::map`
- `std::unordered_map`
它们的目标不是完全替代 PHP Array,而是用于性能敏感、结构稳定、类型明确的代码路径。
@ -196,14 +196,14 @@ $b[] = 20;
$a = $b; // 允许,类型完全一致,执行容器 copy
```
## std::map
## std::ordered_map
`std::map` 是有序 key-value 容器。
`std::ordered_map` 是有序 key-value 容器。
```php
function main(): void
{
$map = std::map(
$map = std::ordered_map(
complex_types::type_str,
native_types::type_int
);
@ -225,30 +225,30 @@ function main(): void
示例:
```php
$map = std::map(native_types::type_int, native_types::type_float);
$map = std::ordered_map(native_types::type_int, native_types::type_float);
$map[10] = 1.25;
$map[20] = 3.5;
```
同类型 map 可以 copy:
同类型 ordered_map 可以 copy:
```php
$a = std::map(native_types::type_int, native_types::type_int);
$b = std::map(native_types::type_int, native_types::type_int);
$a = std::ordered_map(native_types::type_int, native_types::type_int);
$b = std::ordered_map(native_types::type_int, native_types::type_int);
$b[10] = 100;
$a = $b;
```
## std::unordered_map
## std::map
`std::unordered_map` 是哈希表 key-value 容器。
`std::map` 是哈希表 key-value 容器。
```php
function main(): void
{
$map = std::unordered_map(
$map = std::map(
native_types::type_int,
native_types::type_int
);
@ -267,11 +267,11 @@ function main(): void
- 适合大量 key-value 查找
- 通常用于不要求顺序的映射场景
同类型 unordered_map 可以 copy:
同类型 map 可以 copy:
```php
$a = std::unordered_map(native_types::type_int, native_types::type_int);
$b = std::unordered_map(native_types::type_int, native_types::type_int);
$a = std::map(native_types::type_int, native_types::type_int);
$b = std::map(native_types::type_int, native_types::type_int);
$b[1] = 42;
$a = $b;
@ -307,7 +307,7 @@ class User
$vector = std::vector(User::class);
$array = std::array(User::class, 10);
$map = std::map(complex_types::type_str, User::class);
$map = std::ordered_map(complex_types::type_str, User::class);
```
类类型容器会在写入时检查对象类型,避免错误对象混入。
@ -587,7 +587,7 @@ Swoole AOT 的 std 容器提供了一条更适合编译优化的路径:
- 用 `std::array` 表达固定长度强类型数组
- 用 `std::vector` 表达动态连续强类型数组
- 用 `std::map` / `std::unordered_map` 表达强类型映射
- 用 `std::ordered_map` / `std::map` 表达强类型映射
- 普通变量接收 std 容器时自动转 PHP Array
- 同类型 std 容器之间支持原生 copy
- UnsafePtr 支持 native 函数间安全地传递容器引用

@ -126,7 +126,7 @@ class TraitsTest extends TestCase
$this->assertTrue($this->invoke('isStdContainerType', CompilerBase::TYPE_STD_ARRAY));
$this->assertTrue($this->invoke('isStdContainerType', CompilerBase::TYPE_STD_VECTOR));
$this->assertTrue($this->invoke('isStdContainerType', CompilerBase::TYPE_STD_MAP));
$this->assertTrue($this->invoke('isStdContainerType', CompilerBase::TYPE_STD_UNORDERED_MAP));
$this->assertTrue($this->invoke('isStdContainerType', CompilerBase::TYPE_STD_ORDERED_MAP));
}
public function testIsStdContainerTypeFalse(): void
@ -193,17 +193,17 @@ class TraitsTest extends TestCase
$this->assertStringNotContainsString('keyType', $key);
}
public function testGetStdTypeKeyUnorderedMap(): void
public function testGetStdTypeKeyOrderedMap(): void
{
$info = [
'kind' => 'unordered_map',
'decl' => 'php::StdUnorderedMap<php::Str, php::Int>',
'kind' => 'ordered_map',
'decl' => 'php::StdOrderedMap<php::Str, php::Int>',
'type' => 'php::Int',
'class' => '',
'keyType' => 'php::Str',
];
$key = $this->invoke('getStdTypeKey', $info);
$this->assertStringContainsString('kind=unordered_map', $key);
$this->assertStringContainsString('kind=ordered_map', $key);
}
// ========================================================================
@ -288,14 +288,14 @@ class TraitsTest extends TestCase
public function testGetStdMapDecl(): void
{
$result = $this->invoke('getStdMapDecl', 'std::map', 'php::Str', 'php::Int');
$this->assertEquals('std::map<php::Str, php::Int>', $result);
$result = $this->invoke('getStdMapDecl', 'php::StdMap', 'php::Str', 'php::Int');
$this->assertEquals('php::StdMap<php::Str, php::Int>', $result);
}
public function testGetStdMapDeclUnordered(): void
public function testGetStdMapDeclOrdered(): void
{
$result = $this->invoke('getStdMapDecl', 'std::unordered_map', 'php::Int', 'php::Str');
$this->assertEquals('std::unordered_map<php::Int, php::Str>', $result);
$result = $this->invoke('getStdMapDecl', 'php::StdOrderedMap', 'php::Int', 'php::Str');
$this->assertEquals('php::StdOrderedMap<php::Int, php::Str>', $result);
}
// ========================================================================

@ -121,7 +121,7 @@ class CompilerBase extends \PhpAot\Core\Translator
public const string TYPE_STD_ARRAY = 'php::StdArray';
public const string TYPE_STD_VECTOR = 'php::StdVector';
public const string TYPE_STD_MAP = 'php::StdMap';
public const string TYPE_STD_UNORDERED_MAP = 'php::StdUnorderedMap';
public const string TYPE_STD_ORDERED_MAP = 'php::StdOrderedMap';
public const string TYPE_ARGS = 'php::Args';
public const string TYPE_STR = 'php::Str';
public const string TYPE_REF = 'php::Ref';
@ -3888,7 +3888,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->fatalError($var, 'Cannot use [] for array unset');
}
$array = $this->parseIdentifier($var->var);
if (($this->isStdMap($array) or $this->isStdUnorderedMap($array))
if (($this->isStdMap($array) or $this->isStdOrderedMap($array))
and !empty($this->context->stdContainers[$array]['locking'])) {
$this->fatalError($var, 'Cannot delete element in std container in foreach loop');
}
@ -5657,7 +5657,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$code .= 'php::Var ' . $name . ' = php::Var(' . $boxCtor . ');' . PHP_EOL;
$code .= $this->getIndent() . 'auto &' . $name . '_ref = ' . $name . '.toBox<' . $containerType . '>()->container;';
}
} elseif ($type === self::TYPE_STD_MAP || $type === self::TYPE_STD_UNORDERED_MAP) {
} elseif ($type === self::TYPE_STD_MAP || $type === self::TYPE_STD_ORDERED_MAP) {
$info = $this->context->stdContainers[$name];
if (isset($info['boxExpr'])) {
$code .= 'auto &' . $name . '_ref = php::toStdContainer<' . $info['decl'] . '>(' . $info['boxExpr'] . ', ' . $info['typeId'] . ');';

@ -182,7 +182,7 @@ trait AssignOpTrait
} else {
if ($this->isMethodCall($right) and $this->isNamedMethod($right->name)) {
$methodName = $right->name->toString();
if (in_array($methodName, ['toStdArray', 'toStdVector', 'toStdMap', 'toStdUnorderedMap'], true)) {
if (in_array($methodName, ['toStdArray', 'toStdVector', 'toStdMap', 'toStdOrderedMap'], true)) {
if ($this->hasVar($var)) {
$this->fatalError($left, "Cannot re-assign `\${$var}` to {$methodName}()");
}
@ -207,7 +207,7 @@ trait AssignOpTrait
} elseif ($this->isStaticCall($right) and $this->isNameExpr($right->class) and $this->isIdExpr($right->name)) {
$class = $this->parseIdentifier($right->class);
if ($class === 'std') {
if (in_array($right->name->toString(), ['array', 'vector', 'map', 'unordered_map'], true)) {
if (in_array($right->name->toString(), ['array', 'vector', 'map', 'ordered_map'], true)) {
if ($this->hasVar($var)) {
$this->fatalError($left, "Cannot re-assign `\${$var}` to std::{$right->name->toString()}");
}
@ -226,8 +226,8 @@ trait AssignOpTrait
$this->addLocalVar($var, self::TYPE_STD_MAP);
return $this->parseStdMap($var, $right);
}
$this->addLocalVar($var, self::TYPE_STD_UNORDERED_MAP);
return $this->parseStdUnorderedMap($var, $right);
$this->addLocalVar($var, self::TYPE_STD_ORDERED_MAP);
return $this->parseStdOrderedMap($var, $right);
} else {
$valueExpr = $this->parseStdCall($right);
if (!$this->hasVar($var)) {

@ -29,7 +29,7 @@ trait StdContainerTrait
self::TYPE_STD_ARRAY,
self::TYPE_STD_VECTOR,
self::TYPE_STD_MAP,
self::TYPE_STD_UNORDERED_MAP,
self::TYPE_STD_ORDERED_MAP,
], true);
}
@ -48,9 +48,9 @@ trait StdContainerTrait
return $this->hasLocalVar($var) and $this->getVarType($var) === self::TYPE_STD_MAP;
}
protected function isStdUnorderedMap(string $var): bool
protected function isStdOrderedMap(string $var): bool
{
return $this->hasLocalVar($var) and $this->getVarType($var) === self::TYPE_STD_UNORDERED_MAP;
return $this->hasLocalVar($var) and $this->getVarType($var) === self::TYPE_STD_ORDERED_MAP;
}
protected function getStdTypeKey(array $info): string
@ -224,7 +224,7 @@ trait StdContainerTrait
$tmp = $tmp->var;
} elseif ($this->isVarExpr($tmp)) {
$var = $this->parseVariable($tmp);
if ($this->isStdVector($var) || $this->isStdMap($var) || $this->isStdUnorderedMap($var)) {
if ($this->isStdVector($var) || $this->isStdMap($var) || $this->isStdOrderedMap($var)) {
return $this->context->stdContainers[$var];
}
return null;
@ -350,7 +350,7 @@ trait StdContainerTrait
protected function parseForeachStdContainer(Foreach_ $node): string
{
$container = $this->parseIdentifier($node->expr);
if ($this->isStdMap($container) or $this->isStdUnorderedMap($container)) {
if ($this->isStdMap($container) or $this->isStdOrderedMap($container)) {
$this->context->stdContainers[$container]['locking'] = true;
}
$iterator = $this->genTmpVarName();
@ -392,7 +392,7 @@ trait StdContainerTrait
$code .= $this->getIndent() . '}';
unset($this->context->objects[$valueVar]);
if ($this->isStdMap($container) or $this->isStdUnorderedMap($container)) {
if ($this->isStdMap($container) or $this->isStdOrderedMap($container)) {
$this->context->stdContainers[$container]['locking'] = false;
}
return $code;
@ -419,7 +419,7 @@ trait StdContainerTrait
$this->fatalError($expr, 'std container expects a variable');
}
if (count($dims) !== 1) {
$this->fatalError($expr, 'Nested std::vector/std::map/std::unordered_map access is not supported');
$this->fatalError($expr, 'Nested std::vector/std::map/std::ordered_map access is not supported');
}
$dim = $dims[0];
if ($dim === null) {
@ -600,7 +600,7 @@ trait StdContainerTrait
'toStdArray' => 'array',
'toStdVector' => 'vector',
'toStdMap' => 'map',
'toStdUnorderedMap' => 'unordered_map',
'toStdOrderedMap' => 'ordered_map',
};
if (!$this->isVarExpr($expr->var)) {
@ -629,8 +629,8 @@ trait StdContainerTrait
$this->addLocalVar($var, self::TYPE_STD_MAP);
$this->parseStdMap($var, $fakeCall);
} else {
$this->addLocalVar($var, self::TYPE_STD_UNORDERED_MAP);
$this->parseStdUnorderedMap($var, $fakeCall);
$this->addLocalVar($var, self::TYPE_STD_ORDERED_MAP);
$this->parseStdOrderedMap($var, $fakeCall);
}
$this->context->stdContainers[$var]['boxExpr'] = $sourceVar;
return '// StdContainer<' . $this->context->stdContainers[$var]['decl'] . '>(' . $sourceVar . ')';
@ -733,9 +733,9 @@ trait StdContainerTrait
return $this->parseStdMapBase($var, $expr, 'std::map', self::TYPE_STD_MAP, 'map');
}
protected function parseStdUnorderedMap(string $var, Expr\StaticCall $expr): string
protected function parseStdOrderedMap(string $var, Expr\StaticCall $expr): string
{
return $this->parseStdMapBase($var, $expr, 'std::unordered_map', self::TYPE_STD_UNORDERED_MAP, 'unordered_map');
return $this->parseStdMapBase($var, $expr, 'std::ordered_map', self::TYPE_STD_ORDERED_MAP, 'ordered_map');
}
private function parseStdMapBase(string $var, Expr\StaticCall $expr, string $funcName, string $containerType, string $kind): string
@ -812,7 +812,7 @@ trait StdContainerTrait
}
return $var . '_ref.size()';
}
if ($this->isStdMap($var) || $this->isStdUnorderedMap($var)) {
if ($this->isStdMap($var) || $this->isStdOrderedMap($var)) {
return $var . '_ref.size()';
}
}

@ -50,12 +50,12 @@ class std
return [];
}
public static function map(mixed $key_type, mixed $value_type): array
public static function ordered_map(mixed $key_type, mixed $value_type): array
{
return [];
}
public static function unordered_map(mixed $key_type, mixed $value_type): array
public static function map(mixed $key_type, mixed $value_type): array
{
return [];
}

@ -3,17 +3,17 @@ std map: 001
--FILE--
<?php
function main() {
$map = std::map(native_types::type_int, native_types::type_float);
$map[10] = 1.25;
$map[10] += 0.75;
$map[11] = 3.5;
$map = std::map(native_types::type_int, native_types::type_int);
$map[10] = 32;
$map[10] += 10;
$map[20] = 7;
var_dump($map[10] == 2.0);
var_dump($map[11] == 3.5);
var_dump($map[10]);
var_dump($map[20]);
var_dump(count($map));
}
?>
--EXPECT--
bool(true)
bool(true)
int(42)
int(7)
int(2)

@ -3,23 +3,23 @@ std map: string key
--FILE--
<?php
function main() {
$map = std::map(complex_types::type_string, native_types::type_int);
$map["alpha"] = 10;
$map["beta"] = 20;
$map["beta"] += 22;
$map = std::map(complex_types::type_string, native_types::type_float);
$map["alpha"] = 1.5;
$map["beta"] = 2.5;
$map["beta"] += 0.25;
$key = "alpha";
var_dump($map[$key]);
var_dump($map["beta"]);
var_dump($map[$key] == 1.5);
var_dump($map["beta"] == 2.75);
var_dump(count($map));
$map2 = std::map(complex_types::type_str, native_types::type_float);
$map2["pi"] = 3.14;
var_dump($map2["pi"] == 3.14);
$map2 = std::map(complex_types::type_str, native_types::type_int);
$map2["answer"] = 42;
var_dump($map2["answer"]);
}
?>
--EXPECT--
int(10)
int(42)
int(2)
bool(true)
bool(true)
int(2)
int(42)

@ -15,34 +15,34 @@ class StdMapComplexValue
}
function main() {
$strings = std::map(native_types::type_int, complex_types::type_str);
$strings[1] = 456;
$strings = std::map(native_types::type_int, complex_types::type_string);
$strings[1] = 789;
var_dump($strings[1]);
$arrays = std::map(native_types::type_int, complex_types::type_array);
$arrays[2] = ["name" => "map", "value" => 84];
$array = $arrays[2];
$arrays = std::map(complex_types::type_string, complex_types::type_array);
$arrays["item"] = ["name" => "unordered", "value" => 168];
$array = $arrays["item"];
var_dump($array["name"]);
var_dump($array["value"]);
$objects = std::map(complex_types::type_string, complex_types::type_object);
$objects["item"] = new StdMapComplexValue(14);
var_dump($objects["item"] instanceof StdMapComplexValue);
$object = $objects["item"]->toObject(StdMapComplexValue::class);
$objects = std::map(native_types::type_int, complex_types::type_object);
$objects[2] = new StdMapComplexValue(21);
var_dump($objects[2] instanceof StdMapComplexValue);
$object = $objects[2]->toObject(StdMapComplexValue::class);
var_dump($object->getValue());
$variants = std::map(native_types::type_int, complex_types::type_any);
$variants[3] = 12.5;
$variants[4] = "any";
$variants = std::map(native_types::type_int, complex_types::type_var);
$variants[3] = false;
$variants[4] = "variant";
var_dump($variants[3]);
var_dump($variants[4]);
}
?>
--EXPECT--
string(3) "456"
string(3) "map"
int(84)
string(3) "789"
string(9) "unordered"
int(168)
bool(true)
int(14)
float(12.5)
string(3) "any"
int(21)
bool(false)
string(7) "variant"

@ -1,8 +1,8 @@
--TEST--
std containers: exact class value type
std map: exact class value type
--FILE--
<?php
class StdContainerClassValue
class StdMapClassValue
{
public function __construct(public int $value)
{
@ -14,45 +14,25 @@ class StdContainerClassValue
}
}
class StdContainerClassValueChild extends StdContainerClassValue
class StdMapClassValueChild extends StdMapClassValue
{
}
class StdContainerClassValueOther
{
}
function std_container_class_value_mixed(mixed $value): mixed
function std_map_class_value_mixed(mixed $value): mixed
{
return $value;
}
function main() {
$map = std::map(complex_types::type_str, StdContainerClassValue::class);
$map["a"] = new StdContainerClassValue(1);
$item = $map["a"];
var_dump($item->getValue());
$vector = std::vector(StdContainerClassValue::class);
$vector[] = new StdContainerClassValue(2);
var_dump($vector[0]->getValue());
$array = std::array(StdContainerClassValue::class, 2);
$array[0] = new StdContainerClassValue(3);
var_dump($array[0]->getValue());
$map = std::map(complex_types::type_str, StdMapClassValue::class);
$map["a"] = new StdMapClassValue(1);
var_dump($map["a"]->getValue());
$unordered = std::unordered_map(native_types::type_int, StdContainerClassValue::class);
$unordered[1] = std_container_class_value_mixed(new StdContainerClassValue(4));
var_dump($unordered[1]->getValue());
try {
$unordered[2] = std_container_class_value_mixed(new StdContainerClassValueChild(5));
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
$map["b"] = std_map_class_value_mixed(new StdMapClassValue(2));
var_dump($map["b"]->getValue());
try {
$unordered[3] = std_container_class_value_mixed(new StdContainerClassValueOther());
$map["c"] = std_map_class_value_mixed(new StdMapClassValueChild(3));
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
@ -61,7 +41,4 @@ function main() {
--EXPECT--
int(1)
int(2)
int(3)
int(4)
The parameter `object` must be instance of class `StdContainerClassValue`, object of `StdContainerClassValueChild` given
The parameter `object` must be instance of class `StdContainerClassValue`, object of `StdContainerClassValueOther` given
The parameter `object` must be instance of class `StdMapClassValue`, object of `StdMapClassValueChild` given

@ -4,27 +4,21 @@ std map: unsafe_cast
<?php
function std_map_unsafe_ptr_update($source): void
{
$map = $source->toStdMap(complex_types::type_str, native_types::type_int);
var_dump($map["b"]);
$map["c"] = 9;
unset($source);
$array = (array)$map;
var_dump(count($array));
$map = $source->toStdMap(native_types::type_int, native_types::type_int);
var_dump($map[2]);
$map[3] = 9;
}
function main() {
$map = std::map(complex_types::type_str, native_types::type_int);
$map["a"] = 1;
$map["b"] = 7;
$map["c"] = 3;
$map = std::map(native_types::type_int, native_types::type_int);
$map[1] = 1;
$map[2] = 7;
$map[3] = 3;
std_map_unsafe_ptr_update($map);
var_dump($map["c"]);
var_dump($map[3]);
}
?>
--EXPECT--
int(7)
int(3)
int(9)

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

@ -13,10 +13,10 @@ function main() {
?>
--EXPECT--
array(2) {
["alpha"]=>
int(10)
["beta"]=>
int(20)
["alpha"]=>
int(10)
}
array(1) {
["beta"]=>

@ -19,14 +19,14 @@ function main() {
}
?>
--EXPECT--
string(5) "alpha"
int(10)
string(4) "beta"
int(20)
string(5) "gamma"
int(30)
unset-------------
string(4) "beta"
int(20)
string(5) "alpha"
int(10)
unset-------------
string(5) "gamma"
int(30)
int(30)
string(5) "alpha"
int(10)

@ -1,19 +0,0 @@
--TEST--
std unordered map: 001
--FILE--
<?php
function main() {
$map = std::unordered_map(native_types::type_int, native_types::type_int);
$map[10] = 32;
$map[10] += 10;
$map[20] = 7;
var_dump($map[10]);
var_dump($map[20]);
var_dump(count($map));
}
?>
--EXPECT--
int(42)
int(7)
int(2)

@ -1,25 +0,0 @@
--TEST--
std unordered map: string key
--FILE--
<?php
function main() {
$map = std::unordered_map(complex_types::type_string, native_types::type_float);
$map["alpha"] = 1.5;
$map["beta"] = 2.5;
$map["beta"] += 0.25;
$key = "alpha";
var_dump($map[$key] == 1.5);
var_dump($map["beta"] == 2.75);
var_dump(count($map));
$map2 = std::unordered_map(complex_types::type_str, native_types::type_int);
$map2["answer"] = 42;
var_dump($map2["answer"]);
}
?>
--EXPECT--
bool(true)
bool(true)
int(2)
int(42)

@ -1,48 +0,0 @@
--TEST--
std unordered map: complex value types
--FILE--
<?php
class StdUnorderedMapComplexValue
{
public function __construct(public int $value)
{
}
public function getValue(): int
{
return $this->value;
}
}
function main() {
$strings = std::unordered_map(native_types::type_int, complex_types::type_string);
$strings[1] = 789;
var_dump($strings[1]);
$arrays = std::unordered_map(complex_types::type_string, complex_types::type_array);
$arrays["item"] = ["name" => "unordered", "value" => 168];
$array = $arrays["item"];
var_dump($array["name"]);
var_dump($array["value"]);
$objects = std::unordered_map(native_types::type_int, complex_types::type_object);
$objects[2] = new StdUnorderedMapComplexValue(21);
var_dump($objects[2] instanceof StdUnorderedMapComplexValue);
$object = $objects[2]->toObject(StdUnorderedMapComplexValue::class);
var_dump($object->getValue());
$variants = std::unordered_map(native_types::type_int, complex_types::type_var);
$variants[3] = false;
$variants[4] = "variant";
var_dump($variants[3]);
var_dump($variants[4]);
}
?>
--EXPECT--
string(3) "789"
string(9) "unordered"
int(168)
bool(true)
int(21)
bool(false)
string(7) "variant"

@ -1,44 +0,0 @@
--TEST--
std unordered map: exact class value type
--FILE--
<?php
class StdUnorderedMapClassValue
{
public function __construct(public int $value)
{
}
public function getValue(): int
{
return $this->value;
}
}
class StdUnorderedMapClassValueChild extends StdUnorderedMapClassValue
{
}
function std_unordered_map_class_value_mixed(mixed $value): mixed
{
return $value;
}
function main() {
$map = std::unordered_map(complex_types::type_str, StdUnorderedMapClassValue::class);
$map["a"] = new StdUnorderedMapClassValue(1);
var_dump($map["a"]->getValue());
$map["b"] = std_unordered_map_class_value_mixed(new StdUnorderedMapClassValue(2));
var_dump($map["b"]->getValue());
try {
$map["c"] = std_unordered_map_class_value_mixed(new StdUnorderedMapClassValueChild(3));
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
}
?>
--EXPECT--
int(1)
int(2)
The parameter `object` must be instance of class `StdUnorderedMapClassValue`, object of `StdUnorderedMapClassValueChild` given

@ -1,24 +0,0 @@
--TEST--
std unordered map: unsafe_cast
--FILE--
<?php
function std_unordered_map_unsafe_ptr_update($source): void
{
$map = $source->toStdUnorderedMap(native_types::type_int, native_types::type_int);
var_dump($map[2]);
$map[3] = 9;
}
function main() {
$map = std::unordered_map(native_types::type_int, native_types::type_int);
$map[1] = 1;
$map[2] = 7;
$map[3] = 3;
std_unordered_map_unsafe_ptr_update($map);
var_dump($map[3]);
}
?>
--EXPECT--
int(7)
int(9)

@ -1,20 +0,0 @@
--TEST--
std unordered map: unsafe_cast type mismatch
--FILE--
<?php
function std_unordered_map_unsafe_ptr_type_mismatch($source): void
{
$map = $source->toStdUnorderedMap(native_types::type_int, native_types::type_float);
}
function main() {
$map = std::unordered_map(native_types::type_int, native_types::type_int);
try {
std_unordered_map_unsafe_ptr_type_mismatch($map);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
}
?>
--EXPECT--
std container type mismatch

@ -1,21 +0,0 @@
--TEST--
std unordered map: assign to PHP array
--FILE--
<?php
function main() {
$map = std::unordered_map(native_types::type_int, native_types::type_int);
$map[10] = 100;
$map[20] = 200;
$copy = $map;
var_dump(is_array($copy));
var_dump(count($copy));
var_dump($copy[10]);
var_dump($copy[20]);
}
?>
--EXPECT--
bool(true)
int(2)
int(100)
int(200)

@ -1,25 +0,0 @@
--TEST--
std unordered map: same type copy
--FILE--
<?php
function main() {
$a = std::unordered_map(native_types::type_int, native_types::type_int);
$b = std::unordered_map(native_types::type_int, native_types::type_int);
$b[10] = 100;
$b[20] = 200;
$a = $b;
var_dump(count($a));
var_dump($a[10]);
var_dump($a[20]);
$a[10] = 999;
var_dump($b[10]);
}
?>
--EXPECT--
int(2)
int(100)
int(200)
int(100)

@ -1,24 +0,0 @@
--TEST--
std unordered_map: unset
--FILE--
<?php
function main() {
$map = std::unordered_map(complex_types::type_string, native_types::type_int);
$map["alpha"] = 10;
$map["beta"] = 20;
var_dump($map);
unset($map["alpha"]);
var_dump($map);
}
?>
--EXPECT--
array(2) {
["beta"]=>
int(20)
["alpha"]=>
int(10)
}
array(1) {
["beta"]=>
int(20)
}

@ -1,32 +0,0 @@
--TEST--
std map: unset
--FILE--
<?php
function main() {
$map = std::unordered_map(complex_types::type_string, native_types::type_int);
$map["alpha"] = 10;
$map["beta"] = 20;
$map["gamma"] = 30;
foreach ($map as $k => $v) {
var_dump($k, $v);
}
unset($map["beta"]);
echo "unset-------------\n";
foreach ($map as $k => $v) {
var_dump($k, $v);
}
}
?>
--EXPECT--
string(5) "gamma"
int(30)
string(4) "beta"
int(20)
string(5) "alpha"
int(10)
unset-------------
string(5) "gamma"
int(30)
string(5) "alpha"
int(10)
Loading…
Cancel
Save