pull/1/head
韩天峰 8 months ago
parent a635ae4831
commit 26a6d19e1f
  1. 93
      examples/binary-tree.php
  2. 11
      examples/unset.php
  3. 10
      src/Php/Encryptor.php
  4. 82
      src/Php/Translator.php
  5. 28
      src/Python/Translator.php
  6. 6
      src/functions.php

@ -0,0 +1,93 @@
<?php
/* The Computer Language Benchmarks Game
https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
contributed by Peter Baltruschat
modified by Levi Cameron
multiprocessing by Yuriy Moskalchuk
*/
function createTree($depth)
{
echo '';
if (!$depth) {
return [null, null];
}
$depth--;
return [
createTree($depth),
createTree($depth)
];
}
function checkTree($treeNode)
{
return 1
+ ($treeNode[0][0] === null ? 1 : checkTree($treeNode[0]))
+ ($treeNode[1][0] === null ? 1 : checkTree($treeNode[1]));
}
function startWorker($depth, $iter, $n, $size, $shmId)
{
$pid = pcntl_fork();
if ($pid) {
return $pid;
} else {
$check = 0;
for ($i = 1; $i <= $iter; ++$i) {
$t = createTree($depth);
$check += checkTree($t);
unset($t);
}
$result = "$iter\t trees of depth $depth\t check: $check\n";
shmop_write($shmId, $result, $size * ($n - 1));
exit(0);
}
}
function main()
{
global $argc, $argv;
$minDepth = 4;
$n = ($argc == 2) ? $argv[1] : 1;
$maxDepth = max($minDepth + 2, $n);
$stretchDepth = $maxDepth + 1;
$stretchTree = createTree($stretchDepth);
echo "stretch tree of depth $stretchDepth\t check: ", checkTree($stretchTree), PHP_EOL;
unset($stretchTree);
$longLivedTree = createTree($maxDepth);
$iterations = 1 << ($maxDepth);
$depthIterations = [$minDepth => $iterations];
do {
$minDepth += 2;
if ($minDepth <= $maxDepth) {
$iterations >>= 2;
$depthIterations[$minDepth] = $iterations;
}
} while ($minDepth <= $maxDepth);
$size = 128;
$shmId = shmop_open(ftok(__FILE__, 'b'), 'c', 0644, $size * (count($depthIterations) + 1));
$PIDs = [];
$n = 0;
foreach ($depthIterations as $d => $i) {
$PIDs[] = startWorker($d, $i, ++$n, $size, $shmId);
}
foreach ($PIDs as $PID) {
pcntl_waitpid($PID, $status);
}
foreach (range(1, count($depthIterations)) as $n) {
echo trim(shmop_read($shmId, $size * ($n - 1), $size)), PHP_EOL;
}
shmop_delete($shmId);
echo "long lived tree of depth $maxDepth\t check: ", checkTree($longLivedTree), PHP_EOL;
}
main();

@ -0,0 +1,11 @@
<?php
function main()
{
$array['hello'] = 'world';
$name = 'world';
$object = new stdClass();
$object->hello = 'world';
unset($array['hello'], $name, $object->hello);
var_dump($array, $object);
}

@ -125,7 +125,7 @@ class Encryptor extends \PhpAot\Core\Translator
case 'Stmt_Switch':
break;
default:
debug($node);
abort($node);
}
}
@ -172,7 +172,7 @@ class Encryptor extends \PhpAot\Core\Translator
case 'Stmt_Switch':
break;
default:
debug($v);
abort($v);
}
}
$code = '';
@ -218,7 +218,7 @@ class Encryptor extends \PhpAot\Core\Translator
$this->parseConstFetch($expr);
break;
default:
debug($expr);
abort($expr);
}
}
@ -276,7 +276,7 @@ class Encryptor extends \PhpAot\Core\Translator
case 'Expr_Array':
return 'php::Array';
default:
debug($expr);
abort($expr);
}
}
@ -310,7 +310,7 @@ class Encryptor extends \PhpAot\Core\Translator
case 'float':
return 'double';
default:
debug($type);
abort($type);
}
}

@ -90,7 +90,7 @@ class Translator extends \PhpAot\Core\Translator
$cppCode .= $this->parseFunctionDef($v) . PHP_EOL;
break;
default:
debug($v);
abort($v);
}
}
return $cppCode;
@ -213,7 +213,7 @@ class Translator extends \PhpAot\Core\Translator
$lines = [];
foreach ($stmts as $v) {
$class = $v->getType();
// $this->writeLog('Line ' . $this->getLine($v) . ': ' . $class);
$this->writeLog('Line ' . $this->getLine($v) . ': ' . $class);
switch ($class) {
case 'Stmt_Expression':
$lines[] = $this->parseExpr($v->expr) . ';';
@ -245,8 +245,11 @@ class Translator extends \PhpAot\Core\Translator
case 'Stmt_Global':
$lines[] = $this->parseGlobal($v);
break;
case 'Stmt_Unset':
$lines[] = $this->parseUnset($v);
break;
default:
debug($v);
abort($v);
}
}
$code = '';
@ -259,6 +262,7 @@ class Translator extends \PhpAot\Core\Translator
private function parseExpr(mixed $expr)
{
$type = $expr->getType();
$this->writeLog('Line ' . $this->getLine($expr) . ': ' . $type);
switch ($type) {
case 'Expr_Assign':
return $this->parseAssign($expr);
@ -320,6 +324,8 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseArray($expr);
case 'Expr_ArrayDimFetch':
return $this->parseArrayDimFetch($expr);
case 'Expr_PropertyFetch':
return $this->parsePropertyFetch($expr);
case 'Expr_BinaryOp_ShiftLeft':
return $this->parseBinaryOpShiftLeft($expr);
case 'Expr_BinaryOp_ShiftRight':
@ -364,17 +370,40 @@ class Translator extends \PhpAot\Core\Translator
case 'Expr_Exit':
return $this->parseExit($expr);
default:
debug($expr);
abort($expr);
}
}
private function parseAssign(Node $v): string
{
$var = $this->parseIdentifier($v->var);
$expr = $this->parseExpr($v->expr);
$left = $v->var;
$right = $v->expr;
if ($left->getType() === 'Expr_ArrayDimFetch') {
$array = $this->parseIdentifier($left->var);
$code = '';
// 这是 PHP 的初始化+赋值写法,需要先创建数组
if (!$this->hasVar($array)) {
$this->addVar($array, self::TYPE_VAR);
$code .= self::TYPE_ARRAY . " $array;\n" . $this->getIndent();
}
$dim = $this->parseIdentifier($left->dim);
return $code . "$array.offsetSet($dim, " . $this->parseExpr($right) . ")";
} elseif ($left->getType() === 'Expr_PropertyFetch') {
$array = $this->parseIdentifier($left->var);
$propName = $this->parseIdentifier($left->name);
return "$array.setProperty(\"$propName\", " . $this->parseExpr($right) . ")";
}
$var = $this->parseIdentifier($left);
$expr = $this->parseExpr($right);
if (!$this->hasVar($var)) {
$type = $this->detectType($v->expr);
if ($right->getType() === 'Expr_New') {
$type = self::TYPE_OBJECT;
} else {
$type = $this->detectType($right);
}
$this->addVar($var, $type);
return $type . ' ' . $var . ' = ' . $expr;
} else {
@ -493,7 +522,7 @@ class Translator extends \PhpAot\Core\Translator
case 'bool':
return self::TYPE_BOOL;
default:
debug($type);
abort($type);
}
}
@ -928,9 +957,9 @@ class Translator extends \PhpAot\Core\Translator
$className = $this->parseIdentifier($expr->class);
$args = $expr->args;
if (empty($args)) {
return 'new ' . $className . '()';
return 'php::newObject("' . $className . '")';
} else {
return 'new ' . $className . '(' . $this->parseArgs($args) . ')';
return 'php::newObject("' . $className . '"(' . $this->parseArgs($args) . ')';
}
}
@ -959,7 +988,7 @@ class Translator extends \PhpAot\Core\Translator
}
break;
default:
debug($v2);
abort($v2);
}
}
$this->namespace = '';
@ -981,7 +1010,7 @@ class Translator extends \PhpAot\Core\Translator
$code .= $this->parseFunctionDef($v) . PHP_EOL;
break;
default:
debug($v);
abort($v);
}
}
$this->class = '';
@ -1081,4 +1110,33 @@ class Translator extends \PhpAot\Core\Translator
{
return 'php::exit(' . $this->parseIdentifier($node->expr) . ')';
}
private function parseUnset(Node $node): string
{
$vars = $node->vars;
$lines = [];
foreach ($vars as $var) {
$type = $var->getType();
if ($type === 'Expr_ArrayDimFetch') {
$array = $this->parseIdentifier($var->var);
$dim = $this->parseIdentifier($var->dim);
$lines[] = $array . '.offsetUnset(' . $dim . ');';
} elseif ($type === 'Expr_PropertyFetch') {
$object = $this->parseIdentifier($var->var);
$propName = $this->parseIdentifier($var->name);
$lines[] = $object . '.unsetProperty("' . $propName . '");';
} elseif ($type === 'Expr_Variable') {
$name = $this->parseIdentifier($var);
$lines[] = "$name.unset();";
} else {
abort($var);
}
}
return implode(PHP_EOL . $this->getIndent(), $lines);
}
private function parsePropertyFetch(mixed $expr): string
{
return $this->parseIdentifier($expr->var) . '.getProperty(' . $this->parseIdentifier($expr->name) . ')';
}
}

@ -84,7 +84,7 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseBinOp($attr);
default:
var_dump(__METHOD__, __LINE__);
debug($attr);
abort($attr);
}
}
@ -106,7 +106,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Attribute':
return $this->parseAttribute($fn->value) . '->' . $fn->attr;
default:
debug($fn);
abort($fn);
}
}
@ -240,7 +240,7 @@ class Translator extends \PhpAot\Core\Translator
case 'GeneratorExp':
return $this->parseGeneratorExp($value);
default:
debug($value);
abort($value);
break;
}
}
@ -257,7 +257,7 @@ class Translator extends \PhpAot\Core\Translator
$_args[] = $slice->step ? $this->parseTarget($slice->step) : 'null';
return 'PyCore::slice(' . implode(', ', $_args) . ')';
} else {
debug($slice);
abort($slice);
}
}
@ -298,7 +298,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Not':
return '!' . $operand;
default:
debug($target);
abort($target);
break;
}
break;
@ -329,7 +329,7 @@ class Translator extends \PhpAot\Core\Translator
case 'ListComp':
return $this->parseListComp($target);
default:
debug($target);
abort($target);
break;
}
}
@ -386,7 +386,7 @@ class Translator extends \PhpAot\Core\Translator
if ($test->ops) {
$ops = $test->ops;
if (count($ops) != 1) {
debug($test);
abort($test);
}
$op = $ops[0]->_type;
$comparators = $test->comparators;
@ -458,7 +458,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Attribute':
return $this->parseAttribute($iter);
default:
debug($iter);
abort($iter);
}
}
@ -475,7 +475,7 @@ class Translator extends \PhpAot\Core\Translator
return $value . '[' . $this->parseSlice($node->slice) . ']';
}
} else {
debug($node);
abort($node);
}
}
@ -603,7 +603,7 @@ class Translator extends \PhpAot\Core\Translator
$line = $this->parseCall($node) . ';';
break;
default:
debug($node);
abort($node);
$line = '';
break;
}
@ -772,7 +772,7 @@ class Translator extends \PhpAot\Core\Translator
$code = '[' . PHP_EOL;
foreach ($dict->values as $k => $v) {
if (empty($dict->keys[$k])) {
debug($v);
abort($v);
}
$key = $dict->keys[$k];
$this->indentLevel++;
@ -791,7 +791,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Or':
return $this->parseOr($value->values);
default:
debug($value);
abort($value);
break;
}
}
@ -943,7 +943,7 @@ class Translator extends \PhpAot\Core\Translator
$expr = $this->parseValue($value->value);
if ($value->format_spec and $value->format_spec->_type == 'JoinedStr') {
if (count($value->format_spec->values) != 1) {
debug($value);
abort($value);
}
$format = $value->format_spec->values[0]->value;
if ($format[0] == '.' and $format[-1] == 'f') {
@ -974,6 +974,6 @@ class Translator extends \PhpAot\Core\Translator
private function parseGeneratorExp($value)
{
debug($value);
abort($value);
}
}

@ -2,7 +2,7 @@
use PhpAot\Core\Translator;
function debug($v)
function abort($v)
{
/**
* @var $translator Translator
@ -25,13 +25,13 @@ function debug($v)
function if_empty_debug($if_expr, $v)
{
if (empty($if_expr)) {
debug($v);
abort($v);
}
}
function if_not_empty_debug($if_expr, $v)
{
if (!empty($if_expr)) {
debug($v);
abort($v);
}
}

Loading…
Cancel
Save