Beispiel #1
0
    def binary_op(self, lreg: Value, rreg: Value, expr_op: str,
                  line: int) -> Value:
        # special case tuple comparison here so that nested tuples can be supported
        if (isinstance(lreg.type, RTuple) and isinstance(rreg.type, RTuple)
                and expr_op in ('==', '!=')):
            return self.compare_tuples(lreg, rreg, expr_op, line)
        # Special case == and != when we can resolve the method call statically.
        value = None
        if expr_op in ('==', '!='):
            value = self.translate_eq_cmp(lreg, rreg, expr_op, line)
        if value is not None:
            return value

        # Special case 'is' and 'is not'
        if expr_op in ('is', 'is not'):
            return self.translate_is_op(lreg, rreg, expr_op, line)

        if (is_str_rprimitive(lreg.type) and is_str_rprimitive(rreg.type)
                and expr_op in ('==', '!=')):
            return self.compare_strings(lreg, rreg, expr_op, line)

        if is_tagged(lreg.type) and is_tagged(
                rreg.type) and expr_op in int_comparison_op_mapping:
            return self.compare_tagged(lreg, rreg, expr_op, line)

        call_c_ops_candidates = c_binary_ops.get(expr_op, [])
        target = self.matching_call_c(call_c_ops_candidates, [lreg, rreg],
                                      line)
        assert target, 'Unsupported binary operation: %s' % expr_op
        return target
Beispiel #2
0
def maybe_process_conditional_comparison(self: IRBuilder, e: Expression,
                                         true: BasicBlock,
                                         false: BasicBlock) -> bool:
    """Transform simple tagged integer comparisons in a conditional context.

    Return True if the operation is supported (and was transformed). Otherwise,
    do nothing and return False.

    Args:
        e: Arbitrary expression
        true: Branch target if comparison is true
        false: Branch target if comparison is false
    """
    if not isinstance(e, ComparisonExpr) or len(e.operands) != 2:
        return False
    ltype = self.node_type(e.operands[0])
    rtype = self.node_type(e.operands[1])
    if not is_tagged(ltype) or not is_tagged(rtype):
        return False
    op = e.operators[0]
    if op not in ('==', '!=', '<', '<=', '>', '>='):
        return False
    left_expr = e.operands[0]
    right_expr = e.operands[1]
    borrow_left = is_borrow_friendly_expr(self, right_expr)
    left = self.accept(left_expr, can_borrow=borrow_left)
    right = self.accept(right_expr, can_borrow=True)
    # "left op right" for two tagged integers
    self.builder.compare_tagged_condition(left, right, op, true, false, e.line)
    return True
Beispiel #3
0
def transform_operator_assignment_stmt(builder: IRBuilder, stmt: OperatorAssignmentStmt) -> None:
    """Operator assignment statement such as x += 1"""
    builder.disallow_class_assignments([stmt.lvalue], stmt.line)
    if (is_tagged(builder.node_type(stmt.lvalue))
            and is_tagged(builder.node_type(stmt.rvalue))
            and stmt.op in int_borrow_friendly_op):
        can_borrow = (is_borrow_friendly_expr(builder, stmt.rvalue)
                      and is_borrow_friendly_expr(builder, stmt.lvalue))
    else:
        can_borrow = False
    target = builder.get_assignment_target(stmt.lvalue)
    target_value = builder.read(target, stmt.line, can_borrow=can_borrow)
    rreg = builder.accept(stmt.rvalue, can_borrow=can_borrow)
    # the Python parser strips the '=' from operator assignment statements, so re-add it
    op = stmt.op + '='
    res = builder.binary_op(target_value, rreg, op, stmt.line)
    # usually operator assignments are done in-place
    # but when target doesn't support that we need to manually assign
    builder.assign(target, res, res.line)
Beispiel #4
0
    def binary_op(self, lreg: Value, rreg: Value, expr_op: str,
                  line: int) -> Value:
        # Special case == and != when we can resolve the method call statically.
        value = None
        if expr_op in ('==', '!='):
            value = self.translate_eq_cmp(lreg, rreg, expr_op, line)
        if value is not None:
            return value

        if is_tagged(lreg.type) and is_tagged(
                rreg.type) and expr_op in int_logical_op_mapping:
            return self.compare_tagged(lreg, rreg, expr_op, line)

        call_c_ops_candidates = c_binary_ops.get(expr_op, [])
        target = self.matching_call_c(call_c_ops_candidates, [lreg, rreg],
                                      line)
        if target:
            return target
        ops = binary_ops.get(expr_op, [])
        target = self.matching_primitive_op(ops, [lreg, rreg], line)
        assert target, 'Unsupported binary operation: %s' % expr_op
        return target
Beispiel #5
0
 def emit_signed_int_cast(self, type: RType) -> str:
     if is_tagged(type):
         return '(Py_ssize_t)'
     else:
         return ''