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,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]
|