fix(compiler): preserve dynamic arithmetic result types (#133) --skip-tests
* fix(compiler): preserve dynamic arithmetic result types * fix(compiler): preserve referenced arithmetic result typesmaster
parent
cff557b649
commit
4f61dda6c3
4 changed files with 190 additions and 0 deletions
@ -0,0 +1,13 @@ |
||||
<?php |
||||
function dynamicResult(array $values, int $divisor): array |
||||
{ |
||||
return [$values['x'] / $divisor]; |
||||
} |
||||
function nativeIntResult(int $left, int $right): int |
||||
{ |
||||
return $left / $right; |
||||
} |
||||
function nativeFloatResult(float $left, float $right): float |
||||
{ |
||||
return $left / $right; |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
<?php |
||||
|
||||
use TypePhp\CompilerTest; |
||||
|
||||
final class DynamicArithmeticResultTest extends \BaseTest |
||||
{ |
||||
public function testDynamicResultRemainsBoxedAndNativeArithmeticStaysNative(): void |
||||
{ |
||||
global $translator; |
||||
|
||||
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH); |
||||
$translator = $compiler; |
||||
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/dynamic-arithmetic-result.php'; |
||||
$compiler->addFiles([$source]); |
||||
$compiler->prepareFile($source); |
||||
$code = file_get_contents($compiler->convertFile($source)); |
||||
self::assertIsString($code); |
||||
$dynamic = substr($code, strpos($code, 'php_dynamicresult(')); |
||||
$dynamic = substr($dynamic, 0, strpos($dynamic, "\n}") + 3); |
||||
self::assertDoesNotMatchRegularExpression('/php::toInt\([^;]*divisor/s', $dynamic); |
||||
self::assertMatchesRegularExpression('/php::Int php_nativeintresult\(php::Int left, php::Int right\)/', $code); |
||||
self::assertMatchesRegularExpression('/php::Float php_nativefloatresult\(php::Float left, php::Float right\)/', $code); |
||||
foreach (['php_nativeintresult(', 'php_nativefloatresult('] as $name) { |
||||
$body = substr($code, strpos($code, $name)); |
||||
$body = substr($body, 0, strpos($body, "\n}") + 3); |
||||
self::assertStringContainsString('((left) / (right))', $body); |
||||
self::assertStringNotContainsString('php::Var', $body); |
||||
} |
||||
self::assertMatchesRegularExpression('/php::Var (tmp_var_\d+);.*?\1 = \(+tmp_var_\d+\) \/ \(divisor\)/s', $dynamic); |
||||
} |
||||
} |
||||
@ -0,0 +1,139 @@ |
||||
--TEST-- |
||||
Dynamic arithmetic values keep PHP numeric semantics in nested array returns |
||||
--FILE-- |
||||
<?php |
||||
function dynamic_arithmetic(array $values, int $n): array |
||||
{ |
||||
return [ |
||||
'forward' => [ |
||||
'add' => $values['float'] + $n, |
||||
'subtract' => $values['float'] - $n, |
||||
'multiply' => $values['float'] * $n, |
||||
'divide' => $values['float'] / $n, |
||||
'integer_divide' => $values['integer'] / $n, |
||||
], |
||||
'reverse' => [ |
||||
'add' => $n + $values['float'], |
||||
'subtract' => $n - $values['float'], |
||||
'multiply' => $n * $values['float'], |
||||
'divide' => $n / $values['float'], |
||||
], |
||||
]; |
||||
} |
||||
|
||||
function dynamic_return(mixed $value, int $n): mixed |
||||
{ |
||||
return $value / $n; |
||||
} |
||||
|
||||
function dynamic_nested(array $values, int $n): mixed |
||||
{ |
||||
return ($values['float'] + $n) * $n; |
||||
} |
||||
|
||||
function dynamic_kinds(mixed $value, int $n, float $fraction): array |
||||
{ |
||||
return [$value / $n, $value + $fraction, $fraction - $value, |
||||
$value ** $n, $value % $n, $value << $n, $value >> $n, |
||||
$value & $n, $value | $n, $value ^ $n]; |
||||
} |
||||
|
||||
function divisor(): int |
||||
{ |
||||
return 2; |
||||
} |
||||
|
||||
function dynamic_reference_arithmetic(): array |
||||
{ |
||||
$values = [5.5]; |
||||
foreach ($values as &$value) { |
||||
return [ |
||||
'forward' => [$value / divisor(), $value + divisor(), $value - divisor(), $value * divisor()], |
||||
'reverse' => [divisor() / $value, divisor() + $value, divisor() - $value, divisor() * $value], |
||||
]; |
||||
} |
||||
} |
||||
|
||||
function main() |
||||
{ |
||||
var_dump(dynamic_arithmetic(['float' => 5.5, 'integer' => 5], 2)); |
||||
var_dump(dynamic_return(5.5, 2), dynamic_nested(['float' => 5.5], 2)); |
||||
var_dump(dynamic_kinds(4, 2, 0.5)); |
||||
var_dump(dynamic_reference_arithmetic()); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(2) { |
||||
["forward"]=> |
||||
array(5) { |
||||
["add"]=> |
||||
float(7.5) |
||||
["subtract"]=> |
||||
float(3.5) |
||||
["multiply"]=> |
||||
float(11) |
||||
["divide"]=> |
||||
float(2.75) |
||||
["integer_divide"]=> |
||||
float(2.5) |
||||
} |
||||
["reverse"]=> |
||||
array(4) { |
||||
["add"]=> |
||||
float(7.5) |
||||
["subtract"]=> |
||||
float(-3.5) |
||||
["multiply"]=> |
||||
float(11) |
||||
["divide"]=> |
||||
float(0.36363636363636365) |
||||
} |
||||
} |
||||
float(2.75) |
||||
float(15) |
||||
array(10) { |
||||
[0]=> |
||||
int(2) |
||||
[1]=> |
||||
float(4.5) |
||||
[2]=> |
||||
float(-3.5) |
||||
[3]=> |
||||
int(16) |
||||
[4]=> |
||||
int(0) |
||||
[5]=> |
||||
int(16) |
||||
[6]=> |
||||
int(1) |
||||
[7]=> |
||||
int(0) |
||||
[8]=> |
||||
int(6) |
||||
[9]=> |
||||
int(6) |
||||
} |
||||
array(2) { |
||||
["forward"]=> |
||||
array(4) { |
||||
[0]=> |
||||
float(2.75) |
||||
[1]=> |
||||
float(7.5) |
||||
[2]=> |
||||
float(3.5) |
||||
[3]=> |
||||
float(11) |
||||
} |
||||
["reverse"]=> |
||||
array(4) { |
||||
[0]=> |
||||
float(0.36363636363636365) |
||||
[1]=> |
||||
float(7.5) |
||||
[2]=> |
||||
float(-3.5) |
||||
[3]=> |
||||
float(11) |
||||
} |
||||
} |
||||
Loading…
Reference in new issue