kphp
kphp copied to clipboard
`match` expression
RFC: https://wiki.php.net/rfc/match_expression_v2
The basis is the conversion to rvalue statements list with switch
with strict comparisons. For op_switch
added is_match
flag.
In PHP, a regular switch
uses non-strict comparison, which leads to type casts, but the match
uses strict comparison, which is why we need a new is_match
flag in the op_switch
node.
If this flag is set, then strict comparison will be used when generating the code for the switch
.
If we consider the transformation superficially, then the following will be:
For example:
$a = match($b) {
10 => 1,
20 => 2,
default => 3,
}
Converts to something like this:
$a = ({
switch ($b) {
case 10: {
$tmp = 1;
break;
}
case 20: {
$tmp = 2;
break;
}
default: {
$tmp = 3;
break;
}
};
$tmp;
});
If there are several conditions, then the code is generated only once and all conditions fallthrough to this code:
For example:
$a = match($b) {
10, 20 => 1,
default => 3,
}
Converts to something like this:
$a = ({
switch ($b) {
case 10: {} // fallthrough
case 20: {
$tmp = 1;
break;
}
default: {
$tmp = 3;
break;
}
};
$tmp;
});
If there is no default
branch, then the default version is generated.
The default version always gives a warning about an unhandled value.
PHP throws an
UnhandledMatchError
exception if the value is not handled.
For example:
$a = match($b) {
10 => 1,
}
Converts to something like this:
$a = ({
switch ($b) {
case 10: {
$tmp = 1;
break;
}
default: {
warning("Unhandled match value '$b'");
break;
}
};
$tmp;
});
Checks
- Due to the fact that we convert to
switch
, we automatically get a check for a duplicate.
Repeated case [10] in switch/match
- Also added a check for several
default
Match expressions may only contain one default arm
Is it possible to add here some kind of annotation to force exhaustion check at compile time instead of runtime warning
to cover #428?