Tag:
Branch:
Tree:
8f8ae77ec8
master
speed_build
v0.0.1
v0.0.2
v0.0.3
v0.0.4
v0.0.5
v0.0.6
v0.0.7
v0.1.0
v0.4.0
v0.4.1
v0.6.1
v0.6.2
v0.6.5
v0.6.6
v0.6.8
${ noResults }
1 Commits (8f8ae77ec836d260370bffc8febedcef6368a613)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
8f8ae77ec8
|
fix(codegen): PHP semantics for division, modulo, shifts and compound assignment on typed scalars (#45) --skip-tests
* fix(codegen): route typed division, int modulo and shifts through PHP operators
Typed int/int and float-typed division fell through to a raw C++ '/':
7 / 2 on zend_long operands truncated to 3 where PHP returns 3.5,
integer division by zero was undefined behavior and float division by
zero produced INF, while PHP raises a catchable DivisionByZeroError in
both cases; PHP_INT_MIN / -1 also has UB in C++ but promotes to float
in PHP. The '%' guard only routed through php::fn::mod when NOT both
operands were int, so both-int modulo kept raw C++ '%' (UB for a zero
divisor and for PHP_INT_MIN % -1, which PHP defines as 0). Dynamic int
shifts were raw C++ too: PHP defines counts >= the word size as 0 (or
-1 for negative right shifts) and raises ArithmeticError for negative
counts, both undefined in C++.
Route all of these through the encapsulated php::Var operators /
php::fn::mod in non-native mode, matching the existing +/-/* pattern.
Constant folds are untouched; constant shifts that C++ defines
identically to PHP still emit raw operators.
* fix(parser): defer literal zero divisors to the runtime DivisionByZeroError
A literal `/ 0` or `% 0` (including `/=` and `%=`) was a compile-time
fatal, rejecting valid PHP: Zend compiles it and raises a catchable
DivisionByZeroError only when the statement executes, so dead or
guarded code like `if ($cond) { $x = 1 % 0; }` must compile. The
equivalent spellings `1 % (1 - 1)` and `10 / ZERO` were already
accepted and lowered to the catchable runtime error.
Give the literal spelling the same lowering: route the operation
through the encapsulated Variant operators (compound assignments on
Variant slots already defer via operator/= and operator%=), keep a
compile-time warning in normal mode, and keep the fatal in native mode
where the C++ operation would be undefined behavior.
The six OperatorTest cases asserting the old compile-time fatal now
assert the runtime-error lowering instead.
* test(operator): platform-neutral literal suffixes, PHP division on typed ints
The literal-division assertions hardcoded the macOS zend_long suffix
(LL); Linux emits L, so they now match either. native-type.phpt
asserted the truncating int division this change removes: division on
typed int operands follows PHP semantics in non-native mode, consistent
with the pre-existing + - * routing (use native_types keeps raw
division), so std::int(10) / 4 is now float(2.5).
* fix(codegen): literal zero divisors on native scalar slots raise the runtime error
Downgrading the literal-zero compile fatal to a warning exposed the raw
C++ compound path on typed native slots: `int $value; $value /= 0`
compiled to `value /= php::toInt(0L)` and killed the process with
SIGFPE instead of the catchable DivisionByZeroError (`%= 0` likewise;
float `/= 0.0` produced INF). A proven zero divisor always throws
before any assignment happens, so the whole compound lowers to the
PHP-semantics binary operation through php::Var and the target is left
untouched. Native-types mode keeps the compile-time rejection.
* fix(codegen): exclude explicit native scalars from PHP arithmetic routing
std::int()/std::float() opt into native C++ arithmetic independently of
the file-wide native_types declaration, and the existing + - * routing
already honors that via isExplicitNativeArithmeticExpr(). The new
division, both-int modulo and dynamic shift branches, and the
literal-zero compound lowering, bypassed it: std::int(10) / 4 changed
from int(2) to float(2.5) and native-type.phpt was updated to encode
the regression.
Every new PHP-semantics branch now skips explicitly native operands,
native-type.phpt is restored to int(2), and a proven zero divisor on an
explicit native slot keeps the compile-time rejection used by
native_types mode instead of being silently rerouted to PHP semantics.
Boundary coverage added on both sides: ordinary typed parameters keep
PHP behavior (7 / 2 is 3.5, -7 % 2 is -1) while std::int()/std::float()
keep native division, modulo and shifts.
|
1 day ago |