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,268 @@
|
|
1
|
+
"""MIR Value Representations.
|
2
|
+
|
3
|
+
This module defines the various value types used in MIR instructions,
|
4
|
+
including temporaries, variables, constants, and function references.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from abc import ABC, abstractmethod
|
8
|
+
from enum import Enum
|
9
|
+
from typing import Any
|
10
|
+
|
11
|
+
from .mir_types import MIRType, MIRUnionType, infer_type
|
12
|
+
|
13
|
+
|
14
|
+
class VariableScope(Enum):
|
15
|
+
"""Scope of a variable in the program."""
|
16
|
+
|
17
|
+
GLOBAL = "global" # Module-level variables
|
18
|
+
PARAMETER = "param" # Function parameters
|
19
|
+
LOCAL = "local" # Function-local variables
|
20
|
+
|
21
|
+
|
22
|
+
class MIRValue(ABC):
|
23
|
+
"""Base class for all MIR values with rich metadata."""
|
24
|
+
|
25
|
+
def __init__(self, mir_type: MIRType | MIRUnionType) -> None:
|
26
|
+
"""Initialize a MIR value with rich metadata.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
mir_type: The type of the value (can be union type).
|
30
|
+
"""
|
31
|
+
self.type = mir_type
|
32
|
+
# Additional metadata for union types
|
33
|
+
self.union_type: MIRUnionType | None = None
|
34
|
+
if isinstance(mir_type, MIRUnionType):
|
35
|
+
self.union_type = mir_type
|
36
|
+
self.type = MIRType.UNKNOWN # Base type is unknown for unions
|
37
|
+
|
38
|
+
# Rich metadata fields
|
39
|
+
from machine_dialect.mir.dataflow import Range
|
40
|
+
|
41
|
+
self.known_range: Range | None = None # Value range for numeric types
|
42
|
+
self.is_non_null: bool = False # Guaranteed non-null/non-empty
|
43
|
+
self.is_non_zero: bool = False # Guaranteed non-zero
|
44
|
+
self.alignment: int | None = None # Memory alignment in bytes
|
45
|
+
self.provenance: str | None = None # Source of this value (e.g., "user_input", "constant")
|
46
|
+
self.is_loop_invariant: bool = False # True if value doesn't change in loops
|
47
|
+
self.is_pure: bool = True # True if computing this value has no side effects
|
48
|
+
|
49
|
+
@abstractmethod
|
50
|
+
def __str__(self) -> str:
|
51
|
+
"""Return string representation of the value."""
|
52
|
+
pass
|
53
|
+
|
54
|
+
@abstractmethod
|
55
|
+
def __eq__(self, other: object) -> bool:
|
56
|
+
"""Check equality with another value."""
|
57
|
+
pass
|
58
|
+
|
59
|
+
@abstractmethod
|
60
|
+
def __hash__(self) -> int:
|
61
|
+
"""Return hash of the value."""
|
62
|
+
pass
|
63
|
+
|
64
|
+
|
65
|
+
class Temp(MIRValue):
|
66
|
+
"""Temporary value in SSA form.
|
67
|
+
|
68
|
+
Temporaries are compiler-generated values used to hold intermediate
|
69
|
+
results in three-address code.
|
70
|
+
"""
|
71
|
+
|
72
|
+
_next_id = 0
|
73
|
+
|
74
|
+
def __init__(self, mir_type: MIRType | MIRUnionType, temp_id: int | None = None) -> None:
|
75
|
+
"""Initialize a temporary.
|
76
|
+
|
77
|
+
Args:
|
78
|
+
mir_type: The type of the temporary (can be union type).
|
79
|
+
temp_id: Optional explicit ID. If None, auto-generated.
|
80
|
+
"""
|
81
|
+
super().__init__(mir_type)
|
82
|
+
if temp_id is None:
|
83
|
+
self.id = Temp._next_id
|
84
|
+
Temp._next_id += 1
|
85
|
+
else:
|
86
|
+
self.id = temp_id
|
87
|
+
|
88
|
+
def __str__(self) -> str:
|
89
|
+
"""Return string representation (e.g., 't1')."""
|
90
|
+
return f"t{self.id}"
|
91
|
+
|
92
|
+
def __eq__(self, other: object) -> bool:
|
93
|
+
"""Check equality based on ID."""
|
94
|
+
return isinstance(other, Temp) and self.id == other.id
|
95
|
+
|
96
|
+
def __hash__(self) -> int:
|
97
|
+
"""Hash based on ID."""
|
98
|
+
return hash(("temp", self.id))
|
99
|
+
|
100
|
+
@classmethod
|
101
|
+
def reset_counter(cls) -> None:
|
102
|
+
"""Reset the temporary ID counter (useful for tests)."""
|
103
|
+
cls._next_id = 0
|
104
|
+
|
105
|
+
|
106
|
+
class Variable(MIRValue):
|
107
|
+
"""User-defined variable.
|
108
|
+
|
109
|
+
Variables represent named values from the source program.
|
110
|
+
In SSA form, these may be versioned (e.g., x_1, x_2).
|
111
|
+
"""
|
112
|
+
|
113
|
+
def __init__(self, name: str, mir_type: MIRType | MIRUnionType, version: int = 0) -> None:
|
114
|
+
"""Initialize a variable.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
name: The variable name.
|
118
|
+
mir_type: The type of the variable (can be union type).
|
119
|
+
version: SSA version number (0 for non-SSA).
|
120
|
+
"""
|
121
|
+
super().__init__(mir_type)
|
122
|
+
self.name = name
|
123
|
+
self.version = version
|
124
|
+
|
125
|
+
def __str__(self) -> str:
|
126
|
+
"""Return string representation."""
|
127
|
+
if self.version > 0:
|
128
|
+
return f"{self.name}.{self.version}"
|
129
|
+
return self.name
|
130
|
+
|
131
|
+
def __eq__(self, other: object) -> bool:
|
132
|
+
"""Check equality based on name and version."""
|
133
|
+
return isinstance(other, Variable) and self.name == other.name and self.version == other.version
|
134
|
+
|
135
|
+
def __hash__(self) -> int:
|
136
|
+
"""Hash based on name and version."""
|
137
|
+
return hash(("var", self.name, self.version))
|
138
|
+
|
139
|
+
def with_version(self, version: int) -> "Variable":
|
140
|
+
"""Create a new variable with a different version.
|
141
|
+
|
142
|
+
Args:
|
143
|
+
version: The new version number.
|
144
|
+
|
145
|
+
Returns:
|
146
|
+
A new Variable with the same name and type but different version.
|
147
|
+
"""
|
148
|
+
return Variable(self.name, self.type, version)
|
149
|
+
|
150
|
+
|
151
|
+
class ScopedVariable(Variable):
|
152
|
+
"""Variable with explicit scope information.
|
153
|
+
|
154
|
+
This extends Variable to track whether it's a global, parameter, or local variable.
|
155
|
+
"""
|
156
|
+
|
157
|
+
def __init__(
|
158
|
+
self,
|
159
|
+
name: str,
|
160
|
+
scope: VariableScope,
|
161
|
+
mir_type: MIRType | MIRUnionType,
|
162
|
+
version: int = 0,
|
163
|
+
) -> None:
|
164
|
+
"""Initialize a scoped variable.
|
165
|
+
|
166
|
+
Args:
|
167
|
+
name: The variable name.
|
168
|
+
scope: The scope of the variable.
|
169
|
+
mir_type: The type of the variable.
|
170
|
+
version: SSA version number (0 for non-SSA).
|
171
|
+
"""
|
172
|
+
super().__init__(name, mir_type, version)
|
173
|
+
self.scope = scope
|
174
|
+
|
175
|
+
def __str__(self) -> str:
|
176
|
+
"""Return string representation."""
|
177
|
+
base = super().__str__()
|
178
|
+
if self.scope == VariableScope.LOCAL:
|
179
|
+
return f"{base}[local]"
|
180
|
+
elif self.scope == VariableScope.PARAMETER:
|
181
|
+
return f"{base}[param]"
|
182
|
+
return base
|
183
|
+
|
184
|
+
def __eq__(self, other: object) -> bool:
|
185
|
+
"""Check equality based on name, version, and scope."""
|
186
|
+
if not isinstance(other, ScopedVariable):
|
187
|
+
# Allow comparison with regular Variable for compatibility
|
188
|
+
return super().__eq__(other)
|
189
|
+
return self.name == other.name and self.version == other.version and self.scope == other.scope
|
190
|
+
|
191
|
+
def __hash__(self) -> int:
|
192
|
+
"""Hash based on name, version, and scope."""
|
193
|
+
return hash(("scoped_var", self.name, self.version, self.scope))
|
194
|
+
|
195
|
+
def with_version(self, version: int) -> "ScopedVariable":
|
196
|
+
"""Create a new scoped variable with a different version.
|
197
|
+
|
198
|
+
Args:
|
199
|
+
version: The new version number.
|
200
|
+
|
201
|
+
Returns:
|
202
|
+
A new ScopedVariable with the same name, type, and scope but different version.
|
203
|
+
"""
|
204
|
+
return ScopedVariable(self.name, self.scope, self.type, version)
|
205
|
+
|
206
|
+
|
207
|
+
class Constant(MIRValue):
|
208
|
+
"""Constant value.
|
209
|
+
|
210
|
+
Constants represent literal values from the source program.
|
211
|
+
"""
|
212
|
+
|
213
|
+
def __init__(self, value: Any, mir_type: MIRType | MIRUnionType | None = None) -> None:
|
214
|
+
"""Initialize a constant.
|
215
|
+
|
216
|
+
Args:
|
217
|
+
value: The constant value.
|
218
|
+
mir_type: Optional explicit type. If None, inferred from value.
|
219
|
+
"""
|
220
|
+
if mir_type is None:
|
221
|
+
mir_type = infer_type(value)
|
222
|
+
super().__init__(mir_type)
|
223
|
+
self.value = value
|
224
|
+
|
225
|
+
def __str__(self) -> str:
|
226
|
+
"""Return string representation."""
|
227
|
+
if self.type == MIRType.STRING:
|
228
|
+
return f'"{self.value}"'
|
229
|
+
elif self.type == MIRType.EMPTY:
|
230
|
+
return "null"
|
231
|
+
else:
|
232
|
+
return str(self.value)
|
233
|
+
|
234
|
+
def __eq__(self, other: object) -> bool:
|
235
|
+
"""Check equality based on value and type."""
|
236
|
+
return isinstance(other, Constant) and self.value == other.value and self.type == other.type
|
237
|
+
|
238
|
+
def __hash__(self) -> int:
|
239
|
+
"""Hash based on value and type."""
|
240
|
+
return hash(("const", self.value, self.type))
|
241
|
+
|
242
|
+
|
243
|
+
class FunctionRef(MIRValue):
|
244
|
+
"""Function reference.
|
245
|
+
|
246
|
+
Represents a reference to a function that can be called.
|
247
|
+
"""
|
248
|
+
|
249
|
+
def __init__(self, name: str) -> None:
|
250
|
+
"""Initialize a function reference.
|
251
|
+
|
252
|
+
Args:
|
253
|
+
name: The function name.
|
254
|
+
"""
|
255
|
+
super().__init__(MIRType.FUNCTION)
|
256
|
+
self.name = name
|
257
|
+
|
258
|
+
def __str__(self) -> str:
|
259
|
+
"""Return string representation."""
|
260
|
+
return f"@{self.name}"
|
261
|
+
|
262
|
+
def __eq__(self, other: object) -> bool:
|
263
|
+
"""Check equality based on name."""
|
264
|
+
return isinstance(other, FunctionRef) and self.name == other.name
|
265
|
+
|
266
|
+
def __hash__(self) -> int:
|
267
|
+
"""Hash based on name."""
|
268
|
+
return hash(("func", self.name))
|
@@ -0,0 +1,233 @@
|
|
1
|
+
"""Optimization configuration for MIR passes.
|
2
|
+
|
3
|
+
This module defines optimization levels and pass configurations
|
4
|
+
for the MIR optimization pipeline.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from dataclasses import dataclass
|
8
|
+
from typing import TYPE_CHECKING
|
9
|
+
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
pass
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass
|
15
|
+
class OptimizationConfig:
|
16
|
+
"""Configuration for optimization passes.
|
17
|
+
|
18
|
+
Attributes:
|
19
|
+
level: Optimization level (0-3).
|
20
|
+
enable_inlining: Enable function inlining.
|
21
|
+
inline_threshold: Maximum size for inlining.
|
22
|
+
enable_loop_opts: Enable loop optimizations.
|
23
|
+
unroll_threshold: Maximum iterations for unrolling.
|
24
|
+
enable_aggressive_opts: Enable aggressive optimizations.
|
25
|
+
debug_passes: Enable debug output from passes.
|
26
|
+
pass_statistics: Collect pass statistics.
|
27
|
+
"""
|
28
|
+
|
29
|
+
level: int = 1
|
30
|
+
enable_inlining: bool = True
|
31
|
+
inline_threshold: int = 50
|
32
|
+
enable_loop_opts: bool = True
|
33
|
+
unroll_threshold: int = 4
|
34
|
+
enable_aggressive_opts: bool = False
|
35
|
+
debug_passes: bool = False
|
36
|
+
pass_statistics: bool = True
|
37
|
+
|
38
|
+
@classmethod
|
39
|
+
def from_level(cls, level: int) -> "OptimizationConfig":
|
40
|
+
"""Create configuration from optimization level.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
level: Optimization level (0-3).
|
44
|
+
|
45
|
+
Returns:
|
46
|
+
Optimization configuration.
|
47
|
+
"""
|
48
|
+
if level == 0:
|
49
|
+
# No optimizations
|
50
|
+
return cls(
|
51
|
+
level=0,
|
52
|
+
enable_inlining=False,
|
53
|
+
enable_loop_opts=False,
|
54
|
+
enable_aggressive_opts=False,
|
55
|
+
)
|
56
|
+
elif level == 1:
|
57
|
+
# Basic optimizations
|
58
|
+
return cls(
|
59
|
+
level=1,
|
60
|
+
enable_inlining=False,
|
61
|
+
inline_threshold=25,
|
62
|
+
enable_loop_opts=False,
|
63
|
+
enable_aggressive_opts=False,
|
64
|
+
)
|
65
|
+
elif level == 2:
|
66
|
+
# Standard optimizations
|
67
|
+
return cls(
|
68
|
+
level=2,
|
69
|
+
enable_inlining=True,
|
70
|
+
inline_threshold=50,
|
71
|
+
enable_loop_opts=True,
|
72
|
+
unroll_threshold=4,
|
73
|
+
enable_aggressive_opts=False,
|
74
|
+
)
|
75
|
+
elif level >= 3:
|
76
|
+
# Aggressive optimizations
|
77
|
+
return cls(
|
78
|
+
level=3,
|
79
|
+
enable_inlining=True,
|
80
|
+
inline_threshold=100,
|
81
|
+
enable_loop_opts=True,
|
82
|
+
unroll_threshold=8,
|
83
|
+
enable_aggressive_opts=True,
|
84
|
+
)
|
85
|
+
else:
|
86
|
+
raise ValueError(f"Invalid optimization level: {level}")
|
87
|
+
|
88
|
+
|
89
|
+
class OptimizationPipeline:
|
90
|
+
"""Defines optimization pass pipelines for different levels."""
|
91
|
+
|
92
|
+
@staticmethod
|
93
|
+
def get_passes(config: OptimizationConfig) -> list[str]:
|
94
|
+
"""Get list of passes for a configuration.
|
95
|
+
|
96
|
+
Args:
|
97
|
+
config: Optimization configuration.
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
List of pass names to run.
|
101
|
+
"""
|
102
|
+
if config.level == 0:
|
103
|
+
# No optimizations, just validation
|
104
|
+
return []
|
105
|
+
|
106
|
+
passes = []
|
107
|
+
|
108
|
+
# Analysis passes (always needed)
|
109
|
+
passes.extend(
|
110
|
+
[
|
111
|
+
"use-def-chains",
|
112
|
+
]
|
113
|
+
)
|
114
|
+
|
115
|
+
if config.level >= 1:
|
116
|
+
# Basic optimizations
|
117
|
+
passes.extend(
|
118
|
+
[
|
119
|
+
"constant-propagation",
|
120
|
+
"strength-reduction",
|
121
|
+
"dce", # Dead code elimination
|
122
|
+
]
|
123
|
+
)
|
124
|
+
|
125
|
+
if config.level >= 2:
|
126
|
+
# Standard optimizations
|
127
|
+
passes.extend(
|
128
|
+
[
|
129
|
+
"cse", # Common subexpression elimination
|
130
|
+
]
|
131
|
+
)
|
132
|
+
|
133
|
+
if config.enable_loop_opts:
|
134
|
+
passes.extend(
|
135
|
+
[
|
136
|
+
"dominance", # Required for loop analysis (also available via DominanceInfo)
|
137
|
+
"loop-analysis",
|
138
|
+
"licm", # Loop invariant code motion
|
139
|
+
"loop-unrolling", # Unroll small loops
|
140
|
+
]
|
141
|
+
)
|
142
|
+
|
143
|
+
# Run another DCE pass after other optimizations
|
144
|
+
passes.append("dce")
|
145
|
+
|
146
|
+
if config.level >= 3:
|
147
|
+
# Aggressive optimizations
|
148
|
+
if config.enable_aggressive_opts:
|
149
|
+
# Advanced analyses
|
150
|
+
passes.extend(
|
151
|
+
[
|
152
|
+
"alias-analysis", # Alias analysis
|
153
|
+
"escape-analysis", # Escape analysis for stack allocation
|
154
|
+
]
|
155
|
+
)
|
156
|
+
# More aggressive versions of passes
|
157
|
+
passes.append("constant-propagation") # Run again
|
158
|
+
passes.append("cse") # Run again
|
159
|
+
|
160
|
+
if config.enable_inlining:
|
161
|
+
passes.append("inline") # Function inlining
|
162
|
+
|
163
|
+
# Final cleanup
|
164
|
+
passes.extend(
|
165
|
+
[
|
166
|
+
"strength-reduction",
|
167
|
+
"dce",
|
168
|
+
]
|
169
|
+
)
|
170
|
+
|
171
|
+
return passes
|
172
|
+
|
173
|
+
@staticmethod
|
174
|
+
def get_analysis_passes() -> list[str]:
|
175
|
+
"""Get list of available analysis passes.
|
176
|
+
|
177
|
+
Note: This function provides a catalog of available passes but is not
|
178
|
+
currently used in the optimization pipeline. The main entry point is
|
179
|
+
get_passes() which selects passes based on optimization level.
|
180
|
+
|
181
|
+
Returns:
|
182
|
+
List of analysis pass names.
|
183
|
+
"""
|
184
|
+
from machine_dialect.mir.optimization_pass import PassType
|
185
|
+
from machine_dialect.mir.optimizations import register_all_passes
|
186
|
+
from machine_dialect.mir.pass_manager import PassManager
|
187
|
+
|
188
|
+
pm = PassManager()
|
189
|
+
register_all_passes(pm)
|
190
|
+
return pm.registry.list_passes(PassType.ANALYSIS)
|
191
|
+
|
192
|
+
@staticmethod
|
193
|
+
def get_optimization_passes() -> list[str]:
|
194
|
+
"""Get list of available optimization passes.
|
195
|
+
|
196
|
+
Returns:
|
197
|
+
List of optimization pass names.
|
198
|
+
"""
|
199
|
+
from machine_dialect.mir.optimization_pass import PassType
|
200
|
+
from machine_dialect.mir.optimizations import register_all_passes
|
201
|
+
from machine_dialect.mir.pass_manager import PassManager
|
202
|
+
|
203
|
+
pm = PassManager()
|
204
|
+
register_all_passes(pm)
|
205
|
+
return pm.registry.list_passes(PassType.OPTIMIZATION)
|
206
|
+
|
207
|
+
@staticmethod
|
208
|
+
def get_cleanup_passes() -> list[str]:
|
209
|
+
"""Get list of cleanup passes.
|
210
|
+
|
211
|
+
Cleanup passes are lightweight optimizations safe to run at the end
|
212
|
+
of the optimization pipeline. Passes can be both optimization and cleanup.
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
List of cleanup pass names.
|
216
|
+
"""
|
217
|
+
from machine_dialect.mir.optimization_pass import PassType
|
218
|
+
from machine_dialect.mir.optimizations import register_all_passes
|
219
|
+
from machine_dialect.mir.pass_manager import PassManager
|
220
|
+
|
221
|
+
pm = PassManager()
|
222
|
+
register_all_passes(pm)
|
223
|
+
return pm.registry.list_passes(PassType.CLEANUP)
|
224
|
+
|
225
|
+
|
226
|
+
# Predefined configurations
|
227
|
+
NO_OPT_CONFIG = OptimizationConfig.from_level(0)
|
228
|
+
BASIC_OPT_CONFIG = OptimizationConfig.from_level(1)
|
229
|
+
STANDARD_OPT_CONFIG = OptimizationConfig.from_level(2)
|
230
|
+
AGGRESSIVE_OPT_CONFIG = OptimizationConfig.from_level(3)
|
231
|
+
|
232
|
+
# Default configuration
|
233
|
+
DEFAULT_CONFIG = BASIC_OPT_CONFIG
|