diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 2e17335a..e5835423 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1392,8 +1392,8 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return $this->parseConstFetch($expr); case 'Expr_Assign': case 'Expr_AssignRef': - if (!$this->isVarExpr($expr->var)) { - $this->fatalError($expr, 'When an assignment expression serves as an rvalue, it must be an assignment of a variable'); + if (!$this->isVarExpr($expr->var) && !$this->isPropertyFetch($expr->var) && !$this->isArrayDimFetch($expr->var)) { + $this->fatalError($expr, 'When an assignment expression serves as an rvalue, it must be an assignment of a variable, property, or array element'); } return $this->parseExprAsValue($expr); default: @@ -2318,6 +2318,11 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont protected function detectVarType($var): string { + // Unwrap ArrayDimFetch to get the underlying variable type; + // the dim/index does not affect the base variable's type. + if ($var instanceof Expr\ArrayDimFetch) { + return $this->detectVarType($var->var); + } $name = $this->parseIdentifier($var); if ($this->isStdContainer($name)) { return self::TYPE_ARRAY; diff --git a/src/Php/Parser/AssignOpTrait.php b/src/Php/Parser/AssignOpTrait.php index b23b0614..d4b9ef7c 100644 --- a/src/Php/Parser/AssignOpTrait.php +++ b/src/Php/Parser/AssignOpTrait.php @@ -79,13 +79,13 @@ trait AssignOpTrait $chain = array_reverse($chain); $list = []; - $list[] = $this->getIndent() . $tmpVar . ' = ' . $this->parseExpr($next); + $list[] = $tmpVar . ' = ' . $this->parseExpr($next); $rightVar = new Variable($tmpVar); foreach ($chain as $var) { - $list[] = $this->getIndent() . $this->parseAssignFinally($var, $rightVar); + $list[] = $this->parseAssignFinally($var, $rightVar); } - return implode(";\n" . $this->getIndent(), $list); + return '(' . implode(', ', $list) . ')'; } protected function parseAssign(Expr\Assign $v): string @@ -266,6 +266,8 @@ trait AssignOpTrait return $this->parseStdContainerAssign($left, $right); } return $this->parseAssignArrayDim($left, $right); + } elseif ($this->isArrayDimFetch($left) and $this->isPropertyFetch($left->var)) { + return $this->parseAssignPropertyArrayDim($left, $right); } if ($propertyWriteTarget !== null) { diff --git a/tests/aot/basic/multi-var-assign-chained.phpt b/tests/aot/basic/multi-var-assign-chained.phpt new file mode 100644 index 00000000..ab8cf6ec --- /dev/null +++ b/tests/aot/basic/multi-var-assign-chained.phpt @@ -0,0 +1,45 @@ +--TEST-- +Chained assignment with array append ([]), property write, and variable write as rvalue inside constructor argument +--FILE-- +arr[] = $arr[] = $this->value = $value = 1); + var_dump($this->value, $value, $this->arr, $arr); + } +} + +function main() +{ + new Test; +} +?> +--EXPECT-- +int(1) +int(1) +int(1) +array(1) { + [0]=> + int(1) +} +array(2) { + [0]=> + int(0) + [1]=> + int(1) +} diff --git a/tests/aot/basic/multi-var-assign.phpt b/tests/aot/basic/multi-var-assign.phpt new file mode 100644 index 00000000..d2a10236 --- /dev/null +++ b/tests/aot/basic/multi-var-assign.phpt @@ -0,0 +1,50 @@ +--TEST-- +Multi-variable assignment: property assignment as rvalue in constructor argument expression +--FILE-- +value = new Test2($this->arr[0] = $this->value2 = 123); + var_dump($this->value2, $this->arr); + $this->value = new Test2($this->arr[0] = $this->value3 = $this->value2 = 456); + var_dump($this->value2, $this->value3, $this->arr); + } +} + +function main() +{ + new Test; +} +?> +--EXPECT-- +int(123) +int(123) +array(1) { + [0]=> + int(123) +} +int(456) +int(456) +int(456) +array(1) { + [0]=> + int(456) +}