1414HAS_LITERAL_TUPLE = hasattr (astx , "LiteralTuple" )
1515
1616
17+ def _assert_unpacked_literal_struct (alloca : ir .AllocaInstr ) -> None :
18+ """Assert alloca points to an unpacked literal struct."""
19+ assert isinstance (alloca , ir .AllocaInstr )
20+ pointee = alloca .type .pointee
21+ assert isinstance (pointee , ir .LiteralStructType )
22+ assert not pointee .packed
23+
24+
25+ def _assert_empty_stack (visitor : LLVMLiteIRVisitor ) -> None :
26+ """Assert translator result stack is empty after evaluation."""
27+ assert len (visitor .result_stack ) == 0
28+
29+
30+ def _setup_function_context (visitor : LLVMLiteIRVisitor ) -> None :
31+ """Create a dummy function so the visitor can emit alloca instructions."""
32+ fn_ty = ir .FunctionType (ir .VoidType (), [])
33+ fn = ir .Function (visitor ._llvm .module , fn_ty , "test_tuple_fn" )
34+ bb = fn .append_basic_block ("entry" )
35+ visitor ._llvm .ir_builder .position_at_end (bb )
36+
37+
1738@pytest .mark .skipif (
1839 not HAS_LITERAL_TUPLE , reason = "astx.LiteralTuple not available"
1940)
2041@pytest .mark .parametrize ("builder_class" , [LLVMLiteIR ])
2142def test_literal_tuple_empty (builder_class : Type [Builder ]) -> None :
22- """Empty tuple lowers to constant {} (empty literal struct)."""
43+ """Empty tuple lowers to alloca of {} (empty literal struct)."""
2344 builder = builder_class ()
2445 visitor = cast (LLVMLiteIRVisitor , builder .translator )
2546 visitor .result_stack .clear ()
47+ _setup_function_context (visitor )
2648
2749 visitor .visit (astx .LiteralTuple (elements = ()))
28- const = visitor .result_stack .pop ()
50+ result = visitor .result_stack .pop ()
2951
30- assert isinstance ( const , ir . Constant )
31- assert isinstance ( const .type , ir . LiteralStructType )
32- assert len ( const . type . elements ) == 0
52+ _assert_unpacked_literal_struct ( result )
53+ assert len ( result .type . pointee . elements ) == 0
54+ _assert_empty_stack ( visitor )
3355
3456
3557@pytest .mark .skipif (
@@ -39,10 +61,11 @@ def test_literal_tuple_empty(builder_class: Type[Builder]) -> None:
3961def test_literal_tuple_homogeneous_ints (
4062 builder_class : Type [Builder ],
4163) -> None :
42- """Homogeneous integer constants lower to constant struct."""
64+ """Homogeneous integer constants lower to alloca of struct."""
4365 builder = builder_class ()
4466 visitor = cast (LLVMLiteIRVisitor , builder .translator )
4567 visitor .result_stack .clear ()
68+ _setup_function_context (visitor )
4669
4770 visitor .visit (
4871 astx .LiteralTuple (
@@ -53,16 +76,17 @@ def test_literal_tuple_homogeneous_ints(
5376 )
5477 )
5578 )
56- const = visitor .result_stack .pop ()
79+ result = visitor .result_stack .pop ()
5780
58- assert isinstance (const , ir .Constant )
59- assert isinstance (const .type , ir .LiteralStructType )
81+ _assert_unpacked_literal_struct (result )
6082 elem_count = 3
61- assert len (const .type .elements ) == elem_count
83+ pointee = result .type .pointee
84+ assert len (pointee .elements ) == elem_count
6285 assert all (
6386 isinstance (t , ir .IntType ) and t .width == 32 # noqa: PLR2004
64- for t in const . type .elements
87+ for t in pointee .elements
6588 )
89+ _assert_empty_stack (visitor )
6690
6791
6892@pytest .mark .skipif (
@@ -72,10 +96,11 @@ def test_literal_tuple_homogeneous_ints(
7296def test_literal_tuple_heterogeneous (
7397 builder_class : Type [Builder ],
7498) -> None :
75- """Heterogeneous tuple (int, float) lowers to constant struct."""
99+ """Heterogeneous tuple (int, float) lowers to alloca of struct."""
76100 builder = builder_class ()
77101 visitor = cast (LLVMLiteIRVisitor , builder .translator )
78102 visitor .result_stack .clear ()
103+ _setup_function_context (visitor )
79104
80105 visitor .visit (
81106 astx .LiteralTuple (
@@ -85,14 +110,16 @@ def test_literal_tuple_heterogeneous(
85110 )
86111 )
87112 )
88- const = visitor .result_stack .pop ()
113+ result = visitor .result_stack .pop ()
89114
90- assert isinstance (const , ir .Constant )
91- assert isinstance (const .type , ir .LiteralStructType )
115+ _assert_unpacked_literal_struct (result )
92116 elem_count = 2
93- assert len (const .type .elements ) == elem_count
94- assert isinstance (const .type .elements [0 ], ir .IntType )
95- assert isinstance (const .type .elements [1 ], ir .FloatType )
117+ pointee = result .type .pointee
118+ assert len (pointee .elements ) == elem_count
119+ assert isinstance (pointee .elements [0 ], ir .IntType )
120+ assert isinstance (pointee .elements [1 ], ir .FloatType )
121+ assert pointee .elements [1 ] == ir .FloatType ()
122+ _assert_empty_stack (visitor )
96123
97124
98125@pytest .mark .skipif (
@@ -102,15 +129,17 @@ def test_literal_tuple_heterogeneous(
102129def test_literal_tuple_single_element (
103130 builder_class : Type [Builder ],
104131) -> None :
105- """Single-element tuple lowers to constant struct {i32}."""
132+ """Single-element tuple lowers to alloca of struct {i32}."""
106133 builder = builder_class ()
107134 visitor = cast (LLVMLiteIRVisitor , builder .translator )
108135 visitor .result_stack .clear ()
136+ _setup_function_context (visitor )
109137
110138 visitor .visit (astx .LiteralTuple (elements = (astx .LiteralInt32 (42 ),)))
111- const = visitor .result_stack .pop ()
139+ result = visitor .result_stack .pop ()
112140
113- assert isinstance (const , ir .Constant )
114- assert isinstance (const .type , ir .LiteralStructType )
115- assert len (const .type .elements ) == 1
116- assert isinstance (const .type .elements [0 ], ir .IntType )
141+ _assert_unpacked_literal_struct (result )
142+ pointee = result .type .pointee
143+ assert len (pointee .elements ) == 1
144+ assert isinstance (pointee .elements [0 ], ir .IntType )
145+ _assert_empty_stack (visitor )
0 commit comments