diff --git a/src/irx/builders/llvmliteir.py b/src/irx/builders/llvmliteir.py index 6fcfd602..9c20ee42 100644 --- a/src/irx/builders/llvmliteir.py +++ b/src/irx/builders/llvmliteir.py @@ -3552,7 +3552,9 @@ def visit(self, node: astx.VariableDeclaration) -> None: type_str = node.type_.__class__.__name__.lower() # Emit the initializer - if node.value is not None: + if node.value is not None and not isinstance( + node.value, astx.Undefined + ): self.visit(node.value) init_val = self.result_stack.pop() if init_val is None: diff --git a/tests/test_if_stmt.py b/tests/test_if_stmt.py index e344668f..27f9bb30 100644 --- a/tests/test_if_stmt.py +++ b/tests/test_if_stmt.py @@ -19,6 +19,8 @@ (astx.Int16, astx.LiteralInt16), (astx.Int8, astx.LiteralInt8), (astx.Int64, astx.LiteralInt64), + (astx.Float32, astx.LiteralFloat32), + (astx.Float64, astx.LiteralFloat64), ], ) @pytest.mark.parametrize( @@ -75,17 +77,19 @@ def test_if_else_stmt( if_stmt = astx.IfStmt(condition=cond, then=then_block, else_=else_block) main_proto = astx.FunctionPrototype( - "main", args=astx.Arguments(), return_type=int_type() + "main", args=astx.Arguments(), return_type=astx.Int32() ) main_body = astx.Block() main_body.append(init_a) main_body.append(if_stmt) - main_body.append(astx.FunctionReturn(literal_type(0))) + main_body.append(astx.FunctionReturn(astx.LiteralInt32(0))) main_fn = astx.FunctionDef(prototype=main_proto, body=main_body) module.block.append(main_fn) - check_result(action, builder, module, expected_file) + check_result( + action, builder, module, expected_file, expected_output="then branch" + ) @pytest.mark.parametrize( @@ -94,6 +98,8 @@ def test_if_else_stmt( (astx.Int32, astx.LiteralInt32), (astx.Int16, astx.LiteralInt16), (astx.Int8, astx.LiteralInt8), + (astx.Float32, astx.LiteralFloat32), + (astx.Float64, astx.LiteralFloat64), ], ) @pytest.mark.parametrize( @@ -146,17 +152,20 @@ def test_if_only_stmt( if_stmt = astx.IfStmt(condition=cond, then=then_block) main_proto = astx.FunctionPrototype( - "main", args=astx.Arguments(), return_type=int_type() + "main", args=astx.Arguments(), return_type=astx.Int32() ) main_body = astx.Block() main_body.append(init_a) main_body.append(if_stmt) - main_body.append(astx.FunctionReturn(literal_type(0))) + main_body.append(PrintExpr(astx.LiteralUTF8String("done"))) + main_body.append(astx.FunctionReturn(astx.LiteralInt32(0))) main_fn = astx.FunctionDef(prototype=main_proto, body=main_body) module.block.append(main_fn) - check_result(action, builder, module, expected_file) + check_result( + action, builder, module, expected_file, expected_output="done" + ) @pytest.mark.parametrize("builder_class", [LLVMLiteIR]) diff --git a/tests/test_variable_assignment.py b/tests/test_variable_assignment.py index bf0b28b2..dd60726e 100644 --- a/tests/test_variable_assignment.py +++ b/tests/test_variable_assignment.py @@ -7,62 +7,116 @@ from irx.builders.base import Builder from irx.builders.llvmliteir import LLVMLiteIR +from irx.system import PrintExpr from .conftest import check_result @pytest.mark.parametrize( - "int_type, literal_type", + "var_type, literal_type, expected_output", [ - (astx.Int32, astx.LiteralInt32), - (astx.Int16, astx.LiteralInt16), - (astx.Int8, astx.LiteralInt8), - (astx.Int64, astx.LiteralInt64), + (astx.Int32, astx.LiteralInt32, "42"), + (astx.Int16, astx.LiteralInt16, "42"), + (astx.Int8, astx.LiteralInt8, "42"), + (astx.Int64, astx.LiteralInt64, "42"), + (astx.Float32, astx.LiteralFloat32, "42.000000"), + (astx.Float64, astx.LiteralFloat64, "42.000000"), ], ) @pytest.mark.parametrize( "builder_class", [ - # ("translate", "test_variable_assignment.ll"), LLVMLiteIR, ], ) def test_variable_assignment( builder_class: type[Builder], - int_type: type, + var_type: type, literal_type: type, + expected_output: str, ) -> None: """ - title: Test VariableAssignment by reassigning and returning. + title: Test VariableAssignment by reassigning and printing. parameters: builder_class: type: type[Builder] - int_type: + var_type: type: type literal_type: type: type + expected_output: + type: str """ builder = builder_class() module = builder.module() decl = astx.InlineVariableDeclaration( name="x", - type_=int_type(), + type_=var_type(), value=literal_type(10), mutability=astx.MutabilityKind.mutable, ) assignment = astx.VariableAssignment(name="x", value=literal_type(42)) proto = astx.FunctionPrototype( - name="main", args=astx.Arguments(), return_type=int_type() + name="main", args=astx.Arguments(), return_type=astx.Int32() ) fn_block = astx.Block() fn_block.append(decl) fn_block.append(assignment) - fn_block.append(astx.FunctionReturn(astx.Identifier("x"))) + fn_block.append(PrintExpr(astx.Identifier("x"))) + fn_block.append(astx.FunctionReturn(astx.LiteralInt32(0))) + fn_main = astx.FunctionDef(prototype=proto, body=fn_block) + + module.block.append(fn_main) + + check_result("build", builder, module, expected_output=expected_output) + + +@pytest.mark.parametrize( + "var_type, expected_output", + [ + (astx.Int8, "0"), + (astx.Int16, "0"), + (astx.Int32, "0"), + (astx.Int64, "0"), + (astx.Float32, "0.000000"), + (astx.Float64, "0.000000"), + ], +) +@pytest.mark.parametrize("builder_class", [LLVMLiteIR]) +def test_variable_declaration_no_initializer( + builder_class: type[Builder], + var_type: type, + expected_output: str, +) -> None: + """ + title: Test VariableDeclaration without an initializer defaults to zero. + parameters: + builder_class: + type: type[Builder] + var_type: + type: type + expected_output: + type: str + """ + builder = builder_class() + module = builder.module() + + decl = astx.VariableDeclaration( + name="x", + type_=var_type(), + ) + + proto = astx.FunctionPrototype( + name="main", args=astx.Arguments(), return_type=astx.Int32() + ) + fn_block = astx.Block() + fn_block.append(decl) + fn_block.append(PrintExpr(astx.Identifier("x"))) + fn_block.append(astx.FunctionReturn(astx.LiteralInt32(0))) fn_main = astx.FunctionDef(prototype=proto, body=fn_block) module.block.append(fn_main) - expected_output = "42" check_result("build", builder, module, expected_output=expected_output)