(op1: Constant, op2: Constant, func: F)
| 604 | match op1 { |
| 605 | Constant::Boolean(a) => Some(Constant::Boolean(!a)), |
| 606 | // Bitwise NOT on integers |
| 607 | c if parse_constant_to_bigint(&c).is_ok() => { |
| 608 | let bi = parse_constant_to_bigint(&c).ok()?; |
| 609 | // Bitwise NOT for BigInt is `!`, corresponds to two's complement |
| 610 | bigint_to_integer_constant_like(!bi, &c) |
| 611 | } |
| 612 | // Primitives (already handled by BigInt path, but keep for clarity/if BigInt fails?) |
| 613 | Constant::I8(a) => Some(Constant::I8(!a)), |
| 614 | Constant::I16(a) => Some(Constant::I16(!a)), |
| 615 | Constant::I32(a) => Some(Constant::I32(!a)), |
| 616 | Constant::I64(a) => Some(Constant::I64(!a)), |
| 617 | _ => None, // NOT doesn't apply to floats, strings, etc. |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | pub fn neg_constant(op1: Constant) -> Option<Constant> { |
| 622 | match op1 { |
| 623 | // 128-bit integer negation |
| 624 | Constant::Instance { ref class_name, .. } |
| 625 | if is_i128_class(class_name) || is_u128_class(class_name) => |
| 626 | { |
| 627 | let value = parse_constant_to_bigint(&op1).ok()?; |
| 628 | bigint_to_integer_constant_like(-value, &op1) |
| 629 | } |
| 630 | // Primitive Negation |
| 631 | Constant::I8(a) => Some(Constant::I8(a.wrapping_neg())), // Use wrapping_neg for primitives |
| 632 | Constant::I16(a) => Some(Constant::I16(a.wrapping_neg())), |
| 633 | Constant::I32(a) => Some(Constant::I32(a.wrapping_neg())), |
| 634 | Constant::I64(a) => Some(Constant::I64(a.wrapping_neg())), |
| 635 | Constant::F32(a) => Some(Constant::F32(-a)), |
| 636 | Constant::F64(a) => Some(Constant::F64(-a)), |
| 637 | _ => None, // Cannot negate bool, char, string etc. |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | pub fn switch_constants(op: Constant, targets: Vec<(Constant, String)>) -> Option<String> { |
| 642 | // Use the updated eq_constants |
| 643 | for (target_val, label) in targets { |
| 644 | match eq_constants(op.clone(), target_val) { |
| 645 | // Use updated eq_constants |
| 646 | Some(true) => return Some(label), |
| 647 | Some(false) => continue, |
| 648 | None => { /* Constants might be incomparable, treat as no match */ } |
| 649 | } |
| 650 | } |
| 651 | None // No match found |
| 652 | } |
| 653 | |
| 654 | pub fn length_constant(array: Constant) -> Option<Constant> { |
| 655 | match array { |
| 656 | Constant::Array(_, elems) => Some(Constant::I32( |
| 657 | elems.len().try_into().ok().unwrap_or(i32::MAX), // Handle potential overflow |
no test coverage detected