test(compiler): 添加大数类型运算测试和自增自减操作限制

- 添加 Decimal 算术运算测试用例
- 添加 BigInt 复合赋值运算测试用例
- 添加 Decimal 复合赋值运算测试用例
- 添加 Decimal 比较和转换测试用例
- 添加 BigInt 二元运算符测试用例
- 添加 Decimal 运算符重载测试用例
- 添加 Decimal 一元负号测试用例
- 在编译器中实现对 BigInt、Decimal 和 BigFloat 类型的自增自减操作限制
- 添加 PHPUnit 测试验证自增自减操作错误提示
- 为 BigInt 和 Decimal 类型禁用 ++ 和 -- 操作符
pull/1/head
韩天峰 3 months ago
parent a459a8bd95
commit 69e4386454
  1. 8
      phpunit/code/bigint-post-inc.php
  2. 8
      phpunit/code/bigint-pre-inc.php
  3. 8
      phpunit/code/decimal-pre-dec.php
  4. 15
      phpunit/src/AssignOpTest.php
  5. 13
      src/Php/CompilerBase.php
  6. 46
      tests/aot/bigint/assign_op.phpt
  7. 49
      tests/aot/bigint/operator.phpt
  8. 36
      tests/aot/decimal/arithmetic.phpt
  9. 45
      tests/aot/decimal/assign_op.phpt
  10. 26
      tests/aot/decimal/compare.phpt
  11. 51
      tests/aot/decimal/operator.phpt
  12. 21
      tests/aot/decimal/unary_minus.phpt

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
use native_types;
function main()
{
$a = std::bigInt(100);
$a++;
}

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
use native_types;
function main()
{
$a = std::bigInt(100);
++$a;
}

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
use native_types;
function main()
{
$a = std::decimal("100");
--$a;
}

@ -11,4 +11,19 @@ class AssignOpTest extends \BaseTest
{
$this->exec('Cannot concat string to array', 'assign-op-concat-array.php');
}
public function testBigIntPreInc()
{
$this->exec('Cannot use ++ on php::BigInt', 'bigint-pre-inc.php');
}
public function testBigIntPostInc()
{
$this->exec('Cannot use ++ on php::BigInt', 'bigint-post-inc.php');
}
public function testDecimalPreDec()
{
$this->exec('Cannot use -- on php::Decimal', 'decimal-pre-dec.php');
}
}

@ -3018,6 +3018,10 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function parsePreInc(Expr\PreInc $expr): string
{
$type = $this->detectVarType($expr->var);
if ($type === self::TYPE_BIGINT || $type === self::TYPE_DECIMAL || $type === self::TYPE_BIGFLOAT) {
$this->fatalError($expr, 'Cannot use ++ on ' . $type . '. Use += 1 instead (Big* types are immutable).');
}
return '++' . $this->parseIdentifier($expr->var);
}
@ -3721,6 +3725,11 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($this->isVarExpr($expr->var) and !$this->hasVar($var)) {
$this->errorUndefinedVariable($expr->var);
}
$type = $this->detectVarType($expr->var);
if ($type === self::TYPE_BIGINT || $type === self::TYPE_DECIMAL || $type === self::TYPE_BIGFLOAT) {
$opName = $op === '+' ? '++' : '--';
$this->fatalError($expr, "Cannot use {$opName} on {$type}. Use " . ($op === '+' ? '+= 1' : '-= 1') . ' instead (Big* types are immutable).');
}
return $var . str_repeat($op, 2);
}
if ($this->isStaticPropertyFetch($expr->var)) {
@ -3828,6 +3837,10 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function parsePreDec(Expr\PreDec $expr): string
{
$type = $this->detectVarType($expr->var);
if ($type === self::TYPE_BIGINT || $type === self::TYPE_DECIMAL || $type === self::TYPE_BIGFLOAT) {
$this->fatalError($expr, 'Cannot use -- on ' . $type . '. Use -= 1 instead (Big* types are immutable).');
}
return '--' . $this->parseIdentifier($expr->var);
}

@ -0,0 +1,46 @@
--TEST--
BigInt compound assignment operators (+=, -=, *=, /=, %=)
--FILE--
<?php
declare(strict_types=1);
use native_types;
function main(): void {
// BigInt +=
$a = std::bigInt(100);
$a += 50;
echo $a->toString(); echo "\n";
// BigInt += with BigInt
$b = std::bigInt("99999999999999999999");
$b += std::bigInt(1);
echo $b->toString(); echo "\n";
// BigInt -=
$c = std::bigInt(1000);
$c -= 300;
echo $c->toString(); echo "\n";
// BigInt *=
$d = std::bigInt(100);
$d *= 5;
echo $d->toString(); echo "\n";
// BigInt /=
$e = std::bigInt(100);
$e /= 3;
echo $e->toString(); echo "\n";
// BigInt %=
$f = std::bigInt(100);
$f %= 7;
echo $f->toString(); echo "\n";
}
?>
--EXPECT--
150
100000000000000000000
700
500
33
2

@ -0,0 +1,49 @@
--TEST--
BigInt binary operators (+, -, *, /, %) and unary minus
--FILE--
<?php
declare(strict_types=1);
use native_types;
function main(): void {
$a = std::bigInt(100);
// BigInt + Int
$b = $a + 50;
echo $b->toString(); echo "\n";
// Int + BigInt
$c = 200 + $a;
echo $c->toString(); echo "\n";
// BigInt - Int
$d = $a - 30;
echo $d->toString(); echo "\n";
// BigInt * Int
$e = $a * 5;
echo $e->toString(); echo "\n";
// BigInt / Int
$f = $a / 3;
echo $f->toString(); echo "\n";
// BigInt % Int
$g = $a % 7;
echo $g->toString(); echo "\n";
// BigInt ** Int
$h = std::bigInt(2) ** 10;
echo $h->toString(); echo "\n";
// Unary minus
$i = -$a;
echo $i->toString(); echo "\n";
echo (-$i)->toString(); echo "\n";
}
?>
--EXPECT--
150
300
70
500
33
2
1024
-100
100

@ -0,0 +1,36 @@
--TEST--
Decimal arithmetic operations
--FILE--
<?php
declare(strict_types=1);
use native_types;
function main(): void {
$a = std::decimal("100.50");
$b = std::decimal("50.25");
// Decimal + Decimal
echo $a->add($b)->toString(); echo "\n";
// Decimal - Decimal
echo $a->sub($b)->toString(); echo "\n";
// Decimal * Decimal
echo $a->mul($b)->toString(); echo "\n";
// Decimal / Decimal
echo $a->div($b)->toString(); echo "\n";
// Decimal mod
$c = std::decimal("17.5");
echo $c->mod(std::decimal("5.0"))->toString(); echo "\n";
// Decimal neg
echo $a->neg()->toString(); echo "\n";
// Decimal abs
echo $a->neg()->abs()->toString(); echo "\n";
}
?>
--EXPECT--
150.75
50.25
5050.1250
2
2.5
-100.50
100.50

@ -0,0 +1,45 @@
--TEST--
Decimal compound assignment operators (+=, -=, *=, /=, %=)
--FILE--
<?php
declare(strict_types=1);
use native_types;
function main(): void {
// Decimal +=
$a = std::decimal("100.50");
$a += 25.25;
echo $a->toString(); echo "\n";
// Decimal += with int
$a += 100;
echo $a->toString(); echo "\n";
// Decimal -=
$b = std::decimal("500.00");
$b -= 123.45;
echo $b->toString(); echo "\n";
// Decimal *=
$c = std::decimal("50.5");
$c *= 2;
echo $c->toString(); echo "\n";
// Decimal /=
$d = std::decimal("100.00");
$d /= 4;
echo $d->toString(); echo "\n";
// Decimal %=
$e = std::decimal("17.5");
$e %= 5.0;
echo $e->toString(); echo "\n";
}
?>
--EXPECT--
125.75
225.75
376.55
101.0
25.00
2.5

@ -0,0 +1,26 @@
--TEST--
Decimal comparison and conversions
--FILE--
<?php
declare(strict_types=1);
use native_types;
function main(): void {
$a = std::decimal("123.456");
$b = std::decimal("789.012");
echo "cmp(a,b)="; echo $a->cmp($b); echo "\n";
echo "cmp(b,a)="; echo $b->cmp($a); echo "\n";
echo "cmp(a,a)="; echo $a->cmp($a); echo "\n";
// conversion
echo $a->toInt(); echo "\n";
echo $a->toString(); echo "\n";
}
?>
--EXPECT--
cmp(a,b)=-1
cmp(b,a)=1
cmp(a,a)=0
123
123.456

@ -0,0 +1,51 @@
--TEST--
Decimal operator overloading (+, -, *, /, %) and comparisons
--FILE--
<?php
declare(strict_types=1);
use native_types;
function main(): void {
$dec = std::decimal("100.25");
// Decimal + Int
$a = $dec + 50;
echo $a->toString(); echo "\n";
// Int + Decimal
$b = 200 + $dec;
echo $b->toString(); echo "\n";
// Decimal - Float
$c = $dec - 0.25;
echo $c->toString(); echo "\n";
// Decimal * Int
$d = $dec * 4;
echo $d->toString(); echo "\n";
// Decimal / Int
$e = $dec / 5;
echo $e->toString(); echo "\n";
// Decimal % Int
$f = $dec % 7;
echo $f->toString(); echo "\n";
// Comparisons
echo (int)($dec > 50); echo "\n";
echo (int)($dec < 200); echo "\n";
echo (int)($dec == 100.25); echo "\n";
echo (int)($dec != 100); echo "\n";
echo (int)($dec <= 100.25); echo "\n";
echo (int)($dec >= 100); echo "\n";
}
?>
--EXPECT--
150.25
300.25
100.00
401.00
20.05
2.25
1
1
1
1
1
1

@ -0,0 +1,21 @@
--TEST--
Decimal unary minus operator
--FILE--
<?php
declare(strict_types=1);
use native_types;
function main(): void {
$a = std::decimal("123.456");
// Unary minus
$b = -$a;
echo $b->toString(); echo "\n";
// Double minus
$c = -$b;
echo $c->toString(); echo "\n";
}
?>
--EXPECT--
-123.456
123.456
Loading…
Cancel
Save