From dfc94ac09e2fdcd20a6fd0ef6d9da49bed21499c Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 7 Jul 2026 15:10:11 +0800 Subject: [PATCH] =?UTF-8?q?refactor(compiler):=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E5=B1=9E=E6=80=A7=E6=9B=BF=E4=BB=A3=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E6=A0=87=E8=AF=86=E5=A4=84=E7=90=86=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E5=86=99=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Php/CompilerBase.php | 90 ++++++++++++++++++++++------- src/Php/Context/FunctionContext.php | 6 -- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 20cef38a..adac6bb0 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -108,6 +108,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont protected const string NATIVE_PROPERTY_VALUE_VAR = 'var'; protected const string NATIVE_PROPERTY_VALUE_DYNAMIC = 'dynamic'; protected const string ATTR_ARRAY_DIM_FETCH_UPDATE = 'aotArrayDimFetchUpdate'; + protected const string ATTR_PROPERTY_FETCH_UPDATE = 'aotPropertyFetchUpdate'; /** * Keyword methods (to* builtins) with mandated return types. @@ -628,7 +629,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont case 'Expr_ArrayDimFetch': return $this->parseArrayDimFetch($expr); case 'Expr_PropertyFetch': - return $this->parsePropertyFetch($expr, $this->context->inAssignExpr); + return $this->parsePropertyFetch($expr); case 'Expr_NullsafePropertyFetch': return $this->parseNullsafePropertyFetch($expr); case 'Expr_NullsafeMethodCall': @@ -3018,11 +3019,26 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return $this->parseArrayDimFetchUpdate($expr); } - $oriInAssignExpr = $this->context->inAssignExpr; - $this->context->inAssignExpr = true; - $code = $this->parseIdentifier($expr); - $this->context->inAssignExpr = $oriInAssignExpr; - return $code; + if ($expr instanceof Expr\PropertyFetch) { + return $this->parsePropertyFetchUpdate($expr); + } + + if ($expr instanceof Expr\NullsafePropertyFetch) { + return $this->parseNullsafePropertyFetchUpdate($expr); + } + + return $this->parseIdentifier($expr); + } + + protected function parseNodeWithUpdateAttribute(NodeAbstract $node, string $attribute, bool $update, callable $parser): string + { + $attributes = $node->getAttributes(); + $node->setAttribute($attribute, $update); + try { + return $parser(); + } finally { + $node->setAttributes($attributes); + } } protected function parseArrayDimFetchRead(Expr\ArrayDimFetch $node): string @@ -3037,13 +3053,12 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont protected function parseArrayDimFetchWithUpdate(Expr\ArrayDimFetch $node, bool $update): string { - $attributes = $node->getAttributes(); - $node->setAttribute(self::ATTR_ARRAY_DIM_FETCH_UPDATE, $update); - try { - return $this->parseArrayDimFetch($node); - } finally { - $node->setAttributes($attributes); - } + return $this->parseNodeWithUpdateAttribute( + $node, + self::ATTR_ARRAY_DIM_FETCH_UPDATE, + $update, + fn() => $this->parseArrayDimFetch($node) + ); } protected function isArrayDimFetchUpdate(Expr\ArrayDimFetch $node): bool @@ -3061,9 +3076,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return $this->parseStdContainerDimFetch($node); } - $var = $write && $node->var instanceof Expr\ArrayDimFetch - ? $this->parseArrayDimFetchUpdate($node->var) - : $this->parseIdentifier($node->var); + $var = $write ? $this->parseWritableIdentifier($node->var) : $this->parseIdentifier($node->var); if ($this->isVarExpr($node->var)) { if ($var === 'GLOBALS') { return $this->parseGlobalsArrayDimFetch($node); @@ -3094,10 +3107,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return $var . '.newItem()'; } } else { - $oriInAssignExpr = $this->context->inAssignExpr; - $this->context->inAssignExpr = false; $dim = $this->parseIdentifier($node->dim); - $this->context->inAssignExpr = $oriInAssignExpr; return $var . '.item(' . $dim . ', ' . $this->escapeBool($write) . ')'; } } @@ -5124,12 +5134,38 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return null; } - protected function parsePropertyFetch(Expr\PropertyFetch $expr, bool $update = false): string + protected function parsePropertyFetchRead(Expr\PropertyFetch $expr): string + { + return $this->parsePropertyFetchWithUpdate($expr, false); + } + + protected function parsePropertyFetchUpdate(Expr\PropertyFetch $expr): string + { + return $this->parsePropertyFetchWithUpdate($expr, true); + } + + protected function parsePropertyFetchWithUpdate(Expr\PropertyFetch $expr, bool $update): string { + return $this->parseNodeWithUpdateAttribute( + $expr, + self::ATTR_PROPERTY_FETCH_UPDATE, + $update, + fn() => $this->parsePropertyFetch($expr) + ); + } + + protected function isPropertyFetchUpdate(Expr\PropertyFetch|Expr\NullsafePropertyFetch $expr): bool + { + return $expr->getAttribute(self::ATTR_PROPERTY_FETCH_UPDATE, false) === true; + } + + protected function parsePropertyFetch(Expr\PropertyFetch $expr): string + { + $update = $this->isPropertyFetchUpdate($expr); $object = $expr->var; $property = $expr->name; $id = $this->getPropertyIdentifier($expr, $object, $property); - $objectName = $this->parseIdentifier($object); + $objectName = $update ? $this->parseWritableIdentifier($object) : $this->parseIdentifier($object); if ($this->isVarExpr($object) and !$this->hasVar($objectName)) { $this->errorUndefinedVariable($object); } @@ -7460,6 +7496,16 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return $this->parseNullsafeExpr($expr); } + protected function parseNullsafePropertyFetchUpdate(Expr\NullsafePropertyFetch $expr): string + { + return $this->parseNodeWithUpdateAttribute( + $expr, + self::ATTR_PROPERTY_FETCH_UPDATE, + true, + fn() => $this->parseNullsafePropertyFetch($expr) + ); + } + protected function parseNullsafeMethodCall(Expr\NullsafeMethodCall $expr): string { return $this->parseNullsafeExpr($expr); @@ -7500,12 +7546,12 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont $tmpFn = $this->genTmpVarName(); $code = $comment . PHP_EOL . 'auto ' . $tmpFn . ' = [&]() -> ' . self::TYPE_VAR . '{' . PHP_EOL; - $update = $this->escapeBool($this->context->inAssignExpr); foreach ($list as $key => $item) { $tmpVar = $this->addTmpVar($key !== $last ? self::TYPE_OBJECT : self::TYPE_VAR); $code .= "if ({$object}.isNull()) { return " . self::VALUE_NULL . '; }'; if ($item[0] == 'property') { + $update = $this->escapeBool($this->isPropertyFetchUpdate($item[2])); $code .= $this->getIndent() . "{$tmpVar} = {$object}.attr({$item[1]}, {$update});"; } else { $beforeStmtCount = count($this->context->beforeStmtLines); diff --git a/src/Php/Context/FunctionContext.php b/src/Php/Context/FunctionContext.php index 6f3c145b..fb700706 100644 --- a/src/Php/Context/FunctionContext.php +++ b/src/Php/Context/FunctionContext.php @@ -59,10 +59,6 @@ class FunctionContext /** True if any continue N (N > 1) appears in this function. */ public bool $hasMultiLevelContinue = false; - /** - * 赋值表达式的左值,写操作,右值为读操作. - */ - public bool $inAssignExpr = false; public array $beforeStmtLines = []; public array $afterStmtLines = []; public array $objectProps; @@ -96,7 +92,6 @@ class FunctionContext $this->inClosure = false; $this->closureReturnTypeCheck = null; $this->closureReturnTypeStr = ''; - $this->inAssignExpr = false; } public function enterScope(): void @@ -123,6 +118,5 @@ class FunctionContext $this->scopeLayouts = []; $this->scopeLevel = 0; $this->inLoop = false; - $this->inAssignExpr = false; } }