Skip to content

Commit bb36ef3

Browse files
committed
feat: BasicBlock repr
1 parent 36df428 commit bb36ef3

File tree

1 file changed

+29
-20
lines changed

1 file changed

+29
-20
lines changed

mypyc/irbuild/for_helpers.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686

8787
GenFunc = Callable[[], None]
8888

89-
9089
def for_loop_helper(
9190
builder: IRBuilder,
9291
index: Lvalue,
@@ -95,6 +94,7 @@ def for_loop_helper(
9594
else_insts: GenFunc | None,
9695
is_async: bool,
9796
line: int,
97+
can_unroll: bool = True,
9898
) -> None:
9999
"""Generate IR for a loop.
100100
@@ -103,6 +103,7 @@ def for_loop_helper(
103103
expr: the expression to iterate over
104104
body_insts: a function that generates the body of the loop
105105
else_insts: a function that generates the else block instructions
106+
can_unroll: whether unrolling is allowed (for semantic safety)
106107
"""
107108
# Body of the loop
108109
body_block = BasicBlock()
@@ -117,15 +118,19 @@ def for_loop_helper(
117118
normal_loop_exit = else_block if else_insts is not None else exit_block
118119

119120
for_gen = make_for_loop_generator(
120-
builder, index, expr, body_block, normal_loop_exit, line, is_async=is_async, body_insts=body_insts
121+
builder, index, expr, body_block, normal_loop_exit, line, is_async=is_async, body_insts=body_insts, can_unroll=can_unroll
121122
)
122123

123124
is_literal_loop: bool = getattr(for_gen, "handles_body_insts", False)
124125

125126
# Only call body_insts if not handled by unrolled generator
126127
if is_literal_loop:
127-
for_gen.begin_body()
128-
return
128+
try:
129+
for_gen.begin_body()
130+
return
131+
except AssertionError:
132+
# For whatever reason, we can't unpack the loop in this case.
133+
pass
129134

130135
builder.push_loop_stack(step_block, exit_block)
131136
condition_block = BasicBlock()
@@ -420,10 +425,12 @@ def make_for_loop_generator(
420425
is_async: bool = False,
421426
nested: bool = False,
422427
body_insts: GenFunc = None,
428+
can_unroll: bool = True,
423429
) -> ForGenerator:
424430
"""Return helper object for generating a for loop over an iterable.
425431
426432
If "nested" is True, this is a nested iterator such as "e" in "enumerate(e)".
433+
can_unroll: whether unrolling is allowed (for semantic safety)
427434
"""
428435

429436
# Do an async loop if needed. async is always generic
@@ -437,22 +444,24 @@ def make_for_loop_generator(
437444

438445
rtyp = builder.node_type(expr)
439446

440-
# Special case: tuple literal (unroll the loop)
441-
if is_iterable_expr_with_literal_mambers(expr):
442-
return ForUnrolledSequenceLiteral(builder, index, body_block, loop_exit, line, expr, body_insts)
443-
444-
# Special case: RTuple (known-length tuple, struct field iteration)
445-
if isinstance(rtyp, RTuple):
446-
expr_reg = builder.accept(expr)
447-
return ForUnrolledRTuple(builder, index, body_block, loop_exit, line, rtyp, expr_reg, expr, body_insts)
448-
449-
# Special case: string literal (unroll the loop)
450-
if isinstance(expr, StrExpr):
451-
return ForUnrolledStringLiteral(builder, index, body_block, loop_exit, line, expr.value, expr, body_insts)
452-
453-
# Special case: string literal (unroll the loop)
454-
if isinstance(expr, BytesExpr):
455-
return ForUnrolledBytesLiteral(builder, index, body_block, loop_exit, line, expr.value, expr, body_insts)
447+
448+
if can_unroll:
449+
# Special case: tuple/list/set literal (unroll the loop)
450+
if is_iterable_expr_with_literal_mambers(expr):
451+
return ForUnrolledSequenceLiteral(builder, index, body_block, loop_exit, line, expr, body_insts)
452+
453+
# Special case: RTuple (known-length tuple, struct field iteration)
454+
if isinstance(rtyp, RTuple):
455+
expr_reg = builder.accept(expr)
456+
return ForUnrolledRTuple(builder, index, body_block, loop_exit, line, rtyp, expr_reg, expr, body_insts)
457+
458+
# Special case: string literal (unroll the loop)
459+
if isinstance(expr, StrExpr):
460+
return ForUnrolledStringLiteral(builder, index, body_block, loop_exit, line, expr.value, expr, body_insts)
461+
462+
# Special case: string literal (unroll the loop)
463+
if isinstance(expr, BytesExpr):
464+
return ForUnrolledBytesLiteral(builder, index, body_block, loop_exit, line, expr.value, expr, body_insts)
456465

457466
if is_sequence_rprimitive(rtyp):
458467
# Special case "for x in <list>".

0 commit comments

Comments
 (0)