fix(php): 修复编译器基类中的回溯打印和类型返回验证问题

- 将 printBacktraceOnError 默认值从 false 修改为 true
- 扩展子类作为父类返回时的类型检查,支持抽象类或接口
- 更新 SimpleType::fromNode 和 fromString 方法以支持 ArrayType 返回类型
- 修改测试用例中 ZipArchive 的路径处理逻辑
- 更新测试输出预期结果以匹配新的行为
pull/1/head
韩天峰 4 months ago
parent cc785eb7f7
commit c79573a9fe
  1. 22
      examples/const_expr.php
  2. 19
      src/Php/CompilerBase.php
  3. 13
      src/Php/Reflection.php
  4. 6
      src/gen_stub.php

@ -0,0 +1,22 @@
<?php
/**
* Tetris Game - Pure PHP Logic + Win32 C++ Drawing Primitives
*
* This project demonstrates the AOT compiler's capability:
* - C++ only wraps Win32 APIs (window, message, GDI drawing)
* - ALL game logic is implemented in PHP
*/
// ============================================================
// Constants
// ============================================================
const BLOCK_SIZE = 30;
const BOARD_HEIGHT = 20;
const WINDOW_HEIGHT = BLOCK_SIZE * BOARD_HEIGHT + 40;
function main(): void
{
var_dump(BLOCK_SIZE, BOARD_HEIGHT, WINDOW_HEIGHT);
}

@ -87,6 +87,7 @@ class CompilerBase extends \PhpAot\Core\Translator
public const string VALUE_TRUE = 'php::true_'; public const string VALUE_TRUE = 'php::true_';
public const string LITERAL_STRINGS = '_literal_strings'; public const string LITERAL_STRINGS = '_literal_strings';
public const string ANON_CLASS = '_anon_class_'; public const string ANON_CLASS = '_anon_class_';
public const string DYNAMIC_CALLED_CLASS = '__dynamic_called_class__';
public const string STATIC_VAR = '_static_var_'; public const string STATIC_VAR = '_static_var_';
public const string GLOBAL_VAR = '_global_var_'; public const string GLOBAL_VAR = '_global_var_';
public const string OBJECT_PROP = '_object_prop_'; public const string OBJECT_PROP = '_object_prop_';
@ -3017,6 +3018,20 @@ class CompilerBase extends \PhpAot\Core\Translator
return Symbol::argList() . '{' . implode(', ', $listArgs) . '}, ' . $tmpVar . '.array()'; return Symbol::argList() . '{' . implode(', ', $listArgs) . '}, ' . $tmpVar . '.array()';
} }
protected function isReferenceArgument($funcName, $className, $argIndex): bool
{
if ($className) {
// 动态调用类方法,无法判断参数是否为引用
if ($className === self::DYNAMIC_CALLED_CLASS) {
return false;
}
$param = Reflection::getClassMethodParameter($className, $funcName, $argIndex);
} else {
$param = Reflection::getFunctionParameter($funcName, $argIndex);
}
return $param && $param->isPassedByReference();
}
protected function parseCallArgs(array $args, string $funcName = '', string $className = ''): string protected function parseCallArgs(array $args, string $funcName = '', string $className = ''): string
{ {
$list_args = []; $list_args = [];
@ -3028,7 +3043,7 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($arg->name !== null) { if ($arg->name !== null) {
return $this->parseNamedCallArgs($args, $i, $list_args); return $this->parseNamedCallArgs($args, $i, $list_args);
} }
$byRef = $funcName && Reflection::isReferenceArg($funcName, $className, $i); $byRef = $funcName && $this->isReferenceArgument($funcName, $className, $i);
if ($this->isVarExpr($arg->value)) { if ($this->isVarExpr($arg->value)) {
$name = $this->parseIdentifier($arg->value); $name = $this->parseIdentifier($arg->value);
if ($byRef) { if ($byRef) {
@ -4596,7 +4611,7 @@ class CompilerBase extends \PhpAot\Core\Translator
} }
try { try {
// 类名为空,这是一个 var ,类型是 any ,编译期无法获得它的类型,需要动态调用 // 类名为空,这是一个 var ,类型是 any ,编译期无法获得它的类型,需要动态调用
$class = empty($class) ? '__DYNAMIC-CALLED-CLASS__' : $class; $class = empty($class) ? self::DYNAMIC_CALLED_CLASS : $class;
return $object . '.call(' . $methodPtr . ', ' . $this->parseCallArgs($expr->args, $funcName, $class) . ')'; return $object . '.call(' . $methodPtr . ', ' . $this->parseCallArgs($expr->args, $funcName, $class) . ')';
} catch (PlaceHolder) { } catch (PlaceHolder) {
return $this->genPlaceHolder($this->genArray([$object, $method])); return $this->genPlaceHolder($this->genArray([$object, $method]));

@ -153,19 +153,6 @@ class Reflection
return $args[$index]; return $args[$index];
} }
public static function isReferenceArg(string $fnName, string $className, int $index): ?string
{
if ($className) {
$param = self::getClassMethodParameter($className, $fnName, $index);
} else {
$param = self::getFunctionParameter($fnName, $index);
}
if (!$param) {
return null;
}
return $param->isPassedByReference() ? $param->getName() : null;
}
public static function hasMethod(string $extends, string $method): bool public static function hasMethod(string $extends, string $method): bool
{ {
$class = self::getClass($extends); $class = self::getClass($extends);

@ -2324,13 +2324,14 @@ class EvaluatedValue
} }
} }
foreach ($allConstInfos as $const) { foreach ($allConstInfos as $name => $const) {
if ($constName != $const->cValue) { if ($constName != $name) {
continue; continue;
} }
$constType = ($const->phpDocType ?? $const->type)->tryToSimpleType(); $constType = ($const->phpDocType ?? $const->type)->tryToSimpleType();
if ($constType) { if ($constType) {
// 这里返回的并不是真正的值,而是一个类型的占位符,最终的运算由编译器完成,此处仅用于 ArgInfo 处理
if ($constType->isBool()) { if ($constType->isBool()) {
return true; return true;
} elseif ($constType->isInt()) { } elseif ($constType->isInt()) {
@ -2338,7 +2339,6 @@ class EvaluatedValue
} elseif ($constType->isFloat()) { } elseif ($constType->isFloat()) {
return M_PI; return M_PI;
} elseif ($constType->isString()) { } elseif ($constType->isString()) {
var_dump($const);
return $const->name; return $const->name;
} elseif ($constType->isArray()) { } elseif ($constType->isArray()) {
return []; return [];

Loading…
Cancel
Save