|
15 | 15 | )
|
16 | 16 | from mypy.types import TupleType, get_proper_type
|
17 | 17 |
|
| 18 | +from mypyc.common import MAX_LITERAL_SHORT_INT |
18 | 19 | from mypyc.ir.ops import (
|
19 | 20 | Value, TupleGet, TupleSet, BasicBlock, Assign, LoadAddress
|
20 | 21 | )
|
21 |
| -from mypyc.ir.rtypes import RTuple, object_rprimitive, is_none_rprimitive, is_int_rprimitive |
| 22 | +from mypyc.ir.rtypes import ( |
| 23 | + RTuple, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive |
| 24 | +) |
22 | 25 | from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD
|
23 | 26 | from mypyc.primitives.registry import CFunctionDescription, builtin_names
|
24 | 27 | from mypyc.primitives.generic_ops import iter_op
|
25 | 28 | from mypyc.primitives.misc_ops import new_slice_op, ellipsis_op, type_op
|
26 |
| -from mypyc.primitives.list_ops import list_append_op, list_extend_op |
27 |
| -from mypyc.primitives.tuple_ops import list_tuple_op |
| 29 | +from mypyc.primitives.list_ops import list_append_op, list_extend_op, list_slice_op |
| 30 | +from mypyc.primitives.tuple_ops import list_tuple_op, tuple_slice_op |
28 | 31 | from mypyc.primitives.dict_ops import dict_new_op, dict_set_item_op
|
29 | 32 | from mypyc.primitives.set_ops import new_set_op, set_add_op, set_update_op
|
| 33 | +from mypyc.primitives.str_ops import str_slice_op |
30 | 34 | from mypyc.primitives.int_ops import int_comparison_op_mapping
|
31 | 35 | from mypyc.irbuild.specialize import specializers
|
32 | 36 | from mypyc.irbuild.builder import IRBuilder
|
@@ -323,15 +327,59 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value:
|
323 | 327 |
|
324 | 328 | def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value:
|
325 | 329 | base = builder.accept(expr.base)
|
| 330 | + index = expr.index |
| 331 | + |
| 332 | + if isinstance(base.type, RTuple) and isinstance(index, IntExpr): |
| 333 | + return builder.add(TupleGet(base, index.value, expr.line)) |
326 | 334 |
|
327 |
| - if isinstance(base.type, RTuple) and isinstance(expr.index, IntExpr): |
328 |
| - return builder.add(TupleGet(base, expr.index.value, expr.line)) |
| 335 | + if isinstance(index, SliceExpr): |
| 336 | + value = try_gen_slice_op(builder, base, index) |
| 337 | + if value: |
| 338 | + return value |
329 | 339 |
|
330 | 340 | index_reg = builder.accept(expr.index)
|
331 | 341 | return builder.gen_method_call(
|
332 | 342 | base, '__getitem__', [index_reg], builder.node_type(expr), expr.line)
|
333 | 343 |
|
334 | 344 |
|
| 345 | +def try_gen_slice_op(builder: IRBuilder, base: Value, index: SliceExpr) -> Optional[Value]: |
| 346 | + """Generate specialized slice op for some index expressions. |
| 347 | +
|
| 348 | + Return None if a specialized op isn't available. |
| 349 | +
|
| 350 | + This supports obj[x:y], obj[:x], and obj[x:] for a few types. |
| 351 | + """ |
| 352 | + if index.stride: |
| 353 | + # We can only handle the default stride of 1. |
| 354 | + return None |
| 355 | + |
| 356 | + if index.begin_index: |
| 357 | + begin_type = builder.node_type(index.begin_index) |
| 358 | + else: |
| 359 | + begin_type = int_rprimitive |
| 360 | + if index.end_index: |
| 361 | + end_type = builder.node_type(index.end_index) |
| 362 | + else: |
| 363 | + end_type = int_rprimitive |
| 364 | + |
| 365 | + # Both begin and end index must be int (or missing). |
| 366 | + if is_int_rprimitive(begin_type) and is_int_rprimitive(end_type): |
| 367 | + if index.begin_index: |
| 368 | + begin = builder.accept(index.begin_index) |
| 369 | + else: |
| 370 | + begin = builder.load_static_int(0) |
| 371 | + if index.end_index: |
| 372 | + end = builder.accept(index.end_index) |
| 373 | + else: |
| 374 | + # Replace missing end index with the largest short integer |
| 375 | + # (a sequence can't be longer). |
| 376 | + end = builder.load_static_int(MAX_LITERAL_SHORT_INT) |
| 377 | + candidates = [list_slice_op, tuple_slice_op, str_slice_op] |
| 378 | + return builder.builder.matching_call_c(candidates, [base, begin, end], index.line) |
| 379 | + |
| 380 | + return None |
| 381 | + |
| 382 | + |
335 | 383 | def transform_conditional_expr(builder: IRBuilder, expr: ConditionalExpr) -> Value:
|
336 | 384 | if_body, else_body, next = BasicBlock(), BasicBlock(), BasicBlock()
|
337 | 385 |
|
|
0 commit comments