refactor(compiler): 优化标准数组访问的类型检测和表达式解析

- 移除 phpx_std_array.h 头文件引用
- 将表达式解析提取为独立变量以提高可读性
- 添加标准数组维度获取的属性缓存机制
- 实现完整的数组维度访问层级检测
- 修复参数传递中的数组转换逻辑
- 优化嵌套数组访问的解析流程
pull/1/head
韩天峰 4 months ago
parent 36be831b83
commit 805f2a62ee
  1. 22
      src/Php/CompilerBase.php
  2. 9
      src/Php/Parser/StdArrayParser.php
  3. 25
      tests/aot/std-array/002.phpt
  4. 19
      tests/aot/std-array/003.phpt

@ -134,7 +134,6 @@ class CompilerBase extends \PhpAot\Core\Translator
protected array $globalHeaders = [
'phpx.h',
'phpx_helper.h',
'phpx_std_array.h',
'phpx_func.h',
'php_func_decl.h',
'php_global_var_decl.h',
@ -1595,7 +1594,8 @@ class CompilerBase extends \PhpAot\Core\Translator
return $this->parseAssignArrayDim($left, $right);
}
return $var . ' = ' . $this->convertExprType($this->parseExpr($right), $this->detectTypeOfExpr($left), $this->detectTypeOfExpr($right));
$rightExpr = $this->parseExpr($right);
return $var . ' = ' . $this->convertExprType($rightExpr, $this->detectTypeOfExpr($left), $this->detectTypeOfExpr($right));
}
protected function parseEcho(mixed $v): string
@ -2156,7 +2156,15 @@ class CompilerBase extends \PhpAot\Core\Translator
break;
case 'Expr_ArrayDimFetch':
if ($this->isStdArrayExpr($expr)) {
return $this->getStdArrayInfo($expr)['type'];
if (!$expr->hasAttribute('stdArrayDimFetch')) {
$this->parseStdArrayDimFetch($expr);
}
$attr = $expr->getAttribute('stdArrayDimFetch');
if ($attr['accessLevel'] === $attr['totalLevel']) {
return $this->context->stdArrays[$attr['var']]['type'];
} else {
return self::TYPE_ARRAY;
}
}
break;
case 'Expr_New':
@ -3459,7 +3467,13 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function parseArg(Node\Arg $arg): string
{
if ($this->isArrayDimFetch($arg->value) and $this->isStdArrayExpr($arg->value)) {
return $this->convertArrayExpr($this->parseStdArrayDimFetch($arg->value, true));
$valueExpr = $this->parseStdArrayDimFetch($arg->value);
$attr = $arg->value->getAttribute('stdArrayDimFetch');
if ($attr['accessLevel'] === $attr['totalLevel']) {
return $this->convertExprFromType($this->context->stdArrays[$attr['var']]['type'], $valueExpr);
} else {
return $this->convertArrayExpr($valueExpr);
}
}
$expr = $this->parseIdentifier($arg->value);
if ($this->isVarExpr($arg->value) and $this->isStdArray($arg->value->name)) {

@ -64,7 +64,7 @@ trait StdArrayParser
return $arrayDimFetch . ' ' . $binaryOp . '= ' . $this->convertExprFromType($info['type'], $this->parseExpr($expr->expr));
}
protected function parseStdArrayDimFetch(Expr\ArrayDimFetch $expr, bool $toArray = false): string
protected function parseStdArrayDimFetch(Expr\ArrayDimFetch $expr): string
{
$tmp = $expr;
$nesting = [];
@ -92,11 +92,10 @@ trait StdArrayParser
}
}
if (!$toArray and count($nesting) !== count($info['sizes']) + 1) {
$this->fatalError($expr, 'Wrong dimension access std::array used');
}
$nesting = array_reverse($nesting);
$expr->setAttribute('stdArrayDimFetch', ['var' => $nesting[0], 'accessLevel' => $level, 'totalLevel' => count($info['sizes'])]);
return implode('', array_reverse($nesting));
return implode('', $nesting);
}
protected function parseStdArray(string $var, Expr\StaticCall $expr): string

@ -0,0 +1,25 @@
--TEST--
std array: 002
--FILE--
<?php
function main() {
$array = std::array(std::array(std::array(native_types::type_int, 13), 16), 19);
$index = 9;
$index2 = 5;
$array[$index2][$index][0] = 2026;
$array[$index2][$index][12] = 2019;
var_dump($array[$index2][$index][0]);
var_dump(count($array[$index2][$index]));
$value3 = $array[$index2][$index];
var_dump($value3[12]);
var_dump(count($value3));
}
?>
--EXPECT--
int(2026)
int(13)
int(2019)
int(13)

@ -0,0 +1,19 @@
--TEST--
std array: 003
--FILE--
<?php
function main() {
$array = std::array(std::array(std::array(native_types::type_int, 13), 16), 19);
$index = 9;
$index2 = 5;
$array[$index2][$index][0] = 2026;
$array[$index2][$index][12] = 2019;
$array2 = $array[$index2];
var_dump($array2[$index][0]);
var_dump($array2[$index][12]);
}
?>
--EXPECT--
int(2026)
int(2019)
Loading…
Cancel
Save