Skip to content

Commit 158e237

Browse files
authored
feat: add ContinueStmt and BreakStmt (#255)
1 parent 94456ac commit 158e237

File tree

6 files changed

+149
-1
lines changed

6 files changed

+149
-1
lines changed

libs/astx-transpilers/src/astx_transpilers/python_string.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ def visit(self, node: astx.Block) -> str:
115115
"""Handle Block nodes."""
116116
return self._generate_block(node)
117117

118+
@dispatch # type: ignore[no-redef]
119+
def visit(self, node: astx.BreakStmt) -> str:
120+
"""Handle BreakStmt nodes."""
121+
return "break"
122+
118123
@dispatch # type: ignore[no-redef]
119124
def visit(self, node: astx.CaseStmt) -> str:
120125
"""Handle CaseStmt nodes."""
@@ -154,6 +159,11 @@ def visit(self, node: astx.ClassDefStmt) -> str:
154159
class_type = "(ABC)" if node.is_abstract else ""
155160
return f"class {node.name}{class_type}:\n{self.visit(node.body)}"
156161

162+
@dispatch # type: ignore[no-redef]
163+
def visit(self, node: astx.ContinueStmt) -> str:
164+
"""Handle ContinueStmt nodes."""
165+
return "continue"
166+
157167
@dispatch # type: ignore[no-redef]
158168
def visit(self, node: astx.ComprehensionClause) -> str:
159169
"""Handle ComprehensionClause nodes."""

libs/astx-transpilers/tests/test_python.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,52 @@ def test_transpiler_async_for_range_loop_expr() -> None:
457457
)
458458

459459

460+
def test_transpiler_break_stmt() -> None:
461+
"""Test astx.BreakStmt transpilation."""
462+
# Create a simple loop structure (e.g., WhileStmt)
463+
x_var = astx.Variable(name="x")
464+
condition = astx.BinaryOp(op_code="<", lhs=x_var, rhs=astx.LiteralInt32(5))
465+
466+
# Create the loop body with a break statement
467+
body_block = astx.Block(name="while_body")
468+
body_block.append(astx.BreakStmt())
469+
470+
while_stmt = astx.WhileStmt(condition=condition, body=body_block)
471+
472+
# Generate Python code
473+
generated_code = translate(while_stmt)
474+
475+
# Expected code for the WhileStmt with break
476+
expected_code = "while (x < 5):\n break"
477+
478+
assert generated_code == expected_code, (
479+
f"Expected '{expected_code}', but got '{generated_code}'"
480+
)
481+
482+
483+
def test_transpiler_continue_stmt() -> None:
484+
"""Test astx.ContinueStmt transpilation."""
485+
# Create a simple loop structure (e.g., WhileStmt)
486+
x_var = astx.Variable(name="x")
487+
condition = astx.BinaryOp(op_code="<", lhs=x_var, rhs=astx.LiteralInt32(5))
488+
489+
# Create the loop body with a continue statement
490+
body_block = astx.Block(name="while_body")
491+
body_block.append(astx.ContinueStmt())
492+
493+
while_stmt = astx.WhileStmt(condition=condition, body=body_block)
494+
495+
# Generate Python code
496+
generated_code = translate(while_stmt)
497+
498+
# Expected code for the WhileStmt with continue
499+
expected_code = "while (x < 5):\n continue"
500+
501+
assert generated_code == expected_code, (
502+
f"Expected '{expected_code}', but got '{generated_code}'"
503+
)
504+
505+
460506
def test_transpiler_binary_op() -> None:
461507
"""Test astx.BinaryOp for addition operation."""
462508
# Create a BinaryOp node for the expression "x + y"

libs/astx/src/astx/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@
6969
from astx.flows import (
7070
AsyncForRangeLoopExpr,
7171
AsyncForRangeLoopStmt,
72+
BreakStmt,
7273
CaseStmt,
74+
ContinueStmt,
7375
DoWhileExpr,
7476
DoWhileStmt,
7577
ForCountLoopExpr,
@@ -224,6 +226,7 @@ def get_version() -> str:
224226
"BoolBinaryOp",
225227
"BoolUnaryOp",
226228
"Boolean",
229+
"BreakStmt",
227230
"CaseStmt",
228231
"CatchHandlerStmt",
229232
"ClassDeclStmt",
@@ -235,6 +238,7 @@ def get_version() -> str:
235238
"Complex64",
236239
"Comprehension",
237240
"ComprehensionClause",
241+
"ContinueStmt",
238242
"DataType",
239243
"DataTypeOps",
240244
"Date",

libs/astx/src/astx/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ class ASTKind(Enum):
140140
DoWhileStmtKind = -515
141141
DoWhileExprKind = -516
142142
GeneratorExprKind = -517
143+
BreakStmtKind = -518
144+
ContinueStmtKind = -519
143145

144146
# data types
145147
NullDTKind = -600

libs/astx/src/astx/flows.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,56 @@ def get_struct(self, simplified: bool = False) -> ReprStruct:
472472
return self._prepare_struct(key, value, simplified)
473473

474474

475+
@public
476+
@typechecked
477+
class BreakStmt(StatementType):
478+
"""AST class for break statement."""
479+
480+
def __init__(
481+
self,
482+
loc: SourceLocation = NO_SOURCE_LOCATION,
483+
parent: Optional[ASTNodes] = None,
484+
) -> None:
485+
"""Initialize the BreakStmt instance."""
486+
super().__init__(loc=loc, parent=parent)
487+
self.kind = ASTKind.BreakStmtKind
488+
489+
def __str__(self) -> str:
490+
"""Return a string representation of the object."""
491+
return "BreakStmt"
492+
493+
def get_struct(self, simplified: bool = False) -> ReprStruct:
494+
"""Return the AST structure of the object."""
495+
key = "BREAK-STMT"
496+
value: DictDataTypesStruct = {}
497+
return self._prepare_struct(key, value, simplified)
498+
499+
500+
@public
501+
@typechecked
502+
class ContinueStmt(StatementType):
503+
"""AST class for continue statement."""
504+
505+
def __init__(
506+
self,
507+
loc: SourceLocation = NO_SOURCE_LOCATION,
508+
parent: Optional[ASTNodes] = None,
509+
) -> None:
510+
"""Initialize the ContinueStmt instance."""
511+
super().__init__(loc=loc, parent=parent)
512+
self.kind = ASTKind.ContinueStmtKind
513+
514+
def __str__(self) -> str:
515+
"""Return a string representation of the object."""
516+
return "ContinueStmt"
517+
518+
def get_struct(self, simplified: bool = False) -> ReprStruct:
519+
"""Return the AST structure of the object."""
520+
key = "CONTINUE-STMT"
521+
value: DictDataTypesStruct = {}
522+
return self._prepare_struct(key, value, simplified)
523+
524+
475525
@public
476526
@typechecked
477527
class WhileStmt(StatementType):

libs/astx/tests/test_flows.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
"""Tests for control flow statements."""
22

3+
from typing import Any, cast
4+
35
import astx
46
import pytest
57

6-
from astx.base import SourceLocation
8+
from astx.base import ReprStruct, SourceLocation
79
from astx.blocks import Block
810
from astx.flows import (
911
AsyncForRangeLoopExpr,
1012
AsyncForRangeLoopStmt,
13+
BreakStmt,
1114
CaseStmt,
15+
ContinueStmt,
1216
DoWhileExpr,
1317
DoWhileStmt,
1418
ForCountLoopExpr,
@@ -159,6 +163,38 @@ def test_for_count_loop_expr() -> None:
159163
visualize(for_expr.get_struct())
160164

161165

166+
def test_break_stmt() -> None:
167+
"""Test BreakStmt class."""
168+
break_stmt = BreakStmt()
169+
170+
assert str(break_stmt) == "BreakStmt"
171+
assert break_stmt.kind == astx.ASTKind.BreakStmtKind
172+
173+
struct: ReprStruct = break_stmt.get_struct()
174+
assert "BREAK-STMT" in cast(dict[str, Any], struct)
175+
176+
struct_simplified: ReprStruct = break_stmt.get_struct(simplified=True)
177+
assert "BREAK-STMT" in cast(dict[str, Any], struct_simplified)
178+
179+
visualize(struct)
180+
181+
182+
def test_continue_stmt() -> None:
183+
"""Test ContinueStmt class."""
184+
continue_stmt = ContinueStmt()
185+
186+
assert str(continue_stmt) == "ContinueStmt"
187+
assert continue_stmt.kind == astx.ASTKind.ContinueStmtKind
188+
189+
struct: ReprStruct = continue_stmt.get_struct()
190+
assert "CONTINUE-STMT" in cast(dict[str, Any], struct)
191+
192+
struct_simplified: ReprStruct = continue_stmt.get_struct(simplified=True)
193+
assert "CONTINUE-STMT" in cast(dict[str, Any], struct_simplified)
194+
195+
visualize(struct)
196+
197+
162198
def test_async_for_range_loop_expr() -> None:
163199
"""Test `Async For Range Loop` expression`."""
164200
decl_a = InlineVariableDeclaration(

0 commit comments

Comments
 (0)