feat(php): 支持类常量数组类型的编译处理

- 在 CompilerBase.php 中添加对类常量数组类型的判断和处理逻辑
- 在 extension.cc.php 模板中增加类数组常量的声明、初始化和清理代码生成
- 修改 Translator.php 中的类常量解析逻辑以支持类型推断
- 添加对未明确声明类型的类常量进行自动类型检测
- 为类数组常量生成对应的外部变量声明
- 移除不再需要的字面字符串数组外部声明
pull/1/head
韩天峰 5 months ago
parent 26682179d4
commit f2647ccbba
  1. 7
      src/Php/CompilerBase.php
  2. 25
      src/Php/Translator.php
  3. 36
      src/template/extension.cc.php
  4. 38
      tests/aot/class-const-001.phpt

@ -3883,7 +3883,12 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($this->hasNativeClass($class)) {
$classDef = $this->getClassDef($class);
if ($classDef->hasConstant($const)) {
return $classDef->getConstant($const)->value;
$constInfo = $classDef->getConstant($const);
if ($constInfo->type === self::TYPE_ARRAY) {
return self::PREFIX . $this->getNativeName($constInfo->name, $classDef->namespace, $classDef->name);
} else {
return $constInfo->value;
}
}
if ($classDef->enum) {
$ce = $this->getClassEntryPtr($class);

@ -216,6 +216,15 @@ class Translator extends Preprocessor
$propCount = count($this->propMap);
$lines[] = 'extern uint32_t ' . self::PREFIX . self::PROP_MAP . '[' . $propCount . '];' . PHP_EOL;
foreach ($this->classes as $classDef) {
foreach ($classDef->constants as $constant) {
if ($constant->type === self::TYPE_ARRAY) {
$constName = self::PREFIX . $this->getNativeName($constant->name, $classDef->namespace, $classDef->name);
$lines[] = 'extern ' . self::TYPE_VAR . ' ' . $constName . ';' . PHP_EOL;
}
}
}
$code = implode(PHP_EOL, $lines) . PHP_EOL . PHP_EOL;
$this->writeFile($file, $code);
}
@ -407,9 +416,6 @@ class Translator extends Preprocessor
{
$code = '#include <phpx.h>' . PHP_EOL;
$literalStringsCount = count($this->literalStrings);
$code .= 'extern ' . self::TYPE_STR . ' ' . self::LITERAL_STRINGS . '[' . $literalStringsCount . '];' . PHP_EOL;
foreach ($this->nativeFunctions as $name => $func) {
$code .= 'extern ' . $func->returnType . ' ' . self::PREFIX . $name . '(';
$list = [];
@ -1038,8 +1044,19 @@ class Translator extends Preprocessor
protected function parseClassConstDef(Node\Stmt\ClassConst $v): void
{
$flags = $v->flags;
$type = $this->parseTypeDecl($v->type, self::DECL_TYPE_OF_CONST);
if ($v->type) {
$type = $this->parseTypeDecl($v->type, self::DECL_TYPE_OF_CONST);
} else {
$type = null;
}
foreach ($v->consts as $const) {
if ($type === null) {
$type = match ($const->value->getType()) {
'Expr_Array' => self::TYPE_ARRAY,
'Scalar_String' => self::TYPE_STR,
default => self::TYPE_VAR,
};
}
$constName = $this->parseIdentifier($const->name);
$constInfo = new ConstantDef($constName, $flags, $type, $this->parseIdentifier($const->value));
$this->classDef->constants[$constInfo->name] = $constInfo;

@ -79,6 +79,18 @@ foreach ($this->nativeConstants as $name => $const):
<?=$const->type?> <?=$name?>;
<?php endforeach; ?>
// class array constants
<?php
foreach ($this->classes as $classDef) :
foreach ($classDef->constants as $constant) :
if ($constant->type === Translator::TYPE_ARRAY) :
$constName = Translator::PREFIX . $this->getNativeName($constant->name, $classDef->namespace, $classDef->name);
echo Translator::TYPE_VAR . " " . $constName . ";\n";
endif;
endforeach;
endforeach;
?>
// clang-format off
static const zend_function_entry ext_functions[] = {
PHP_FE(cli_set_process_title, arginfo_cli_set_process_title)
@ -142,6 +154,18 @@ foreach ($this->staticPropertyList as $prop):
php::setStaticProperty(<?=$this->genCharPtr($prop->class, true)?>, <?=$this->genCharPtr($prop->name)?>, <?=$prop->default?>);
<?php
endforeach;
?>
// class array constants
<?php
foreach ($this->classes as $classDef) :
foreach ($classDef->constants as $constant) :
if ($constant->type === Translator::TYPE_ARRAY) :
$constName = Translator::PREFIX . $this->getNativeName($constant->name, $classDef->namespace, $classDef->name);
echo $constName . " = " . $constant->value . ";\n";
endif;
endforeach;
endforeach;
?>
}
@ -160,6 +184,18 @@ foreach ($this->nativeConstants as $name => $const):
?>
<?= $name ?>.unset();
<?php endforeach; ?>
// class array constants
<?php
foreach ($this->classes as $classDef) :
foreach ($classDef->constants as $constant) :
if ($constant->type === Translator::TYPE_ARRAY) :
$constName = Translator::PREFIX . $this->getNativeName($constant->name, $classDef->namespace, $classDef->name);
echo $constName . ".unset();\n";
endif;
endforeach;
endforeach;
?>
}
PHP_RINIT_FUNCTION(<?=$this->getModuleName()?>) {

@ -0,0 +1,38 @@
--TEST--
class const 001
--FILE--
<?php
class Worker
{
public const FOO = [
'php',
'java',
'c++',
'golang',
];
public const BAR = "string constant";
public const BAZ = 123;
}
function main()
{
var_dump(Worker::FOO);
var_dump(Worker::FOO[2]);
var_dump(WOrker::BAR);
var_dump(Worker::BAZ);
}
?>
--EXPECT--
array(4) {
[0]=>
string(3) "php"
[1]=>
string(4) "java"
[2]=>
string(3) "c++"
[3]=>
string(6) "golang"
}
string(3) "c++"
string(15) "string constant"
int(123)
Loading…
Cancel
Save