优化 Switch 脚本

pull/1/head
韩天峰 8 months ago
parent 1dd9f62914
commit f1bbcfe64c
  1. 3
      bin/compiler.php
  2. 72
      src/Php/Translator.php
  3. 10
      tests/core/lang/013.phpt
  4. 14
      tests/core/lang/014.phpt
  5. 3
      tests/core/lang/015.inc
  6. 8
      tests/core/lang/015.phpt
  7. 5
      tests/core/lang/016.inc
  8. 9
      tests/core/lang/016.phpt
  9. 19
      tests/core/lang/017.phpt
  10. 35
      tests/core/lang/018.phpt
  11. 36
      tests/core/lang/019.phpt

@ -18,4 +18,7 @@ $translator->save($code, $cppFile);
$translator->compileFile($cppFile);
$objectFile = './tmp/' . $info['filename'] . '.cc.o';
if (!is_file($objectFile)) {
throw new Exception("compile error");
}
$translator->compileBinary($info['filename'], $objectFile);

@ -13,12 +13,13 @@ use PhpParser\PrettyPrinter;
class Translator extends \PhpAot\Core\Translator
{
const TYPE_VAR = 'php::Var';
const TYPE_BOOL = 'php::Bool';
const TYPE_INT = 'php::Int';
const TYPE_FLOAT = 'php::Float';
const TYPE_OBJECT = 'php::Object';
const TYPE_ARRAY = 'php::Array';
const string TYPE_VAR = 'php::Var';
const string TYPE_BOOL = 'php::Bool';
const string TYPE_INT = 'php::Int';
const string TYPE_FLOAT = 'php::Float';
const string TYPE_OBJECT = 'php::Object';
const string TYPE_ARRAY = 'php::Array';
const string TYPE_STR = 'php::Str';
private string $phpxDir = '~/workspace/projects/phpx';
protected string $lang = 'PHP';
@ -208,6 +209,11 @@ class Translator extends \PhpAot\Core\Translator
}
}
private function parseScalarValue($expr): string
{
return $expr->getAttribute('rawValue');
}
private function parseIdentifier(Node $expr)
{
$type = $expr->getType();
@ -405,6 +411,10 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseTernary($expr);
case 'Expr_FuncCall':
return $this->parseFuncCall($expr);
case 'Expr_Include':
return $this->parseInclude($expr);
case 'Expr_Eval':
return $this->parseEval($expr);
case 'Expr_New':
return $this->parseNew($expr);
case 'Expr_Clone':
@ -418,6 +428,8 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseIdentifier($expr);
case 'Scalar_MagicConst_File':
return $this->parseMagicConstFile($expr);
case 'Scalar_MagicConst_Dir':
return $this->parseMagicConstDir($expr);
case 'Scalar_InterpolatedString':
return $this->parseInterpolatedString($expr);
case 'Expr_Cast_Int':
@ -735,7 +747,6 @@ class Translator extends \PhpAot\Core\Translator
$stmts = $v->stmts;
$code = '';
$list_expr = [];
foreach ($init as $expr) {
$list_expr[] = $this->parseExpr($expr);
@ -1324,15 +1335,20 @@ class Translator extends \PhpAot\Core\Translator
$cond = $v->cond;
$tmp_var = $this->addTmpVar();
$type = $this->detectExprType($cond);
$code = $type . ' ' . $tmp_var . ' = ' . $this->parseExpr($cond) . ';' . PHP_EOL;
$var_def = $type . ' ' . $tmp_var . ' = ' . $this->parseExpr($cond) . ';' . PHP_EOL;
if ($type === self::TYPE_INT or $type === self::TYPE_FLOAT) {
$code .= 'switch (' . $tmp_var . ') {' . PHP_EOL;
$code = 'switch (' . $tmp_var . ') {' . PHP_EOL;
$this->indentLevel++;
foreach ($v->cases as $case) {
if (empty($case->cond)) {
$code .= $this->getIndent() . 'default: {' . PHP_EOL;
} else {
$code .= $this->getIndent() . 'case ' . $this->parseIdentifier($case->cond) . ': {' . PHP_EOL;
$condType = $case->cond->getType();
if ($condType !== 'Scalar_Int' and $condType !== 'Scalar_Float') {
goto _fail;
}
$code .= $this->getIndent() . 'case ' . $this->parseScalarValue($case->cond) . ': {' . PHP_EOL;
}
$this->indentLevel++;
$code .= $this->parseStmts($case->stmts);
@ -1341,11 +1357,26 @@ class Translator extends \PhpAot\Core\Translator
}
$this->indentLevel--;
$code .= $this->getIndent() . '}';
return $code;
} else {
return $var_def . $code;
}
_fail:
$code = 'do {' . PHP_EOL;
$this->indentLevel++;
foreach ($v->cases as $case) {
if (empty($case->cond)) {
$code .= $this->getIndent() . 'else {' . PHP_EOL;
} else {
$code .= $this->getIndent() . 'if (' . $tmp_var.'=='. $this->parseIdentifier($case->cond) . ') {' . PHP_EOL;
}
$this->indentLevel++;
$code .= $this->parseStmts($case->stmts);
$this->indentLevel--;
$code .= $this->getIndent() . '}' . PHP_EOL;
}
exit(2);
$this->indentLevel--;
$code .= $this->getIndent() . '} while (0);';
return $var_def . $code;
}
private function parseStatic(mixed $v): string
@ -1357,4 +1388,19 @@ class Translator extends \PhpAot\Core\Translator
}
return implode(PHP_EOL . $this->getIndent(), $list);
}
private function parseEval(mixed $expr): string
{
return 'php::eval(' . $this->parseIdentifier($expr->expr) . ')';
}
private function parseInclude(mixed $expr): string
{
return 'php::include(' . $this->parseIdentifier($expr->expr) . ')';
}
private function parseMagicConstDir(mixed $expr): string
{
return '"' . $this->escapeString($this->dir) . '"';
}
}

@ -0,0 +1,10 @@
--TEST--
Testing eval function
--FILE--
<?php
error_reporting(0);
$a="echo \"Hello\";";
eval($a);
?>
--EXPECT--
Hello

@ -0,0 +1,14 @@
--TEST--
Testing eval function inside user-defined function
--FILE--
<?php
function F ($a) {
eval($a);
}
function main() {
error_reporting(0);
F("echo \"Hello\";");
}
?>
--EXPECT--
Hello

@ -0,0 +1,3 @@
<?php
echo "Hello";
?>

@ -0,0 +1,8 @@
--TEST--
Testing include
--FILE--
<?php
include __DIR__ . "/015.inc";
?>
--EXPECT--
Hello

@ -0,0 +1,5 @@
<?php
function MyFunc ($a) {
echo $a;
}
?>

@ -0,0 +1,9 @@
--TEST--
Testing user-defined function in included file
--FILE--
<?php
include __DIR__ . "/016.inc";
MyFunc("Hello");
?>
--EXPECT--
Hello

@ -0,0 +1,19 @@
--TEST--
Testing user-defined function falling out of an If into another
--FILE--
<?php
function Test ($a) {
if ($a<3) {
return(3);
}
}
function main() {
$a = 1;
if ($a < Test($a)) {
echo "$a\n";
$a++;
}
}
?>
--EXPECT--
1

@ -0,0 +1,35 @@
--TEST--
eval() test
--FILE--
<?php
error_reporting(0);
$message = "echo \"hey\n\";";
for ($i=0; $i<10; $i++) {
eval($message);
echo $i."\n";
}
?>
--EXPECT--
hey
0
hey
1
hey
2
hey
3
hey
4
hey
5
hey
6
hey
7
hey
8
hey
9

@ -0,0 +1,36 @@
--TEST--
eval() test
--FILE--
<?php
eval("function test() { echo \"hey, this is a function inside an eval()!\\n\"; }");
$i=0;
while ($i<10) {
eval("echo \"hey, this is a regular echo'd eval()\\n\";");
test();
$i++;
}
?>
--EXPECTF--
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
Loading…
Cancel
Save