lang: Fold unsigned division as unsigned
438a079ffb70c1e14c3c6ffd292efa7929f896e128405e15e3f1c77a60e78ffc
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
ce82565a
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 | + | } |