arxlang / astx

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

`EnumDeclStmt` / `EnumDefStmt` - Declares and Definition of an enumeration. #91

Open xmnlab opened 2 months ago

xmnlab commented 2 months ago

from gpt:

Understanding the Existing Structure

Based on the modules you've provided, here's a summary of key points relevant to creating the EnumDeclarationStmt class:


Designing the EnumDeclarationStmt Class

We need to design an EnumDeclarationStmt class that:

Given that astx/classes.py is meant for class-related AST nodes, and enums are similar to classes in many languages, we can include EnumDeclarationStmt in astx/classes.py. Alternatively, if you prefer to separate them, we can create a new module astx/enums.py.

For consistency, we'll include it in astx/classes.py.


1. Updating ASTKind Enum

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

In astx/base.py, add:

# astx/base.py

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

    # ... existing kinds ...

    # Class and Enum statements
    ClassDeclarationKind = -700
    ClassDefinitionKind = -701
    EnumDeclarationKind = -702

    # ... rest of the code ...

2. Defining EnumDeclarationStmt

In astx/classes.py, add the following:

# astx/classes.py

from typing import Dict, Union
from astx.variables import Variable
from astx.datatypes import Literal

# ... existing imports ...

@public
class EnumDeclarationStmt(StatementType):
    """AST class for enum declaration."""

    name: str
    values: Dict[str, Union[int, str, float, Literal]]
    decorators: List[Expr]
    visibility: VisibilityKind

    def __init__(
        self,
        name: str,
        values: Dict[str, Union[int, str, float, Literal]],
        decorators: Optional[List[Expr]] = None,
        visibility: VisibilityKind = VisibilityKind.public,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.name = name
        self.values = values
        self.decorators = decorators or []
        self.visibility = visibility
        self.kind = ASTKind.EnumDeclarationKind

    def __str__(self) -> str:
        decorators_str = "".join(f"@{decorator}\n" for decorator in self.decorators)
        visibility_str = self.visibility.name.lower() if self.visibility != VisibilityKind.public else ""
        enum_header = f"{visibility_str} enum {self.name}".strip()
        values_str = ",\n    ".join(f"{key} = {value}" for key, value in self.values.items())
        return f"{decorators_str}{enum_header} {{\n    {values_str}\n}}"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = f"EnumDeclaration[{self.name}]"
        value = {
            "visibility": self.visibility.name.lower(),
            "values": {k: v if isinstance(v, (int, float, str)) else v.get_struct(simplified) for k, v in self.values.items()},
            "decorators": [decorator.get_struct(simplified) for decorator in self.decorators],
        }
        return self._prepare_struct(key, value, simplified)

Explanation:


3. Updating astx/__init__.py

Add the EnumDeclarationStmt to your package's __init__.py:

# astx/__init__.py

from astx.classes import ClassDeclarationStmt, ClassDefinitionStmt, EnumDeclarationStmt

__all__ = [
    # ... existing exports ...
    "ClassDeclarationStmt",
    "ClassDefinitionStmt",
    "EnumDeclarationStmt",
]

Example Usage

1. Creating an Enum Declaration

from astx.classes import EnumDeclarationStmt
from astx.variables import Variable
from astx.datatypes import LiteralInt32, LiteralString
from astx.base import SourceLocation
from astx.modifiers import VisibilityKind

# Create decorators
decorator1 = Variable(name="unique")

# Enum values
enum_values = {
    "RED": LiteralInt32(1),
    "GREEN": LiteralInt32(2),
    "BLUE": LiteralInt32(3),
}

# Create an enum declaration
enum_decl = EnumDeclarationStmt(
    name="Color",
    values=enum_values,
    decorators=[decorator1],
    visibility=VisibilityKind.public,
    loc=SourceLocation(line=1, col=0)
)

# Print the string representation
print(enum_decl)

Output:

@Variable[unique]
public enum Color {
    RED = Literal[Int32]: 1,
    GREEN = Literal[Int32]: 2,
    BLUE = Literal[Int32]: 3
}

2. Enum with String Values

# Enum values with string literals
enum_values_str = {
    "SMALL": LiteralString("S"),
    "MEDIUM": LiteralString("M"),
    "LARGE": LiteralString("L"),
}

# Create an enum declaration
enum_size = EnumDeclarationStmt(
    name="Size",
    values=enum_values_str,
    visibility=VisibilityKind.public,
    loc=SourceLocation(line=1, col=0)
)

# Print the string representation
print(enum_size)

Output:

public enum Size {
    SMALL = Literal[String]: S,
    MEDIUM = Literal[String]: M,
    LARGE = Literal[String]: L
}

Integration with Existing Structures


Updating LiteralString Class

Since the LiteralString class was not previously defined in astx.datatypes, let's define it to represent string literals.

In astx/datatypes.py, add:

@public
class LiteralString(Literal):
    """LiteralString data type class."""

    value: str

    def __init__(
        self, value: str, loc: SourceLocation = NO_SOURCE_LOCATION
    ) -> None:
        """Initialize LiteralString."""
        super().__init__(loc)
        self.value = value
        self.type_ = String
        self.loc = loc

@public
class String(DataType):
    """String data type expression."""

Explanation:


Testing and Validation


Documentation


Conclusion

By creating the EnumDeclarationStmt class, we've extended your astx module to support enum declarations. This class fits naturally into your existing framework, utilizing existing components and following your established conventions.


Next Steps


Full Code for astx/classes.py with EnumDeclarationStmt

Here's the complete code for astx/classes.py, including the EnumDeclarationStmt:

# astx/classes.py

from __future__ import annotations
from typing import Optional, List, Dict, Union

from public import public

from astx.base import (
    NO_SOURCE_LOCATION,
    ASTKind,
    ASTNodes,
    Expr,
    SourceLocation,
    StatementType,
)
from astx.types import ReprStruct
from astx.modifiers import VisibilityKind
from astx.blocks import Block
from astx.variables import Variable
from astx.datatypes import Literal

@public
class ClassDeclarationStmt(StatementType):
    # ... existing code for ClassDeclarationStmt ...

@public
class ClassDefinitionStmt(ClassDeclarationStmt):
    # ... existing code for ClassDefinitionStmt ...

@public
class EnumDeclarationStmt(StatementType):
    """AST class for enum declaration."""

    name: str
    values: Dict[str, Union[int, str, float, Literal]]
    decorators: List[Expr]
    visibility: VisibilityKind

    def __init__(
        self,
        name: str,
        values: Dict[str, Union[int, str, float, Literal]],
        decorators: Optional[List[Expr]] = None,
        visibility: VisibilityKind = VisibilityKind.public,
        loc: SourceLocation = NO_SOURCE_LOCATION,
        parent: Optional[ASTNodes] = None,
    ) -> None:
        super().__init__(loc=loc, parent=parent)
        self.name = name
        self.values = values
        self.decorators = decorators or []
        self.visibility = visibility
        self.kind = ASTKind.EnumDeclarationKind

    def __str__(self) -> str:
        decorators_str = "".join(f"@{decorator}\n" for decorator in self.decorators)
        visibility_str = self.visibility.name.lower() if self.visibility != VisibilityKind.public else ""
        enum_header = f"{visibility_str} enum {self.name}".strip()
        values_str = ",\n    ".join(f"{key} = {value}" for key, value in self.values.items())
        return f"{decorators_str}{enum_header} {{\n    {values_str}\n}}"

    def get_struct(self, simplified: bool = False) -> ReprStruct:
        key = f"EnumDeclaration[{self.name}]"
        value = {
            "visibility": self.visibility.name.lower(),
            "values": {k: v if isinstance(v, (int, float, str)) else v.get_struct(simplified) for k, v in self.values.items()},
            "decorators": [decorator.get_struct(simplified) for decorator in self.decorators],
        }
        return self._prepare_struct(key, value, simplified)

Implementing LiteralString and String in astx/datatypes.py

# astx/datatypes.py

# ... existing imports and classes ...

@public
class String(DataType):
    """String data type expression."""

@public
class LiteralString(Literal):
    """LiteralString data type class."""

    value: str

    def __init__(
        self, value: str, loc: SourceLocation = NO_SOURCE_LOCATION
    ) -> None:
        """Initialize LiteralString."""
        super().__init__(loc)
        self.value = value
        self.type_ = String
        self.loc = loc

Final Notes

xmnlab commented 6 days ago
class MyEnum(Enum):
    SMALL: str = "S"
    MEDIUM: str = "M"
    LARGE: str = "L"