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,270 @@
|
|
1
|
+
"""Type system for compile-time type checking in Machine Dialect™.
|
2
|
+
|
3
|
+
This module provides the type system used during compilation for:
|
4
|
+
- Type checking variable definitions
|
5
|
+
- Validating assignments
|
6
|
+
- Union type support
|
7
|
+
- Type compatibility checking
|
8
|
+
|
9
|
+
IMPORTANT: This is for compile-time checking. Runtime types are in runtime/types.py.
|
10
|
+
"""
|
11
|
+
|
12
|
+
from dataclasses import dataclass
|
13
|
+
from enum import Enum, auto
|
14
|
+
from typing import Any
|
15
|
+
|
16
|
+
|
17
|
+
class MDType(Enum):
|
18
|
+
"""Machine Dialect™ type enumeration for compile-time type checking.
|
19
|
+
|
20
|
+
Maps to the language's type keywords and provides type compatibility rules.
|
21
|
+
"""
|
22
|
+
|
23
|
+
TEXT = auto() # "Text" keyword
|
24
|
+
WHOLE_NUMBER = auto() # "Whole Number" keyword
|
25
|
+
FLOAT = auto() # "Float" keyword
|
26
|
+
NUMBER = auto() # "Number" keyword (integer or float)
|
27
|
+
YES_NO = auto() # "Yes/No" keyword (boolean)
|
28
|
+
URL = auto() # "URL" keyword
|
29
|
+
DATE = auto() # "Date" keyword
|
30
|
+
DATETIME = auto() # "DateTime" keyword
|
31
|
+
TIME = auto() # "Time" keyword
|
32
|
+
LIST = auto() # "List" keyword (generic list)
|
33
|
+
UNORDERED_LIST = auto() # Unordered list (dash markers)
|
34
|
+
ORDERED_LIST = auto() # Ordered list (numbered markers)
|
35
|
+
NAMED_LIST = auto() # Named list (dictionary with colon syntax)
|
36
|
+
EMPTY = auto() # "Empty" keyword (null/none)
|
37
|
+
ANY = auto() # "Any" keyword (future, dynamic type)
|
38
|
+
|
39
|
+
|
40
|
+
# Mapping from type names (as they appear in source) to MDType enum
|
41
|
+
TYPE_NAME_MAP = {
|
42
|
+
"Text": MDType.TEXT,
|
43
|
+
"Whole Number": MDType.WHOLE_NUMBER,
|
44
|
+
"Float": MDType.FLOAT,
|
45
|
+
"Number": MDType.NUMBER,
|
46
|
+
"Yes/No": MDType.YES_NO,
|
47
|
+
"URL": MDType.URL,
|
48
|
+
"Date": MDType.DATE,
|
49
|
+
"DateTime": MDType.DATETIME,
|
50
|
+
"Time": MDType.TIME,
|
51
|
+
"List": MDType.LIST,
|
52
|
+
"Unordered List": MDType.UNORDERED_LIST,
|
53
|
+
"Ordered List": MDType.ORDERED_LIST,
|
54
|
+
"Named List": MDType.NAMED_LIST,
|
55
|
+
"Empty": MDType.EMPTY,
|
56
|
+
"Any": MDType.ANY,
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
# Reverse mapping for error messages
|
61
|
+
TYPE_DISPLAY_NAMES = {
|
62
|
+
MDType.TEXT: "Text",
|
63
|
+
MDType.WHOLE_NUMBER: "Whole Number",
|
64
|
+
MDType.FLOAT: "Float",
|
65
|
+
MDType.NUMBER: "Number",
|
66
|
+
MDType.YES_NO: "Yes/No",
|
67
|
+
MDType.URL: "URL",
|
68
|
+
MDType.DATE: "Date",
|
69
|
+
MDType.DATETIME: "DateTime",
|
70
|
+
MDType.TIME: "Time",
|
71
|
+
MDType.LIST: "List",
|
72
|
+
MDType.UNORDERED_LIST: "Unordered List",
|
73
|
+
MDType.ORDERED_LIST: "Ordered List",
|
74
|
+
MDType.NAMED_LIST: "Named List",
|
75
|
+
MDType.EMPTY: "Empty",
|
76
|
+
MDType.ANY: "Any",
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
@dataclass
|
81
|
+
class TypeSpec:
|
82
|
+
"""Type specification for a variable, supporting union types.
|
83
|
+
|
84
|
+
Attributes:
|
85
|
+
types: List of allowed types (for union types)
|
86
|
+
"""
|
87
|
+
|
88
|
+
types: list[MDType]
|
89
|
+
|
90
|
+
def __init__(self, type_names: list[str]) -> None:
|
91
|
+
"""Initialize TypeSpec from type name strings.
|
92
|
+
|
93
|
+
Args:
|
94
|
+
type_names: List of type names as strings (e.g., ["Whole Number", "Text"])
|
95
|
+
"""
|
96
|
+
self.types = []
|
97
|
+
for name in type_names:
|
98
|
+
md_type = get_type_from_name(name)
|
99
|
+
if md_type:
|
100
|
+
self.types.append(md_type)
|
101
|
+
|
102
|
+
def allows_type(self, md_type: MDType) -> bool:
|
103
|
+
"""Check if this TypeSpec allows the given type.
|
104
|
+
|
105
|
+
Args:
|
106
|
+
md_type: The type to check
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
True if type is allowed, False otherwise
|
110
|
+
"""
|
111
|
+
# ANY type allows everything
|
112
|
+
if MDType.ANY in self.types:
|
113
|
+
return True
|
114
|
+
|
115
|
+
# Check direct membership
|
116
|
+
if md_type in self.types:
|
117
|
+
return True
|
118
|
+
|
119
|
+
# Special case: Number allows both Whole Number and Float
|
120
|
+
if MDType.NUMBER in self.types:
|
121
|
+
if md_type in (MDType.WHOLE_NUMBER, MDType.FLOAT):
|
122
|
+
return True
|
123
|
+
|
124
|
+
# Special case: Whole Number/Float are assignable to Number
|
125
|
+
# (This is for when we have a Number variable and assign int/float)
|
126
|
+
# But this is handled by is_assignable_to, not here
|
127
|
+
|
128
|
+
return False
|
129
|
+
|
130
|
+
def __str__(self) -> str:
|
131
|
+
"""Return human-readable type specification."""
|
132
|
+
if len(self.types) == 1:
|
133
|
+
return TYPE_DISPLAY_NAMES[self.types[0]]
|
134
|
+
return " or ".join(TYPE_DISPLAY_NAMES[t] for t in self.types)
|
135
|
+
|
136
|
+
|
137
|
+
def get_type_from_name(name: str) -> MDType | None:
|
138
|
+
"""Convert type name string to MDType enum.
|
139
|
+
|
140
|
+
Args:
|
141
|
+
name: Type name as it appears in source code
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
Corresponding MDType or None if not recognized
|
145
|
+
"""
|
146
|
+
return TYPE_NAME_MAP.get(name)
|
147
|
+
|
148
|
+
|
149
|
+
def get_type_from_value(value: Any) -> MDType | None:
|
150
|
+
"""Determine the MDType of a literal value during compilation.
|
151
|
+
|
152
|
+
Args:
|
153
|
+
value: The value to determine the type of
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
The MDType of the value or None if unknown
|
157
|
+
"""
|
158
|
+
# This is for compile-time type checking of literals
|
159
|
+
# The value here would typically be from AST literal nodes
|
160
|
+
|
161
|
+
if value is None or (hasattr(value, "value") and value.value is None):
|
162
|
+
return MDType.EMPTY
|
163
|
+
|
164
|
+
# Check AST literal nodes
|
165
|
+
if hasattr(value, "__class__"):
|
166
|
+
class_name = value.__class__.__name__
|
167
|
+
|
168
|
+
if class_name == "WholeNumberLiteral":
|
169
|
+
return MDType.WHOLE_NUMBER
|
170
|
+
elif class_name == "FloatLiteral":
|
171
|
+
return MDType.FLOAT
|
172
|
+
elif class_name == "StringLiteral":
|
173
|
+
# Check if it's a URL
|
174
|
+
if hasattr(value, "value") and isinstance(value.value, str):
|
175
|
+
if value.value.startswith(("http://", "https://", "ftp://", "file://")):
|
176
|
+
return MDType.URL
|
177
|
+
return MDType.TEXT
|
178
|
+
elif class_name == "YesNoLiteral":
|
179
|
+
return MDType.YES_NO
|
180
|
+
elif class_name == "EmptyLiteral":
|
181
|
+
return MDType.EMPTY
|
182
|
+
elif class_name == "URLLiteral":
|
183
|
+
return MDType.URL
|
184
|
+
elif class_name == "UnorderedListLiteral":
|
185
|
+
return MDType.UNORDERED_LIST
|
186
|
+
elif class_name == "OrderedListLiteral":
|
187
|
+
return MDType.ORDERED_LIST
|
188
|
+
elif class_name == "NamedListLiteral":
|
189
|
+
return MDType.NAMED_LIST
|
190
|
+
|
191
|
+
# Fallback to Python types (for testing or when we have actual values)
|
192
|
+
if isinstance(value, bool):
|
193
|
+
return MDType.YES_NO
|
194
|
+
elif isinstance(value, int):
|
195
|
+
return MDType.WHOLE_NUMBER
|
196
|
+
elif isinstance(value, float):
|
197
|
+
return MDType.FLOAT
|
198
|
+
elif isinstance(value, str):
|
199
|
+
if value.startswith(("http://", "https://", "ftp://", "file://")):
|
200
|
+
return MDType.URL
|
201
|
+
return MDType.TEXT
|
202
|
+
elif isinstance(value, list):
|
203
|
+
return MDType.LIST # Generic list for Python lists
|
204
|
+
elif isinstance(value, dict):
|
205
|
+
return MDType.NAMED_LIST # Dictionary maps to named list
|
206
|
+
elif value == "empty" or value is None:
|
207
|
+
return MDType.EMPTY
|
208
|
+
|
209
|
+
return None
|
210
|
+
|
211
|
+
|
212
|
+
def is_assignable_to(value_type: MDType, target_type: MDType) -> bool:
|
213
|
+
"""Check if a value of one type can be assigned to a variable of another type.
|
214
|
+
|
215
|
+
This implements the Machine Dialect™ type compatibility rules.
|
216
|
+
NO implicit conversions are allowed per the spec.
|
217
|
+
|
218
|
+
Args:
|
219
|
+
value_type: The type of the value being assigned
|
220
|
+
target_type: The type of the variable being assigned to
|
221
|
+
|
222
|
+
Returns:
|
223
|
+
True if assignment is allowed, False otherwise
|
224
|
+
"""
|
225
|
+
# Exact match is always allowed
|
226
|
+
if value_type == target_type:
|
227
|
+
return True
|
228
|
+
|
229
|
+
# ANY type can accept anything
|
230
|
+
if target_type == MDType.ANY:
|
231
|
+
return True
|
232
|
+
|
233
|
+
# Number type can accept Whole Number or Float
|
234
|
+
if target_type == MDType.NUMBER:
|
235
|
+
if value_type in (MDType.WHOLE_NUMBER, MDType.FLOAT):
|
236
|
+
return True
|
237
|
+
|
238
|
+
# Empty can be assigned to any type (null/none value)
|
239
|
+
if value_type == MDType.EMPTY:
|
240
|
+
return True
|
241
|
+
|
242
|
+
# NO other implicit conversions per spec
|
243
|
+
return False
|
244
|
+
|
245
|
+
|
246
|
+
def check_type_compatibility(
|
247
|
+
value_type: MDType,
|
248
|
+
type_spec: TypeSpec,
|
249
|
+
) -> tuple[bool, str | None]:
|
250
|
+
"""Check if a value type is compatible with a type specification.
|
251
|
+
|
252
|
+
Args:
|
253
|
+
value_type: The type of the value being checked
|
254
|
+
type_spec: The type specification to check against
|
255
|
+
|
256
|
+
Returns:
|
257
|
+
Tuple of (is_compatible, error_message)
|
258
|
+
error_message is None if compatible
|
259
|
+
"""
|
260
|
+
# Check each type in the union
|
261
|
+
for allowed_type in type_spec.types:
|
262
|
+
if is_assignable_to(value_type, allowed_type):
|
263
|
+
return (True, None)
|
264
|
+
|
265
|
+
# Not compatible with any type in the union
|
266
|
+
value_name = TYPE_DISPLAY_NAMES[value_type]
|
267
|
+
spec_name = str(type_spec)
|
268
|
+
error = f"Cannot assign {value_name} value to variable of type {spec_name}"
|
269
|
+
|
270
|
+
return (False, error)
|
@@ -0,0 +1,128 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: machine-dialect
|
3
|
+
Version: 0.1.0a1
|
4
|
+
Summary: Machine Dialect™ - Natural language programming in Markdown
|
5
|
+
Author: Lajara AI, LLC
|
6
|
+
Project-URL: Homepage, https://github.com/kennylajara/machine-dialect
|
7
|
+
Project-URL: Bug Tracker, https://github.com/kennylajara/machine-dialect/issues
|
8
|
+
Keywords: programming-language,natural-language,markdown,compiler
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
10
|
+
Classifier: Intended Audience :: Developers
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
17
|
+
Classifier: Topic :: Software Development :: Code Generators
|
18
|
+
Classifier: Topic :: Software Development :: Compilers
|
19
|
+
Classifier: Topic :: Software Development :: Interpreters
|
20
|
+
Requires-Python: >=3.10
|
21
|
+
Description-Content-Type: text/markdown
|
22
|
+
License-File: LICENSE
|
23
|
+
Requires-Dist: rfc3986>=2.0.0
|
24
|
+
Requires-Dist: click>=8.1.0
|
25
|
+
Requires-Dist: lark>=1.2.2
|
26
|
+
Requires-Dist: openai>=1.99.9
|
27
|
+
Requires-Dist: machine-dialect-vm>=0.1.0a1
|
28
|
+
Dynamic: license-file
|
29
|
+
|
30
|
+
# Machine Dialect™
|
31
|
+
|
32
|
+
The **Machine Dialect™ programming language** is designed to look like natural language and feel
|
33
|
+
like structured documentation. It is written in Markdown and intended to be both human-friendly
|
34
|
+
and AI-native — readable by people, generatable and parsable by machines.
|
35
|
+
|
36
|
+
> ⚠️ **ALPHA VERSION** ⚠️
|
37
|
+
>
|
38
|
+
> The Machine Dialect™ language is currently in **ALPHA** stage. We are rapidly iterating on the language
|
39
|
+
> design and implementation. During this phase:
|
40
|
+
>
|
41
|
+
> - **Breaking changes will be frequent** and without deprecation warnings
|
42
|
+
> - The syntax and semantics are still evolving based on user feedback
|
43
|
+
> - APIs and compiler behavior may change between any versions
|
44
|
+
> - No backward compatibility is maintained during alpha
|
45
|
+
>
|
46
|
+
> We encourage experimentation and feedback, but please be aware that code written today
|
47
|
+
> may require updates to work with future versions.
|
48
|
+
|
49
|
+
## Table of Contents
|
50
|
+
|
51
|
+
- [Why Another Programming Language?](#why-another-programming-language)
|
52
|
+
- [Installation](#installation)
|
53
|
+
- [Getting Started](#getting-started)
|
54
|
+
- [Contributing](#contributing)
|
55
|
+
- [License](#license)
|
56
|
+
|
57
|
+
## Why Another Programming Language?
|
58
|
+
|
59
|
+
Modern programming languages were made for humans to instruct machines. But now that machines
|
60
|
+
can understand and generate human-like language, it's time to rethink the language itself.
|
61
|
+
|
62
|
+
The Machine Dialect™ language is designed for a world where:
|
63
|
+
|
64
|
+
- **AI writes most of the code**, and humans supervise, modify, and approve
|
65
|
+
- Code is **visually readable**, even by non-programmers
|
66
|
+
- The structure of the program is as **intuitive as a document**, and lives comfortably inside
|
67
|
+
Markdown files
|
68
|
+
|
69
|
+
### The Philosophy of Machine Dialect™
|
70
|
+
|
71
|
+
- **Natural structure**: Programs are written as paragraphs, headings, lists — not brackets,
|
72
|
+
semicolons, and cryptic symbols
|
73
|
+
- **AI-first**: Syntax is deterministic enough for parsing, but optimized for LLMs to
|
74
|
+
generate and understand effortlessly
|
75
|
+
- **Human-friendly**: Uses everyday words over technical jargon. Markdown keeps everything readable,
|
76
|
+
diffable, and renderable
|
77
|
+
- **Self-documenting**: Looks like pseudocode. Reads like an explanation of what the code does
|
78
|
+
|
79
|
+
## Installation
|
80
|
+
|
81
|
+
### From PyPI (Recommended)
|
82
|
+
|
83
|
+
```bash
|
84
|
+
pip install machine-dialect
|
85
|
+
```
|
86
|
+
|
87
|
+
### From Source
|
88
|
+
|
89
|
+
For development installation, please see our [Contributing Guide](CONTRIBUTING.md#development-setup)
|
90
|
+
for detailed setup instructions.
|
91
|
+
|
92
|
+
## Getting started
|
93
|
+
|
94
|
+
### Writing Your First Program
|
95
|
+
|
96
|
+
Create a file `hello.md`:
|
97
|
+
|
98
|
+
> Define `greeting` as _Text_.\
|
99
|
+
> Set `greeting` to _"Hello, World!"_.
|
100
|
+
>
|
101
|
+
> Say `greeting`.
|
102
|
+
|
103
|
+
### Compiling and Running Programs
|
104
|
+
|
105
|
+
The Machine Dialect™ toolchain provides a complete toolchain for compiling and executing programs:
|
106
|
+
|
107
|
+
```bash
|
108
|
+
# Compile a .md file to bytecode (.mdbc)
|
109
|
+
python -m machine_dialect compile hello.md
|
110
|
+
|
111
|
+
# Compile with custom filename (main)
|
112
|
+
python -m machine_dialect compile hello.md -o main.mdbc
|
113
|
+
|
114
|
+
# Run a compiled bytecode file
|
115
|
+
python -m machine_dialect run hello.mdbc
|
116
|
+
|
117
|
+
# Interactive shell (REPL)
|
118
|
+
python -m machine_dialect shell
|
119
|
+
```
|
120
|
+
|
121
|
+
## Contributing
|
122
|
+
|
123
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for detailed information.
|
124
|
+
|
125
|
+
## License
|
126
|
+
|
127
|
+
This project is licensed under the Apache License, Version 2.0 - see the [LICENSE](LICENSE) file
|
128
|
+
for details.
|