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,313 @@
1
+ """Tests for MIR dumper utility."""
2
+
3
+ import sys
4
+ from io import StringIO
5
+
6
+ from machine_dialect.mir.basic_block import BasicBlock
7
+ from machine_dialect.mir.mir_dumper import (
8
+ ColorCode,
9
+ DumpVerbosity,
10
+ MIRDumper,
11
+ dump_mir,
12
+ )
13
+ from machine_dialect.mir.mir_function import MIRFunction
14
+ from machine_dialect.mir.mir_instructions import (
15
+ BinaryOp,
16
+ LoadConst,
17
+ Return,
18
+ )
19
+ from machine_dialect.mir.mir_module import MIRModule
20
+ from machine_dialect.mir.mir_types import MIRType
21
+ from machine_dialect.mir.mir_values import Constant, Temp, Variable
22
+
23
+
24
+ class TestMIRDumper:
25
+ """Test MIR dumper functionality."""
26
+
27
+ def create_test_module(self) -> MIRModule:
28
+ """Create a test MIR module."""
29
+ module = MIRModule("test_module")
30
+
31
+ # Create main function
32
+ main_func = MIRFunction("main", return_type=MIRType.INT)
33
+
34
+ # Create entry block
35
+ entry_block = BasicBlock("entry")
36
+
37
+ # Add instructions
38
+ t0 = Temp(MIRType.INT, 0)
39
+ t1 = Temp(MIRType.INT, 1)
40
+ t2 = Temp(MIRType.INT, 2)
41
+
42
+ entry_block.add_instruction(LoadConst(t0, Constant(10, MIRType.INT), (1, 1)))
43
+ entry_block.add_instruction(LoadConst(t1, Constant(20, MIRType.INT), (1, 1)))
44
+ entry_block.add_instruction(BinaryOp(t2, "+", t0, t1, (1, 1)))
45
+ entry_block.add_instruction(Return((1, 1), t2))
46
+
47
+ # Set up CFG
48
+ main_func.cfg.add_block(entry_block)
49
+ main_func.cfg.entry_block = entry_block
50
+
51
+ module.add_function(main_func)
52
+ return module
53
+
54
+ def test_basic_dump(self) -> None:
55
+ """Test basic MIR dumping."""
56
+ module = self.create_test_module()
57
+ dumper = MIRDumper(use_color=False, verbosity=DumpVerbosity.NORMAL)
58
+
59
+ output = StringIO()
60
+ result = dumper.dump_module(module, output)
61
+
62
+ assert "MIR Module: test_module" in result
63
+ assert "Function main" in result
64
+ assert "entry:" in result
65
+ assert "return" in result.lower()
66
+
67
+ def test_dump_with_colors(self) -> None:
68
+ """Test MIR dumping with colors."""
69
+ module = self.create_test_module()
70
+
71
+ # Force color output
72
+ original_isatty = sys.stdout.isatty
73
+ sys.stdout.isatty = lambda: True # type: ignore[method-assign]
74
+
75
+ try:
76
+ dumper = MIRDumper(use_color=True, verbosity=DumpVerbosity.NORMAL)
77
+ output = StringIO()
78
+ result = dumper.dump_module(module, output)
79
+
80
+ # Check for color codes
81
+ assert ColorCode.CYAN in result or ColorCode.GREEN in result
82
+ finally:
83
+ sys.stdout.isatty = original_isatty # type: ignore[method-assign]
84
+
85
+ def test_verbosity_minimal(self) -> None:
86
+ """Test minimal verbosity level."""
87
+ module = self.create_test_module()
88
+ dumper = MIRDumper(use_color=False, verbosity=DumpVerbosity.MINIMAL)
89
+
90
+ output = StringIO()
91
+ result = dumper.dump_module(module, output)
92
+
93
+ assert "Function main" in result
94
+ # Minimal verbosity should not include block details
95
+ assert "t0 =" not in result
96
+
97
+ def test_verbosity_detailed(self) -> None:
98
+ """Test detailed verbosity level."""
99
+ module = self.create_test_module()
100
+ dumper = MIRDumper(use_color=False, verbosity=DumpVerbosity.DETAILED)
101
+
102
+ output = StringIO()
103
+ result = dumper.dump_module(module, output)
104
+
105
+ assert "Function main" in result
106
+ assert "entry:" in result
107
+
108
+ def test_verbosity_debug(self) -> None:
109
+ """Test debug verbosity level."""
110
+ module = self.create_test_module()
111
+ dumper = MIRDumper(use_color=False, verbosity=DumpVerbosity.DEBUG)
112
+
113
+ output = StringIO()
114
+ result = dumper.dump_module(module, output)
115
+
116
+ assert "Function main" in result
117
+ assert "entry:" in result
118
+
119
+ def test_dump_with_statistics(self) -> None:
120
+ """Test dumping with statistics enabled."""
121
+ module = self.create_test_module()
122
+ dumper = MIRDumper(use_color=False, show_stats=True)
123
+
124
+ output = StringIO()
125
+ result = dumper.dump_module(module, output)
126
+
127
+ assert "Statistics" in result
128
+ assert "Functions: 1" in result
129
+ assert "Basic Blocks: 1" in result
130
+ assert "Instructions: 4" in result
131
+
132
+ def test_dump_with_optimization_stats(self) -> None:
133
+ """Test dumping with optimization statistics."""
134
+ module = self.create_test_module()
135
+
136
+ # Add fake optimization stats
137
+ module.optimization_stats = { # type: ignore[attr-defined]
138
+ "constant-propagation": {
139
+ "constants_propagated": 5,
140
+ "expressions_folded": 2,
141
+ },
142
+ "dce": {
143
+ "dead_instructions_removed": 3,
144
+ },
145
+ }
146
+
147
+ dumper = MIRDumper(use_color=False, show_stats=True)
148
+
149
+ output = StringIO()
150
+ result = dumper.dump_module(module, output)
151
+
152
+ assert "Optimizations Applied:" in result
153
+ assert "constant-propagation:" in result
154
+ assert "constants_propagated: 5" in result
155
+
156
+ def test_dump_function(self) -> None:
157
+ """Test dumping a single function."""
158
+ func = MIRFunction("test_func", return_type=MIRType.INT)
159
+
160
+ # Create a simple block
161
+ entry = BasicBlock("entry")
162
+ entry.add_instruction(Return((1, 1), Constant(42, MIRType.INT)))
163
+ func.cfg.add_block(entry)
164
+ func.cfg.entry_block = entry
165
+
166
+ dumper = MIRDumper(use_color=False)
167
+
168
+ output = StringIO()
169
+ result = dumper.dump_function(func, output)
170
+
171
+ assert "Function test_func" in result
172
+ assert "entry:" in result
173
+ assert "return 42" in result.lower()
174
+
175
+ def test_dump_with_parameters(self) -> None:
176
+ """Test dumping function with parameters."""
177
+ params = [
178
+ Variable("x", MIRType.INT),
179
+ Variable("y", MIRType.INT),
180
+ ]
181
+ func = MIRFunction("add", params=params, return_type=MIRType.INT)
182
+
183
+ entry = BasicBlock("entry")
184
+ t0 = Temp(MIRType.INT, 0)
185
+ entry.add_instruction(BinaryOp(t0, "+", params[0], params[1], (1, 1)))
186
+ entry.add_instruction(Return((1, 1), t0))
187
+
188
+ func.cfg.add_block(entry)
189
+ func.cfg.entry_block = entry
190
+
191
+ dumper = MIRDumper(use_color=False)
192
+ output = StringIO()
193
+ result = dumper.dump_function(func, output)
194
+
195
+ assert "Function add" in result
196
+ assert "-> 1" in result # Return type MIRType.INT has value 1
197
+
198
+ def test_dump_with_control_flow(self) -> None:
199
+ """Test dumping with multiple basic blocks."""
200
+ module = MIRModule("cf_test")
201
+ func = MIRFunction("branch_test", return_type=MIRType.INT)
202
+
203
+ # Create blocks
204
+ entry = BasicBlock("entry")
205
+ then_block = BasicBlock("then")
206
+ else_block = BasicBlock("else")
207
+ merge = BasicBlock("merge")
208
+
209
+ # Add control flow
210
+ entry.add_successor(then_block)
211
+ entry.add_successor(else_block)
212
+ then_block.add_successor(merge)
213
+ else_block.add_successor(merge)
214
+
215
+ # Add to CFG
216
+ func.cfg.add_block(entry)
217
+ func.cfg.add_block(then_block)
218
+ func.cfg.add_block(else_block)
219
+ func.cfg.add_block(merge)
220
+ func.cfg.entry_block = entry
221
+
222
+ module.add_function(func)
223
+
224
+ dumper = MIRDumper(use_color=False)
225
+ output = StringIO()
226
+ result = dumper.dump_module(module, output)
227
+
228
+ assert "entry:" in result
229
+ assert "then:" in result
230
+ assert "else:" in result
231
+ assert "merge:" in result
232
+
233
+ def test_dump_mir_convenience_function(self) -> None:
234
+ """Test the convenience dump_mir function."""
235
+ module = self.create_test_module()
236
+
237
+ # Capture stdout
238
+ old_stdout = sys.stdout
239
+ sys.stdout = StringIO()
240
+
241
+ try:
242
+ dump_mir(module, use_color=False, verbosity="normal")
243
+ output = sys.stdout.getvalue()
244
+
245
+ assert "MIR Module: test_module" in output
246
+ assert "Function main" in output
247
+ finally:
248
+ sys.stdout = old_stdout
249
+
250
+ def test_dump_with_annotations(self) -> None:
251
+ """Test dumping with annotations enabled."""
252
+ module = self.create_test_module()
253
+ func = module.functions["main"]
254
+
255
+ # Add some fake annotations
256
+ if func.cfg.entry_block:
257
+ func.cfg.entry_block.loop_depth = 1 # type: ignore[attr-defined]
258
+ func.cfg.entry_block.frequency = 0.95 # type: ignore[attr-defined]
259
+
260
+ dumper = MIRDumper(
261
+ use_color=False,
262
+ verbosity=DumpVerbosity.NORMAL,
263
+ show_annotations=True,
264
+ )
265
+
266
+ output = StringIO()
267
+ result = dumper.dump_module(module, output)
268
+
269
+ assert "loop depth: 1" in result
270
+ assert "frequency: 0.95" in result
271
+
272
+ def test_empty_module(self) -> None:
273
+ """Test dumping an empty module."""
274
+ module = MIRModule("empty")
275
+ dumper = MIRDumper(use_color=False)
276
+
277
+ output = StringIO()
278
+ result = dumper.dump_module(module, output)
279
+
280
+ assert "MIR Module: empty" in result
281
+
282
+ def test_instruction_coloring(self) -> None:
283
+ """Test that different instruction types get colored differently."""
284
+ module = self.create_test_module()
285
+
286
+ # Add various instruction types
287
+ func = module.functions["main"]
288
+ if func.cfg.entry_block:
289
+ from machine_dialect.mir.mir_instructions import Call
290
+
291
+ # Add a call instruction
292
+ func.cfg.entry_block.add_instruction(
293
+ Call(
294
+ Temp(MIRType.INT, 10),
295
+ "helper",
296
+ [],
297
+ (1, 1),
298
+ )
299
+ )
300
+
301
+ # Force colors
302
+ original_isatty = sys.stdout.isatty
303
+ sys.stdout.isatty = lambda: True # type: ignore[method-assign]
304
+
305
+ try:
306
+ dumper = MIRDumper(use_color=True)
307
+ output = StringIO()
308
+ result = dumper.dump_module(module, output)
309
+
310
+ # Different instruction types should have different colors
311
+ assert ColorCode.YELLOW in result or ColorCode.RED in result
312
+ finally:
313
+ sys.stdout.isatty = original_isatty # type: ignore[method-assign]