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: ***