From f3565a64397e57c5c5a67864aac060e763efb294 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Mon, 29 Dec 2025 20:08:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=9E=E5=BD=92=E8=B5=8B=E5=80=BC=E7=9A=84?= =?UTF-8?q?=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run-tests.php | 2 - src/Php/Translator.php | 66 +++++++--- tests/core/lang/020.phpt | 76 ++++++++++++ tests/core/lang/021.phpt | 44 +++++++ tests/core/lang/022.phpt | 65 ++++++++++ tests/core/lang/023.phpt | 251 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 486 insertions(+), 18 deletions(-) create mode 100644 tests/core/lang/020.phpt create mode 100644 tests/core/lang/021.phpt create mode 100644 tests/core/lang/022.phpt create mode 100644 tests/core/lang/023.phpt diff --git a/run-tests.php b/run-tests.php index 9c9c1bc3..2d714ac6 100755 --- a/run-tests.php +++ b/run-tests.php @@ -1169,8 +1169,6 @@ function system_with_timeout( $descriptorspec[2] = ['pipe', 'w']; } - var_dump($commandline); - $proc = proc_open($commandline, $descriptorspec, $pipes, TEST_PHP_SRCDIR, $bin_env, ['suppress_errors' => true]); if (!$proc) { diff --git a/src/Php/Translator.php b/src/Php/Translator.php index d4ed5d23..a62676a4 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -24,6 +24,11 @@ class Translator extends \PhpAot\Core\Translator private string $phpxDir = '~/workspace/projects/phpx'; protected string $lang = 'PHP'; private array $scope = []; + /** + * 插入到语句之前 + * @var array + */ + private array $beforeStmtLines = []; private int $tmpVarIndex = 0; // 需要插入到函数头部的变量定义代码 private array $definitions = []; @@ -51,6 +56,8 @@ class Translator extends \PhpAot\Core\Translator const string PREFIX = 'php_'; private string $rootPath; private int $debugLine = 0; + // 回归赋值 + private bool $regressionDetection = false; public function __construct(string $rootPath) @@ -230,6 +237,13 @@ class Translator extends \PhpAot\Core\Translator return '"' . $this->escapeString($expr->value) . '"'; case 'Expr_ConstFetch': return $this->parseConstFetch($expr); + case 'Expr_Assign': + if ($this->regressionDetection) { + $var = $this->parseIdentifier($expr->var); + $this->beforeStmtLines[] = $this->parseExpr($expr) . ";\n"; + return '(' . $var . ')'; + } + return $this->parseExpr($expr); default: return $this->parseExpr($expr); } @@ -262,56 +276,61 @@ class Translator extends \PhpAot\Core\Translator $lines = []; foreach ($stmts as $v) { $class = $v->getType(); + $this->beforeStmtLines = []; $this->writeLog('Line ' . $this->getLine($v) . ': ' . $class); switch ($class) { case 'Stmt_Expression': - $lines[] = $this->parseExpr($v->expr) . ';'; + $result = $this->parseExpr($v->expr) . ';'; break; case 'Stmt_Echo': - $this->parseEcho($v, $lines); + $result = $this->parseEcho($v); break; case 'Stmt_Return': - $lines[] = $this->parseReturn($v) . ';'; + $result = $this->parseReturn($v) . ';'; break; case 'Stmt_For': - $lines[] = $this->parseFor($v); + $result = $this->parseFor($v); break; case 'Stmt_Foreach': - $lines[] = $this->parseForeach($v); + $result = $this->parseForeach($v); break; case 'Stmt_Switch': - $lines[] = $this->parseSwitch($v); + $result = $this->parseSwitch($v); break; case 'Stmt_While': - $lines[] = $this->parseWhile($v); + $result = $this->parseWhile($v); break; case 'Stmt_Do': - $lines[] = $this->parseDo($v); + $result = $this->parseDo($v); break; case 'Stmt_If': - $lines[] = $this->parseIf($v); + $result = $this->parseIf($v); break; case 'Stmt_Break': - $lines[] = 'break;'; + $result = $this->parseBreak($v); break; case 'Stmt_Continue': - $lines[] = 'continue;'; + $result = 'continue;'; break; case 'Stmt_Global': - $lines[] = $this->parseGlobal($v); + $result = $this->parseGlobal($v); break; case 'Stmt_Static': - $lines[] = $this->parseStatic($v); + $result = $this->parseStatic($v); break; case 'Stmt_Unset': - $lines[] = $this->parseUnset($v); + $result = $this->parseUnset($v); break; default: abort($v); } + if ($this->beforeStmtLines) { + $lines = array_merge($lines, $this->beforeStmtLines); + } + $lines[] = $result; } - $code = ''; + $code = ''; foreach ($lines as $line) { $code .= $this->getIndent() . $line . PHP_EOL; } @@ -509,11 +528,12 @@ class Translator extends \PhpAot\Core\Translator } } - private function parseEcho(mixed $v, &$lines): void + private function parseEcho(mixed $v): string { foreach ($v->exprs as $expr) { $lines[] = 'php::echo(' . $this->parseExpr($expr) . ');'; } + return implode("\n" . $this->getIndent(), $lines); } private function parseBinaryOp($left, $right, $op): string @@ -733,8 +753,10 @@ class Translator extends \PhpAot\Core\Translator private function parseBinaryOpConcat(mixed $expr): string { + $this->regressionDetection = true; $left = $this->parseIdentifier($expr->left); $right = $this->parseIdentifier($expr->right); + $this->regressionDetection = false; return 'php::concat(' . $left . ', ' . $right . ')'; } @@ -1407,4 +1429,16 @@ class Translator extends \PhpAot\Core\Translator { return '"' . $this->escapeString($this->dir) . '"'; } + + private function parseBreak(mixed $v): string + { + $num = $v->num; + if ($num) { + $value = $this->parseIdentifier($num); + if ($value > 1) { + abort($v); + } + } + return 'break;'; + } } diff --git a/tests/core/lang/020.phpt b/tests/core/lang/020.phpt new file mode 100644 index 00000000..97c928d2 --- /dev/null +++ b/tests/core/lang/020.phpt @@ -0,0 +1,76 @@ +--TEST-- +Switch test 1 +--FILE-- + +--EXPECT-- +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 +In branch 1 +Inner default... +blah=100 diff --git a/tests/core/lang/021.phpt b/tests/core/lang/021.phpt new file mode 100644 index 00000000..517f3215 --- /dev/null +++ b/tests/core/lang/021.phpt @@ -0,0 +1,44 @@ +--TEST-- +Switch test 2 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +i=0 +In branch 0 +i=1 +In branch 1 +i=2 +In branch 2 +i=3 +In branch 3 +hi diff --git a/tests/core/lang/022.phpt b/tests/core/lang/022.phpt new file mode 100644 index 00000000..6b2c5ee0 --- /dev/null +++ b/tests/core/lang/022.phpt @@ -0,0 +1,65 @@ +--TEST-- +Switch test 3 +--FILE-- + +--EXPECT-- +zero +one +2 +3 +4 +5 +6 +7 +8 +9 +zero +one +2 +3 +4 +5 +6 +7 +8 +9 +zero +one +2 +3 +4 +5 +6 +7 +8 +9 diff --git a/tests/core/lang/023.phpt b/tests/core/lang/023.phpt new file mode 100644 index 00000000..bfb427bb --- /dev/null +++ b/tests/core/lang/023.phpt @@ -0,0 +1,251 @@ +--TEST-- +Regression test +--INI-- +date.timezone=UTC +--FILE-- +0) { + $days = $time_left/(24*3600); + $time_left -= $days*24*3600; + $hours = $time_left/3600; + $time_left -= $hours*3600; + $minutes = $time_left/60; + echo "Limor Ullmann is getting married on ".($wedding_date=date("l, F dS, Y",$wedding_timestamp)).",\nwhich is $days days, $hours hours and $minutes minutes from now.\n"; + echo "Her hashed wedding date is $wedding_date.\n"; +} else { + echo "Limor Ullmann is now Limor Baruch :I\n"; +} +?> +--EXPECT-- + + + +*** Testing assignments and variable aliasing: ***
+This should read "blah": blah
+This should read "this is nifty": this is nifty
+*************************************************
+ +*** Testing integer operators ***
+Correct result - 8: 8
+Correct result - 8: 8
+Correct result - 2: 2
+Correct result - -2: -2
+Correct result - 15: 15
+Correct result - 15: 15
+Correct result - 2: 2
+Correct result - 3: 3
+*********************************
+ +*** Testing real operators ***
+Correct result - 8: 8
+Correct result - 8: 8
+Correct result - 2: 2
+Correct result - -2: -2
+Correct result - 15: 15
+Correct result - 15: 15
+Correct result - 2: 2
+Correct result - 3: 3
+*********************************
+ +*** Testing if/elseif/else control ***
+ +This works
+this_still_works
+should_print
+ + +*** Seriously nested if's test ***
+** spelling correction by kluzz ** +Only two lines of text should follow:
+this should be displayed. should be: $i=1, $j=0. is: $i=1, $j=0
+this is supposed to be displayed. should be: $i=2, $j=4. is: $i=2, $j=4
+3 loop iterations should follow:
+2 4
+3 4
+4 4
+**********************************
+ +*** C-style else-if's ***
+This should be displayed
+*************************
+ +*** WHILE tests ***
+0 is smaller than 20
+1 is smaller than 20
+2 is smaller than 20
+3 is smaller than 20
+4 is smaller than 20
+5 is smaller than 20
+6 is smaller than 20
+7 is smaller than 20
+8 is smaller than 20
+9 is smaller than 20
+10 is smaller than 20
+11 is smaller than 20
+12 is smaller than 20
+13 is smaller than 20
+14 is smaller than 20
+15 is smaller than 20
+16 is smaller than 20
+17 is smaller than 20
+18 is smaller than 20
+19 is smaller than 20
+20 equals 20
+21 is greater than 20
+22 is greater than 20
+23 is greater than 20
+24 is greater than 20
+25 is greater than 20
+26 is greater than 20
+27 is greater than 20
+28 is greater than 20
+29 is greater than 20
+30 is greater than 20
+31 is greater than 20
+32 is greater than 20
+33 is greater than 20
+34 is greater than 20
+35 is greater than 20
+36 is greater than 20
+37 is greater than 20
+38 is greater than 20
+39 is greater than 20
+*******************
+ + +*** Nested WHILEs ***
+Each array variable should be equal to the sum of its indices:
+${test00}[0] = 0
+${test00}[1] = 1
+${test00}[2] = 2
+${test01}[0] = 1
+${test01}[1] = 2
+${test01}[2] = 3
+${test02}[0] = 2
+${test02}[1] = 3
+${test02}[2] = 4
+${test10}[0] = 1
+${test10}[1] = 2
+${test10}[2] = 3
+${test11}[0] = 2
+${test11}[1] = 3
+${test11}[2] = 4
+${test12}[0] = 3
+${test12}[1] = 4
+${test12}[2] = 5
+${test20}[0] = 2
+${test20}[1] = 3
+${test20}[2] = 4
+${test21}[0] = 3
+${test21}[1] = 4
+${test21}[2] = 5
+${test22}[0] = 4
+${test22}[1] = 5
+${test22}[2] = 6
+*********************
+ +*** hash test... ***
+commented out... +**************************
+ +*** Hash resizing test ***
+ba
+baa
+baaa
+baaaa
+baaaaa
+baaaaaa
+baaaaaaa
+baaaaaaaa
+baaaaaaaaa
+baaaaaaaaaa
+ba
+10
+baa
+9
+baaa
+8
+baaaa
+7
+baaaaa
+6
+baaaaaa
+5
+baaaaaaa
+4
+baaaaaaaa
+3
+baaaaaaaaa
+2
+baaaaaaaaaa
+1
+**************************
+ + +*** break/continue test ***
+$i should go from 0 to 2
+$j should go from 3 to 4, and $q should go from 3 to 4
+ $j=3
+ $q=3
+ $q=4
+ $j=4
+ $q=3
+ $q=4
+$j should go from 0 to 2
+ $j=0
+ $j=1
+ $j=2
+$k should go from 0 to 2
+ $k=0
+ $k=1
+ $k=2
+$i=0
+$j should go from 3 to 4, and $q should go from 3 to 4
+ $j=3
+ $q=3
+ $q=4
+ $j=4
+ $q=3
+ $q=4
+$j should go from 0 to 2
+ $j=0
+ $j=1
+ $j=2
+$k should go from 0 to 2
+ $k=0
+ $k=1
+ $k=2
+$i=1
+$j should go from 3 to 4, and $q should go from 3 to 4
+ $j=3
+ $q=3
+ $q=4
+ $j=4
+ $q=3
+ $q=4
+$j should go from 0 to 2
+ $j=0
+ $j=1
+ $j=2
+$k should go from 0 to 2
+ $k=0
+ $k=1
+ $k=2
+$i=2
+***********************
+ +*** Nested file include test ***
+ +This is Finish.phtml. This file is supposed to be included +from regression_test.phtml. This is normal HTML. +and this is PHP code, 2+2=4 + +********************************
+ +Tests completed.
+Limor Ullmann is now Limor Baruch :I