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,197 @@
|
|
1
|
+
"""Main compiler module.
|
2
|
+
|
3
|
+
This module provides the main Compiler class that manages the entire
|
4
|
+
compilation process.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from pathlib import Path
|
8
|
+
|
9
|
+
from machine_dialect.compiler.config import CompilerConfig
|
10
|
+
from machine_dialect.compiler.context import CompilationContext
|
11
|
+
from machine_dialect.compiler.pipeline import CompilationPipeline
|
12
|
+
|
13
|
+
|
14
|
+
class Compiler:
|
15
|
+
"""Main compiler class for Machine Dialect™.
|
16
|
+
|
17
|
+
Manages the entire compilation process from source files to bytecode,
|
18
|
+
including lexing, parsing, HIR/MIR generation, optimization, and
|
19
|
+
bytecode generation.
|
20
|
+
|
21
|
+
Attributes:
|
22
|
+
config: Compiler configuration settings.
|
23
|
+
pipeline: Compilation pipeline instance.
|
24
|
+
"""
|
25
|
+
|
26
|
+
def __init__(self, config: CompilerConfig | None = None) -> None:
|
27
|
+
"""Initialize the compiler.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
config: Compiler configuration.
|
31
|
+
"""
|
32
|
+
self.config = config or CompilerConfig()
|
33
|
+
self.pipeline = CompilationPipeline(self.config)
|
34
|
+
|
35
|
+
def compile_file(
|
36
|
+
self,
|
37
|
+
source_path: str | Path,
|
38
|
+
output_path: str | Path | None = None,
|
39
|
+
) -> bool:
|
40
|
+
"""Compile a Machine Dialect™ source file to bytecode.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
source_path: Path to the .md source file to compile.
|
44
|
+
output_path: Optional output path for compiled bytecode.
|
45
|
+
If not provided, uses config default or derives from source.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
True if compilation succeeded without errors.
|
49
|
+
|
50
|
+
Raises:
|
51
|
+
FileNotFoundError: If source file doesn't exist.
|
52
|
+
PermissionError: If unable to write output file.
|
53
|
+
"""
|
54
|
+
source_path = Path(source_path)
|
55
|
+
|
56
|
+
# Update output path in config if provided
|
57
|
+
if output_path:
|
58
|
+
self.config.output_path = Path(output_path)
|
59
|
+
|
60
|
+
# Run compilation pipeline
|
61
|
+
context = self.pipeline.compile_file(source_path)
|
62
|
+
|
63
|
+
# Print errors and warnings
|
64
|
+
context.print_errors_and_warnings()
|
65
|
+
|
66
|
+
# Check for errors
|
67
|
+
if context.has_errors():
|
68
|
+
return False
|
69
|
+
|
70
|
+
# Save compiled module if bytecode was generated
|
71
|
+
if context.bytecode_module and not self.config.mir_phase_only:
|
72
|
+
success = self._save_module(context)
|
73
|
+
if not success:
|
74
|
+
return False
|
75
|
+
|
76
|
+
# Show disassembly if requested
|
77
|
+
if self.config.verbose and context.bytecode_module:
|
78
|
+
self._show_disassembly(context)
|
79
|
+
|
80
|
+
# Print success message (but not for MIR-only mode)
|
81
|
+
if not self.config.mir_phase_only:
|
82
|
+
if self.config.verbose:
|
83
|
+
self._print_success(context)
|
84
|
+
else:
|
85
|
+
# Always print basic success message
|
86
|
+
output_path = context.get_output_path()
|
87
|
+
print(f"Successfully compiled to '{output_path}'")
|
88
|
+
|
89
|
+
return True
|
90
|
+
|
91
|
+
def compile_string(self, source: str, module_name: str = "__main__") -> CompilationContext:
|
92
|
+
"""Compile a string of source code.
|
93
|
+
|
94
|
+
Args:
|
95
|
+
source: Source code string.
|
96
|
+
module_name: Name for the module.
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
Compilation context with results.
|
100
|
+
"""
|
101
|
+
# Create a context with dummy source path
|
102
|
+
context = CompilationContext(
|
103
|
+
source_path=Path("<string>"),
|
104
|
+
config=self.config,
|
105
|
+
source_content=source,
|
106
|
+
)
|
107
|
+
|
108
|
+
# Set module name
|
109
|
+
self.config.module_name = module_name
|
110
|
+
|
111
|
+
# Run compilation pipeline
|
112
|
+
return self.pipeline.compile(context)
|
113
|
+
|
114
|
+
def _save_module(self, context: CompilationContext) -> bool:
|
115
|
+
"""Save compiled bytecode module to disk.
|
116
|
+
|
117
|
+
Args:
|
118
|
+
context: Compilation context containing bytecode module.
|
119
|
+
|
120
|
+
Returns:
|
121
|
+
True if save succeeded, False otherwise.
|
122
|
+
|
123
|
+
Note:
|
124
|
+
Errors during save are added to the compilation context.
|
125
|
+
"""
|
126
|
+
if not context.bytecode_module:
|
127
|
+
return False
|
128
|
+
|
129
|
+
output_path = context.get_output_path()
|
130
|
+
|
131
|
+
try:
|
132
|
+
# Set module name
|
133
|
+
context.bytecode_module.name = context.get_module_name()
|
134
|
+
|
135
|
+
# Serialize and save using VM serializer
|
136
|
+
bytecode_data = context.bytecode_module.serialize()
|
137
|
+
with open(output_path, "wb") as f:
|
138
|
+
f.write(bytecode_data)
|
139
|
+
|
140
|
+
if self.config.verbose:
|
141
|
+
print(f"Wrote compiled module to {output_path}")
|
142
|
+
|
143
|
+
return True
|
144
|
+
|
145
|
+
except Exception as e:
|
146
|
+
context.add_error(f"Failed to save module: {e}")
|
147
|
+
return False
|
148
|
+
|
149
|
+
def _show_disassembly(self, context: CompilationContext) -> None:
|
150
|
+
"""Display human-readable disassembly of compiled bytecode.
|
151
|
+
|
152
|
+
Args:
|
153
|
+
context: Compilation context containing bytecode module.
|
154
|
+
|
155
|
+
Note:
|
156
|
+
Currently placeholder - disassembly for register-based
|
157
|
+
bytecode is not yet implemented.
|
158
|
+
"""
|
159
|
+
if not context.bytecode_module:
|
160
|
+
return
|
161
|
+
|
162
|
+
print("\n=== Disassembly ===")
|
163
|
+
# TODO: Implement disassembly for new register-based bytecode
|
164
|
+
print("Disassembly not yet implemented for register-based bytecode")
|
165
|
+
|
166
|
+
def _print_success(self, context: CompilationContext) -> None:
|
167
|
+
"""Print detailed compilation success summary.
|
168
|
+
|
169
|
+
Args:
|
170
|
+
context: Compilation context containing statistics and results.
|
171
|
+
|
172
|
+
Note:
|
173
|
+
Only called when verbose mode is enabled in config.
|
174
|
+
"""
|
175
|
+
stats = context.get_statistics()
|
176
|
+
|
177
|
+
print("\n=== Compilation Summary ===")
|
178
|
+
print(f"Source: {stats['source_file']}")
|
179
|
+
print(f"Module: {stats['module_name']}")
|
180
|
+
|
181
|
+
if "mir_functions" in stats:
|
182
|
+
print(f"Functions: {stats['mir_functions']}")
|
183
|
+
|
184
|
+
if "optimizations" in stats:
|
185
|
+
opt_stats = stats["optimizations"]
|
186
|
+
if opt_stats:
|
187
|
+
# opt_stats is a string summary, not a dict
|
188
|
+
if isinstance(opt_stats, str):
|
189
|
+
# Just show that optimizations were applied
|
190
|
+
print("Optimizations applied")
|
191
|
+
elif isinstance(opt_stats, dict):
|
192
|
+
print(f"Optimizations applied: {opt_stats.get('total_transformations', 0)}")
|
193
|
+
|
194
|
+
if "bytecode_chunks" in stats:
|
195
|
+
print(f"Bytecode chunks: {stats['bytecode_chunks']}")
|
196
|
+
|
197
|
+
print("Compilation successful!")
|
@@ -0,0 +1,149 @@
|
|
1
|
+
"""Compiler configuration module.
|
2
|
+
|
3
|
+
This module defines configuration options for the Machine Dialect™ compiler.
|
4
|
+
"""
|
5
|
+
|
6
|
+
from dataclasses import dataclass, field
|
7
|
+
from enum import IntEnum
|
8
|
+
from pathlib import Path
|
9
|
+
|
10
|
+
|
11
|
+
class OptimizationLevel(IntEnum):
|
12
|
+
"""Optimization level enumeration."""
|
13
|
+
|
14
|
+
NONE = 0 # No optimizations
|
15
|
+
BASIC = 1 # Basic optimizations (constant folding, DCE)
|
16
|
+
STANDARD = 2 # Standard optimizations (default)
|
17
|
+
AGGRESSIVE = 3 # Aggressive optimizations (inlining, specialization)
|
18
|
+
|
19
|
+
|
20
|
+
@dataclass
|
21
|
+
class CompilerConfig:
|
22
|
+
"""Compiler configuration settings.
|
23
|
+
|
24
|
+
Attributes:
|
25
|
+
optimization_level: Level of optimization to apply.
|
26
|
+
dump_mir: Whether to dump MIR representation.
|
27
|
+
dump_cfg: Path to export control flow graph.
|
28
|
+
show_optimization_report: Whether to show optimization report.
|
29
|
+
verbose: Enable verbose output.
|
30
|
+
debug: Enable debug mode.
|
31
|
+
profile_path: Path to profile data for PGO.
|
32
|
+
mir_phase_only: Stop after MIR generation.
|
33
|
+
output_path: Output file path.
|
34
|
+
module_name: Name for the compiled module.
|
35
|
+
"""
|
36
|
+
|
37
|
+
optimization_level: OptimizationLevel = OptimizationLevel.STANDARD
|
38
|
+
dump_mir: bool = False
|
39
|
+
dump_cfg: Path | None = None
|
40
|
+
show_optimization_report: bool = False
|
41
|
+
verbose: bool = False
|
42
|
+
debug: bool = False
|
43
|
+
profile_path: Path | None = None
|
44
|
+
mir_phase_only: bool = False
|
45
|
+
output_path: Path | None = None
|
46
|
+
module_name: str | None = None
|
47
|
+
|
48
|
+
# MIR dumping options
|
49
|
+
mir_dump_verbosity: str = "normal"
|
50
|
+
mir_dump_phases: list[str] = field(default_factory=list)
|
51
|
+
|
52
|
+
# Optimization pass configuration
|
53
|
+
enabled_passes: list[str] | None = None
|
54
|
+
disabled_passes: list[str] | None = None
|
55
|
+
pass_pipeline: str | None = None # Custom pass pipeline
|
56
|
+
|
57
|
+
@classmethod
|
58
|
+
def from_cli_options(
|
59
|
+
cls,
|
60
|
+
opt_level: str = "2",
|
61
|
+
dump_mir: bool = False,
|
62
|
+
show_cfg: str | None = None,
|
63
|
+
opt_report: bool = False,
|
64
|
+
verbose: bool = False,
|
65
|
+
debug: bool = False,
|
66
|
+
mir_phase: bool = False,
|
67
|
+
output: str | None = None,
|
68
|
+
module_name: str | None = None,
|
69
|
+
**kwargs: object,
|
70
|
+
) -> "CompilerConfig":
|
71
|
+
"""Create config from CLI options.
|
72
|
+
|
73
|
+
Args:
|
74
|
+
opt_level: Optimization level string.
|
75
|
+
dump_mir: Whether to dump MIR.
|
76
|
+
show_cfg: Path for CFG export.
|
77
|
+
opt_report: Whether to show optimization report.
|
78
|
+
verbose: Enable verbose output.
|
79
|
+
debug: Enable debug mode.
|
80
|
+
mir_phase: Stop after MIR generation.
|
81
|
+
output: Output file path.
|
82
|
+
module_name: Module name.
|
83
|
+
**kwargs: Additional options.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
Compiler configuration instance.
|
87
|
+
"""
|
88
|
+
return cls(
|
89
|
+
optimization_level=OptimizationLevel(int(opt_level)),
|
90
|
+
dump_mir=dump_mir,
|
91
|
+
dump_cfg=Path(show_cfg) if show_cfg else None,
|
92
|
+
show_optimization_report=opt_report,
|
93
|
+
verbose=verbose,
|
94
|
+
debug=debug,
|
95
|
+
mir_phase_only=mir_phase,
|
96
|
+
output_path=Path(output) if output else None,
|
97
|
+
module_name=module_name,
|
98
|
+
)
|
99
|
+
|
100
|
+
def get_optimization_passes(self) -> list[str]:
|
101
|
+
"""Get list of optimization passes to run based on level.
|
102
|
+
|
103
|
+
Returns:
|
104
|
+
List of optimization pass names.
|
105
|
+
"""
|
106
|
+
if self.pass_pipeline:
|
107
|
+
return self.pass_pipeline.split(",")
|
108
|
+
|
109
|
+
passes = []
|
110
|
+
|
111
|
+
if self.optimization_level >= OptimizationLevel.BASIC:
|
112
|
+
passes.extend(
|
113
|
+
[
|
114
|
+
"constant-folding",
|
115
|
+
"constant-propagation",
|
116
|
+
"dce",
|
117
|
+
"simplify-cfg",
|
118
|
+
]
|
119
|
+
)
|
120
|
+
|
121
|
+
if self.optimization_level >= OptimizationLevel.STANDARD:
|
122
|
+
passes.extend(
|
123
|
+
[
|
124
|
+
"cse",
|
125
|
+
"strength-reduction",
|
126
|
+
"algebraic-simplification", # New pass
|
127
|
+
"licm",
|
128
|
+
"loop-unrolling",
|
129
|
+
"tail-call",
|
130
|
+
]
|
131
|
+
)
|
132
|
+
|
133
|
+
if self.optimization_level >= OptimizationLevel.AGGRESSIVE:
|
134
|
+
passes.extend(
|
135
|
+
[
|
136
|
+
"inlining",
|
137
|
+
"type-specialization",
|
138
|
+
"branch-prediction",
|
139
|
+
"escape-analysis",
|
140
|
+
]
|
141
|
+
)
|
142
|
+
|
143
|
+
# Filter based on enabled/disabled lists
|
144
|
+
if self.enabled_passes:
|
145
|
+
passes = [p for p in passes if p in self.enabled_passes]
|
146
|
+
if self.disabled_passes:
|
147
|
+
passes = [p for p in passes if p not in self.disabled_passes]
|
148
|
+
|
149
|
+
return passes
|
@@ -0,0 +1,149 @@
|
|
1
|
+
"""Compilation context module.
|
2
|
+
|
3
|
+
This module manages the state and context throughout the compilation process.
|
4
|
+
"""
|
5
|
+
|
6
|
+
from dataclasses import dataclass, field
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import Any
|
9
|
+
|
10
|
+
from machine_dialect.ast.ast_node import ASTNode
|
11
|
+
from machine_dialect.codegen.bytecode_module import BytecodeModule
|
12
|
+
from machine_dialect.compiler.config import CompilerConfig
|
13
|
+
from machine_dialect.mir.mir_module import MIRModule
|
14
|
+
from machine_dialect.mir.profiling.profile_data import ProfileData
|
15
|
+
from machine_dialect.mir.reporting.optimization_reporter import OptimizationReporter
|
16
|
+
|
17
|
+
|
18
|
+
@dataclass
|
19
|
+
class CompilationContext:
|
20
|
+
"""Context for a single compilation session.
|
21
|
+
|
22
|
+
Attributes:
|
23
|
+
source_path: Path to source file being compiled.
|
24
|
+
config: Compiler configuration.
|
25
|
+
source_content: Source file content.
|
26
|
+
ast: Abstract syntax tree.
|
27
|
+
mir_module: MIR module.
|
28
|
+
bytecode_module: Bytecode module.
|
29
|
+
optimization_reporter: Optimization statistics reporter.
|
30
|
+
profile_data: Profile data for PGO.
|
31
|
+
errors: List of compilation errors.
|
32
|
+
warnings: List of compilation warnings.
|
33
|
+
metadata: Additional compilation metadata.
|
34
|
+
"""
|
35
|
+
|
36
|
+
source_path: Path
|
37
|
+
config: CompilerConfig
|
38
|
+
source_content: str = ""
|
39
|
+
ast: ASTNode | None = None
|
40
|
+
mir_module: MIRModule | None = None
|
41
|
+
bytecode_module: BytecodeModule | None = None
|
42
|
+
optimization_reporter: OptimizationReporter | None = None
|
43
|
+
profile_data: ProfileData | None = None
|
44
|
+
errors: list[str] = field(default_factory=list)
|
45
|
+
warnings: list[str] = field(default_factory=list)
|
46
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
47
|
+
|
48
|
+
def add_error(self, message: str) -> None:
|
49
|
+
"""Add a compilation error.
|
50
|
+
|
51
|
+
Args:
|
52
|
+
message: Error message.
|
53
|
+
"""
|
54
|
+
self.errors.append(message)
|
55
|
+
|
56
|
+
def add_warning(self, message: str) -> None:
|
57
|
+
"""Add a compilation warning.
|
58
|
+
|
59
|
+
Args:
|
60
|
+
message: Warning message.
|
61
|
+
"""
|
62
|
+
self.warnings.append(message)
|
63
|
+
|
64
|
+
def has_errors(self) -> bool:
|
65
|
+
"""Check if compilation has errors.
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
True if there are errors.
|
69
|
+
"""
|
70
|
+
return len(self.errors) > 0
|
71
|
+
|
72
|
+
def get_module_name(self) -> str:
|
73
|
+
"""Get the module name for compilation.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
Module name.
|
77
|
+
"""
|
78
|
+
if self.config.module_name:
|
79
|
+
return self.config.module_name
|
80
|
+
return self.source_path.stem
|
81
|
+
|
82
|
+
def get_output_path(self) -> Path:
|
83
|
+
"""Get the output path for compiled module.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
Output file path.
|
87
|
+
"""
|
88
|
+
if self.config.output_path:
|
89
|
+
return self.config.output_path
|
90
|
+
return self.source_path.with_suffix(".mdbc")
|
91
|
+
|
92
|
+
def should_optimize(self) -> bool:
|
93
|
+
"""Check if optimization should be performed.
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
True if optimization is enabled.
|
97
|
+
"""
|
98
|
+
from machine_dialect.compiler.config import OptimizationLevel
|
99
|
+
|
100
|
+
return self.config.optimization_level > OptimizationLevel.NONE
|
101
|
+
|
102
|
+
def should_dump_mir(self) -> bool:
|
103
|
+
"""Check if MIR should be dumped.
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
True if MIR dumping is enabled.
|
107
|
+
"""
|
108
|
+
return self.config.dump_mir or self.config.mir_phase_only
|
109
|
+
|
110
|
+
def should_generate_bytecode(self) -> bool:
|
111
|
+
"""Check if bytecode generation should proceed.
|
112
|
+
|
113
|
+
Returns:
|
114
|
+
True if bytecode should be generated.
|
115
|
+
"""
|
116
|
+
return not self.config.mir_phase_only
|
117
|
+
|
118
|
+
def print_errors_and_warnings(self) -> None:
|
119
|
+
"""Print compilation errors and warnings."""
|
120
|
+
for warning in self.warnings:
|
121
|
+
print(f"Warning: {warning}")
|
122
|
+
|
123
|
+
for error in self.errors:
|
124
|
+
print(f"Error: {error}", file=__import__("sys").stderr)
|
125
|
+
|
126
|
+
def get_statistics(self) -> dict[str, Any]:
|
127
|
+
"""Get compilation statistics.
|
128
|
+
|
129
|
+
Returns:
|
130
|
+
Dictionary of compilation statistics.
|
131
|
+
"""
|
132
|
+
stats = {
|
133
|
+
"source_file": str(self.source_path),
|
134
|
+
"module_name": self.get_module_name(),
|
135
|
+
"errors": len(self.errors),
|
136
|
+
"warnings": len(self.warnings),
|
137
|
+
}
|
138
|
+
|
139
|
+
if self.mir_module:
|
140
|
+
stats["mir_functions"] = len(self.mir_module.functions)
|
141
|
+
stats["mir_globals"] = len(self.mir_module.globals)
|
142
|
+
|
143
|
+
if self.optimization_reporter:
|
144
|
+
stats["optimizations"] = self.optimization_reporter.generate_summary()
|
145
|
+
|
146
|
+
if self.bytecode_module:
|
147
|
+
stats["bytecode_chunks"] = len(self.bytecode_module.chunks)
|
148
|
+
|
149
|
+
return stats
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"""Compilation phases module.
|
2
|
+
|
3
|
+
This module contains individual compilation phases that make up the
|
4
|
+
compilation pipeline.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from machine_dialect.compiler.phases.codegen import CodeGenerationPhase
|
8
|
+
from machine_dialect.compiler.phases.hir_generation import HIRGenerationPhase
|
9
|
+
from machine_dialect.compiler.phases.mir_generation import MIRGenerationPhase
|
10
|
+
from machine_dialect.compiler.phases.optimization import OptimizationPhase
|
11
|
+
from machine_dialect.compiler.phases.parsing import ParsingPhase
|
12
|
+
|
13
|
+
__all__ = [
|
14
|
+
"CodeGenerationPhase",
|
15
|
+
"HIRGenerationPhase",
|
16
|
+
"MIRGenerationPhase",
|
17
|
+
"OptimizationPhase",
|
18
|
+
"ParsingPhase",
|
19
|
+
]
|
@@ -0,0 +1,90 @@
|
|
1
|
+
"""Bytecode optimization phase.
|
2
|
+
|
3
|
+
This module handles bytecode-level optimizations after code generation.
|
4
|
+
"""
|
5
|
+
|
6
|
+
from __future__ import annotations
|
7
|
+
|
8
|
+
from typing import TYPE_CHECKING
|
9
|
+
|
10
|
+
from machine_dialect.codegen.bytecode_module import BytecodeModule
|
11
|
+
from machine_dialect.mir.optimizations.jump_threading import JumpThreadingOptimizer
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from machine_dialect.compiler.context import CompilationContext
|
15
|
+
|
16
|
+
|
17
|
+
class BytecodeOptimizationPhase:
|
18
|
+
"""Bytecode optimization phase.
|
19
|
+
|
20
|
+
Applies bytecode-level optimizations like jump threading,
|
21
|
+
peephole optimization, etc.
|
22
|
+
"""
|
23
|
+
|
24
|
+
def __init__(self) -> None:
|
25
|
+
"""Initialize the bytecode optimization phase."""
|
26
|
+
self.jump_threading = JumpThreadingOptimizer()
|
27
|
+
|
28
|
+
def run(self, context: CompilationContext, bytecode_module: BytecodeModule) -> BytecodeModule:
|
29
|
+
"""Run bytecode optimizations.
|
30
|
+
|
31
|
+
Args:
|
32
|
+
context: Compilation context.
|
33
|
+
bytecode_module: Bytecode module to optimize.
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
Optimized bytecode module.
|
37
|
+
"""
|
38
|
+
if not context.should_optimize():
|
39
|
+
return bytecode_module
|
40
|
+
|
41
|
+
if context.config.verbose:
|
42
|
+
print("Running bytecode optimizations...")
|
43
|
+
|
44
|
+
# Apply jump threading to each chunk
|
45
|
+
optimized_chunks = []
|
46
|
+
total_stats = {
|
47
|
+
"jumps_threaded": 0,
|
48
|
+
"blocks_eliminated": 0,
|
49
|
+
"jumps_simplified": 0,
|
50
|
+
"blocks_merged": 0,
|
51
|
+
}
|
52
|
+
|
53
|
+
for chunk in bytecode_module.chunks:
|
54
|
+
# Reset optimizer for each chunk
|
55
|
+
self.jump_threading = JumpThreadingOptimizer()
|
56
|
+
|
57
|
+
# Optimize the chunk
|
58
|
+
optimized_chunk = self.jump_threading.optimize(chunk)
|
59
|
+
optimized_chunks.append(optimized_chunk)
|
60
|
+
|
61
|
+
# Accumulate statistics
|
62
|
+
stats = self.jump_threading.get_stats()
|
63
|
+
for key, value in stats.items():
|
64
|
+
total_stats[key] += value
|
65
|
+
|
66
|
+
# Create new module with optimized chunks
|
67
|
+
optimized_module = BytecodeModule(bytecode_module.name)
|
68
|
+
optimized_module.chunks = optimized_chunks
|
69
|
+
optimized_module.function_table = bytecode_module.function_table.copy()
|
70
|
+
optimized_module.global_names = bytecode_module.global_names.copy()
|
71
|
+
optimized_module.metadata = bytecode_module.metadata.copy()
|
72
|
+
|
73
|
+
# Report optimization results
|
74
|
+
if context.config.verbose and any(total_stats.values()):
|
75
|
+
print("\n=== Bytecode Optimization Results ===")
|
76
|
+
if total_stats["jumps_threaded"] > 0:
|
77
|
+
print(f" Jumps threaded: {total_stats['jumps_threaded']}")
|
78
|
+
if total_stats["blocks_eliminated"] > 0:
|
79
|
+
print(f" Dead blocks eliminated: {total_stats['blocks_eliminated']}")
|
80
|
+
if total_stats["jumps_simplified"] > 0:
|
81
|
+
print(f" Conditional jumps simplified: {total_stats['jumps_simplified']}")
|
82
|
+
if total_stats["blocks_merged"] > 0:
|
83
|
+
print(f" Blocks merged: {total_stats['blocks_merged']}")
|
84
|
+
print()
|
85
|
+
|
86
|
+
# Store stats in context for reporting
|
87
|
+
if context.optimization_reporter:
|
88
|
+
context.optimization_reporter.add_custom_stats("bytecode_optimization", total_stats)
|
89
|
+
|
90
|
+
return optimized_module
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"""Register-based code generation phase.
|
2
|
+
|
3
|
+
This module handles the register-based bytecode generation for the new Rust VM.
|
4
|
+
"""
|
5
|
+
|
6
|
+
from machine_dialect.codegen.bytecode_module import BytecodeModule
|
7
|
+
from machine_dialect.codegen.register_codegen import RegisterBytecodeGenerator
|
8
|
+
from machine_dialect.compiler.context import CompilationContext
|
9
|
+
from machine_dialect.mir.mir_module import MIRModule
|
10
|
+
|
11
|
+
|
12
|
+
class CodeGenerationPhase:
|
13
|
+
"""Register-based bytecode generation phase."""
|
14
|
+
|
15
|
+
def run(self, context: CompilationContext, mir_module: MIRModule) -> BytecodeModule | None:
|
16
|
+
"""Run code generation phase.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
context: Compilation context.
|
20
|
+
mir_module: MIR module to generate code from.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
Bytecode module or None if generation failed.
|
24
|
+
"""
|
25
|
+
try:
|
26
|
+
# Create bytecode generator with debug if verbose mode is on
|
27
|
+
debug = context.config.verbose if context.config else False
|
28
|
+
generator = RegisterBytecodeGenerator(debug=debug)
|
29
|
+
|
30
|
+
# Generate bytecode from MIR
|
31
|
+
bytecode_module = generator.generate(mir_module)
|
32
|
+
|
33
|
+
# Store in context
|
34
|
+
context.bytecode_module = bytecode_module
|
35
|
+
|
36
|
+
return bytecode_module
|
37
|
+
|
38
|
+
except Exception as e:
|
39
|
+
context.add_error(f"Code generation failed: {e}")
|
40
|
+
return None
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""HIR generation phase of compilation.
|
2
|
+
|
3
|
+
This module handles the High-level IR generation (desugaring) phase.
|
4
|
+
"""
|
5
|
+
|
6
|
+
from machine_dialect.ast.ast_node import ASTNode
|
7
|
+
from machine_dialect.compiler.context import CompilationContext
|
8
|
+
|
9
|
+
|
10
|
+
class HIRGenerationPhase:
|
11
|
+
"""HIR generation (desugaring) phase."""
|
12
|
+
|
13
|
+
def run(self, context: CompilationContext, ast: ASTNode) -> ASTNode:
|
14
|
+
"""Run HIR generation phase.
|
15
|
+
|
16
|
+
Converts AST to HIR by applying desugaring and canonicalization
|
17
|
+
transformations using the to_hir method.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
context: Compilation context.
|
21
|
+
ast: Abstract syntax tree.
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
HIR representation with desugared and canonicalized nodes.
|
25
|
+
"""
|
26
|
+
if context.config.verbose:
|
27
|
+
print("Generating HIR")
|
28
|
+
|
29
|
+
# Use to_hir to convert AST to HIR
|
30
|
+
# The ast should be a Program which has to_hir method
|
31
|
+
from machine_dialect.ast.program import Program
|
32
|
+
|
33
|
+
assert isinstance(ast, Program), "HIR generation expects a Program node"
|
34
|
+
hir = ast.to_hir()
|
35
|
+
|
36
|
+
if context.config.verbose:
|
37
|
+
print("HIR generation complete")
|
38
|
+
|
39
|
+
return hir
|