multilingualprogramming 0.2.0__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.
Files changed (61) hide show
  1. multilingualprogramming/__init__.py +74 -0
  2. multilingualprogramming/__main__.py +194 -0
  3. multilingualprogramming/codegen/__init__.py +12 -0
  4. multilingualprogramming/codegen/executor.py +215 -0
  5. multilingualprogramming/codegen/python_generator.py +592 -0
  6. multilingualprogramming/codegen/repl.py +489 -0
  7. multilingualprogramming/codegen/runtime_builtins.py +308 -0
  8. multilingualprogramming/core/__init__.py +12 -0
  9. multilingualprogramming/core/ir.py +29 -0
  10. multilingualprogramming/core/lowering.py +24 -0
  11. multilingualprogramming/datetime/__init__.py +11 -0
  12. multilingualprogramming/datetime/date_parser.py +190 -0
  13. multilingualprogramming/datetime/mp_date.py +210 -0
  14. multilingualprogramming/datetime/mp_datetime.py +153 -0
  15. multilingualprogramming/datetime/mp_time.py +147 -0
  16. multilingualprogramming/datetime/resource_loader.py +18 -0
  17. multilingualprogramming/exceptions.py +158 -0
  18. multilingualprogramming/imports.py +150 -0
  19. multilingualprogramming/keyword/__init__.py +13 -0
  20. multilingualprogramming/keyword/keyword_registry.py +249 -0
  21. multilingualprogramming/keyword/keyword_validator.py +59 -0
  22. multilingualprogramming/keyword/language_pack_validator.py +110 -0
  23. multilingualprogramming/lexer/__init__.py +11 -0
  24. multilingualprogramming/lexer/lexer.py +570 -0
  25. multilingualprogramming/lexer/source_reader.py +91 -0
  26. multilingualprogramming/lexer/token.py +54 -0
  27. multilingualprogramming/lexer/token_types.py +38 -0
  28. multilingualprogramming/numeral/__init__.py +11 -0
  29. multilingualprogramming/numeral/abstract_numeral.py +232 -0
  30. multilingualprogramming/numeral/complex_numeral.py +190 -0
  31. multilingualprogramming/numeral/fraction_numeral.py +165 -0
  32. multilingualprogramming/numeral/mp_numeral.py +243 -0
  33. multilingualprogramming/numeral/numeral_converter.py +151 -0
  34. multilingualprogramming/numeral/roman_numeral.py +301 -0
  35. multilingualprogramming/numeral/unicode_numeral.py +292 -0
  36. multilingualprogramming/parser/__init__.py +28 -0
  37. multilingualprogramming/parser/ast_nodes.py +459 -0
  38. multilingualprogramming/parser/ast_printer.py +677 -0
  39. multilingualprogramming/parser/error_messages.py +75 -0
  40. multilingualprogramming/parser/parser.py +1796 -0
  41. multilingualprogramming/parser/semantic_analyzer.py +689 -0
  42. multilingualprogramming/parser/surface_normalizer.py +282 -0
  43. multilingualprogramming/resources/datetime/eras.json +23 -0
  44. multilingualprogramming/resources/datetime/formats.json +32 -0
  45. multilingualprogramming/resources/datetime/months.json +150 -0
  46. multilingualprogramming/resources/datetime/weekdays.json +90 -0
  47. multilingualprogramming/resources/parser/error_messages.json +310 -0
  48. multilingualprogramming/resources/repl/commands.json +636 -0
  49. multilingualprogramming/resources/usm/builtins_aliases.json +731 -0
  50. multilingualprogramming/resources/usm/keywords.json +1063 -0
  51. multilingualprogramming/resources/usm/operators.json +532 -0
  52. multilingualprogramming/resources/usm/schema.json +34 -0
  53. multilingualprogramming/resources/usm/surface_patterns.json +1523 -0
  54. multilingualprogramming/unicode_string.py +140 -0
  55. multilingualprogramming/version.py +9 -0
  56. multilingualprogramming-0.2.0.dist-info/METADATA +350 -0
  57. multilingualprogramming-0.2.0.dist-info/RECORD +61 -0
  58. multilingualprogramming-0.2.0.dist-info/WHEEL +5 -0
  59. multilingualprogramming-0.2.0.dist-info/entry_points.txt +3 -0
  60. multilingualprogramming-0.2.0.dist-info/licenses/LICENSE +674 -0
  61. multilingualprogramming-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,74 @@
1
+ #
2
+ # SPDX-FileCopyrightText: 2022 John Samuel <johnsamuelwrites@gmail.com>
3
+ #
4
+ # SPDX-License-Identifier: GPL-3.0-or-later
5
+ #
6
+
7
+ """multilingualprogramming is an application for multilingual programming."""
8
+
9
+ from multilingualprogramming.numeral.mp_numeral import MPNumeral
10
+ from multilingualprogramming.numeral.unicode_numeral import UnicodeNumeral
11
+ from multilingualprogramming.numeral.roman_numeral import RomanNumeral
12
+ from multilingualprogramming.numeral.complex_numeral import ComplexNumeral
13
+ from multilingualprogramming.numeral.fraction_numeral import FractionNumeral
14
+ from multilingualprogramming.numeral.numeral_converter import NumeralConverter
15
+ from multilingualprogramming.keyword.keyword_registry import KeywordRegistry
16
+ from multilingualprogramming.keyword.keyword_validator import KeywordValidator
17
+ from multilingualprogramming.keyword.language_pack_validator import (
18
+ LanguagePackValidator,
19
+ )
20
+ from multilingualprogramming.datetime.mp_date import MPDate
21
+ from multilingualprogramming.datetime.mp_time import MPTime
22
+ from multilingualprogramming.datetime.mp_datetime import MPDatetime
23
+ from multilingualprogramming.lexer.lexer import Lexer
24
+ from multilingualprogramming.lexer.token import Token
25
+ from multilingualprogramming.lexer.token_types import TokenType
26
+ from multilingualprogramming.parser.parser import Parser
27
+ from multilingualprogramming.parser.ast_printer import ASTPrinter
28
+ from multilingualprogramming.parser.semantic_analyzer import (
29
+ Symbol, Scope, SymbolTable, SemanticAnalyzer,
30
+ )
31
+ from multilingualprogramming.parser.error_messages import ErrorMessageRegistry
32
+ from multilingualprogramming.codegen.python_generator import PythonCodeGenerator
33
+ from multilingualprogramming.codegen.runtime_builtins import RuntimeBuiltins
34
+ from multilingualprogramming.codegen.executor import ProgramExecutor, ExecutionResult
35
+ from multilingualprogramming.codegen.repl import REPL
36
+ from multilingualprogramming.core.ir import CoreIRProgram
37
+ from multilingualprogramming.core.lowering import lower_to_core_ir
38
+ from multilingualprogramming.imports import (
39
+ enable_multilingual_imports, disable_multilingual_imports,
40
+ )
41
+
42
+ __all__ = [
43
+ "MPNumeral",
44
+ "UnicodeNumeral",
45
+ "RomanNumeral",
46
+ "ComplexNumeral",
47
+ "FractionNumeral",
48
+ "NumeralConverter",
49
+ "KeywordRegistry",
50
+ "KeywordValidator",
51
+ "LanguagePackValidator",
52
+ "MPDate",
53
+ "MPTime",
54
+ "MPDatetime",
55
+ "Lexer",
56
+ "Token",
57
+ "TokenType",
58
+ "Parser",
59
+ "ASTPrinter",
60
+ "Symbol",
61
+ "Scope",
62
+ "SymbolTable",
63
+ "SemanticAnalyzer",
64
+ "ErrorMessageRegistry",
65
+ "PythonCodeGenerator",
66
+ "RuntimeBuiltins",
67
+ "ProgramExecutor",
68
+ "ExecutionResult",
69
+ "REPL",
70
+ "CoreIRProgram",
71
+ "lower_to_core_ir",
72
+ "enable_multilingual_imports",
73
+ "disable_multilingual_imports",
74
+ ]
@@ -0,0 +1,194 @@
1
+ #
2
+ # SPDX-FileCopyrightText: 2024 John Samuel <johnsamuelwrites@gmail.com>
3
+ #
4
+ # SPDX-License-Identifier: GPL-3.0-or-later
5
+ #
6
+
7
+ """
8
+ CLI entry point for the multilingual programming language.
9
+
10
+ Usage:
11
+ python -m multilingualprogramming # Start REPL
12
+ python -m multilingualprogramming run <file> # Execute a file
13
+ python -m multilingualprogramming repl [--lang XX] # Start REPL
14
+ python -m multilingualprogramming compile <file> # Show generated Python
15
+ python -m multilingualprogramming smoke --lang fr # Validate one language pack
16
+ python -m multilingualprogramming smoke --all # Validate all language packs
17
+ """
18
+
19
+ import argparse
20
+ import sys
21
+
22
+ from multilingualprogramming.codegen.executor import ProgramExecutor
23
+ from multilingualprogramming.codegen.python_generator import PythonCodeGenerator
24
+ from multilingualprogramming.codegen.repl import REPL
25
+ from multilingualprogramming.keyword.language_pack_validator import (
26
+ LanguagePackValidator,
27
+ )
28
+ from multilingualprogramming.exceptions import UnsupportedLanguageError
29
+ from multilingualprogramming.lexer.lexer import Lexer
30
+ from multilingualprogramming.parser.parser import Parser
31
+ from multilingualprogramming.version import __version__
32
+
33
+
34
+ def cmd_run(args):
35
+ """Execute a multilingual source file."""
36
+
37
+ try:
38
+ with open(args.file, encoding="utf-8") as f:
39
+ source = f.read()
40
+ except FileNotFoundError:
41
+ print(f"Error: file not found: {args.file}", file=sys.stderr)
42
+ sys.exit(1)
43
+ except OSError as e:
44
+ print(f"Error: {e}", file=sys.stderr)
45
+ sys.exit(1)
46
+
47
+ executor = ProgramExecutor(language=args.lang)
48
+ result = executor.execute(source)
49
+
50
+ if result.output:
51
+ sys.stdout.write(result.output)
52
+
53
+ if not result.success:
54
+ for err in result.errors:
55
+ print(err, file=sys.stderr)
56
+ sys.exit(1)
57
+
58
+
59
+ def cmd_repl(args):
60
+ """Start the interactive REPL."""
61
+ repl = REPL(language=args.lang, show_python=args.show_python)
62
+ repl.run()
63
+
64
+
65
+ def cmd_compile(args):
66
+ """Compile a source file and print the generated Python."""
67
+
68
+ try:
69
+ with open(args.file, encoding="utf-8") as f:
70
+ source = f.read()
71
+ except FileNotFoundError:
72
+ print(f"Error: file not found: {args.file}", file=sys.stderr)
73
+ sys.exit(1)
74
+ except OSError as e:
75
+ print(f"Error: {e}", file=sys.stderr)
76
+ sys.exit(1)
77
+
78
+ lang = args.lang
79
+ lexer = Lexer(source, language=lang)
80
+ tokens = lexer.tokenize()
81
+ detected_lang = lexer.language or lang or "en"
82
+
83
+ parser = Parser(tokens, source_language=detected_lang)
84
+ program = parser.parse()
85
+
86
+ generator = PythonCodeGenerator()
87
+ python_source = generator.generate(program)
88
+ print(python_source)
89
+
90
+
91
+ def cmd_smoke(args):
92
+ """Run language-pack smoke validation checks."""
93
+ registry_validator = LanguagePackValidator()
94
+ languages = (
95
+ sorted(registry_validator.get_supported_languages())
96
+ if args.all
97
+ else [args.lang]
98
+ )
99
+
100
+ failed = False
101
+ for language in languages:
102
+ try:
103
+ errors = registry_validator.validate(language)
104
+ except UnsupportedLanguageError as exc:
105
+ failed = True
106
+ print(f"[FAIL] {language}: {exc}", file=sys.stderr)
107
+ continue
108
+
109
+ if errors:
110
+ failed = True
111
+ print(f"[FAIL] {language}", file=sys.stderr)
112
+ for error in errors:
113
+ print(f" - {error}", file=sys.stderr)
114
+ else:
115
+ print(f"[PASS] {language}")
116
+
117
+ if failed:
118
+ sys.exit(1)
119
+
120
+
121
+ def main():
122
+ """Run the CLI entry point and dispatch subcommands."""
123
+ parser = argparse.ArgumentParser(
124
+ prog="multilingual",
125
+ description="Multilingual Programming Language CLI",
126
+ )
127
+ parser.add_argument(
128
+ "--version", action="version",
129
+ version=f"%(prog)s {__version__}",
130
+ )
131
+
132
+ subparsers = parser.add_subparsers(dest="command")
133
+
134
+ # run subcommand
135
+ run_parser = subparsers.add_parser("run", help="Execute a source file")
136
+ run_parser.add_argument("file", help="Path to the source file")
137
+ run_parser.add_argument(
138
+ "--lang", default=None,
139
+ help="Source language code (e.g., en, fr, hi). Auto-detect if omitted.",
140
+ )
141
+
142
+ # repl subcommand
143
+ repl_parser = subparsers.add_parser("repl", help="Start interactive REPL")
144
+ repl_parser.add_argument(
145
+ "--lang", default=None,
146
+ help="Source language code (e.g., en, fr, hi). Auto-detect if omitted.",
147
+ )
148
+ repl_parser.add_argument(
149
+ "--show-python", action="store_true",
150
+ help="Display generated Python code before execution",
151
+ )
152
+
153
+ # compile subcommand
154
+ compile_parser = subparsers.add_parser(
155
+ "compile", help="Show generated Python code"
156
+ )
157
+ compile_parser.add_argument("file", help="Path to the source file")
158
+ compile_parser.add_argument(
159
+ "--lang", default=None,
160
+ help="Source language code (e.g., en, fr, hi). Auto-detect if omitted.",
161
+ )
162
+
163
+ # smoke subcommand
164
+ smoke_parser = subparsers.add_parser(
165
+ "smoke", help="Validate language pack(s)"
166
+ )
167
+ smoke_parser.add_argument(
168
+ "--lang", default="en",
169
+ help="Language code to validate (default: en)",
170
+ )
171
+ smoke_parser.add_argument(
172
+ "--all", action="store_true",
173
+ help="Validate all supported languages",
174
+ )
175
+
176
+ args = parser.parse_args()
177
+
178
+ if args.command == "run":
179
+ cmd_run(args)
180
+ elif args.command == "repl":
181
+ cmd_repl(args)
182
+ elif args.command == "compile":
183
+ cmd_compile(args)
184
+ elif args.command == "smoke":
185
+ cmd_smoke(args)
186
+ else:
187
+ # Default: start REPL
188
+ args.lang = None
189
+ args.show_python = False
190
+ cmd_repl(args)
191
+
192
+
193
+ if __name__ == "__main__":
194
+ main()
@@ -0,0 +1,12 @@
1
+ #
2
+ # SPDX-FileCopyrightText: 2024 John Samuel <johnsamuelwrites@gmail.com>
3
+ #
4
+ # SPDX-License-Identifier: GPL-3.0-or-later
5
+ #
6
+
7
+ """Code generation and runtime subpackage for the multilingual programming language."""
8
+
9
+ from multilingualprogramming.codegen.python_generator import PythonCodeGenerator
10
+ from multilingualprogramming.codegen.runtime_builtins import RuntimeBuiltins
11
+ from multilingualprogramming.codegen.executor import ProgramExecutor, ExecutionResult
12
+ from multilingualprogramming.codegen.repl import REPL
@@ -0,0 +1,215 @@
1
+ #
2
+ # SPDX-FileCopyrightText: 2024 John Samuel <johnsamuelwrites@gmail.com>
3
+ #
4
+ # SPDX-License-Identifier: GPL-3.0-or-later
5
+ #
6
+
7
+ """
8
+ Program executor: full pipeline from multilingual source to execution.
9
+
10
+ source (any language) -> Lexer -> Parser -> SemanticAnalyzer
11
+ -> PythonCodeGenerator -> compile + exec
12
+ """
13
+
14
+ import io
15
+ import sys
16
+
17
+ from multilingualprogramming.lexer.lexer import Lexer
18
+ from multilingualprogramming.parser.parser import Parser
19
+ from multilingualprogramming.parser.semantic_analyzer import SemanticAnalyzer
20
+ from multilingualprogramming.codegen.python_generator import PythonCodeGenerator
21
+ from multilingualprogramming.codegen.runtime_builtins import RuntimeBuiltins
22
+ from multilingualprogramming.core.lowering import lower_to_core_ir
23
+ from multilingualprogramming.imports import enable_multilingual_imports
24
+ from multilingualprogramming.exceptions import (
25
+ RuntimeExecutionError,
26
+ CodeGenerationError,
27
+ )
28
+
29
+
30
+ class ExecutionResult:
31
+ """Result of executing a multilingual program."""
32
+
33
+ def __init__(self, output="", return_value=None, python_source="",
34
+ errors=None, success=True):
35
+ self.output = output
36
+ self.return_value = return_value
37
+ self.python_source = python_source
38
+ self.errors = errors or []
39
+ self.success = success
40
+
41
+ def __repr__(self):
42
+ status = "OK" if self.success else "FAILED"
43
+ return (f"ExecutionResult({status}, "
44
+ f"output={self.output!r}, "
45
+ f"errors={self.errors!r})")
46
+
47
+
48
+ class ProgramExecutor:
49
+ """
50
+ Executes multilingual source code through the full pipeline.
51
+
52
+ Usage:
53
+ executor = ProgramExecutor(language="fr")
54
+ result = executor.execute(french_source)
55
+ print(result.output) # captured stdout
56
+ print(result.success) # True/False
57
+ """
58
+
59
+ def __init__(self, language=None, check_semantics=True):
60
+ """
61
+ Initialize the executor.
62
+
63
+ Args:
64
+ language: Source language code (e.g., "en", "fr", "hi").
65
+ If None, auto-detect from keywords.
66
+ check_semantics: Whether to run semantic analysis before
67
+ code generation. Default True.
68
+ """
69
+ self.language = language
70
+ self.check_semantics = check_semantics
71
+
72
+ def execute(self, source, capture_output=True, globals_dict=None):
73
+ """
74
+ Execute multilingual source code.
75
+
76
+ Args:
77
+ source: Multilingual source code string.
78
+ capture_output: If True, capture stdout to result.output.
79
+ If False, print to actual stdout.
80
+ globals_dict: Optional dict to merge into execution globals.
81
+
82
+ Returns:
83
+ ExecutionResult with output, generated Python source, and errors.
84
+ """
85
+ try:
86
+ # Step 1-3: Frontend to typed core representation
87
+ core_program = self.to_core_ir(source)
88
+ detected_language = core_program.source_language
89
+
90
+ # Step 4: Semantic analysis (optional)
91
+ if self.check_semantics:
92
+ analyzer = SemanticAnalyzer(
93
+ source_language=detected_language
94
+ )
95
+ # Pre-seed symbol table with runtime builtins so that
96
+ # names like print, range, len, etc. are not flagged
97
+ # as undefined.
98
+ builtins_ns = RuntimeBuiltins(detected_language).namespace()
99
+ for name in builtins_ns:
100
+ analyzer.symbol_table.define(
101
+ name, "variable", line=0, column=0
102
+ )
103
+ semantic_errors = analyzer.analyze(core_program.ast)
104
+ if semantic_errors:
105
+ return ExecutionResult(
106
+ errors=[str(e) for e in semantic_errors],
107
+ success=False,
108
+ )
109
+
110
+ # Step 5: Lowered core to Python
111
+ generator = PythonCodeGenerator()
112
+ python_source = generator.generate(core_program)
113
+
114
+ # Step 6: Execute
115
+ return self._exec_python(
116
+ python_source, detected_language,
117
+ capture_output, globals_dict
118
+ )
119
+
120
+ except (CodeGenerationError, RuntimeExecutionError) as exc:
121
+ return ExecutionResult(
122
+ errors=[str(exc)],
123
+ success=False,
124
+ )
125
+ except Exception as exc:
126
+ return ExecutionResult(
127
+ errors=[f"{type(exc).__name__}: {exc}"],
128
+ success=False,
129
+ )
130
+
131
+ def transpile(self, source):
132
+ """
133
+ Transpile multilingual source to Python without executing.
134
+
135
+ Args:
136
+ source: Multilingual source code string.
137
+
138
+ Returns:
139
+ Python source code string.
140
+
141
+ Raises:
142
+ Various exceptions on lex/parse/codegen errors.
143
+ """
144
+ core_program = self.to_core_ir(source)
145
+ generator = PythonCodeGenerator()
146
+ return generator.generate(core_program)
147
+
148
+ def to_core_ir(self, source):
149
+ """Compile source into the typed core representation."""
150
+ lexer = Lexer(source, language=self.language)
151
+ tokens = lexer.tokenize()
152
+ detected_language = lexer.language or self.language or "en"
153
+
154
+ parser = Parser(tokens, source_language=detected_language)
155
+ program = parser.parse()
156
+ return lower_to_core_ir(
157
+ program, detected_language, frontend_name="lexer_parser"
158
+ )
159
+
160
+ def _exec_python(self, python_source, language,
161
+ capture_output, globals_dict):
162
+ """Compile and execute generated Python code."""
163
+ enable_multilingual_imports()
164
+
165
+ # Build execution namespace with builtins
166
+ builtins_ns = RuntimeBuiltins(language).namespace()
167
+ exec_globals = dict(builtins_ns)
168
+
169
+ if globals_dict:
170
+ exec_globals.update(globals_dict)
171
+
172
+ # Compile for better error reporting
173
+ try:
174
+ code = compile(python_source, "<multilingual>", "exec")
175
+ except SyntaxError as exc:
176
+ return ExecutionResult(
177
+ python_source=python_source,
178
+ errors=[f"Generated Python has syntax error: {exc}"],
179
+ success=False,
180
+ )
181
+
182
+ # Execute with optional output capture
183
+ output = ""
184
+ if capture_output:
185
+ captured = io.StringIO()
186
+ old_stdout = sys.stdout
187
+ try:
188
+ sys.stdout = captured
189
+ exec(code, exec_globals) # pylint: disable=exec-used
190
+ output = captured.getvalue()
191
+ except Exception as exc:
192
+ output = captured.getvalue()
193
+ return ExecutionResult(
194
+ output=output,
195
+ python_source=python_source,
196
+ errors=[f"{type(exc).__name__}: {exc}"],
197
+ success=False,
198
+ )
199
+ finally:
200
+ sys.stdout = old_stdout
201
+ else:
202
+ try:
203
+ exec(code, exec_globals) # pylint: disable=exec-used
204
+ except Exception as exc:
205
+ return ExecutionResult(
206
+ python_source=python_source,
207
+ errors=[f"{type(exc).__name__}: {exc}"],
208
+ success=False,
209
+ )
210
+
211
+ return ExecutionResult(
212
+ output=output,
213
+ python_source=python_source,
214
+ success=True,
215
+ )