From cebe50121aa9524fe38ff8563e2a5b420d5379c9 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 5 Mar 2026 11:23:04 +0800 Subject: [PATCH] =?UTF-8?q?refactor(php):=20=E4=BC=98=E5=8C=96PHP=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=99=A8=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=E5=92=8C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复AstNodeType中isAssignOp方法的命名空间引用问题 - 移除class-static-002测试用例中的多余输出断言 - 在CompilerBase中添加objectWrappers和ceWrappers属性用于对象包装器管理 - 新增getCeWrapper方法用于获取类入口包装器 - 修改注释格式从文档块改为行注释以提升性能 - 移除hasNativeClass和hasNativeFunction的返回值类型注解 - 重构parseArrayMixed方法的位置,从私有方法调整为类末尾重新定义 - 简化魔术常量解析中的字符串拼接逻辑 - 优化静态调用处理,支持static关键字的正确解析 - 添加addTmpVar辅助方法用于临时变量创建 - 统一字符串字面量的引号使用规范 --- src/Php/AstNodeType.php | 2 +- src/Php/CompilerBase.php | 119 +++++++++++++++--------- src/Php/Generator/PropertyPromotion.php | 10 +- tests/aot/class-static-002.phpt | 1 - 4 files changed, 82 insertions(+), 50 deletions(-) diff --git a/src/Php/AstNodeType.php b/src/Php/AstNodeType.php index c33204b3..7c87a1d9 100644 --- a/src/Php/AstNodeType.php +++ b/src/Php/AstNodeType.php @@ -86,6 +86,6 @@ trait AstNodeType protected function isAssignOp(NodeAbstract $expr): bool { - return $expr instanceof Node\Expr\AssignOp or $expr instanceof Node\Expr\Assign; + return $expr instanceof Expr\AssignOp or $expr instanceof Expr\Assign; } } diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index d053073d..1ad5dd83 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -112,6 +112,7 @@ class CompilerBase extends \PhpAot\Core\Translator 'php_aot_helper.h', ]; protected array $localHeaders = []; + /** * 存储所有函数、类方法的定义,key 是 native name,命名空间需要转为 `_`,并且必须为小写 * @var array @@ -155,6 +156,7 @@ class CompilerBase extends \PhpAot\Core\Translator * @var array */ protected array $classes = []; + /** * @var array */ @@ -206,7 +208,16 @@ class CompilerBase extends \PhpAot\Core\Translator protected array $objects = []; protected array $localVars = []; protected array $staticVars = []; + + /** + * @var array + */ protected array $objectWrappers = []; + + /** + * @var array + */ + protected array $ceWrappers = []; protected bool $strictTypes = false; protected string $rootPath; protected string $buildDir; @@ -697,6 +708,17 @@ class CompilerBase extends \PhpAot\Core\Translator return 'php_get_class(' . $id . ', ' . $this->getLiteralString($className) . ')'; } + protected function getCeWrapper(string $className): string + { + if (isset($this->ceWrappers[$className])) { + return $this->ceWrappers[$className]; + } + $object = $this->addTmpVar(self::TYPE_OBJECT); + $this->beforeStmtLines[] = 'Z_PTR_P(' . $object . '.ptr()) = ' . $this->getClassEntryPtr($className) . ';'; + $this->ceWrappers[$className] = $object; + return $object; + } + protected function getFuncPtr(string $funcName, bool $macro = true): string { $id = $this->getFuncId($funcName); @@ -915,7 +937,7 @@ class CompilerBase extends \PhpAot\Core\Translator if (!$default) { return null; } - /** + /* * 函数参数默认值只能为字面量,无法使用表达式获取值 */ if ($default instanceof Node\Expr\ConstFetch) { @@ -1417,6 +1439,13 @@ class CompilerBase extends \PhpAot\Core\Translator $this->localVars[$name] = $type; } + protected function addTmpVar(string $type): string + { + $var = $this->genTmpVarName(); + $this->addLocalVar($var, $type); + return $var; + } + protected function addStaticVar(string $name, string $type): void { $this->staticVars[$name] = $type; @@ -1464,7 +1493,6 @@ class CompilerBase extends \PhpAot\Core\Translator /** * @param string $name 必须传入带有完整命名空间的类名,将会自动转义为 native name - * @return bool */ protected function hasNativeClass(string $name): bool { @@ -1473,7 +1501,6 @@ class CompilerBase extends \PhpAot\Core\Translator /** * @param string $name 必须传入带有完整命名空间的类名,将会自动转义为 native name - * @return bool */ protected function hasNativeFunction(string $name): bool { @@ -1592,38 +1619,6 @@ class CompilerBase extends \PhpAot\Core\Translator return self::TYPE_VAR; } - /** - * 混杂数组赋值,需要拆分为多行插入 - */ - private function parseArrayMixed(Node\Expr\Array_ $node): string - { - $tmpVar = $this->genTmpVarName(); - $this->addLocalVar($tmpVar, self::TYPE_ARRAY); - - $items = $node->items; - foreach ($items as $item) { - $value = $this->parseIdentifier($item->value); - if ($item->unpack) { - $this->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.merge(' . $value . ');'; - } elseif ($item->key) { - $key = $this->parseIdentifier($item->key); - if (str_starts_with($key, self::LITERAL_STRINGS)) { - $key = "{$key}.toStdString()"; - } elseif ($key === '0L') { - $key = 'php::zero'; - } - $this->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.set(' . $key . ', ' . $value . ');'; - } else { - $this->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.append(' . $value . ');'; - } - } - - // 释放临时变量,避免修改数组产生数组复制操作 - $this->afterStmtLines[] = $this->getIndent() . $tmpVar . '.unset();'; - - return $tmpVar; - } - protected function parseArray(Node\Expr\Array_ $node): string { $items = $node->items; @@ -2057,9 +2052,6 @@ class CompilerBase extends \PhpAot\Core\Translator /** * 查找原生函数. - * - * @param string $fname - * @return string|false */ protected function findNativeFunction(string $fname): string|false { @@ -2911,8 +2903,8 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parseMagicConst(MagicConst $expr): string { - $class = ($this->namespace ? $this->namespace . '\\' : '') . $this->class; - $function = ($this->namespace ? $this->namespace . '\\' : '') . $this->function; + $class = ($this->namespace ? $this->namespace . '\\' : '') . $this->class; + $function = ($this->namespace ? $this->namespace . '\\' : '') . $this->function; switch ($expr->getType()) { case 'Scalar_MagicConst_Dir': return '"' . $this->escapeString($this->dir) . '"'; @@ -3407,7 +3399,7 @@ class CompilerBase extends \PhpAot\Core\Translator } return $id; } - /** + /* * 对 static 的支持存在问题,静态编译时无法获得实际运行时的子类名,所以只能使用 self * self 是在编译期确定的,而 static 是运行时确定的,但使用 AOT 编译为可执行文件后,运行时类的名称是无法确定的 */ @@ -3433,8 +3425,10 @@ class CompilerBase extends \PhpAot\Core\Translator { $self = false; $callScope = []; + $class = $this->parseIdentifier($expr->class); + if ($this->isVarExpr($expr->class) or $this->isVarExpr($expr->name)) { - $var = $this->parseIdentifier($expr->class); + $var = $class; if ($this->isTypedObject($var)) { $class = $this->getObjectType($var); goto _do_call; @@ -3445,8 +3439,11 @@ class CompilerBase extends \PhpAot\Core\Translator $fn = 'php::concat({' . $this->identifierToStr($expr->class) . ', "::", ' . $this->identifierToStr($expr->name) . '})'; } $placeHolder = $fn; + } elseif ($class === 'static') { + $methodPtr = $this->identifierToStr($expr->name); + $fn = 'php_get_called_ce(this_), php::getMethod(php_get_called_ce(this_), ' . $methodPtr . ')'; + $placeHolder = $this->genArray(['php_get_called_class(this_)', $methodPtr]); } else { - $class = $this->parseIdentifier($expr->class); if ($class === 'self') { $class = $this->class; $self = true; @@ -3475,9 +3472,7 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->methodDef and $self) { $object = 'this_'; } else { - $object = $this->genTmpVarName(); - $this->addLocalVar($object, self::TYPE_OBJECT); - $this->beforeStmtLines[] = 'Z_PTR_P('.$object.'.ptr()) = ' . $this->getClassEntryPtr($class) . ';'; + $object = $this->getCeWrapper($class); } if ($args) { return self::PREFIX . $nativeFunc . '(' . $object . ', ' . $args . ')'; @@ -4032,4 +4027,36 @@ class CompilerBase extends \PhpAot\Core\Translator } return $stmts[array_key_last($stmts)] instanceof Node\Stmt\Return_; } + + /** + * 混杂数组赋值,需要拆分为多行插入 + */ + private function parseArrayMixed(Node\Expr\Array_ $node): string + { + $tmpVar = $this->genTmpVarName(); + $this->addLocalVar($tmpVar, self::TYPE_ARRAY); + + $items = $node->items; + foreach ($items as $item) { + $value = $this->parseIdentifier($item->value); + if ($item->unpack) { + $this->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.merge(' . $value . ');'; + } elseif ($item->key) { + $key = $this->parseIdentifier($item->key); + if (str_starts_with($key, self::LITERAL_STRINGS)) { + $key = "{$key}.toStdString()"; + } elseif ($key === '0L') { + $key = 'php::zero'; + } + $this->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.set(' . $key . ', ' . $value . ');'; + } else { + $this->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.append(' . $value . ');'; + } + } + + // 释放临时变量,避免修改数组产生数组复制操作 + $this->afterStmtLines[] = $this->getIndent() . $tmpVar . '.unset();'; + + return $tmpVar; + } } diff --git a/src/Php/Generator/PropertyPromotion.php b/src/Php/Generator/PropertyPromotion.php index 06de8457..1ef954de 100644 --- a/src/Php/Generator/PropertyPromotion.php +++ b/src/Php/Generator/PropertyPromotion.php @@ -1,4 +1,10 @@ genCharPtr($argInfo->name) . ", " . $argInfo->name . ")"; + $code .= 'this_.setProperty(' . $this->genCharPtr($argInfo->name) . ', ' . $argInfo->name . ')'; $code .= ";\n"; return $code; } -} \ No newline at end of file +} diff --git a/tests/aot/class-static-002.phpt b/tests/aot/class-static-002.phpt index a7fd946c..28fc9799 100644 --- a/tests/aot/class-static-002.phpt +++ b/tests/aot/class-static-002.phpt @@ -37,4 +37,3 @@ namespace { --EXPECT-- string(5) "hello" string(5) "world" -string(3) "foo"