fix(generator): ensure all generated C values are returned as strings

- Modified genCValue method to always return string type instead of mixed
- Changed float values to be cast to string in genCValue method
- Updated boolean values to return '1'/'0' strings instead of integers
- Fixed getInternalScalarConstantValue return type to string only
- Added explicit string casting for literal string keys in Translator
- Added comprehensive tests for C value generation ensuring source code strings
- Added comments explaining integer-string array key handling in literalStrings
pull/45/head
韩天峰 4 weeks ago
parent 8dd33c1400
commit 9d1ba7ee7a
  1. 14
      phpunit/src/CompilerBaseApiTest.php
  2. 6
      src/Generator/Utils.php
  3. 2
      src/Parser/ConstantExpressionTrait.php
  4. 5
      src/Translator.php

@ -216,6 +216,20 @@ class CompilerBaseApiTest extends TestCase
$this->assertSame('ZEND_LONG_MIN', $this->invokeMethod('genCValue', PHP_INT_MIN)); $this->assertSame('ZEND_LONG_MIN', $this->invokeMethod('genCValue', PHP_INT_MIN));
} }
public function testGeneratedCValuesAreAlwaysSourceCodeStrings(): void
{
$this->assertSame((string) M_E, $this->invokeMethod('genCValue', M_E));
$this->assertSame('1', $this->invokeMethod('genCValue', true));
$this->assertSame('0', $this->invokeMethod('genCValue', false));
$code = $this->invokeMethod(
'parseConstFetch',
new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('M_E'))
);
$this->assertIsString($code);
$this->assertSame((string) M_E, $code);
}
public function testWindowsIntegerLiteralSuffixForInternalConstants(): void public function testWindowsIntegerLiteralSuffixForInternalConstants(): void
{ {
$this->setPropertyValue('platform', new Windows()); $this->setPropertyValue('platform', new Windows());

@ -25,16 +25,16 @@ trait Utils
return $value . $this->getPlatform()->getIntegerLiteralSuffix(); return $value . $this->getPlatform()->getIntegerLiteralSuffix();
} }
protected function genCValue(mixed $value): mixed protected function genCValue(mixed $value): string
{ {
if (is_int($value)) { if (is_int($value)) {
return $this->genIntegerLiteral($value); return $this->genIntegerLiteral($value);
} }
if (is_float($value)) { if (is_float($value)) {
return $value; return (string) $value;
} }
if (is_bool($value)) { if (is_bool($value)) {
return $value ? 1 : 0; return $value ? '1' : '0';
} }
if (is_string($value)) { if (is_string($value)) {
return $this->genCharPtr($value); return $this->genCharPtr($value);

@ -147,7 +147,7 @@ trait ConstantExpressionTrait
return $this->isInternalConstant($name) && is_scalar($this->internalConstants[$name]); return $this->isInternalConstant($name) && is_scalar($this->internalConstants[$name]);
} }
protected function getInternalScalarConstantValue(string $name): string|int|float protected function getInternalScalarConstantValue(string $name): string
{ {
$value = $this->internalConstants[$name]; $value = $this->internalConstants[$name];
if (is_int($value)) { if (is_int($value)) {

@ -822,7 +822,10 @@ CODE;
if ($this->literalStrings) { if ($this->literalStrings) {
$code .= Type::STR . ' ' . self::LITERAL_STRINGS . '[] = {' . PHP_EOL; $code .= Type::STR . ' ' . self::LITERAL_STRINGS . '[] = {' . PHP_EOL;
foreach ($this->literalStrings as $str => $index) { foreach ($this->literalStrings as $str => $index) {
$code .= Type::STR . '{ZEND_STRL("' . $this->escapeString($str) . '"), true}, // [' . $index . ']' . PHP_EOL; // PHP converts canonical integer-string array keys (for
// example "0" and "-1") to int. literalStrings only accepts
// strings, so restore the original key type at this boundary.
$code .= Type::STR . '{ZEND_STRL("' . $this->escapeString((string) $str) . '"), true}, // [' . $index . ']' . PHP_EOL;
} }
$code .= '};' . PHP_EOL . PHP_EOL; $code .= '};' . PHP_EOL . PHP_EOL;
} else { } else {

Loading…
Cancel
Save