feat(php): 添加 refval 函数支持引用传递功能

- 新增 isRefvalCall 方法检测 refval 函数调用
- 在编译器中添加对 refval 函数的特殊处理逻辑
- 实现 refval 函数调用的参数解析和优化
- 添加 refval 函数的 polyfill 实现
- 在 stub 生成中使用 refval 包装声明字符串
- 添加 refval 函数的测试用例
pull/1/head
韩天峰 4 months ago
parent 10a66b1c31
commit 799aa629c0
  1. 5
      src/Php/AstNodeType.php
  2. 12
      src/Php/CompilerBase.php
  3. 2
      src/gen_stub.php
  4. 5
      src/polyfills.php
  5. 0
      tests/aot/ref/refval1.phpt
  6. 16
      tests/aot/ref/refval2.phpt

@ -75,6 +75,11 @@ trait AstNodeType
return $expr instanceof Expr\FuncCall;
}
protected function isRefvalCall(NodeAbstract $expr): bool
{
return $this->isFuncCallExpr($expr) and $this->isNameExpr($expr->name) and $expr->name->toString() === 'refval';
}
protected function isMethodCall(NodeAbstract $expr): bool
{
return $expr instanceof Expr\MethodCall;

@ -2665,6 +2665,9 @@ class CompilerBase extends \PhpAot\Core\Translator
return '{' . implode(', ', $list_args) . '}';
}
/**
* 仅用于动态调用的参数解析
*/
protected function parseArgRefVar(Node\Arg $arg, string $name): string
{
if (!$this->hasVar($name)) {
@ -2681,6 +2684,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->context->beforeStmtLines[] = $tmpVar . ' = ' . $this->parseExpr($arg->value) . '.toReference();';
$name = $tmpVar;
}
// 动态调用,参数列表是 Variant 类型而不是 Reference,必须使用 & 符号取地址,传递指针,以保持引用传递
return '&' . $name;
}
@ -3334,6 +3338,14 @@ class CompilerBase extends \PhpAot\Core\Translator
$type = $this->detectTypeOfExpr($arg->value);
if ($argInfo->byRef) {
if ($this->isRefvalCall($arg->value)) {
if (count($arg->value->args) === 1 and $this->isVarExpr($arg->value->args[0]->value)) {
// 消除 refval() 函数调用,直接使用变量
$arg->value = $arg->value->args[0]->value;
} else {
$this->fatalError($arg, 'The refval function only accepts one parameter of variable type');
}
}
if ($this->isVarExpr($arg->value)) {
$var = $this->parseVariable($arg->value);
// 若参数是引用类型,可以传入未定义变量,将立即创建变量作为引用

@ -3673,7 +3673,7 @@ class ClassInfo {
"class_{$escapedName}_$key",
$allConstInfos,
$this->phpVersionIdMinimumCompatibility,
$declaredStrings
refval($declaredStrings)
);
}

@ -38,3 +38,8 @@ function objval(mixed $obj, string $class): object
}
throw new Exception('Invalid object type');
}
function &refval(&$var)
{
return $var;
}

@ -0,0 +1,16 @@
--TEST--
refval
--FILE--
<?php
function retval_test(&$name) {
$name .= "refval test";
}
function main()
{
$name = 'php ';
retval_test(refval($name));
echo $name;
}
?>
--EXPECT--
php refval test
Loading…
Cancel
Save