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.
- machine_dialect/__main__.py +667 -0
- machine_dialect/agent/__init__.py +5 -0
- machine_dialect/agent/agent.py +360 -0
- machine_dialect/ast/__init__.py +95 -0
- machine_dialect/ast/ast_node.py +35 -0
- machine_dialect/ast/call_expression.py +82 -0
- machine_dialect/ast/dict_extraction.py +60 -0
- machine_dialect/ast/expressions.py +439 -0
- machine_dialect/ast/literals.py +309 -0
- machine_dialect/ast/program.py +35 -0
- machine_dialect/ast/statements.py +1433 -0
- machine_dialect/ast/tests/test_ast_string_representation.py +62 -0
- machine_dialect/ast/tests/test_boolean_literal.py +29 -0
- machine_dialect/ast/tests/test_collection_hir.py +138 -0
- machine_dialect/ast/tests/test_define_statement.py +142 -0
- machine_dialect/ast/tests/test_desugar.py +541 -0
- machine_dialect/ast/tests/test_foreach_desugar.py +245 -0
- machine_dialect/cfg/__init__.py +6 -0
- machine_dialect/cfg/config.py +156 -0
- machine_dialect/cfg/examples.py +221 -0
- machine_dialect/cfg/generate_with_ai.py +187 -0
- machine_dialect/cfg/openai_generation.py +200 -0
- machine_dialect/cfg/parser.py +94 -0
- machine_dialect/cfg/tests/__init__.py +1 -0
- machine_dialect/cfg/tests/test_cfg_parser.py +252 -0
- machine_dialect/cfg/tests/test_config.py +188 -0
- machine_dialect/cfg/tests/test_examples.py +391 -0
- machine_dialect/cfg/tests/test_generate_with_ai.py +354 -0
- machine_dialect/cfg/tests/test_openai_generation.py +256 -0
- machine_dialect/codegen/__init__.py +5 -0
- machine_dialect/codegen/bytecode_module.py +89 -0
- machine_dialect/codegen/bytecode_serializer.py +300 -0
- machine_dialect/codegen/opcodes.py +101 -0
- machine_dialect/codegen/register_codegen.py +1996 -0
- machine_dialect/codegen/symtab.py +208 -0
- machine_dialect/codegen/tests/__init__.py +1 -0
- machine_dialect/codegen/tests/test_array_operations_codegen.py +295 -0
- machine_dialect/codegen/tests/test_bytecode_serializer.py +185 -0
- machine_dialect/codegen/tests/test_register_codegen_ssa.py +324 -0
- machine_dialect/codegen/tests/test_symtab.py +418 -0
- machine_dialect/codegen/vm_serializer.py +621 -0
- machine_dialect/compiler/__init__.py +18 -0
- machine_dialect/compiler/compiler.py +197 -0
- machine_dialect/compiler/config.py +149 -0
- machine_dialect/compiler/context.py +149 -0
- machine_dialect/compiler/phases/__init__.py +19 -0
- machine_dialect/compiler/phases/bytecode_optimization.py +90 -0
- machine_dialect/compiler/phases/codegen.py +40 -0
- machine_dialect/compiler/phases/hir_generation.py +39 -0
- machine_dialect/compiler/phases/mir_generation.py +86 -0
- machine_dialect/compiler/phases/optimization.py +110 -0
- machine_dialect/compiler/phases/parsing.py +39 -0
- machine_dialect/compiler/pipeline.py +143 -0
- machine_dialect/compiler/tests/__init__.py +1 -0
- machine_dialect/compiler/tests/test_compiler.py +568 -0
- machine_dialect/compiler/vm_runner.py +173 -0
- machine_dialect/errors/__init__.py +32 -0
- machine_dialect/errors/exceptions.py +369 -0
- machine_dialect/errors/messages.py +82 -0
- machine_dialect/errors/tests/__init__.py +0 -0
- machine_dialect/errors/tests/test_expected_token_errors.py +188 -0
- machine_dialect/errors/tests/test_name_errors.py +118 -0
- machine_dialect/helpers/__init__.py +0 -0
- machine_dialect/helpers/stopwords.py +225 -0
- machine_dialect/helpers/validators.py +30 -0
- machine_dialect/lexer/__init__.py +9 -0
- machine_dialect/lexer/constants.py +23 -0
- machine_dialect/lexer/lexer.py +907 -0
- machine_dialect/lexer/tests/__init__.py +0 -0
- machine_dialect/lexer/tests/helpers.py +86 -0
- machine_dialect/lexer/tests/test_apostrophe_identifiers.py +122 -0
- machine_dialect/lexer/tests/test_backtick_identifiers.py +140 -0
- machine_dialect/lexer/tests/test_boolean_literals.py +108 -0
- machine_dialect/lexer/tests/test_case_insensitive_keywords.py +188 -0
- machine_dialect/lexer/tests/test_comments.py +200 -0
- machine_dialect/lexer/tests/test_double_asterisk_keywords.py +127 -0
- machine_dialect/lexer/tests/test_lexer_position.py +113 -0
- machine_dialect/lexer/tests/test_list_tokens.py +282 -0
- machine_dialect/lexer/tests/test_stopwords.py +80 -0
- machine_dialect/lexer/tests/test_strict_equality.py +129 -0
- machine_dialect/lexer/tests/test_token.py +41 -0
- machine_dialect/lexer/tests/test_tokenization.py +294 -0
- machine_dialect/lexer/tests/test_underscore_literals.py +343 -0
- machine_dialect/lexer/tests/test_url_literals.py +169 -0
- machine_dialect/lexer/tokens.py +487 -0
- machine_dialect/linter/__init__.py +10 -0
- machine_dialect/linter/__main__.py +144 -0
- machine_dialect/linter/linter.py +154 -0
- machine_dialect/linter/rules/__init__.py +8 -0
- machine_dialect/linter/rules/base.py +112 -0
- machine_dialect/linter/rules/statement_termination.py +99 -0
- machine_dialect/linter/tests/__init__.py +1 -0
- machine_dialect/linter/tests/mdrules/__init__.py +0 -0
- machine_dialect/linter/tests/mdrules/test_md101_statement_termination.py +181 -0
- machine_dialect/linter/tests/test_linter.py +81 -0
- machine_dialect/linter/tests/test_rules.py +110 -0
- machine_dialect/linter/tests/test_violations.py +71 -0
- machine_dialect/linter/violations.py +51 -0
- machine_dialect/mir/__init__.py +69 -0
- machine_dialect/mir/analyses/__init__.py +20 -0
- machine_dialect/mir/analyses/alias_analysis.py +315 -0
- machine_dialect/mir/analyses/dominance_analysis.py +49 -0
- machine_dialect/mir/analyses/escape_analysis.py +286 -0
- machine_dialect/mir/analyses/loop_analysis.py +272 -0
- machine_dialect/mir/analyses/tests/test_type_analysis.py +736 -0
- machine_dialect/mir/analyses/type_analysis.py +448 -0
- machine_dialect/mir/analyses/use_def_chains.py +232 -0
- machine_dialect/mir/basic_block.py +385 -0
- machine_dialect/mir/dataflow.py +445 -0
- machine_dialect/mir/debug_info.py +208 -0
- machine_dialect/mir/hir_to_mir.py +1738 -0
- machine_dialect/mir/mir_dumper.py +366 -0
- machine_dialect/mir/mir_function.py +167 -0
- machine_dialect/mir/mir_instructions.py +1877 -0
- machine_dialect/mir/mir_interpreter.py +556 -0
- machine_dialect/mir/mir_module.py +225 -0
- machine_dialect/mir/mir_printer.py +480 -0
- machine_dialect/mir/mir_transformer.py +410 -0
- machine_dialect/mir/mir_types.py +367 -0
- machine_dialect/mir/mir_validation.py +455 -0
- machine_dialect/mir/mir_values.py +268 -0
- machine_dialect/mir/optimization_config.py +233 -0
- machine_dialect/mir/optimization_pass.py +251 -0
- machine_dialect/mir/optimization_pipeline.py +355 -0
- machine_dialect/mir/optimizations/__init__.py +84 -0
- machine_dialect/mir/optimizations/algebraic_simplification.py +733 -0
- machine_dialect/mir/optimizations/branch_prediction.py +372 -0
- machine_dialect/mir/optimizations/constant_propagation.py +634 -0
- machine_dialect/mir/optimizations/cse.py +398 -0
- machine_dialect/mir/optimizations/dce.py +288 -0
- machine_dialect/mir/optimizations/inlining.py +551 -0
- machine_dialect/mir/optimizations/jump_threading.py +487 -0
- machine_dialect/mir/optimizations/licm.py +405 -0
- machine_dialect/mir/optimizations/loop_unrolling.py +366 -0
- machine_dialect/mir/optimizations/strength_reduction.py +422 -0
- machine_dialect/mir/optimizations/tail_call.py +207 -0
- machine_dialect/mir/optimizations/tests/test_loop_unrolling.py +483 -0
- machine_dialect/mir/optimizations/type_narrowing.py +397 -0
- machine_dialect/mir/optimizations/type_specialization.py +447 -0
- machine_dialect/mir/optimizations/type_specific.py +906 -0
- machine_dialect/mir/optimize_mir.py +89 -0
- machine_dialect/mir/pass_manager.py +391 -0
- machine_dialect/mir/profiling/__init__.py +26 -0
- machine_dialect/mir/profiling/profile_collector.py +318 -0
- machine_dialect/mir/profiling/profile_data.py +372 -0
- machine_dialect/mir/profiling/profile_reader.py +272 -0
- machine_dialect/mir/profiling/profile_writer.py +226 -0
- machine_dialect/mir/register_allocation.py +302 -0
- machine_dialect/mir/reporting/__init__.py +17 -0
- machine_dialect/mir/reporting/optimization_reporter.py +314 -0
- machine_dialect/mir/reporting/report_formatter.py +289 -0
- machine_dialect/mir/ssa_construction.py +342 -0
- machine_dialect/mir/tests/__init__.py +1 -0
- machine_dialect/mir/tests/test_algebraic_associativity.py +204 -0
- machine_dialect/mir/tests/test_algebraic_complex_patterns.py +221 -0
- machine_dialect/mir/tests/test_algebraic_division.py +126 -0
- machine_dialect/mir/tests/test_algebraic_simplification.py +863 -0
- machine_dialect/mir/tests/test_basic_block.py +425 -0
- machine_dialect/mir/tests/test_branch_prediction.py +459 -0
- machine_dialect/mir/tests/test_call_lowering.py +168 -0
- machine_dialect/mir/tests/test_collection_lowering.py +604 -0
- machine_dialect/mir/tests/test_cross_block_constant_propagation.py +255 -0
- machine_dialect/mir/tests/test_custom_passes.py +166 -0
- machine_dialect/mir/tests/test_debug_info.py +285 -0
- machine_dialect/mir/tests/test_dict_extraction_lowering.py +192 -0
- machine_dialect/mir/tests/test_dictionary_lowering.py +299 -0
- machine_dialect/mir/tests/test_double_negation.py +231 -0
- machine_dialect/mir/tests/test_escape_analysis.py +233 -0
- machine_dialect/mir/tests/test_hir_to_mir.py +465 -0
- machine_dialect/mir/tests/test_hir_to_mir_complete.py +389 -0
- machine_dialect/mir/tests/test_hir_to_mir_simple.py +130 -0
- machine_dialect/mir/tests/test_inlining.py +435 -0
- machine_dialect/mir/tests/test_licm.py +472 -0
- machine_dialect/mir/tests/test_mir_dumper.py +313 -0
- machine_dialect/mir/tests/test_mir_instructions.py +445 -0
- machine_dialect/mir/tests/test_mir_module.py +860 -0
- machine_dialect/mir/tests/test_mir_printer.py +387 -0
- machine_dialect/mir/tests/test_mir_types.py +123 -0
- machine_dialect/mir/tests/test_mir_types_enhanced.py +132 -0
- machine_dialect/mir/tests/test_mir_validation.py +378 -0
- machine_dialect/mir/tests/test_mir_values.py +168 -0
- machine_dialect/mir/tests/test_one_based_indexing.py +202 -0
- machine_dialect/mir/tests/test_optimization_helpers.py +60 -0
- machine_dialect/mir/tests/test_optimization_pipeline.py +554 -0
- machine_dialect/mir/tests/test_optimization_reporter.py +318 -0
- machine_dialect/mir/tests/test_pass_manager.py +294 -0
- machine_dialect/mir/tests/test_pass_registration.py +64 -0
- machine_dialect/mir/tests/test_profiling.py +356 -0
- machine_dialect/mir/tests/test_register_allocation.py +307 -0
- machine_dialect/mir/tests/test_report_formatters.py +372 -0
- machine_dialect/mir/tests/test_ssa_construction.py +433 -0
- machine_dialect/mir/tests/test_tail_call.py +236 -0
- machine_dialect/mir/tests/test_type_annotated_instructions.py +192 -0
- machine_dialect/mir/tests/test_type_narrowing.py +277 -0
- machine_dialect/mir/tests/test_type_specialization.py +421 -0
- machine_dialect/mir/tests/test_type_specific_optimization.py +545 -0
- machine_dialect/mir/tests/test_type_specific_optimization_advanced.py +382 -0
- machine_dialect/mir/type_inference.py +368 -0
- machine_dialect/parser/__init__.py +12 -0
- machine_dialect/parser/enums.py +45 -0
- machine_dialect/parser/parser.py +3655 -0
- machine_dialect/parser/protocols.py +11 -0
- machine_dialect/parser/symbol_table.py +169 -0
- machine_dialect/parser/tests/__init__.py +0 -0
- machine_dialect/parser/tests/helper_functions.py +193 -0
- machine_dialect/parser/tests/test_action_statements.py +334 -0
- machine_dialect/parser/tests/test_boolean_literal_expressions.py +152 -0
- machine_dialect/parser/tests/test_call_statements.py +154 -0
- machine_dialect/parser/tests/test_call_statements_errors.py +187 -0
- machine_dialect/parser/tests/test_collection_mutations.py +264 -0
- machine_dialect/parser/tests/test_conditional_expressions.py +343 -0
- machine_dialect/parser/tests/test_define_integration.py +468 -0
- machine_dialect/parser/tests/test_define_statements.py +311 -0
- machine_dialect/parser/tests/test_dict_extraction.py +115 -0
- machine_dialect/parser/tests/test_empty_literal.py +155 -0
- machine_dialect/parser/tests/test_float_literal_expressions.py +163 -0
- machine_dialect/parser/tests/test_identifier_expressions.py +57 -0
- machine_dialect/parser/tests/test_if_empty_block.py +61 -0
- machine_dialect/parser/tests/test_if_statements.py +299 -0
- machine_dialect/parser/tests/test_illegal_tokens.py +86 -0
- machine_dialect/parser/tests/test_infix_expressions.py +680 -0
- machine_dialect/parser/tests/test_integer_literal_expressions.py +137 -0
- machine_dialect/parser/tests/test_interaction_statements.py +269 -0
- machine_dialect/parser/tests/test_list_literals.py +277 -0
- machine_dialect/parser/tests/test_no_none_in_ast.py +94 -0
- machine_dialect/parser/tests/test_panic_mode_recovery.py +171 -0
- machine_dialect/parser/tests/test_parse_errors.py +114 -0
- machine_dialect/parser/tests/test_possessive_syntax.py +182 -0
- machine_dialect/parser/tests/test_prefix_expressions.py +415 -0
- machine_dialect/parser/tests/test_program.py +13 -0
- machine_dialect/parser/tests/test_return_statements.py +89 -0
- machine_dialect/parser/tests/test_set_statements.py +152 -0
- machine_dialect/parser/tests/test_strict_equality.py +258 -0
- machine_dialect/parser/tests/test_symbol_table.py +217 -0
- machine_dialect/parser/tests/test_url_literal_expressions.py +209 -0
- machine_dialect/parser/tests/test_utility_statements.py +423 -0
- machine_dialect/parser/token_buffer.py +159 -0
- machine_dialect/repl/__init__.py +3 -0
- machine_dialect/repl/repl.py +426 -0
- machine_dialect/repl/tests/__init__.py +0 -0
- machine_dialect/repl/tests/test_repl.py +606 -0
- machine_dialect/semantic/__init__.py +12 -0
- machine_dialect/semantic/analyzer.py +906 -0
- machine_dialect/semantic/error_messages.py +189 -0
- machine_dialect/semantic/tests/__init__.py +1 -0
- machine_dialect/semantic/tests/test_analyzer.py +364 -0
- machine_dialect/semantic/tests/test_error_messages.py +104 -0
- machine_dialect/tests/edge_cases/__init__.py +10 -0
- machine_dialect/tests/edge_cases/test_boundary_access.py +256 -0
- machine_dialect/tests/edge_cases/test_empty_collections.py +166 -0
- machine_dialect/tests/edge_cases/test_invalid_operations.py +243 -0
- machine_dialect/tests/edge_cases/test_named_list_edge_cases.py +295 -0
- machine_dialect/tests/edge_cases/test_nested_structures.py +313 -0
- machine_dialect/tests/edge_cases/test_type_mixing.py +277 -0
- machine_dialect/tests/integration/test_array_operations_emulation.py +248 -0
- machine_dialect/tests/integration/test_list_compilation.py +395 -0
- machine_dialect/tests/integration/test_lists_and_dictionaries.py +322 -0
- machine_dialect/type_checking/__init__.py +21 -0
- machine_dialect/type_checking/tests/__init__.py +1 -0
- machine_dialect/type_checking/tests/test_type_system.py +230 -0
- machine_dialect/type_checking/type_system.py +270 -0
- machine_dialect-0.1.0a1.dist-info/METADATA +128 -0
- machine_dialect-0.1.0a1.dist-info/RECORD +268 -0
- machine_dialect-0.1.0a1.dist-info/WHEEL +5 -0
- machine_dialect-0.1.0a1.dist-info/entry_points.txt +3 -0
- machine_dialect-0.1.0a1.dist-info/licenses/LICENSE +201 -0
- machine_dialect-0.1.0a1.dist-info/top_level.txt +2 -0
- 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)})"
|