lang: Fold unsigned division as unsigned
a902a880655810bab5d555af66e3037a18203098fe58c72077a39b3aa60f8d68
Constant division and remainder converted every operand through i64. Values above the signed maximum therefore produced signed quotients and remainders. Evaluate unsigned constant operands from their u64 magnitudes while retaining the signed path for signed expressions. Assisted-by: Codex:gpt-5.6-sol
1 parent
9913dc8b
lib/std/lang/resolver.rad
+16 -4
| 6338 | 6338 | return ConstValue::Bool(l >= r if signed else left.magnitude >= right.magnitude), |
|
| 6339 | 6339 | case ast::BinaryOp::Add => return ConstValue::Int(constIntFromSigned(l + r, bits, signed)), |
|
| 6340 | 6340 | case ast::BinaryOp::Sub => return ConstValue::Int(constIntFromSigned(l - r, bits, signed)), |
|
| 6341 | 6341 | case ast::BinaryOp::Mul => return ConstValue::Int(constIntFromSigned(l * r, bits, signed)), |
|
| 6342 | 6342 | case ast::BinaryOp::Div => { |
|
| 6343 | - | if r == 0 { |
|
| 6343 | + | if signed { |
|
| 6344 | + | if r == 0 { |
|
| 6345 | + | return nil; |
|
| 6346 | + | } |
|
| 6347 | + | return ConstValue::Int(constIntFromSigned(l / r, bits, true)); |
|
| 6348 | + | } |
|
| 6349 | + | if right.magnitude == 0 { |
|
| 6344 | 6350 | return nil; |
|
| 6345 | 6351 | } |
|
| 6346 | - | return ConstValue::Int(constIntFromSigned(l / r, bits, signed)); |
|
| 6352 | + | return constInt(left.magnitude / right.magnitude, bits, false, false); |
|
| 6347 | 6353 | }, |
|
| 6348 | 6354 | case ast::BinaryOp::Mod => { |
|
| 6349 | - | if r == 0 { |
|
| 6355 | + | if signed { |
|
| 6356 | + | if r == 0 { |
|
| 6357 | + | return nil; |
|
| 6358 | + | } |
|
| 6359 | + | return ConstValue::Int(constIntFromSigned(l % r, bits, true)); |
|
| 6360 | + | } |
|
| 6361 | + | if right.magnitude == 0 { |
|
| 6350 | 6362 | return nil; |
|
| 6351 | 6363 | } |
|
| 6352 | - | return ConstValue::Int(constIntFromSigned(l % r, bits, signed)); |
|
| 6364 | + | return constInt(left.magnitude % right.magnitude, bits, false, false); |
|
| 6353 | 6365 | }, |
|
| 6354 | 6366 | case ast::BinaryOp::BitAnd => return ConstValue::Int(constIntFromSigned(l & r, bits, signed)), |
|
| 6355 | 6367 | case ast::BinaryOp::BitOr => return ConstValue::Int(constIntFromSigned(l | r, bits, signed)), |
|
| 6356 | 6368 | case ast::BinaryOp::BitXor => return ConstValue::Int(constIntFromSigned(l ^ r, bits, signed)), |
|
| 6357 | 6369 | else => return nil, |
test/tests/const.u64.divide.rad
added
+10 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | ||
| 3 | + | constant QUOTIENT: u64 = 0xffffffffffffffff / 2; |
|
| 4 | + | ||
| 5 | + | @default fn main() -> i32 { |
|
| 6 | + | if QUOTIENT == 0x7fffffffffffffff { |
|
| 7 | + | return 0; |
|
| 8 | + | } |
|
| 9 | + | return 1; |
|
| 10 | + | } |