feat(compiler): 支持匿名类静态访问方法和属性

- 添加匿名类索引计数器用于生成唯一类名
- 实现对象类型获取功能以支持动态类型解析
- 优化静态调用解析逻辑以处理变量表达式情况
- 添加测试用例验证匿名类静态访问功能
pull/1/head
韩天峰 7 months ago
parent 35a81376a1
commit a1d74df985
  1. 21
      src/Php/CompilerBase.php
  2. 25
      tests/zend/anon/008.phpt

@ -73,6 +73,7 @@ class CompilerBase extends \PhpAot\Core\Translator
protected array $literalStrings = []; protected array $literalStrings = [];
protected int $literalStringIndex = 0; protected int $literalStringIndex = 0;
protected int $tmpVarIndex = 0; protected int $tmpVarIndex = 0;
protected int $anonClassIndex = 0;
protected int $classIndex = 0; protected int $classIndex = 0;
/** /**
@ -252,6 +253,11 @@ class CompilerBase extends \PhpAot\Core\Translator
return isset($this->objects[$object]); return isset($this->objects[$object]);
} }
public function getObjectType(string $object): string
{
return $this->objects[$object] ?? 'stdClass';
}
public function parseExpr(mixed $expr) public function parseExpr(mixed $expr)
{ {
$type = $expr->getType(); $type = $expr->getType();
@ -485,7 +491,7 @@ class CompilerBase extends \PhpAot\Core\Translator
public function genAnonClassName(): string public function genAnonClassName(): string
{ {
return self::ANON_CLASS . $this->tmpVarIndex++; return self::ANON_CLASS . $this->anonClassIndex++;
} }
public function writeFile(string $file, string $content): void public function writeFile(string $file, string $content): void
@ -3156,16 +3162,25 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function parseStaticCall(Node\Expr\StaticCall $expr): string protected function parseStaticCall(Node\Expr\StaticCall $expr): string
{ {
if ($this->isVarExpr($expr->class) or $this->isVarExpr($expr->name)) { if ($this->isVarExpr($expr->class) or $this->isVarExpr($expr->name)) {
$fn = 'php::concat({' . $this->identifierToStr($expr->class) . ', "::", ' . $this->identifierToStr($expr->name) . '})'; $var = $this->parseIdentifier($expr->class);
if ($this->isTypedObject($var)) {
$class = $this->getObjectType($var);
goto _do_call;
} elseif ($this->getVarType($var) == self::TYPE_OBJECT) {
$fn = 'php::concat({' . $var . '.getClassName()' . ', "::", ' . $this->identifierToStr($expr->name) . '})';
} else {
$fn = 'php::concat({' . $this->identifierToStr($expr->class) . ', "::", ' . $this->identifierToStr($expr->name) . '})';
}
} else { } else {
$class = $this->parseIdentifier($expr->class); $class = $this->parseIdentifier($expr->class);
$method = $this->parseIdentifier($expr->name);
if ($class === 'self') { if ($class === 'self') {
$class = $this->class; $class = $this->class;
} elseif ($class === 'parent') { } elseif ($class === 'parent') {
return $this->parseParentMethodCall($expr); return $this->parseParentMethodCall($expr);
} }
_do_call:
$method = $this->parseIdentifier($expr->name);
$this->beforeStmtLines[] = '// Static Call: ' . $class . '::' . $method; $this->beforeStmtLines[] = '// Static Call: ' . $class . '::' . $method;
if ($this->isNameExpr($expr->class) and $this->isIdExpr($expr->name)) { if ($this->isNameExpr($expr->class) and $this->isIdExpr($expr->name)) {

@ -0,0 +1,25 @@
--TEST--
testing static access for methods and properties in anon classes
--FILE--
<?php
function main() {
$anonClass = new class("cats", "dogs") {
public static $foo;
private static $bar;
public function __construct($foo, $bar) {
static::$foo = $foo;
static::$bar = $bar;
}
public static function getBar() {
return static::$bar;
}
};
var_dump($anonClass::$foo);
var_dump($anonClass::getBar());
}
?>
--EXPECT--
string(4) "cats"
string(4) "dogs"
Loading…
Cancel
Save