arxlang / astx

https://astx.arxlang.org/
Other
1 stars 4 forks source link

`ForCounterExpr` - Represents a for counter loop. #95

Open xmnlab opened 1 month ago

xmnlab commented 1 month ago

from gpt:

Understanding the Existing Structure

Based on the modules you've provided and the previous classes we've created, here's a summary of key points relevant to creating the ForCounterExpr class:


Designing the ForCounterExpr Class

We need to design a ForCounterExpr class that:


1. Updating ASTKind Enum

First, we need to add a new kind for the ForCounterExpr.

In astx/base.py, add:

# astx/base.py

@public
class ASTKind(Enum):
    """The expression kind class used for downcasting."""

    # ... existing kinds ...

    # Expressions
    ForCounterExprKind = -801

    # ... rest of the code ...

**2. Defining ForCounterExpr

We'll define the ForCounterExpr in astx/expressions.py, alongside ForRangeExpr.

In astx/expressions.py, add the following:

# astx/expressions.py

from __future__ import annotations
from typing import Optional

from public import public

from astx.base import (
    NO_SOURCE_LOCATION,
    ASTKind,
    ASTNodes,
    Expr,
    SourceLocation,
)
from astx.variables import InlineVariableDeclaration, VariableAssignment
from astx.types import ReprStruct
from astx.blocks import Block

@public
class ForCounterExpr(Expr):
    """AST class for counter expressions used in count-controlled loops."""

    initializer: InlineVariableDeclaration
    condition: Expr
    update: Expr

    def __init__(
        self,
        initializer: InlineVariableDeclaration,
        condition: Expr,
        update: Expr,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.initializer = initializer
        self.condition = condition
        self.update = update
        self.kind = ASTKind.ForCounterExprKind

    def __str__(self) -> str:
        return f"ForCounterExpr(initializer={self.initializer}, condition={self.condition}, update={self.update})"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = "ForCounterExpr"
        value = {
            "initializer": self.initializer.get_struct(simplified),
            "condition": self.condition.get_struct(simplified),
            "update": self.update.get_struct(simplified),
        }
        return self._prepare_struct(key, value, simplified)

Explanation:


3. Modifying ForCountLoop to Use ForCounterExpr

Now, we'll modify the ForCountLoop class in astx/flows.py to use ForCounterExpr instead of separate components.

In astx/flows.py, modify ForCountLoop:

# astx/flows.py

from astx.expressions import ForCounterExpr

@public
class ForCountLoop(StatementType):
    """
    AST class for a simple Count-Controlled `For` Loop statement.

    This is a very basic `for` loop, used by languages like C or C++.
    """

    counter_expr: ForCounterExpr
    body: Block

    def __init__(
        self,
        counter_expr: ForCounterExpr,
        body: Block,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        """Initialize the ForCountLoop instance."""
        super().__init__(loc=loc, parent=parent)
        self.counter_expr = counter_expr
        self.body = body
        self.kind = ASTKind.ForCountKind

    def __str__(self) -> str:
        return f"ForCountLoop({self.counter_expr})"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = "FOR-COUNT-LOOP"
        value = {
            "counter_expr": self.counter_expr.get_struct(simplified),
            "body": self.body.get_struct(simplified),
        }
        return self._prepare_struct(key, value, simplified)

Explanation:


4. Updating astx/__init__.py

Add the ForCounterExpr class to your package's __init__.py:

# astx/__init__.py

from astx.expressions import ForRangeExpr, ForCounterExpr

__all__ = [
    # ... existing exports ...
    "ForRangeExpr",
    "ForCounterExpr",
]

Example Usage

1. Using ForCounterExpr in a ForCountLoop

from astx.expressions import ForCounterExpr
from astx.variables import InlineVariableDeclaration, VariableAssignment
from astx.datatypes import Int32, LiteralInt32
from astx.blocks import Block
from astx.flows import ForCountLoop
from astx.operators import BinaryOp
from astx.base import SourceLocation
from astx.modifiers import MutabilityKind
from astx.datatypes import DataTypeOps

# Initialize loop variable i = 0
initializer = InlineVariableDeclaration(
    name="i",
    type_=Int32,
    mutability=MutabilityKind.mutable,
    value=LiteralInt32(0),
    loc=SourceLocation(line=1, col=0)
)

# Condition: i < 10
condition = BinaryOp(
    op_code="<",
    lhs=DataTypeOps(name="i"),
    rhs=LiteralInt32(10),
    loc=SourceLocation(line=1, col=10)
)

# Update: i = i + 1
update = VariableAssignment(
    name="i",
    value=BinaryOp(
        op_code="+",
        lhs=DataTypeOps(name="i"),
        rhs=LiteralInt32(1),
        loc=SourceLocation(line=1, col=20)
    ),
    loc=SourceLocation(line=1, col=20)
)

# Create ForCounterExpr
counter_expr = ForCounterExpr(
    initializer=initializer,
    condition=condition,
    update=update,
    loc=SourceLocation(line=1, col=0)
)

# Loop body
loop_body = Block(name="loop_body")
# Add statements to the loop body as needed

# Create ForCountLoop using ForCounterExpr
for_loop = ForCountLoop(
    counter_expr=counter_expr,
    body=loop_body,
    loc=SourceLocation(line=1, col=0)
)

# Print the string representation
print(for_loop)

Output:

ForCountLoop(ForCounterExpr(initializer=InlineVariableDeclaration[i, Int32], condition=BinaryOp[<](Variable[i], Literal[Int32]: 10), update=VariableAssignment[i]))

2. Using ForCounterExpr in Other Contexts

If you have contexts where a counter expression is needed outside of a loop, you can use ForCounterExpr directly.


Testing and Validation


Documentation


Conclusion

By creating the ForCounterExpr class, we've extended your astx module to support counter expressions, allowing for more flexible and expressive code representations, especially in count-controlled loops. This class fits naturally into your existing framework, utilizing existing components and following your established conventions.


Full Code for astx/expressions.py with ForCounterExpr

# astx/expressions.py

from __future__ import annotations
from typing import Optional

from public import public

from astx.base import (
    NO_SOURCE_LOCATION,
    ASTKind,
    ASTNodes,
    Expr,
    SourceLocation,
)
from astx.variables import InlineVariableDeclaration, VariableAssignment, Variable
from astx.types import ReprStruct
from astx.datatypes import LiteralInt32, DataTypeOps
from astx.operators import BinaryOp

@public
class ForRangeExpr(Expr):
    # ... existing code for ForRangeExpr ...

@public
class ForCounterExpr(Expr):
    """AST class for counter expressions used in count-controlled loops."""

    initializer: InlineVariableDeclaration
    condition: Expr
    update: Expr

    def __init__(
        self,
        initializer: InlineVariableDeclaration,
        condition: Expr,
        update: Expr,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.initializer = initializer
        self.condition = condition
        self.update = update
        self.kind = ASTKind.ForCounterExprKind

    def __str__(self) -> str:
        return f"ForCounterExpr(initializer={self.initializer}, condition={self.condition}, update={self.update})"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = "ForCounterExpr"
        value = {
            "initializer": self.initializer.get_struct(simplified),
            "condition": self.condition.get_struct(simplified),
            "update": self.update.get_struct(simplified),
        }
        return self._prepare_struct(key, value, simplified)

Final Notes

apkrelling commented 1 week ago

No python transpiler visit method for this class.