|
94 | 94 | join_formatted_strings, |
95 | 95 | tokenizer_format_call, |
96 | 96 | ) |
97 | | -from mypyc.primitives.bytes_ops import isinstance_bytearray, isinstance_bytes |
| 97 | +from mypyc.primitives.bytes_ops import ( |
| 98 | + bytes_adjust_index_op, |
| 99 | + bytes_get_item_unsafe_op, |
| 100 | + bytes_range_check_op, |
| 101 | + isinstance_bytearray, |
| 102 | + isinstance_bytes, |
| 103 | +) |
98 | 104 | from mypyc.primitives.dict_ops import ( |
99 | 105 | dict_items_op, |
100 | 106 | dict_keys_op, |
@@ -1299,3 +1305,54 @@ def translate_bytes_writer_set_item( |
1299 | 1305 | ) |
1300 | 1306 |
|
1301 | 1307 | return builder.none() |
| 1308 | + |
| 1309 | + |
| 1310 | +@specialize_dunder("__getitem__", bytes_rprimitive) |
| 1311 | +def translate_bytes_get_item( |
| 1312 | + builder: IRBuilder, base_expr: Expression, args: list[Expression], ctx_expr: Expression |
| 1313 | +) -> Value | None: |
| 1314 | + """Optimized bytes.__getitem__ implementation with bounds checking.""" |
| 1315 | + # Check that we have exactly one argument |
| 1316 | + if len(args) != 1: |
| 1317 | + return None |
| 1318 | + |
| 1319 | + # Get the bytes object |
| 1320 | + obj = builder.accept(base_expr) |
| 1321 | + |
| 1322 | + # Get the index argument |
| 1323 | + index = builder.accept(args[0]) |
| 1324 | + |
| 1325 | + # Only use the optimized version for i64 index (requires experimental mode) |
| 1326 | + if not is_int64_rprimitive(index.type): |
| 1327 | + return None |
| 1328 | + |
| 1329 | + # Adjust the index (handle negative indices) |
| 1330 | + adjusted_index = builder.primitive_op( |
| 1331 | + bytes_adjust_index_op, [obj, index], ctx_expr.line |
| 1332 | + ) |
| 1333 | + |
| 1334 | + # Check if the adjusted index is in valid range |
| 1335 | + range_check = builder.primitive_op( |
| 1336 | + bytes_range_check_op, [obj, adjusted_index], ctx_expr.line |
| 1337 | + ) |
| 1338 | + |
| 1339 | + # Create blocks for branching |
| 1340 | + valid_block = BasicBlock() |
| 1341 | + invalid_block = BasicBlock() |
| 1342 | + |
| 1343 | + builder.add_bool_branch(range_check, valid_block, invalid_block) |
| 1344 | + |
| 1345 | + # Handle invalid index - raise IndexError |
| 1346 | + builder.activate_block(invalid_block) |
| 1347 | + builder.add( |
| 1348 | + RaiseStandardError(RaiseStandardError.INDEX_ERROR, "index out of range", ctx_expr.line) |
| 1349 | + ) |
| 1350 | + builder.add(Unreachable()) |
| 1351 | + |
| 1352 | + # Handle valid index - get the item |
| 1353 | + builder.activate_block(valid_block) |
| 1354 | + result = builder.primitive_op( |
| 1355 | + bytes_get_item_unsafe_op, [obj, adjusted_index], ctx_expr.line |
| 1356 | + ) |
| 1357 | + |
| 1358 | + return result |
0 commit comments