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,1877 @@
|
|
1
|
+
"""MIR Three-Address Code Instructions.
|
2
|
+
|
3
|
+
This module defines the TAC instruction set used in the MIR.
|
4
|
+
Each instruction follows the three-address code format where possible.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from abc import ABC, abstractmethod
|
8
|
+
from typing import Any
|
9
|
+
|
10
|
+
from .mir_types import MIRType, MIRUnionType
|
11
|
+
from .mir_values import Constant, FunctionRef, MIRValue, Temp, Variable
|
12
|
+
|
13
|
+
|
14
|
+
class MIRInstruction(ABC):
|
15
|
+
"""Base class for all MIR instructions with rich metadata."""
|
16
|
+
|
17
|
+
def __init__(self, source_location: tuple[int, int]) -> None:
|
18
|
+
"""Initialize instruction with metadata.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
source_location: Required (line, column) from source code for error reporting.
|
22
|
+
"""
|
23
|
+
# Rich metadata for optimization
|
24
|
+
self.result_type: MIRType | None = None # Inferred type of result
|
25
|
+
self.is_pure: bool = False # No side effects
|
26
|
+
self.can_throw: bool = False # Can raise exceptions
|
27
|
+
self.cost: int = 1 # Estimated execution cost
|
28
|
+
self.is_commutative: bool = False # Operands can be swapped
|
29
|
+
self.is_associative: bool = False # Can be regrouped
|
30
|
+
self.memory_effects: set[str] = set() # Memory locations affected
|
31
|
+
# Source location for error reporting (REQUIRED for proper error messages)
|
32
|
+
self.source_location: tuple[int, int] = source_location # (line, column)
|
33
|
+
|
34
|
+
@abstractmethod
|
35
|
+
def __str__(self) -> str:
|
36
|
+
"""Return string representation of the instruction."""
|
37
|
+
pass
|
38
|
+
|
39
|
+
@abstractmethod
|
40
|
+
def get_uses(self) -> list[MIRValue]:
|
41
|
+
"""Get values used (read) by this instruction.
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
List of values that this instruction reads.
|
45
|
+
"""
|
46
|
+
pass
|
47
|
+
|
48
|
+
@abstractmethod
|
49
|
+
def get_defs(self) -> list[MIRValue]:
|
50
|
+
"""Get values defined (written) by this instruction.
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
List of values that this instruction writes.
|
54
|
+
"""
|
55
|
+
pass
|
56
|
+
|
57
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None: # noqa: B027
|
58
|
+
"""Replace uses of a value in this instruction.
|
59
|
+
|
60
|
+
Args:
|
61
|
+
old_value: The value to replace.
|
62
|
+
new_value: The replacement value.
|
63
|
+
"""
|
64
|
+
# Default implementation does nothing - this is intentional
|
65
|
+
# Subclasses should override if they have uses
|
66
|
+
# Not abstract because many instructions don't use values
|
67
|
+
pass
|
68
|
+
|
69
|
+
|
70
|
+
class BinaryOp(MIRInstruction):
|
71
|
+
"""Binary operation: dest = left op right."""
|
72
|
+
|
73
|
+
def __init__(
|
74
|
+
self, dest: MIRValue, op: str, left: MIRValue, right: MIRValue, source_location: tuple[int, int]
|
75
|
+
) -> None:
|
76
|
+
"""Initialize a binary operation.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
dest: Destination to store result.
|
80
|
+
op: Operator (+, -, *, /, %, ^, ==, !=, <, >, <=, >=, and, or).
|
81
|
+
left: Left operand.
|
82
|
+
right: Right operand.
|
83
|
+
source_location: Source code location (line, column).
|
84
|
+
"""
|
85
|
+
super().__init__(source_location)
|
86
|
+
self.dest = dest
|
87
|
+
self.op = op
|
88
|
+
self.left = left
|
89
|
+
self.right = right
|
90
|
+
|
91
|
+
# Set metadata based on operator
|
92
|
+
if op in ["+", "*", "==", "!=", "and", "or"]:
|
93
|
+
self.is_commutative = True
|
94
|
+
if op in ["+", "*", "and", "or"]:
|
95
|
+
self.is_associative = True
|
96
|
+
if op in ["+", "-", "*", "==", "!=", "<", ">", "<=", ">="]:
|
97
|
+
self.is_pure = True
|
98
|
+
if op == "/":
|
99
|
+
self.can_throw = True # Division by zero
|
100
|
+
|
101
|
+
# Set cost estimates
|
102
|
+
if op in ["*", "/", "%", "**"]:
|
103
|
+
self.cost = 3
|
104
|
+
elif op in ["+", "-"]:
|
105
|
+
self.cost = 1
|
106
|
+
else:
|
107
|
+
self.cost = 2
|
108
|
+
|
109
|
+
def __str__(self) -> str:
|
110
|
+
"""Return string representation."""
|
111
|
+
return f"{self.dest} = {self.left} {self.op} {self.right}"
|
112
|
+
|
113
|
+
def get_uses(self) -> list[MIRValue]:
|
114
|
+
"""Get operands used."""
|
115
|
+
return [self.left, self.right]
|
116
|
+
|
117
|
+
def get_defs(self) -> list[MIRValue]:
|
118
|
+
"""Get destination defined."""
|
119
|
+
return [self.dest]
|
120
|
+
|
121
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
122
|
+
"""Replace uses of a value."""
|
123
|
+
if self.left == old_value:
|
124
|
+
self.left = new_value
|
125
|
+
if self.right == old_value:
|
126
|
+
self.right = new_value
|
127
|
+
|
128
|
+
|
129
|
+
class UnaryOp(MIRInstruction):
|
130
|
+
"""Unary operation: dest = op operand."""
|
131
|
+
|
132
|
+
def __init__(self, dest: MIRValue, op: str, operand: MIRValue, source_location: tuple[int, int]) -> None:
|
133
|
+
"""Initialize a unary operation.
|
134
|
+
|
135
|
+
Args:
|
136
|
+
dest: Destination to store result.
|
137
|
+
op: Operator (-, not, abs).
|
138
|
+
operand: Operand.
|
139
|
+
source_location: Source code location (line, column).
|
140
|
+
"""
|
141
|
+
super().__init__(source_location)
|
142
|
+
self.dest = dest
|
143
|
+
self.op = op
|
144
|
+
self.operand = operand
|
145
|
+
|
146
|
+
# All unary ops are pure
|
147
|
+
self.is_pure = True
|
148
|
+
self.cost = 1
|
149
|
+
|
150
|
+
def __str__(self) -> str:
|
151
|
+
"""Return string representation."""
|
152
|
+
return f"{self.dest} = {self.op} {self.operand}"
|
153
|
+
|
154
|
+
def get_uses(self) -> list[MIRValue]:
|
155
|
+
"""Get operand used."""
|
156
|
+
return [self.operand]
|
157
|
+
|
158
|
+
def get_defs(self) -> list[MIRValue]:
|
159
|
+
"""Get destination defined."""
|
160
|
+
return [self.dest]
|
161
|
+
|
162
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
163
|
+
"""Replace uses of a value."""
|
164
|
+
if self.operand == old_value:
|
165
|
+
self.operand = new_value
|
166
|
+
|
167
|
+
|
168
|
+
class ShiftOp(MIRInstruction):
|
169
|
+
"""Bitwise shift operation: dest = left op right.
|
170
|
+
|
171
|
+
Used for strength reduction optimizations where multiply/divide
|
172
|
+
by powers of 2 are converted to shift operations.
|
173
|
+
"""
|
174
|
+
|
175
|
+
def __init__(
|
176
|
+
self, dest: MIRValue, left: MIRValue, right: MIRValue, op: str, source_location: tuple[int, int]
|
177
|
+
) -> None:
|
178
|
+
"""Initialize a shift operation.
|
179
|
+
|
180
|
+
Args:
|
181
|
+
dest: Destination to store result.
|
182
|
+
left: Value to shift.
|
183
|
+
right: Shift amount.
|
184
|
+
op: Shift operator ('<<' for left shift, '>>' for right shift).
|
185
|
+
source_location: Source code location (line, column).
|
186
|
+
"""
|
187
|
+
super().__init__(source_location)
|
188
|
+
self.dest = dest
|
189
|
+
self.left = left
|
190
|
+
self.right = right
|
191
|
+
self.op = op
|
192
|
+
|
193
|
+
def __str__(self) -> str:
|
194
|
+
"""Return string representation."""
|
195
|
+
return f"{self.dest} = {self.left} {self.op} {self.right}"
|
196
|
+
|
197
|
+
def get_uses(self) -> list[MIRValue]:
|
198
|
+
"""Get operands used."""
|
199
|
+
return [self.left, self.right]
|
200
|
+
|
201
|
+
def get_defs(self) -> list[MIRValue]:
|
202
|
+
"""Get destination defined."""
|
203
|
+
return [self.dest]
|
204
|
+
|
205
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
206
|
+
"""Replace uses of a value."""
|
207
|
+
if self.left == old_value:
|
208
|
+
self.left = new_value
|
209
|
+
if self.right == old_value:
|
210
|
+
self.right = new_value
|
211
|
+
|
212
|
+
|
213
|
+
class Copy(MIRInstruction):
|
214
|
+
"""Copy instruction: dest = source."""
|
215
|
+
|
216
|
+
def __init__(self, dest: MIRValue, source: MIRValue, source_location: tuple[int, int]) -> None:
|
217
|
+
"""Initialize a copy instruction.
|
218
|
+
|
219
|
+
Args:
|
220
|
+
dest: Destination.
|
221
|
+
source: Source value.
|
222
|
+
source_location: Source code location (line, column).
|
223
|
+
"""
|
224
|
+
super().__init__(source_location)
|
225
|
+
self.dest = dest
|
226
|
+
self.source = source
|
227
|
+
|
228
|
+
def __str__(self) -> str:
|
229
|
+
"""Return string representation."""
|
230
|
+
return f"{self.dest} = {self.source}"
|
231
|
+
|
232
|
+
def get_uses(self) -> list[MIRValue]:
|
233
|
+
"""Get source used."""
|
234
|
+
return [self.source]
|
235
|
+
|
236
|
+
def get_defs(self) -> list[MIRValue]:
|
237
|
+
"""Get destination defined."""
|
238
|
+
return [self.dest]
|
239
|
+
|
240
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
241
|
+
"""Replace uses of a value."""
|
242
|
+
if self.source == old_value:
|
243
|
+
self.source = new_value
|
244
|
+
|
245
|
+
|
246
|
+
class LoadConst(MIRInstruction):
|
247
|
+
"""Load constant: dest = constant."""
|
248
|
+
|
249
|
+
def __init__(self, dest: MIRValue, value: Any, source_location: tuple[int, int]) -> None:
|
250
|
+
"""Initialize a load constant instruction.
|
251
|
+
|
252
|
+
Args:
|
253
|
+
dest: Destination.
|
254
|
+
value: Constant value to load.
|
255
|
+
source_location: Source code location (line, column).
|
256
|
+
"""
|
257
|
+
super().__init__(source_location)
|
258
|
+
self.dest = dest
|
259
|
+
self.constant = Constant(value) if not isinstance(value, Constant) else value
|
260
|
+
|
261
|
+
def __str__(self) -> str:
|
262
|
+
"""Return string representation."""
|
263
|
+
return f"{self.dest} = {self.constant}"
|
264
|
+
|
265
|
+
def get_uses(self) -> list[MIRValue]:
|
266
|
+
"""Constants are not uses."""
|
267
|
+
return []
|
268
|
+
|
269
|
+
def get_defs(self) -> list[MIRValue]:
|
270
|
+
"""Get destination defined."""
|
271
|
+
return [self.dest]
|
272
|
+
|
273
|
+
|
274
|
+
class LoadVar(MIRInstruction):
|
275
|
+
"""Load variable: dest = variable."""
|
276
|
+
|
277
|
+
def __init__(self, dest: MIRValue, var: Variable, source_location: tuple[int, int]) -> None:
|
278
|
+
"""Initialize a load variable instruction.
|
279
|
+
|
280
|
+
Args:
|
281
|
+
dest: Destination temporary.
|
282
|
+
var: Variable to load from.
|
283
|
+
source_location: Source code location (line, column).
|
284
|
+
"""
|
285
|
+
super().__init__(source_location)
|
286
|
+
self.dest = dest
|
287
|
+
self.var = var
|
288
|
+
|
289
|
+
def __str__(self) -> str:
|
290
|
+
"""Return string representation."""
|
291
|
+
return f"{self.dest} = {self.var}"
|
292
|
+
|
293
|
+
def get_uses(self) -> list[MIRValue]:
|
294
|
+
"""Get variable used."""
|
295
|
+
return [self.var]
|
296
|
+
|
297
|
+
def get_defs(self) -> list[MIRValue]:
|
298
|
+
"""Get destination defined."""
|
299
|
+
return [self.dest]
|
300
|
+
|
301
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
302
|
+
"""Replace uses of a value."""
|
303
|
+
if self.var == old_value and isinstance(new_value, Variable):
|
304
|
+
self.var = new_value
|
305
|
+
|
306
|
+
|
307
|
+
class StoreVar(MIRInstruction):
|
308
|
+
"""Store to variable: variable = source."""
|
309
|
+
|
310
|
+
def __init__(self, var: Variable, source: MIRValue, source_location: tuple[int, int]) -> None:
|
311
|
+
"""Initialize a store variable instruction.
|
312
|
+
|
313
|
+
Args:
|
314
|
+
var: Variable to store to.
|
315
|
+
source: Source value.
|
316
|
+
source_location: Source code location (line, column).
|
317
|
+
"""
|
318
|
+
super().__init__(source_location)
|
319
|
+
self.var = var
|
320
|
+
self.source = source
|
321
|
+
|
322
|
+
def __str__(self) -> str:
|
323
|
+
"""Return string representation."""
|
324
|
+
return f"{self.var} = {self.source}"
|
325
|
+
|
326
|
+
def get_uses(self) -> list[MIRValue]:
|
327
|
+
"""Get source used."""
|
328
|
+
return [self.source]
|
329
|
+
|
330
|
+
def get_defs(self) -> list[MIRValue]:
|
331
|
+
"""Get variable defined."""
|
332
|
+
return [self.var]
|
333
|
+
|
334
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
335
|
+
"""Replace uses of a value."""
|
336
|
+
if self.source == old_value:
|
337
|
+
self.source = new_value
|
338
|
+
|
339
|
+
|
340
|
+
class Call(MIRInstruction):
|
341
|
+
"""Function call: dest = call func(args)."""
|
342
|
+
|
343
|
+
def __init__(
|
344
|
+
self,
|
345
|
+
dest: MIRValue | None,
|
346
|
+
func: FunctionRef | str,
|
347
|
+
args: list[MIRValue],
|
348
|
+
source_location: tuple[int, int],
|
349
|
+
is_tail_call: bool = False,
|
350
|
+
) -> None:
|
351
|
+
"""Initialize a function call.
|
352
|
+
|
353
|
+
Args:
|
354
|
+
dest: Optional destination for return value.
|
355
|
+
func: Function to call (FunctionRef or name string).
|
356
|
+
args: Arguments to pass.
|
357
|
+
source_location: Source code location (line, column).
|
358
|
+
is_tail_call: Whether this is a tail call that can be optimized.
|
359
|
+
"""
|
360
|
+
super().__init__(source_location)
|
361
|
+
self.dest = dest
|
362
|
+
self.func = FunctionRef(func) if isinstance(func, str) else func
|
363
|
+
self.args = args
|
364
|
+
self.is_tail_call = is_tail_call
|
365
|
+
|
366
|
+
def __str__(self) -> str:
|
367
|
+
"""Return string representation."""
|
368
|
+
args_str = ", ".join(str(arg) for arg in self.args)
|
369
|
+
tail_str = " [tail]" if self.is_tail_call else ""
|
370
|
+
if self.dest:
|
371
|
+
return f"{self.dest} = call {self.func}({args_str}){tail_str}"
|
372
|
+
else:
|
373
|
+
return f"call {self.func}({args_str}){tail_str}"
|
374
|
+
|
375
|
+
def get_uses(self) -> list[MIRValue]:
|
376
|
+
"""Get arguments used."""
|
377
|
+
return self.args.copy()
|
378
|
+
|
379
|
+
def get_defs(self) -> list[MIRValue]:
|
380
|
+
"""Get destination defined if any."""
|
381
|
+
return [self.dest] if self.dest else []
|
382
|
+
|
383
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
384
|
+
"""Replace uses of a value in arguments."""
|
385
|
+
self.args = [new_value if arg == old_value else arg for arg in self.args]
|
386
|
+
|
387
|
+
|
388
|
+
class Return(MIRInstruction):
|
389
|
+
"""Return instruction: return value."""
|
390
|
+
|
391
|
+
def __init__(self, source_location: tuple[int, int], value: MIRValue | None = None) -> None:
|
392
|
+
"""Initialize a return instruction.
|
393
|
+
|
394
|
+
Args:
|
395
|
+
source_location: Source code location (line, column).
|
396
|
+
value: Optional value to return.
|
397
|
+
"""
|
398
|
+
super().__init__(source_location)
|
399
|
+
self.value = value
|
400
|
+
|
401
|
+
def __str__(self) -> str:
|
402
|
+
"""Return string representation."""
|
403
|
+
if self.value:
|
404
|
+
return f"return {self.value}"
|
405
|
+
else:
|
406
|
+
return "return"
|
407
|
+
|
408
|
+
def get_uses(self) -> list[MIRValue]:
|
409
|
+
"""Get value used if any."""
|
410
|
+
return [self.value] if self.value else []
|
411
|
+
|
412
|
+
def get_defs(self) -> list[MIRValue]:
|
413
|
+
"""Return defines nothing."""
|
414
|
+
return []
|
415
|
+
|
416
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
417
|
+
"""Replace uses of a value."""
|
418
|
+
if self.value == old_value:
|
419
|
+
self.value = new_value
|
420
|
+
|
421
|
+
|
422
|
+
class Jump(MIRInstruction):
|
423
|
+
"""Unconditional jump: goto label."""
|
424
|
+
|
425
|
+
def __init__(self, label: str, source_location: tuple[int, int]) -> None:
|
426
|
+
"""Initialize a jump instruction.
|
427
|
+
|
428
|
+
Args:
|
429
|
+
label: Target label.
|
430
|
+
source_location: Source code location (line, column).
|
431
|
+
"""
|
432
|
+
super().__init__(source_location)
|
433
|
+
self.label = label
|
434
|
+
|
435
|
+
def __str__(self) -> str:
|
436
|
+
"""Return string representation."""
|
437
|
+
return f"goto {self.label}"
|
438
|
+
|
439
|
+
def get_uses(self) -> list[MIRValue]:
|
440
|
+
"""Jump uses nothing."""
|
441
|
+
return []
|
442
|
+
|
443
|
+
def get_defs(self) -> list[MIRValue]:
|
444
|
+
"""Jump defines nothing."""
|
445
|
+
return []
|
446
|
+
|
447
|
+
|
448
|
+
class ConditionalJump(MIRInstruction):
|
449
|
+
"""Conditional jump: if condition goto true_label else false_label."""
|
450
|
+
|
451
|
+
def __init__(
|
452
|
+
self, condition: MIRValue, true_label: str, source_location: tuple[int, int], false_label: str | None = None
|
453
|
+
) -> None:
|
454
|
+
"""Initialize a conditional jump.
|
455
|
+
|
456
|
+
Args:
|
457
|
+
condition: Condition to test.
|
458
|
+
true_label: Label to jump to if true.
|
459
|
+
source_location: Source code location (line, column).
|
460
|
+
false_label: Optional label to jump to if false (falls through if None).
|
461
|
+
"""
|
462
|
+
super().__init__(source_location)
|
463
|
+
self.condition = condition
|
464
|
+
self.true_label = true_label
|
465
|
+
self.false_label = false_label
|
466
|
+
|
467
|
+
def __str__(self) -> str:
|
468
|
+
"""Return string representation."""
|
469
|
+
if self.false_label:
|
470
|
+
return f"if {self.condition} goto {self.true_label} else {self.false_label}"
|
471
|
+
else:
|
472
|
+
return f"if {self.condition} goto {self.true_label}"
|
473
|
+
|
474
|
+
def get_uses(self) -> list[MIRValue]:
|
475
|
+
"""Get condition used."""
|
476
|
+
return [self.condition]
|
477
|
+
|
478
|
+
def get_defs(self) -> list[MIRValue]:
|
479
|
+
"""Conditional jump defines nothing."""
|
480
|
+
return []
|
481
|
+
|
482
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
483
|
+
"""Replace uses of a value."""
|
484
|
+
if self.condition == old_value:
|
485
|
+
self.condition = new_value
|
486
|
+
|
487
|
+
|
488
|
+
class Phi(MIRInstruction):
|
489
|
+
"""SSA phi node: dest = φ(value1, value2, ...).
|
490
|
+
|
491
|
+
Phi nodes are used at join points in SSA form to merge values
|
492
|
+
from different control flow paths.
|
493
|
+
"""
|
494
|
+
|
495
|
+
def __init__(self, dest: MIRValue, incoming: list[tuple[MIRValue, str]], source_location: tuple[int, int]) -> None:
|
496
|
+
"""Initialize a phi node.
|
497
|
+
|
498
|
+
Args:
|
499
|
+
dest: Destination to store merged value.
|
500
|
+
incoming: List of (value, predecessor_label) pairs.
|
501
|
+
source_location: Source code location (line, column).
|
502
|
+
"""
|
503
|
+
super().__init__(source_location)
|
504
|
+
self.dest = dest
|
505
|
+
self.incoming = incoming
|
506
|
+
|
507
|
+
def __str__(self) -> str:
|
508
|
+
"""Return string representation."""
|
509
|
+
args = ", ".join(f"{val}:{label}" for val, label in self.incoming)
|
510
|
+
return f"{self.dest} = φ({args})"
|
511
|
+
|
512
|
+
def get_uses(self) -> list[MIRValue]:
|
513
|
+
"""Get all incoming values."""
|
514
|
+
return [val for val, _ in self.incoming]
|
515
|
+
|
516
|
+
def get_defs(self) -> list[MIRValue]:
|
517
|
+
"""Get destination defined."""
|
518
|
+
return [self.dest]
|
519
|
+
|
520
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
521
|
+
"""Replace uses of a value in incoming values."""
|
522
|
+
self.incoming = [(new_value if val == old_value else val, label) for val, label in self.incoming]
|
523
|
+
|
524
|
+
def add_incoming(self, value: MIRValue, label: str) -> None:
|
525
|
+
"""Add an incoming value from a predecessor.
|
526
|
+
|
527
|
+
Args:
|
528
|
+
value: The value from the predecessor.
|
529
|
+
label: The predecessor's label.
|
530
|
+
"""
|
531
|
+
self.incoming.append((value, label))
|
532
|
+
|
533
|
+
|
534
|
+
class Label(MIRInstruction):
|
535
|
+
"""Label pseudo-instruction: label_name:."""
|
536
|
+
|
537
|
+
def __init__(self, name: str, source_location: tuple[int, int]) -> None:
|
538
|
+
"""Initialize a label.
|
539
|
+
|
540
|
+
Args:
|
541
|
+
name: Label name.
|
542
|
+
source_location: Source code location (line, column).
|
543
|
+
"""
|
544
|
+
super().__init__(source_location)
|
545
|
+
self.name = name
|
546
|
+
|
547
|
+
def __str__(self) -> str:
|
548
|
+
"""Return string representation."""
|
549
|
+
return f"{self.name}:"
|
550
|
+
|
551
|
+
def get_uses(self) -> list[MIRValue]:
|
552
|
+
"""Labels use nothing."""
|
553
|
+
return []
|
554
|
+
|
555
|
+
def get_defs(self) -> list[MIRValue]:
|
556
|
+
"""Labels define nothing."""
|
557
|
+
return []
|
558
|
+
|
559
|
+
|
560
|
+
class Print(MIRInstruction):
|
561
|
+
"""Print instruction for Say/Tell statements: print value."""
|
562
|
+
|
563
|
+
def __init__(self, value: MIRValue, source_location: tuple[int, int]) -> None:
|
564
|
+
"""Initialize a print instruction.
|
565
|
+
|
566
|
+
Args:
|
567
|
+
value: Value to print.
|
568
|
+
source_location: Source code location (line, column).
|
569
|
+
"""
|
570
|
+
super().__init__(source_location)
|
571
|
+
self.value = value
|
572
|
+
|
573
|
+
def __str__(self) -> str:
|
574
|
+
"""Return string representation."""
|
575
|
+
return f"print {self.value}"
|
576
|
+
|
577
|
+
def get_uses(self) -> list[MIRValue]:
|
578
|
+
"""Get value used."""
|
579
|
+
return [self.value]
|
580
|
+
|
581
|
+
def get_defs(self) -> list[MIRValue]:
|
582
|
+
"""Print defines nothing."""
|
583
|
+
return []
|
584
|
+
|
585
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
586
|
+
"""Replace uses of a value."""
|
587
|
+
if self.value == old_value:
|
588
|
+
self.value = new_value
|
589
|
+
|
590
|
+
|
591
|
+
class Nop(MIRInstruction):
|
592
|
+
"""No-operation instruction."""
|
593
|
+
|
594
|
+
def __str__(self) -> str:
|
595
|
+
"""Return string representation."""
|
596
|
+
return "nop"
|
597
|
+
|
598
|
+
def get_uses(self) -> list[MIRValue]:
|
599
|
+
"""Nop uses nothing."""
|
600
|
+
return []
|
601
|
+
|
602
|
+
def get_defs(self) -> list[MIRValue]:
|
603
|
+
"""Nop defines nothing."""
|
604
|
+
return []
|
605
|
+
|
606
|
+
|
607
|
+
class Assert(MIRInstruction):
|
608
|
+
"""Assert instruction for runtime checks: assert condition."""
|
609
|
+
|
610
|
+
def __init__(self, condition: MIRValue, source_location: tuple[int, int], message: str | None = None) -> None:
|
611
|
+
"""Initialize an assert instruction.
|
612
|
+
|
613
|
+
Args:
|
614
|
+
condition: Condition to check.
|
615
|
+
source_location: Source code location (line, column).
|
616
|
+
message: Optional error message.
|
617
|
+
"""
|
618
|
+
super().__init__(source_location)
|
619
|
+
self.condition = condition
|
620
|
+
self.message = message
|
621
|
+
|
622
|
+
def __str__(self) -> str:
|
623
|
+
"""Return string representation."""
|
624
|
+
if self.message:
|
625
|
+
return f'assert {self.condition}, "{self.message}"'
|
626
|
+
return f"assert {self.condition}"
|
627
|
+
|
628
|
+
def get_uses(self) -> list[MIRValue]:
|
629
|
+
"""Get condition used."""
|
630
|
+
return [self.condition]
|
631
|
+
|
632
|
+
def get_defs(self) -> list[MIRValue]:
|
633
|
+
"""Assert defines nothing."""
|
634
|
+
return []
|
635
|
+
|
636
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
637
|
+
"""Replace uses of a value."""
|
638
|
+
if self.condition == old_value:
|
639
|
+
self.condition = new_value
|
640
|
+
|
641
|
+
|
642
|
+
class Select(MIRInstruction):
|
643
|
+
"""Select instruction (ternary): dest = condition ? true_val : false_val."""
|
644
|
+
|
645
|
+
def __init__(
|
646
|
+
self,
|
647
|
+
dest: MIRValue,
|
648
|
+
condition: MIRValue,
|
649
|
+
true_val: MIRValue,
|
650
|
+
false_val: MIRValue,
|
651
|
+
source_location: tuple[int, int],
|
652
|
+
) -> None:
|
653
|
+
"""Initialize a select instruction.
|
654
|
+
|
655
|
+
Args:
|
656
|
+
dest: Destination to store result.
|
657
|
+
condition: Condition to test.
|
658
|
+
true_val: Value when condition is true.
|
659
|
+
false_val: Value when condition is false.
|
660
|
+
source_location: Source code location (line, column).
|
661
|
+
"""
|
662
|
+
super().__init__(source_location)
|
663
|
+
self.dest = dest
|
664
|
+
self.condition = condition
|
665
|
+
self.true_val = true_val
|
666
|
+
self.false_val = false_val
|
667
|
+
|
668
|
+
def __str__(self) -> str:
|
669
|
+
"""Return string representation."""
|
670
|
+
return f"{self.dest} = select {self.condition}, {self.true_val}, {self.false_val}"
|
671
|
+
|
672
|
+
def get_uses(self) -> list[MIRValue]:
|
673
|
+
"""Get values used."""
|
674
|
+
return [self.condition, self.true_val, self.false_val]
|
675
|
+
|
676
|
+
def get_defs(self) -> list[MIRValue]:
|
677
|
+
"""Get destination defined."""
|
678
|
+
return [self.dest]
|
679
|
+
|
680
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
681
|
+
"""Replace uses of a value."""
|
682
|
+
if self.condition == old_value:
|
683
|
+
self.condition = new_value
|
684
|
+
if self.true_val == old_value:
|
685
|
+
self.true_val = new_value
|
686
|
+
if self.false_val == old_value:
|
687
|
+
self.false_val = new_value
|
688
|
+
|
689
|
+
|
690
|
+
class Scope(MIRInstruction):
|
691
|
+
"""Scope instruction for block management: begin_scope/end_scope."""
|
692
|
+
|
693
|
+
def __init__(self, source_location: tuple[int, int], is_begin: bool = True) -> None:
|
694
|
+
"""Initialize a scope instruction.
|
695
|
+
|
696
|
+
Args:
|
697
|
+
source_location: Source code location (line, column).
|
698
|
+
is_begin: True for begin_scope, False for end_scope.
|
699
|
+
"""
|
700
|
+
super().__init__(source_location)
|
701
|
+
self.is_begin = is_begin
|
702
|
+
|
703
|
+
def __str__(self) -> str:
|
704
|
+
"""Return string representation."""
|
705
|
+
return "begin_scope" if self.is_begin else "end_scope"
|
706
|
+
|
707
|
+
def get_uses(self) -> list[MIRValue]:
|
708
|
+
"""Scope uses nothing."""
|
709
|
+
return []
|
710
|
+
|
711
|
+
def get_defs(self) -> list[MIRValue]:
|
712
|
+
"""Scope defines nothing."""
|
713
|
+
return []
|
714
|
+
|
715
|
+
|
716
|
+
class GetAttr(MIRInstruction):
|
717
|
+
"""Get attribute instruction: dest = object.attr."""
|
718
|
+
|
719
|
+
def __init__(self, dest: MIRValue, obj: MIRValue, attr: str) -> None:
|
720
|
+
"""Initialize a get attribute instruction.
|
721
|
+
|
722
|
+
Args:
|
723
|
+
dest: Destination to store attribute value.
|
724
|
+
obj: Object to get attribute from.
|
725
|
+
attr: Attribute name.
|
726
|
+
"""
|
727
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
728
|
+
self.dest = dest
|
729
|
+
self.obj = obj
|
730
|
+
self.attr = attr
|
731
|
+
|
732
|
+
def __str__(self) -> str:
|
733
|
+
"""Return string representation."""
|
734
|
+
return f"{self.dest} = {self.obj}.{self.attr}"
|
735
|
+
|
736
|
+
def get_uses(self) -> list[MIRValue]:
|
737
|
+
"""Get object used."""
|
738
|
+
return [self.obj]
|
739
|
+
|
740
|
+
def get_defs(self) -> list[MIRValue]:
|
741
|
+
"""Get destination defined."""
|
742
|
+
return [self.dest]
|
743
|
+
|
744
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
745
|
+
"""Replace uses of a value."""
|
746
|
+
if self.obj == old_value:
|
747
|
+
self.obj = new_value
|
748
|
+
|
749
|
+
|
750
|
+
class SetAttr(MIRInstruction):
|
751
|
+
"""Set attribute instruction: object.attr = value."""
|
752
|
+
|
753
|
+
def __init__(self, obj: MIRValue, attr: str, value: MIRValue) -> None:
|
754
|
+
"""Initialize a set attribute instruction.
|
755
|
+
|
756
|
+
Args:
|
757
|
+
obj: Object to set attribute on.
|
758
|
+
attr: Attribute name.
|
759
|
+
value: Value to set.
|
760
|
+
"""
|
761
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
762
|
+
self.obj = obj
|
763
|
+
self.attr = attr
|
764
|
+
self.value = value
|
765
|
+
|
766
|
+
def __str__(self) -> str:
|
767
|
+
"""Return string representation."""
|
768
|
+
return f"{self.obj}.{self.attr} = {self.value}"
|
769
|
+
|
770
|
+
def get_uses(self) -> list[MIRValue]:
|
771
|
+
"""Get object and value used."""
|
772
|
+
return [self.obj, self.value]
|
773
|
+
|
774
|
+
def get_defs(self) -> list[MIRValue]:
|
775
|
+
"""SetAttr defines nothing directly."""
|
776
|
+
return []
|
777
|
+
|
778
|
+
def replace_use(self, old_value: MIRValue, new_value: MIRValue) -> None:
|
779
|
+
"""Replace uses of a value."""
|
780
|
+
if self.obj == old_value:
|
781
|
+
self.obj = new_value
|
782
|
+
if self.value == old_value:
|
783
|
+
self.value = new_value
|
784
|
+
|
785
|
+
|
786
|
+
class Pop(MIRInstruction):
|
787
|
+
"""Pop instruction to discard a value from the stack.
|
788
|
+
|
789
|
+
This instruction is used when an expression result is not needed,
|
790
|
+
such as in expression statements where the value is computed but
|
791
|
+
then discarded.
|
792
|
+
"""
|
793
|
+
|
794
|
+
def __init__(self, value: MIRValue, source_location: tuple[int, int]) -> None:
|
795
|
+
"""Initialize a pop instruction.
|
796
|
+
|
797
|
+
Args:
|
798
|
+
value: The value to pop/discard.
|
799
|
+
source_location: Source code location (line, column).
|
800
|
+
"""
|
801
|
+
super().__init__(source_location)
|
802
|
+
self.value = value
|
803
|
+
|
804
|
+
def __str__(self) -> str:
|
805
|
+
"""Return string representation."""
|
806
|
+
return f"pop {self.value}"
|
807
|
+
|
808
|
+
def get_uses(self) -> list[MIRValue]:
|
809
|
+
"""Get values used by this instruction."""
|
810
|
+
return [self.value]
|
811
|
+
|
812
|
+
def get_defs(self) -> list[MIRValue]:
|
813
|
+
"""Get values defined by this instruction."""
|
814
|
+
return [] # Pop doesn't define any values
|
815
|
+
|
816
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
817
|
+
"""Replace a used value."""
|
818
|
+
if self.value == old:
|
819
|
+
self.value = new
|
820
|
+
|
821
|
+
|
822
|
+
class TypeCast(MIRInstruction):
|
823
|
+
"""Type cast instruction: dest = cast(value, target_type).
|
824
|
+
|
825
|
+
Explicit type conversion between compatible types.
|
826
|
+
"""
|
827
|
+
|
828
|
+
def __init__(self, dest: MIRValue, value: MIRValue, target_type: MIRType | MIRUnionType) -> None:
|
829
|
+
"""Initialize a type cast instruction.
|
830
|
+
|
831
|
+
Args:
|
832
|
+
dest: Destination to store cast result.
|
833
|
+
value: Value to cast.
|
834
|
+
target_type: Target type to cast to.
|
835
|
+
"""
|
836
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
837
|
+
self.dest = dest
|
838
|
+
self.value = value
|
839
|
+
self.target_type = target_type
|
840
|
+
|
841
|
+
def __str__(self) -> str:
|
842
|
+
"""Return string representation."""
|
843
|
+
return f"{self.dest} = cast({self.value}, {self.target_type})"
|
844
|
+
|
845
|
+
def get_uses(self) -> list[MIRValue]:
|
846
|
+
"""Get value used."""
|
847
|
+
return [self.value]
|
848
|
+
|
849
|
+
def get_defs(self) -> list[MIRValue]:
|
850
|
+
"""Get destination defined."""
|
851
|
+
return [self.dest]
|
852
|
+
|
853
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
854
|
+
"""Replace uses of a value."""
|
855
|
+
if self.value == old:
|
856
|
+
self.value = new
|
857
|
+
|
858
|
+
|
859
|
+
class TypeCheck(MIRInstruction):
|
860
|
+
"""Type check instruction: dest = is_type(value, type).
|
861
|
+
|
862
|
+
Runtime type checking for union types or dynamic typing.
|
863
|
+
"""
|
864
|
+
|
865
|
+
def __init__(self, dest: MIRValue, value: MIRValue, check_type: MIRType | MIRUnionType) -> None:
|
866
|
+
"""Initialize a type check instruction.
|
867
|
+
|
868
|
+
Args:
|
869
|
+
dest: Destination to store boolean result.
|
870
|
+
value: Value to check type of.
|
871
|
+
check_type: Type to check against.
|
872
|
+
"""
|
873
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
874
|
+
self.dest = dest
|
875
|
+
self.value = value
|
876
|
+
self.check_type = check_type
|
877
|
+
|
878
|
+
def __str__(self) -> str:
|
879
|
+
"""Return string representation."""
|
880
|
+
return f"{self.dest} = is_type({self.value}, {self.check_type})"
|
881
|
+
|
882
|
+
def get_uses(self) -> list[MIRValue]:
|
883
|
+
"""Get value used."""
|
884
|
+
return [self.value]
|
885
|
+
|
886
|
+
def get_defs(self) -> list[MIRValue]:
|
887
|
+
"""Get destination defined."""
|
888
|
+
return [self.dest]
|
889
|
+
|
890
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
891
|
+
"""Replace uses of a value."""
|
892
|
+
if self.value == old:
|
893
|
+
self.value = new
|
894
|
+
|
895
|
+
|
896
|
+
class TypeAssert(MIRInstruction):
|
897
|
+
"""Type assertion instruction: assert_type(value, type).
|
898
|
+
|
899
|
+
Assert that a value has a specific type at runtime.
|
900
|
+
Throws error if type mismatch.
|
901
|
+
"""
|
902
|
+
|
903
|
+
def __init__(self, value: MIRValue, assert_type: MIRType | MIRUnionType) -> None:
|
904
|
+
"""Initialize a type assertion instruction.
|
905
|
+
|
906
|
+
Args:
|
907
|
+
value: Value to assert type of.
|
908
|
+
assert_type: Expected type.
|
909
|
+
"""
|
910
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
911
|
+
self.value = value
|
912
|
+
self.assert_type = assert_type
|
913
|
+
|
914
|
+
def __str__(self) -> str:
|
915
|
+
"""Return string representation."""
|
916
|
+
return f"assert_type({self.value}, {self.assert_type})"
|
917
|
+
|
918
|
+
def get_uses(self) -> list[MIRValue]:
|
919
|
+
"""Get value used."""
|
920
|
+
return [self.value]
|
921
|
+
|
922
|
+
def get_defs(self) -> list[MIRValue]:
|
923
|
+
"""No values defined."""
|
924
|
+
return []
|
925
|
+
|
926
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
927
|
+
"""Replace uses of a value."""
|
928
|
+
if self.value == old:
|
929
|
+
self.value = new
|
930
|
+
|
931
|
+
|
932
|
+
class NarrowType(MIRInstruction):
|
933
|
+
"""Type narrowing instruction: dest = narrow(value, type).
|
934
|
+
|
935
|
+
Used after type checks to narrow union types to specific types.
|
936
|
+
This is a compile-time hint for optimization, not a runtime operation.
|
937
|
+
"""
|
938
|
+
|
939
|
+
def __init__(self, dest: MIRValue, value: MIRValue, narrow_type: MIRType) -> None:
|
940
|
+
"""Initialize a type narrowing instruction.
|
941
|
+
|
942
|
+
Args:
|
943
|
+
dest: Destination with narrowed type.
|
944
|
+
value: Value to narrow.
|
945
|
+
narrow_type: The specific type to narrow to.
|
946
|
+
"""
|
947
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
948
|
+
self.dest = dest
|
949
|
+
self.value = value
|
950
|
+
self.narrow_type = narrow_type
|
951
|
+
self.is_pure = True
|
952
|
+
self.cost = 0 # Compile-time only
|
953
|
+
|
954
|
+
def __str__(self) -> str:
|
955
|
+
"""Return string representation."""
|
956
|
+
return f"{self.dest} = narrow({self.value}, {self.narrow_type})"
|
957
|
+
|
958
|
+
def get_uses(self) -> list[MIRValue]:
|
959
|
+
"""Get value used."""
|
960
|
+
return [self.value]
|
961
|
+
|
962
|
+
def get_defs(self) -> list[MIRValue]:
|
963
|
+
"""Get destination defined."""
|
964
|
+
return [self.dest]
|
965
|
+
|
966
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
967
|
+
"""Replace uses of a value."""
|
968
|
+
if self.value == old:
|
969
|
+
self.value = new
|
970
|
+
|
971
|
+
|
972
|
+
# New specialized instructions for better optimization
|
973
|
+
|
974
|
+
|
975
|
+
class SelectOp(MIRInstruction):
|
976
|
+
"""Conditional select without branches: dest = cond ? true_val : false_val."""
|
977
|
+
|
978
|
+
def __init__(self, dest: MIRValue, cond: MIRValue, true_val: MIRValue, false_val: MIRValue) -> None:
|
979
|
+
"""Initialize a select operation.
|
980
|
+
|
981
|
+
Args:
|
982
|
+
dest: Destination to store result.
|
983
|
+
cond: Condition to test.
|
984
|
+
true_val: Value if condition is true.
|
985
|
+
false_val: Value if condition is false.
|
986
|
+
"""
|
987
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
988
|
+
self.dest = dest
|
989
|
+
self.cond = cond
|
990
|
+
self.true_val = true_val
|
991
|
+
self.false_val = false_val
|
992
|
+
self.is_pure = True
|
993
|
+
self.cost = 1 # Branchless on modern CPUs
|
994
|
+
|
995
|
+
def __str__(self) -> str:
|
996
|
+
"""Return string representation."""
|
997
|
+
return f"{self.dest} = select({self.cond}, {self.true_val}, {self.false_val})"
|
998
|
+
|
999
|
+
def get_uses(self) -> list[MIRValue]:
|
1000
|
+
"""Get values used."""
|
1001
|
+
return [self.cond, self.true_val, self.false_val]
|
1002
|
+
|
1003
|
+
def get_defs(self) -> list[MIRValue]:
|
1004
|
+
"""Get destination defined."""
|
1005
|
+
return [self.dest]
|
1006
|
+
|
1007
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1008
|
+
"""Replace uses of a value."""
|
1009
|
+
if self.cond == old:
|
1010
|
+
self.cond = new
|
1011
|
+
if self.true_val == old:
|
1012
|
+
self.true_val = new
|
1013
|
+
if self.false_val == old:
|
1014
|
+
self.false_val = new
|
1015
|
+
|
1016
|
+
|
1017
|
+
class MinOp(MIRInstruction):
|
1018
|
+
"""Minimum operation: dest = min(left, right)."""
|
1019
|
+
|
1020
|
+
def __init__(self, dest: MIRValue, left: MIRValue, right: MIRValue) -> None:
|
1021
|
+
"""Initialize a min operation.
|
1022
|
+
|
1023
|
+
Args:
|
1024
|
+
dest: Destination to store result.
|
1025
|
+
left: Left operand.
|
1026
|
+
right: Right operand.
|
1027
|
+
"""
|
1028
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
1029
|
+
self.dest = dest
|
1030
|
+
self.left = left
|
1031
|
+
self.right = right
|
1032
|
+
self.is_pure = True
|
1033
|
+
self.is_commutative = True
|
1034
|
+
self.cost = 1
|
1035
|
+
|
1036
|
+
def __str__(self) -> str:
|
1037
|
+
"""Return string representation."""
|
1038
|
+
return f"{self.dest} = min({self.left}, {self.right})"
|
1039
|
+
|
1040
|
+
def get_uses(self) -> list[MIRValue]:
|
1041
|
+
"""Get operands used."""
|
1042
|
+
return [self.left, self.right]
|
1043
|
+
|
1044
|
+
def get_defs(self) -> list[MIRValue]:
|
1045
|
+
"""Get destination defined."""
|
1046
|
+
return [self.dest]
|
1047
|
+
|
1048
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1049
|
+
"""Replace uses of a value."""
|
1050
|
+
if self.left == old:
|
1051
|
+
self.left = new
|
1052
|
+
if self.right == old:
|
1053
|
+
self.right = new
|
1054
|
+
|
1055
|
+
|
1056
|
+
class MaxOp(MIRInstruction):
|
1057
|
+
"""Maximum operation: dest = max(left, right)."""
|
1058
|
+
|
1059
|
+
def __init__(self, dest: MIRValue, left: MIRValue, right: MIRValue) -> None:
|
1060
|
+
"""Initialize a max operation.
|
1061
|
+
|
1062
|
+
Args:
|
1063
|
+
dest: Destination to store result.
|
1064
|
+
left: Left operand.
|
1065
|
+
right: Right operand.
|
1066
|
+
"""
|
1067
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
1068
|
+
self.dest = dest
|
1069
|
+
self.left = left
|
1070
|
+
self.right = right
|
1071
|
+
self.is_pure = True
|
1072
|
+
self.is_commutative = True
|
1073
|
+
self.cost = 1
|
1074
|
+
|
1075
|
+
def __str__(self) -> str:
|
1076
|
+
"""Return string representation."""
|
1077
|
+
return f"{self.dest} = max({self.left}, {self.right})"
|
1078
|
+
|
1079
|
+
def get_uses(self) -> list[MIRValue]:
|
1080
|
+
"""Get operands used."""
|
1081
|
+
return [self.left, self.right]
|
1082
|
+
|
1083
|
+
def get_defs(self) -> list[MIRValue]:
|
1084
|
+
"""Get destination defined."""
|
1085
|
+
return [self.dest]
|
1086
|
+
|
1087
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1088
|
+
"""Replace uses of a value."""
|
1089
|
+
if self.left == old:
|
1090
|
+
self.left = new
|
1091
|
+
if self.right == old:
|
1092
|
+
self.right = new
|
1093
|
+
|
1094
|
+
|
1095
|
+
class SaturatingAddOp(MIRInstruction):
|
1096
|
+
"""Saturating addition: dest = saturating_add(left, right, min, max)."""
|
1097
|
+
|
1098
|
+
def __init__(
|
1099
|
+
self,
|
1100
|
+
dest: MIRValue,
|
1101
|
+
left: MIRValue,
|
1102
|
+
right: MIRValue,
|
1103
|
+
min_val: MIRValue | None = None,
|
1104
|
+
max_val: MIRValue | None = None,
|
1105
|
+
) -> None:
|
1106
|
+
"""Initialize a saturating add operation.
|
1107
|
+
|
1108
|
+
Args:
|
1109
|
+
dest: Destination to store result.
|
1110
|
+
left: Left operand.
|
1111
|
+
right: Right operand.
|
1112
|
+
min_val: Minimum value (saturates to this).
|
1113
|
+
max_val: Maximum value (saturates to this).
|
1114
|
+
"""
|
1115
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
1116
|
+
self.dest = dest
|
1117
|
+
self.left = left
|
1118
|
+
self.right = right
|
1119
|
+
self.min_val = min_val
|
1120
|
+
self.max_val = max_val
|
1121
|
+
self.is_pure = True
|
1122
|
+
self.is_commutative = True
|
1123
|
+
self.cost = 2
|
1124
|
+
|
1125
|
+
def __str__(self) -> str:
|
1126
|
+
"""Return string representation."""
|
1127
|
+
return f"{self.dest} = saturating_add({self.left}, {self.right})"
|
1128
|
+
|
1129
|
+
def get_uses(self) -> list[MIRValue]:
|
1130
|
+
"""Get operands used."""
|
1131
|
+
uses = [self.left, self.right]
|
1132
|
+
if self.min_val:
|
1133
|
+
uses.append(self.min_val)
|
1134
|
+
if self.max_val:
|
1135
|
+
uses.append(self.max_val)
|
1136
|
+
return uses
|
1137
|
+
|
1138
|
+
def get_defs(self) -> list[MIRValue]:
|
1139
|
+
"""Get destination defined."""
|
1140
|
+
return [self.dest]
|
1141
|
+
|
1142
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1143
|
+
"""Replace uses of a value."""
|
1144
|
+
if self.left == old:
|
1145
|
+
self.left = new
|
1146
|
+
if self.right == old:
|
1147
|
+
self.right = new
|
1148
|
+
if self.min_val == old:
|
1149
|
+
self.min_val = new
|
1150
|
+
if self.max_val == old:
|
1151
|
+
self.max_val = new
|
1152
|
+
|
1153
|
+
|
1154
|
+
class PopCountOp(MIRInstruction):
|
1155
|
+
"""Population count (count set bits): dest = popcount(value)."""
|
1156
|
+
|
1157
|
+
def __init__(self, dest: MIRValue, value: MIRValue) -> None:
|
1158
|
+
"""Initialize a popcount operation.
|
1159
|
+
|
1160
|
+
Args:
|
1161
|
+
dest: Destination to store result.
|
1162
|
+
value: Value to count bits in.
|
1163
|
+
"""
|
1164
|
+
super().__init__((0, 0)) # TODO: Add proper source_location
|
1165
|
+
self.dest = dest
|
1166
|
+
self.value = value
|
1167
|
+
self.is_pure = True
|
1168
|
+
self.cost = 1 # Hardware instruction on modern CPUs
|
1169
|
+
|
1170
|
+
def __str__(self) -> str:
|
1171
|
+
"""Return string representation."""
|
1172
|
+
return f"{self.dest} = popcount({self.value})"
|
1173
|
+
|
1174
|
+
def get_uses(self) -> list[MIRValue]:
|
1175
|
+
"""Get value used."""
|
1176
|
+
return [self.value]
|
1177
|
+
|
1178
|
+
def get_defs(self) -> list[MIRValue]:
|
1179
|
+
"""Get destination defined."""
|
1180
|
+
return [self.dest]
|
1181
|
+
|
1182
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1183
|
+
"""Replace uses of a value."""
|
1184
|
+
if self.value == old:
|
1185
|
+
self.value = new
|
1186
|
+
|
1187
|
+
|
1188
|
+
# Array/List operations
|
1189
|
+
class ArrayCreate(MIRInstruction):
|
1190
|
+
"""Create a new array: dest = new_array(size)."""
|
1191
|
+
|
1192
|
+
def __init__(self, dest: MIRValue, size: MIRValue, source_location: tuple[int, int]) -> None:
|
1193
|
+
"""Initialize array creation.
|
1194
|
+
|
1195
|
+
Args:
|
1196
|
+
dest: Destination to store array reference.
|
1197
|
+
size: Initial size of the array.
|
1198
|
+
source_location: Source location in original code.
|
1199
|
+
"""
|
1200
|
+
super().__init__(source_location)
|
1201
|
+
self.dest = dest
|
1202
|
+
self.size = size
|
1203
|
+
self.cost = 2
|
1204
|
+
|
1205
|
+
def __str__(self) -> str:
|
1206
|
+
"""Return string representation."""
|
1207
|
+
return f"{self.dest} = new_array({self.size})"
|
1208
|
+
|
1209
|
+
def get_uses(self) -> list[MIRValue]:
|
1210
|
+
"""Get size value used."""
|
1211
|
+
return [self.size]
|
1212
|
+
|
1213
|
+
def get_defs(self) -> list[MIRValue]:
|
1214
|
+
"""Get destination defined."""
|
1215
|
+
return [self.dest]
|
1216
|
+
|
1217
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1218
|
+
"""Replace uses of a value."""
|
1219
|
+
if self.size == old:
|
1220
|
+
self.size = new
|
1221
|
+
|
1222
|
+
|
1223
|
+
class ArrayGet(MIRInstruction):
|
1224
|
+
"""Get array element: dest = array[index]."""
|
1225
|
+
|
1226
|
+
def __init__(
|
1227
|
+
self,
|
1228
|
+
dest: MIRValue,
|
1229
|
+
array: MIRValue,
|
1230
|
+
index: MIRValue,
|
1231
|
+
source_location: tuple[int, int],
|
1232
|
+
) -> None:
|
1233
|
+
"""Initialize array get operation.
|
1234
|
+
|
1235
|
+
Args:
|
1236
|
+
dest: Destination to store the value.
|
1237
|
+
array: Array to get from.
|
1238
|
+
index: Index to access.
|
1239
|
+
source_location: Source location in original code.
|
1240
|
+
"""
|
1241
|
+
super().__init__(source_location)
|
1242
|
+
self.dest = dest
|
1243
|
+
self.array = array
|
1244
|
+
self.index = index
|
1245
|
+
self.is_pure = True
|
1246
|
+
self.cost = 1
|
1247
|
+
|
1248
|
+
def __str__(self) -> str:
|
1249
|
+
"""Return string representation."""
|
1250
|
+
return f"{self.dest} = {self.array}[{self.index}]"
|
1251
|
+
|
1252
|
+
def get_uses(self) -> list[MIRValue]:
|
1253
|
+
"""Get operands used."""
|
1254
|
+
return [self.array, self.index]
|
1255
|
+
|
1256
|
+
def get_defs(self) -> list[MIRValue]:
|
1257
|
+
"""Get destination defined."""
|
1258
|
+
return [self.dest]
|
1259
|
+
|
1260
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1261
|
+
"""Replace uses of a value."""
|
1262
|
+
if self.array == old:
|
1263
|
+
self.array = new
|
1264
|
+
if self.index == old:
|
1265
|
+
self.index = new
|
1266
|
+
|
1267
|
+
|
1268
|
+
class ArraySet(MIRInstruction):
|
1269
|
+
"""Set array element: array[index] = value."""
|
1270
|
+
|
1271
|
+
def __init__(
|
1272
|
+
self,
|
1273
|
+
array: MIRValue,
|
1274
|
+
index: MIRValue,
|
1275
|
+
value: MIRValue,
|
1276
|
+
source_location: tuple[int, int],
|
1277
|
+
) -> None:
|
1278
|
+
"""Initialize array set operation.
|
1279
|
+
|
1280
|
+
Args:
|
1281
|
+
array: Array to modify.
|
1282
|
+
index: Index to set.
|
1283
|
+
value: Value to store.
|
1284
|
+
source_location: Source location in original code.
|
1285
|
+
"""
|
1286
|
+
super().__init__(source_location)
|
1287
|
+
self.array = array
|
1288
|
+
self.index = index
|
1289
|
+
self.value = value
|
1290
|
+
self.has_side_effects = True
|
1291
|
+
self.cost = 1
|
1292
|
+
|
1293
|
+
def __str__(self) -> str:
|
1294
|
+
"""Return string representation."""
|
1295
|
+
return f"{self.array}[{self.index}] = {self.value}"
|
1296
|
+
|
1297
|
+
def get_uses(self) -> list[MIRValue]:
|
1298
|
+
"""Get operands used."""
|
1299
|
+
return [self.array, self.index, self.value]
|
1300
|
+
|
1301
|
+
def get_defs(self) -> list[MIRValue]:
|
1302
|
+
"""No direct defs, modifies array in place."""
|
1303
|
+
return []
|
1304
|
+
|
1305
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1306
|
+
"""Replace uses of a value."""
|
1307
|
+
if self.array == old:
|
1308
|
+
self.array = new
|
1309
|
+
if self.index == old:
|
1310
|
+
self.index = new
|
1311
|
+
if self.value == old:
|
1312
|
+
self.value = new
|
1313
|
+
|
1314
|
+
|
1315
|
+
class ArrayLength(MIRInstruction):
|
1316
|
+
"""Get array length: dest = len(array)."""
|
1317
|
+
|
1318
|
+
def __init__(self, dest: MIRValue, array: MIRValue, source_location: tuple[int, int]) -> None:
|
1319
|
+
"""Initialize array length operation.
|
1320
|
+
|
1321
|
+
Args:
|
1322
|
+
dest: Destination to store length.
|
1323
|
+
array: Array to get length of.
|
1324
|
+
source_location: Source location in original code.
|
1325
|
+
"""
|
1326
|
+
super().__init__(source_location)
|
1327
|
+
self.dest = dest
|
1328
|
+
self.array = array
|
1329
|
+
self.is_pure = True
|
1330
|
+
self.cost = 1
|
1331
|
+
|
1332
|
+
def __str__(self) -> str:
|
1333
|
+
"""Return string representation."""
|
1334
|
+
return f"{self.dest} = len({self.array})"
|
1335
|
+
|
1336
|
+
def get_uses(self) -> list[MIRValue]:
|
1337
|
+
"""Get array used."""
|
1338
|
+
return [self.array]
|
1339
|
+
|
1340
|
+
def get_defs(self) -> list[MIRValue]:
|
1341
|
+
"""Get destination defined."""
|
1342
|
+
return [self.dest]
|
1343
|
+
|
1344
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1345
|
+
"""Replace uses of a value."""
|
1346
|
+
if self.array == old:
|
1347
|
+
self.array = new
|
1348
|
+
|
1349
|
+
|
1350
|
+
class ArrayAppend(MIRInstruction):
|
1351
|
+
"""Append to array: array.append(value)."""
|
1352
|
+
|
1353
|
+
def __init__(
|
1354
|
+
self,
|
1355
|
+
array: MIRValue,
|
1356
|
+
value: MIRValue,
|
1357
|
+
source_location: tuple[int, int],
|
1358
|
+
) -> None:
|
1359
|
+
"""Initialize array append operation.
|
1360
|
+
|
1361
|
+
Args:
|
1362
|
+
array: Array to append to.
|
1363
|
+
value: Value to append.
|
1364
|
+
source_location: Source location in original code.
|
1365
|
+
"""
|
1366
|
+
super().__init__(source_location)
|
1367
|
+
self.array = array
|
1368
|
+
self.value = value
|
1369
|
+
self.has_side_effects = True
|
1370
|
+
self.cost = 2
|
1371
|
+
|
1372
|
+
def __str__(self) -> str:
|
1373
|
+
"""Return string representation."""
|
1374
|
+
return f"{self.array}.append({self.value})"
|
1375
|
+
|
1376
|
+
def get_uses(self) -> list[MIRValue]:
|
1377
|
+
"""Get operands used."""
|
1378
|
+
return [self.array, self.value]
|
1379
|
+
|
1380
|
+
def get_defs(self) -> list[MIRValue]:
|
1381
|
+
"""No direct defs, modifies array in place."""
|
1382
|
+
return []
|
1383
|
+
|
1384
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1385
|
+
"""Replace uses of a value."""
|
1386
|
+
if self.array == old:
|
1387
|
+
self.array = new
|
1388
|
+
if self.value == old:
|
1389
|
+
self.value = new
|
1390
|
+
|
1391
|
+
|
1392
|
+
class ArrayRemove(MIRInstruction):
|
1393
|
+
"""Remove element from array at index: array.remove(index)."""
|
1394
|
+
|
1395
|
+
def __init__(
|
1396
|
+
self,
|
1397
|
+
array: MIRValue,
|
1398
|
+
index: MIRValue,
|
1399
|
+
source_location: tuple[int, int],
|
1400
|
+
) -> None:
|
1401
|
+
"""Initialize array remove operation.
|
1402
|
+
|
1403
|
+
Args:
|
1404
|
+
array: The array to remove from.
|
1405
|
+
index: The index to remove at.
|
1406
|
+
source_location: Source code location (line, column).
|
1407
|
+
"""
|
1408
|
+
super().__init__(source_location)
|
1409
|
+
self.array = array
|
1410
|
+
self.index = index
|
1411
|
+
|
1412
|
+
def __str__(self) -> str:
|
1413
|
+
"""Return string representation."""
|
1414
|
+
return f"{self.array}.remove({self.index})"
|
1415
|
+
|
1416
|
+
def get_uses(self) -> list[MIRValue]:
|
1417
|
+
"""Get operands used."""
|
1418
|
+
return [self.array, self.index]
|
1419
|
+
|
1420
|
+
def get_defs(self) -> list[MIRValue]:
|
1421
|
+
"""No direct defs, modifies array in place."""
|
1422
|
+
return []
|
1423
|
+
|
1424
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1425
|
+
"""Replace uses of a value."""
|
1426
|
+
if self.array == old:
|
1427
|
+
self.array = new
|
1428
|
+
if self.index == old:
|
1429
|
+
self.index = new
|
1430
|
+
|
1431
|
+
|
1432
|
+
class ArrayInsert(MIRInstruction):
|
1433
|
+
"""Insert element into array at index: array.insert(index, value)."""
|
1434
|
+
|
1435
|
+
def __init__(
|
1436
|
+
self,
|
1437
|
+
array: MIRValue,
|
1438
|
+
index: MIRValue,
|
1439
|
+
value: MIRValue,
|
1440
|
+
source_location: tuple[int, int],
|
1441
|
+
) -> None:
|
1442
|
+
"""Initialize array insert operation.
|
1443
|
+
|
1444
|
+
Args:
|
1445
|
+
array: The array to insert into.
|
1446
|
+
index: The index to insert at.
|
1447
|
+
value: The value to insert.
|
1448
|
+
source_location: Source code location (line, column).
|
1449
|
+
"""
|
1450
|
+
super().__init__(source_location)
|
1451
|
+
self.array = array
|
1452
|
+
self.index = index
|
1453
|
+
self.value = value
|
1454
|
+
|
1455
|
+
def __str__(self) -> str:
|
1456
|
+
"""Return string representation."""
|
1457
|
+
return f"{self.array}.insert({self.index}, {self.value})"
|
1458
|
+
|
1459
|
+
def get_uses(self) -> list[MIRValue]:
|
1460
|
+
"""Get operands used."""
|
1461
|
+
return [self.array, self.index, self.value]
|
1462
|
+
|
1463
|
+
def get_defs(self) -> list[MIRValue]:
|
1464
|
+
"""No direct defs, modifies array in place."""
|
1465
|
+
return []
|
1466
|
+
|
1467
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1468
|
+
"""Replace uses of a value."""
|
1469
|
+
if self.array == old:
|
1470
|
+
self.array = new
|
1471
|
+
if self.index == old:
|
1472
|
+
self.index = new
|
1473
|
+
if self.value == old:
|
1474
|
+
self.value = new
|
1475
|
+
|
1476
|
+
|
1477
|
+
class ArrayFindIndex(MIRInstruction):
|
1478
|
+
"""Find index of value in array: dest = array.index(value)."""
|
1479
|
+
|
1480
|
+
def __init__(
|
1481
|
+
self,
|
1482
|
+
dest: MIRValue,
|
1483
|
+
array: MIRValue,
|
1484
|
+
value: MIRValue,
|
1485
|
+
source_location: tuple[int, int],
|
1486
|
+
) -> None:
|
1487
|
+
"""Initialize array find index operation.
|
1488
|
+
|
1489
|
+
Args:
|
1490
|
+
dest: Destination for the index (-1 if not found).
|
1491
|
+
array: The array to search in.
|
1492
|
+
value: The value to find.
|
1493
|
+
source_location: Source code location (line, column).
|
1494
|
+
"""
|
1495
|
+
super().__init__(source_location)
|
1496
|
+
self.dest = dest
|
1497
|
+
self.array = array
|
1498
|
+
self.value = value
|
1499
|
+
|
1500
|
+
def __str__(self) -> str:
|
1501
|
+
"""Return string representation."""
|
1502
|
+
return f"{self.dest} = {self.array}.index({self.value})"
|
1503
|
+
|
1504
|
+
def get_uses(self) -> list[MIRValue]:
|
1505
|
+
"""Get operands used."""
|
1506
|
+
return [self.array, self.value]
|
1507
|
+
|
1508
|
+
def get_defs(self) -> list[MIRValue]:
|
1509
|
+
"""Get destination defined."""
|
1510
|
+
return [self.dest]
|
1511
|
+
|
1512
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1513
|
+
"""Replace uses of a value."""
|
1514
|
+
if self.array == old:
|
1515
|
+
self.array = new
|
1516
|
+
if self.value == old:
|
1517
|
+
self.value = new
|
1518
|
+
|
1519
|
+
|
1520
|
+
class ArrayClear(MIRInstruction):
|
1521
|
+
"""Clear all elements from array: array.clear()."""
|
1522
|
+
|
1523
|
+
def __init__(
|
1524
|
+
self,
|
1525
|
+
array: MIRValue,
|
1526
|
+
source_location: tuple[int, int],
|
1527
|
+
) -> None:
|
1528
|
+
"""Initialize array clear operation.
|
1529
|
+
|
1530
|
+
Args:
|
1531
|
+
array: The array to clear.
|
1532
|
+
source_location: Source code location (line, column).
|
1533
|
+
"""
|
1534
|
+
super().__init__(source_location)
|
1535
|
+
self.array = array
|
1536
|
+
|
1537
|
+
def __str__(self) -> str:
|
1538
|
+
"""Return string representation."""
|
1539
|
+
return f"{self.array}.clear()"
|
1540
|
+
|
1541
|
+
def get_uses(self) -> list[MIRValue]:
|
1542
|
+
"""Get operands used."""
|
1543
|
+
return [self.array]
|
1544
|
+
|
1545
|
+
def get_defs(self) -> list[MIRValue]:
|
1546
|
+
"""No direct defs, modifies array in place."""
|
1547
|
+
return []
|
1548
|
+
|
1549
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1550
|
+
"""Replace uses of a value."""
|
1551
|
+
if self.array == old:
|
1552
|
+
self.array = new
|
1553
|
+
|
1554
|
+
|
1555
|
+
# Dictionary Operations
|
1556
|
+
|
1557
|
+
|
1558
|
+
class DictCreate(MIRInstruction):
|
1559
|
+
"""Create a new dictionary: dest = {}."""
|
1560
|
+
|
1561
|
+
def __init__(
|
1562
|
+
self,
|
1563
|
+
dest: Temp,
|
1564
|
+
source_location: tuple[int, int],
|
1565
|
+
) -> None:
|
1566
|
+
"""Initialize dictionary creation.
|
1567
|
+
|
1568
|
+
Args:
|
1569
|
+
dest: Destination temp for the new dictionary.
|
1570
|
+
source_location: Source code location (line, column).
|
1571
|
+
"""
|
1572
|
+
super().__init__(source_location)
|
1573
|
+
self.dest = dest
|
1574
|
+
|
1575
|
+
def __str__(self) -> str:
|
1576
|
+
"""Return string representation."""
|
1577
|
+
return f"{self.dest} = {{}}"
|
1578
|
+
|
1579
|
+
def get_uses(self) -> list[MIRValue]:
|
1580
|
+
"""DictCreate uses nothing."""
|
1581
|
+
return []
|
1582
|
+
|
1583
|
+
def get_defs(self) -> list[MIRValue]:
|
1584
|
+
"""Get defined value."""
|
1585
|
+
return [self.dest]
|
1586
|
+
|
1587
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1588
|
+
"""Replace uses of a value."""
|
1589
|
+
pass # No uses to replace
|
1590
|
+
|
1591
|
+
|
1592
|
+
class DictGet(MIRInstruction):
|
1593
|
+
"""Get value from dictionary by key: dest = dict[key]."""
|
1594
|
+
|
1595
|
+
def __init__(
|
1596
|
+
self,
|
1597
|
+
dest: Temp,
|
1598
|
+
dict_val: MIRValue,
|
1599
|
+
key: MIRValue,
|
1600
|
+
source_location: tuple[int, int],
|
1601
|
+
) -> None:
|
1602
|
+
"""Initialize dictionary get operation.
|
1603
|
+
|
1604
|
+
Args:
|
1605
|
+
dest: Destination temp for the value.
|
1606
|
+
dict_val: The dictionary to get from.
|
1607
|
+
key: The key to look up.
|
1608
|
+
source_location: Source code location (line, column).
|
1609
|
+
"""
|
1610
|
+
super().__init__(source_location)
|
1611
|
+
self.dest = dest
|
1612
|
+
self.dict_val = dict_val
|
1613
|
+
self.key = key
|
1614
|
+
|
1615
|
+
def __str__(self) -> str:
|
1616
|
+
"""Return string representation."""
|
1617
|
+
return f"{self.dest} = {self.dict_val}[{self.key}]"
|
1618
|
+
|
1619
|
+
def get_uses(self) -> list[MIRValue]:
|
1620
|
+
"""Get operands used."""
|
1621
|
+
return [self.dict_val, self.key]
|
1622
|
+
|
1623
|
+
def get_defs(self) -> list[MIRValue]:
|
1624
|
+
"""Get defined value."""
|
1625
|
+
return [self.dest]
|
1626
|
+
|
1627
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1628
|
+
"""Replace uses of a value."""
|
1629
|
+
if self.dict_val == old:
|
1630
|
+
self.dict_val = new
|
1631
|
+
if self.key == old:
|
1632
|
+
self.key = new
|
1633
|
+
|
1634
|
+
|
1635
|
+
class DictSet(MIRInstruction):
|
1636
|
+
"""Set value in dictionary: dict[key] = value."""
|
1637
|
+
|
1638
|
+
def __init__(
|
1639
|
+
self,
|
1640
|
+
dict_val: MIRValue,
|
1641
|
+
key: MIRValue,
|
1642
|
+
value: MIRValue,
|
1643
|
+
source_location: tuple[int, int],
|
1644
|
+
) -> None:
|
1645
|
+
"""Initialize dictionary set operation.
|
1646
|
+
|
1647
|
+
Args:
|
1648
|
+
dict_val: The dictionary to modify.
|
1649
|
+
key: The key to set.
|
1650
|
+
value: The value to set.
|
1651
|
+
source_location: Source code location (line, column).
|
1652
|
+
"""
|
1653
|
+
super().__init__(source_location)
|
1654
|
+
self.dict_val = dict_val
|
1655
|
+
self.key = key
|
1656
|
+
self.value = value
|
1657
|
+
|
1658
|
+
def __str__(self) -> str:
|
1659
|
+
"""Return string representation."""
|
1660
|
+
return f"{self.dict_val}[{self.key}] = {self.value}"
|
1661
|
+
|
1662
|
+
def get_uses(self) -> list[MIRValue]:
|
1663
|
+
"""Get operands used."""
|
1664
|
+
return [self.dict_val, self.key, self.value]
|
1665
|
+
|
1666
|
+
def get_defs(self) -> list[MIRValue]:
|
1667
|
+
"""No direct defs, modifies dict in place."""
|
1668
|
+
return []
|
1669
|
+
|
1670
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1671
|
+
"""Replace uses of a value."""
|
1672
|
+
if self.dict_val == old:
|
1673
|
+
self.dict_val = new
|
1674
|
+
if self.key == old:
|
1675
|
+
self.key = new
|
1676
|
+
if self.value == old:
|
1677
|
+
self.value = new
|
1678
|
+
|
1679
|
+
|
1680
|
+
class DictRemove(MIRInstruction):
|
1681
|
+
"""Remove key from dictionary: del dict[key]."""
|
1682
|
+
|
1683
|
+
def __init__(
|
1684
|
+
self,
|
1685
|
+
dict_val: MIRValue,
|
1686
|
+
key: MIRValue,
|
1687
|
+
source_location: tuple[int, int],
|
1688
|
+
) -> None:
|
1689
|
+
"""Initialize dictionary remove operation.
|
1690
|
+
|
1691
|
+
Args:
|
1692
|
+
dict_val: The dictionary to modify.
|
1693
|
+
key: The key to remove.
|
1694
|
+
source_location: Source code location (line, column).
|
1695
|
+
"""
|
1696
|
+
super().__init__(source_location)
|
1697
|
+
self.dict_val = dict_val
|
1698
|
+
self.key = key
|
1699
|
+
|
1700
|
+
def __str__(self) -> str:
|
1701
|
+
"""Return string representation."""
|
1702
|
+
return f"del {self.dict_val}[{self.key}]"
|
1703
|
+
|
1704
|
+
def get_uses(self) -> list[MIRValue]:
|
1705
|
+
"""Get operands used."""
|
1706
|
+
return [self.dict_val, self.key]
|
1707
|
+
|
1708
|
+
def get_defs(self) -> list[MIRValue]:
|
1709
|
+
"""No direct defs, modifies dict in place."""
|
1710
|
+
return []
|
1711
|
+
|
1712
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1713
|
+
"""Replace uses of a value."""
|
1714
|
+
if self.dict_val == old:
|
1715
|
+
self.dict_val = new
|
1716
|
+
if self.key == old:
|
1717
|
+
self.key = new
|
1718
|
+
|
1719
|
+
|
1720
|
+
class DictKeys(MIRInstruction):
|
1721
|
+
"""Get all keys from a dictionary as an array: dest = dict.keys()."""
|
1722
|
+
|
1723
|
+
def __init__(
|
1724
|
+
self,
|
1725
|
+
dest: MIRValue,
|
1726
|
+
dict_val: MIRValue,
|
1727
|
+
source_location: tuple[int, int],
|
1728
|
+
) -> None:
|
1729
|
+
"""Initialize dictionary keys extraction.
|
1730
|
+
|
1731
|
+
Args:
|
1732
|
+
dest: Destination register for the keys array.
|
1733
|
+
dict_val: The dictionary to get keys from.
|
1734
|
+
source_location: Source code location (line, column).
|
1735
|
+
"""
|
1736
|
+
super().__init__(source_location)
|
1737
|
+
self.dest = dest
|
1738
|
+
self.dict_val = dict_val
|
1739
|
+
|
1740
|
+
def __str__(self) -> str:
|
1741
|
+
"""Return string representation."""
|
1742
|
+
return f"{self.dest} = {self.dict_val}.keys()"
|
1743
|
+
|
1744
|
+
def get_uses(self) -> list[MIRValue]:
|
1745
|
+
"""Get operands used."""
|
1746
|
+
return [self.dict_val]
|
1747
|
+
|
1748
|
+
def get_defs(self) -> list[MIRValue]:
|
1749
|
+
"""Get values defined."""
|
1750
|
+
return [self.dest]
|
1751
|
+
|
1752
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1753
|
+
"""Replace uses of a value."""
|
1754
|
+
if self.dict_val == old:
|
1755
|
+
self.dict_val = new
|
1756
|
+
if self.dest == old:
|
1757
|
+
self.dest = new
|
1758
|
+
|
1759
|
+
|
1760
|
+
class DictValues(MIRInstruction):
|
1761
|
+
"""Get all values from a dictionary as an array: dest = dict.values()."""
|
1762
|
+
|
1763
|
+
def __init__(
|
1764
|
+
self,
|
1765
|
+
dest: MIRValue,
|
1766
|
+
dict_val: MIRValue,
|
1767
|
+
source_location: tuple[int, int],
|
1768
|
+
) -> None:
|
1769
|
+
"""Initialize dictionary values extraction.
|
1770
|
+
|
1771
|
+
Args:
|
1772
|
+
dest: Destination register for the values array.
|
1773
|
+
dict_val: The dictionary to get values from.
|
1774
|
+
source_location: Source code location (line, column).
|
1775
|
+
"""
|
1776
|
+
super().__init__(source_location)
|
1777
|
+
self.dest = dest
|
1778
|
+
self.dict_val = dict_val
|
1779
|
+
|
1780
|
+
def __str__(self) -> str:
|
1781
|
+
"""Return string representation."""
|
1782
|
+
return f"{self.dest} = {self.dict_val}.values()"
|
1783
|
+
|
1784
|
+
def get_uses(self) -> list[MIRValue]:
|
1785
|
+
"""Get operands used."""
|
1786
|
+
return [self.dict_val]
|
1787
|
+
|
1788
|
+
def get_defs(self) -> list[MIRValue]:
|
1789
|
+
"""Get values defined."""
|
1790
|
+
return [self.dest]
|
1791
|
+
|
1792
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1793
|
+
"""Replace uses of a value."""
|
1794
|
+
if self.dict_val == old:
|
1795
|
+
self.dict_val = new
|
1796
|
+
if self.dest == old:
|
1797
|
+
self.dest = new
|
1798
|
+
|
1799
|
+
|
1800
|
+
class DictContains(MIRInstruction):
|
1801
|
+
"""Check if key exists in dictionary: dest = key in dict."""
|
1802
|
+
|
1803
|
+
def __init__(
|
1804
|
+
self,
|
1805
|
+
dest: Temp,
|
1806
|
+
dict_val: MIRValue,
|
1807
|
+
key: MIRValue,
|
1808
|
+
source_location: tuple[int, int],
|
1809
|
+
) -> None:
|
1810
|
+
"""Initialize dictionary contains check.
|
1811
|
+
|
1812
|
+
Args:
|
1813
|
+
dest: Destination temp for the boolean result.
|
1814
|
+
dict_val: The dictionary to check.
|
1815
|
+
key: The key to look for.
|
1816
|
+
source_location: Source code location (line, column).
|
1817
|
+
"""
|
1818
|
+
super().__init__(source_location)
|
1819
|
+
self.dest = dest
|
1820
|
+
self.dict_val = dict_val
|
1821
|
+
self.key = key
|
1822
|
+
|
1823
|
+
def __str__(self) -> str:
|
1824
|
+
"""Return string representation."""
|
1825
|
+
return f"{self.dest} = {self.key} in {self.dict_val}"
|
1826
|
+
|
1827
|
+
def get_uses(self) -> list[MIRValue]:
|
1828
|
+
"""Get operands used."""
|
1829
|
+
return [self.dict_val, self.key]
|
1830
|
+
|
1831
|
+
def get_defs(self) -> list[MIRValue]:
|
1832
|
+
"""Get defined value."""
|
1833
|
+
return [self.dest]
|
1834
|
+
|
1835
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1836
|
+
"""Replace uses of a value."""
|
1837
|
+
if self.dict_val == old:
|
1838
|
+
self.dict_val = new
|
1839
|
+
if self.key == old:
|
1840
|
+
self.key = new
|
1841
|
+
|
1842
|
+
|
1843
|
+
class DictClear(MIRInstruction):
|
1844
|
+
"""Clear all entries from dictionary: dict.clear()."""
|
1845
|
+
|
1846
|
+
def __init__(
|
1847
|
+
self,
|
1848
|
+
dict_val: MIRValue,
|
1849
|
+
source_location: tuple[int, int],
|
1850
|
+
) -> None:
|
1851
|
+
"""Initialize dictionary clear operation.
|
1852
|
+
|
1853
|
+
Args:
|
1854
|
+
dict_val: The dictionary to clear.
|
1855
|
+
source_location: Source code location (line, column).
|
1856
|
+
"""
|
1857
|
+
super().__init__(source_location)
|
1858
|
+
self.dict_val = dict_val
|
1859
|
+
self.has_side_effects = True
|
1860
|
+
self.cost = 2
|
1861
|
+
|
1862
|
+
def __str__(self) -> str:
|
1863
|
+
"""String representation for debugging."""
|
1864
|
+
return f"DictClear {self.dict_val}"
|
1865
|
+
|
1866
|
+
def get_uses(self) -> list[MIRValue]:
|
1867
|
+
"""Get operands used."""
|
1868
|
+
return [self.dict_val]
|
1869
|
+
|
1870
|
+
def get_defs(self) -> list[MIRValue]:
|
1871
|
+
"""Get defined values."""
|
1872
|
+
return [] # Modifies dict in-place
|
1873
|
+
|
1874
|
+
def replace_use(self, old: MIRValue, new: MIRValue) -> None:
|
1875
|
+
"""Replace uses of a value."""
|
1876
|
+
if self.dict_val == old:
|
1877
|
+
self.dict_val = new
|