refactor(php): 重构PHP编译器代码结构

- 将字符串转义相关方法从CompilerBase移至Utils trait中
- 将括号检查和闭合表达式验证逻辑从CompilerBase移至Utils trait
- 修改genCharPtr方法支持字符串转义参数
- 添加genRawStr方法用于生成原始字符串字面量
- 在ClosureGenerator中正确保存和恢复对象状态
- 修复类名定义中的命名空间分隔符问题
- 更新模板文件中属性偏移量生成方式
- 修复内存分配中的类型转换问题
pull/1/head
韩天峰 6 months ago
parent b1662f3cc9
commit 7292635b3d
  1. 2
      bin/gen_stub.php
  2. 104
      src/Php/CompilerBase.php
  3. 2
      src/Php/Entity/ClassLikeDef.php
  4. 10
      src/Php/Generator/ClosureGenerator.php
  5. 102
      src/Php/Generator/Utils.php
  6. 2
      src/template/extension.cc.php

@ -2546,7 +2546,7 @@ abstract class VariableLike
}
$classTypeCount = count($arginfoType->classTypes);
$code .= "\tzend_type_list *{$variableLikeType}_{$variableLikeName}_type_list = malloc(ZEND_TYPE_LIST_SIZE($classTypeCount));\n";
$code .= "\tzend_type_list *{$variableLikeType}_{$variableLikeName}_type_list = (zend_type_list *) malloc(ZEND_TYPE_LIST_SIZE($classTypeCount));\n";
$code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->num_types = $classTypeCount;\n";
foreach ($arginfoType->classTypes as $k => $classType) {

@ -461,38 +461,6 @@ class CompilerBase extends \PhpAot\Core\Translator
}
}
public function isClosedCall($expr, $call): bool
{
if ($call === '') {
if (!str_starts_with($expr, '(')) {
return false;
}
$startPos = 0;
} else {
if (!str_starts_with($expr, $call . '(')) {
return false;
}
$startPos = strlen($call);
}
$bracketCount = 0;
$length = strlen($expr);
for ($i = $startPos; $i < $length; $i++) {
$char = $expr[$i];
if ($char === '(') {
$bracketCount++;
} elseif ($char === ')') {
$bracketCount--;
if ($bracketCount === 0) {
return $i === $length - 1;
}
}
}
return false;
}
public function stop(string $string): never
{
$this->climate->red($string . "\n");
@ -2416,18 +2384,9 @@ class CompilerBase extends \PhpAot\Core\Translator
return $code;
}
protected function trimBrackets(string $str): string
{
if ($this->isClosedCall($str, '')) {
return substr($str, 1, -1);
}
return $str;
}
protected function convertIntExpr(string $expr): string
{
if (!$this->isClosedCall($expr, 'php::toInt')) {
if (!$this->isClosedExpr($expr, 'php::toInt')) {
return 'php::toInt(' . $this->trimBrackets($expr) . ')';
}
@ -2436,7 +2395,7 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function convertFloatExpr(string $expr): string
{
if (!$this->isClosedCall($expr, 'php::toFloat')) {
if (!$this->isClosedExpr($expr, 'php::toFloat')) {
return 'php::toFloat(' . $this->trimBrackets($expr) . ')';
}
@ -2445,7 +2404,7 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function convertStringExpr(string $expr): string
{
if (!$this->isClosedCall($expr, 'php::toString')) {
if (!$this->isClosedExpr($expr, 'php::toString')) {
return 'php::toString(' . $this->trimBrackets($expr) . ')';
}
@ -2454,7 +2413,7 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function convertObjectExpr(string $expr, string $class = ''): string
{
if (!$this->isClosedCall($expr, 'php::toObject')) {
if (!$this->isClosedExpr($expr, 'php::toObject')) {
if ($class === '') {
return 'php::toObject(' . $this->trimBrackets($expr) . ')';
}
@ -2466,7 +2425,7 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function convertArrayExpr(string $expr): string
{
if (!$this->isClosedCall($expr, 'php::toArray')) {
if (!$this->isClosedExpr($expr, 'php::toArray')) {
return 'php::toArray(' . $this->trimBrackets($expr) . ')';
}
@ -2475,7 +2434,7 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function convertBoolExpr(string $expr): string
{
if (!$this->isClosedCall($expr, 'php::toBool')) {
if (!$this->isClosedExpr($expr, 'php::toBool')) {
return 'php::toBool(' . $this->trimBrackets($expr) . ')';
}
@ -2696,57 +2655,6 @@ class CompilerBase extends \PhpAot\Core\Translator
return 'php::concat({' . implode(', ', $list) . '})';
}
protected function escapeString(string $str): string
{
return addcslashes($str, "\\\"\n\r\t\v\f\0\x01..\x1f\x7f..\xff");
}
protected function escapeBool(bool $bool): string
{
return $bool ? 'true' : 'false';
}
protected function escapeVarName(string $name): string
{
if (in_array($name, Constants::CPP_RESERVED_NAMES)) {
return '_php__var__' . $name;
}
if ($name === 'this') {
return 'this_';
}
return $name;
}
protected function escapeNamespace(string $ns): string
{
return str_replace('\\', self::NAMESPACE_SEPARATOR, strtolower($ns));
}
protected function escapeZendFnName(string $fn): string
{
return str_replace('\\', '_', strtolower($fn));
}
protected function escapeName(string $name): string
{
return strtolower($name);
}
protected function escapeClass(string $class): string
{
return str_replace('\\', '_', trim(strtolower($class), '\\'));
}
protected function escapeFileName(string $file): string
{
return str_replace('-', '_', $file);
}
protected function unescapeVarName(string $name): string
{
return str_replace('_php__var__', '', $name);
}
protected function parseInterpolatedStringPart(Node $expr): string
{
return '"' . $this->escapeString($expr->value) . '"';

@ -29,6 +29,6 @@ class ClassLikeDef
return str_replace('\\', '_', $this->namespace . '_' . $this->name);
}
return $this->namespace . '\\\\' . $this->name;
return $this->namespace . '\\' . $this->name;
}
}

@ -32,9 +32,14 @@ trait ClosureGenerator
$this->localVars = [];
}
$oriObjects = $this->objects;
$oriObjectWrappers = $this->objectWrappers;
$oriArgs = $this->arguments;
$this->arguments = [];
$oriInClosure = $this->inClosure;
$this->objects = [];
$this->objectWrappers = [];
$this->arguments = [];
$this->inClosure = true;
$this->indentLevel++;
@ -67,6 +72,9 @@ trait ClosureGenerator
if (!$useCurrentScope) {
$this->localVars = $oriLocalVars;
}
$this->objects = $oriObjects;
$this->objectWrappers = $oriObjectWrappers;
$this->arguments = $oriArgs;
$this->inClosure = $oriInClosure;

@ -9,16 +9,114 @@
namespace PhpAot\Php\Generator;
use PhpAot\Php\CompilerBase;
use PhpAot\Php\Constants;
trait Utils
{
protected function genCharPtr(string $str): string
protected function genCharPtr(string $str, bool $escape = false): string
{
return '"' . $str . '"';
return '"' . ($escape ? $this->escapeString($str) : $str) . '"';
}
protected function genArray(array $elements): string
{
return CompilerBase::TYPE_ARRAY . '{' . implode(', ', $elements) . ' }';
}
protected function genRawStr(string $str): string
{
return 'R"(' . $str . ')"';
}
protected function escapeString(string $str): string
{
return addcslashes($str, "\\\"\n\r\t\v\f\0\x01..\x1f\x7f..\xff");
}
protected function escapeBool(bool $bool): string
{
return $bool ? 'true' : 'false';
}
protected function escapeVarName(string $name): string
{
if (in_array($name, Constants::CPP_RESERVED_NAMES)) {
return '_php__var__' . $name;
}
if ($name === 'this') {
return 'this_';
}
return $name;
}
protected function escapeNamespace(string $ns): string
{
return str_replace('\\', self::NAMESPACE_SEPARATOR, strtolower($ns));
}
protected function escapeZendFnName(string $fn): string
{
return str_replace('\\', '_', strtolower($fn));
}
protected function escapeName(string $name): string
{
return strtolower($name);
}
protected function escapeClass(string $class): string
{
return str_replace('\\', '_', trim(strtolower($class), '\\'));
}
protected function escapeFileName(string $file): string
{
return str_replace('-', '_', $file);
}
protected function unescapeVarName(string $name): string
{
return str_replace('_php__var__', '', $name);
}
protected function isClosedExpr($expr, $call): bool
{
if ($call === '') {
if (!str_starts_with($expr, '(')) {
return false;
}
$startPos = 0;
} else {
if (!str_starts_with($expr, $call . '(')) {
return false;
}
$startPos = strlen($call);
}
$bracketCount = 0;
$length = strlen($expr);
for ($i = $startPos; $i < $length; $i++) {
$char = $expr[$i];
if ($char === '(') {
$bracketCount++;
} elseif ($char === ')') {
$bracketCount--;
if ($bracketCount === 0) {
return $i === $length - 1;
}
}
}
return false;
}
protected function trimBrackets(string $str): string
{
if ($this->isClosedExpr($str, '')) {
return substr($str, 1, -1);
}
return $str;
}
}

@ -135,7 +135,7 @@ foreach ($this->globalVars as $name => $type):
foreach ($this->classes as $classDef):
foreach ($classDef->properties as $propertyDef):
?>
<?=Translator::PREFIX . $this->getPropertyOffset($propertyDef->name, $classDef->name, $classDef->namespace)?> = php::getPropertyOffset("<?=$classDef->getNamespacedName(false)?>", "<?=$propertyDef->name?>");
<?=Translator::PREFIX . $this->getPropertyOffset($propertyDef->name, $classDef->name, $classDef->namespace)?> = php::getPropertyOffset(<?=$this->genCharPtr($classDef->getNamespacedName(false), true)?>, "<?=$propertyDef->name?>");
<?php
endforeach;
endforeach;

Loading…
Cancel
Save