@_infer_type.register(irast.BinOp)
def __infer_binop(ir, schema):
    (left_type, right_type) = _infer_binop_args(ir.left, ir.right, schema)
    if isinstance(ir.op, (ast.ops.ComparisonOperator, ast.ops.MembershipOperator)):
        result = schema.get('std::bool')
    else:
        result = s_basetypes.TypeRules.get_result(ir.op, (left_type, right_type), schema)
        if (result is None):
            result = s_basetypes.TypeRules.get_result((ir.op, 'reversed'), (right_type, left_type), schema)
        if (result is None):
            if right_type.implicitly_castable_to(left_type, schema):
                right_type = left_type
            elif left_type.implicitly_castable_to(right_type, schema):
                left_type = right_type
            result = s_basetypes.TypeRules.get_result((ir.op, 'reversed'), (right_type, left_type), schema)
    if (result is None):
        raise ql_errors.EdgeQLError(f'binary operator `{ir.op.upper()}` is not defined for types {left_type.name} and {right_type.name}', context=ir.left.context)
    return result
@_infer_type.register(irast.BinOp)
def __infer_binop(ir, schema):
    (left_type, right_type) = _infer_binop_args(ir.left, ir.right, schema)
    if isinstance(ir.op, (ast.ops.ComparisonOperator, ast.ops.MembershipOperator)):
        result = schema.get('std::bool')
    else:
        result = s_basetypes.TypeRules.get_result(ir.op, (left_type, right_type), schema)
        if (result is None):
            result = s_basetypes.TypeRules.get_result((ir.op, 'reversed'), (right_type, left_type), schema)
        if (result is None):
            if right_type.implicitly_castable_to(left_type, schema):
                right_type = left_type
            elif left_type.implicitly_castable_to(right_type, schema):
                left_type = right_type
            result = s_basetypes.TypeRules.get_result((ir.op, 'reversed'), (right_type, left_type), schema)
    if (result is None):
        raise ql_errors.EdgeQLError(f'binary operator `{ir.op.upper()}` is not defined for types {left_type.name} and {right_type.name}', context=ir.left.context)
    return result