pull/1/head
parent
6ac8494173
commit
72b7ebdfae
8 changed files with 838 additions and 36 deletions
@ -0,0 +1,31 @@ |
||||
<?php |
||||
|
||||
namespace PhpAot\Php; |
||||
|
||||
use ReflectionFunction; |
||||
|
||||
class Reflection |
||||
{ |
||||
private static array $functions = []; |
||||
|
||||
static function getFunction(string $fn) |
||||
{ |
||||
if (!isset(self::$functions[$fn])) { |
||||
self::$functions[$fn] = new ReflectionFunction($fn); |
||||
} |
||||
return self::$functions[$fn]; |
||||
} |
||||
|
||||
static function getFunctionReturnType(string $fn): ?string |
||||
{ |
||||
$func = self::getFunction($fn); |
||||
$returnType = $func->getReturnType(); |
||||
if (!$returnType) { |
||||
return null; |
||||
} |
||||
if ($returnType instanceof \ReflectionUnionType) { |
||||
return null; |
||||
} |
||||
return $returnType->getName(); |
||||
} |
||||
} |
||||
@ -0,0 +1,147 @@ |
||||
--TEST-- |
||||
Arithmetic Operators |
||||
--FILE-- |
||||
<?php |
||||
// Test basic arithmetic operators |
||||
$a = 10; |
||||
$b = 3; |
||||
|
||||
// Addition |
||||
$add = $a + $b; |
||||
var_dump($add); |
||||
|
||||
// Subtraction |
||||
$sub = $a - $b; |
||||
var_dump($sub); |
||||
|
||||
// Multiplication |
||||
$mul = $a * $b; |
||||
var_dump($mul); |
||||
|
||||
// Division |
||||
$div = $a / floatval($b); |
||||
var_dump($div); |
||||
|
||||
// Modulus |
||||
$mod = $a % $b; |
||||
var_dump($mod); |
||||
|
||||
// Exponentiation (PHP 5.6+) |
||||
$pow = $a ** $b; |
||||
var_dump($pow); |
||||
|
||||
// Test with floats |
||||
$x = 10.5; |
||||
$y = 3.2; |
||||
|
||||
$float_add = $x + $y; |
||||
var_dump($float_add); |
||||
|
||||
echo "float_div:\n==========================\n"; |
||||
$float_div = $x / $y; |
||||
var_dump($float_div); |
||||
|
||||
// Test increment/decrement operators |
||||
$c = 5; |
||||
var_dump($c); // 5 |
||||
|
||||
$c++; // post-increment |
||||
var_dump($c); // 6 |
||||
|
||||
++$c; // pre-increment |
||||
var_dump($c); // 7 |
||||
|
||||
$c--; // post-decrement |
||||
var_dump($c); // 6 |
||||
|
||||
--$c; // pre-decrement |
||||
var_dump($c); // 5 |
||||
|
||||
// Test compound assignment operators |
||||
$d = 20; |
||||
$d += 5; |
||||
var_dump($d); // 25 |
||||
|
||||
echo "self plus:\n==========================\n"; |
||||
$float_div = $x / $y; |
||||
|
||||
$d -= 3; |
||||
var_dump($d); // 22 |
||||
|
||||
$d *= 2; |
||||
var_dump($d); // 44 |
||||
|
||||
echo "assign div:\n==========================\n"; |
||||
$d /= 4; |
||||
var_dump($d); // 11 |
||||
|
||||
$d %= 5; |
||||
var_dump($d); // 1 |
||||
|
||||
// Test operator precedence |
||||
$result1 = 2 + 3 * 4; // 2 + (3 * 4) = 14 |
||||
var_dump($result1); |
||||
|
||||
$result2 = (2 + 3) * 4; // (2 + 3) * 4 = 20 |
||||
var_dump($result2); |
||||
|
||||
$result3 = 10 - 3 + 2; // (10 - 3) + 2 = 9 |
||||
var_dump($result3); |
||||
|
||||
$result4 = 2 ** 3 ** 2; // 2 ** (3 ** 2) = 2 ** 9 = 512 |
||||
var_dump($result4); |
||||
|
||||
// Test with negative numbers |
||||
$neg_a = -10; |
||||
$neg_b = 3; |
||||
|
||||
$neg_result = $neg_a % $neg_b; |
||||
var_dump($neg_result); |
||||
|
||||
echo "neg float div:\n==========================\n"; |
||||
$neg_result2 = $neg_a / (float)$neg_b; |
||||
var_dump($neg_result2); |
||||
|
||||
// Test division by zero behavior (should not crash in this test) |
||||
$zero_div = 10 / 2; // Not dividing by zero, just testing normal division |
||||
var_dump($zero_div); |
||||
|
||||
// Test zero modulus behavior (should not crash in this test) |
||||
$zero_mod = 10 % 2; |
||||
var_dump($zero_mod); |
||||
?> |
||||
--EXPECT-- |
||||
int(13) |
||||
int(7) |
||||
int(30) |
||||
float(3.3333333333333335) |
||||
int(1) |
||||
int(1000) |
||||
float(13.7) |
||||
float_div: |
||||
========================== |
||||
float(3.28125) |
||||
int(5) |
||||
int(6) |
||||
int(7) |
||||
int(6) |
||||
int(5) |
||||
int(25) |
||||
self plus: |
||||
========================== |
||||
int(22) |
||||
int(44) |
||||
assign div: |
||||
========================== |
||||
int(11) |
||||
int(1) |
||||
int(14) |
||||
int(20) |
||||
int(9) |
||||
int(512) |
||||
int(-1) |
||||
neg float div: |
||||
========================== |
||||
float(-3.3333333333333335) |
||||
int(5) |
||||
int(0) |
||||
@ -0,0 +1,158 @@ |
||||
--TEST-- |
||||
Assignment Operators |
||||
--FILE-- |
||||
<?php |
||||
// Test assignment operators |
||||
$a = 10; |
||||
var_dump($a); |
||||
|
||||
// Addition assignment |
||||
$a += 5; |
||||
var_dump($a); |
||||
|
||||
// Subtraction assignment |
||||
$a -= 3; |
||||
var_dump($a); |
||||
|
||||
// Multiplication assignment |
||||
$a *= 2; |
||||
var_dump($a); |
||||
|
||||
// Division assignment |
||||
$a /= 4; |
||||
var_dump($a); |
||||
|
||||
// Modulus assignment |
||||
$a = 17; |
||||
$a %= 5; |
||||
var_dump($a); |
||||
|
||||
// Concatenation assignment |
||||
$str = "Hello"; |
||||
var_dump($str); |
||||
|
||||
$str .= " World"; |
||||
var_dump($str); |
||||
|
||||
// Test with different data types |
||||
$num = 100; |
||||
var_dump($num); |
||||
|
||||
$num /= 4; |
||||
var_dump($num); |
||||
|
||||
$num_float = floatval($num); |
||||
$num_float *= 1.5; |
||||
var_dump($num_float); |
||||
|
||||
// Test compound operations with expressions |
||||
$x = 5; |
||||
$x += 3 * 2; // $x = $x + (3 * 2) = 5 + 6 = 11 |
||||
var_dump($x); |
||||
|
||||
$y = 20; |
||||
$y -= 4 + 1; // $y = $y - (4 + 1) = 20 - 5 = 15 |
||||
var_dump($y); |
||||
|
||||
$z = 6; |
||||
$z *= 2 ** 3; // $z = $z * (2 ** 3) = 6 * 8 = 48 |
||||
var_dump($z); |
||||
|
||||
// Test assignment with function results |
||||
$numbers = [1, 2, 3, 4, 5]; |
||||
$sum = 0; |
||||
foreach ($numbers as $num) { |
||||
$sum += $num; |
||||
} |
||||
var_dump($sum); |
||||
|
||||
// Test multiple assignments |
||||
$a = $b = $c = 10; |
||||
var_dump($a); |
||||
var_dump($b); |
||||
var_dump($c); |
||||
|
||||
$a += 5; |
||||
$b *= 2; |
||||
$c -= 3; |
||||
var_dump($a); |
||||
var_dump($b); |
||||
var_dump($c); |
||||
|
||||
// Test assignment operators with arrays |
||||
$arr = [1, 2, 3]; |
||||
var_dump($arr); |
||||
|
||||
// Append to array using assignment |
||||
$arr[] = 4; |
||||
var_dump($arr); |
||||
|
||||
// String concatenation with variable |
||||
$greeting = "Hello"; |
||||
$name = "John"; |
||||
$greeting .= ", " . $name . "!"; |
||||
var_dump($greeting); |
||||
|
||||
// Test assignment in conditional context |
||||
$value = 5; |
||||
$result = $value *= 2; |
||||
var_dump($value); |
||||
var_dump($result); |
||||
|
||||
// Test increment and decrement in assignments |
||||
$counter = 10; |
||||
$pre_inc = ++$counter; // counter becomes 11, pre_inc gets 11 |
||||
var_dump($counter); |
||||
var_dump($pre_inc); |
||||
|
||||
$post_inc = $counter++; // post_inc gets 11, counter becomes 12 |
||||
var_dump($counter); |
||||
var_dump($post_inc); |
||||
?> |
||||
--EXPECT-- |
||||
int(10) |
||||
int(15) |
||||
int(12) |
||||
int(24) |
||||
int(6) |
||||
int(2) |
||||
string(5) "Hello" |
||||
string(11) "Hello World" |
||||
int(100) |
||||
int(25) |
||||
float(37.5) |
||||
int(11) |
||||
int(15) |
||||
int(48) |
||||
int(15) |
||||
int(10) |
||||
int(10) |
||||
int(10) |
||||
int(15) |
||||
int(20) |
||||
int(7) |
||||
array(3) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
int(2) |
||||
[2]=> |
||||
int(3) |
||||
} |
||||
array(4) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
int(2) |
||||
[2]=> |
||||
int(3) |
||||
[3]=> |
||||
int(4) |
||||
} |
||||
string(12) "Hello, John!" |
||||
int(10) |
||||
int(10) |
||||
int(11) |
||||
int(11) |
||||
int(12) |
||||
int(11) |
||||
@ -0,0 +1,177 @@ |
||||
--TEST-- |
||||
Comparison Operators |
||||
--FILE-- |
||||
<?php |
||||
// Test comparison operators |
||||
$a = 5; |
||||
$b = 10; |
||||
$c = 5; |
||||
|
||||
// Equal (==) |
||||
var_dump($a == $c); // true |
||||
var_dump($a == $b); // false |
||||
|
||||
// Identical (===) |
||||
var_dump($a === $c); // true |
||||
var_dump($a === "5"); // false |
||||
|
||||
// Not equal (!=, <>) |
||||
var_dump($a != $b); // true |
||||
var_dump($a <> $c); // false |
||||
|
||||
// Not identical (!==) |
||||
var_dump($a !== "5"); // true |
||||
var_dump($a !== $c); // false |
||||
|
||||
// Greater than |
||||
var_dump($b > $a); // true |
||||
var_dump($a > $c); // false |
||||
|
||||
// Less than |
||||
var_dump($a < $b); // true |
||||
var_dump($a < $c); // false |
||||
|
||||
// Greater than or equal |
||||
var_dump($a >= $c); // true |
||||
var_dump($b >= $a); // true |
||||
var_dump($a >= $b); // false |
||||
|
||||
// Less than or equal |
||||
var_dump($a <= $c); // true |
||||
var_dump($a <= $b); // true |
||||
var_dump($b <= $a); // false |
||||
|
||||
// Test with different data types |
||||
$str_num = "10"; |
||||
$int_num = 10; |
||||
var_dump($str_num == $int_num); // true (loose comparison) |
||||
var_dump($str_num === $int_num); // false (strict comparison) |
||||
|
||||
// Test spaceship operator (PHP 7+) |
||||
$spaceship1 = 5 <=> 10; // -1 |
||||
var_dump($spaceship1); |
||||
|
||||
$spaceship2 = 10 <=> 10; // 0 |
||||
var_dump($spaceship2); |
||||
|
||||
$spaceship3 = 15 <=> 10; // 1 |
||||
var_dump($spaceship3); |
||||
|
||||
// Test comparisons with strings |
||||
$str1 = "apple"; |
||||
$str2 = "banana"; |
||||
$str3 = "apple"; |
||||
|
||||
var_dump($str1 < $str2); // true (lexicographic comparison) |
||||
var_dump($str1 == $str3); // true |
||||
var_dump($str1 > $str3); // false |
||||
|
||||
// Test comparisons with floats |
||||
$float1 = 1.5; |
||||
$float2 = 1.7; |
||||
$float3 = 1.5; |
||||
|
||||
var_dump($float1 < $float2); // true |
||||
var_dump($float1 == $float3); // true |
||||
var_dump($float1 > $float2); // false |
||||
|
||||
// Test boolean comparisons |
||||
$bool1 = true; |
||||
$bool2 = false; |
||||
$int1 = 1; |
||||
$int0 = 0; |
||||
|
||||
var_dump($bool1 == $int1); // true |
||||
var_dump($bool2 == $int0); // true |
||||
var_dump($bool1 === $int1); // false (different types) |
||||
|
||||
// Test in conditional contexts |
||||
if (5 > 3) { |
||||
$result1 = "5 is greater than 3"; |
||||
} |
||||
var_dump($result1); |
||||
|
||||
if (2 < 1) { |
||||
$result2 = "This won't execute"; |
||||
} else { |
||||
$result2 = "2 is not less than 1"; |
||||
} |
||||
var_dump($result2); |
||||
|
||||
// Test complex comparisons |
||||
$x = 15; |
||||
$y = 20; |
||||
$z = 15; |
||||
|
||||
$complex1 = ($x < $y) && ($x == $z); |
||||
var_dump($complex1); |
||||
|
||||
$complex2 = ($x > $y) || ($x == $z); |
||||
var_dump($complex2); |
||||
|
||||
$complex3 = !($x > $y); |
||||
var_dump($complex3); |
||||
|
||||
// Test null comparisons |
||||
$null_val = null; |
||||
$zero_val = 0; |
||||
$empty_str = ""; |
||||
|
||||
var_dump($null_val == $zero_val); // true |
||||
var_dump($null_val === $zero_val); // false |
||||
echo '$zero_val == $empty_str:' . PHP_EOL; |
||||
var_dump($zero_val == $empty_str); // true |
||||
var_dump($zero_val === $empty_str); // false |
||||
|
||||
$num_a = 999; |
||||
$num_b = 999; |
||||
var_dump('int==int', $num_a == $num_b); |
||||
var_dump('int!=int', $num_a != $num_b); |
||||
?> |
||||
--EXPECT-- |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
int(-1) |
||||
int(0) |
||||
int(1) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
string(19) "5 is greater than 3" |
||||
string(20) "2 is not less than 1" |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
$zero_val == $empty_str: |
||||
bool(false) |
||||
bool(false) |
||||
string(8) "int==int" |
||||
bool(true) |
||||
string(8) "int!=int" |
||||
bool(false) |
||||
@ -0,0 +1,82 @@ |
||||
--TEST-- |
||||
Control Structures - if/else, for/while, switch |
||||
--FILE-- |
||||
<?php |
||||
// Test if/else structures |
||||
$a = 10; |
||||
$b = 20; |
||||
|
||||
if ($a > $b) { |
||||
$result = "a is greater"; |
||||
} elseif ($a < $b) { |
||||
$result = "b is greater"; |
||||
} else { |
||||
$result = "a and b are equal"; |
||||
} |
||||
|
||||
var_dump($result); |
||||
|
||||
// Test for loop |
||||
$sum = 0; |
||||
for ($i = 1; $i <= 5; $i++) { |
||||
$sum += $i; |
||||
} |
||||
var_dump($sum); |
||||
|
||||
// Test while loop |
||||
$counter = 0; |
||||
$while_sum = 0; |
||||
while ($counter < 5) { |
||||
$counter++; |
||||
$while_sum += $counter; |
||||
} |
||||
var_dump($while_sum); |
||||
|
||||
// Test do-while loop |
||||
$do_counter = 0; |
||||
$do_sum = 0; |
||||
do { |
||||
$do_counter++; |
||||
$do_sum += $do_counter; |
||||
} while ($do_counter < 5); |
||||
var_dump($do_sum); |
||||
|
||||
// Test switch statement |
||||
$number = 2; |
||||
switch ($number) { |
||||
case 1: |
||||
$switch_result = "one"; |
||||
break; |
||||
case 2: |
||||
$switch_result = "two"; |
||||
break; |
||||
case 3: |
||||
$switch_result = "three"; |
||||
break; |
||||
default: |
||||
$switch_result = "other"; |
||||
break; |
||||
} |
||||
var_dump($switch_result); |
||||
|
||||
// Test nested conditions |
||||
$x = 5; |
||||
$y = 10; |
||||
if ($x > 0) { |
||||
if ($y > $x) { |
||||
$nested_result = "y is greater than x"; |
||||
} else { |
||||
$nested_result = "x is greater than or equal to y"; |
||||
} |
||||
} else { |
||||
$nested_result = "x is not positive"; |
||||
} |
||||
var_dump($nested_result); |
||||
?> |
||||
--EXPECT-- |
||||
string(12) "b is greater" |
||||
int(15) |
||||
int(15) |
||||
int(15) |
||||
string(3) "two" |
||||
string(19) "y is greater than x" |
||||
@ -0,0 +1,136 @@ |
||||
--TEST-- |
||||
Logical Operators |
||||
--FILE-- |
||||
<?php |
||||
// Test logical operators |
||||
$a = true; |
||||
$b = false; |
||||
$x = 5; |
||||
$y = 10; |
||||
|
||||
// AND operator (&&) |
||||
var_dump($a && $a); // true |
||||
var_dump($a && $b); // false |
||||
var_dump(($x > 0) && ($y > 0)); // true |
||||
var_dump(($x > 0) && ($y < 0)); // false |
||||
|
||||
// OR operator (||) |
||||
var_dump($a || $b); // true |
||||
var_dump($b || $b); // false |
||||
var_dump(($x > 10) || ($y > 5)); // true |
||||
var_dump(($x > 10) || ($y < 5)); // false |
||||
|
||||
// NOT operator (!) |
||||
var_dump(!$a); // false |
||||
var_dump(!$b); // true |
||||
var_dump(!($x > 0)); // false |
||||
var_dump(!($x > 10)); // true |
||||
|
||||
// XOR operator (XOR) |
||||
var_dump('$a xor $b', $a xor $b); // true |
||||
var_dump($a xor $a); // false |
||||
var_dump($b xor $b); // false |
||||
var_dump(($x > 0) xor ($y < 0)); // true |
||||
|
||||
// Alternative operators |
||||
var_dump($a and $b); // false (lower precedence) |
||||
var_dump($a or $b); // true (lower precedence) |
||||
var_dump(!$b); // true (lower precedence) |
||||
|
||||
// Complex logical expressions |
||||
$age = 25; |
||||
$has_license = true; |
||||
$has_car = false; |
||||
|
||||
$can_drive = ($age >= 18) && $has_license; |
||||
var_dump($can_drive); |
||||
|
||||
$can_travel = $can_drive || $has_car; |
||||
var_dump($can_travel); |
||||
|
||||
$should_buy_car = !$has_car && $can_drive; |
||||
var_dump($should_buy_car); |
||||
|
||||
// Test with numeric values (0 is false, non-zero is true) |
||||
$num1 = 0; |
||||
$num2 = 5; |
||||
$num3 = -3; |
||||
|
||||
var_dump($num1 && $num2); // false |
||||
var_dump($num2 && $num3); // true |
||||
var_dump($num1 || $num2); // true |
||||
var_dump(!$num1); // true |
||||
var_dump(!$num2); // false |
||||
|
||||
// Test with strings (empty string is false, non-empty is true) |
||||
$str1 = ""; |
||||
$str2 = "hello"; |
||||
|
||||
var_dump($str1 || $str2); // true |
||||
var_dump(!$str1); // true |
||||
|
||||
// Test precedence: && has higher precedence than || |
||||
$result3 = true || false && false; |
||||
var_dump($result3); // true (true || (false && false)) |
||||
|
||||
$result4 = (true || false) && false; |
||||
var_dump($result4); // false |
||||
|
||||
// Test with null and other falsy values |
||||
$null_val = null; |
||||
$falsy1 = 0; |
||||
$falsy2 = ""; |
||||
|
||||
var_dump(!$null_val); // true |
||||
var_dump($falsy1 || $falsy2); // false |
||||
|
||||
$message = ""; |
||||
if ($x > 0 && $y > 0) { |
||||
$message = "Both x and y are positive"; |
||||
} |
||||
var_dump($message); |
||||
|
||||
if ($x < 0 || $y < 0) { |
||||
$message2 = "Either x or y is negative"; |
||||
} else { |
||||
$message2 = "Neither x nor y is negative"; |
||||
} |
||||
var_dump($message2); |
||||
?> |
||||
--EXPECT-- |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
string(9) "$a xor $b" |
||||
bool(true) |
||||
bool(false) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(false) |
||||
string(25) "Both x and y are positive" |
||||
string(27) "Neither x nor y is negative" |
||||
Loading…
Reference in new issue