diff --git a/bin/compiler.php b/bin/compiler.php index b3c84b48..9420de83 100755 --- a/bin/compiler.php +++ b/bin/compiler.php @@ -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); diff --git a/src/Php/Translator.php b/src/Php/Translator.php index ef476df0..5fec899d 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -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) . '"'; + } } diff --git a/tests/core/lang/013.phpt b/tests/core/lang/013.phpt new file mode 100644 index 00000000..c25cf41a --- /dev/null +++ b/tests/core/lang/013.phpt @@ -0,0 +1,10 @@ +--TEST-- +Testing eval function +--FILE-- + +--EXPECT-- +Hello diff --git a/tests/core/lang/014.phpt b/tests/core/lang/014.phpt new file mode 100644 index 00000000..03f818d9 --- /dev/null +++ b/tests/core/lang/014.phpt @@ -0,0 +1,14 @@ +--TEST-- +Testing eval function inside user-defined function +--FILE-- + +--EXPECT-- +Hello diff --git a/tests/core/lang/015.inc b/tests/core/lang/015.inc new file mode 100644 index 00000000..a528d8cd --- /dev/null +++ b/tests/core/lang/015.inc @@ -0,0 +1,3 @@ + diff --git a/tests/core/lang/015.phpt b/tests/core/lang/015.phpt new file mode 100644 index 00000000..0c8077c0 --- /dev/null +++ b/tests/core/lang/015.phpt @@ -0,0 +1,8 @@ +--TEST-- +Testing include +--FILE-- + +--EXPECT-- +Hello diff --git a/tests/core/lang/016.inc b/tests/core/lang/016.inc new file mode 100644 index 00000000..453755d8 --- /dev/null +++ b/tests/core/lang/016.inc @@ -0,0 +1,5 @@ + diff --git a/tests/core/lang/016.phpt b/tests/core/lang/016.phpt new file mode 100644 index 00000000..ba960e60 --- /dev/null +++ b/tests/core/lang/016.phpt @@ -0,0 +1,9 @@ +--TEST-- +Testing user-defined function in included file +--FILE-- + +--EXPECT-- +Hello diff --git a/tests/core/lang/017.phpt b/tests/core/lang/017.phpt new file mode 100644 index 00000000..c772ac02 --- /dev/null +++ b/tests/core/lang/017.phpt @@ -0,0 +1,19 @@ +--TEST-- +Testing user-defined function falling out of an If into another +--FILE-- + +--EXPECT-- +1 diff --git a/tests/core/lang/018.phpt b/tests/core/lang/018.phpt new file mode 100644 index 00000000..647bee87 --- /dev/null +++ b/tests/core/lang/018.phpt @@ -0,0 +1,35 @@ +--TEST-- +eval() test +--FILE-- + +--EXPECT-- +hey +0 +hey +1 +hey +2 +hey +3 +hey +4 +hey +5 +hey +6 +hey +7 +hey +8 +hey +9 diff --git a/tests/core/lang/019.phpt b/tests/core/lang/019.phpt new file mode 100644 index 00000000..b1147983 --- /dev/null +++ b/tests/core/lang/019.phpt @@ -0,0 +1,36 @@ +--TEST-- +eval() test +--FILE-- + +--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()!