(builder: IRBuilder, e: ComparisonExpr)
| 909 | |
| 910 | |
| 911 | def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value: |
| 912 | # x in (...)/[...] |
| 913 | # x not in (...)/[...] |
| 914 | first_op = e.operators[0] |
| 915 | if first_op in ["in", "not in"] and len(e.operators) == 1: |
| 916 | result = try_specialize_in_expr(builder, first_op, e.operands[0], e.operands[1], e.line) |
| 917 | if result is not None: |
| 918 | return result |
| 919 | |
| 920 | if len(e.operators) == 1: |
| 921 | # Special some common simple cases |
| 922 | if first_op in ("is", "is not"): |
| 923 | right_expr = e.operands[1] |
| 924 | if isinstance(right_expr, NameExpr) and right_expr.fullname == "builtins.None": |
| 925 | # Special case 'is None' / 'is not None'. |
| 926 | return translate_is_none(builder, e.operands[0], negated=first_op != "is") |
| 927 | left_expr = e.operands[0] |
| 928 | if is_int_rprimitive(builder.node_type(left_expr)): |
| 929 | right_expr = e.operands[1] |
| 930 | if is_int_rprimitive(builder.node_type(right_expr)): |
| 931 | if first_op in int_borrow_friendly_op: |
| 932 | borrow_left = is_borrow_friendly_expr(builder, right_expr) |
| 933 | left = builder.accept(left_expr, can_borrow=borrow_left) |
| 934 | right = builder.accept(right_expr, can_borrow=True) |
| 935 | return builder.binary_op(left, right, first_op, e.line) |
| 936 | |
| 937 | # TODO: Don't produce an expression when used in conditional context |
| 938 | # All of the trickiness here is due to support for chained conditionals |
| 939 | # (`e1 < e2 > e3`, etc). `e1 < e2 > e3` is approximately equivalent to |
| 940 | # `e1 < e2 and e2 > e3` except that `e2` is only evaluated once. |
| 941 | expr_type = builder.node_type(e) |
| 942 | |
| 943 | # go(i, prev) generates code for `ei opi e{i+1} op{i+1} ... en`, |
| 944 | # assuming that prev contains the value of `ei`. |
| 945 | def go(i: int, prev: Value) -> Value: |
| 946 | if i == len(e.operators) - 1: |
| 947 | return transform_basic_comparison( |
| 948 | builder, e.operators[i], prev, builder.accept(e.operands[i + 1]), e.line |
| 949 | ) |
| 950 | |
| 951 | next = builder.accept(e.operands[i + 1]) |
| 952 | return builder.builder.shortcircuit_helper( |
| 953 | "and", |
| 954 | expr_type, |
| 955 | lambda: transform_basic_comparison(builder, e.operators[i], prev, next, e.line), |
| 956 | lambda: go(i + 1, next), |
| 957 | e.line, |
| 958 | ) |
| 959 | |
| 960 | return go(0, builder.accept(e.operands[0])) |
| 961 | |
| 962 | |
| 963 | def try_specialize_in_expr( |
no test coverage detected
searching dependent graphs…