diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 6f1ceeb6..e504c523 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -917,7 +917,7 @@ class CompilerBase extends \PhpAot\Core\Translator case 'Scalar_Float': return $this->parseScalarFloat($expr); case 'Scalar_String': - return $expr->hasAttribute('noLiteralString') ? $this->genCharPtr($expr->value) : $this->getLiteralString($expr->value); + return $expr->hasAttribute('noLiteralString') ? $this->genCharPtr($expr->value, true) : $this->getLiteralString($expr->value); default: abort($expr); break; @@ -2586,21 +2586,7 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->isVarExpr($arg->value)) { $name = $this->parseIdentifier($arg->value); if ($byRef) { - if (!$this->hasVar($name)) { - // 若参数是引用类型,可以传入未定义变量,将立即创建变量作为引用 - $this->addLocalVar($name, self::TYPE_REF); - } else { - // 本地变量,且是原生类型,则转为普通变量 - if ($this->hasLocalVar($name) and $this->isNativeType($this->getVarType($name))) { - $this->context->localVars[$name] = self::TYPE_VAR; - } - // 需要引用类型的参数,使用临时变量作为引用,并替换掉实际的参数 - $tmpVar = $this->genTmpVarName(); - $this->addLocalVar($tmpVar, self::TYPE_REF); - $this->context->beforeStmtLines[] = $tmpVar . ' = ' . $this->parseExpr($arg->value) . '.toReference();'; - $name = $tmpVar; - } - $list_args[] = '&' . $name; + $list_args[] = $this->parseArgRefVar($arg, $name); continue; } if (!$this->hasVar($name)) { @@ -2639,6 +2625,18 @@ class CompilerBase extends \PhpAot\Core\Translator $list_args[] = $array . '.itemRef(' . $this->identifierToStr($arg->value->dim) . ')'; continue; } + } elseif ($this->isFuncCallExpr($arg->value)) { + if ($this->isNameExpr($arg->value->name) and $arg->value->name->toString() === 'refval') { + if (count($arg->value->args) === 1 and $this->isVarExpr($arg->value->args[0]->value)) { + $name = $this->parseVariable($arg->value->args[0]->value); + // 消除 refval() 函数调用,直接使用变量 + $arg->value = $arg->value->args[0]->value; + $list_args[] = $this->parseArgRefVar($arg, $name); + continue; + } else { + $this->fatalError($arg, 'The refval function only accepts one parameter of variable type'); + } + } } else { if ($byRef) { $list_args[] = $this->parseChainedExpr($arg->value, self::OP_REFVAL); @@ -2667,6 +2665,25 @@ class CompilerBase extends \PhpAot\Core\Translator return '{' . implode(', ', $list_args) . '}'; } + protected function parseArgRefVar(Node\Arg $arg, string $name): string + { + if (!$this->hasVar($name)) { + // 若参数是引用类型,可以传入未定义变量,将立即创建变量作为引用 + $this->addLocalVar($name, self::TYPE_REF); + } else { + // 本地变量,且是原生类型,则转为普通变量 + if ($this->hasLocalVar($name) and $this->isNativeType($this->getVarType($name))) { + $this->context->localVars[$name] = self::TYPE_VAR; + } + // 需要引用类型的参数,使用临时变量作为引用,并替换掉实际的参数 + $tmpVar = $this->genTmpVarName(); + $this->addLocalVar($tmpVar, self::TYPE_REF); + $this->context->beforeStmtLines[] = $tmpVar . ' = ' . $this->parseExpr($arg->value) . '.toReference();'; + $name = $tmpVar; + } + return '&' . $name; + } + protected function parseArg(Node\Arg $arg): string { return $this->parseIdentifier($arg->value); @@ -3702,7 +3719,7 @@ class CompilerBase extends \PhpAot\Core\Translator { // 对 eval() 指令的 PHP 代码段禁止字面量优化 $expr->expr->setAttribute('noLiteralString', true); - return 'php::eval(' . $this->parseIdentifier($expr->expr) . ')'; + return 'php::eval(' . $this->identifierToStr($expr->expr) . ')'; } protected function parseInclude(Expr\Include_ $expr): string diff --git a/tests/aot/ref/refval.phpt b/tests/aot/ref/refval.phpt new file mode 100644 index 00000000..1966fd0f --- /dev/null +++ b/tests/aot/ref/refval.phpt @@ -0,0 +1,15 @@ +--TEST-- +refval +--FILE-- + +--EXPECT-- +php refval test \ No newline at end of file