From 13499a0b7feb77fd7afa92a3b850626c3e6e389d Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 17 Mar 2026 16:09:34 +0800 Subject: [PATCH] =?UTF-8?q?feat(php):=20=E6=B7=BB=E5=8A=A0=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E7=94=9F=E6=88=90=E5=99=A8=E6=94=AF=E6=8C=81=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 RefGenerator 用于处理引用相关的代码生成 - 添加 OP_REFVAL 操作常量用于引用值转换 - 实现函数参数引用检测和处理逻辑 - 将 parseVarCheckExpr 重命名为 parseChainedExpr 并增强链式表达式支持 - 修复 isset 和 empty 操作的表达式解析一致性 - 添加对多维数组和对象属性链的引用处理支持 - 更新赋值操作中的空合并运算符表达式解析 - 增加引用功能的测试用例验证 --- src/Php/CompilerBase.php | 21 ++++++++++++++------- tests/aot/ref-005.phpt | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 tests/aot/ref-005.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 8e880d3b..96b4af2c 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -21,6 +21,7 @@ use PhpAot\Php\Generator\ClosureGenerator; use PhpAot\Php\Generator\PlaceHolderGenerator; use PhpAot\Php\Generator\PropertyPromotion; use PhpAot\Php\Generator\Utils; +use PhpAot\Php\Generator\RefGenerator; use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\Node\Expr\Variable; @@ -78,6 +79,7 @@ class CompilerBase extends \PhpAot\Core\Translator public const string STATIC_VAR = '_static_var_'; public const string OP_ISSET = 'isset'; public const string OP_EMPTY = 'empty'; + public const string OP_REFVAL = 'toReference'; public const string OP_NOP = "if (0) {}\n"; protected string $phpxDir = '~/workspace/projects/phpx'; protected string $lang = 'PHP'; @@ -2359,6 +2361,11 @@ class CompilerBase extends \PhpAot\Core\Translator $list_args[] = $array . '.itemRef(' . $this->identifierToStr($arg->value->dim) . ')'; continue; } + } else { + if ($funcName and Reflection::isReferenceArg($funcName, $className, $i)) { + $list_args[] = $this->parseChainedExpr($arg->value, self::OP_REFVAL); + continue; + } } // 变长参数展开的语法,例如:array_merge(...$arr) if ($arg->unpack) { @@ -2718,7 +2725,7 @@ class CompilerBase extends \PhpAot\Core\Translator $left = $this->parseIdentifier($expr->left); $right = $this->parseIdentifier($expr->right); - return $this->parseVarCheckExpr($expr->left, 'isset') . ' ? ' . $left . ' : ' . $right; + return $this->parseChainedExpr($expr->left, 'isset') . ' ? ' . $left . ' : ' . $right; } protected function parseBinaryOpNotIdentical(Node\Expr\BinaryOp $expr): string @@ -3336,16 +3343,16 @@ class CompilerBase extends \PhpAot\Core\Translator if (count($vars) > 1) { $list = []; foreach ($vars as $var) { - $list[] = $this->parseVarCheckExpr($var, 'isset'); + $list[] = $this->parseChainedExpr($var, 'isset'); } return '(' . implode(' && ', $list) . ')'; } - return $this->parseVarCheckExpr($vars[0], 'isset'); + return $this->parseChainedExpr($vars[0], 'isset'); } protected function parseEmpty(Node\Expr\Empty_ $expr): string { - return $this->parseVarCheckExpr($expr->expr, 'empty'); + return $this->parseChainedExpr($expr->expr, 'empty'); } /** @@ -3358,7 +3365,7 @@ class CompilerBase extends \PhpAot\Core\Translator } } - protected function parseVarCheckExpr(NodeAbstract $expr, string $op): string + protected function parseChainedExpr(NodeAbstract $expr, string $op): string { if ($this->isVarExpr($expr)) { if ($op === 'isset') { @@ -3391,7 +3398,7 @@ class CompilerBase extends \PhpAot\Core\Translator $expr = $expr->var; } $list = array_reverse($list); - $fn = $op === 'isset' ? 'exists' : 'empty'; + $fn = $op === 'isset' ? 'exists' : $op; return 'php::' . $fn . '(' . $var . ', {' . implode(', ', $list) . '})'; } @@ -4201,7 +4208,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parseAssignOpCoalesce(Node\Expr\AssignOp\Coalesce $expr): string { $this->checkLeftValue($expr->var); - $isset = $this->parseVarCheckExpr($expr->var, self::OP_ISSET); + $isset = $this->parseChainedExpr($expr->var, self::OP_ISSET); $inAssignExpr = $this->inAssignExpr; $this->inAssignExpr = true; diff --git a/tests/aot/ref-005.phpt b/tests/aot/ref-005.phpt new file mode 100644 index 00000000..e96e41a6 --- /dev/null +++ b/tests/aot/ref-005.phpt @@ -0,0 +1,19 @@ +--TEST-- +ref +--FILE-- +data = ['get' => [],]; + + parse_str("hello=world", $req->data['get']); + var_dump($req->data['get']['hello']); +} +?> +--EXPECT-- +string(5) "world" \ No newline at end of file