diff --git a/docs/tutorials/context.ipynb b/docs/tutorials/context.ipynb index d2cc6e07..a6fdd58d 100644 --- a/docs/tutorials/context.ipynb +++ b/docs/tutorials/context.ipynb @@ -229,7 +229,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "ast", "language": "python", "name": "python3" }, @@ -243,7 +243,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.7" + "version": "3.13.2" } }, "nbformat": 4, diff --git a/docs/tutorials/generatorExp.ipynb b/docs/tutorials/generatorExp.ipynb new file mode 100644 index 00000000..247a8a63 --- /dev/null +++ b/docs/tutorials/generatorExp.ipynb @@ -0,0 +1,210 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c:\\Users\\1hasa\\astx\\src\n" + ] + } + ], + "source": [ + "\n", + "import os, sys\n", + "print(os.path.abspath(os.path.join(os.getcwd(), \"../../\", \"src\")))\n", + "sys.path.insert(0, os.path.abspath(os.path.join(os.getcwd(), \"../../\", \"src\")))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from astx.flows import GeneratorExpr,GotoStmt\n", + "import astx" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "from astx.base import (\n", + " NO_SOURCE_LOCATION,\n", + " ASTKind,\n", + " ASTNodes,\n", + " DictDataTypesStruct,\n", + " Expr,\n", + " Identifier,\n", + " ReprStruct,\n", + " SourceLocation,\n", + " StatementType,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "got = GotoStmt(astx.Identifier('x'))\n", + "it = astx.LiteralFloat32(1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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YlKRQQiNE9AU1/r27YspU6agqKhIdilEYSsqKkJVVRX27t0ruxT6zUIuyhMRkS4YKEREpAsGChER6YKBQkREumCgEBGRLhgoRESkCwYKERHpgoFCRES6YKAQEZEuGChERKQLBgoREemCgUJERLpgoBARkS4YKEREpAsGChER6SJVdgEUPXv27EFVVZXsMojCtmfPHtklkA8MlCTy6quv4tVXX5VdBpEu+vTpI7sEaoFTXkli7969EELExc3hcOD666+HwWDA4sWLpdcTzC0vLw95eXlB9amqqkJKSgrq6uqk1x9PN35bY+xhoFDMOHnyJMrKytC/f3/s378f69atw/333y+7rIibPHkyBg8ejEceeUR2KURhYaBQTNi9ezeuvPJKzJkzB/fccw92796NnJwc2WVFhcFgwOOPP44333wT7733nuxyiELGQCGpjh49iqKiIgwbNgwpKSnYtWsXnnjiCXTo0EF2aVE1btw4jBkzBg899BCEELLLIQoJA4Wk2bhxIwYOHIglS5ZgyZIl2Lx5M/r16ye7LGkWLVqEDz/8EDabTXYpRCFhoFDUHT16FPPmzUNOTg769OmDvXv34p577kFKSnL/dxw+fDgmTZqERx55BCdOnJBdDlHQkvsvmKJu9+7dGDVqFCoqKrB06VKsWrUK559/vuyyYsbjjz+O/fv34+WXX5ZdClHQGCgUFSdOnMCTTz6JYcOGoWPHjti5cyfuuusu2WXFnJ49e+K2227DggUL8PPPP8suhygoDBSKuC+++AI5OTkoKirCo48+is2bN6NHjx6yy4pZCxcuxOHDh7F06VLZpRAFhYFCEfXSSy9h4MCB+Pbbb7Ft2zb88Y9/TPq1kracd955mDNnDh577DF89913sssh0ox/2RQRX3/9NSZOnIg77rgD9913H3bs2IHMzEzZZcWNhx9+GCdPnkRpaansUog0Y6CQ7rZu3YohQ4Zgz5492Lx5M0pKSpCWlia7rLjSpUsXPPDAA1i8eDGcTqfscog0YaCQboQQePrpp3HNNddg4MCB2LlzJ0aNGiW7rLh13333oUuXLnjsscdkl0KkCQOFdPHdd99h6tSpmDdvHh5++GFUV1eja9eussuKa6effjrMZjOWLVuGf/zjH7LLIWoTA4XCtmvXLgwZMgQbN27E6tWrUVRUxIV3ncycOROXXHIJioqKZJdC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oMSpkydPYsaMGejUqRPnx6lNDz74IOrr6/kpxBRRDJQ4VVRUhPfffx9VVVU488wzZZdDMa5v376YMGEClixZIrsUSmAMlBh27Ngxn9s3bNiAxx9/HE899RQGDx4c5aooXt1///147733sH37dtmlUIJioMQoIQSGDRuGVatWNdvudDoxY8YMTJo0CSaTSVJ1FI/GjBmDzMxMPPPMM7JLoQTFQIlRu3fvxscff4wbb7wRt912G7777jucPHkSBQUFOOOMM7huQiG57777UFlZiQMHDsguhRIQAyVGrVmzBmlpaQBOfXJs7969cccdd2DTpk1YuXIljEaj5AopHk2fPh1nn302li1bJrsUSkAMlBj1zjvv4MSJEwBOraU0NTXhxRdfxLBhw9C7d2/J1VG8Ou2002AymbB06VL88MMPssuhBMNAiUFHjx7Fli1bmr1nQA2XDz74AAMHDuR3hlPI7rnnHvz44494+eWXZZdCCYaBEoM2b97s92Myjh8/DofDgZEjR+LRRx/F8ePHo1wdxbtu3bph+vTpWLx4Md/oSLpioMSgtWvXon379n7vP378OE6ePIny8nLU19dHsTJKFHPnzsWnn36KNWvWyC6FEggDJQa9+eabAT/Iz2AwQFEU1NXVoV+/flGsjBLFgAEDkJOTw0uISVcMlBjjdDr9nnWkpqYiLS0NS5YswapVq9C1a9coV0eJ5N5778Xq1avx6aefyi6FEgQDJcasXbvW55djpaam4uKLL8ZHH32E++67T0JllGhyc3ORkZGBsrIy2aVQgmCgxJi1a9eiXbt2np/VcJk6dSrsdjsGDhwoqzRKMO3atcOsWbPw/PPP48cff5RdDiUABkoMEUJg9erVns/wSktLQ8eOHbFixQq8/PLLOOOMMyRXSInm7rvvxo8//oiqqirZpVACYKDEkN27d+Prr78GcOrV46BBg/DJJ58gPz9fcmWUqLp164ZJkybhv//7v2WXQgmAgRJD1q5dC+DUNNe9996LLVu24OKLL5ZbFCW8e+65B7t27cKHH34ouxSKcwyUGPLuu++iW7duePfdd/H00097PsuLKJJGjx6NIUOG4LnnnpNdCsW51JYbDhw4gK1bt8qoJakdO3YMR44cQUlJCY4cOZLUc9pZWVm44IILZJeRVO6++27853/+J/7rv/4L3bp1k10OxalWgbJ161ZM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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gen = GeneratorExpr(\n", + " Identifier('x*x'),\n", + " Identifier('x'),\n", + " astx.literals.LiteralSet(\n", + " elements={\n", + " astx.LiteralInt32(1),\n", + " astx.LiteralInt32(2),\n", + " astx.LiteralInt32(3)\n", + " }\n", + " )\n", + "\n", + ")\n", + "\n", + "gen = GeneratorExpr(\n", + " Identifier('x*x'),\n", + " Identifier('x'),\n", + " astx.Identifier(\"list\")\n", + ")\n", + "gen" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(x*x for x in list)\n" + ] + }, + { + "data": { + "image/png": "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YlKRQQiNE9AU1/r27YspU6agqKhIdilEYSsqKkJVVRX27t0ruxT6zUIuyhMRkS4YKEREpAsGChER6YKBQkREumCgEBGRLhgoRESkCwYKERHpgoFCRES6YKAQEZEuGChERKQLBgoREemCgUJERLpgoBARkS4YKEREpAsGChER6SJVdgEUPXv27EFVVZXsMojCtmfPHtklkA8MlCTy6quv4tVXX5VdBpEu+vTpI7sEaoFTXkli7969EELExc3hcOD666+HwWDA4sWLpdcTzC0vLw95eXlB9amqqkJKSgrq6uqk1x9PN35bY+xhoFDMOHnyJMrKytC/f3/s378f69atw/333y+7rIibPHkyBg8ejEceeUR2KURhYaBQTNi9ezeuvPJKzJkzB/fccw92796NnJwc2WVFhcFgwOOPP44333wT7733nuxyiELGQCGpjh49iqKiIgwbNgwpKSnYtWsXnnjiCXTo0EF2aVE1btw4jBkzBg899BCEELLLIQoJA4Wk2bhxIwYOHIglS5ZgyZIl2Lx5M/r16ye7LGkWLVqEDz/8EDabTXYpRCFhoFDUHT16FPPmzUNOTg769OmDvXv34p577kFKSnL/dxw+fDgmTZqERx55BCdOnJBdDlHQkvsvmKJu9+7dGDVqFCoqKrB06VKsWrUK559/vuyyYsbjjz+O/fv34+WXX5ZdClHQGCgUFSdOnMCTTz6JYcOGoWPHjti5cyfuuusu2WXFnJ49e+K2227DggUL8PPPP8suhygoDBSKuC+++AI5OTkoKirCo48+is2bN6NHjx6yy4pZCxcuxOHDh7F06VLZpRAFhYFCEfXSSy9h4MCB+Pbbb7Ft2zb88Y9/TPq1kracd955mDNnDh577DF89913sssh0ox/2RQRX3/9NSZOnIg77rgD9913H3bs2IHMzEzZZcWNhx9+GCdPnkRpaansUog0Y6CQ7rZu3YohQ4Zgz5492Lx5M0pKSpCWlia7rLjSpUsXPPDAA1i8eDGcTqfscog0YaCQboQQePrpp3HNNddg4MCB2LlzJ0aNGiW7rLh13333oUuXLnjsscdkl0KkCQOFdPHdd99h6tSpmDdvHh5++GFUV1eja9eussuKa6effjrMZjOWLVuGf/zjH7LLIWoTA4XCtmvXLgwZMgQbN27E6tWrUVRUxIV3ncycOROXXHIJioqKZJdC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oMSpkydPYsaMGejUqRPnx6lNDz74IOrr6/kpxBRRDJQ4VVRUhPfffx9VVVU488wzZZdDMa5v376YMGEClixZIrsUSmAMlBh27Ngxn9s3bNiAxx9/HE899RQGDx4c5aooXt1///147733sH37dtmlUIJioMQoIQSGDRuGVatWNdvudDoxY8YMTJo0CSaTSVJ1FI/GjBmDzMxMPPPMM7JLoQTFQIlRu3fvxscff4wbb7wRt912G7777jucPHkSBQUFOOOMM7huQiG57777UFlZiQMHDsguhRIQAyVGrVmzBmlpaQBOfXJs7969cccdd2DTpk1YuXIljEaj5AopHk2fPh1nn302li1bJrsUSkAMlBj1zjvv4MSJEwBOraU0NTXhxRdfxLBhw9C7d2/J1VG8Ou2002AymbB06VL88MMPssuhBMNAiUFHjx7Fli1bmr1nQA2XDz74AAMHDuR3hlPI7rnnHvz44494+eWXZZdCCYaBEoM2b97s92Myjh8/DofDgZEjR+LRRx/F8ePHo1wdxbtu3bph+vTpWLx4Md/oSLpioMSgtWvXon379n7vP378OE6ePIny8nLU19dHsTJKFHPnzsWnn36KNWvWyC6FEggDJQa9+eabAT/Iz2AwQFEU1NXVoV+/flGsjBLFgAEDkJOTw0uISVcMlBjjdDr9nnWkpqYiLS0NS5YswapVq9C1a9coV0eJ5N5778Xq1avx6aefyi6FEgQDJcasXbvW55djpaam4uKLL8ZHH32E++67T0JllGhyc3ORkZGBsrIy2aVQgmCgxJi1a9eiXbt2np/VcJk6dSrsdjsGDhwoqzRKMO3atcOsWbPw/PPP48cff5RdDiUABkoMEUJg9erVns/wSktLQ8eOHbFixQq8/PLLOOOMMyRXSInm7rvvxo8//oiqqirZpVACYKDEkN27d+Prr78GcOrV46BBg/DJJ58gPz9fcmWUqLp164ZJkybhv//7v2WXQgmAgRJD1q5dC+DUNNe9996LLVu24OKLL5ZbFCW8e+65B7t27cKHH34ouxSKcwyUGPLuu++iW7duePfdd/H00097PsuLKJJGjx6NIUOG4LnnnpNdCsW51JYbDhw4gK1bt8qoJakdO3YMR44cQUlJCY4cOZLUc9pZWVm44IILZJeRVO6++27853/+J/7rv/4L3bp1k10OxalWgbJ161ZM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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "print((gen))\n", + "gen" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import astx.operators\n", + "from typing import Optional, cast, Iterable\n", + "from astx.types.collections import List\n", + "# iterable = astx.TupleType([\n", + "# astx.LiteralInt32(2),\n", + "# astx.LiteralInt32(3),\n", + "# astx.LiteralInt32(1)]\n", + "# )\n", + "iterable = astx.literals.LiteralList(\n", + " elements=[\n", + " astx.LiteralInt32(1),\n", + " astx.LiteralInt32(2),\n", + " astx.LiteralInt32(3)\n", + " ]\n", + ")\n", + "for i in iterable.elements:\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# print(gen)\n", + "print(iterable)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ast", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/astx/__init__.py b/src/astx/__init__.py index 0ffa1e51..136955ad 100644 --- a/src/astx/__init__.py +++ b/src/astx/__init__.py @@ -43,6 +43,7 @@ FunctionReturn, LambdaExpr, YieldExpr, + YieldFromExpr, ) from astx.classes import ( ClassDeclStmt, @@ -58,12 +59,15 @@ ThrowStmt, ) from astx.flows import ( + AsyncForRangeLoopExpr, + AsyncForRangeLoopStmt, CaseStmt, ForCountLoopExpr, ForCountLoopStmt, ForRangeLoopExpr, ForRangeLoopStmt, GotoStmt, + GeneratorExpr, IfExpr, IfStmt, SwitchStmt, @@ -199,6 +203,8 @@ def get_version() -> str: "Argument", "Arguments", "AssignmentExpr", + "AsyncForRangeLoopExpr", + "AsyncForRangeLoopStmt", "AwaitExpr", "BinaryOp", "Block", @@ -236,6 +242,7 @@ def get_version() -> str: "FunctionDef", "FunctionPrototype", "FunctionReturn", + "GeneratorExpr", "GotoStmt", "Identifier", "IfExpr", @@ -330,6 +337,7 @@ def get_version() -> str: "XnorOp", "XorOp", "YieldExpr", + "YieldFromExpr", "base", "blocks", "callables", diff --git a/src/astx/base.py b/src/astx/base.py index 84d4b5b9..17ccc2ca 100644 --- a/src/astx/base.py +++ b/src/astx/base.py @@ -113,6 +113,7 @@ class ASTKind(Enum): FunctionAsyncDefKind = -405 AwaitExprKind = -406 YieldExprKind = -510 + YieldFromExprKind = -407 # control flow IfStmtKind = -500 @@ -127,6 +128,9 @@ class ASTKind(Enum): SwitchStmtKind = -509 GotoStmtKind = -511 WithStmtKind = -512 + GeneratorExprKind = -516 + AsyncRangeLoopStmtKind = -513 + AsyncRangeLoopExprKind = -514 # data types NullDTKind = -600 diff --git a/src/astx/callables.py b/src/astx/callables.py index 7d9cae1f..2cecaa8f 100644 --- a/src/astx/callables.py +++ b/src/astx/callables.py @@ -386,3 +386,32 @@ def get_struct(self, simplified: bool = False) -> ReprStruct: key = "YIELD-EXPR" value = {} if self.value is None else self.value.get_struct(simplified) return self._prepare_struct(key, value, simplified) + + +@public +@typechecked +class YieldFromExpr(Expr): + """AST class for YieldFromExpr.""" + + value: Expr + + def __init__( + self, + value: Expr, + loc: SourceLocation = NO_SOURCE_LOCATION, + parent: Optional[ASTNodes] = None, + ) -> None: + """Initialize the YieldFromExpr instance.""" + super().__init__(loc=loc, parent=parent) + self.value = value + self.kind = ASTKind.YieldFromExprKind + + def __str__(self) -> str: + """Return a string representation of the object.""" + return f"YieldFromExpr[{self.value}]" + + def get_struct(self, simplified: bool = False) -> ReprStruct: + """Return the AST structure of the object.""" + key = "YIELDFROM-EXPR" + value = self.value.get_struct(simplified) + return self._prepare_struct(key, value, simplified) diff --git a/src/astx/flows.py b/src/astx/flows.py index 79f3196c..e409a03c 100644 --- a/src/astx/flows.py +++ b/src/astx/flows.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import Optional, cast +from typing import Optional, cast, Union + from public import public @@ -20,7 +21,7 @@ from astx.blocks import Block from astx.tools.typing import typechecked from astx.variables import InlineVariableDeclaration - +from astx.literals import LiteralString, LiteralList, LiteralTuple, LiteralSet @public @typechecked @@ -343,6 +344,131 @@ def get_struct(self, simplified: bool = False) -> ReprStruct: return self._prepare_struct(key, value, simplified) +@public +@typechecked +class AsyncForRangeLoopStmt(StatementType): + """AST class for asynchronous `For` Range Statement.""" + + variable: InlineVariableDeclaration + start: Optional[Expr] + end: Expr + step: Optional[Expr] + body: Block + + def __init__( + self, + variable: InlineVariableDeclaration, + start: Optional[Expr], + end: Expr, + step: Optional[Expr], + body: Block, + loc: SourceLocation = NO_SOURCE_LOCATION, + parent: Optional[ASTNodes] = None, + ) -> None: + """Initialize the AsyncForRangeLoopStmt instance.""" + super().__init__(loc=loc, parent=parent) + self.variable = variable + self.start = start + self.end = end + self.step = step + self.body = body + self.kind = ASTKind.AsyncRangeLoopStmtKind + + def __str__(self) -> str: + """Return a string that represents the object.""" + start = self.start + end = self.end + step = self.step + var_name = self.variable.name + return f"AsyncForRangeLoopStmt({var_name}=[{start}:{end}:{step}])" + + def get_struct(self, simplified: bool = False) -> ReprStruct: + """Return the AST structure of the object.""" + for_start = { + "start": {} + if self.start is None + else self.start.get_struct(simplified) + } + for_end = {"end": self.end.get_struct(simplified)} + for_step = { + "step": {} + if self.step is None + else self.step.get_struct(simplified) + } + for_body = self.body.get_struct(simplified) + + key = "ASYNC-FOR-RANGE-LOOP-STMT" + value: ReprStruct = { + **cast(DictDataTypesStruct, for_start), + **cast(DictDataTypesStruct, for_end), + **cast(DictDataTypesStruct, for_step), + **cast(DictDataTypesStruct, for_body), + } + return self._prepare_struct(key, value, simplified) + + +@public +@typechecked +class AsyncForRangeLoopExpr(Expr): + """AST class for asynchronous `For` Range Expression.""" + + variable: InlineVariableDeclaration + start: Optional[Expr] + end: Expr + step: Optional[Expr] + body: Block + + def __init__( + self, + variable: InlineVariableDeclaration, + start: Optional[Expr], + end: Expr, + step: Optional[Expr], + body: Block, + loc: SourceLocation = NO_SOURCE_LOCATION, + parent: Optional[ASTNodes] = None, + ) -> None: + """Initialize the AsyncForRangeLoopExpr instance.""" + super().__init__(loc=loc, parent=parent) + self.variable = variable + self.start = start + self.end = end + self.step = step + self.body = body + self.kind = ASTKind.AsyncRangeLoopExprKind + + def __str__(self) -> str: + """Return a string that represents the object.""" + var_name = self.variable.name + return f"AsyncForRangeLoopExpr[{var_name}]" + + def get_struct(self, simplified: bool = False) -> ReprStruct: + """Return the AST structure of the object.""" + for_var = {"var": self.variable.get_struct(simplified)} + for_start = { + "start": {} + if self.start is None + else self.start.get_struct(simplified) + } + for_end = {"end": self.end.get_struct(simplified)} + for_step = { + "step": {} + if self.step is None + else self.step.get_struct(simplified) + } + for_body = self.body.get_struct(simplified) + + key = "ASYNC-FOR-RANGE-LOOP-EXPR" + value: ReprStruct = { + **cast(DictDataTypesStruct, for_var), + **cast(DictDataTypesStruct, for_start), + **cast(DictDataTypesStruct, for_end), + **cast(DictDataTypesStruct, for_step), + **cast(DictDataTypesStruct, for_body), + } + return self._prepare_struct(key, value, simplified) + + @public @typechecked class WhileStmt(StatementType): @@ -562,3 +688,55 @@ def get_struct(self, simplified: bool = False) -> ReprStruct: key = f"GOTO-STMT[{self.label.value}]" value: DictDataTypesStruct = {} return self._prepare_struct(key, value, simplified) +@public +@typechecked +class GeneratorExpr(Expr): + """AST class for generator expressions.""" + + element: Identifier + target: Identifier + iterator: Union[LiteralList, LiteralTuple, LiteralSet, LiteralString, Identifier] + def __init__( + self, + element: Identifier, + target: Identifier, + iterator: Union[LiteralList, LiteralTuple, LiteralSet, LiteralString, Identifier], + loc: SourceLocation = NO_SOURCE_LOCATION, + parent: Optional[ASTNodes] = None, + ) -> None: + """Initialize the GeneratorExpr instance.""" + super().__init__(loc=loc, parent=parent) + self.element = element + self.target = target + self.iterator = iterator + self.kind = ASTKind.GeneratorExprKind + + def __str__(self) -> str: + """Return a string representation of the object.""" + if isinstance(self.iterator, LiteralList): + return f"({self.element.value} for {self.target.value} in [{", ".join(str(e.value) for e in self.iterator.elements)}])" + elif isinstance(self.iterator, LiteralTuple): + return f"({self.element.value} for {self.target.value} in ({", ".join(str(e.value) for e in self.iterator.elements)}))" + elif isinstance(self.iterator, LiteralSet): + return f"({self.element.value} for {self.target.value} in {{{", ".join(str(e.value) for e in self.iterator.elements)}}})" + elif isinstance(self.iterator, Identifier): + return f"({self.element.value} for {self.target.value} in {self.iterator.value})" + else: + return f"({self.element.value} for {self.target.value} in {self.iterator})" + + def get_struct(self, simplified: bool = False) -> ReprStruct: + """Return the AST structure of the object.""" + key = "GENERATOR-EXPR" + value: ReprStruct = { + "element": self.element.get_struct(simplified), + "target": self.target.get_struct(simplified), + } + if isinstance(self.iterator, (LiteralList, LiteralTuple, LiteralSet)): + value["iterator"] = { + "type": self.iterator.__class__.__name__, + "elements": [e.get_struct(simplified) for e in self.iterator.elements] + } + else: + value["iterator"] = self.iterator.get_struct(simplified) + + return self._prepare_struct(key, value, simplified) diff --git a/src/astx/literals/collections.py b/src/astx/literals/collections.py index 2b05ee39..3025a292 100644 --- a/src/astx/literals/collections.py +++ b/src/astx/literals/collections.py @@ -69,7 +69,6 @@ def __init__( ) self.loc = loc - @public @typechecked class LiteralDict(Literal): diff --git a/src/astx/tools/transpilers/python.py b/src/astx/tools/transpilers/python.py index 6383bff1..af64627b 100644 --- a/src/astx/tools/transpilers/python.py +++ b/src/astx/tools/transpilers/python.py @@ -66,6 +66,31 @@ def visit(self, node: astx.AssignmentExpr) -> str: target_str = " = ".join(self.visit(target) for target in node.targets) return f"{target_str} = {self.visit(node.value)}" + @dispatch # type: ignore[no-redef] + def visit(self, node: astx.AsyncForRangeLoopExpr) -> str: + """Handle AsyncForRangeLoopExpr nodes.""" + if len(node.body) > 1: + raise ValueError( + "AsyncForRangeLoopExpr in Python just accept 1 node in the " + "body attribute." + ) + start = ( + self.visit(node.start) + if getattr(node, "start", None) is not None + else "0" + ) + end = self.visit(node.end) + step = ( + self.visit(node.step) + if getattr(node, "step", None) is not None + else "1" + ) + + return ( + f"result = [{self.visit(node.body).strip()} async for " + f"{node.variable.name} in range({start}, {end}, {step})]" + ) + @dispatch # type: ignore[no-redef] def visit(self, node: astx.AwaitExpr) -> str: """Handle AwaitExpr nodes.""" @@ -520,6 +545,12 @@ def visit(self, node: astx.YieldExpr) -> str: value = self.visit(node.value) if node.value else "" return f"yield {value}".strip() + @dispatch # type: ignore[no-redef] + def visit(self, node: astx.YieldFromExpr) -> str: + """Handle YieldFromExpr nodes.""" + value = self.visit(node.value) + return f"yield from {value}".strip() + @dispatch # type: ignore[no-redef] def visit(self, node: astx.Date) -> str: """Handle Date nodes.""" @@ -643,3 +674,8 @@ def visit(self, node: astx.LiteralDict) -> str: for key, value in node.elements.items() ) return f"{{{items_code}}}" + + @dispatch # type: ignore[no-redef] + def visit(self, node: astx.GeneratorExpr) -> str: + """Handle GeneratorExr nodes.""" + return f"({self.visit(node.element)} for {self.visit(node.target)} in {self.visit(node.iterator)})".strip() diff --git a/tests/test_callables.py b/tests/test_callables.py index 70478a25..4672c83c 100644 --- a/tests/test_callables.py +++ b/tests/test_callables.py @@ -14,6 +14,7 @@ FunctionReturn, LambdaExpr, YieldExpr, + YieldFromExpr, ) from astx.literals.numeric import LiteralInt32 from astx.modifiers import ScopeKind, VisibilityKind @@ -163,3 +164,13 @@ def test_yield_expr() -> None: assert yield_expr.get_struct() assert yield_expr.get_struct(simplified=True) visualize(yield_expr.get_struct()) + + +def test_yieldfrom_expr() -> None: + """Test `YieldFromExpr` class.""" + yieldfrom_expr = YieldFromExpr(value=LiteralInt32(1)) + + assert str(yieldfrom_expr) + assert yieldfrom_expr.get_struct() + assert yieldfrom_expr.get_struct(simplified=True) + visualize(yieldfrom_expr.get_struct()) diff --git a/tests/test_flows.py b/tests/test_flows.py index 69068d57..af9a72db 100644 --- a/tests/test_flows.py +++ b/tests/test_flows.py @@ -3,9 +3,13 @@ import astx import pytest + + from astx.base import SourceLocation from astx.blocks import Block from astx.flows import ( + AsyncForRangeLoopExpr, + AsyncForRangeLoopStmt, CaseStmt, ForCountLoopExpr, ForCountLoopStmt, @@ -16,6 +20,7 @@ SwitchStmt, WhileExpr, WhileStmt, + GeneratorExpr, ) from astx.literals import LiteralInt32, LiteralString from astx.literals.numeric import LiteralInt32 @@ -155,6 +160,46 @@ def test_for_count_loop_expr() -> None: visualize(for_expr.get_struct()) +def test_async_for_range_loop_expr() -> None: + """Test `Async For Range Loop` expression`.""" + decl_a = InlineVariableDeclaration( + "a", type_=Int32(), value=LiteralInt32(-1) + ) + start = LiteralInt32(1) + end = LiteralInt32(10) + step = LiteralInt32(1) + body = Block() + body.append(LiteralInt32(2)) + for_expr = AsyncForRangeLoopExpr( + variable=decl_a, start=start, end=end, step=step, body=body + ) + + assert str(for_expr) + assert for_expr.get_struct() + assert for_expr.get_struct(simplified=True) + visualize(for_expr.get_struct()) + + +def test_async_for_range_loop_stmt() -> None: + """Test `Async For Range Loop` statement.""" + decl_a = InlineVariableDeclaration( + "a", type_=Int32(), value=LiteralInt32(-1) + ) + start = LiteralInt32(1) + end = LiteralInt32(10) + step = LiteralInt32(1) + body = Block() + body.append(LiteralInt32(2)) + for_stmt = AsyncForRangeLoopStmt( + variable=decl_a, start=start, end=end, step=step, body=body + ) + + assert str(for_stmt) + assert for_stmt.get_struct() + assert for_stmt.get_struct(simplified=True) + visualize(for_stmt.get_struct()) + + def test_while_expr() -> None: """Test `WhileExpr` class.""" # Define a condition: x < 5 @@ -281,3 +326,17 @@ def test_goto_stmt() -> None: assert goto_stmt.get_struct() assert goto_stmt.get_struct(simplified=True) visualize(goto_stmt.get_struct()) + +def test_generator_exp() -> None: + """Test `GeneratorEx` class.""" + gen1 = GeneratorExpr( + astx.Identifier('x*x'), + astx.Identifier('x'), + astx.Identifier("list") + + ) + + assert str(gen1) == '(x*x for x in list)' + assert gen1.get_struct() + assert gen1.get_struct(simplified=True) + visualize(gen1.get_struct()) diff --git a/tests/tools/transpilers/test_python.py b/tests/tools/transpilers/test_python.py index 4ce136d6..c28e84bc 100644 --- a/tests/tools/transpilers/test_python.py +++ b/tests/tools/transpilers/test_python.py @@ -434,6 +434,29 @@ def test_transpiler_for_range_loop_expr() -> None: ) +def test_transpiler_async_for_range_loop_expr() -> None: + """Test `Async For Range Loop` expression`.""" + decl_a = astx.InlineVariableDeclaration( + "a", type_=astx.Int32(), value=astx.LiteralInt32(-1) + ) + start = astx.LiteralInt32(0) + end = astx.LiteralInt32(10) + step = astx.LiteralInt32(1) + body = astx.Block() + body.append(astx.LiteralInt32(2)) + + for_expr = astx.AsyncForRangeLoopExpr( + variable=decl_a, start=start, end=end, step=step, body=body + ) + + generated_code = translate(for_expr) + expected_code = "result = [2 async for a in range(0, 10, 1)]" + + assert generated_code == expected_code, ( + f"Expected '{expected_code}', but got '{generated_code}'" + ) + + def test_transpiler_binary_op() -> None: """Test astx.BinaryOp for addition operation.""" # Create a BinaryOp node for the expression "x + y" @@ -1047,6 +1070,33 @@ def test_transpiler_yieldexpr_whilestmt() -> None: ) +def test_transpiler_yieldfromexpr_whilestmt() -> None: + """Test astx.YieldFromExpr (using WhileStmt).""" + # Create the `while True` loop + while_cond = astx.LiteralBoolean(True) + while_body = astx.Block() + + # Create the `yieldfrom` expression + yieldfrom_expr = astx.YieldFromExpr(value=astx.Variable("x")) + + # Assign the result of `yieldfrom` back to `value` + assign_value = astx.VariableAssignment(name="value", value=yieldfrom_expr) + + # Add the assignment to the loop body + while_body.append(assign_value) + + # Define the `while` loop and add it to the function body + while_stmt = astx.WhileStmt(condition=while_cond, body=while_body) + + # Generate Python code + generated_code = translate(while_stmt) + expected_code = "while True:\n value = yield from x" + + assert generated_code == expected_code, ( + f"Expected '{expected_code}', but got '{generated_code}'" + ) + + def test_transpiler_assignmentexpr() -> None: """Test astx.AssignmentExpr.""" var_a = astx.Variable(name="a") @@ -1347,3 +1397,19 @@ def test_transpiler_literal_dict() -> None: 1: 10, 2: 20, }, f"Expected '{expected_code}', but got '{generated_code}'" + + def test_generator_expression() -> None: + gen = astx.GeneratorExpr( + astx.Identifier('x*x'), + astx.Identifier('x'), + astx.LiteralList( + list = [ + astx.LiteralInt32(4), + astx.LiteralInt32(1), + astx.LiteralInt32(5) + ] + ) + ) + generated_code = transpiler.visit(gen) + expected_code = "(x*x for x in [4, 1, 5])" + assert generated_code == expected_code , f"expected: {expected_code} ; generated: {generated_code}"