Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ForRangeExpr - Represents a for range loop. #94

Closed
Tracked by #73
xmnlab opened this issue Sep 17, 2024 · 1 comment
Closed
Tracked by #73

ForRangeExpr - Represents a for range loop. #94

xmnlab opened this issue Sep 17, 2024 · 1 comment
Assignees
Labels

Comments

@xmnlab
Copy link
Contributor

xmnlab commented Sep 17, 2024

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 ForRangeExpr class:

  • Base Classes and Enums:

    • AST: The root class for all AST nodes (astx/base.py).
    • Expr: Inherits from AST, used for expressions.
    • ASTKind: An enumeration of different AST node kinds.
  • Modules:

    • astx.base: Contains base classes and fundamental definitions.
    • astx.flows: Contains flow control statements like If, ForCountLoop, ForRangeLoop, and While.
    • astx.datatypes: Contains data type classes and operations.
    • astx.variables: Contains variable-related classes.
    • astx.blocks: Contains the Block class for sequences of statements.
    • astx.modifiers: Contains enums for VisibilityKind, MutabilityKind, and ScopeKind.
    • astx.types: Contains type aliases and structures.
  • Existing Classes:

    • ForRangeLoop: Represents a for loop using a range, inherits from StatementType.
    • Expr: Base class for expressions.

Designing the ForRangeExpr Class

We need to design a ForRangeExpr class that:

  • Inherits from Expr, since it represents an expression.
  • Represents a range of values, possibly with start, end, and step expressions.
  • Can be used in For loops or other contexts where a range expression is needed.
  • Integrates with existing structures.

1. Updating ASTKind Enum

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

In astx/base.py, add:

# astx/base.py

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

    # ... existing kinds ...

    # Expressions
    ForRangeExprKind = -800

    # ... rest of the code ...

**2. Defining ForRangeExpr

We'll define the ForRangeExpr in a new module astx/expressions.py.

Create astx/expressions.py:

# 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 Variable
from astx.types import ReprStruct
from astx.datatypes import LiteralInt32, LiteralInt64

@public
class ForRangeExpr(Expr):
    """AST class for range expressions used in loops or other contexts."""

    start: Expr
    end: Expr
    step: Expr

    def __init__(
        self,
        start: Expr,
        end: Expr,
        step: Optional[Expr] = None,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.start = start
        self.end = end
        self.step = step if step is not None else LiteralInt32(1)
        self.kind = ASTKind.ForRangeExprKind

    def __str__(self) -> str:
        return f"ForRangeExpr(start={self.start}, end={self.end}, step={self.step})"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = "ForRangeExpr"
        value = {
            "start": self.start.get_struct(simplified),
            "end": self.end.get_struct(simplified),
            "step": self.step.get_struct(simplified),
        }
        return self._prepare_struct(key, value, simplified)

Explanation:

  • Inheritance: Inherits from Expr since it's an expression.
  • Attributes:
    • start: The starting expression of the range.
    • end: The ending expression of the range.
    • step: The step expression of the range (defaults to 1 if not provided).
  • Methods:
    • __str__: Provides a readable string representation.
    • get_struct: Returns a structured representation suitable for serialization.
  • Notes:
    • Uses LiteralInt32 for the default step value, assuming it's defined in astx.datatypes.
    • The start, end, and step are Expr instances, allowing for flexibility.

3. Updating astx/__init__.py

Add the new module and class to your package's __init__.py:

# astx/__init__.py

from astx import (
    # ... existing imports ...
    expressions,
)
from astx.expressions import ForRangeExpr

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

4. Ensuring Integration with Existing Structures

  • Expressions: ForRangeExpr is an Expr, fitting into the existing hierarchy.
  • Usage in Loops: Modify ForRangeLoop to accept a ForRangeExpr instead of individual start, end, and step expressions.

Modify ForRangeLoop in astx/flows.py:

# astx/flows.py

from astx.expressions import ForRangeExpr

@public
class ForRangeLoop(StatementType):
    """AST class for `For` Loop using a range expression."""

    variable: InlineVariableDeclaration
    range_expr: ForRangeExpr
    body: Block

    def __init__(
        self,
        variable: InlineVariableDeclaration,
        range_expr: ForRangeExpr,
        body: Block,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        """Initialize the ForRangeLoop instance."""
        super().__init__(loc=loc, parent=parent)
        self.variable = variable
        self.range_expr = range_expr
        self.body = body
        self.kind = ASTKind.ForRangeKind

    def __str__(self) -> str:
        return f"ForRangeLoop(variable={self.variable}, range={self.range_expr})"

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

Example Usage

1. Using ForRangeExpr in a ForRangeLoop

from astx.expressions import ForRangeExpr
from astx.variables import InlineVariableDeclaration
from astx.blocks import Block
from astx.flows import ForRangeLoop
from astx.datatypes import LiteralInt32
from astx.base import SourceLocation
from astx.datatypes import Int32
from astx.modifiers import MutabilityKind

# Create a range expression from 0 to 10 with step 1
range_expr = ForRangeExpr(
    start=LiteralInt32(0),
    end=LiteralInt32(10),
    step=LiteralInt32(1)
)

# Variable declaration for the loop variable
loop_var = InlineVariableDeclaration(
    name="i",
    type_=Int32,
    mutability=MutabilityKind.mutable,
    value=LiteralInt32(0),
    loc=SourceLocation(line=1, col=0)
)

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

# Create the ForRangeLoop using the range expression
for_loop = ForRangeLoop(
    variable=loop_var,
    range_expr=range_expr,
    body=loop_body,
    loc=SourceLocation(line=1, col=0)
)

# Print the string representation
print(for_loop)

Output:

ForRangeLoop(variable=InlineVariableDeclaration[i, Int32], range=ForRangeExpr(start=Literal[Int32]: 0, end=Literal[Int32]: 10, step=Literal[Int32]: 1))

2. Using ForRangeExpr in Other Contexts

If you have contexts where a range expression is needed, you can use ForRangeExpr directly.


Testing and Validation

  • Unit Tests: Write tests to create instances of ForRangeExpr with various configurations.
  • Integration Tests: Ensure that ForRangeExpr integrates correctly with loops and other expressions.
  • Visualization: Use astx.viz to visualize the AST involving ForRangeExpr.

Documentation

  • Docstrings: Ensure all new classes and methods have clear docstrings.
  • Module Documentation: Update your module's documentation to include the new ForRangeExpr class.

Conclusion

By creating the ForRangeExpr class, we've extended your astx module to support range expressions, allowing for more flexible and expressive code representations. This class fits naturally into your existing framework, utilizing existing components and following your established conventions.


Full Code for astx/expressions.py

# 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 Variable
from astx.types import ReprStruct
from astx.datatypes import LiteralInt32

@public
class ForRangeExpr(Expr):
    """AST class for range expressions used in loops or other contexts."""

    start: Expr
    end: Expr
    step: Expr

    def __init__(
        self,
        start: Expr,
        end: Expr,
        step: Optional[Expr] = None,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.start = start
        self.end = end
        self.step = step if step is not None else LiteralInt32(1)
        self.kind = ASTKind.ForRangeExprKind

    def __str__(self) -> str:
        return f"ForRangeExpr(start={self.start}, end={self.end}, step={self.step})"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = "ForRangeExpr"
        value = {
            "start": self.start.get_struct(simplified),
            "end": self.end.get_struct(simplified),
            "step": self.step.get_struct(simplified),
        }
        return self._prepare_struct(key, value, simplified)

Final Notes

  • Imports: Ensure that all necessary imports are included in each module.
  • Testing: Write tests to verify the functionality and integration of the ForRangeExpr class.
  • Documentation: Update any documentation or comments to reflect these additions.
  • Integration: Ensure that ForRangeExpr can be used seamlessly in ForRangeLoop and other contexts.
@apkrelling
Copy link
Contributor

apkrelling commented Oct 28, 2024

Example to be used for the transpiler:
result = [x * 2 for x in range(1,6)]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants