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

WhileExpr - Represents a while loop. #96

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

WhileExpr - Represents a while loop. #96

xmnlab opened this issue Sep 17, 2024 · 1 comment · Fixed by #142
Assignees

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 WhileExpr 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.expressions: Contains expression classes like ForRangeExpr, ForCounterExpr.
    • astx.blocks: Contains the Block class for sequences of statements.
    • astx.datatypes: Contains data type classes and operations.
    • astx.variables: Contains variable-related classes.
    • astx.modifiers: Contains enums for VisibilityKind, MutabilityKind, and ScopeKind.
    • astx.types: Contains type aliases and structures.
  • Existing Classes:

    • While: Represents a while loop statement, inherits from StatementType.
    • Expr: Base class for expressions.

Designing the WhileExpr Class

We need to design a WhileExpr class that:

  • Inherits from Expr, since it represents an expression.
  • Encapsulates the components of a while expression:
    • condition: The loop continuation condition.
    • body: The block of code to execute while the condition is true.
  • Can be used in contexts where a while loop is needed as an expression (e.g., in functional programming languages or specific language constructs).
  • Integrates with existing structures.

1. Updating ASTKind Enum

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

In astx/base.py, add:

# astx/base.py

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

    # ... existing kinds ...

    # Expressions
    ForRangeExprKind = -800
    ForCounterExprKind = -801
    WhileExprKind = -802  # Add this line

    # ... rest of the code ...

2. Defining WhileExpr

We'll define the WhileExpr in astx/expressions.py, alongside other expressions.

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.blocks import Block
from astx.types import ReprStruct

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

    condition: Expr
    body: Block

    def __init__(
        self,
        condition: Expr,
        body: Block,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.condition = condition
        self.body = body
        self.kind = ASTKind.WhileExprKind

    def __str__(self) -> str:
        return f"WhileExpr(condition={self.condition}, body={self.body})"

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

Explanation:

  • Inheritance: Inherits from Expr since it's an expression.
  • Attributes:
    • condition: An Expr representing the loop continuation condition.
    • body: A Block containing the code to execute while the condition is true.
  • Methods:
    • __str__: Provides a readable string representation.
    • get_struct: Returns a structured representation suitable for serialization.
  • Notes:
    • This class allows you to represent a while loop as an expression, which can be useful in certain language constructs or for intermediate representations.

3. Updating astx/__init__.py

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

# astx/__init__.py

from astx.expressions import ForRangeExpr, ForCounterExpr, WhileExpr

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

4. Ensuring Integration with Existing Structures

  • Expressions: WhileExpr is an Expr, fitting into the existing hierarchy.
  • Blocks: Uses Block from astx.blocks for the loop body.
  • Usage: Can be used wherever an expression is expected, allowing for constructs like assigning the result of a while expression to a variable.

Example Usage

1. Using WhileExpr in Code

from astx.expressions import WhileExpr
from astx.datatypes import LiteralBoolean
from astx.blocks import Block
from astx.variables import VariableAssignment, Variable
from astx.operators import BinaryOp
from astx.base import SourceLocation
from astx.datatypes import Int32, LiteralInt32, DataTypeOps

# Define a condition: x < 5
x_var = Variable(name="x")
condition = BinaryOp(
    op_code="<",
    lhs=x_var,
    rhs=LiteralInt32(5),
    loc=SourceLocation(line=1, col=0)
)

# Define the loop body: x = x + 1
update_expr = VariableAssignment(
    name="x",
    value=BinaryOp(
        op_code="+",
        lhs=x_var,
        rhs=LiteralInt32(1),
        loc=SourceLocation(line=2, col=4)
    ),
    loc=SourceLocation(line=2, col=4)
)

# Create the body block
body_block = Block(name="while_body")
body_block.append(update_expr)

# Create the WhileExpr
while_expr = WhileExpr(
    condition=condition,
    body=body_block,
    loc=SourceLocation(line=1, col=0)
)

# Print the string representation
print(while_expr)

Output:

WhileExpr(condition=BinaryOp[<](Variable[x], Literal[Int32]: 5), body=Block[while_body])

2. Using WhileExpr in an Assignment

In some languages or contexts, a while loop might return a value or be used as part of an expression.

from astx.variables import VariableDeclaration
from astx.modifiers import MutabilityKind

# Variable declaration: x = 0
x_decl = VariableDeclaration(
    name="x",
    type_=Int32,
    mutability=MutabilityKind.mutable,
    value=LiteralInt32(0),
    loc=SourceLocation(line=0, col=0)
)

# Assuming we have a context where WhileExpr can be used as an expression
# For example: result = while (condition) { body }

result_var = VariableDeclaration(
    name="result",
    type_=Int32,
    mutability=MutabilityKind.mutable,
    value=while_expr,  # Using the WhileExpr we created earlier
    loc=SourceLocation(line=3, col=0)
)

# Print the string representation of the variable declaration
print(result_var)

Output:

VariableDeclaration[result, Int32]

Testing and Validation

  • Unit Tests: Write tests to create instances of WhileExpr with various conditions and bodies.
  • Integration Tests: Ensure that WhileExpr integrates correctly with expressions, variables, and other AST nodes.
  • Visualization: Use astx.viz to visualize the AST involving WhileExpr.

Documentation

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

Conclusion

By creating the WhileExpr class, we've extended your astx module to support while 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 with WhileExpr

Here's the complete code for astx/expressions.py, including the WhileExpr:

# 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
from astx.blocks import Block

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

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

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

    condition: Expr
    body: Block

    def __init__(
        self,
        condition: Expr,
        body: Block,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.condition = condition
        self.body = body
        self.kind = ASTKind.WhileExprKind

    def __str__(self) -> str:
        return f"WhileExpr(condition={self.condition}, body={self.body})"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = "WhileExpr"
        value = {
            "condition": self.condition.get_struct(simplified),
            "body": self.body.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 WhileExpr class.
  • Documentation: Update any documentation or comments to reflect these additions.
  • Integration: Ensure that WhileExpr can be used seamlessly in contexts where expressions are expected.
Copy link

🎉 This issue has been resolved in version 0.16.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Successfully merging a pull request may close this issue.

2 participants