Ejemplo n.º 1
0
 def visit_Compare(self, n: ast35.Compare) -> Node:
     operators = [self.from_comp_operator(o) for o in n.ops]
     operands = self.visit_list([n.left] + n.comparators)
     return ComparisonExpr(operators, operands)
Ejemplo n.º 2
0
 def visit_Compare(self, n: ast27.Compare) -> ComparisonExpr:
     operators = [self.from_comp_operator(o) for o in n.ops]
     operands = self.translate_expr_list([n.left] + n.comparators)
     e = ComparisonExpr(operators, operands)
     return self.set_line(e, n)
Ejemplo n.º 3
0
 def visit_comparison_expr(self, node: ComparisonExpr) -> Node:
     new = ComparisonExpr(node.operators, self.nodes(node.operands))
     new.method_types = [self.optional_type(t) for t in node.method_types]
     return new
Ejemplo n.º 4
0
def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value:
    # x in (...)/[...]
    # x not in (...)/[...]
    first_op = e.operators[0]
    if (first_op in ['in', 'not in']
            and len(e.operators) == 1
            and isinstance(e.operands[1], (TupleExpr, ListExpr))):
        items = e.operands[1].items
        n_items = len(items)
        # x in y -> x == y[0] or ... or x == y[n]
        # x not in y -> x != y[0] and ... and x != y[n]
        # 16 is arbitrarily chosen to limit code size
        if 1 < n_items < 16:
            if e.operators[0] == 'in':
                bin_op = 'or'
                cmp_op = '=='
            else:
                bin_op = 'and'
                cmp_op = '!='
            lhs = e.operands[0]
            mypy_file = builder.graph['builtins'].tree
            assert mypy_file is not None
            bool_type = Instance(cast(TypeInfo, mypy_file.names['bool'].node), [])
            exprs = []
            for item in items:
                expr = ComparisonExpr([cmp_op], [lhs, item])
                builder.types[expr] = bool_type
                exprs.append(expr)

            or_expr: Expression = exprs.pop(0)
            for expr in exprs:
                or_expr = OpExpr(bin_op, or_expr, expr)
                builder.types[or_expr] = bool_type
            return builder.accept(or_expr)
        # x in [y]/(y) -> x == y
        # x not in [y]/(y) -> x != y
        elif n_items == 1:
            if e.operators[0] == 'in':
                cmp_op = '=='
            else:
                cmp_op = '!='
            e.operators = [cmp_op]
            e.operands[1] = items[0]
        # x in []/() -> False
        # x not in []/() -> True
        elif n_items == 0:
            if e.operators[0] == 'in':
                return builder.false()
            else:
                return builder.true()

    if first_op in ('is', 'is not') and len(e.operators) == 1:
        right = e.operands[1]
        if isinstance(right, NameExpr) and right.fullname == 'builtins.None':
            # Special case 'is None' / 'is not None'.
            return translate_is_none(builder, e.operands[0], negated=first_op != 'is')

    # TODO: Don't produce an expression when used in conditional context
    # All of the trickiness here is due to support for chained conditionals
    # (`e1 < e2 > e3`, etc). `e1 < e2 > e3` is approximately equivalent to
    # `e1 < e2 and e2 > e3` except that `e2` is only evaluated once.
    expr_type = builder.node_type(e)

    # go(i, prev) generates code for `ei opi e{i+1} op{i+1} ... en`,
    # assuming that prev contains the value of `ei`.
    def go(i: int, prev: Value) -> Value:
        if i == len(e.operators) - 1:
            return transform_basic_comparison(
                builder, e.operators[i], prev, builder.accept(e.operands[i + 1]), e.line)

        next = builder.accept(e.operands[i + 1])
        return builder.builder.shortcircuit_helper(
            'and', expr_type,
            lambda: transform_basic_comparison(
                builder, e.operators[i], prev, next, e.line),
            lambda: go(i + 1, next),
            e.line)

    return go(0, builder.accept(e.operands[0]))
Ejemplo n.º 5
0
 def visit_comparison_expr(self, node: ComparisonExpr) -> Node:
     new = ComparisonExpr(node.operators, self.nodes(node.operands))
     new.method_types = [self.optional_type(t) for t in node.method_types]
     return new
Ejemplo n.º 6
0
 def visit_Compare(self, n):
     operators = [self.from_comp_operator(o) for o in n.ops]
     operands = self.visit([n.left] + n.comparators)
     return ComparisonExpr(operators, operands)