refactor(parser): change numeric parsing to always return strings

- Modified parseOrderedBinaryOperand and parseOrderedOperand to return string instead of float|int|string
- Changed parseNumericIdentifier to always return string values instead of numeric types
- Updated genCValue method to return string representations of boolean and float values
- Adjusted safeIndex method parameter type to accept int|string for size parameter
- Updated test cases to verify string output from numeric identifier parsing
- Modified generator test expectation to check Iterator instance instead of dumping object details
pull/45/head
韩天峰 4 weeks ago
parent 9d1ba7ee7a
commit b71ef5ca1a
  1. 16
      phpunit/src/CompilerBaseApiTest.php
  2. 6
      phpunit/src/Generator/UtilsTest.php
  3. 6
      phpunit/src/SymbolTest.php
  4. 8
      src/CompilerBase.php
  5. 2
      src/Generator/Symbol.php
  6. 4
      src/Parser/BinaryOpTrait.php
  7. 33
      tests/compiler/generator/generator-foreach-yield.phpt

@ -230,6 +230,22 @@ class CompilerBaseApiTest extends TestCase
$this->assertSame((string) M_E, $code); $this->assertSame((string) M_E, $code);
} }
public function testNumericStringIdentifiersGenerateSourceCodeStrings(): void
{
$this->assertSame(
(string) floatval('0.2'),
$this->invokeMethod('parseNumericIdentifier', new \PhpParser\Node\Scalar\String_('0.2'))
);
$this->assertSame(
'42',
$this->invokeMethod('parseNumericIdentifier', new \PhpParser\Node\Scalar\String_('42'))
);
$this->assertSame(
'0',
$this->invokeMethod('parseNumericIdentifier', new \PhpParser\Node\Scalar\String_('0'))
);
}
public function testWindowsIntegerLiteralSuffixForInternalConstants(): void public function testWindowsIntegerLiteralSuffixForInternalConstants(): void
{ {
$this->setPropertyValue('platform', new Windows()); $this->setPropertyValue('platform', new Windows());

@ -49,13 +49,13 @@ class UtilsTest extends TestCase
public function testGenCValueFloat(): void public function testGenCValueFloat(): void
{ {
$result = $this->invokeMethod('genCValue', 3.14); $result = $this->invokeMethod('genCValue', 3.14);
$this->assertSame(3.14, $result); $this->assertSame((string) 3.14, $result);
} }
public function testGenCValueBool(): void public function testGenCValueBool(): void
{ {
$this->assertSame(1, $this->invokeMethod('genCValue', true)); $this->assertSame('1', $this->invokeMethod('genCValue', true));
$this->assertSame(0, $this->invokeMethod('genCValue', false)); $this->assertSame('0', $this->invokeMethod('genCValue', false));
} }
public function testGenCValueString(): void public function testGenCValueString(): void

@ -68,4 +68,10 @@ class SymbolTest extends TestCase
$result = Symbol::safeIndex('i', 'count'); $result = Symbol::safeIndex('i', 'count');
$this->assertEquals('php::safeIndex(i, count)', $result); $this->assertEquals('php::safeIndex(i, count)', $result);
} }
public function testSafeIndexWithFixedIntegerSize(): void
{
$result = Symbol::safeIndex('i', 10);
$this->assertEquals('php::safeIndex(i, 10)', $result);
}
} }

@ -1730,17 +1730,17 @@ class CompilerBase implements PropertyAccessContext
/** /**
* 尽可能转为数字,优先级 浮点 > 整数 > 字符串. * 尽可能转为数字,优先级 浮点 > 整数 > 字符串.
*/ */
protected function parseNumericIdentifier(NodeAbstract $expr): float|int|string protected function parseNumericIdentifier(NodeAbstract $expr): string
{ {
if ($expr->getType() === 'Scalar_String') { if ($expr->getType() === 'Scalar_String') {
if ($this->isFloatStr($expr->value)) { if ($this->isFloatStr($expr->value)) {
return floatval($expr->value); return (string) floatval($expr->value);
} }
if ($this->isIntStr($expr->value)) { if ($this->isIntStr($expr->value)) {
return intval($expr->value); return (string) intval($expr->value);
} }
if ($expr->value === '0') { if ($expr->value === '0') {
return 0; return '0';
} }
} }

@ -62,7 +62,7 @@ class Symbol
return 'php::ArgList'; return 'php::ArgList';
} }
public static function safeIndex(string $index, string $size): string public static function safeIndex(string $index, int|string $size): string
{ {
return "php::safeIndex({$index}, {$size})"; return "php::safeIndex({$index}, {$size})";
} }

@ -516,12 +516,12 @@ trait BinaryOpTrait
|| $expr instanceof Expr\Eval_; || $expr instanceof Expr\Eval_;
} }
protected function parseOrderedBinaryOperand(NodeAbstract $expr): float|int|string protected function parseOrderedBinaryOperand(NodeAbstract $expr): string
{ {
return $this->parseOrderedOperand($expr, true); return $this->parseOrderedOperand($expr, true);
} }
protected function parseOrderedOperand(NodeAbstract $expr, bool $numeric): float|int|string protected function parseOrderedOperand(NodeAbstract $expr, bool $numeric): string
{ {
$this->assertExprCanBeUsedAsValue($expr, 'operand'); $this->assertExprCanBeUsedAsValue($expr, 'operand');
if (!$this->shouldMaterializeOrderedOperand($expr)) { if (!$this->shouldMaterializeOrderedOperand($expr)) {

@ -6,7 +6,7 @@ generator re-yielding array elements via foreach with \Generator return type
function main() function main()
{ {
$g = test([1, 2, 3]); $g = test([1, 2, 3]);
var_dump($g); var_dump($g instanceof \Iterator);
foreach ($g as $value) foreach ($g as $value)
{ {
var_dump($value); var_dump($value);
@ -23,35 +23,8 @@ function test(array $array): \Generator
// main(); // main();
?> ?>
--EXPECTF-- --EXPECT--
object(FiberGenerator)#%d (9) { bool(true)
["callback":"FiberGenerator":private]=>
object(Closure)#%d (2) {
["function"]=>
string(19) "stdClass::{closure}"
["this"]=>
object(stdClass)#%d (1) {
["box"]=>
resource(%d) of type (php::box)
}
}
["fiber":"FiberGenerator":private]=>
NULL
["current":"FiberGenerator":private]=>
NULL
["key":"FiberGenerator":private]=>
NULL
["valid":"FiberGenerator":private]=>
bool(false)
["state":"FiberGenerator":private]=>
int(0)
["yield_count":"FiberGenerator":private]=>
int(0)
["next_index":"FiberGenerator":private]=>
int(0)
["return_value":"FiberGenerator":private]=>
NULL
}
int(1) int(1)
int(2) int(2)
int(3) int(3)

Loading…
Cancel
Save