diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index e0b22f73..11156f9c 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -135,6 +135,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected array $beforeStmtLines = []; protected array $afterStmtLines = []; protected bool $inLoop = false; + protected bool $inAssignExpr = false; protected bool $stubFile = false; protected bool $stubFileIncluded = false; protected Parser $parser; @@ -534,9 +535,15 @@ class CompilerBase extends \PhpAot\Core\Translator case 'Expr_Empty': return $this->parseEmpty($expr); case 'Expr_Assign': - return $this->parseAssign($expr); + $this->inAssignExpr = true; + $result = $this->parseAssign($expr); + $this->inAssignExpr = false; + return $result; case 'Expr_AssignRef': - return $this->parseAssignRef($expr); + $this->inAssignExpr = true; + $result = $this->parseAssignRef($expr); + $this->inAssignExpr = false; + return $result; case 'Expr_Print': return $this->parsePrint($expr); case 'Expr_BinaryOp_Equal': @@ -712,35 +719,43 @@ class CompilerBase extends \PhpAot\Core\Translator } } - protected function parseAssign(Node $v): string + protected function parseAssignArrayDim(Node $left, Node $right): string + { + if ($this->isPropertyFetch($left)) { + return $this->parseAssignPropertyArrayDim($left, $right); + } + $array = $this->parseIdentifier($left->var); + $code = ''; + // 这是 PHP 的初始化+赋值写法,需要先创建数组 + if (!$this->hasVar($array) and $this->isVarExpr($left->var)) { + $this->addLocalVar($array, self::TYPE_ARRAY); + } + + $value = $this->trimBrackets($this->parseExpr($right)); + if ($left->dim === null) { + return $code . "$array.offsetSet(php::null, $value)"; + } else { + $dim = $this->trimBrackets($this->parseIdentifier($left->dim)); + return $code . "$array.offsetSet($dim, $value)"; + } + } + + protected function parseAssignPropertyFetch(Node $left, Node $right): string + { + $array = $this->parseIdentifier($left->var); + $propName = $this->identifierToStr($left->name); + return "$array.setProperty($propName, " . $this->trimBrackets($this->parseExpr($right)) . ")"; + } + + protected function parseAssign(Node\Expr\Assign $v): string { $left = $v->var; $right = $v->expr; if ($left->getType() === self::EXPR_ARRAY_DIM_FETCH) { - $array = $this->parseIdentifier($left->var); - $code = ''; - // 这是 PHP 的初始化+赋值写法,需要先创建数组 - if (!$this->hasVar($array) and $this->isVarExpr($left->var)) { - $this->addLocalVar($array, self::TYPE_ARRAY); - } - - // 这是属性赋值操作 - if ($this->isPropertyFetch($left->var)) { - return $this->parseAssignPropertyArrayDim($left, $right); - } - - $value = $this->trimBrackets($this->parseExpr($right)); - if ($left->dim === null) { - return $code . "$array.offsetSet(php::null, $value)"; - } else { - $dim = $this->trimBrackets($this->parseIdentifier($left->dim)); - return $code . "$array.offsetSet($dim, $value)"; - } + return $this->parseAssignArrayDim($left, $right); } elseif ($left->getType() === 'Expr_PropertyFetch') { - $array = $this->parseIdentifier($left->var); - $propName = $this->identifierToStr($left->name); - return "$array.setProperty($propName, " . $this->trimBrackets($this->parseExpr($right)) . ")"; + return $this->parseAssignPropertyFetch($left, $right); } elseif ($left->getType() === 'Expr_StaticPropertyFetch') { $class = $this->identifierToStr($left->class); $propName = $this->identifierToStr($left->name); @@ -789,7 +804,7 @@ class CompilerBase extends \PhpAot\Core\Translator if (!$this->hasVar($var)) { $this->addLocalVar($var, self::TYPE_VAR); } - $code .= "$var = $tmpVar.offsetGet($k); "; + $code .= "$var = $tmpVar.offsetGetIndirect($k); "; } else { abort($item); } @@ -1258,10 +1273,6 @@ class CompilerBase extends \PhpAot\Core\Translator $this->convertExprType($expr, $type, $rightType) . ';'; } return $this->parseArrayDimStore($node->var->var, $dim, $tmpVar); - } elseif ($this->isPropertyFetch($node->var)) { - $obj = $this->parseIdentifier($node->var->var); - $prop = $this->identifierToStr($node->var->name); - return $obj . '.setProperty(' . $prop . ', ' . $obj . '.getProperty(' . $prop . ') ' . $this->removeAssignOp($op) . ' ' . $expr . ')'; } else { return $var . ' ' . $op . ' (' . $expr . ')'; } @@ -1328,7 +1339,7 @@ class CompilerBase extends \PhpAot\Core\Translator $this->fatalError($node, 'Unsupported operand types: null + array'); } $dim = $this->parseIdentifier($node->dim); - return $var . '.offsetGet(' . $this->trimBrackets($dim) . ')'; + return $var . '.offsetGetIndirect(' . $this->trimBrackets($dim) . ')'; } protected function parseArrayDimStore($array, $dim, $var): string @@ -2009,7 +2020,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parsePropertyFetch(Node\Expr\PropertyFetch $expr): string { - return $this->convertToObject($expr->var) . '.getProperty("' . $this->parseIdentifier($expr->name) . '")'; + return $this->convertToObject($expr->var) . '.getPropertyIndirect("' . $this->parseIdentifier($expr->name) . '")'; } protected function parseAssignOpShiftRight(Node $node): string diff --git a/tests/aot/object-link.phpt b/tests/aot/object-link.phpt new file mode 100644 index 00000000..46944868 --- /dev/null +++ b/tests/aot/object-link.phpt @@ -0,0 +1,15 @@ +--TEST-- +object link operator +--FILE-- +prop = ['dim2' => ['dim3' => 'value']]; + $o->prop['dim2']['dim3'] = 'hello'; + + var_dump($o->prop['dim2']['dim3']); +} +?> +--EXPECT-- +string(5) "hello" diff --git a/tests/aot/property-assign-op.phpt b/tests/aot/property-assign-op.phpt new file mode 100644 index 00000000..eb7aa50c --- /dev/null +++ b/tests/aot/property-assign-op.phpt @@ -0,0 +1,11 @@ +--TEST-- +property assign op +--FILE-- +a = 1024; +$o->a *= 2; +var_dump($o->a); +?> +--EXPECT-- +int(2048)