feat(php): 添加PHP编译器基础功能和八皇后问题示例

- 在CompilerBase中初始化result变量以避免未定义变量错误
- 优化Stmt_Nop节点处理逻辑,移除不必要的赋值操作
- 添加对空结果和空后续语句行的条件判断,避免向输出添加空内容
- 实现parseAssignPropertyArrayDim方法用于处理对象属性数组维度赋值操作
- 在parseAssign方法中添加属性获取检查,支持属性赋值操作解析
- 添加dump调试方法用于在指定行号时输出节点信息
- 新增EightQueue.php示例文件,实现优化版八皇后问题求解算法
- 修改Preprocessor以支持Trait语句的预处理
- 更新Translator以支持Trait语句的转换处理
- 扩展类相关方法签名以接受Trait节点类型参数
pull/1/head
韩天峰 7 months ago
parent 3dc79d2074
commit 1b78fc7fd9
  1. 123
      examples/EightQueue.php
  2. 38
      src/Php/CompilerBase.php
  3. 4
      src/Php/Preprocessor.php
  4. 5
      src/Php/Translator.php

@ -0,0 +1,123 @@
<?php
class EightQueensOptimized
{
private $solutions = [];
private $n = 8;
private $cols = []; // 记录每行皇后的列位置
public function __construct($n = 8)
{
$this->n = $n;
$this->cols = array_fill(0, $n, -1);
}
/**
* 检查在 (row, col) 位置放置皇后是否安全
*/
private function isSafe($row, $col)
{
for ($i = 0; $i < $row; $i++) {
// 检查列冲突和对角线冲突
if ($this->cols[$i] == $col ||
abs($this->cols[$i] - $col) == abs($i - $row)) {
return false;
}
}
return true;
}
/**
* 回溯求解
*/
private function solve($row)
{
if ($row == $this->n) {
$this->solutions[] = array_slice($this->cols, 0);
return;
}
for ($col = 0; $col < $this->n; $col++) {
if ($this->isSafe($row, $col)) {
$this->cols[$row] = $col;
$this->solve($row + 1);
$this->cols[$row] = -1;
}
}
}
/**
* 获取所有解决方案
*/
public function getSolutions()
{
$this->solutions = [];
$this->solve(0);
return $this->solutions;
}
/**
* 打印解决方案
*/
public function printSolution($solution)
{
echo str_repeat('-', $this->n * 4 + 1) . "\n";
for ($row = 0; $row < $this->n; $row++) {
echo '| ';
for ($col = 0; $col < $this->n; $col++) {
echo ($solution[$row] == $col ? 'Q' : '.') . ' | ';
}
echo "\n" . str_repeat('-', $this->n * 4 + 1) . "\n";
}
}
/**
* 打印所有解决方案
*/
public function printAllSolutions()
{
$solutions = $this->getSolutions();
echo "找到 " . count($solutions) . " 个解决方案\n\n";
foreach ($solutions as $index => $solution) {
echo "解决方案 #" . ($index + 1) . ": [" .
implode(', ', $solution) . "]\n";
$this->printSolution($solution);
echo "\n";
}
}
/**
* 只统计解的数量(不保存所有解)
*/
public function countSolutions()
{
return count($this->getSolutions());
}
}
function main()
{
// 使用示例
echo "=== 8 皇后问题 ===\n\n";
$queens = new EightQueensOptimized(8);
// 只显示前3个解决方案
$solutions = $queens->getSolutions();
echo "总共找到 " . count($solutions) . " 个解决方案\n\n";
for ($i = 0; $i < min(3, count($solutions)); $i++) {
echo "解决方案 #" . ($i + 1) . ":\n";
$queens->printSolution($solutions[$i]);
echo "\n";
}
// 测试不同规模
echo "\n=== 不同规模的皇后问题 ===\n";
for ($n = 4; $n <= 10; $n++) {
$q = new EightQueensOptimized($n);
$count = $q->countSolutions();
echo "{$n} 皇后问题有 {$count} 个解\n";
}
}

@ -429,6 +429,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$class = $v->getType();
$this->beforeStmtLines = [];
$this->afterStmtLines = [];
$result = '';
$this->writeLog('Line ' . $this->getLine($v) . ': ' . $class);
$lines[] = $this->getComment($v, $class);
@ -483,7 +484,6 @@ class CompilerBase extends \PhpAot\Core\Translator
$result = $this->parseContinue($v);
break;
case 'Stmt_Nop':
$result = '';
break;
case 'Stmt_Global':
$result = $this->parseGlobal($v);
@ -505,9 +505,13 @@ class CompilerBase extends \PhpAot\Core\Translator
}
$lines = array_merge($lines, $this->beforeStmtLines);
$this->beforeStmtLines = [];
$lines[] = $result;
$lines = array_merge($lines, $this->afterStmtLines);
$this->afterStmtLines = [];
if ($result) {
$lines[] = $result;
}
if ($this->afterStmtLines) {
$lines = array_merge($lines, $this->afterStmtLines);
$this->afterStmtLines = [];
}
}
$code = '';
@ -694,6 +698,20 @@ class CompilerBase extends \PhpAot\Core\Translator
}
}
private function parseAssignPropertyArrayDim(Node $left, Node $right): string
{
$obj = $this->parseIdentifier($left->var->var);
$propName = $this->identifierToStr($left->var->name);
$code = '';
$value = $this->trimBrackets($this->parseExpr($right));
if ($left->dim === null) {
return $code . "$obj.appendArrayProperty($propName, $value)";
} else {
$dim = $this->trimBrackets($this->parseIdentifier($left->dim));
return $code . "$obj.updateArrayProperty($propName, $dim, $value)";
}
}
protected function parseAssign(Node $v): string
{
$left = $v->var;
@ -707,6 +725,11 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->addLocalVar($array, self::TYPE_ARRAY);
}
// 这是属性赋值操作
if ($this->isPropertyFetch($left->var)) {
return $this->parseAssignPropertyArrayDim($left, $right);
}
$value = $this->trimBrackets($this->parseExpr($right));
if ($left->dim === null) {
return $code . "$array.offsetSet(php::null, $value)";
@ -1291,6 +1314,13 @@ class CompilerBase extends \PhpAot\Core\Translator
exit(255);
}
protected function dump(NodeAbstract $v): void
{
if ($this->debugLine == $v->getStartLine()) {
var_dump($v);
}
}
protected function parseArrayDimFetch($node): string
{
$var = $this->parseIdentifier($node->var);

@ -103,6 +103,7 @@ class Preprocessor extends CompilerBase
$this->prepareNamespaceDef($v);
break;
case 'Stmt_Class':
case 'Stmt_Trait':
$this->prepareClass($v);
break;
case 'Stmt_Function':
@ -146,7 +147,7 @@ class Preprocessor extends CompilerBase
}
protected function prepareClass(Node\Stmt\Class_ $class): string
protected function prepareClass(Node\Stmt\Class_|Node\Stmt\Trait_ $class): string
{
$this->class = $this->parseIdentifier($class->name);
$code = '';
@ -156,6 +157,7 @@ class Preprocessor extends CompilerBase
case 'Stmt_ClassConst':
case 'Stmt_Property':
case 'Stmt_Nop':
case 'Stmt_TraitUse':
break;
case 'Stmt_ClassMethod':
$code .= $this->prepareFunction($v) . PHP_EOL;

@ -218,6 +218,7 @@ class Translator extends Preprocessor
$cppCode .= $this->parseNamespace($v);
break;
case 'Stmt_Class':
case 'Stmt_Trait':
$cppCode .= $this->parseClass($v);
break;
case 'Stmt_Use':
@ -494,7 +495,7 @@ class Translator extends Preprocessor
return $code;
}
protected function genClassStubFile(Node\Stmt\Class_ $class, string $file): void
protected function genClassStubFile(Node\Stmt\Class_|Node\Stmt\Trait_ $class, string $file): void
{
$genStubCmd = PHP_BINARY. ' ' . $this->rootPath . '/bin/gen_stub.php --gen-class-info -f ' . $file;
$output = shell_exec($genStubCmd);
@ -509,7 +510,7 @@ class Translator extends Preprocessor
$this->stubFileIncluded = true;
}
protected function parseClass(Node\Stmt\Class_ $class): string
protected function parseClass(Node\Stmt\Class_|Node\Stmt\Trait_ $class): string
{
$this->class = $this->parseIdentifier($class->name);
if (!$this->stubFileIncluded) {

Loading…
Cancel
Save