From 1d1591eff3b1b1a0881202a877ce41169bfac15e Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Wed, 16 Oct 2024 09:35:10 -0400 Subject: [PATCH 1/9] add ASTKind for LambdaExpr --- src/astx/base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/astx/base.py b/src/astx/base.py index 0bcdc14..1fe85ce 100644 --- a/src/astx/base.py +++ b/src/astx/base.py @@ -128,6 +128,8 @@ class ASTKind(Enum): ImportExprKind = -800 ImportFromExprKind = -801 + LambdaExprKind = -807 + class ASTMeta(type): def __str__(cls) -> str: From 93c6a95796654d4bbc30849305231ecb15853254 Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Thu, 17 Oct 2024 10:06:23 -0400 Subject: [PATCH 2/9] add LambdaExpr class --- src/astx/callables.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/astx/callables.py b/src/astx/callables.py index d782882..972b289 100644 --- a/src/astx/callables.py +++ b/src/astx/callables.py @@ -252,3 +252,36 @@ def get_struct(self, simplified: bool = False) -> ReprStruct: value: ReprStruct = {**args_struct, **body_struct} return self._prepare_struct(key, value, simplified) + + +@public +class LambdaExpr(Expr): + """AST class for lambda expressions.""" + + params: Arguments + body: Expr + + def __init__( + self, + params: Arguments, + body: Expr, + loc: SourceLocation = NO_SOURCE_LOCATION, + parent: Optional[ASTNodes] = None, + ) -> None: + super().__init__(loc=loc, parent=parent) + self.params = params + self.body = body + self.kind = ASTKind.LambdaExprKind + + def __str__(self) -> str: + """Return a string representation of the object.""" + return f" lambda x: {self.body}" + + def get_struct(self, simplified: bool = False) -> ReprStruct: + """Return the AST structure of the import-from expression.""" + body = self.body + # body_str = body.get_struct(simplified) + key = "LambdaExpr" + + value = cast(ReprStruct, body.get_struct(simplified)) + return self._prepare_struct(key, value, simplified) From b1f6a1423c5f09de0ee29d2cee26f12db8099e4c Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Thu, 17 Oct 2024 10:08:17 -0400 Subject: [PATCH 3/9] add LambdaExpr class in __init__.py --- src/astx/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/astx/__init__.py b/src/astx/__init__.py index 77572c2..298cb31 100644 --- a/src/astx/__init__.py +++ b/src/astx/__init__.py @@ -36,6 +36,7 @@ FunctionCall, FunctionPrototype, FunctionReturn, + LambdaExpr, ) from astx.datatypes import ( Boolean, @@ -173,6 +174,7 @@ def get_version() -> str: "UInt32", "UInt64", "UInt128", + "LambdaExpr", "Literal", "LiteralBoolean", "LiteralInt8", From 1cd0c262d50d124e94d02a4740246a2c74265b2b Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Thu, 17 Oct 2024 10:11:29 -0400 Subject: [PATCH 4/9] add transpiler visit method for LambdaExpr --- src/astx/transpilers/python.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/astx/transpilers/python.py b/src/astx/transpilers/python.py index 4726af2..24c567a 100644 --- a/src/astx/transpilers/python.py +++ b/src/astx/transpilers/python.py @@ -178,6 +178,11 @@ def visit(self, node: astx.FunctionReturn) -> str: value = self.visit(node.value) if node.value else "" return f"return {value}" + @dispatch # type: ignore[no-redef] + def visit(self, node: astx.LambdaExpr) -> str: + """Handle LambdaExpr nodes.""" + return f" lambda x: {self.visit(node.body)}" + @dispatch # type: ignore[no-redef] def visit(self, node: astx.UnaryOp) -> str: """Handle UnaryOp nodes.""" From 137ed8829cc56ee31f3a8016216fdb04e6658e14 Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Thu, 17 Oct 2024 10:18:44 -0400 Subject: [PATCH 5/9] add transpiler test for LambdaExpr --- src/astx/transpilers/python.py | 2 +- tests/transpilers/test_python.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/astx/transpilers/python.py b/src/astx/transpilers/python.py index 24c567a..2205431 100644 --- a/src/astx/transpilers/python.py +++ b/src/astx/transpilers/python.py @@ -181,7 +181,7 @@ def visit(self, node: astx.FunctionReturn) -> str: @dispatch # type: ignore[no-redef] def visit(self, node: astx.LambdaExpr) -> str: """Handle LambdaExpr nodes.""" - return f" lambda x: {self.visit(node.body)}" + return f"lambda x: {self.visit(node.body)}" @dispatch # type: ignore[no-redef] def visit(self, node: astx.UnaryOp) -> str: diff --git a/tests/transpilers/test_python.py b/tests/transpilers/test_python.py index 0ffe532..2a2ff15 100644 --- a/tests/transpilers/test_python.py +++ b/tests/transpilers/test_python.py @@ -186,6 +186,26 @@ def test_transpiler_relative_import_from_expr() -> None: assert generated_code == expected_code, "generated_code != expected_code" +def test_transpiler_lambdaexpr() -> None: + """Test astx.LambdaExpr.""" + params = astx.Arguments(astx.Argument(name="a", type_=astx.Int32)) + body = astx.BinaryOp( + op_code="+", lhs=astx.Variable(name="x"), rhs=astx.LiteralInt32(1) + ) + + lambda_expr = astx.LambdaExpr(params=params, body=body) + + # Initialize the generator + generator = astx2py.ASTxPythonTranspiler() + + # Generate Python code + generated_code = generator.visit(lambda_expr) + + expected_code = "lambda x: (x + 1)" + + assert generated_code == expected_code, "generated_code != expected_code" + + def test_transpiler_function() -> None: """Test astx.Function.""" # Function parameters From a32dc5c4f442707f7cdd7e48a12ddeb22f092522 Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Thu, 17 Oct 2024 10:24:33 -0400 Subject: [PATCH 6/9] add test for LambdaExpr class --- tests/test_callables.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_callables.py b/tests/test_callables.py index e23b083..e9b8c74 100644 --- a/tests/test_callables.py +++ b/tests/test_callables.py @@ -10,9 +10,12 @@ FunctionCall, FunctionPrototype, FunctionReturn, + LambdaExpr, ) from astx.datatypes import Int32, LiteralInt32 from astx.modifiers import ScopeKind, VisibilityKind +from astx.operators import BinaryOp +from astx.variables import Variable from astx.viz import visualize @@ -91,3 +94,14 @@ def test_function_return() -> None: assert str(fn_return) assert fn_return.get_struct() assert fn_return.get_struct(simplified=True) + + +def test_lambdaexpr() -> None: + """Test the LambdaExpr class.""" + params = Arguments(Argument(name="a", type_=Int32)) + body = BinaryOp(op_code="+", lhs=Variable(name="x"), rhs=LiteralInt32(1)) + lambda_expr = LambdaExpr(params=params, body=body) + + assert str(lambda_expr) + assert lambda_expr.get_struct() + assert lambda_expr.get_struct(simplified=True) From 0274fac7cd307d3e1e90e3cef42c64e66d1bebcd Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Sat, 19 Oct 2024 11:23:16 -0400 Subject: [PATCH 7/9] fix tests for LambdaExpr --- src/astx/callables.py | 19 ++++++++++--------- src/astx/transpilers/python.py | 4 +++- tests/test_callables.py | 2 +- tests/transpilers/test_python.py | 19 ++++++++++++++++++- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/astx/callables.py b/src/astx/callables.py index 972b289..f93881d 100644 --- a/src/astx/callables.py +++ b/src/astx/callables.py @@ -258,13 +258,13 @@ def get_struct(self, simplified: bool = False) -> ReprStruct: class LambdaExpr(Expr): """AST class for lambda expressions.""" - params: Arguments + params: Arguments = Arguments() body: Expr def __init__( self, - params: Arguments, body: Expr, + params: Arguments = Arguments(), loc: SourceLocation = NO_SOURCE_LOCATION, parent: Optional[ASTNodes] = None, ) -> None: @@ -274,14 +274,15 @@ def __init__( self.kind = ASTKind.LambdaExprKind def __str__(self) -> str: - """Return a string representation of the object.""" - return f" lambda x: {self.body}" + """Return a string representation of the lambda expression.""" + params_str = ", ".join(param.name for param in self.params) # type: ignore[attr-defined] + return f"lambda {params_str}: {self.body}" def get_struct(self, simplified: bool = False) -> ReprStruct: - """Return the AST structure of the import-from expression.""" - body = self.body - # body_str = body.get_struct(simplified) + """Return the AST structure of the lambda expression.""" key = "LambdaExpr" - - value = cast(ReprStruct, body.get_struct(simplified)) + value: ReprStruct = { + "params": self.params.get_struct(simplified), + "body": self.body.get_struct(simplified), + } return self._prepare_struct(key, value, simplified) diff --git a/src/astx/transpilers/python.py b/src/astx/transpilers/python.py index 2205431..a1ca52d 100644 --- a/src/astx/transpilers/python.py +++ b/src/astx/transpilers/python.py @@ -181,7 +181,9 @@ def visit(self, node: astx.FunctionReturn) -> str: @dispatch # type: ignore[no-redef] def visit(self, node: astx.LambdaExpr) -> str: """Handle LambdaExpr nodes.""" - return f"lambda x: {self.visit(node.body)}" + # params_str = ", ".join(arg.name for arg in node.params.args) + params_str = ", ".join(param.name for param in node.params) + return f"lambda {params_str}: {self.visit(node.body)}" @dispatch # type: ignore[no-redef] def visit(self, node: astx.UnaryOp) -> str: diff --git a/tests/test_callables.py b/tests/test_callables.py index e9b8c74..678e541 100644 --- a/tests/test_callables.py +++ b/tests/test_callables.py @@ -98,7 +98,7 @@ def test_function_return() -> None: def test_lambdaexpr() -> None: """Test the LambdaExpr class.""" - params = Arguments(Argument(name="a", type_=Int32)) + params = Arguments(Argument(name="x", type_=Int32)) body = BinaryOp(op_code="+", lhs=Variable(name="x"), rhs=LiteralInt32(1)) lambda_expr = LambdaExpr(params=params, body=body) diff --git a/tests/transpilers/test_python.py b/tests/transpilers/test_python.py index 2a2ff15..cf5d124 100644 --- a/tests/transpilers/test_python.py +++ b/tests/transpilers/test_python.py @@ -188,7 +188,7 @@ def test_transpiler_relative_import_from_expr() -> None: def test_transpiler_lambdaexpr() -> None: """Test astx.LambdaExpr.""" - params = astx.Arguments(astx.Argument(name="a", type_=astx.Int32)) + params = astx.Arguments(astx.Argument(name="x", type_=astx.Int32)) body = astx.BinaryOp( op_code="+", lhs=astx.Variable(name="x"), rhs=astx.LiteralInt32(1) ) @@ -206,6 +206,23 @@ def test_transpiler_lambdaexpr() -> None: assert generated_code == expected_code, "generated_code != expected_code" +def test_transpiler_lambdaexpr_noparams() -> None: + """Test astx.LambdaExpr without params.""" + body = astx.LiteralInt32(1) + + lambda_expr = astx.LambdaExpr(body=body) + + # Initialize the generator + generator = astx2py.ASTxPythonTranspiler() + + # Generate Python code + generated_code = generator.visit(lambda_expr) + + expected_code = "lambda : 1" + + assert generated_code == expected_code, "generated_code != expected_code" + + def test_transpiler_function() -> None: """Test astx.Function.""" # Function parameters From d5a1d257efeb06694410086bc79f9a36cab64369 Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Sat, 19 Oct 2024 11:24:46 -0400 Subject: [PATCH 8/9] fix tests for LambdaExpr --- tests/test_callables.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_callables.py b/tests/test_callables.py index 678e541..61ff378 100644 --- a/tests/test_callables.py +++ b/tests/test_callables.py @@ -105,3 +105,13 @@ def test_lambdaexpr() -> None: assert str(lambda_expr) assert lambda_expr.get_struct() assert lambda_expr.get_struct(simplified=True) + + +def test_lambdaexpr_noparams() -> None: + """Test the LambdaExpr class without params.""" + body = LiteralInt32(1) + lambda_expr = LambdaExpr(body=body) + + assert str(lambda_expr) + assert lambda_expr.get_struct() + assert lambda_expr.get_struct(simplified=True) From 13857acce7a85c276437af3e26042d4a0bd81015 Mon Sep 17 00:00:00 2001 From: Ana Krelling Date: Mon, 21 Oct 2024 08:33:25 -0400 Subject: [PATCH 9/9] cleanup --- src/astx/transpilers/python.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/astx/transpilers/python.py b/src/astx/transpilers/python.py index a1ca52d..b032203 100644 --- a/src/astx/transpilers/python.py +++ b/src/astx/transpilers/python.py @@ -181,7 +181,6 @@ def visit(self, node: astx.FunctionReturn) -> str: @dispatch # type: ignore[no-redef] def visit(self, node: astx.LambdaExpr) -> str: """Handle LambdaExpr nodes.""" - # params_str = ", ".join(arg.name for arg in node.params.args) params_str = ", ".join(param.name for param in node.params) return f"lambda {params_str}: {self.visit(node.body)}"