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