TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3.1 KiB
3.1 KiB
Std 容器参数类型注解
StdArray、StdVector、StdMap、StdOrderedMap 是 TypePHP 内置的 Box 容器类型注解。
它们描述容器种类和元素类型,并自动完成以前需要手写的 toStd*() 类型恢复。
本文记录现有 Box 容器参数实现。包含 StdList / StdDict 的统一规则见
类型注解统一设计;拟议函数签名见 StdFunc / StdArgInfo。
function append(#[StdVector(Type::Int)] $vec): void
{
$vec[] = 42;
}
function update_matrix(#[StdArray(Type::Int, [2, 3])] box $matrix): void
{
$matrix[1][2] = 42;
}
function update(#[StdMap(Type::String, User::class)] $users): void
{
$users['alice'] = new User();
}
function visit(#[StdOrderedMap(Type::Int, Type::String)] $names): void
{
foreach ($names as $key => $value) {
echo $key, ':', $value, "\n";
}
}
声明规则
- 一个参数只能有一个容器类型注解,不能重复或混用。
- 类型注解提供完整契约,PHP 参数类型可以省略或声明为兼容的
box;不能声明mixed、any、array、Nullable、联合类型或其他不兼容类型。 StdArray接受叶子类型及单长度或外到内维度数组;StdVector接受一个类型实参;StdMap、StdOrderedMap接受 key/value 两个类型实参。- 类型实参使用现有 std 工厂支持的
Type::*或ClassName::class;map 的 key 只支持Type::Int、Type::String。 - 使用位置为具名函数和方法参数,包括接口、抽象方法和 trait 方法;支持 Attribute 别名导入。
- 首版不支持引用、可变、带默认值、构造器属性提升参数,以及 Closure、箭头函数和 Generator 参数。
- 容器内不能保存 Native 对象并通过 Box 参数边界传递;原有 Native 容器逃逸限制不变。
- 参数绑定不能换成其他 Box/值、
unset()或被 Closure 按引用捕获;同类型 std 容器赋值仍按现有规则复制内容。元素的读取、更新、追加和遍历继续遵循现有 std 容器规则。
以下声明会产生编译错误:
function invalid(#[StdVector(Type::Int)] mixed $vec): void {}
调用和生命周期
函数的底层调用 ABI 仍为 php::Var,容器仍由 Box 管理生命周期。编译器在入口
检查 Box、容器种类及元素类型,取得具体 C++ 容器引用;不复制容器,也不逐个转换元素。
错误的容器类型、PHP 数组及其他非 Box 实参会产生 TypeError。
函数中修改容器内容时,调用者可观察到相同修改:
$vec = std::vector(Type::Int);
append($vec);
var_dump($vec[0]); // int(42)
现有动态调用把已知 std 容器转换为 PHP 数组的规则不变。如果通过动态 callable 调用这类函数,需传入实际的 Box 值,而不是已经转换成 PHP 数组的值。 注解不会让普通 Zend PHP 获得 C++ 泛型容器支持,也不会把 C++ 模板类型变成 PHP 的原生参数类型。
容器契约保存在声明缓存和导出的 library stub 中。修改参数注解会使源文件及依赖它的 调用方重新转换;仅复用缓存时,入口类型恢复仍然保留。