From ec836bcb31c36ae01c3599e5661e96d9a8183bcf Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 6 Jan 2026 12:08:53 +0800 Subject: [PATCH] =?UTF-8?q?nbody-php-3=20=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/compiler.php | 4 ++ examples/nbody.php-3.php | 122 +++++++++++++++++++++++++++++++++++++++ src/Php/Translator.php | 63 ++++++++++++++++---- 3 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 examples/nbody.php-3.php diff --git a/bin/compiler.php b/bin/compiler.php index 01c495fb..f33ca40f 100755 --- a/bin/compiler.php +++ b/bin/compiler.php @@ -44,6 +44,10 @@ foreach ($list as $file) { } } +if (empty($sourceFiles)) { + $translator->stop("No valid source file found"); +} + // 生成所有函数声明 $translator->genFunctionDeclaration("./php_func_decl.h"); diff --git a/examples/nbody.php-3.php b/examples/nbody.php-3.php new file mode 100644 index 00000000..a497382e --- /dev/null +++ b/examples/nbody.php-3.php @@ -0,0 +1,122 @@ + 2 ? $argv[2] : 100; + + printf("%0.9f\n", energy($bodies)); + + $i = 0; + do { + foreach ($pairs as $k => $p) { + $a = $p[0]; + $b = $p[1]; + + $dx = $a[0] - $b[0]; + $dy = $a[1] - $b[1]; + $dz = $a[2] - $b[2]; + + $dist = sqrt($dx * $dx + $dy * $dy + $dz * $dz); + $mag = 0.01 / ($dist * $dist * $dist); + $mag_a = $a[6] * $mag; + $mag_b = $b[6] * $mag; + + $a[3] -= $dx * $mag_b; + $a[4] -= $dy * $mag_b; + $a[5] -= $dz * $mag_b; + $b[3] += $dx * $mag_a; + $b[4] += $dy * $mag_a; + $b[5] += $dz * $mag_a; + + $pairs[$k][0] = $a; + $pairs[$k][1] = $b; + } + + foreach ($bodies as $k => $b) { + $b[0] += 0.01 * $b[3]; + $b[1] += 0.01 * $b[4]; + $b[2] += 0.01 * $b[5]; + $bodies[$k] = $b; + } + + } while (++$i < $n); + + printf("%0.9f\n", energy($bodies)); + printf("count=%d, %0.9f\n", $n, microtime(true) - $begin); +} diff --git a/src/Php/Translator.php b/src/Php/Translator.php index f6712aa5..1fc4d348 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -1299,7 +1299,7 @@ class Translator extends \PhpAot\Core\Translator } else { $fn = '"' . $name . '"'; } - if ($name === 'strlen') { + if ($name === 'strlen' or $name === 'sizeof' or $name === 'count') { return 'php::len(' . $this->parseIdentifier($expr->args[0]->value) . ')'; } if (count($expr->args) == 1) { @@ -1506,9 +1506,40 @@ class Translator extends \PhpAot\Core\Translator return $code; } + 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; + } + private function trimBrackets(string $str): string { - if (str_starts_with($str, '(') and str_ends_with($str, ')')) { + if ($this->isClosedCall($str, '')) { return substr($str, 1, -1); } return $str; @@ -1516,7 +1547,7 @@ class Translator extends \PhpAot\Core\Translator private function convertIntExpr(string $expr): string { - if (!str_starts_with($expr, 'php::to_int(')) { + if (!$this->isClosedCall($expr, 'php::to_int')) { return 'php::to_int(' . $this->trimBrackets($expr) . ')'; } return $expr; @@ -1524,15 +1555,21 @@ class Translator extends \PhpAot\Core\Translator private function convertFloatExpr(string $expr): string { - if (!str_starts_with($expr, 'php::to_float(')) { + if (!$this->isClosedCall($expr, 'php::to_float')) { return 'php::to_float(' . $this->trimBrackets($expr) . ')'; } return $expr; } + public function stop(string $string): void + { + $this->climate->red($string . "\n"); + exit(1); + } + private function convertStringExpr(string $expr): string { - if (!str_starts_with($expr, 'php::to_string(')) { + if (!$this->isClosedCall($expr, 'php::to_string')) { return 'php::to_string(' . $this->trimBrackets($expr) . ')'; } return $expr; @@ -1540,7 +1577,7 @@ class Translator extends \PhpAot\Core\Translator private function convertArrayExpr(string $expr): string { - if (!str_starts_with($expr, 'php::to_array(')) { + if (!$this->isClosedCall($expr, 'php::to_array')) { return 'php::to_array(' . $this->trimBrackets($expr) . ')'; } return $expr; @@ -1548,7 +1585,7 @@ class Translator extends \PhpAot\Core\Translator private function convertBoolExpr(string $expr): string { - if (!str_starts_with($expr, 'php::to_bool(')) { + if (!$this->isClosedCall($expr, 'php::to_bool')) { return 'php::to_bool(' . $this->trimBrackets($expr) . ')'; } return $expr; @@ -1837,6 +1874,9 @@ class Translator extends \PhpAot\Core\Translator private function parseForeach(Node $node): string { + if ($node->byRef) { + $this->fatalError($node, 'Cannot use & with foreach'); + } if ($node->keyVar) { $keyVar = $this->parseIdentifier($node->keyVar); } @@ -2169,10 +2209,13 @@ class Translator extends \PhpAot\Core\Translator private function parseAssignRef(mixed $expr) { - if ($expr->var->getType() === self::EXPR_VARIABLE && $expr->expr->getType() === self::EXPR_VARIABLE) { - return $this->parseIdentifier($expr->var) . ' = &' . $this->parseIdentifier($expr->expr); + if ($expr->var->getType() === self::EXPR_VARIABLE) { + if ($expr->expr->getType() === self::EXPR_VARIABLE) { + return $this->parseIdentifier($expr->var) . ' = &' . $this->parseIdentifier($expr->expr); + } elseif ($expr->expr->getType() === self::EXPR_ARRAY_DIM_FETCH) { + return $this->parseIdentifier($expr->var) . ' = ' . $this->parseIdentifier($expr->expr); + } } - abort($expr); } private function parseMethodCall(mixed $expr): string