Perform a binary operation. Generate specialized operations based on operand types, with a fallback to generic operations.
(self, lreg: Value, rreg: Value, op: str, line: int)
| 1564 | # Other primitive operations |
| 1565 | |
| 1566 | def binary_op(self, lreg: Value, rreg: Value, op: str, line: int) -> Value: |
| 1567 | """Perform a binary operation. |
| 1568 | |
| 1569 | Generate specialized operations based on operand types, with a fallback |
| 1570 | to generic operations. |
| 1571 | """ |
| 1572 | ltype = lreg.type |
| 1573 | rtype = rreg.type |
| 1574 | |
| 1575 | # Special case tuple comparison here so that nested tuples can be supported |
| 1576 | if isinstance(ltype, RTuple) and isinstance(rtype, RTuple) and op in ("==", "!="): |
| 1577 | return self.compare_tuples(lreg, rreg, op, line) |
| 1578 | |
| 1579 | # Special case == and != when we can resolve the method call statically |
| 1580 | if op in ("==", "!="): |
| 1581 | value = self.translate_eq_cmp(lreg, rreg, op, line) |
| 1582 | if value is not None: |
| 1583 | return value |
| 1584 | |
| 1585 | # Special case various ops |
| 1586 | if op in ("is", "is not"): |
| 1587 | return self.translate_is_op(lreg, rreg, op, line) |
| 1588 | if ( |
| 1589 | is_bool_or_bit_rprimitive(ltype) |
| 1590 | and is_bool_or_bit_rprimitive(rtype) |
| 1591 | and op in BOOL_BINARY_OPS |
| 1592 | ): |
| 1593 | if op in ComparisonOp.signed_ops: |
| 1594 | return self.bool_comparison_op(lreg, rreg, op, line) |
| 1595 | else: |
| 1596 | return self.bool_bitwise_op(lreg, rreg, op[0], line) |
| 1597 | if isinstance(rtype, RInstance) and op in ("in", "not in"): |
| 1598 | return self.translate_instance_contains(rreg, lreg, op, line) |
| 1599 | if is_fixed_width_rtype(ltype): |
| 1600 | if op in FIXED_WIDTH_INT_BINARY_OPS: |
| 1601 | op = op.removesuffix("=") |
| 1602 | if op != "//": |
| 1603 | op_id = int_op_to_id[op] |
| 1604 | else: |
| 1605 | op_id = IntOp.DIV |
| 1606 | if is_bool_or_bit_rprimitive(rtype): |
| 1607 | rreg = self.coerce(rreg, ltype, line) |
| 1608 | rtype = ltype |
| 1609 | if is_fixed_width_rtype(rtype) or is_tagged(rtype): |
| 1610 | return self.fixed_width_int_op(ltype, lreg, rreg, op_id, line) |
| 1611 | if isinstance(rreg, Integer): |
| 1612 | return self.fixed_width_int_op( |
| 1613 | ltype, lreg, self.coerce(rreg, ltype, line), op_id, line |
| 1614 | ) |
| 1615 | elif op in ComparisonOp.signed_ops: |
| 1616 | if is_int_rprimitive(rtype): |
| 1617 | rreg = self.coerce_int_to_fixed_width(rreg, ltype, line) |
| 1618 | elif is_bool_or_bit_rprimitive(rtype): |
| 1619 | rreg = self.coerce(rreg, ltype, line) |
| 1620 | op_id = ComparisonOp.signed_ops[op] |
| 1621 | if is_fixed_width_rtype(rreg.type): |
| 1622 | return self.comparison_op(lreg, rreg, op_id, line) |
| 1623 | if isinstance(rreg, Integer): |
no test coverage detected