Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions phpunit/code/float-constant-precision.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
/**
* This file is part of TypePHP(AOT).
*
* @link https://www.swoole.com/aot/
* @contact service@swoole.com
*/

function main(): void
{
var_dump(M_E);
var_dump(log(M_E));
}
6 changes: 4 additions & 2 deletions phpunit/src/CompilerBaseApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,9 @@ public function testWindowsIntegerLiteralSuffixForGeneratedCValues(): void

public function testGeneratedCValuesAreAlwaysSourceCodeStrings(): void
{
$this->assertSame((string) M_E, $this->invokeMethod('genCValue', M_E));
// A string cast here would follow the precision ini, so the assertion
// is that the emitted literal reads back as the same double.
$this->assertSame(M_E, (float) $this->invokeMethod('genCValue', M_E));
$this->assertSame('1', $this->invokeMethod('genCValue', true));
$this->assertSame('0', $this->invokeMethod('genCValue', false));

Expand All @@ -370,7 +372,7 @@ public function testGeneratedCValuesAreAlwaysSourceCodeStrings(): void
new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('M_E'))
);
$this->assertIsString($code);
$this->assertSame((string) M_E, $code);
$this->assertSame(M_E, (float) $code);
}

public function testNumericStringIdentifiersGenerateSourceCodeStrings(): void
Expand Down
50 changes: 50 additions & 0 deletions phpunit/src/FloatLiteralPrecisionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* This file is part of TypePHP(AOT).
*
* @link https://www.swoole.com/aot/
* @contact service@swoole.com
*/

namespace TypePhp\Tests;

use PHPUnit\Framework\TestCase;
use TypePhp\CompilerTest;

/**
* @internal
* @coversNothing
*/
class FloatLiteralPrecisionTest extends TestCase
{
public function testFloatConstantsIgnoreThePrecisionIniOfTheHost(): void
{
// precision=14 is the PHP default, so this is what most hosts compile
// with. The constant baked into the binary must not depend on it.
$previous = ini_set('precision', '14');

try {
$cpp = $this->compileToCpp('float-constant-precision.php');
} finally {
if ($previous !== false) {
ini_set('precision', $previous);
}
}

self::assertStringContainsString('2.7182818284590451', $cpp);
self::assertStringNotContainsString('2.718281828459)', $cpp);
}

private function compileToCpp(string $file): string
{
global $translator;

$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/' . $file;
$compiler->addFiles([$source]);
$compiler->prepareFile($source);

return file_get_contents($compiler->convertFile($source));
}
}
7 changes: 6 additions & 1 deletion phpunit/src/Generator/UtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ public function testGenCValueInt(): void
public function testGenCValueFloat(): void
{
$result = $this->invokeMethod('genCValue', 3.14);
$this->assertSame((string) 3.14, $result);

// The literal has to read back as the same double. Its exact spelling
// is not part of the contract, but a string cast would depend on the
// precision ini and lose digits.
$this->assertSame(3.14, (float) $result);
$this->assertMatchesRegularExpression('/[.E]/i', $result);
}

public function testGenCValueBool(): void
Expand Down
4 changes: 3 additions & 1 deletion src/Generator/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ protected function genCValue(mixed $value): string
return $this->genIntegerLiteral($value);
}
if (is_float($value)) {
return (string) $value;
// A string cast formats with the precision ini, which defaults to
// 14 and would bake a truncated constant into the binary.
return $this->genFloatLiteral($value);
}
if (is_bool($value)) {
return $value ? '1' : '0';
Expand Down