in src/io/intersection_interfaces.php [15:55]
function generate_intersection_interfaces(): void {
// Map these to powers of two, so we can later use a bitmask
$bases = vec[
'Closeable',
'Seekable',
'Read',
'Write',
'FD',
]
|> Dict\flip($$)
|> Dict\map($$, $vec_idx ==> 2 ** $vec_idx as int);
for ($i = 3; $i < (2 ** C\count($bases)); $i++) {
// $i is a bitmask that represents:
// - the current interface
// - the parents: for each set bit, turn it off. That's a parent.
//
// For example, the parents of 111 are 011, 101, and 110.
//
// If we have ^0*10*$, we have a direct child of 'Handle', not an
// intersection (a.k.a. composite/intermediate) interface.
if (Str\trim((string)$i, '0') === '1') {
continue;
}
$active = Dict\filter($bases, $bit ==> ($i & $bit) === $bit);
$parents = Dict\map(
$active,
$this_bit ==> Dict\filter($active, $bit ==> $bit !== $this_bit)
|> Vec\keys($$)
|> Str\join($$, '').'Handle',
);
if (C\count($parents) === 1) {
continue;
}
\printf(
"interface %sHandle extends %s {}\n",
Str\join(Vec\keys($active), ''),
Str\join($parents, ', '),
);
}
}