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,173 @@
|
|
1
|
+
"""VM Runner - Manages Rust VM execution for Machine Dialectâ„¢.
|
2
|
+
|
3
|
+
This module provides the integration layer between the Python compiler
|
4
|
+
pipeline and the Rust VM for executing Machine Dialectâ„¢ programs.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
|
9
|
+
import tempfile
|
10
|
+
from pathlib import Path
|
11
|
+
from typing import Any
|
12
|
+
|
13
|
+
from machine_dialect.codegen.register_codegen import (
|
14
|
+
RegisterBytecodeGenerator,
|
15
|
+
)
|
16
|
+
from machine_dialect.compiler.config import CompilerConfig
|
17
|
+
from machine_dialect.compiler.context import CompilationContext
|
18
|
+
from machine_dialect.compiler.phases.hir_generation import HIRGenerationPhase
|
19
|
+
from machine_dialect.compiler.phases.mir_generation import MIRGenerationPhase
|
20
|
+
from machine_dialect.mir.mir_module import MIRModule
|
21
|
+
from machine_dialect.mir.optimize_mir import optimize_mir
|
22
|
+
from machine_dialect.parser.parser import Parser
|
23
|
+
|
24
|
+
|
25
|
+
class VMRunner:
|
26
|
+
"""Manages compilation and execution of Machine Dialectâ„¢ code on the Rust VM.
|
27
|
+
|
28
|
+
This class provides a high-level interface for:
|
29
|
+
1. Compiling Machine Dialectâ„¢ source to bytecode
|
30
|
+
2. Loading bytecode into the Rust VM
|
31
|
+
3. Executing programs and returning results
|
32
|
+
"""
|
33
|
+
|
34
|
+
def __init__(self, debug: bool = False, optimize: bool = False) -> None:
|
35
|
+
"""Initialize the VM runner.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
debug: Enable debug output
|
39
|
+
optimize: Enable MIR optimizations
|
40
|
+
"""
|
41
|
+
self.debug = debug
|
42
|
+
self.optimize = optimize
|
43
|
+
self.vm: Any = None
|
44
|
+
self._init_vm()
|
45
|
+
|
46
|
+
def _init_vm(self) -> None:
|
47
|
+
"""Initialize the Rust VM instance."""
|
48
|
+
try:
|
49
|
+
import machine_dialect_vm
|
50
|
+
|
51
|
+
self.vm = machine_dialect_vm.RustVM()
|
52
|
+
if self.debug:
|
53
|
+
self.vm.set_debug(True)
|
54
|
+
except ImportError as e:
|
55
|
+
raise RuntimeError(
|
56
|
+
"Rust VM module not available. Please build it first:\n"
|
57
|
+
" ./build_vm.sh\n"
|
58
|
+
"or manually:\n"
|
59
|
+
" cd machine_dialect_vm && maturin develop --features pyo3"
|
60
|
+
) from e
|
61
|
+
|
62
|
+
def compile_to_bytecode(self, source: str, source_path: Path | None = None) -> bytes:
|
63
|
+
"""Compile Machine Dialectâ„¢ source code to bytecode.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
source: Machine Dialectâ„¢ source code
|
67
|
+
source_path: Optional path to source file
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
Serialized bytecode ready for VM execution
|
71
|
+
|
72
|
+
Raises:
|
73
|
+
CompilationError: If compilation fails at any stage
|
74
|
+
"""
|
75
|
+
if source_path is None:
|
76
|
+
source_path = Path("<repl>")
|
77
|
+
|
78
|
+
# Step 1: Parse to AST
|
79
|
+
parser = Parser()
|
80
|
+
ast = parser.parse(source)
|
81
|
+
if ast is None:
|
82
|
+
raise ValueError("Failed to parse source code")
|
83
|
+
|
84
|
+
# Step 2: Generate HIR
|
85
|
+
config = CompilerConfig(verbose=self.debug)
|
86
|
+
context = CompilationContext(source_path=source_path, config=config, source_content=source)
|
87
|
+
hir_phase = HIRGenerationPhase()
|
88
|
+
hir = hir_phase.run(context, ast)
|
89
|
+
if hir is None:
|
90
|
+
raise ValueError("Failed to generate HIR")
|
91
|
+
|
92
|
+
# Step 3: Generate MIR
|
93
|
+
mir_phase = MIRGenerationPhase()
|
94
|
+
mir_module = mir_phase.run(context, hir)
|
95
|
+
if mir_module is None:
|
96
|
+
raise ValueError("Failed to generate MIR")
|
97
|
+
|
98
|
+
# Step 4: Optimize MIR (if enabled)
|
99
|
+
if self.optimize:
|
100
|
+
mir_module, _ = optimize_mir(mir_module)
|
101
|
+
|
102
|
+
# Step 5: Generate bytecode
|
103
|
+
return self._mir_to_bytecode(mir_module)
|
104
|
+
|
105
|
+
def _mir_to_bytecode(self, mir_module: MIRModule) -> bytes:
|
106
|
+
"""Convert MIR module to bytecode.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
mir_module: The MIR module to convert
|
110
|
+
|
111
|
+
Returns:
|
112
|
+
Serialized bytecode
|
113
|
+
"""
|
114
|
+
# Generate bytecode
|
115
|
+
generator = RegisterBytecodeGenerator()
|
116
|
+
bytecode_module = generator.generate(mir_module)
|
117
|
+
|
118
|
+
# Serialize to bytes
|
119
|
+
return bytecode_module.serialize()
|
120
|
+
|
121
|
+
def execute(self, source: str) -> Any:
|
122
|
+
"""Compile and execute Machine Dialectâ„¢ source code.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
source: Machine Dialectâ„¢ source code
|
126
|
+
|
127
|
+
Returns:
|
128
|
+
The result of program execution
|
129
|
+
|
130
|
+
Raises:
|
131
|
+
RuntimeError: If execution fails
|
132
|
+
"""
|
133
|
+
# Compile to bytecode
|
134
|
+
bytecode = self.compile_to_bytecode(source)
|
135
|
+
|
136
|
+
# Write to temporary file (VM loads from file)
|
137
|
+
with tempfile.NamedTemporaryFile(suffix=".mdbc", delete=False) as f:
|
138
|
+
f.write(bytecode)
|
139
|
+
bytecode_path = f.name
|
140
|
+
|
141
|
+
try:
|
142
|
+
# Load and execute in VM
|
143
|
+
self.vm.load_bytecode(bytecode_path)
|
144
|
+
result = self.vm.execute()
|
145
|
+
return result
|
146
|
+
finally:
|
147
|
+
# Clean up temporary file
|
148
|
+
Path(bytecode_path).unlink(missing_ok=True)
|
149
|
+
|
150
|
+
def execute_bytecode(self, bytecode: bytes) -> Any:
|
151
|
+
"""Execute pre-compiled bytecode.
|
152
|
+
|
153
|
+
Args:
|
154
|
+
bytecode: Serialized bytecode
|
155
|
+
|
156
|
+
Returns:
|
157
|
+
The result of program execution
|
158
|
+
"""
|
159
|
+
# Write to temporary file
|
160
|
+
with tempfile.NamedTemporaryFile(suffix=".mdbc", delete=False) as f:
|
161
|
+
f.write(bytecode)
|
162
|
+
bytecode_path = f.name
|
163
|
+
|
164
|
+
try:
|
165
|
+
self.vm.load_bytecode(bytecode_path)
|
166
|
+
result = self.vm.execute()
|
167
|
+
return result
|
168
|
+
finally:
|
169
|
+
Path(bytecode_path).unlink(missing_ok=True)
|
170
|
+
|
171
|
+
def reset(self) -> None:
|
172
|
+
"""Reset the VM to initial state."""
|
173
|
+
self._init_vm()
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"""Error handling for Machine Dialectâ„¢.
|
2
|
+
|
3
|
+
This package provides exception classes and error reporting utilities.
|
4
|
+
"""
|
5
|
+
|
6
|
+
from machine_dialect.errors.exceptions import (
|
7
|
+
MDException,
|
8
|
+
MDNameError,
|
9
|
+
MDSyntaxError,
|
10
|
+
MDTypeError,
|
11
|
+
MDUninitializedError,
|
12
|
+
MDValueError,
|
13
|
+
)
|
14
|
+
from machine_dialect.errors.messages import (
|
15
|
+
EXPECTED_BLOCK_MARKER,
|
16
|
+
EXPECTED_EXPRESSION,
|
17
|
+
EXPECTED_PREFIX_OPERATOR,
|
18
|
+
UNEXPECTED_TOKEN,
|
19
|
+
)
|
20
|
+
|
21
|
+
__all__ = [
|
22
|
+
"EXPECTED_BLOCK_MARKER",
|
23
|
+
"EXPECTED_EXPRESSION",
|
24
|
+
"EXPECTED_PREFIX_OPERATOR",
|
25
|
+
"UNEXPECTED_TOKEN",
|
26
|
+
"MDException",
|
27
|
+
"MDNameError",
|
28
|
+
"MDSyntaxError",
|
29
|
+
"MDTypeError",
|
30
|
+
"MDUninitializedError",
|
31
|
+
"MDValueError",
|
32
|
+
]
|
@@ -0,0 +1,369 @@
|
|
1
|
+
"""Machine Dialectâ„¢ exception classes.
|
2
|
+
|
3
|
+
This module defines the exception hierarchy for the Machine Dialectâ„¢ language.
|
4
|
+
All exceptions inherit from MDBaseException, which provides a common base
|
5
|
+
for error handling throughout the system.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from abc import ABC, abstractmethod
|
9
|
+
from typing import Any
|
10
|
+
|
11
|
+
from machine_dialect.errors.messages import ErrorTemplate
|
12
|
+
|
13
|
+
|
14
|
+
class MDBaseException(ABC):
|
15
|
+
"""Base Machine Dialectâ„¢ Exception.
|
16
|
+
|
17
|
+
The base class for all built-in Machine Dialectâ„¢ exceptions.
|
18
|
+
This is an abstract base class and should not be instantiated directly.
|
19
|
+
|
20
|
+
Attributes:
|
21
|
+
message (str): The error message.
|
22
|
+
line (int, optional): The line number where the error occurred.
|
23
|
+
column (int, optional): The column number where the error occurred.
|
24
|
+
filename (str, optional): The filename where the error occurred.
|
25
|
+
|
26
|
+
Note:
|
27
|
+
This is a pure ABC that does not inherit from Python's Exception.
|
28
|
+
These exceptions represent errors in Machine Dialectâ„¢ code, not Python code.
|
29
|
+
"""
|
30
|
+
|
31
|
+
def __init__(
|
32
|
+
self, message: ErrorTemplate, line: int, column: int, filename: str | None = None, **kwargs: Any
|
33
|
+
) -> None:
|
34
|
+
"""Initialize the Machine Dialectâ„¢ exception.
|
35
|
+
|
36
|
+
Args:
|
37
|
+
message: The error message template.
|
38
|
+
line: The line number where the error occurred.
|
39
|
+
column: The column number where the error occurred.
|
40
|
+
filename: The filename where the error occurred.
|
41
|
+
**kwargs: Template substitution parameters.
|
42
|
+
"""
|
43
|
+
# Format the message with any provided kwargs
|
44
|
+
# If no kwargs, call substitute with empty dict to get the template with no substitutions
|
45
|
+
self._message = message.format(**kwargs) if kwargs else message.substitute()
|
46
|
+
self._line = line
|
47
|
+
self._column = column
|
48
|
+
self._filename = filename or "<standard-input>"
|
49
|
+
|
50
|
+
def __str__(self) -> str:
|
51
|
+
"""Return string representation of the exception.
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
A formatted error message with location information if available.
|
55
|
+
"""
|
56
|
+
parts = []
|
57
|
+
if self._filename:
|
58
|
+
parts.append(f'File "{self._filename}"')
|
59
|
+
if self._line is not None:
|
60
|
+
parts.append(f"line {self._line}")
|
61
|
+
if self._column is not None:
|
62
|
+
parts.append(f"column {self._column}")
|
63
|
+
|
64
|
+
location = ", ".join(parts)
|
65
|
+
if location:
|
66
|
+
return f"{location}: {self._message}"
|
67
|
+
return self._message
|
68
|
+
|
69
|
+
def __repr__(self) -> str:
|
70
|
+
"""Return detailed representation of the exception.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
A string showing the exception class and all attributes.
|
74
|
+
"""
|
75
|
+
mydict = {
|
76
|
+
"message": self._message.__repr__(),
|
77
|
+
"line": self._line,
|
78
|
+
"column": self._column,
|
79
|
+
"filename": self._filename.__repr__(),
|
80
|
+
}
|
81
|
+
concatenated = ", ".join([f"{k}={v}" for k, v in mydict.items()])
|
82
|
+
return f"{self.__class__.__name__}({concatenated})"
|
83
|
+
|
84
|
+
@abstractmethod
|
85
|
+
def error_type(self) -> str:
|
86
|
+
"""Return the error type identifier for this exception.
|
87
|
+
|
88
|
+
This should return a string that identifies the type of error
|
89
|
+
in Machine Dialectâ„¢ terms (e.g., "SyntaxError", "NameError").
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
The error type as a string.
|
93
|
+
"""
|
94
|
+
pass
|
95
|
+
|
96
|
+
|
97
|
+
class MDException(MDBaseException):
|
98
|
+
"""General Machine Dialectâ„¢ Exception.
|
99
|
+
|
100
|
+
This is the base class for all non-syntax Machine Dialectâ„¢ exceptions.
|
101
|
+
It provides a concrete implementation of MDBaseException that can be
|
102
|
+
instantiated directly for general errors.
|
103
|
+
|
104
|
+
Note:
|
105
|
+
Most specific error conditions should use a more specialized
|
106
|
+
exception subclass when available.
|
107
|
+
"""
|
108
|
+
|
109
|
+
def error_type(self) -> str:
|
110
|
+
"""Return the error type identifier.
|
111
|
+
|
112
|
+
Returns:
|
113
|
+
"Exception" for general Machine Dialectâ„¢ exceptions.
|
114
|
+
"""
|
115
|
+
return "Exception"
|
116
|
+
|
117
|
+
|
118
|
+
class MDDivisionByZero(MDException):
|
119
|
+
"""Raised when a division or modulo operation has zero as divisor.
|
120
|
+
|
121
|
+
This exception is raised when attempting to divide by zero or perform
|
122
|
+
a modulo operation with zero as the divisor.
|
123
|
+
|
124
|
+
Example:
|
125
|
+
>>> 10 / 0
|
126
|
+
Traceback (most recent call last):
|
127
|
+
...
|
128
|
+
MDDivisionByZero: division by zero
|
129
|
+
|
130
|
+
>>> 10 % 0
|
131
|
+
Traceback (most recent call last):
|
132
|
+
...
|
133
|
+
MDDivisionByZero: integer division or modulo by zero
|
134
|
+
"""
|
135
|
+
|
136
|
+
|
137
|
+
class MDAssertionError(MDException):
|
138
|
+
"""Raised when an assertion fails.
|
139
|
+
|
140
|
+
This exception is raised when an assert statement fails in Machine Dialectâ„¢ code.
|
141
|
+
It corresponds to Python's built-in AssertionError.
|
142
|
+
|
143
|
+
Example:
|
144
|
+
>>> assert False, "This will raise MDAssertionError"
|
145
|
+
Traceback (most recent call last):
|
146
|
+
...
|
147
|
+
MDAssertionError: This will raise MDAssertionError
|
148
|
+
"""
|
149
|
+
|
150
|
+
|
151
|
+
class MDSystemExit(MDException):
|
152
|
+
"""Raised to exit from the Machine Dialectâ„¢ interpreter.
|
153
|
+
|
154
|
+
This exception is used to exit from the interpreter or terminate
|
155
|
+
program execution. It corresponds to Python's SystemExit.
|
156
|
+
|
157
|
+
Attributes:
|
158
|
+
code (int | str | None): The exit status code. If None, defaults to 0.
|
159
|
+
An integer gives the exit status (0 means success).
|
160
|
+
A string prints the message to stderr and exits with status 1.
|
161
|
+
|
162
|
+
Example:
|
163
|
+
>>> exit(0) # Normal termination
|
164
|
+
>>> exit(1) # Termination with error
|
165
|
+
>>> exit("Error message") # Print message and exit with status 1
|
166
|
+
"""
|
167
|
+
|
168
|
+
|
169
|
+
class MDNameError(MDException):
|
170
|
+
"""Raised when a name is not found in any scope.
|
171
|
+
|
172
|
+
This exception is raised when a local or global name is not found.
|
173
|
+
This applies to unqualified names within functions, methods, or
|
174
|
+
the global scope.
|
175
|
+
|
176
|
+
Attributes:
|
177
|
+
name (str, optional): The name that could not be found.
|
178
|
+
|
179
|
+
Example:
|
180
|
+
>>> print(undefined_variable)
|
181
|
+
Traceback (most recent call last):
|
182
|
+
...
|
183
|
+
MDNameError: name 'undefined_variable' is not defined
|
184
|
+
|
185
|
+
>>> del nonexistent
|
186
|
+
Traceback (most recent call last):
|
187
|
+
...
|
188
|
+
MDNameError: name 'nonexistent' is not defined
|
189
|
+
"""
|
190
|
+
|
191
|
+
def __init__(self, message: str | ErrorTemplate, line: int = 0, column: int = 0, **kwargs: Any) -> None:
|
192
|
+
"""Initialize name error.
|
193
|
+
|
194
|
+
Args:
|
195
|
+
message: Error message string or ErrorTemplate
|
196
|
+
line: Line number where error occurred
|
197
|
+
column: Column position where error occurred
|
198
|
+
**kwargs: Additional template parameters if message is ErrorTemplate
|
199
|
+
"""
|
200
|
+
if isinstance(message, str):
|
201
|
+
# Create a simple ErrorTemplate from the string
|
202
|
+
from machine_dialect.errors.messages import ErrorTemplate
|
203
|
+
|
204
|
+
template = ErrorTemplate(message)
|
205
|
+
super().__init__(template, line, column, **kwargs)
|
206
|
+
else:
|
207
|
+
super().__init__(message, line, column, **kwargs)
|
208
|
+
|
209
|
+
|
210
|
+
class MDSyntaxError(MDException):
|
211
|
+
"""Raised when a syntax error is encountered.
|
212
|
+
|
213
|
+
This exception is raised when the parser encounters syntactically
|
214
|
+
incorrect Machine Dialectâ„¢ code. This includes malformed expressions,
|
215
|
+
invalid statement structure, or improper use of keywords.
|
216
|
+
|
217
|
+
Example:
|
218
|
+
>>> if x = 5: # Should use 'is' for comparison
|
219
|
+
... pass
|
220
|
+
Traceback (most recent call last):
|
221
|
+
...
|
222
|
+
MDSyntaxError: invalid syntax
|
223
|
+
|
224
|
+
>>> def function(
|
225
|
+
... # Missing closing parenthesis
|
226
|
+
Traceback (most recent call last):
|
227
|
+
...
|
228
|
+
MDSyntaxError: unexpected EOF while parsing
|
229
|
+
"""
|
230
|
+
|
231
|
+
|
232
|
+
class MDTypeError(MDException):
|
233
|
+
"""Raised when an operation is applied to an inappropriate type.
|
234
|
+
|
235
|
+
This exception is raised when an operation or function is applied to
|
236
|
+
an object of inappropriate type. It can occur during parsing when
|
237
|
+
type validation fails.
|
238
|
+
|
239
|
+
Example:
|
240
|
+
>>> "string" + 5
|
241
|
+
Traceback (most recent call last):
|
242
|
+
...
|
243
|
+
MDTypeError: can only concatenate str (not "int") to str
|
244
|
+
|
245
|
+
>>> len(42)
|
246
|
+
Traceback (most recent call last):
|
247
|
+
...
|
248
|
+
MDTypeError: object of type 'int' has no len()
|
249
|
+
"""
|
250
|
+
|
251
|
+
def __init__(self, message: str | ErrorTemplate, line: int = 0, column: int = 0, **kwargs: Any) -> None:
|
252
|
+
"""Initialize type error.
|
253
|
+
|
254
|
+
Args:
|
255
|
+
message: Error message string or ErrorTemplate
|
256
|
+
line: Line number where error occurred
|
257
|
+
column: Column position where error occurred
|
258
|
+
**kwargs: Additional template parameters if message is ErrorTemplate
|
259
|
+
"""
|
260
|
+
if isinstance(message, str):
|
261
|
+
# Create a simple ErrorTemplate from the string
|
262
|
+
from machine_dialect.errors.messages import ErrorTemplate
|
263
|
+
|
264
|
+
template = ErrorTemplate(message)
|
265
|
+
super().__init__(template, line, column, **kwargs)
|
266
|
+
else:
|
267
|
+
super().__init__(message, line, column, **kwargs)
|
268
|
+
|
269
|
+
|
270
|
+
class MDValueError(MDException):
|
271
|
+
"""Raised when a value is inappropriate for the operation.
|
272
|
+
|
273
|
+
This exception is raised when an operation or function receives an
|
274
|
+
argument that has the right type but an inappropriate value. It can
|
275
|
+
occur during parsing when value validation fails.
|
276
|
+
|
277
|
+
Example:
|
278
|
+
>>> int("not a number")
|
279
|
+
Traceback (most recent call last):
|
280
|
+
...
|
281
|
+
MDValueError: invalid literal for int() with base 10: 'not a number'
|
282
|
+
|
283
|
+
>>> list.remove([1, 2, 3], 4)
|
284
|
+
Traceback (most recent call last):
|
285
|
+
...
|
286
|
+
MDValueError: list.remove(x): x not in list
|
287
|
+
"""
|
288
|
+
|
289
|
+
|
290
|
+
class MDUninitializedError(MDException):
|
291
|
+
"""Raised when a variable is used before being initialized.
|
292
|
+
|
293
|
+
This exception is raised during semantic analysis when a variable
|
294
|
+
that has been defined but not yet assigned a value is used in an
|
295
|
+
expression or assignment.
|
296
|
+
|
297
|
+
Example:
|
298
|
+
>>> Define `x` as Whole Number.
|
299
|
+
>>> Set `y` to `x`.
|
300
|
+
Traceback (most recent call last):
|
301
|
+
...
|
302
|
+
MDUninitializedError: Variable 'x' is used before being initialized
|
303
|
+
"""
|
304
|
+
|
305
|
+
def __init__(self, message: str | ErrorTemplate, line: int = 0, position: int = 0, **kwargs: Any) -> None:
|
306
|
+
"""Initialize uninitialized variable error.
|
307
|
+
|
308
|
+
Args:
|
309
|
+
message: Error message string or ErrorTemplate
|
310
|
+
line: Line number where error occurred
|
311
|
+
position: Column position where error occurred
|
312
|
+
**kwargs: Additional template parameters if message is ErrorTemplate
|
313
|
+
"""
|
314
|
+
if isinstance(message, str):
|
315
|
+
# Create a simple ErrorTemplate from the string
|
316
|
+
from machine_dialect.errors.messages import ErrorTemplate
|
317
|
+
|
318
|
+
template = ErrorTemplate(message)
|
319
|
+
super().__init__(template, line, position, **kwargs)
|
320
|
+
else:
|
321
|
+
super().__init__(message, line, position, **kwargs)
|
322
|
+
|
323
|
+
|
324
|
+
class MDRuntimeError(Exception):
|
325
|
+
"""Machine Dialectâ„¢ Runtime Error.
|
326
|
+
|
327
|
+
Raised during runtime execution with optional source location.
|
328
|
+
This is used for errors that occur during MIR interpretation or VM execution.
|
329
|
+
|
330
|
+
Note: This inherits from Python's Exception (not MDException) because
|
331
|
+
it represents runtime errors that need to be caught by Python's exception
|
332
|
+
handling mechanism.
|
333
|
+
"""
|
334
|
+
|
335
|
+
def __init__(
|
336
|
+
self,
|
337
|
+
message: str,
|
338
|
+
line: int | None = None,
|
339
|
+
column: int | None = None,
|
340
|
+
filename: str | None = None,
|
341
|
+
) -> None:
|
342
|
+
"""Initialize runtime error.
|
343
|
+
|
344
|
+
Args:
|
345
|
+
message: Error message string.
|
346
|
+
line: Line number where error occurred (None if unknown).
|
347
|
+
column: Column position where error occurred (None if unknown).
|
348
|
+
filename: Source file name (None if unknown).
|
349
|
+
"""
|
350
|
+
self.message = message
|
351
|
+
self.line = line
|
352
|
+
self.column = column
|
353
|
+
self.filename = filename or "<standard-input>"
|
354
|
+
super().__init__(str(self))
|
355
|
+
|
356
|
+
def __str__(self) -> str:
|
357
|
+
"""Return formatted error message with location."""
|
358
|
+
parts = []
|
359
|
+
if self.filename != "<standard-input>":
|
360
|
+
parts.append(f'File "{self.filename}"')
|
361
|
+
if self.line is not None and self.line > 0:
|
362
|
+
parts.append(f"line {self.line}")
|
363
|
+
if self.column is not None and self.column > 0:
|
364
|
+
parts.append(f"column {self.column}")
|
365
|
+
|
366
|
+
location = ", ".join(parts)
|
367
|
+
if location:
|
368
|
+
return f"{location}: {self.message}"
|
369
|
+
return self.message
|
@@ -0,0 +1,82 @@
|
|
1
|
+
from string import Template
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
|
5
|
+
class ErrorTemplate(Template):
|
6
|
+
"""Custom template class that prevents direct string usage in error messages.
|
7
|
+
|
8
|
+
DO NOT USE THIS CLASS DIRECTLY, USE THE CONSTANTS DEFINED BELOW"""
|
9
|
+
|
10
|
+
def format(self, **kwargs: Any) -> str:
|
11
|
+
"""Format the template with keyword arguments.
|
12
|
+
|
13
|
+
This is a more Pythonic alternative to substitute().
|
14
|
+
"""
|
15
|
+
return self.substitute(**kwargs)
|
16
|
+
|
17
|
+
|
18
|
+
# NameError
|
19
|
+
NAME_UNDEFINED = ErrorTemplate("Name '$name' is not defined")
|
20
|
+
VARIABLE_NOT_DEFINED = ErrorTemplate(
|
21
|
+
"Variable '$name' is not defined. Use 'Define `$name` as <type>.' to define it first"
|
22
|
+
)
|
23
|
+
VARIABLE_ALREADY_DEFINED = ErrorTemplate(
|
24
|
+
"Variable '$name' is already defined at line $original_line. Cannot redefine variables in the same scope"
|
25
|
+
)
|
26
|
+
ASSIGNMENT_TYPE_MISMATCH = ErrorTemplate(
|
27
|
+
"Cannot assign $actual_type value to variable '$variable' of type $expected_type"
|
28
|
+
)
|
29
|
+
UNEXPECTED_TOKEN = ErrorTemplate(
|
30
|
+
"Unexpected '$token_literal'. Expected a '$expected_token_type', but a got a '$received_token_type'"
|
31
|
+
)
|
32
|
+
INVALID_INTEGER_LITERAL = ErrorTemplate("Invalid integer literal: '$literal'")
|
33
|
+
INVALID_FLOAT_LITERAL = ErrorTemplate("Invalid float literal: '$literal'")
|
34
|
+
NO_PARSE_FUNCTION = ErrorTemplate("No suitable parse function was found to handle '$literal'")
|
35
|
+
EXPECTED_EXPRESSION_AFTER_OPERATOR = ErrorTemplate("expected expression after operator '$operator', got $got")
|
36
|
+
UNEXPECTED_TOKEN_AT_START = ErrorTemplate("unexpected token '$token' at start of expression")
|
37
|
+
EXPECTED_EXPRESSION = ErrorTemplate("expected expression, got $got")
|
38
|
+
|
39
|
+
# Block and control flow errors
|
40
|
+
EMPTY_IF_CONSEQUENCE = ErrorTemplate("If statement must have a non-empty consequence block")
|
41
|
+
EMPTY_ELSE_BLOCK = ErrorTemplate("Else/otherwise block must not be empty. If no alternative is needed, omit it.")
|
42
|
+
EMPTY_WHILE_BODY = ErrorTemplate("While loop must have a non-empty body block")
|
43
|
+
EMPTY_FOR_EACH_BODY = ErrorTemplate("For-each loop must have a non-empty body block")
|
44
|
+
EXPECTED_DETAILS_CLOSE = ErrorTemplate("Expected </details> tag after action body, got $token_type")
|
45
|
+
EXPECTED_BLOCK_MARKER = ErrorTemplate("Expected block marker '>', got $token_type")
|
46
|
+
EXPECTED_PREFIX_OPERATOR = ErrorTemplate("Expected prefix operator, got $token_type")
|
47
|
+
MISSING_DEPTH_TRANSITION = ErrorTemplate(
|
48
|
+
"After nested blocks ($nested_depth), add a blank line with just '$parent_depth' "
|
49
|
+
"before continuing at the parent depth. Found '$token_type' at line $line"
|
50
|
+
)
|
51
|
+
UNEXPECTED_BLOCK_DEPTH = ErrorTemplate("Unexpected block depth: expected $expected '>' but got $actual")
|
52
|
+
|
53
|
+
# Collection and list errors
|
54
|
+
INVALID_NAMED_LIST_KEY = ErrorTemplate("Named list keys must be string literals. Got $literal")
|
55
|
+
|
56
|
+
# Use statement errors
|
57
|
+
EXPECTED_FUNCTION_NAME = ErrorTemplate("Expected identifier for function name, got $token_type")
|
58
|
+
EXPECTED_IDENTIFIER_FOR_NAMED_ARG = ErrorTemplate("Expected identifier for named argument, got $type_name")
|
59
|
+
POSITIONAL_AFTER_NAMED = ErrorTemplate("Positional arguments cannot appear after named arguments")
|
60
|
+
INVALID_ARGUMENT_VALUE = ErrorTemplate("Invalid argument value: '$literal'")
|
61
|
+
MISSING_COMMA_BETWEEN_ARGS = ErrorTemplate("Expected comma between arguments")
|
62
|
+
|
63
|
+
# Generic parser errors
|
64
|
+
EXPECTED_TOKEN_AFTER = ErrorTemplate("Expected $expected after $after")
|
65
|
+
EXPECTED_IDENTIFIER_AFTER = ErrorTemplate("Expected $what identifier after $after")
|
66
|
+
EXPECTED_TOKEN = ErrorTemplate("Expected $token, got $got_token_type")
|
67
|
+
ILLEGAL_CHARACTER = ErrorTemplate("Expected $expected but found illegal character '$character'")
|
68
|
+
ILLEGAL_TOKEN = ErrorTemplate("Illegal token: '$token'")
|
69
|
+
UNEXPECTED_STATEMENT = ErrorTemplate("Unexpected statement type: $type")
|
70
|
+
UNHANDLED_OPERATION = ErrorTemplate("Unhandled $what operation: $operation")
|
71
|
+
INVALID_TYPE_NAME = ErrorTemplate("'$name' is not a valid type name. Expected one of: $valid_types")
|
72
|
+
|
73
|
+
# Interpreter errors
|
74
|
+
UNKNOWN_PREFIX_OPERATOR = ErrorTemplate("Unknown prefix operator: $operator")
|
75
|
+
UNKNOWN_INFIX_OPERATOR = ErrorTemplate("Unknown infix operator: $operator")
|
76
|
+
TYPE_MISMATCH = ErrorTemplate(
|
77
|
+
"Type mismatch: cannot apply operator '$operator' to operands of type '$left_type' and '$right_type'"
|
78
|
+
)
|
79
|
+
UNSUPPORTED_OPERATION = ErrorTemplate("Unsupported operation: '$operation' on type '$type'")
|
80
|
+
DIVISION_BY_ZERO = ErrorTemplate("Division by zero")
|
81
|
+
UNSUPPORTED_OPERAND_TYPE = ErrorTemplate("Unsupported operand type(s) for $operator: '$left_type' and '$right_type'")
|
82
|
+
UNSUPPORTED_UNARY_OPERAND = ErrorTemplate("Unsupported operand type for unary $operator: '$type'")
|
File without changes
|