refactor(Php): 优化 MagicConst 和 Foreach 语句解析

- 修复 MagicConst 解析函数的类型声明
- 修复 Line 常量解析的返回值类型转换
- 修复 Foreach 语句解析函数的类型声明
- 更新 PhpParser 导入以支持 MagicConst 和 Foreach_ 节点类型
pull/1/head
韩天峰 8 months ago
parent 185c5a75dc
commit a085c33208
  1. 4
      examples/project/main.php
  2. 60
      src/Php/Translator.php

@ -3,5 +3,9 @@ function main()
{ {
fn1(); fn1();
$rs = fn_test(199, 189); $rs = fn_test(199, 189);
$array = [1, 3, 5];
foreach ($array as $r) {
echo $r;
}
var_dump(gettype($rs)); var_dump(gettype($rs));
} }

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace PhpAot\Php; namespace PhpAot\Php;
@ -10,6 +11,8 @@ use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier; use PhpParser\Node\Identifier;
use PhpParser\Error; use PhpParser\Error;
use PhpParser\Node\NullableType; use PhpParser\Node\NullableType;
use PhpParser\Node\Scalar\MagicConst;
use PhpParser\Node\Stmt\Foreach_;
use PhpParser\NodeFinder; use PhpParser\NodeFinder;
use PhpParser\NodeTraverser; use PhpParser\NodeTraverser;
use PhpParser\Parser; use PhpParser\Parser;
@ -20,22 +23,22 @@ use stdClass;
class Translator extends \PhpAot\Core\Translator class Translator extends \PhpAot\Core\Translator
{ {
const string TYPE_VAR = 'php::Var'; public const string TYPE_VAR = 'php::Var';
const string TYPE_BOOL = 'php::Bool'; public const string TYPE_BOOL = 'php::Bool';
const string TYPE_INT = 'php::Int'; public const string TYPE_INT = 'php::Int';
const string TYPE_FLOAT = 'php::Float'; public const string TYPE_FLOAT = 'php::Float';
const string TYPE_OBJECT = 'php::Object'; public const string TYPE_OBJECT = 'php::Object';
const string TYPE_ARRAY = 'php::Array'; public const string TYPE_ARRAY = 'php::Array';
const string TYPE_STR = 'php::Str'; public const string TYPE_STR = 'php::Str';
const string TYPE_REF = 'php::Var'; public const string TYPE_REF = 'php::Var';
const string VALUE_NAN = 'std::numeric_limits<double>::quiet_NaN()'; public const string VALUE_NAN = 'std::numeric_limits<double>::quiet_NaN()';
const string VALUE_INF = 'std::numeric_limits<double>::infinity()'; public const string VALUE_INF = 'std::numeric_limits<double>::infinity()';
const string LITERAL_STRINGS = '_literal_strings'; public const string LITERAL_STRINGS = '_literal_strings';
const string EXPR_VARIABLE = 'Expr_Variable'; public const string EXPR_VARIABLE = 'Expr_Variable';
const string EXPR_NEW = 'Expr_New'; public const string EXPR_NEW = 'Expr_New';
const string EXPR_ARRAY_DIM_FETCH = 'Expr_ArrayDimFetch'; public const string EXPR_ARRAY_DIM_FETCH = 'Expr_ArrayDimFetch';
const string NAMESPACE_SEPARATOR = '__'; public const string NAMESPACE_SEPARATOR = '__';
private string $phpxDir = '~/workspace/projects/phpx'; private string $phpxDir = '~/workspace/projects/phpx';
protected string $lang = 'PHP'; protected string $lang = 'PHP';
@ -137,7 +140,7 @@ class Translator extends \PhpAot\Core\Translator
private array $objectWrappers = []; private array $objectWrappers = [];
private bool $strictTypes = false; private bool $strictTypes = false;
const string PREFIX = 'php_'; public const string PREFIX = 'php_';
private string $rootPath; private string $rootPath;
private string $buildDir; private string $buildDir;
private int $debugLine = 0; private int $debugLine = 0;
@ -155,7 +158,7 @@ class Translator extends \PhpAot\Core\Translator
$this->parser = (new ParserFactory())->createForNewestSupportedVersion(); $this->parser = (new ParserFactory())->createForNewestSupportedVersion();
// $this->prettyPrinter = new PrettyPrinter\Standard; // $this->prettyPrinter = new PrettyPrinter\Standard;
$this->setBuildDir($rootPath . '/build'); $this->setBuildDir($rootPath . '/build');
$climate = new CLImate; $climate = new CLImate();
$this->climate = $climate; $this->climate = $climate;
$climate->arguments->add([ $climate->arguments->add([
'optimize' => [ 'optimize' => [
@ -203,7 +206,7 @@ class Translator extends \PhpAot\Core\Translator
$this->internalFunctions = array_flip(get_defined_functions()['internal']); $this->internalFunctions = array_flip(get_defined_functions()['internal']);
} }
function showUsage(): void public function showUsage(): void
{ {
$climate = $this->climate; $climate = $this->climate;
$climate->bold()->green('PHP AOT Compiler v1.0.0'); $climate->bold()->green('PHP AOT Compiler v1.0.0');
@ -234,7 +237,7 @@ class Translator extends \PhpAot\Core\Translator
$climate->br(); $climate->br();
} }
function preprocessArgvAdvanced(): void public function preprocessArgvAdvanced(): void
{ {
global $argv; global $argv;
$processed = [$argv[0]]; $processed = [$argv[0]];
@ -289,7 +292,7 @@ class Translator extends \PhpAot\Core\Translator
$this->climate->info('convert: ' . $this->file); $this->climate->info('convert: ' . $this->file);
$ast = $this->parser->parse($phpCode); $ast = $this->parser->parse($phpCode);
$traverser = new NodeTraverser; $traverser = new NodeTraverser();
$traverser->addVisitor(new Visitor()); $traverser->addVisitor(new Visitor());
$stmts = $traverser->traverse($ast); $stmts = $traverser->traverse($ast);
@ -451,7 +454,7 @@ class Translator extends \PhpAot\Core\Translator
if (isset($this->redoAfterDeclare[$name])) { if (isset($this->redoAfterDeclare[$name])) {
unset($this->redoAfterDeclare[$name]); unset($this->redoAfterDeclare[$name]);
$this->climate->cyan('Received redo request, retrying...'); $this->climate->cyan('Received redo request, retrying...');
throw new RedoException; throw new RedoException();
} }
} }
@ -510,6 +513,7 @@ class Translator extends \PhpAot\Core\Translator
$index = $this->literalStrings[$expr->value] ?? $this->addLiteralString($expr->value); $index = $this->literalStrings[$expr->value] ?? $this->addLiteralString($expr->value);
return self::LITERAL_STRINGS . '[' . $index . ']'; return self::LITERAL_STRINGS . '[' . $index . ']';
} }
// no break
default: default:
abort($expr); abort($expr);
} }
@ -1022,7 +1026,7 @@ class Translator extends \PhpAot\Core\Translator
$this->functionDef->returnType = $type; $this->functionDef->returnType = $type;
// 返回值变更,需要重新解析 // 返回值变更,需要重新解析
$this->climate->cyan('Return type changed, retrying...'); $this->climate->cyan('Return type changed, retrying...');
throw new RedoException; throw new RedoException();
} }
private function detectVarType($var): string private function detectVarType($var): string
@ -1692,7 +1696,7 @@ class Translator extends \PhpAot\Core\Translator
return $code; return $code;
} }
function isClosedCall($expr, $call): bool public function isClosedCall($expr, $call): bool
{ {
if ($call === '') { if ($call === '') {
if (!str_starts_with($expr, '(')) { if (!str_starts_with($expr, '(')) {
@ -2118,7 +2122,7 @@ class Translator extends \PhpAot\Core\Translator
return $var . ' ^= ' . $this->parseIdentifier($node->expr); return $var . ' ^= ' . $this->parseIdentifier($node->expr);
} }
private function parseMagicConst(mixed $expr): string private function parseMagicConst(MagicConst $expr): string
{ {
switch ($expr->getType()) { switch ($expr->getType()) {
case 'Scalar_MagicConst_Dir': case 'Scalar_MagicConst_Dir':
@ -2126,7 +2130,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Scalar_MagicConst_File': case 'Scalar_MagicConst_File':
return '"' . $this->escapeString($this->file) . '"'; return '"' . $this->escapeString($this->file) . '"';
case 'Scalar_MagicConst_Line': case 'Scalar_MagicConst_Line':
return $expr->getStartLine(); return (string)$expr->getStartLine();
case 'Scalar_MagicConst_Function': case 'Scalar_MagicConst_Function':
return '"' . $this->escapeString($this->functionDef->name) . '"'; return '"' . $this->escapeString($this->functionDef->name) . '"';
default: default:
@ -2134,7 +2138,7 @@ class Translator extends \PhpAot\Core\Translator
} }
} }
private function parseForeach(Node $node): string private function parseForeach(Foreach_ $node): string
{ {
if ($node->byRef) { if ($node->byRef) {
$this->fatalError($node, 'Cannot use & with foreach'); $this->fatalError($node, 'Cannot use & with foreach');
@ -2740,7 +2744,7 @@ class Translator extends \PhpAot\Core\Translator
$this->climate->info('prepare: ' . $this->file); $this->climate->info('prepare: ' . $this->file);
$ast = $this->parser->parse($phpCode); $ast = $this->parser->parse($phpCode);
$traverser = new NodeTraverser; $traverser = new NodeTraverser();
$traverser->addVisitor(new Visitor()); $traverser->addVisitor(new Visitor());
$stmts = $traverser->traverse($ast); $stmts = $traverser->traverse($ast);

Loading…
Cancel
Save