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,445 @@
|
|
1
|
+
"""Tests for MIR TAC instructions."""
|
2
|
+
|
3
|
+
from machine_dialect.mir.mir_instructions import (
|
4
|
+
BinaryOp,
|
5
|
+
Call,
|
6
|
+
ConditionalJump,
|
7
|
+
Copy,
|
8
|
+
Jump,
|
9
|
+
Label,
|
10
|
+
LoadConst,
|
11
|
+
LoadVar,
|
12
|
+
Phi,
|
13
|
+
Return,
|
14
|
+
StoreVar,
|
15
|
+
UnaryOp,
|
16
|
+
)
|
17
|
+
from machine_dialect.mir.mir_types import MIRType
|
18
|
+
from machine_dialect.mir.mir_values import Constant, FunctionRef, Temp, Variable
|
19
|
+
|
20
|
+
|
21
|
+
class TestBinaryOp:
|
22
|
+
"""Test binary operation instruction."""
|
23
|
+
|
24
|
+
def test_binary_op_creation(self) -> None:
|
25
|
+
"""Test creating binary operations."""
|
26
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
27
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
28
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
29
|
+
|
30
|
+
add_op = BinaryOp(t0, "+", t1, t2, (1, 1))
|
31
|
+
assert str(add_op) == "t0 = t1 + t2"
|
32
|
+
assert add_op.dest == t0
|
33
|
+
assert add_op.op == "+"
|
34
|
+
assert add_op.left == t1
|
35
|
+
assert add_op.right == t2
|
36
|
+
|
37
|
+
def test_binary_op_uses_and_defs(self) -> None:
|
38
|
+
"""Test uses and defs for binary operations."""
|
39
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
40
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
41
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
42
|
+
|
43
|
+
mul_op = BinaryOp(t0, "*", t1, t2, (1, 1))
|
44
|
+
assert mul_op.get_uses(), [t1 == t2]
|
45
|
+
assert mul_op.get_defs() == [t0]
|
46
|
+
|
47
|
+
def test_binary_op_replace_use(self) -> None:
|
48
|
+
"""Test replacing uses in binary operations."""
|
49
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
50
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
51
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
52
|
+
t3 = Temp(MIRType.INT, temp_id=3)
|
53
|
+
|
54
|
+
sub_op = BinaryOp(t0, "-", t1, t2, (1, 1))
|
55
|
+
sub_op.replace_use(t1, t3)
|
56
|
+
assert sub_op.left == t3
|
57
|
+
assert sub_op.right == t2
|
58
|
+
assert str(sub_op) == "t0 = t3 - t2"
|
59
|
+
|
60
|
+
def test_comparison_operators(self) -> None:
|
61
|
+
"""Test comparison operators."""
|
62
|
+
t0 = Temp(MIRType.BOOL, temp_id=0)
|
63
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
64
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
65
|
+
|
66
|
+
eq_op = BinaryOp(t0, "==", t1, t2, (1, 1))
|
67
|
+
assert str(eq_op) == "t0 = t1 == t2"
|
68
|
+
|
69
|
+
lt_op = BinaryOp(t0, "<", t1, t2, (1, 1))
|
70
|
+
assert str(lt_op) == "t0 = t1 < t2"
|
71
|
+
|
72
|
+
ge_op = BinaryOp(t0, ">=", t1, t2, (1, 1))
|
73
|
+
assert str(ge_op) == "t0 = t1 >= t2"
|
74
|
+
|
75
|
+
|
76
|
+
class TestUnaryOp:
|
77
|
+
"""Test unary operation instruction."""
|
78
|
+
|
79
|
+
def test_unary_op_creation(self) -> None:
|
80
|
+
"""Test creating unary operations."""
|
81
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
82
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
83
|
+
|
84
|
+
neg_op = UnaryOp(t0, "-", t1, (1, 1))
|
85
|
+
assert str(neg_op) == "t0 = - t1"
|
86
|
+
assert neg_op.dest == t0
|
87
|
+
assert neg_op.op == "-"
|
88
|
+
assert neg_op.operand == t1
|
89
|
+
|
90
|
+
def test_unary_op_uses_and_defs(self) -> None:
|
91
|
+
"""Test uses and defs for unary operations."""
|
92
|
+
t0 = Temp(MIRType.BOOL, temp_id=0)
|
93
|
+
t1 = Temp(MIRType.BOOL, temp_id=1)
|
94
|
+
|
95
|
+
not_op = UnaryOp(t0, "not", t1, (1, 1))
|
96
|
+
assert not_op.get_uses() == [t1]
|
97
|
+
assert not_op.get_defs() == [t0]
|
98
|
+
|
99
|
+
def test_unary_op_replace_use(self) -> None:
|
100
|
+
"""Test replacing uses in unary operations."""
|
101
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
102
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
103
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
104
|
+
|
105
|
+
neg_op = UnaryOp(t0, "-", t1, (1, 1))
|
106
|
+
neg_op.replace_use(t1, t2)
|
107
|
+
assert neg_op.operand == t2
|
108
|
+
assert str(neg_op) == "t0 = - t2"
|
109
|
+
|
110
|
+
|
111
|
+
class TestCopy:
|
112
|
+
"""Test copy instruction."""
|
113
|
+
|
114
|
+
def test_copy_creation(self) -> None:
|
115
|
+
"""Test creating copy instructions."""
|
116
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
117
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
118
|
+
|
119
|
+
copy = Copy(t0, t1, (1, 1))
|
120
|
+
assert str(copy) == "t0 = t1"
|
121
|
+
assert copy.dest == t0
|
122
|
+
assert copy.source == t1
|
123
|
+
|
124
|
+
def test_copy_with_constant(self) -> None:
|
125
|
+
"""Test copy with constant source."""
|
126
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
127
|
+
c = Constant(42)
|
128
|
+
|
129
|
+
copy = Copy(t0, c, (1, 1))
|
130
|
+
assert str(copy) == "t0 = 42"
|
131
|
+
|
132
|
+
def test_copy_uses_and_defs(self) -> None:
|
133
|
+
"""Test uses and defs for copy instructions."""
|
134
|
+
v = Variable("x", MIRType.INT)
|
135
|
+
t = Temp(MIRType.INT, temp_id=0)
|
136
|
+
|
137
|
+
copy = Copy(v, t, (1, 1))
|
138
|
+
assert copy.get_uses() == [t]
|
139
|
+
assert copy.get_defs() == [v]
|
140
|
+
|
141
|
+
|
142
|
+
class TestLoadConst:
|
143
|
+
"""Test load constant instruction."""
|
144
|
+
|
145
|
+
def test_load_const_creation(self) -> None:
|
146
|
+
"""Test creating load constant instructions."""
|
147
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
148
|
+
load = LoadConst(t0, 42, (1, 1))
|
149
|
+
|
150
|
+
assert str(load) == "t0 = 42"
|
151
|
+
assert load.dest == t0
|
152
|
+
assert load.constant.value == 42
|
153
|
+
|
154
|
+
def test_load_const_with_different_types(self) -> None:
|
155
|
+
"""Test load constant with various types."""
|
156
|
+
t0 = Temp(MIRType.FLOAT, temp_id=0)
|
157
|
+
t1 = Temp(MIRType.STRING, temp_id=1)
|
158
|
+
t2 = Temp(MIRType.BOOL, temp_id=2)
|
159
|
+
|
160
|
+
load_float = LoadConst(t0, 3.14, (1, 1))
|
161
|
+
assert str(load_float) == "t0 = 3.14"
|
162
|
+
|
163
|
+
load_str = LoadConst(t1, "hello", (1, 1))
|
164
|
+
assert str(load_str) == 't1 = "hello"'
|
165
|
+
|
166
|
+
load_bool = LoadConst(t2, True, (1, 1))
|
167
|
+
assert str(load_bool) == "t2 = True"
|
168
|
+
|
169
|
+
def test_load_const_uses_and_defs(self) -> None:
|
170
|
+
"""Test uses and defs for load constant."""
|
171
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
172
|
+
load = LoadConst(t0, 100, (1, 1))
|
173
|
+
|
174
|
+
assert load.get_uses() == [] # Constants are not uses
|
175
|
+
assert load.get_defs() == [t0]
|
176
|
+
|
177
|
+
|
178
|
+
class TestLoadVar:
|
179
|
+
"""Test load variable instruction."""
|
180
|
+
|
181
|
+
def test_load_var_creation(self) -> None:
|
182
|
+
"""Test creating load variable instructions."""
|
183
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
184
|
+
v = Variable("x", MIRType.INT)
|
185
|
+
|
186
|
+
load = LoadVar(t0, v, (1, 1))
|
187
|
+
assert str(load) == "t0 = x"
|
188
|
+
assert load.dest == t0
|
189
|
+
assert load.var == v
|
190
|
+
|
191
|
+
def test_load_var_with_versioned_variable(self) -> None:
|
192
|
+
"""Test load with SSA versioned variable."""
|
193
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
194
|
+
v = Variable("x", MIRType.INT, version=2)
|
195
|
+
|
196
|
+
load = LoadVar(t0, v, (1, 1))
|
197
|
+
assert str(load) == "t0 = x.2"
|
198
|
+
|
199
|
+
def test_load_var_uses_and_defs(self) -> None:
|
200
|
+
"""Test uses and defs for load variable."""
|
201
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
202
|
+
v = Variable("counter", MIRType.INT)
|
203
|
+
|
204
|
+
load = LoadVar(t0, v, (1, 1))
|
205
|
+
assert load.get_uses() == [v]
|
206
|
+
assert load.get_defs() == [t0]
|
207
|
+
|
208
|
+
|
209
|
+
class TestStoreVar:
|
210
|
+
"""Test store variable instruction."""
|
211
|
+
|
212
|
+
def test_store_var_creation(self) -> None:
|
213
|
+
"""Test creating store variable instructions."""
|
214
|
+
v = Variable("x", MIRType.INT)
|
215
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
216
|
+
|
217
|
+
store = StoreVar(v, t0, (1, 1))
|
218
|
+
assert str(store) == "x = t0"
|
219
|
+
assert store.var == v
|
220
|
+
assert store.source == t0
|
221
|
+
|
222
|
+
def test_store_var_with_constant(self) -> None:
|
223
|
+
"""Test store with constant source."""
|
224
|
+
v = Variable("count", MIRType.INT)
|
225
|
+
c = Constant(10)
|
226
|
+
|
227
|
+
store = StoreVar(v, c, (1, 1))
|
228
|
+
assert str(store) == "count = 10"
|
229
|
+
|
230
|
+
def test_store_var_uses_and_defs(self) -> None:
|
231
|
+
"""Test uses and defs for store variable."""
|
232
|
+
v = Variable("result", MIRType.FLOAT)
|
233
|
+
t = Temp(MIRType.FLOAT, temp_id=0)
|
234
|
+
|
235
|
+
store = StoreVar(v, t, (1, 1))
|
236
|
+
assert store.get_uses() == [t]
|
237
|
+
assert store.get_defs() == [v]
|
238
|
+
|
239
|
+
|
240
|
+
class TestCall:
|
241
|
+
"""Test function call instruction."""
|
242
|
+
|
243
|
+
def test_call_creation(self) -> None:
|
244
|
+
"""Test creating call instructions."""
|
245
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
246
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
247
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
248
|
+
func = FunctionRef("add")
|
249
|
+
|
250
|
+
call = Call(t0, func, [t1, t2], (1, 1))
|
251
|
+
assert str(call), "t0 = call @add(t1 == t2)"
|
252
|
+
assert call.dest == t0
|
253
|
+
assert call.func == func
|
254
|
+
assert call.args, [t1 == t2]
|
255
|
+
|
256
|
+
def test_call_without_return(self) -> None:
|
257
|
+
"""Test void call without destination."""
|
258
|
+
t0 = Temp(MIRType.STRING, temp_id=0)
|
259
|
+
func = FunctionRef("print")
|
260
|
+
|
261
|
+
call = Call(None, func, [t0], (1, 1))
|
262
|
+
assert str(call) == "call @print(t0)"
|
263
|
+
assert call.dest is None
|
264
|
+
|
265
|
+
def test_call_with_string_function_name(self) -> None:
|
266
|
+
"""Test call with string function name."""
|
267
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
268
|
+
call = Call(t0, "factorial", [Constant(5)], (1, 1))
|
269
|
+
assert str(call) == "t0 = call @factorial(5)"
|
270
|
+
assert isinstance(call.func, FunctionRef)
|
271
|
+
|
272
|
+
def test_call_uses_and_defs(self) -> None:
|
273
|
+
"""Test uses and defs for call instructions."""
|
274
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
275
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
276
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
277
|
+
|
278
|
+
call = Call(t0, "max", [t1, t2], (1, 1))
|
279
|
+
assert call.get_uses(), [t1 == t2]
|
280
|
+
assert call.get_defs() == [t0]
|
281
|
+
|
282
|
+
void_call = Call(None, "print", [t1], (1, 1))
|
283
|
+
assert void_call.get_uses() == [t1]
|
284
|
+
assert void_call.get_defs() == []
|
285
|
+
|
286
|
+
def test_call_replace_use(self) -> None:
|
287
|
+
"""Test replacing argument values."""
|
288
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
289
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
290
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
291
|
+
t3 = Temp(MIRType.INT, temp_id=3)
|
292
|
+
|
293
|
+
call = Call(t0, "compute", [t1, t2], (1, 1))
|
294
|
+
call.replace_use(t1, t3)
|
295
|
+
assert call.args, [t3 == t2]
|
296
|
+
|
297
|
+
|
298
|
+
class TestReturn:
|
299
|
+
"""Test return instruction."""
|
300
|
+
|
301
|
+
def test_return_with_value(self) -> None:
|
302
|
+
"""Test return with value."""
|
303
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
304
|
+
ret = Return((1, 1), t0)
|
305
|
+
assert str(ret) == "return t0"
|
306
|
+
assert ret.value == t0
|
307
|
+
|
308
|
+
def test_return_without_value(self) -> None:
|
309
|
+
"""Test void return."""
|
310
|
+
ret = Return((1, 1))
|
311
|
+
assert str(ret) == "return"
|
312
|
+
assert ret.value is None
|
313
|
+
|
314
|
+
def test_return_uses_and_defs(self) -> None:
|
315
|
+
"""Test uses and defs for return."""
|
316
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
317
|
+
ret = Return((1, 1), t0)
|
318
|
+
assert ret.get_uses() == [t0]
|
319
|
+
assert ret.get_defs() == []
|
320
|
+
|
321
|
+
void_ret = Return((1, 1))
|
322
|
+
assert void_ret.get_uses() == []
|
323
|
+
assert void_ret.get_defs() == []
|
324
|
+
|
325
|
+
|
326
|
+
class TestJump:
|
327
|
+
"""Test unconditional jump instruction."""
|
328
|
+
|
329
|
+
def test_jump_creation(self) -> None:
|
330
|
+
"""Test creating jump instructions."""
|
331
|
+
jump = Jump("loop_start", (1, 1))
|
332
|
+
assert str(jump) == "goto loop_start"
|
333
|
+
assert jump.label == "loop_start"
|
334
|
+
|
335
|
+
def test_jump_uses_and_defs(self) -> None:
|
336
|
+
"""Test uses and defs for jump."""
|
337
|
+
jump = Jump("exit", (1, 1))
|
338
|
+
assert jump.get_uses() == []
|
339
|
+
assert jump.get_defs() == []
|
340
|
+
|
341
|
+
|
342
|
+
class TestConditionalJump:
|
343
|
+
"""Test conditional jump instruction."""
|
344
|
+
|
345
|
+
def test_conditional_jump_with_else(self) -> None:
|
346
|
+
"""Test conditional jump with else branch."""
|
347
|
+
t0 = Temp(MIRType.BOOL, temp_id=0)
|
348
|
+
cjump = ConditionalJump(t0, "then_block", (1, 1), "else_block")
|
349
|
+
|
350
|
+
assert str(cjump) == "if t0 goto then_block else else_block"
|
351
|
+
assert cjump.condition == t0
|
352
|
+
assert cjump.true_label == "then_block"
|
353
|
+
assert cjump.false_label == "else_block"
|
354
|
+
|
355
|
+
def test_conditional_jump_without_else(self) -> None:
|
356
|
+
"""Test conditional jump with fallthrough."""
|
357
|
+
t0 = Temp(MIRType.BOOL, temp_id=0)
|
358
|
+
cjump = ConditionalJump(t0, "skip", (1, 1))
|
359
|
+
|
360
|
+
assert str(cjump) == "if t0 goto skip"
|
361
|
+
assert cjump.true_label == "skip"
|
362
|
+
assert cjump.false_label is None
|
363
|
+
|
364
|
+
def test_conditional_jump_uses_and_defs(self) -> None:
|
365
|
+
"""Test uses and defs for conditional jump."""
|
366
|
+
t0 = Temp(MIRType.BOOL, temp_id=0)
|
367
|
+
cjump = ConditionalJump(t0, "L1", (1, 1), "L2")
|
368
|
+
|
369
|
+
assert cjump.get_uses() == [t0]
|
370
|
+
assert cjump.get_defs() == []
|
371
|
+
|
372
|
+
def test_conditional_jump_replace_use(self) -> None:
|
373
|
+
"""Test replacing condition value."""
|
374
|
+
t0 = Temp(MIRType.BOOL, temp_id=0)
|
375
|
+
t1 = Temp(MIRType.BOOL, temp_id=1)
|
376
|
+
cjump = ConditionalJump(t0, "L1", (1, 1))
|
377
|
+
|
378
|
+
cjump.replace_use(t0, t1)
|
379
|
+
assert cjump.condition == t1
|
380
|
+
|
381
|
+
|
382
|
+
class TestPhi:
|
383
|
+
"""Test SSA phi node instruction."""
|
384
|
+
|
385
|
+
def test_phi_creation(self) -> None:
|
386
|
+
"""Test creating phi nodes."""
|
387
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
388
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
389
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
390
|
+
|
391
|
+
phi = Phi(t0, [(t1, "block1"), (t2, "block2")], (1, 1))
|
392
|
+
assert str(phi), "t0 = φ(t1:block1 == t2:block2)"
|
393
|
+
assert phi.dest == t0
|
394
|
+
assert phi.incoming, [(t1, "block1"), (t2 == "block2")]
|
395
|
+
|
396
|
+
def test_phi_add_incoming(self) -> None:
|
397
|
+
"""Test adding incoming values to phi node."""
|
398
|
+
v = Variable("x", MIRType.INT, version=3)
|
399
|
+
v1 = Variable("x", MIRType.INT, version=1)
|
400
|
+
v2 = Variable("x", MIRType.INT, version=2)
|
401
|
+
|
402
|
+
phi = Phi(v, [(v1, "entry")], (1, 1))
|
403
|
+
phi.add_incoming(v2, "loop")
|
404
|
+
|
405
|
+
assert len(phi.incoming) == 2
|
406
|
+
assert phi.incoming[1], v2 == "loop"
|
407
|
+
|
408
|
+
def test_phi_uses_and_defs(self) -> None:
|
409
|
+
"""Test uses and defs for phi nodes."""
|
410
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
411
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
412
|
+
c = Constant(0)
|
413
|
+
|
414
|
+
phi = Phi(t0, [(t1, "loop"), (c, "entry")], (1, 1))
|
415
|
+
assert phi.get_uses(), [t1 == c]
|
416
|
+
assert phi.get_defs() == [t0]
|
417
|
+
|
418
|
+
def test_phi_replace_use(self) -> None:
|
419
|
+
"""Test replacing incoming values in phi node."""
|
420
|
+
t0 = Temp(MIRType.INT, temp_id=0)
|
421
|
+
t1 = Temp(MIRType.INT, temp_id=1)
|
422
|
+
t2 = Temp(MIRType.INT, temp_id=2)
|
423
|
+
t3 = Temp(MIRType.INT, temp_id=3)
|
424
|
+
|
425
|
+
phi = Phi(t0, [(t1, "L1"), (t2, "L2")], (1, 1))
|
426
|
+
phi.replace_use(t1, t3)
|
427
|
+
|
428
|
+
assert phi.incoming[0], t3 == "L1"
|
429
|
+
assert phi.incoming[1], t2 == "L2"
|
430
|
+
|
431
|
+
|
432
|
+
class TestLabel:
|
433
|
+
"""Test label pseudo-instruction."""
|
434
|
+
|
435
|
+
def test_label_creation(self) -> None:
|
436
|
+
"""Test creating labels."""
|
437
|
+
label = Label("loop_start", (1, 1))
|
438
|
+
assert str(label) == "loop_start:"
|
439
|
+
assert label.name == "loop_start"
|
440
|
+
|
441
|
+
def test_label_uses_and_defs(self) -> None:
|
442
|
+
"""Test uses and defs for labels."""
|
443
|
+
label = Label("exit", (1, 1))
|
444
|
+
assert label.get_uses() == []
|
445
|
+
assert label.get_defs() == []
|