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

@ -90,7 +90,7 @@ class Translator extends \PhpAot\Core\Translator
$cppCode .= $this->parseFunctionDef($v) . PHP_EOL; $cppCode .= $this->parseFunctionDef($v) . PHP_EOL;
break; break;
default: default:
debug($v); abort($v);
} }
} }
return $cppCode; return $cppCode;
@ -213,7 +213,7 @@ class Translator extends \PhpAot\Core\Translator
$lines = []; $lines = [];
foreach ($stmts as $v) { foreach ($stmts as $v) {
$class = $v->getType(); $class = $v->getType();
// $this->writeLog('Line ' . $this->getLine($v) . ': ' . $class); $this->writeLog('Line ' . $this->getLine($v) . ': ' . $class);
switch ($class) { switch ($class) {
case 'Stmt_Expression': case 'Stmt_Expression':
$lines[] = $this->parseExpr($v->expr) . ';'; $lines[] = $this->parseExpr($v->expr) . ';';
@ -245,8 +245,11 @@ class Translator extends \PhpAot\Core\Translator
case 'Stmt_Global': case 'Stmt_Global':
$lines[] = $this->parseGlobal($v); $lines[] = $this->parseGlobal($v);
break; break;
case 'Stmt_Unset':
$lines[] = $this->parseUnset($v);
break;
default: default:
debug($v); abort($v);
} }
} }
$code = ''; $code = '';
@ -259,6 +262,7 @@ class Translator extends \PhpAot\Core\Translator
private function parseExpr(mixed $expr) private function parseExpr(mixed $expr)
{ {
$type = $expr->getType(); $type = $expr->getType();
$this->writeLog('Line ' . $this->getLine($expr) . ': ' . $type);
switch ($type) { switch ($type) {
case 'Expr_Assign': case 'Expr_Assign':
return $this->parseAssign($expr); return $this->parseAssign($expr);
@ -320,6 +324,8 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseArray($expr); return $this->parseArray($expr);
case 'Expr_ArrayDimFetch': case 'Expr_ArrayDimFetch':
return $this->parseArrayDimFetch($expr); return $this->parseArrayDimFetch($expr);
case 'Expr_PropertyFetch':
return $this->parsePropertyFetch($expr);
case 'Expr_BinaryOp_ShiftLeft': case 'Expr_BinaryOp_ShiftLeft':
return $this->parseBinaryOpShiftLeft($expr); return $this->parseBinaryOpShiftLeft($expr);
case 'Expr_BinaryOp_ShiftRight': case 'Expr_BinaryOp_ShiftRight':
@ -364,17 +370,40 @@ class Translator extends \PhpAot\Core\Translator
case 'Expr_Exit': case 'Expr_Exit':
return $this->parseExit($expr); return $this->parseExit($expr);
default: default:
debug($expr); abort($expr);
} }
} }
private function parseAssign(Node $v): string private function parseAssign(Node $v): string
{ {
$var = $this->parseIdentifier($v->var); $left = $v->var;
$expr = $this->parseExpr($v->expr); $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)) { 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); $this->addVar($var, $type);
return $type . ' ' . $var . ' = ' . $expr; return $type . ' ' . $var . ' = ' . $expr;
} else { } else {
@ -493,7 +522,7 @@ class Translator extends \PhpAot\Core\Translator
case 'bool': case 'bool':
return self::TYPE_BOOL; return self::TYPE_BOOL;
default: default:
debug($type); abort($type);
} }
} }
@ -928,9 +957,9 @@ class Translator extends \PhpAot\Core\Translator
$className = $this->parseIdentifier($expr->class); $className = $this->parseIdentifier($expr->class);
$args = $expr->args; $args = $expr->args;
if (empty($args)) { if (empty($args)) {
return 'new ' . $className . '()'; return 'php::newObject("' . $className . '")';
} else { } 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; break;
default: default:
debug($v2); abort($v2);
} }
} }
$this->namespace = ''; $this->namespace = '';
@ -981,7 +1010,7 @@ class Translator extends \PhpAot\Core\Translator
$code .= $this->parseFunctionDef($v) . PHP_EOL; $code .= $this->parseFunctionDef($v) . PHP_EOL;
break; break;
default: default:
debug($v); abort($v);
} }
} }
$this->class = ''; $this->class = '';
@ -1081,4 +1110,33 @@ class Translator extends \PhpAot\Core\Translator
{ {
return 'php::exit(' . $this->parseIdentifier($node->expr) . ')'; 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); return $this->parseBinOp($attr);
default: default:
var_dump(__METHOD__, __LINE__); var_dump(__METHOD__, __LINE__);
debug($attr); abort($attr);
} }
} }
@ -106,7 +106,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Attribute': case 'Attribute':
return $this->parseAttribute($fn->value) . '->' . $fn->attr; return $this->parseAttribute($fn->value) . '->' . $fn->attr;
default: default:
debug($fn); abort($fn);
} }
} }
@ -240,7 +240,7 @@ class Translator extends \PhpAot\Core\Translator
case 'GeneratorExp': case 'GeneratorExp':
return $this->parseGeneratorExp($value); return $this->parseGeneratorExp($value);
default: default:
debug($value); abort($value);
break; break;
} }
} }
@ -257,7 +257,7 @@ class Translator extends \PhpAot\Core\Translator
$_args[] = $slice->step ? $this->parseTarget($slice->step) : 'null'; $_args[] = $slice->step ? $this->parseTarget($slice->step) : 'null';
return 'PyCore::slice(' . implode(', ', $_args) . ')'; return 'PyCore::slice(' . implode(', ', $_args) . ')';
} else { } else {
debug($slice); abort($slice);
} }
} }
@ -298,7 +298,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Not': case 'Not':
return '!' . $operand; return '!' . $operand;
default: default:
debug($target); abort($target);
break; break;
} }
break; break;
@ -329,7 +329,7 @@ class Translator extends \PhpAot\Core\Translator
case 'ListComp': case 'ListComp':
return $this->parseListComp($target); return $this->parseListComp($target);
default: default:
debug($target); abort($target);
break; break;
} }
} }
@ -386,7 +386,7 @@ class Translator extends \PhpAot\Core\Translator
if ($test->ops) { if ($test->ops) {
$ops = $test->ops; $ops = $test->ops;
if (count($ops) != 1) { if (count($ops) != 1) {
debug($test); abort($test);
} }
$op = $ops[0]->_type; $op = $ops[0]->_type;
$comparators = $test->comparators; $comparators = $test->comparators;
@ -458,7 +458,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Attribute': case 'Attribute':
return $this->parseAttribute($iter); return $this->parseAttribute($iter);
default: default:
debug($iter); abort($iter);
} }
} }
@ -475,7 +475,7 @@ class Translator extends \PhpAot\Core\Translator
return $value . '[' . $this->parseSlice($node->slice) . ']'; return $value . '[' . $this->parseSlice($node->slice) . ']';
} }
} else { } else {
debug($node); abort($node);
} }
} }
@ -603,7 +603,7 @@ class Translator extends \PhpAot\Core\Translator
$line = $this->parseCall($node) . ';'; $line = $this->parseCall($node) . ';';
break; break;
default: default:
debug($node); abort($node);
$line = ''; $line = '';
break; break;
} }
@ -772,7 +772,7 @@ class Translator extends \PhpAot\Core\Translator
$code = '[' . PHP_EOL; $code = '[' . PHP_EOL;
foreach ($dict->values as $k => $v) { foreach ($dict->values as $k => $v) {
if (empty($dict->keys[$k])) { if (empty($dict->keys[$k])) {
debug($v); abort($v);
} }
$key = $dict->keys[$k]; $key = $dict->keys[$k];
$this->indentLevel++; $this->indentLevel++;
@ -791,7 +791,7 @@ class Translator extends \PhpAot\Core\Translator
case 'Or': case 'Or':
return $this->parseOr($value->values); return $this->parseOr($value->values);
default: default:
debug($value); abort($value);
break; break;
} }
} }
@ -943,7 +943,7 @@ class Translator extends \PhpAot\Core\Translator
$expr = $this->parseValue($value->value); $expr = $this->parseValue($value->value);
if ($value->format_spec and $value->format_spec->_type == 'JoinedStr') { if ($value->format_spec and $value->format_spec->_type == 'JoinedStr') {
if (count($value->format_spec->values) != 1) { if (count($value->format_spec->values) != 1) {
debug($value); abort($value);
} }
$format = $value->format_spec->values[0]->value; $format = $value->format_spec->values[0]->value;
if ($format[0] == '.' and $format[-1] == 'f') { if ($format[0] == '.' and $format[-1] == 'f') {
@ -974,6 +974,6 @@ class Translator extends \PhpAot\Core\Translator
private function parseGeneratorExp($value) private function parseGeneratorExp($value)
{ {
debug($value); abort($value);
} }
} }

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

Loading…
Cancel
Save