回归赋值的语法

pull/1/head
韩天峰 8 months ago
parent 668244ae64
commit f3565a6439
  1. 2
      run-tests.php
  2. 66
      src/Php/Translator.php
  3. 76
      tests/core/lang/020.phpt
  4. 44
      tests/core/lang/021.phpt
  5. 65
      tests/core/lang/022.phpt
  6. 251
      tests/core/lang/023.phpt

@ -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) {

@ -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;';
}
}

@ -0,0 +1,76 @@
--TEST--
Switch test 1
--FILE--
<?php
$i="abc";
for ($j=0; $j<10; $j++) {
switch (1) {
case 1:
echo "In branch 1\n";
switch ($i) {
case "ab":
echo "This doesn't work... :(\n";
break;
case "abcd":
echo "This works!\n";
break;
case "blah":
echo "Hmmm, no worki\n";
break;
default:
echo "Inner default...\n";
}
for ($blah=0; $blah<200; $blah++) {
if ($blah==100) {
echo "blah=$blah\n";
}
}
break;
case 2:
echo "In branch 2\n";
break;
case $i:
echo "In branch \$i\n";
break;
case 4:
echo "In branch 4\n";
break;
default:
echo "Hi, I'm default\n";
break;
}
}
?>
--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

@ -0,0 +1,44 @@
--TEST--
Switch test 2
--SKIPIF--
<?php die("skip");?>
--FILE--
<?php
for ($i=0; $i<=5; $i++)
{
echo "i=$i\n";
switch($i) {
case 0:
echo "In branch 0\n";
break;
case 1:
echo "In branch 1\n";
break;
case 2:
echo "In branch 2\n";
break;
case 3:
echo "In branch 3\n";
break 2;
case 4:
echo "In branch 4\n";
break;
default:
echo "In default\n";
break;
}
}
echo "hi\n";
?>
--EXPECT--
i=0
In branch 0
i=1
In branch 1
i=2
In branch 2
i=3
In branch 3
hi

@ -0,0 +1,65 @@
--TEST--
Switch test 3
--FILE--
<?php
function switchtest ($i, $j)
{
switch ($i) {
case 0:
switch($j) {
case 0:
echo "zero";
break;
case 1:
echo "one";
break;
default:
echo $j;
break;
}
echo "\n";
break;
default:
echo "Default taken\n";
}
}
function main() {
for ($i=0; $i<3; $i++) {
for ($k=0; $k<10; $k++) {
switchtest (0,$k);
}
}
}
?>
--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

@ -0,0 +1,251 @@
--TEST--
Regression test
--INI--
date.timezone=UTC
--FILE--
<?php
include __DIR__.("/023-1.inc");
$wedding_timestamp = mktime(20,0,0,8,31,1997);
$time_left=$wedding_timestamp-time();
if ($time_left>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--
<html>
<head>
*** Testing assignments and variable aliasing: ***<br>
This should read "blah": blah<br>
This should read "this is nifty": this is nifty<br>
*************************************************<br>
*** Testing integer operators ***<br>
Correct result - 8: 8<br>
Correct result - 8: 8<br>
Correct result - 2: 2<br>
Correct result - -2: -2<br>
Correct result - 15: 15<br>
Correct result - 15: 15<br>
Correct result - 2: 2<br>
Correct result - 3: 3<br>
*********************************<br>
*** Testing real operators ***<br>
Correct result - 8: 8<br>
Correct result - 8: 8<br>
Correct result - 2: 2<br>
Correct result - -2: -2<br>
Correct result - 15: 15<br>
Correct result - 15: 15<br>
Correct result - 2: 2<br>
Correct result - 3: 3<br>
*********************************<br>
*** Testing if/elseif/else control ***<br>
This works<br>
this_still_works<br>
should_print<br>
*** Seriously nested if's test ***<br>
** spelling correction by kluzz **
Only two lines of text should follow:<br>
this should be displayed. should be: $i=1, $j=0. is: $i=1, $j=0<br>
this is supposed to be displayed. should be: $i=2, $j=4. is: $i=2, $j=4<br>
3 loop iterations should follow:<br>
2 4<br>
3 4<br>
4 4<br>
**********************************<br>
*** C-style else-if's ***<br>
This should be displayed<br>
*************************<br>
*** WHILE tests ***<br>
0 is smaller than 20<br>
1 is smaller than 20<br>
2 is smaller than 20<br>
3 is smaller than 20<br>
4 is smaller than 20<br>
5 is smaller than 20<br>
6 is smaller than 20<br>
7 is smaller than 20<br>
8 is smaller than 20<br>
9 is smaller than 20<br>
10 is smaller than 20<br>
11 is smaller than 20<br>
12 is smaller than 20<br>
13 is smaller than 20<br>
14 is smaller than 20<br>
15 is smaller than 20<br>
16 is smaller than 20<br>
17 is smaller than 20<br>
18 is smaller than 20<br>
19 is smaller than 20<br>
20 equals 20<br>
21 is greater than 20<br>
22 is greater than 20<br>
23 is greater than 20<br>
24 is greater than 20<br>
25 is greater than 20<br>
26 is greater than 20<br>
27 is greater than 20<br>
28 is greater than 20<br>
29 is greater than 20<br>
30 is greater than 20<br>
31 is greater than 20<br>
32 is greater than 20<br>
33 is greater than 20<br>
34 is greater than 20<br>
35 is greater than 20<br>
36 is greater than 20<br>
37 is greater than 20<br>
38 is greater than 20<br>
39 is greater than 20<br>
*******************<br>
*** Nested WHILEs ***<br>
Each array variable should be equal to the sum of its indices:<br>
${test00}[0] = 0<br>
${test00}[1] = 1<br>
${test00}[2] = 2<br>
${test01}[0] = 1<br>
${test01}[1] = 2<br>
${test01}[2] = 3<br>
${test02}[0] = 2<br>
${test02}[1] = 3<br>
${test02}[2] = 4<br>
${test10}[0] = 1<br>
${test10}[1] = 2<br>
${test10}[2] = 3<br>
${test11}[0] = 2<br>
${test11}[1] = 3<br>
${test11}[2] = 4<br>
${test12}[0] = 3<br>
${test12}[1] = 4<br>
${test12}[2] = 5<br>
${test20}[0] = 2<br>
${test20}[1] = 3<br>
${test20}[2] = 4<br>
${test21}[0] = 3<br>
${test21}[1] = 4<br>
${test21}[2] = 5<br>
${test22}[0] = 4<br>
${test22}[1] = 5<br>
${test22}[2] = 6<br>
*********************<br>
*** hash test... ***<br>
commented out...
**************************<br>
*** Hash resizing test ***<br>
ba<br>
baa<br>
baaa<br>
baaaa<br>
baaaaa<br>
baaaaaa<br>
baaaaaaa<br>
baaaaaaaa<br>
baaaaaaaaa<br>
baaaaaaaaaa<br>
ba<br>
10<br>
baa<br>
9<br>
baaa<br>
8<br>
baaaa<br>
7<br>
baaaaa<br>
6<br>
baaaaaa<br>
5<br>
baaaaaaa<br>
4<br>
baaaaaaaa<br>
3<br>
baaaaaaaaa<br>
2<br>
baaaaaaaaaa<br>
1<br>
**************************<br>
*** break/continue test ***<br>
$i should go from 0 to 2<br>
$j should go from 3 to 4, and $q should go from 3 to 4<br>
$j=3<br>
$q=3<br>
$q=4<br>
$j=4<br>
$q=3<br>
$q=4<br>
$j should go from 0 to 2<br>
$j=0<br>
$j=1<br>
$j=2<br>
$k should go from 0 to 2<br>
$k=0<br>
$k=1<br>
$k=2<br>
$i=0<br>
$j should go from 3 to 4, and $q should go from 3 to 4<br>
$j=3<br>
$q=3<br>
$q=4<br>
$j=4<br>
$q=3<br>
$q=4<br>
$j should go from 0 to 2<br>
$j=0<br>
$j=1<br>
$j=2<br>
$k should go from 0 to 2<br>
$k=0<br>
$k=1<br>
$k=2<br>
$i=1<br>
$j should go from 3 to 4, and $q should go from 3 to 4<br>
$j=3<br>
$q=3<br>
$q=4<br>
$j=4<br>
$q=3<br>
$q=4<br>
$j should go from 0 to 2<br>
$j=0<br>
$j=1<br>
$j=2<br>
$k should go from 0 to 2<br>
$k=0<br>
$k=1<br>
$k=2<br>
$i=2<br>
***********************<br>
*** Nested file include test ***<br>
<html>
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
</html>
********************************<br>
Tests completed.<br>
Limor Ullmann is now Limor Baruch :I
Loading…
Cancel
Save