From 21b7de3905d9ae0d790d1efb6fa26b9a125c827c Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 31 Mar 2026 12:39:17 +0800 Subject: [PATCH] =?UTF-8?q?feat(php):=20=E6=B7=BB=E5=8A=A0=E5=AF=B9trait?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81=E5=92=8C=E4=BC=98=E5=8C=96=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E8=B0=83=E7=94=A8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在AstNodeType中添加isNull方法用于检查null值 - 更新CompilerBase中的参数默认值处理逻辑,支持引用参数的null默认值 - 将FuncCallOptimizer中的函数移动到合适位置并修复逻辑 - 重命名Preprocessor中的命名空间准备方法 - 在Translator中添加对trait语句的支持并抛出异常 - 添加对func_get_args和func_get_arg函数的优化实现 --- src/Php/AstNodeType.php | 5 +++ src/Php/CompilerBase.php | 9 +++-- src/Php/FuncCallOptimizer.php | 71 ++++++++++++++++++----------------- src/Php/Preprocessor.php | 4 +- src/Php/Translator.php | 9 +++++ 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/src/Php/AstNodeType.php b/src/Php/AstNodeType.php index 69020ae9..e27b5140 100644 --- a/src/Php/AstNodeType.php +++ b/src/Php/AstNodeType.php @@ -142,4 +142,9 @@ trait AstNodeType { return $expr instanceof Expr\Array_ && count($expr->items) === 0; } + + protected function isNull(NodeAbstract $expr): bool + { + return $expr instanceof Node\Expr\ConstFetch && $expr->name->toString() === 'null'; + } } diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index f7461930..3bd7252d 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1055,11 +1055,14 @@ class CompilerBase extends \PhpAot\Core\Translator } if ($param->default) { if ($param->byRef) { - if (!$this->isEmptyArray($param->default)) { - $this->fatalError($param, 'Default value for parameters passed by reference must be an empty array'); - } else { + if ($this->isEmptyArray($param->default)) { $argInfo->default = 'php::getEmptyArrayRef()'; $argInfo->defaultValue = null; + } elseif ($this->isNull($param->default)) { + $argInfo->default = 'nullptr'; + $argInfo->defaultValue = null; + } else { + $this->fatalError($param, 'Only null and empty array can be used as default value for reference parameter'); } } else { $argInfo->default = $this->parseParamDefaultValue($param->default); diff --git a/src/Php/FuncCallOptimizer.php b/src/Php/FuncCallOptimizer.php index 00f74a06..216069b5 100644 --- a/src/Php/FuncCallOptimizer.php +++ b/src/Php/FuncCallOptimizer.php @@ -12,6 +12,42 @@ use PhpParser\Node; trait FuncCallOptimizer { + public function genFuncGetArgs(string $name, Node\Expr\FuncCall $expr): string + { + $funcDef = $this->functionDef; + $list = []; + foreach ($funcDef->argInfoList as $i => $argInfo) { + if ($argInfo->variadic) { + $tmpVar = $this->addTmpVar(self::TYPE_ARRAY); + $this->context->beforeStmtLines[] = $this->genArray($list) . ';'; + $this->context->beforeStmtLines[] = $tmpVar . '.merge(' . $argInfo->name . ');'; + return $tmpVar; + } + $list[] = $argInfo->name; + } + return $this->genArray($list); + } + + public function genFuncGetArg(string $name, Node\Expr\FuncCall $expr) + { + $position = $expr->args[0]->value; + if ($this->isScalarInt($position)) { + $funcDef = $this->functionDef; + $posInt = intval($position->value); + foreach ($funcDef->argInfoList as $i => $argInfo) { + if ($argInfo->variadic) { + return $argInfo->name . '.offsetGet(' . ($posInt - $i) . ')'; + } + if ($i == $posInt) { + return $argInfo->name; + } + } + $this->fatalError($expr, 'wrong parameter position `' . $posInt . '`'); + } else { + $this->fatalError($expr, 'func_get_arg() only support scalar int'); + } + } + protected function parseFuncCallWithOptimizer(string $name, Node\Expr\FuncCall $expr): string|false { $getArg = function ($i) use ($expr) { @@ -71,41 +107,6 @@ trait FuncCallOptimizer return false; } - public function genFuncGetArgs(string $name, Node\Expr\FuncCall $expr): string - { - $funcDef = $this->functionDef; - $list = []; - foreach ($funcDef->argInfoList as $i => $argInfo) { - if ($argInfo->variadic) { - $tmpVar = $this->addTmpVar(self::TYPE_ARRAY); - $this->context->beforeStmtLines[] = $this->genArray($list) . ';'; - $this->context->beforeStmtLines[] = $tmpVar . '.merge(' . $argInfo->name . ');'; - return $tmpVar; - } - $list[] = $argInfo->name; - } - return $this->genArray($list); - } - - public function genFuncGetArg(string $name, Node\Expr\FuncCall $expr) - { - $position = $expr->args[0]->value; - if ($this->isScalarInt($position)) { - $funcDef = $this->functionDef; - $posInt = intval($position->value); - foreach ($funcDef->argInfoList as $i => $argInfo) { - if ($argInfo->variadic) { - return $argInfo->name . '.offsetGet(' . ($posInt - $i) . ')'; - } elseif ($i == $posInt) { - return $argInfo->name; - } - } - $this->fatalError($expr, 'wrong parameter position `' . $posInt . '`'); - } else { - $this->fatalError($expr, 'func_get_arg() only support scalar int'); - } - } - protected function genFuncNumArgs(string $name, Node\Expr\FuncCall $expr): string { $funcDef = $this->functionDef; diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 4b95e3bf..236588bf 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -106,7 +106,7 @@ class Preprocessor extends CompilerBase $type = $v->getType(); switch ($type) { case 'Stmt_Namespace': - $this->prepareNamespaceDef($v); + $this->prepareNamespace($v); break; case 'Stmt_Enum': case 'Stmt_Class': @@ -161,7 +161,7 @@ class Preprocessor extends CompilerBase $this->symbolCallInFile[$this->file] = array_unique($this->symbolCallInFile[$this->file]); } - protected function prepareNamespaceDef(Node\Stmt\Namespace_ $node): void + protected function prepareNamespace(Node\Stmt\Namespace_ $node): void { $this->resetNamespace(); $this->namespace = $node->name ? $this->parseIdentifier($node->name) : ''; diff --git a/src/Php/Translator.php b/src/Php/Translator.php index ac41a099..9a37973b 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -17,6 +17,7 @@ use PhpAot\Php\Entity\InterfaceDef; use PhpAot\Php\Entity\MethodDef; use PhpAot\Php\Entity\PropertyDef; use PhpAot\Php\Exception\Redo; +use PhpAot\Php\Exception\Unsupported; use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\Node\Stmt\Foreach_; @@ -825,6 +826,9 @@ class Translator extends Preprocessor case 'Stmt_Interface': $code .= $this->parseInterface($v2) . PHP_EOL; break; + case 'Stmt_Trait': + $code .= $this->parseTrait($v2) . PHP_EOL; + break; default: abort($v2); } @@ -1363,4 +1367,9 @@ class Translator extends Preprocessor return $code; } + + protected function parseTrait(Node\Stmt\Trait_ $trait) + { + throw new Unsupported('Unsupported Trait '); + } }