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,366 @@
1
+ """MIR dumper for pretty-printing and debugging.
2
+
3
+ This module provides utilities for dumping MIR in various formats with
4
+ syntax highlighting and different verbosity levels.
5
+ """
6
+
7
+ import sys
8
+ from enum import Enum
9
+ from io import StringIO
10
+ from typing import Any, TextIO
11
+
12
+ from machine_dialect.mir.mir_function import MIRFunction
13
+ from machine_dialect.mir.mir_module import MIRModule
14
+ from machine_dialect.mir.mir_printer import MIRPrinter
15
+
16
+
17
+ class DumpVerbosity(Enum):
18
+ """Verbosity levels for MIR dumping."""
19
+
20
+ MINIMAL = "minimal" # Just function signatures and basic blocks
21
+ NORMAL = "normal" # Include instructions
22
+ DETAILED = "detailed" # Include types and metadata
23
+ DEBUG = "debug" # Include all available information
24
+
25
+ @classmethod
26
+ def from_string(cls, value: str) -> "DumpVerbosity":
27
+ """Create DumpVerbosity from string.
28
+
29
+ Args:
30
+ value: String representation of verbosity level.
31
+
32
+ Returns:
33
+ DumpVerbosity enum value.
34
+ """
35
+ for member in cls:
36
+ if member.value == value.lower():
37
+ return member
38
+ # Default to NORMAL if not found
39
+ return cls.NORMAL
40
+
41
+
42
+ class ColorCode:
43
+ """ANSI color codes for terminal output."""
44
+
45
+ RESET = "\033[0m"
46
+ BOLD = "\033[1m"
47
+ DIM = "\033[2m"
48
+
49
+ # Colors
50
+ RED = "\033[31m"
51
+ GREEN = "\033[32m"
52
+ YELLOW = "\033[33m"
53
+ BLUE = "\033[34m"
54
+ MAGENTA = "\033[35m"
55
+ CYAN = "\033[36m"
56
+ WHITE = "\033[37m"
57
+
58
+ # Bright colors
59
+ BRIGHT_RED = "\033[91m"
60
+ BRIGHT_GREEN = "\033[92m"
61
+ BRIGHT_YELLOW = "\033[93m"
62
+ BRIGHT_BLUE = "\033[94m"
63
+ BRIGHT_MAGENTA = "\033[95m"
64
+ BRIGHT_CYAN = "\033[96m"
65
+
66
+
67
+ class MIRDumper:
68
+ """Pretty-printer for MIR with syntax highlighting and formatting."""
69
+
70
+ def __init__(
71
+ self,
72
+ use_color: bool = True,
73
+ verbosity: DumpVerbosity = DumpVerbosity.NORMAL,
74
+ show_stats: bool = False,
75
+ show_annotations: bool = True,
76
+ ) -> None:
77
+ """Initialize MIR dumper.
78
+
79
+ Args:
80
+ use_color: Whether to use ANSI color codes.
81
+ verbosity: Level of detail to include.
82
+ show_stats: Whether to show optimization statistics.
83
+ show_annotations: Whether to show optimization annotations.
84
+ """
85
+ self.use_color = use_color and sys.stdout.isatty()
86
+ self.verbosity = verbosity
87
+ self.show_stats = show_stats
88
+ self.show_annotations = show_annotations
89
+ self.printer = MIRPrinter()
90
+
91
+ def _color(self, text: str, color: str) -> str:
92
+ """Apply color to text if colors are enabled.
93
+
94
+ Args:
95
+ text: Text to color.
96
+ color: Color code to apply.
97
+
98
+ Returns:
99
+ Colored text or original text.
100
+ """
101
+ if self.use_color:
102
+ return f"{color}{text}{ColorCode.RESET}"
103
+ return text
104
+
105
+ def dump_module(self, module: MIRModule, output: TextIO | None = None) -> str:
106
+ """Dump a MIR module with formatting.
107
+
108
+ Args:
109
+ module: Module to dump.
110
+ output: Optional output stream (defaults to stdout).
111
+
112
+ Returns:
113
+ Formatted module string.
114
+ """
115
+ if output is None:
116
+ output = sys.stdout
117
+
118
+ buffer = StringIO()
119
+
120
+ # Module header
121
+ header = f"=== MIR Module: {module.name} ==="
122
+ buffer.write(self._color(header, ColorCode.BOLD + ColorCode.CYAN))
123
+ buffer.write("\n\n")
124
+
125
+ # Module-level information
126
+ if self.verbosity in [DumpVerbosity.DETAILED, DumpVerbosity.DEBUG]:
127
+ if hasattr(module, "optimization_level"):
128
+ buffer.write(self._color("Optimization Level: ", ColorCode.YELLOW))
129
+ buffer.write(f"{getattr(module, 'optimization_level', 0)}\n")
130
+
131
+ if hasattr(module, "profile_data") and module.profile_data:
132
+ buffer.write(self._color("Profile Data: ", ColorCode.YELLOW))
133
+ buffer.write("Available\n")
134
+
135
+ buffer.write("\n")
136
+
137
+ # Dump each function
138
+ for _, function in module.functions.items():
139
+ self._dump_function(function, buffer)
140
+ buffer.write("\n")
141
+
142
+ # Statistics
143
+ if self.show_stats:
144
+ buffer.write(self._dump_statistics(module))
145
+
146
+ result = buffer.getvalue()
147
+ output.write(result)
148
+ return result
149
+
150
+ def dump_function(self, function: MIRFunction, output: TextIO | None = None) -> str:
151
+ """Dump a single MIR function.
152
+
153
+ Args:
154
+ function: Function to dump.
155
+ output: Optional output stream.
156
+
157
+ Returns:
158
+ Formatted function string.
159
+ """
160
+ if output is None:
161
+ output = sys.stdout
162
+
163
+ buffer = StringIO()
164
+ self._dump_function(function, buffer)
165
+ result = buffer.getvalue()
166
+ output.write(result)
167
+ return result
168
+
169
+ def _dump_function(self, function: MIRFunction, buffer: StringIO) -> None:
170
+ """Internal function dumper.
171
+
172
+ Args:
173
+ function: Function to dump.
174
+ buffer: String buffer to write to.
175
+ """
176
+ # Function signature
177
+ sig = f"Function {function.name}"
178
+ if function.params:
179
+ param_str = ", ".join(f"{p.name}: {getattr(p, 'mir_type', 'unknown')}" for p in function.params)
180
+ sig += f"({param_str})"
181
+ else:
182
+ sig += "()"
183
+
184
+ if function.return_type:
185
+ sig += f" -> {function.return_type.value}"
186
+
187
+ buffer.write(self._color(sig, ColorCode.BOLD + ColorCode.GREEN))
188
+ buffer.write("\n")
189
+
190
+ # Function attributes
191
+ if self.verbosity in [DumpVerbosity.DETAILED, DumpVerbosity.DEBUG]:
192
+ if hasattr(function, "is_inline") and function.is_inline:
193
+ buffer.write(self._color(" @inline", ColorCode.DIM + ColorCode.MAGENTA))
194
+ buffer.write("\n")
195
+
196
+ if hasattr(function, "is_hot") and function.is_hot:
197
+ buffer.write(self._color(" @hot", ColorCode.DIM + ColorCode.RED))
198
+ buffer.write("\n")
199
+
200
+ if hasattr(function, "optimization_hints"):
201
+ for hint in function.optimization_hints:
202
+ buffer.write(
203
+ self._color(
204
+ f" @hint({hint})",
205
+ ColorCode.DIM + ColorCode.BLUE,
206
+ )
207
+ )
208
+ buffer.write("\n")
209
+
210
+ # Basic blocks
211
+ if self.verbosity != DumpVerbosity.MINIMAL:
212
+ # Get blocks from CFG
213
+ if hasattr(function, "cfg") and function.cfg:
214
+ # Process blocks in order, starting with entry block
215
+ if function.cfg.entry_block:
216
+ visited = set()
217
+ to_visit = [function.cfg.entry_block]
218
+ while to_visit:
219
+ block = to_visit.pop(0)
220
+ if block.label in visited:
221
+ continue
222
+ visited.add(block.label)
223
+ self._dump_block(block, buffer)
224
+ # Add successors
225
+ for succ in block.successors:
226
+ if succ.label not in visited:
227
+ to_visit.append(succ)
228
+
229
+ def _dump_block(self, block: Any, buffer: StringIO) -> None:
230
+ """Dump a basic block.
231
+
232
+ Args:
233
+ block: Basic block to dump.
234
+ buffer: String buffer to write to.
235
+ """
236
+ # Block header
237
+ block_header = f"\n {block.label}:"
238
+ if hasattr(block, "predecessors") and block.predecessors:
239
+ pred_str = ", ".join(p.label for p in block.predecessors)
240
+ block_header += f" (preds: {pred_str})"
241
+
242
+ buffer.write(self._color(block_header, ColorCode.BOLD + ColorCode.BLUE))
243
+ buffer.write("\n")
244
+
245
+ # Annotations
246
+ if self.show_annotations:
247
+ if hasattr(block, "loop_depth") and block.loop_depth > 0:
248
+ buffer.write(
249
+ self._color(
250
+ f" ; loop depth: {block.loop_depth}",
251
+ ColorCode.DIM,
252
+ )
253
+ )
254
+ buffer.write("\n")
255
+
256
+ if hasattr(block, "frequency"):
257
+ buffer.write(
258
+ self._color(
259
+ f" ; frequency: {block.frequency:.2f}",
260
+ ColorCode.DIM,
261
+ )
262
+ )
263
+ buffer.write("\n")
264
+
265
+ # Instructions
266
+ for inst in block.instructions:
267
+ inst_str = f" {inst!s}"
268
+
269
+ # Color based on instruction type
270
+ if "call" in inst_str.lower():
271
+ inst_str = self._color(inst_str, ColorCode.YELLOW)
272
+ elif "jump" in inst_str.lower() or "branch" in inst_str.lower():
273
+ inst_str = self._color(inst_str, ColorCode.MAGENTA)
274
+ elif "return" in inst_str.lower():
275
+ inst_str = self._color(inst_str, ColorCode.RED)
276
+ elif "=" in inst_str:
277
+ # Assignment operations
278
+ parts = inst_str.split("=", 1)
279
+ if len(parts) == 2:
280
+ lhs = self._color(parts[0].strip(), ColorCode.CYAN)
281
+ inst_str = f" {lhs} = {parts[1].strip()}"
282
+
283
+ buffer.write(inst_str)
284
+
285
+ # Add type information in detailed mode
286
+ if self.verbosity == DumpVerbosity.DEBUG:
287
+ if hasattr(inst, "result") and hasattr(inst.result, "mir_type"):
288
+ type_info = f" : {inst.result.mir_type.value}"
289
+ buffer.write(self._color(type_info, ColorCode.DIM + ColorCode.GREEN))
290
+
291
+ buffer.write("\n")
292
+
293
+ def _dump_statistics(self, module: MIRModule) -> str:
294
+ """Dump module statistics.
295
+
296
+ Args:
297
+ module: Module to analyze.
298
+
299
+ Returns:
300
+ Statistics string.
301
+ """
302
+ buffer = StringIO()
303
+ buffer.write("\n")
304
+ buffer.write(self._color("=== Statistics ===", ColorCode.BOLD + ColorCode.CYAN))
305
+ buffer.write("\n")
306
+
307
+ # Count statistics
308
+ num_functions = len(module.functions)
309
+
310
+ block_counts = []
311
+ for f in module.functions.values():
312
+ if hasattr(f, "cfg") and f.cfg:
313
+ block_counts.append(len(f.cfg.blocks))
314
+ else:
315
+ block_counts.append(0)
316
+ num_blocks = sum(block_counts)
317
+
318
+ instruction_counts = []
319
+ for f in module.functions.values():
320
+ if hasattr(f, "cfg") and f.cfg:
321
+ instruction_counts.append(sum(len(b.instructions) for b in f.cfg.blocks.values()))
322
+ else:
323
+ instruction_counts.append(0)
324
+ num_instructions = sum(instruction_counts)
325
+
326
+ buffer.write(f" Functions: {num_functions}\n")
327
+ buffer.write(f" Basic Blocks: {num_blocks}\n")
328
+ buffer.write(f" Instructions: {num_instructions}\n")
329
+
330
+ # Optimization statistics if available
331
+ if hasattr(module, "optimization_stats"):
332
+ buffer.write("\n")
333
+ buffer.write(self._color("Optimizations Applied:", ColorCode.YELLOW))
334
+ buffer.write("\n")
335
+ for pass_name, stats in module.optimization_stats.items():
336
+ buffer.write(f" {pass_name}:\n")
337
+ for stat, value in stats.items():
338
+ buffer.write(f" {stat}: {value}\n")
339
+
340
+ return buffer.getvalue()
341
+
342
+
343
+ def dump_mir(
344
+ module_or_function: MIRModule | MIRFunction,
345
+ use_color: bool = True,
346
+ verbosity: str = "normal",
347
+ show_stats: bool = False,
348
+ ) -> None:
349
+ """Convenience function to dump MIR to stdout.
350
+
351
+ Args:
352
+ module_or_function: Module or function to dump.
353
+ use_color: Whether to use colors.
354
+ verbosity: Verbosity level (minimal, normal, detailed, debug).
355
+ show_stats: Whether to show statistics.
356
+ """
357
+ dumper = MIRDumper(
358
+ use_color=use_color,
359
+ verbosity=DumpVerbosity(verbosity),
360
+ show_stats=show_stats,
361
+ )
362
+
363
+ if isinstance(module_or_function, MIRModule):
364
+ dumper.dump_module(module_or_function)
365
+ else:
366
+ dumper.dump_function(module_or_function)
@@ -0,0 +1,167 @@
1
+ """MIR Function Representation.
2
+
3
+ This module defines the MIRFunction class that represents a function
4
+ in the MIR, including its parameters, locals, temporaries, and CFG.
5
+ """
6
+
7
+ from .basic_block import CFG
8
+ from .mir_types import MIRType, MIRUnionType
9
+ from .mir_values import ScopedVariable, Temp, Variable
10
+
11
+
12
+ class MIRFunction:
13
+ """A function in MIR representation.
14
+
15
+ Contains all the information about a function including its
16
+ signature, local variables, temporaries, and control flow graph.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ name: str,
22
+ params: list[Variable | ScopedVariable] | None = None,
23
+ return_type: MIRType = MIRType.EMPTY,
24
+ ) -> None:
25
+ """Initialize a MIR function.
26
+
27
+ Args:
28
+ name: Function name.
29
+ params: List of parameter variables.
30
+ return_type: Return type of the function.
31
+ """
32
+ self.name = name
33
+ self.params = params if params is not None else []
34
+ self.return_type = return_type
35
+ self.locals: dict[str, Variable] = {}
36
+ self.temporaries: list[Temp] = []
37
+ self.cfg = CFG()
38
+ self.is_ssa = False
39
+ self._next_temp_id = 0
40
+ self._next_var_version: dict[str, int] = {}
41
+
42
+ def add_local(self, var: Variable) -> None:
43
+ """Add a local variable.
44
+
45
+ Args:
46
+ var: The variable to add.
47
+ """
48
+ self.locals[var.name] = var
49
+
50
+ def declare_local(self, name: str, mir_type: MIRType) -> Variable:
51
+ """Declare a function-local variable.
52
+
53
+ Args:
54
+ name: The variable name.
55
+ mir_type: The type of the variable.
56
+
57
+ Returns:
58
+ A ScopedVariable with LOCAL scope.
59
+ """
60
+ from .mir_values import ScopedVariable, VariableScope
61
+
62
+ var = ScopedVariable(name, VariableScope.LOCAL, mir_type)
63
+ self.locals[name] = var
64
+ return var
65
+
66
+ def get_local(self, name: str) -> Variable | None:
67
+ """Get a local variable by name.
68
+
69
+ Args:
70
+ name: Variable name.
71
+
72
+ Returns:
73
+ The variable or None if not found.
74
+ """
75
+ return self.locals.get(name)
76
+
77
+ def new_temp(self, mir_type: MIRType | MIRUnionType) -> Temp:
78
+ """Create a new temporary.
79
+
80
+ Args:
81
+ mir_type: Type of the temporary.
82
+
83
+ Returns:
84
+ A new temporary.
85
+ """
86
+ temp = Temp(mir_type, self._next_temp_id)
87
+ self._next_temp_id += 1
88
+ self.temporaries.append(temp)
89
+ return temp
90
+
91
+ def new_var_version(self, var_name: str) -> int:
92
+ """Get a new SSA version for a variable.
93
+
94
+ Args:
95
+ var_name: Variable name.
96
+
97
+ Returns:
98
+ The next version number.
99
+ """
100
+ if var_name not in self._next_var_version:
101
+ self._next_var_version[var_name] = 1
102
+ version = self._next_var_version[var_name]
103
+ self._next_var_version[var_name] += 1
104
+ return version
105
+
106
+ def get_param_by_name(self, name: str) -> Variable | None:
107
+ """Get a parameter by name.
108
+
109
+ Args:
110
+ name: Parameter name.
111
+
112
+ Returns:
113
+ The parameter variable or None if not found.
114
+ """
115
+ for param in self.params:
116
+ if param.name == name:
117
+ return param
118
+ return None
119
+
120
+ def to_string(self, include_cfg: bool = True) -> str:
121
+ """Convert function to string representation.
122
+
123
+ Args:
124
+ include_cfg: Whether to include the CFG in the output.
125
+
126
+ Returns:
127
+ String representation of the function.
128
+ """
129
+ lines = []
130
+
131
+ # Function signature
132
+ params_str = ", ".join(f"{p.name}: {p.type}" for p in self.params)
133
+ if self.return_type != MIRType.EMPTY:
134
+ lines.append(f"function {self.name}({params_str}) -> {self.return_type} {{")
135
+ else:
136
+ lines.append(f"function {self.name}({params_str}) {{")
137
+
138
+ # Locals
139
+ if self.locals:
140
+ lines.append(" locals:")
141
+ for name, var in self.locals.items():
142
+ lines.append(f" {name}: {var.type}")
143
+
144
+ # Temporaries (summary)
145
+ if self.temporaries:
146
+ lines.append(f" temporaries: {len(self.temporaries)}")
147
+
148
+ # SSA status
149
+ lines.append(f" ssa: {self.is_ssa}")
150
+
151
+ # CFG
152
+ if include_cfg:
153
+ lines.append(" cfg:")
154
+ cfg_str = str(self.cfg)
155
+ for line in cfg_str.split("\n"):
156
+ lines.append(f" {line}")
157
+
158
+ lines.append("}")
159
+ return "\n".join(lines)
160
+
161
+ def __str__(self) -> str:
162
+ """Return string representation."""
163
+ return self.to_string()
164
+
165
+ def __repr__(self) -> str:
166
+ """Return debug representation."""
167
+ return f"MIRFunction({self.name}, params={len(self.params)}, locals={len(self.locals)})"