数值系统 单元测试

pull/1/head
韩天峰 8 months ago
parent 204908f6e9
commit 0dbb12812d
  1. 97
      src/Php/Translator.php
  2. 20
      tests/zend/add_005.phpt
  3. 39
      tests/zend/and_001.phpt
  4. 20
      tests/zend/array_hash_zero.phpt
  5. 32
      tests/zend/div_001.phpt
  6. 18
      tests/zend/double_array_cast.phpt

@ -48,7 +48,9 @@ class Translator extends \PhpAot\Core\Translator
private array $internalFunctions = [];
private int $optimizeLevel = 5;
private int $optimizeLevel = 0;
private int $floatPrecision = 17;
private bool $debugInfo = true;
private bool $verbose = false;
private string $file;
private string $dir;
@ -406,6 +408,8 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseAssignOpConcat($expr);
case 'Expr_AssignOp_ShiftRight':
return $this->parseAssignOpShiftRight($expr);
case 'Expr_AssignOp_BitwiseAnd':
return $this->parseAssignOpBitwiseAnd($expr);
case 'Expr_BinaryOp_Mul':
return $this->parseBinaryOpMul($expr);
case 'Expr_BinaryOp_Concat':
@ -480,6 +484,8 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseUnaryPlus($expr);
case 'InterpolatedStringPart':
return $this->parseInterpolatedStringPart($expr);
case 'Expr_Cast_Array':
return $this->parseCastArray($expr);
case 'Expr_Exit':
return $this->parseExit($expr);
default:
@ -597,11 +603,11 @@ class Translator extends \PhpAot\Core\Translator
if ($leftType === self::TYPE_FLOAT) {
$rightExpr = $this->convertExprType($rightExpr, self::TYPE_FLOAT, $rightType);
} elseif ($rightType === self::TYPE_FLOAT) {
$leftExpr = $this->convertExprType($leftExpr, self::TYPE_FLOAT, $leftType);
$leftExpr = $this->convertExprType($leftExpr, $leftType, self::TYPE_FLOAT);
} elseif ($leftType === self::TYPE_INT) {
$rightExpr = $this->convertExprType($rightExpr, self::TYPE_INT, $rightType);
} elseif ($rightType === self::TYPE_INT) {
$leftExpr = $this->convertExprType($leftExpr, self::TYPE_INT, $leftType);
$leftExpr = $this->convertExprType($leftExpr, $leftType, self::TYPE_INT);
}
return $leftExpr . ' ' . $op . ' ' . $rightExpr;
@ -667,14 +673,28 @@ class Translator extends \PhpAot\Core\Translator
case 'Expr_Cast_Float':
case 'Scalar_Float':
return self::TYPE_FLOAT;
case 'Expr_Cast_Bool':
case 'Scalar_Bool':
return self::TYPE_BOOL;
case 'Expr_Array':
return 'php::Array';
case 'Expr_BinaryOp_Plus':
case 'Expr_BinaryOp_Minus':
case 'Expr_BinaryOp_Mul':
case 'Expr_BinaryOp_Div':
case 'Expr_BinaryOp_Mod':
case 'Expr_BinaryOp_Pow':
case 'Expr_BinaryOp_ShiftLeft':
case 'Expr_BinaryOp_ShiftRight':
case 'Expr_BinaryOp_BitwiseAnd':
case 'Expr_BinaryOp_BitwiseOr':
case 'Expr_BinaryOp_BitwiseXor':
case 'Expr_BinaryOp_BooleanAnd':
$leftType = $this->detectExprType($expr->left);
$rightType = $this->detectExprType($expr->right);
if ($leftType === self::TYPE_FLOAT || $rightType === self::TYPE_FLOAT) {
return self::TYPE_FLOAT;
}
if ($leftType === self::TYPE_INT || $rightType === self::TYPE_INT) {
return self::TYPE_INT;
}
@ -713,34 +733,34 @@ class Translator extends \PhpAot\Core\Translator
return self::TYPE_ARRAY .'{}';
}
// 检查一下数组的赋值方式,是否为索引数组或关联数组,若是混杂模式,需要改为多行插入
$assocArray = (bool)$items[0]->key;
$mixed = false;
$assocArray = false;
foreach ($items as $item) {
if ($item->key) {
if (!$assocArray) {
$mixed = true;
break;
}
} else {
if ($assocArray) {
$mixed = true;
$assocArray = true;
break;
}
}
}
if ($mixed) {
abort($node);
} else {
$list = [];
$this->indentLevel++;
foreach ($items as $item) {
if ($item->key) {
$list[] = $this->getIndent() . '{ ' . $this->parseIdentifier($item->key) . ', ' .
self::TYPE_VAR . '(' . $this->parseIdentifier($item->value) . ') }';
/**
* 数组赋值语句
* $array = [1, 2, $x = 3];
*/
if ($item->value->getType() === 'Expr_Assign') {
$left = $item->value->var;
$this->beforeStmtLines[] = $this->getIndent() . $this->parseExpr($item->value) . ';';
$value = $this->parseIdentifier($left);
} else {
$value = $this->parseIdentifier($item->value);
}
if ($assocArray) {
// TODO 混杂模式数组赋值
$key = $item->key ? $this->parseIdentifier($item->key) : 'php::null';
$list[] = $this->getIndent() . '{ ' . $key . ', ' .
self::TYPE_VAR . '(' . $value . ') }';
} else {
$list[] = $this->getIndent() . self::TYPE_VAR . '(' . $value . ')';
}
}
@ -750,7 +770,6 @@ class Translator extends \PhpAot\Core\Translator
$this->getIndent() .
'}';
}
}
private function parseType($type)
{
@ -812,7 +831,11 @@ class Translator extends \PhpAot\Core\Translator
public function compileFile($file): void
{
$cmd = 'g++ -c ' . $file . ' -o ' . $file . '.o ' . $this->parseIncludes() . ' -O' . $this->optimizeLevel;
$cmd = 'g++ -c ' . $file . ' -o ' . $file . '.o ' . $this->parseIncludes();
$cmd .= ' -O' . $this->optimizeLevel;
if ($this->debugInfo) {
$cmd .= ' -g';
}
echo $cmd . PHP_EOL;
shell_exec($cmd);
}
@ -1128,6 +1151,16 @@ class Translator extends \PhpAot\Core\Translator
return 'php::to_float(' . $expr . ')';
}
private function convertStringExpr(string $expr): string
{
return 'php::to_string(' . $expr . ')';
}
private function convertArrayExpr(string $expr): string
{
return 'php::to_array(' . $expr . ')';
}
private function convertBoolExpr(string $expr): string
{
return 'php::to_bool(' . $expr . ')';
@ -1343,13 +1376,13 @@ class Translator extends \PhpAot\Core\Translator
private function convertExprType(string $expr, $leftType, $rightType): string
{
if ($leftType === self::TYPE_FLOAT && $rightType !== self::TYPE_FLOAT) {
if ($leftType === self::TYPE_FLOAT or $rightType === self::TYPE_FLOAT) {
return $this->convertFloatExpr($expr);
}
if ($leftType === self::TYPE_INT && $rightType !== self::TYPE_INT) {
if ($leftType === self::TYPE_INT or $rightType === self::TYPE_INT) {
return $this->convertIntExpr($expr);
}
if ($leftType === self::TYPE_BOOL && $rightType !== self::TYPE_BOOL) {
if ($leftType === self::TYPE_BOOL or $rightType === self::TYPE_BOOL) {
return $this->convertBoolExpr($expr);
}
return $expr;
@ -1569,6 +1602,7 @@ class Translator extends \PhpAot\Core\Translator
private function parseScalarFloat(Node $expr): string
{
$value = $expr->value;
if (is_nan($value)) {
return self::VALUE_NAN;
} elseif (is_infinite($value)) {
@ -1576,7 +1610,7 @@ class Translator extends \PhpAot\Core\Translator
} else if (floor($value) == $value && abs($value) < 1e15) {
return number_format($value, 1, '.', '');
} else {
return $value;
return sprintf('%.' . $this->floatPrecision . 'g', $value);
}
}
@ -1591,4 +1625,15 @@ class Translator extends \PhpAot\Core\Translator
}
}
}
private function parseAssignOpBitwiseAnd(mixed $node): string
{
$var = $this->parseIdentifier($node->var);
return $var . ' &= ' . $this->parseIdentifier($node->expr);
}
private function parseCastArray(mixed $expr): string
{
return $this->convertArrayExpr($this->parseIdentifier($expr->expr));
}
}

@ -0,0 +1,20 @@
--TEST--
adding integers to doubles
--FILE--
<?php
ini_set('precision', '14');
$i = 75636;
$d = 2834681123.123123;
$c = $i + $d;
var_dump($c);
$c = $d + $i;
var_dump($c);
echo "Done\n";
?>
--EXPECT--
float(2834756759.123123)
float(2834756759.123123)
Done

@ -0,0 +1,39 @@
--TEST--
bitwise AND and strings
--FILE--
<?php
$s = "123";
$s1 = "234";
var_dump($s & $s1);
$s = "test";
$s1 = "some";
var_dump($s & $s1);
$s = "test long";
$s1 = "some";
var_dump($s & $s1);
$s = "test";
$s1 = "some long";
var_dump($s & $s1);
$s = "test";
$s &= "some long";
var_dump($s);
echo "Done\n";
?>
--EXPECT--
string(3) "020"
string(4) "pead"
string(4) "pead"
string(4) "pead"
string(4) "pead"
Done

@ -0,0 +1,20 @@
--TEST--
Accept hashes being equal to zero
--FILE--
<?php
$hashes = [
"\x8e\x1a\x63\x0f\x61" => 32,
"\xf7\x17\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x6b\x03\x6a\x13\x63\x17\x6b\x1d\x67" => 64,
];
foreach ($hashes as $hash => $bits) {
var_dump($hashes[$hash], $bits);
}
?>
--EXPECT--
int(32)
int(32)
int(64)
int(64)

@ -0,0 +1,32 @@
--TEST--
dividing doubles
--INI--
precision=14
--FILE--
<?php
$d1 = 1.1;
$d2 = 434234.234;
$c = $d2 / $d1;
var_dump($c);
$d1 = 1.1;
$d2 = "434234.234";
$c = $d2 / $d1;
var_dump($c);
$d1 = "1.1";
$d2 = "434234.234";
$c = $d2 / $d1;
var_dump($c);
echo "Done\n";
?>
--EXPECT--
float(394758.39454545453)
float(394758.39454545453)
float(394758.39454545453)
Done

@ -0,0 +1,18 @@
--TEST--
Double array cast
--FILE--
<?php
$array = [1, 2, $x = 3];
var_dump((array) (array) $array);
?>
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
Loading…
Cancel
Save