machine-dialect 0.1.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. machine_dialect/__main__.py +667 -0
  2. machine_dialect/agent/__init__.py +5 -0
  3. machine_dialect/agent/agent.py +360 -0
  4. machine_dialect/ast/__init__.py +95 -0
  5. machine_dialect/ast/ast_node.py +35 -0
  6. machine_dialect/ast/call_expression.py +82 -0
  7. machine_dialect/ast/dict_extraction.py +60 -0
  8. machine_dialect/ast/expressions.py +439 -0
  9. machine_dialect/ast/literals.py +309 -0
  10. machine_dialect/ast/program.py +35 -0
  11. machine_dialect/ast/statements.py +1433 -0
  12. machine_dialect/ast/tests/test_ast_string_representation.py +62 -0
  13. machine_dialect/ast/tests/test_boolean_literal.py +29 -0
  14. machine_dialect/ast/tests/test_collection_hir.py +138 -0
  15. machine_dialect/ast/tests/test_define_statement.py +142 -0
  16. machine_dialect/ast/tests/test_desugar.py +541 -0
  17. machine_dialect/ast/tests/test_foreach_desugar.py +245 -0
  18. machine_dialect/cfg/__init__.py +6 -0
  19. machine_dialect/cfg/config.py +156 -0
  20. machine_dialect/cfg/examples.py +221 -0
  21. machine_dialect/cfg/generate_with_ai.py +187 -0
  22. machine_dialect/cfg/openai_generation.py +200 -0
  23. machine_dialect/cfg/parser.py +94 -0
  24. machine_dialect/cfg/tests/__init__.py +1 -0
  25. machine_dialect/cfg/tests/test_cfg_parser.py +252 -0
  26. machine_dialect/cfg/tests/test_config.py +188 -0
  27. machine_dialect/cfg/tests/test_examples.py +391 -0
  28. machine_dialect/cfg/tests/test_generate_with_ai.py +354 -0
  29. machine_dialect/cfg/tests/test_openai_generation.py +256 -0
  30. machine_dialect/codegen/__init__.py +5 -0
  31. machine_dialect/codegen/bytecode_module.py +89 -0
  32. machine_dialect/codegen/bytecode_serializer.py +300 -0
  33. machine_dialect/codegen/opcodes.py +101 -0
  34. machine_dialect/codegen/register_codegen.py +1996 -0
  35. machine_dialect/codegen/symtab.py +208 -0
  36. machine_dialect/codegen/tests/__init__.py +1 -0
  37. machine_dialect/codegen/tests/test_array_operations_codegen.py +295 -0
  38. machine_dialect/codegen/tests/test_bytecode_serializer.py +185 -0
  39. machine_dialect/codegen/tests/test_register_codegen_ssa.py +324 -0
  40. machine_dialect/codegen/tests/test_symtab.py +418 -0
  41. machine_dialect/codegen/vm_serializer.py +621 -0
  42. machine_dialect/compiler/__init__.py +18 -0
  43. machine_dialect/compiler/compiler.py +197 -0
  44. machine_dialect/compiler/config.py +149 -0
  45. machine_dialect/compiler/context.py +149 -0
  46. machine_dialect/compiler/phases/__init__.py +19 -0
  47. machine_dialect/compiler/phases/bytecode_optimization.py +90 -0
  48. machine_dialect/compiler/phases/codegen.py +40 -0
  49. machine_dialect/compiler/phases/hir_generation.py +39 -0
  50. machine_dialect/compiler/phases/mir_generation.py +86 -0
  51. machine_dialect/compiler/phases/optimization.py +110 -0
  52. machine_dialect/compiler/phases/parsing.py +39 -0
  53. machine_dialect/compiler/pipeline.py +143 -0
  54. machine_dialect/compiler/tests/__init__.py +1 -0
  55. machine_dialect/compiler/tests/test_compiler.py +568 -0
  56. machine_dialect/compiler/vm_runner.py +173 -0
  57. machine_dialect/errors/__init__.py +32 -0
  58. machine_dialect/errors/exceptions.py +369 -0
  59. machine_dialect/errors/messages.py +82 -0
  60. machine_dialect/errors/tests/__init__.py +0 -0
  61. machine_dialect/errors/tests/test_expected_token_errors.py +188 -0
  62. machine_dialect/errors/tests/test_name_errors.py +118 -0
  63. machine_dialect/helpers/__init__.py +0 -0
  64. machine_dialect/helpers/stopwords.py +225 -0
  65. machine_dialect/helpers/validators.py +30 -0
  66. machine_dialect/lexer/__init__.py +9 -0
  67. machine_dialect/lexer/constants.py +23 -0
  68. machine_dialect/lexer/lexer.py +907 -0
  69. machine_dialect/lexer/tests/__init__.py +0 -0
  70. machine_dialect/lexer/tests/helpers.py +86 -0
  71. machine_dialect/lexer/tests/test_apostrophe_identifiers.py +122 -0
  72. machine_dialect/lexer/tests/test_backtick_identifiers.py +140 -0
  73. machine_dialect/lexer/tests/test_boolean_literals.py +108 -0
  74. machine_dialect/lexer/tests/test_case_insensitive_keywords.py +188 -0
  75. machine_dialect/lexer/tests/test_comments.py +200 -0
  76. machine_dialect/lexer/tests/test_double_asterisk_keywords.py +127 -0
  77. machine_dialect/lexer/tests/test_lexer_position.py +113 -0
  78. machine_dialect/lexer/tests/test_list_tokens.py +282 -0
  79. machine_dialect/lexer/tests/test_stopwords.py +80 -0
  80. machine_dialect/lexer/tests/test_strict_equality.py +129 -0
  81. machine_dialect/lexer/tests/test_token.py +41 -0
  82. machine_dialect/lexer/tests/test_tokenization.py +294 -0
  83. machine_dialect/lexer/tests/test_underscore_literals.py +343 -0
  84. machine_dialect/lexer/tests/test_url_literals.py +169 -0
  85. machine_dialect/lexer/tokens.py +487 -0
  86. machine_dialect/linter/__init__.py +10 -0
  87. machine_dialect/linter/__main__.py +144 -0
  88. machine_dialect/linter/linter.py +154 -0
  89. machine_dialect/linter/rules/__init__.py +8 -0
  90. machine_dialect/linter/rules/base.py +112 -0
  91. machine_dialect/linter/rules/statement_termination.py +99 -0
  92. machine_dialect/linter/tests/__init__.py +1 -0
  93. machine_dialect/linter/tests/mdrules/__init__.py +0 -0
  94. machine_dialect/linter/tests/mdrules/test_md101_statement_termination.py +181 -0
  95. machine_dialect/linter/tests/test_linter.py +81 -0
  96. machine_dialect/linter/tests/test_rules.py +110 -0
  97. machine_dialect/linter/tests/test_violations.py +71 -0
  98. machine_dialect/linter/violations.py +51 -0
  99. machine_dialect/mir/__init__.py +69 -0
  100. machine_dialect/mir/analyses/__init__.py +20 -0
  101. machine_dialect/mir/analyses/alias_analysis.py +315 -0
  102. machine_dialect/mir/analyses/dominance_analysis.py +49 -0
  103. machine_dialect/mir/analyses/escape_analysis.py +286 -0
  104. machine_dialect/mir/analyses/loop_analysis.py +272 -0
  105. machine_dialect/mir/analyses/tests/test_type_analysis.py +736 -0
  106. machine_dialect/mir/analyses/type_analysis.py +448 -0
  107. machine_dialect/mir/analyses/use_def_chains.py +232 -0
  108. machine_dialect/mir/basic_block.py +385 -0
  109. machine_dialect/mir/dataflow.py +445 -0
  110. machine_dialect/mir/debug_info.py +208 -0
  111. machine_dialect/mir/hir_to_mir.py +1738 -0
  112. machine_dialect/mir/mir_dumper.py +366 -0
  113. machine_dialect/mir/mir_function.py +167 -0
  114. machine_dialect/mir/mir_instructions.py +1877 -0
  115. machine_dialect/mir/mir_interpreter.py +556 -0
  116. machine_dialect/mir/mir_module.py +225 -0
  117. machine_dialect/mir/mir_printer.py +480 -0
  118. machine_dialect/mir/mir_transformer.py +410 -0
  119. machine_dialect/mir/mir_types.py +367 -0
  120. machine_dialect/mir/mir_validation.py +455 -0
  121. machine_dialect/mir/mir_values.py +268 -0
  122. machine_dialect/mir/optimization_config.py +233 -0
  123. machine_dialect/mir/optimization_pass.py +251 -0
  124. machine_dialect/mir/optimization_pipeline.py +355 -0
  125. machine_dialect/mir/optimizations/__init__.py +84 -0
  126. machine_dialect/mir/optimizations/algebraic_simplification.py +733 -0
  127. machine_dialect/mir/optimizations/branch_prediction.py +372 -0
  128. machine_dialect/mir/optimizations/constant_propagation.py +634 -0
  129. machine_dialect/mir/optimizations/cse.py +398 -0
  130. machine_dialect/mir/optimizations/dce.py +288 -0
  131. machine_dialect/mir/optimizations/inlining.py +551 -0
  132. machine_dialect/mir/optimizations/jump_threading.py +487 -0
  133. machine_dialect/mir/optimizations/licm.py +405 -0
  134. machine_dialect/mir/optimizations/loop_unrolling.py +366 -0
  135. machine_dialect/mir/optimizations/strength_reduction.py +422 -0
  136. machine_dialect/mir/optimizations/tail_call.py +207 -0
  137. machine_dialect/mir/optimizations/tests/test_loop_unrolling.py +483 -0
  138. machine_dialect/mir/optimizations/type_narrowing.py +397 -0
  139. machine_dialect/mir/optimizations/type_specialization.py +447 -0
  140. machine_dialect/mir/optimizations/type_specific.py +906 -0
  141. machine_dialect/mir/optimize_mir.py +89 -0
  142. machine_dialect/mir/pass_manager.py +391 -0
  143. machine_dialect/mir/profiling/__init__.py +26 -0
  144. machine_dialect/mir/profiling/profile_collector.py +318 -0
  145. machine_dialect/mir/profiling/profile_data.py +372 -0
  146. machine_dialect/mir/profiling/profile_reader.py +272 -0
  147. machine_dialect/mir/profiling/profile_writer.py +226 -0
  148. machine_dialect/mir/register_allocation.py +302 -0
  149. machine_dialect/mir/reporting/__init__.py +17 -0
  150. machine_dialect/mir/reporting/optimization_reporter.py +314 -0
  151. machine_dialect/mir/reporting/report_formatter.py +289 -0
  152. machine_dialect/mir/ssa_construction.py +342 -0
  153. machine_dialect/mir/tests/__init__.py +1 -0
  154. machine_dialect/mir/tests/test_algebraic_associativity.py +204 -0
  155. machine_dialect/mir/tests/test_algebraic_complex_patterns.py +221 -0
  156. machine_dialect/mir/tests/test_algebraic_division.py +126 -0
  157. machine_dialect/mir/tests/test_algebraic_simplification.py +863 -0
  158. machine_dialect/mir/tests/test_basic_block.py +425 -0
  159. machine_dialect/mir/tests/test_branch_prediction.py +459 -0
  160. machine_dialect/mir/tests/test_call_lowering.py +168 -0
  161. machine_dialect/mir/tests/test_collection_lowering.py +604 -0
  162. machine_dialect/mir/tests/test_cross_block_constant_propagation.py +255 -0
  163. machine_dialect/mir/tests/test_custom_passes.py +166 -0
  164. machine_dialect/mir/tests/test_debug_info.py +285 -0
  165. machine_dialect/mir/tests/test_dict_extraction_lowering.py +192 -0
  166. machine_dialect/mir/tests/test_dictionary_lowering.py +299 -0
  167. machine_dialect/mir/tests/test_double_negation.py +231 -0
  168. machine_dialect/mir/tests/test_escape_analysis.py +233 -0
  169. machine_dialect/mir/tests/test_hir_to_mir.py +465 -0
  170. machine_dialect/mir/tests/test_hir_to_mir_complete.py +389 -0
  171. machine_dialect/mir/tests/test_hir_to_mir_simple.py +130 -0
  172. machine_dialect/mir/tests/test_inlining.py +435 -0
  173. machine_dialect/mir/tests/test_licm.py +472 -0
  174. machine_dialect/mir/tests/test_mir_dumper.py +313 -0
  175. machine_dialect/mir/tests/test_mir_instructions.py +445 -0
  176. machine_dialect/mir/tests/test_mir_module.py +860 -0
  177. machine_dialect/mir/tests/test_mir_printer.py +387 -0
  178. machine_dialect/mir/tests/test_mir_types.py +123 -0
  179. machine_dialect/mir/tests/test_mir_types_enhanced.py +132 -0
  180. machine_dialect/mir/tests/test_mir_validation.py +378 -0
  181. machine_dialect/mir/tests/test_mir_values.py +168 -0
  182. machine_dialect/mir/tests/test_one_based_indexing.py +202 -0
  183. machine_dialect/mir/tests/test_optimization_helpers.py +60 -0
  184. machine_dialect/mir/tests/test_optimization_pipeline.py +554 -0
  185. machine_dialect/mir/tests/test_optimization_reporter.py +318 -0
  186. machine_dialect/mir/tests/test_pass_manager.py +294 -0
  187. machine_dialect/mir/tests/test_pass_registration.py +64 -0
  188. machine_dialect/mir/tests/test_profiling.py +356 -0
  189. machine_dialect/mir/tests/test_register_allocation.py +307 -0
  190. machine_dialect/mir/tests/test_report_formatters.py +372 -0
  191. machine_dialect/mir/tests/test_ssa_construction.py +433 -0
  192. machine_dialect/mir/tests/test_tail_call.py +236 -0
  193. machine_dialect/mir/tests/test_type_annotated_instructions.py +192 -0
  194. machine_dialect/mir/tests/test_type_narrowing.py +277 -0
  195. machine_dialect/mir/tests/test_type_specialization.py +421 -0
  196. machine_dialect/mir/tests/test_type_specific_optimization.py +545 -0
  197. machine_dialect/mir/tests/test_type_specific_optimization_advanced.py +382 -0
  198. machine_dialect/mir/type_inference.py +368 -0
  199. machine_dialect/parser/__init__.py +12 -0
  200. machine_dialect/parser/enums.py +45 -0
  201. machine_dialect/parser/parser.py +3655 -0
  202. machine_dialect/parser/protocols.py +11 -0
  203. machine_dialect/parser/symbol_table.py +169 -0
  204. machine_dialect/parser/tests/__init__.py +0 -0
  205. machine_dialect/parser/tests/helper_functions.py +193 -0
  206. machine_dialect/parser/tests/test_action_statements.py +334 -0
  207. machine_dialect/parser/tests/test_boolean_literal_expressions.py +152 -0
  208. machine_dialect/parser/tests/test_call_statements.py +154 -0
  209. machine_dialect/parser/tests/test_call_statements_errors.py +187 -0
  210. machine_dialect/parser/tests/test_collection_mutations.py +264 -0
  211. machine_dialect/parser/tests/test_conditional_expressions.py +343 -0
  212. machine_dialect/parser/tests/test_define_integration.py +468 -0
  213. machine_dialect/parser/tests/test_define_statements.py +311 -0
  214. machine_dialect/parser/tests/test_dict_extraction.py +115 -0
  215. machine_dialect/parser/tests/test_empty_literal.py +155 -0
  216. machine_dialect/parser/tests/test_float_literal_expressions.py +163 -0
  217. machine_dialect/parser/tests/test_identifier_expressions.py +57 -0
  218. machine_dialect/parser/tests/test_if_empty_block.py +61 -0
  219. machine_dialect/parser/tests/test_if_statements.py +299 -0
  220. machine_dialect/parser/tests/test_illegal_tokens.py +86 -0
  221. machine_dialect/parser/tests/test_infix_expressions.py +680 -0
  222. machine_dialect/parser/tests/test_integer_literal_expressions.py +137 -0
  223. machine_dialect/parser/tests/test_interaction_statements.py +269 -0
  224. machine_dialect/parser/tests/test_list_literals.py +277 -0
  225. machine_dialect/parser/tests/test_no_none_in_ast.py +94 -0
  226. machine_dialect/parser/tests/test_panic_mode_recovery.py +171 -0
  227. machine_dialect/parser/tests/test_parse_errors.py +114 -0
  228. machine_dialect/parser/tests/test_possessive_syntax.py +182 -0
  229. machine_dialect/parser/tests/test_prefix_expressions.py +415 -0
  230. machine_dialect/parser/tests/test_program.py +13 -0
  231. machine_dialect/parser/tests/test_return_statements.py +89 -0
  232. machine_dialect/parser/tests/test_set_statements.py +152 -0
  233. machine_dialect/parser/tests/test_strict_equality.py +258 -0
  234. machine_dialect/parser/tests/test_symbol_table.py +217 -0
  235. machine_dialect/parser/tests/test_url_literal_expressions.py +209 -0
  236. machine_dialect/parser/tests/test_utility_statements.py +423 -0
  237. machine_dialect/parser/token_buffer.py +159 -0
  238. machine_dialect/repl/__init__.py +3 -0
  239. machine_dialect/repl/repl.py +426 -0
  240. machine_dialect/repl/tests/__init__.py +0 -0
  241. machine_dialect/repl/tests/test_repl.py +606 -0
  242. machine_dialect/semantic/__init__.py +12 -0
  243. machine_dialect/semantic/analyzer.py +906 -0
  244. machine_dialect/semantic/error_messages.py +189 -0
  245. machine_dialect/semantic/tests/__init__.py +1 -0
  246. machine_dialect/semantic/tests/test_analyzer.py +364 -0
  247. machine_dialect/semantic/tests/test_error_messages.py +104 -0
  248. machine_dialect/tests/edge_cases/__init__.py +10 -0
  249. machine_dialect/tests/edge_cases/test_boundary_access.py +256 -0
  250. machine_dialect/tests/edge_cases/test_empty_collections.py +166 -0
  251. machine_dialect/tests/edge_cases/test_invalid_operations.py +243 -0
  252. machine_dialect/tests/edge_cases/test_named_list_edge_cases.py +295 -0
  253. machine_dialect/tests/edge_cases/test_nested_structures.py +313 -0
  254. machine_dialect/tests/edge_cases/test_type_mixing.py +277 -0
  255. machine_dialect/tests/integration/test_array_operations_emulation.py +248 -0
  256. machine_dialect/tests/integration/test_list_compilation.py +395 -0
  257. machine_dialect/tests/integration/test_lists_and_dictionaries.py +322 -0
  258. machine_dialect/type_checking/__init__.py +21 -0
  259. machine_dialect/type_checking/tests/__init__.py +1 -0
  260. machine_dialect/type_checking/tests/test_type_system.py +230 -0
  261. machine_dialect/type_checking/type_system.py +270 -0
  262. machine_dialect-0.1.0a1.dist-info/METADATA +128 -0
  263. machine_dialect-0.1.0a1.dist-info/RECORD +268 -0
  264. machine_dialect-0.1.0a1.dist-info/WHEEL +5 -0
  265. machine_dialect-0.1.0a1.dist-info/entry_points.txt +3 -0
  266. machine_dialect-0.1.0a1.dist-info/licenses/LICENSE +201 -0
  267. machine_dialect-0.1.0a1.dist-info/top_level.txt +2 -0
  268. machine_dialect_vm/__init__.pyi +15 -0
@@ -0,0 +1,395 @@
1
+ """Integration tests for list compilation to bytecode.
2
+
3
+ Tests the full compilation pipeline from source code to bytecode
4
+ for list literal types.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from machine_dialect.codegen.register_codegen import generate_bytecode_from_mir
10
+ from machine_dialect.compiler.config import CompilerConfig
11
+ from machine_dialect.compiler.pipeline import CompilationPipeline
12
+
13
+
14
+ class TestListCompilation:
15
+ """Test compilation of list literals to bytecode."""
16
+
17
+ def test_compile_unordered_list(self) -> None:
18
+ """Test compiling an unordered list."""
19
+ source = """
20
+ Define `shopping` as unordered list.
21
+ Set `shopping` to:
22
+ - _"milk"_.
23
+ - _"bread"_.
24
+ - _"eggs"_.
25
+ """
26
+ config = CompilerConfig(verbose=False)
27
+ pipeline = CompilationPipeline(config)
28
+
29
+ # Create temp file
30
+ test_file = Path("test_unordered.md")
31
+ test_file.write_text(source)
32
+
33
+ try:
34
+ context = pipeline.compile_file(test_file)
35
+
36
+ # Check no errors
37
+ assert not context.has_errors(), f"Compilation errors: {context.errors}"
38
+
39
+ # Check MIR was generated
40
+ assert hasattr(context, "mir_module"), "No MIR module generated"
41
+ assert context.mir_module is not None
42
+
43
+ # Generate bytecode
44
+ bytecode_module, _metadata = generate_bytecode_from_mir(context.mir_module)
45
+
46
+ # Check bytecode was generated
47
+ assert bytecode_module is not None
48
+ serialized = bytecode_module.serialize()
49
+ assert len(serialized) > 0, "No bytecode generated"
50
+
51
+ # Verify bytecode contains array creation opcode (0x21 = NEW_ARRAY_R)
52
+ assert b"\x21" in serialized, "No array creation instruction found"
53
+
54
+ finally:
55
+ test_file.unlink(missing_ok=True)
56
+
57
+ def test_compile_ordered_list(self) -> None:
58
+ """Test compiling an ordered list."""
59
+ source = """
60
+ Define `steps` as ordered list.
61
+ Set `steps` to:
62
+ 1. _"First"_.
63
+ 2. _"Second"_.
64
+ 3. _"Third"_.
65
+ """
66
+ config = CompilerConfig(verbose=False)
67
+ pipeline = CompilationPipeline(config)
68
+
69
+ test_file = Path("test_ordered.md")
70
+ test_file.write_text(source)
71
+
72
+ try:
73
+ context = pipeline.compile_file(test_file)
74
+
75
+ assert not context.has_errors(), f"Compilation errors: {context.errors}"
76
+ assert hasattr(context, "mir_module")
77
+ assert context.mir_module is not None
78
+
79
+ bytecode_module, _metadata = generate_bytecode_from_mir(context.mir_module)
80
+ serialized = bytecode_module.serialize()
81
+
82
+ # Check for array creation
83
+ assert b"\x21" in serialized, "No array creation instruction"
84
+ # Check for array set operations (0x23 = ARRAY_SET_R)
85
+ assert b"\x23" in serialized, "No array set instructions"
86
+
87
+ finally:
88
+ test_file.unlink(missing_ok=True)
89
+
90
+ def test_compile_named_list(self) -> None:
91
+ """Test compiling a named list (dictionary)."""
92
+ source = """
93
+ Define `person` as named list.
94
+ Set `person` to:
95
+ - _"name"_: _"Alice"_.
96
+ - _"age"_: _30_.
97
+ - _"active"_: _yes_.
98
+ """
99
+ config = CompilerConfig(verbose=False)
100
+ pipeline = CompilationPipeline(config)
101
+
102
+ test_file = Path("test_named.md")
103
+ test_file.write_text(source)
104
+
105
+ try:
106
+ context = pipeline.compile_file(test_file)
107
+
108
+ assert not context.has_errors(), f"Compilation errors: {context.errors}"
109
+ assert hasattr(context, "mir_module")
110
+ assert context.mir_module is not None
111
+
112
+ # Check that dictionary operations are generated in MIR
113
+ main_func = context.mir_module.get_function("__main__")
114
+ assert main_func is not None
115
+
116
+ # Verify DictCreate instruction exists in MIR
117
+ from machine_dialect.mir.mir_instructions import DictCreate, DictSet
118
+
119
+ dict_creates = []
120
+ dict_sets = []
121
+ for block in main_func.cfg.blocks.values():
122
+ for inst in block.instructions:
123
+ if isinstance(inst, DictCreate):
124
+ dict_creates.append(inst)
125
+ elif isinstance(inst, DictSet):
126
+ dict_sets.append(inst)
127
+
128
+ assert len(dict_creates) > 0, "No DictCreate instructions found in MIR"
129
+ assert len(dict_sets) >= 3, "Expected at least 3 DictSet instructions for name, age, and active"
130
+
131
+ # TODO: Bytecode generation for dictionary operations not yet implemented
132
+ # Once implemented, the bytecode should contain dictionary creation/set instructions
133
+ # For now, we just verify the MIR is correct
134
+
135
+ finally:
136
+ test_file.unlink(missing_ok=True)
137
+
138
+ def test_compile_mixed_type_list(self) -> None:
139
+ """Test compiling a list with mixed types."""
140
+ source = """
141
+ Define `data` as unordered list.
142
+ Set `data` to:
143
+ - _42_.
144
+ - _"text"_.
145
+ - _3.14_.
146
+ - _yes_.
147
+ - _empty_.
148
+ """
149
+ config = CompilerConfig(verbose=False)
150
+ pipeline = CompilationPipeline(config)
151
+
152
+ test_file = Path("test_mixed.md")
153
+ test_file.write_text(source)
154
+
155
+ try:
156
+ context = pipeline.compile_file(test_file)
157
+
158
+ assert not context.has_errors(), f"Compilation errors: {context.errors}"
159
+ assert context.mir_module is not None
160
+
161
+ bytecode_module, _metadata = generate_bytecode_from_mir(context.mir_module)
162
+ serialized = bytecode_module.serialize()
163
+
164
+ # Should handle all types
165
+ assert len(serialized) > 50, "Bytecode too small for mixed list"
166
+ assert b"\x21" in serialized, "No array creation"
167
+ assert b"\x23" in serialized, "No array set operations"
168
+
169
+ finally:
170
+ test_file.unlink(missing_ok=True)
171
+
172
+ def test_compile_nested_lists(self) -> None:
173
+ """Test compiling nested lists."""
174
+ source = """
175
+ Define `matrix` as unordered list.
176
+ Define `row1` as unordered list.
177
+ Define `row2` as unordered list.
178
+
179
+ Set `row1` to:
180
+ - _1_.
181
+ - _2_.
182
+ - _3_.
183
+
184
+ Set `row2` to:
185
+ - _4_.
186
+ - _5_.
187
+ - _6_.
188
+
189
+ Set `matrix` to:
190
+ - `row1`.
191
+ - `row2`.
192
+ """
193
+ config = CompilerConfig(verbose=False)
194
+ pipeline = CompilationPipeline(config)
195
+
196
+ test_file = Path("test_nested.md")
197
+ test_file.write_text(source)
198
+
199
+ try:
200
+ context = pipeline.compile_file(test_file)
201
+
202
+ assert not context.has_errors(), f"Compilation errors: {context.errors}"
203
+ assert context.mir_module is not None
204
+
205
+ bytecode_module, _metadata = generate_bytecode_from_mir(context.mir_module)
206
+ serialized = bytecode_module.serialize()
207
+
208
+ # Should have multiple array creations
209
+ array_create_count = serialized.count(b"\x21")
210
+ assert array_create_count >= 3, f"Expected at least 3 arrays, found {array_create_count}"
211
+
212
+ finally:
213
+ test_file.unlink(missing_ok=True)
214
+
215
+ def test_empty_list_compilation(self) -> None:
216
+ """Test compiling an empty list."""
217
+ source = """
218
+ Define `empty_list` as unordered list.
219
+ Set `empty_list` to:
220
+ """
221
+ config = CompilerConfig(verbose=False)
222
+ pipeline = CompilationPipeline(config)
223
+
224
+ test_file = Path("test_empty.md")
225
+ test_file.write_text(source)
226
+
227
+ try:
228
+ context = pipeline.compile_file(test_file)
229
+
230
+ # Empty list should compile successfully
231
+ assert not context.has_errors(), f"Compilation errors: {context.errors}"
232
+ assert context.mir_module is not None
233
+
234
+ bytecode_module, _metadata = generate_bytecode_from_mir(context.mir_module)
235
+ serialized = bytecode_module.serialize()
236
+
237
+ # Should create array with size 0
238
+ assert b"\x21" in serialized, "No array creation"
239
+
240
+ finally:
241
+ test_file.unlink(missing_ok=True)
242
+
243
+ def test_list_type_mismatch_error(self) -> None:
244
+ """Test that mismatched list types produce an error."""
245
+ source = """
246
+ Define `mylist` as unordered list.
247
+ Set `mylist` to:
248
+ 1. _"This is ordered"_
249
+ 2. _"Not unordered"_
250
+ """
251
+ config = CompilerConfig(verbose=False)
252
+ pipeline = CompilationPipeline(config)
253
+
254
+ test_file = Path("test_mismatch.md")
255
+ test_file.write_text(source)
256
+
257
+ try:
258
+ context = pipeline.compile_file(test_file)
259
+
260
+ # Should have type mismatch error
261
+ assert context.has_errors(), "Should have type mismatch error"
262
+ error_messages = " ".join(context.errors)
263
+ assert "Ordered List" in error_messages or "type" in error_messages.lower()
264
+
265
+ finally:
266
+ test_file.unlink(missing_ok=True)
267
+
268
+
269
+ class TestListBytecodeStructure:
270
+ """Test the structure of generated bytecode for lists."""
271
+
272
+ def test_bytecode_constants_for_list_elements(self) -> None:
273
+ """Test that list elements are properly stored in constant pool."""
274
+ source = """
275
+ Define `nums` as ordered list.
276
+ Set `nums` to:
277
+ 1. _100_.
278
+ 2. _200_.
279
+ 3. _300_.
280
+ """
281
+ config = CompilerConfig(verbose=False)
282
+ pipeline = CompilationPipeline(config)
283
+
284
+ test_file = Path("test_constants.md")
285
+ test_file.write_text(source)
286
+
287
+ try:
288
+ context = pipeline.compile_file(test_file)
289
+ assert not context.has_errors()
290
+ assert context.mir_module is not None
291
+
292
+ # Generate bytecode
293
+ bytecode_module, _metadata = generate_bytecode_from_mir(context.mir_module)
294
+
295
+ # Check constant pool contains our values
296
+ # Constants are stored as (tag, value) tuples
297
+ constants_values = [val for tag, val in bytecode_module.chunks[0].constants]
298
+ assert 100 in constants_values
299
+ assert 200 in constants_values
300
+ assert 300 in constants_values
301
+
302
+ # Also verify bytecode contains array operations
303
+ serialized = bytecode_module.serialize()
304
+ assert b"\x21" in serialized, "No array creation instruction"
305
+ assert b"\x23" in serialized, "No array set operations"
306
+
307
+ finally:
308
+ test_file.unlink(missing_ok=True)
309
+
310
+ def test_bytecode_constants_all_types(self) -> None:
311
+ """Test that all data types are properly stored in constant pool."""
312
+ source = """
313
+ Define `mixed` as unordered list.
314
+ Set `mixed` to:
315
+ - _"hello world"_.
316
+ - _42_.
317
+ - _3.14_.
318
+ - _yes_.
319
+ - _no_.
320
+ """
321
+ config = CompilerConfig(verbose=False)
322
+ pipeline = CompilationPipeline(config)
323
+
324
+ test_file = Path("test_all_types.md")
325
+ test_file.write_text(source)
326
+
327
+ try:
328
+ context = pipeline.compile_file(test_file)
329
+ assert not context.has_errors()
330
+ assert context.mir_module is not None
331
+
332
+ bytecode_module, _metadata = generate_bytecode_from_mir(context.mir_module)
333
+
334
+ # Check constant pool contains our values
335
+ from machine_dialect.codegen.bytecode_module import ConstantTag
336
+
337
+ constants = bytecode_module.chunks[0].constants
338
+
339
+ # Extract values by type
340
+ strings = [val for tag, val in constants if tag == ConstantTag.STRING]
341
+ ints = [val for tag, val in constants if tag == ConstantTag.INT]
342
+ floats = [val for tag, val in constants if tag == ConstantTag.FLOAT]
343
+ bools = [val for tag, val in constants if tag == ConstantTag.BOOL]
344
+
345
+ # Check all values are in the pool
346
+ assert "hello world" in strings, f"String not in pool. Strings: {strings}"
347
+ assert 42 in ints, f"Integer not in pool. Ints: {ints}"
348
+ assert 3.14 in floats, f"Float not in pool. Floats: {floats}"
349
+ assert True in bools, f"True not in pool. Bools: {bools}"
350
+ assert False in bools, f"False not in pool. Bools: {bools}"
351
+
352
+ finally:
353
+ test_file.unlink(missing_ok=True)
354
+
355
+ def test_bytecode_size_scaling(self) -> None:
356
+ """Test that bytecode size scales with list size."""
357
+ # Small list
358
+ small_source = """
359
+ Define `small` as unordered list.
360
+ Set `small` to:
361
+ - _1_.
362
+ - _2_.
363
+ """
364
+ # Large list
365
+ large_items = "\n".join([f"- _{i}_." for i in range(20)])
366
+ large_source = f"""
367
+ Define `large` as unordered list.
368
+ Set `large` to:
369
+ {large_items}
370
+ """
371
+
372
+ config = CompilerConfig(verbose=False)
373
+ pipeline = CompilationPipeline(config)
374
+
375
+ # Compile small list
376
+ test_file = Path("test_size.md")
377
+ test_file.write_text(small_source)
378
+ context = pipeline.compile_file(test_file)
379
+ assert not context.has_errors()
380
+ assert context.mir_module is not None
381
+ small_bytecode, _ = generate_bytecode_from_mir(context.mir_module)
382
+ small_size = len(small_bytecode.serialize())
383
+
384
+ # Compile large list
385
+ test_file.write_text(large_source)
386
+ context = pipeline.compile_file(test_file)
387
+ assert not context.has_errors()
388
+ assert context.mir_module is not None
389
+ large_bytecode, _ = generate_bytecode_from_mir(context.mir_module)
390
+ large_size = len(large_bytecode.serialize())
391
+
392
+ test_file.unlink(missing_ok=True)
393
+
394
+ # Large list should generate more bytecode
395
+ assert large_size > small_size * 2, f"Large list ({large_size}) should be much bigger than small ({small_size})"