parent
934628e2c2
commit
7ccdd3add9
8 changed files with 342 additions and 0 deletions
@ -0,0 +1,31 @@ |
||||
--TEST-- |
||||
array_keys after array_diff_key with integer block ids |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function strict_dominators(array $dominators, int $block): array |
||||
{ |
||||
return array_keys(array_diff_key($dominators[$block], [$block => true])); |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$dominators = [ |
||||
0 => [0 => true], |
||||
1 => [0 => true, 1 => true], |
||||
2 => [0 => true, 1 => true, 2 => true], |
||||
]; |
||||
|
||||
var_dump(strict_dominators($dominators, 0)); |
||||
var_dump(strict_dominators($dominators, 2)); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(0) { |
||||
} |
||||
array(2) { |
||||
[0]=> |
||||
int(0) |
||||
[1]=> |
||||
int(1) |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
--TEST-- |
||||
array_values reindexes array_unique result |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function unique_defs(array $defs): array |
||||
{ |
||||
return array_values(array_unique($defs)); |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(unique_defs(['a', 'b', 'a', 'c', 'b'])); |
||||
var_dump(unique_defs([2 => 'x', 5 => 'x', 9 => 'y'])); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(3) { |
||||
[0]=> |
||||
string(1) "a" |
||||
[1]=> |
||||
string(1) "b" |
||||
[2]=> |
||||
string(1) "c" |
||||
} |
||||
array(2) { |
||||
[0]=> |
||||
string(1) "x" |
||||
[1]=> |
||||
string(1) "y" |
||||
} |
||||
@ -0,0 +1,61 @@ |
||||
--TEST-- |
||||
repeatable argv parser with separated equals and compact short flags |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function is_long_flag_with_equals(string $arg, array $flags, array &$values): bool |
||||
{ |
||||
foreach ($flags as $flag) { |
||||
if (str_starts_with($arg, $flag . '=')) { |
||||
$values[] = substr($arg, strlen($flag) + 1); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
function parse_repeatable_argv(array $argv, array $flags): array |
||||
{ |
||||
$values = []; |
||||
for ($i = 1; $i < count($argv); $i++) { |
||||
if (in_array($argv[$i], $flags, true) && isset($argv[$i + 1]) && $argv[$i + 1] !== '' && $argv[$i + 1][0] !== '-') { |
||||
$values[] = $argv[$i + 1]; |
||||
$i++; |
||||
} elseif (!is_long_flag_with_equals($argv[$i], $flags, $values)) { |
||||
foreach ($flags as $flag) { |
||||
if (strlen($flag) === 2 && $flag[0] === '-') { |
||||
$short = substr($flag, 1); |
||||
if (preg_match('/^-' . preg_quote($short, '/') . '(.+)$/', $argv[$i], $m)) { |
||||
$values[] = $m[1]; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return $values; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$argv = [ |
||||
'compiler.php', |
||||
'-I', 'include', |
||||
'--include-path=/opt/include', |
||||
'-Irelative', |
||||
'-I', '-not-a-value', |
||||
'--include-path', '', |
||||
'--other', 'skip', |
||||
]; |
||||
|
||||
var_dump(parse_repeatable_argv($argv, ['-I', '--include-path'])); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(3) { |
||||
[0]=> |
||||
string(7) "include" |
||||
[1]=> |
||||
string(12) "/opt/include" |
||||
[2]=> |
||||
string(8) "relative" |
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
--TEST-- |
||||
dynamic is_subclass_of and class_implements checks |
||||
--FILE-- |
||||
<?php |
||||
|
||||
interface DynamicContract {} |
||||
class DynamicBase {} |
||||
class DynamicImpl extends DynamicBase implements DynamicContract {} |
||||
|
||||
function check_subclass(string|object $value, string $class): bool |
||||
{ |
||||
return is_subclass_of($value, $class); |
||||
} |
||||
|
||||
function check_implements(string|object $value, string $interface): bool |
||||
{ |
||||
return in_array($interface, class_implements($value)); |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(check_subclass(DynamicImpl::class, DynamicBase::class)); |
||||
var_dump(check_subclass(new DynamicImpl(), DynamicBase::class)); |
||||
var_dump(check_subclass(DynamicBase::class, DynamicImpl::class)); |
||||
|
||||
var_dump(check_implements(DynamicImpl::class, DynamicContract::class)); |
||||
var_dump(check_implements(new DynamicImpl(), DynamicContract::class)); |
||||
var_dump(check_implements(DynamicBase::class, DynamicContract::class)); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
bool(true) |
||||
bool(true) |
||||
bool(false) |
||||
@ -0,0 +1,47 @@ |
||||
--TEST-- |
||||
null coalescing assignment with instanceof boolean expression rhs |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class CoalescePlatform |
||||
{ |
||||
public function enabled(): bool |
||||
{ |
||||
echo "enabled\n"; |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
function ensure_option(array &$options, object $platform): void |
||||
{ |
||||
$options['is_zts'] ??= $platform instanceof CoalescePlatform && $platform->enabled(); |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$options = []; |
||||
ensure_option($options, new CoalescePlatform()); |
||||
var_dump($options); |
||||
|
||||
ensure_option($options, new CoalescePlatform()); |
||||
var_dump($options); |
||||
|
||||
$options = []; |
||||
ensure_option($options, new stdClass()); |
||||
var_dump($options); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
enabled |
||||
array(1) { |
||||
["is_zts"]=> |
||||
bool(true) |
||||
} |
||||
array(1) { |
||||
["is_zts"]=> |
||||
bool(true) |
||||
} |
||||
array(1) { |
||||
["is_zts"]=> |
||||
bool(false) |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
--TEST-- |
||||
match true with instanceof conditions |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class MatchTrueBase {} |
||||
class MatchTrueChild extends MatchTrueBase {} |
||||
|
||||
function describe_value(mixed $value): string |
||||
{ |
||||
return match (true) { |
||||
$value instanceof MatchTrueChild => 'child', |
||||
$value instanceof MatchTrueBase => 'base', |
||||
is_string($value) => 'string:' . $value, |
||||
default => 'other', |
||||
}; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(describe_value(new MatchTrueChild())); |
||||
var_dump(describe_value(new MatchTrueBase())); |
||||
var_dump(describe_value('x')); |
||||
var_dump(describe_value(42)); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(5) "child" |
||||
string(4) "base" |
||||
string(8) "string:x" |
||||
string(5) "other" |
||||
@ -0,0 +1,23 @@ |
||||
--TEST-- |
||||
count array_unique result for duplicate detection |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function duplicate_count(array $values): int |
||||
{ |
||||
$allValues = count($values); |
||||
$uniqueValues = count(array_unique($values)); |
||||
return $allValues - $uniqueValues; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(duplicate_count(['a', 'b', 'a', 'c', 'b'])); |
||||
var_dump(duplicate_count([1, '1', true, 2])); |
||||
var_dump(duplicate_count([])); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(2) |
||||
int(2) |
||||
int(0) |
||||
@ -0,0 +1,81 @@ |
||||
--TEST-- |
||||
array or interface object checks for accessible countable iterable values |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class AccessCountIterator implements ArrayAccess, Countable, IteratorAggregate |
||||
{ |
||||
private array $items = ['a' => 1, 'b' => 2]; |
||||
|
||||
public function offsetExists(mixed $offset): bool |
||||
{ |
||||
return isset($this->items[$offset]); |
||||
} |
||||
|
||||
public function offsetGet(mixed $offset): mixed |
||||
{ |
||||
return $this->items[$offset]; |
||||
} |
||||
|
||||
public function offsetSet(mixed $offset, mixed $value): void |
||||
{ |
||||
$this->items[$offset] = $value; |
||||
} |
||||
|
||||
public function offsetUnset(mixed $offset): void |
||||
{ |
||||
unset($this->items[$offset]); |
||||
} |
||||
|
||||
public function count(): int |
||||
{ |
||||
return count($this->items); |
||||
} |
||||
|
||||
public function getIterator(): Traversable |
||||
{ |
||||
return new ArrayIterator($this->items); |
||||
} |
||||
} |
||||
|
||||
function check_value(mixed $value): array |
||||
{ |
||||
return [ |
||||
is_array($value) || $value instanceof ArrayAccess, |
||||
is_array($value) || $value instanceof Countable, |
||||
is_array($value) || $value instanceof Traversable, |
||||
]; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(check_value(['x'])); |
||||
var_dump(check_value(new AccessCountIterator())); |
||||
var_dump(check_value(new stdClass())); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(3) { |
||||
[0]=> |
||||
bool(true) |
||||
[1]=> |
||||
bool(true) |
||||
[2]=> |
||||
bool(true) |
||||
} |
||||
array(3) { |
||||
[0]=> |
||||
bool(true) |
||||
[1]=> |
||||
bool(true) |
||||
[2]=> |
||||
bool(true) |
||||
} |
||||
array(3) { |
||||
[0]=> |
||||
bool(false) |
||||
[1]=> |
||||
bool(false) |
||||
[2]=> |
||||
bool(false) |
||||
} |
||||
Loading…
Reference in new issue