fix(aot): 修复空合并运算符的编译逻辑

- 在 parseExpr 中添加对 replace 属性的检查
- 修改 coalesce 运算符的处理逻辑,避免重复函数调用
- 添加临时变量来存储 coalesce 表达式的结果
- 更新测试用例以验证正确的执行顺序和结果
- 添加新的测试用例验证 null 合并运算符行为
- 添加测试用例验证 ??= 运算符的链式赋值功能
pull/1/head
韩天峰 5 months ago
parent fdf7eb9765
commit ecb7795243
  1. 17
      src/Php/CompilerBase.php
  2. 16
      tests/aot/coalesce/002.phpt
  3. 20
      tests/aot/coalesce/003.phpt
  4. 28
      tests/aot/coalesce/004.phpt

@ -310,6 +310,9 @@ class CompilerBase extends \PhpAot\Core\Translator
public function parseExpr(NodeAbstract $expr)
{
if ($expr->hasAttribute('replace')) {
return $expr->getAttribute('replace');
}
$type = $expr->getType();
$this->writeLog('Line ' . $this->getLine($expr) . ': ' . $type);
if ($expr->getLine() === $this->debugLine) {
@ -2924,17 +2927,21 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->checkVarMustExist($expr->left, $left);
}
$this->mustNoCall($expr->right);
$right = $this->parseIdentifier($expr->right);
$this->checkVarMustExist($expr->right, $right);
$isset = $this->parseChainedExpr($expr->left, self::OP_ISSET, true);
$chainOpResult = $expr->left->getAttribute('chainOpResult');
if ($chainOpResult) {
$left = $chainOpResult;
}
return $isset . ' ? ' . $left . ' : ' . $right;
$right = $this->parseIdentifier($expr->right);
$this->checkVarMustExist($expr->right, $right);
$tmpVar = $this->addTmpVar(self::TYPE_VAR);
$this->context->beforeStmtLines[] = '// Coalesce: ' . $this->printer->prettyPrintExpr($expr) . PHP_EOL .
$tmpVar . ' = ' . $isset . ' ? ' . $left . ' : ' . $right . ';';
$expr->setAttribute('replace', $tmpVar);
return $tmpVar;
}
protected function parseBinaryOpNotIdentical(Node\Expr\BinaryOp $expr): string

@ -10,14 +10,16 @@ function f($x)
}
function main() {
$r1 = f(1);
$r2 = f(2);
$a = f(null) ?? $r1 ?? $r2;
$a = f(null) ?? f(2);
var_dump($a);
$a = f(1) ?? f(2);
var_dump($a);
}
?>
--EXPECTF--
f(1)
f(2)
--EXPECT--
f(0)
int(1)
f(2)
int(2)
f(1)
int(1)

@ -0,0 +1,20 @@
--TEST--
Test ?? operator
--FILE--
<?php
function f($x)
{
printf("%s(%d)\n", __FUNCTION__, $x);
return $x;
}
function main() {
$a = f(null) ?? f(1) ?? f(2);
var_dump($a);
}
?>
--EXPECT--
f(0)
f(1)
int(1)

@ -0,0 +1,28 @@
--TEST--
Test ?? operator
--FILE--
<?php
function foo1() {
$c = 100;
$a ??= $b ??= $c;
var_dump($a, $b);
}
function foo2() {
$c = 100;
$b = 33;
$a ??= $b ??= $c;
var_dump($a, $b);
}
function main() {
foo1();
foo2();
}
?>
--EXPECT--
int(100)
int(100)
int(33)
int(33)
Loading…
Cancel
Save