diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index b678acd8..a3128acc 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -670,15 +670,14 @@ class CompilerBase extends \PhpAot\Core\Translator protected function getNativeName(string $fn, string $ns = '', string $class = ''): string { - $names[] = $this->escapeName($fn); if ($ns) { $names[] = $this->escapeNamespace($ns); } if ($class) { $names[] = $this->escapeClass($class); } - - return implode(self::NAMESPACE_SEPARATOR, array_reverse($names)); + $names[] = $this->escapeName($fn); + return implode(self::NAMESPACE_SEPARATOR, $names); } protected function getClassId(string $className): int @@ -942,7 +941,14 @@ class CompilerBase extends \PhpAot\Core\Translator $argInfo->variadic = $param->variadic; if (isset($param->default)) { $functionDef->argCountRequired = count($list) - 1; - $argInfo->default = $this->parseIdentifier($param->default); + /** + * 函数参数默认值只能为字面量,无法使用表达式获取值 + */ + if ($param->default instanceof Node\Expr\ConstFetch) { + $argInfo->default = $this->parseConstFetch($param->default, true); + } else { + $argInfo->default = $this->parseIdentifier($param->default); + } } $functionDef->argInfoList[] = $argInfo; } @@ -1367,15 +1373,17 @@ class CompilerBase extends \PhpAot\Core\Translator // 返回值类型不一致,说明存在多种类型的返回值,修改为 var 表示 any $this->resetReturnType($v, self::TYPE_VAR); } - $exprCode = $this->convertExprType($expr, $this->getReturnType(), $type); + $returnType = $this->getReturnType(); + $exprCode = $this->convertExprType($expr, $returnType, $type); // return 如果使用了 Indirect 语句,可能会导致变量提前析构,出现悬空指针 // 将 Indirect 赋值给临时变量后,使用 Ctor::Copy 解除了 Indirect,保证内存安全 if (!$this->isVarExpr($v->expr) and !$this->isScalar($v->expr)) { $tmpVar = $this->genTmpVarName(); // 必须提前声明变量,否则在末尾声明并 return 可能会被 gcc 优化掉 - $this->addLocalVar($tmpVar, $type); + $this->addLocalVar($tmpVar, $returnType); $code = $tmpVar . ' = ' . $exprCode . ';' . PHP_EOL; - $code .= $this->getIndent() . 'return ' . $tmpVar . ';'; + // 解析表达式后可能会插入语句,因此需要在末尾添加 return 语句,而不是直接返回 + $this->afterStmtLines[] = $this->getIndent() . 'return ' . $tmpVar . ';'; } else { $code = 'return ' . $exprCode . ';'; } @@ -2593,7 +2601,7 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->convertObjectExpr($this->parseExpr($node->expr)); } - protected function parseConstFetch(Node\Expr\ConstFetch $expr): string + protected function parseConstFetch(Node\Expr\ConstFetch $expr, bool $scalar = false): string { if ($expr->name->getType() != 'Name' and !($expr->name instanceof Node\Name\FullyQualified)) { abort($expr); @@ -2614,6 +2622,9 @@ class CompilerBase extends \PhpAot\Core\Translator if ($name === 'PHP_EOL') { return '"' . $this->escapeString(PHP_EOL) . '"'; } + if ($scalar) { + return constant($expr->name); + } if ($this->isNameExpr($expr->name)) { if (str_contains($name, '::')) { $ns = explode('::', $name)[0]; diff --git a/src/Php/Translator.php b/src/Php/Translator.php index b72fda4a..d53dd988 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -307,6 +307,9 @@ class Translator extends Preprocessor } $argInfoList = $func->argInfoList; if ($argInfoList) { + /** + * @var ArgInfo $argInfo + */ foreach ($argInfoList as $argInfo) { if ($argInfo->variadic) { $arg = self::TYPE_ARRAY . ' ' . $argInfo->name . '()';