From 6c4031250f2e2e619b8d45d69314dd82d338e0cb Mon Sep 17 00:00:00 2001 From: Zimri Leisher Date: Wed, 9 Sep 2026 14:01:38 -0400 Subject: [PATCH] Share bytecode statement emission --- src/fpy/codegen_fpybc.py | 41 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/fpy/codegen_fpybc.py b/src/fpy/codegen_fpybc.py index cc9abe5..679808e 100644 --- a/src/fpy/codegen_fpybc.py +++ b/src/fpy/codegen_fpybc.py @@ -728,8 +728,13 @@ def _should_lower_stmt(self, stmt: Ast, state: CompileState) -> bool: return False def emit_AstBlock(self, node: AstBlock, state: CompileState): + return self._emit_stmts(node.stmts, state) + + def _emit_stmts( + self, stmts: list[Ast], state: CompileState + ) -> list[Directive | Ir]: dirs = [] - for stmt in node.stmts: + for stmt in stmts: if is_instance_compat(stmt, AstBlock): # a sub block. this is only possible if it is an imported sequence # emit its statements inline in this frame @@ -801,29 +806,17 @@ def emit_AstWhile(self, node: AstWhile, state: CompileState): dirs.extend(self.emit(node.condition, state)) # if the cond is true, fall thru, otherwise go to end dirs.append(IrIf(while_end_label)) - # run body - - for stmt_idx, stmt in enumerate(node.body.stmts): - if not self._should_lower_stmt(stmt, state): - # if the stmt can't do anything on its own, ignore it - continue - # we're going to manually emit the body's stmts instead - # of just emitting the body, because A) it doesn't matter - # and B) we need the index of the last statement in the body - # if we're a for loop, because that's where the continue stmt - # needs to go - if ( - stmt_idx == len(node.body.stmts) - 1 - and for_loop_increment_label is not None - ): - # last stmt, it must be the inc stmt, add the label before it - dirs.append(for_loop_increment_label) - dirs.extend(self.emit(stmt, state)) - if is_cmd_and_response_unhandled(stmt, state): - dirs.extend(self._emit_assert_cmd_response_ok(stmt, state)) - else: - # discard stack value if it was an expr - dirs.extend(self._emit_discard_expr_result(stmt, state)) + # A desugared for loop ends with its increment statement; continue + # jumps to the label immediately before that statement. + if for_loop_increment_label is not None: + assert node.body.stmts and is_instance_compat( + node.body.stmts[-1], AstAssign + ), node.body.stmts + dirs.extend(self._emit_stmts(node.body.stmts[:-1], state)) + dirs.append(for_loop_increment_label) + dirs.extend(self._emit_stmts(node.body.stmts[-1:], state)) + else: + dirs.extend(self._emit_stmts(node.body.stmts, state)) # go back to condition check dirs.append(IrGoto(while_start_label)) dirs.append(while_end_label)