diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index bf2a88f1..e0a5023a 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1266,6 +1266,18 @@ class CompilerBase extends \PhpAot\Core\Translator return array_key_exists($name, $this->classes); } + protected function getNativeStaticMethod(string $class, string $method): string|false + { + if (!$this->hasNativeClass($class)) { + return false; + } + $class = $this->getClassDef($class); + if (!$class->hasMethod($method)) { + return false; + } + return $this->getNativeName($method, $class->name, $class->namespace); + } + protected function getClassDef(string $name): ClassDef { $name = trim($name, '\\'); @@ -1704,6 +1716,11 @@ class CompilerBase extends \PhpAot\Core\Translator } else { $this->fatalError($node->var, "The variable `{$node->var->name}` is undefined"); } + } else { + $type = $this->getVarType($var); + if ($type === self::TYPE_BOOL || $type === self::TYPE_INT || $type === self::TYPE_FLOAT) { + $this->fatalError($node, 'Cannot use [] for numbers'); + } } if ($this->getVarType($var) === self::TYPE_STR) { if ($node->dim === null) { @@ -1864,10 +1881,19 @@ class CompilerBase extends \PhpAot\Core\Translator } } elseif ($this->isPropertyFetch($arg->value)) { if ($funcName and Reflection::isReferenceArg($funcName, $i)) { - $obj = $this->parseIdentifier($arg->value->var); + $obj = $this->parseIdentifier($arg->value->var); $list_args[] = $obj . '.attrRef(' . $this->identifierToStr($arg->value->name) . ')'; continue; } + } elseif ($this->isArrayDimFetch($arg->value)) { + if ($funcName and Reflection::isReferenceArg($funcName, $i)) { + $obj = $this->parseIdentifier($arg->value->var); + if ($arg->value->dim === null) { + $this->fatalError($arg, 'Array dimension must be a constant expression'); + } + $list_args[] = $obj . '.itemRef(' . $this->identifierToStr($arg->value->dim) . ')'; + continue; + } } // 不支持变长参数展开的语法,例如:array_merge(...$arr) if ($arg->unpack) { @@ -2916,12 +2942,22 @@ class CompilerBase extends \PhpAot\Core\Translator $fn = 'php::concat({' . $this->identifierToStr($expr->class) . ', "::", ' . $this->identifierToStr($expr->name) . '})'; } else { $class = $this->parseIdentifier($expr->class); + $method = $this->parseIdentifier($expr->name); if ($class === 'self') { $class = $this->class; } elseif ($class === 'parent') { return $this->parseParentMethodCall($expr); } - $method = $this->parseIdentifier($expr->name); + + if ($this->isNameExpr($expr->class) and $this->isIdExpr($expr->name)) { + $nativeFunc = $this->getNativeStaticMethod($class, $method); + $args = $this->parseNativeCallArgs($expr->args, $nativeFunc); + if ($args) { + return self::PREFIX . $nativeFunc . '(php::null_object, ' . $args . ')'; + } else { + return self::PREFIX . $nativeFunc . '(php::null_object)'; + } + } $ce = $this->getClassEntryPtr($class); $fn = $ce . ', ' . $this->getFuncPtr($class . '::' . $method, false); } diff --git a/tests/aot/item-ref.phpt b/tests/aot/item-ref.phpt new file mode 100644 index 00000000..7cfec61d --- /dev/null +++ b/tests/aot/item-ref.phpt @@ -0,0 +1,46 @@ +--TEST-- +item reference +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + array(7) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + [3]=> + int(3) + [4]=> + int(4) + [5]=> + int(5) + [6]=> + int(9) + } + [1]=> + array(7) { + [0]=> + int(5) + [1]=> + int(3) + [2]=> + int(1) + [3]=> + int(9) + [4]=> + int(2) + [5]=> + int(4) + [6]=> + int(3) + } +} \ No newline at end of file