Return bool(value). The result type can be bit_rprimitive or bool_rprimitive.
(self, value: Value)
| 2129 | return target |
| 2130 | |
| 2131 | def bool_value(self, value: Value) -> Value: |
| 2132 | """Return bool(value). |
| 2133 | |
| 2134 | The result type can be bit_rprimitive or bool_rprimitive. |
| 2135 | """ |
| 2136 | if is_bool_or_bit_rprimitive(value.type): |
| 2137 | result = value |
| 2138 | elif is_runtime_subtype(value.type, int_rprimitive): |
| 2139 | zero = Integer(0, short_int_rprimitive) |
| 2140 | result = self.comparison_op(value, zero, ComparisonOp.NEQ, value.line) |
| 2141 | elif is_fixed_width_rtype(value.type): |
| 2142 | zero = Integer(0, value.type) |
| 2143 | result = self.add(ComparisonOp(value, zero, ComparisonOp.NEQ)) |
| 2144 | elif is_str_rprimitive(value.type): |
| 2145 | result = self.call_c(str_check_if_true, [value], value.line) |
| 2146 | elif ( |
| 2147 | is_list_rprimitive(value.type) |
| 2148 | or is_dict_rprimitive(value.type) |
| 2149 | or is_tuple_rprimitive(value.type) |
| 2150 | ): |
| 2151 | length = self.builtin_len(value, value.line) |
| 2152 | zero = Integer(0) |
| 2153 | result = self.binary_op(length, zero, "!=", value.line) |
| 2154 | elif ( |
| 2155 | isinstance(value.type, RInstance) |
| 2156 | and value.type.class_ir.is_ext_class |
| 2157 | and value.type.class_ir.has_method("__bool__") |
| 2158 | ): |
| 2159 | # Directly call the __bool__ method on classes that have it. |
| 2160 | result = self.gen_method_call(value, "__bool__", [], bool_rprimitive, value.line) |
| 2161 | elif is_float_rprimitive(value.type): |
| 2162 | result = self.compare_floats(value, Float(0.0), FloatComparisonOp.NEQ, value.line) |
| 2163 | else: |
| 2164 | value_type = optional_value_type(value.type) |
| 2165 | if value_type is not None: |
| 2166 | not_none = self.translate_is_op(value, self.none_object(), "is not", value.line) |
| 2167 | always_truthy = False |
| 2168 | if isinstance(value_type, RInstance): |
| 2169 | # check whether X.__bool__ is always just the default (object.__bool__) |
| 2170 | if not value_type.class_ir.has_method( |
| 2171 | "__bool__" |
| 2172 | ) and value_type.class_ir.is_method_final("__bool__"): |
| 2173 | always_truthy = True |
| 2174 | |
| 2175 | if always_truthy: |
| 2176 | result = not_none |
| 2177 | else: |
| 2178 | # "X | None" where X may be falsey and requires a check |
| 2179 | result = Register(bit_rprimitive) |
| 2180 | true, false, end = BasicBlock(), BasicBlock(), BasicBlock() |
| 2181 | branch = Branch(not_none, true, false, Branch.BOOL) |
| 2182 | self.add(branch) |
| 2183 | self.activate_block(true) |
| 2184 | # unbox_or_cast instead of coerce because we want the |
| 2185 | # type to change even if it is a subtype. |
| 2186 | remaining = self.unbox_or_cast(value, value_type, value.line) |
| 2187 | as_bool = self.bool_value(remaining) |
| 2188 | self.add(Assign(result, as_bool)) |
no test coverage detected