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,459 @@
1
+ #
2
+ # SPDX-FileCopyrightText: 2024 John Samuel <johnsamuelwrites@gmail.com>
3
+ #
4
+ # SPDX-License-Identifier: GPL-3.0-or-later
5
+ #
6
+ """AST node classes for the multilingual programming language."""
7
+ class ASTNode:
8
+ """Base class for all AST nodes."""
9
+ def __init__(self, line=0, column=0):
10
+ self.line = line
11
+ self.column = column
12
+ def accept(self, visitor):
13
+ """Visitor pattern dispatch."""
14
+ method_name = f"visit_{type(self).__name__}"
15
+ visitor_method = getattr(visitor, method_name, visitor.generic_visit)
16
+ return visitor_method(self)
17
+ # ---------------------------------------------------------------------------
18
+ # Program root
19
+ # ---------------------------------------------------------------------------
20
+ class Program(ASTNode):
21
+ """Root node containing a list of top-level statements."""
22
+ def __init__(self, body, line=0, column=0):
23
+ super().__init__(line, column)
24
+ self.body = body
25
+ # ---------------------------------------------------------------------------
26
+ # Literal nodes
27
+ # ---------------------------------------------------------------------------
28
+ class NumeralLiteral(ASTNode):
29
+ """Number literal (raw string from NUMERAL token)."""
30
+ def __init__(self, value, line=0, column=0):
31
+ super().__init__(line, column)
32
+ self.value = value
33
+ class StringLiteral(ASTNode):
34
+ """String literal (content without delimiters)."""
35
+ def __init__(self, value, line=0, column=0):
36
+ super().__init__(line, column)
37
+ self.value = value
38
+ class DateLiteral(ASTNode):
39
+ """Date literal from special delimiters."""
40
+ def __init__(self, value, line=0, column=0):
41
+ super().__init__(line, column)
42
+ self.value = value
43
+ class BooleanLiteral(ASTNode):
44
+ """TRUE or FALSE keyword as a literal value."""
45
+ def __init__(self, value, line=0, column=0):
46
+ super().__init__(line, column)
47
+ self.value = value
48
+ class NoneLiteral(ASTNode):
49
+ """NONE keyword as a literal value."""
50
+ class ListLiteral(ASTNode):
51
+ """List literal [a, b, c]."""
52
+ def __init__(self, elements, line=0, column=0):
53
+ super().__init__(line, column)
54
+ self.elements = elements
55
+ class DictLiteral(ASTNode):
56
+ """Dict literal {key: value, ...}."""
57
+ def __init__(self, entries, line=0, column=0):
58
+ super().__init__(line, column)
59
+ self.entries = entries
60
+ # Backward compatibility for code that expects key/value pairs only.
61
+ self.pairs = [
62
+ entry for entry in entries
63
+ if isinstance(entry, tuple) and len(entry) == 2
64
+ ]
65
+ class SetLiteral(ASTNode):
66
+ """Set literal {a, b, c}."""
67
+ def __init__(self, elements, line=0, column=0):
68
+ super().__init__(line, column)
69
+ self.elements = elements
70
+ class DictUnpackEntry(ASTNode):
71
+ """Dictionary unpacking entry: **expr."""
72
+ def __init__(self, value, line=0, column=0):
73
+ super().__init__(line, column)
74
+ self.value = value
75
+ # ---------------------------------------------------------------------------
76
+ # Expression nodes
77
+ # ---------------------------------------------------------------------------
78
+ class Identifier(ASTNode):
79
+ """Variable or name reference."""
80
+ def __init__(self, name, line=0, column=0):
81
+ super().__init__(line, column)
82
+ self.name = name
83
+ class BinaryOp(ASTNode):
84
+ """Binary operation: left op right."""
85
+ def __init__(self, left, op, right, line=0, column=0):
86
+ super().__init__(line, column)
87
+ self.left = left
88
+ self.op = op
89
+ self.right = right
90
+ class UnaryOp(ASTNode):
91
+ """Unary operation: op operand."""
92
+ def __init__(self, op, operand, line=0, column=0):
93
+ super().__init__(line, column)
94
+ self.op = op
95
+ self.operand = operand
96
+ class BooleanOp(ASTNode):
97
+ """Logical AND / OR with short-circuit semantics."""
98
+ def __init__(self, op, values, line=0, column=0):
99
+ super().__init__(line, column)
100
+ self.op = op
101
+ self.values = values
102
+ class CompareOp(ASTNode):
103
+ """Chained comparison: a < b < c."""
104
+ def __init__(self, left, comparators, line=0, column=0):
105
+ super().__init__(line, column)
106
+ self.left = left
107
+ self.comparators = comparators
108
+ class CallExpr(ASTNode):
109
+ """Function or method call: func(args)."""
110
+ def __init__(self, func, args, keywords=None, line=0, column=0):
111
+ super().__init__(line, column)
112
+ self.func = func
113
+ self.args = args
114
+ self.keywords = keywords or []
115
+ class AttributeAccess(ASTNode):
116
+ """Attribute access: obj.attr."""
117
+ def __init__(self, obj, attr, line=0, column=0):
118
+ super().__init__(line, column)
119
+ self.obj = obj
120
+ self.attr = attr
121
+ class IndexAccess(ASTNode):
122
+ """Index/subscript access: obj[index]."""
123
+ def __init__(self, obj, index, line=0, column=0):
124
+ super().__init__(line, column)
125
+ self.obj = obj
126
+ self.index = index
127
+ class LambdaExpr(ASTNode):
128
+ """Lambda expression: lambda params: body."""
129
+ def __init__(self, params, body, line=0, column=0):
130
+ super().__init__(line, column)
131
+ self.params = params
132
+ self.body = body
133
+ class YieldExpr(ASTNode):
134
+ """Yield expression: yield [from] value."""
135
+ def __init__(self, value=None, is_from=False, line=0, column=0):
136
+ super().__init__(line, column)
137
+ self.value = value
138
+ self.is_from = is_from
139
+ class AwaitExpr(ASTNode):
140
+ """Await expression: await value."""
141
+ def __init__(self, value, line=0, column=0):
142
+ super().__init__(line, column)
143
+ self.value = value
144
+ class NamedExpr(ASTNode):
145
+ """Named expression (walrus): target := value."""
146
+ def __init__(self, target, value, line=0, column=0):
147
+ super().__init__(line, column)
148
+ self.target = target
149
+ self.value = value
150
+ class ConditionalExpr(ASTNode):
151
+ """Ternary conditional: true_expr if condition else false_expr."""
152
+ def __init__(self, condition, true_expr, false_expr, line=0, column=0):
153
+ super().__init__(line, column)
154
+ self.condition = condition
155
+ self.true_expr = true_expr
156
+ self.false_expr = false_expr
157
+ # ---------------------------------------------------------------------------
158
+ # Simple statement nodes
159
+ # ---------------------------------------------------------------------------
160
+ class VariableDeclaration(ASTNode):
161
+ """Variable declaration: let x = expr / const PI = 3.14."""
162
+ def __init__(self, name, value, is_const=False, line=0, column=0):
163
+ super().__init__(line, column)
164
+ self.name = name
165
+ self.value = value
166
+ self.is_const = is_const
167
+ class Assignment(ASTNode):
168
+ """Assignment: target = value (also +=, -=, *=, /=)."""
169
+ def __init__(self, target, value, op="=", line=0, column=0):
170
+ super().__init__(line, column)
171
+ self.target = target
172
+ self.value = value
173
+ self.op = op
174
+ class AnnAssignment(ASTNode):
175
+ """Annotated assignment: x: T [= value]."""
176
+ def __init__(self, target, annotation, value=None, line=0, column=0):
177
+ super().__init__(line, column)
178
+ self.target = target
179
+ self.annotation = annotation
180
+ self.value = value
181
+ class ExpressionStatement(ASTNode):
182
+ """A bare expression used as a statement."""
183
+ def __init__(self, expression, line=0, column=0):
184
+ super().__init__(line, column)
185
+ self.expression = expression
186
+ class PassStatement(ASTNode):
187
+ """Pass/no-op statement."""
188
+ class ReturnStatement(ASTNode):
189
+ """Return statement: return value."""
190
+ def __init__(self, value=None, line=0, column=0):
191
+ super().__init__(line, column)
192
+ self.value = value
193
+ class BreakStatement(ASTNode):
194
+ """Break statement."""
195
+ class ContinueStatement(ASTNode):
196
+ """Continue statement."""
197
+ class RaiseStatement(ASTNode):
198
+ """Raise statement: raise expression [from cause]."""
199
+ def __init__(self, value=None, cause=None, line=0, column=0):
200
+ super().__init__(line, column)
201
+ self.value = value
202
+ self.cause = cause
203
+ class DelStatement(ASTNode):
204
+ """Delete statement: del target."""
205
+ def __init__(self, target, line=0, column=0):
206
+ super().__init__(line, column)
207
+ self.target = target
208
+ class GlobalStatement(ASTNode):
209
+ """Global declaration: global x, y."""
210
+ def __init__(self, names, line=0, column=0):
211
+ super().__init__(line, column)
212
+ self.names = names
213
+ class LocalStatement(ASTNode):
214
+ """Local (nonlocal) declaration: local x, y."""
215
+ def __init__(self, names, line=0, column=0):
216
+ super().__init__(line, column)
217
+ self.names = names
218
+ class YieldStatement(ASTNode):
219
+ """Yield as a statement: yield [from] value."""
220
+ def __init__(self, value=None, is_from=False, line=0, column=0):
221
+ super().__init__(line, column)
222
+ self.value = value
223
+ self.is_from = is_from
224
+ # ---------------------------------------------------------------------------
225
+ # Compound statement nodes
226
+ # ---------------------------------------------------------------------------
227
+ class IfStatement(ASTNode):
228
+ """If/elif/else block."""
229
+ def __init__(self, condition, body, elif_clauses=None,
230
+ else_body=None, line=0, column=0):
231
+ super().__init__(line, column)
232
+ self.condition = condition
233
+ self.body = body
234
+ self.elif_clauses = elif_clauses or []
235
+ self.else_body = else_body
236
+ class WhileLoop(ASTNode):
237
+ """While loop: while condition: body [else: else_body]."""
238
+ def __init__(self, condition, body, else_body=None, line=0, column=0):
239
+ super().__init__(line, column)
240
+ self.condition = condition
241
+ self.body = body
242
+ self.else_body = else_body
243
+ class ForLoop(ASTNode):
244
+ """For loop: for target in iterable: body [else: else_body]."""
245
+ def __init__(self, target, iterable, body, is_async=False,
246
+ else_body=None, line=0, column=0):
247
+ super().__init__(line, column)
248
+ self.target = target
249
+ self.iterable = iterable
250
+ self.body = body
251
+ self.is_async = is_async
252
+ self.else_body = else_body
253
+ class FunctionDef(ASTNode):
254
+ """Function definition: def name(params): body."""
255
+ def __init__(self, name, params, body, decorators=None,
256
+ return_annotation=None, is_async=False, **kwargs):
257
+ line = kwargs.get("line", 0)
258
+ column = kwargs.get("column", 0)
259
+ super().__init__(line, column)
260
+ self.name = name
261
+ self.params = params
262
+ self.body = body
263
+ self.decorators = decorators or []
264
+ self.return_annotation = return_annotation
265
+ self.is_async = is_async
266
+ class ClassDef(ASTNode):
267
+ """Class definition: class Name(bases): body."""
268
+ def __init__(self, name, bases, body, decorators=None,
269
+ line=0, column=0):
270
+ super().__init__(line, column)
271
+ self.name = name
272
+ self.bases = bases
273
+ self.body = body
274
+ self.decorators = decorators or []
275
+ class TryStatement(ASTNode):
276
+ """Try/except/else/finally block."""
277
+ def __init__(self, body, handlers=None, else_body=None, finally_body=None,
278
+ line=0, column=0):
279
+ super().__init__(line, column)
280
+ self.body = body
281
+ self.handlers = handlers or []
282
+ self.else_body = else_body
283
+ self.finally_body = finally_body
284
+ class ExceptHandler(ASTNode):
285
+ """Single except clause: except Type as name: body."""
286
+ def __init__(self, exc_type=None, name=None, body=None,
287
+ line=0, column=0):
288
+ super().__init__(line, column)
289
+ self.exc_type = exc_type
290
+ self.name = name
291
+ self.body = body or []
292
+ class MatchStatement(ASTNode):
293
+ """Match/case block."""
294
+ def __init__(self, subject, cases, line=0, column=0):
295
+ super().__init__(line, column)
296
+ self.subject = subject
297
+ self.cases = cases
298
+ class CaseClause(ASTNode):
299
+ """Single case or default clause with optional guard."""
300
+ def __init__(self, pattern=None, body=None, is_default=False,
301
+ guard=None, line=0, column=0):
302
+ super().__init__(line, column)
303
+ self.pattern = pattern
304
+ self.body = body or []
305
+ self.is_default = is_default
306
+ self.guard = guard
307
+ class WithStatement(ASTNode):
308
+ """With statement: with expr as name, ...: body."""
309
+ def __init__(self, items, name=None, body=None, is_async=False, line=0, column=0):
310
+ super().__init__(line, column)
311
+ # Backward compatibility: WithStatement(expr, name=..., body=...)
312
+ if not isinstance(items, list):
313
+ items = [(items, name)]
314
+ self.items = items
315
+ # Backward compatibility with old single-item attributes.
316
+ self.context_expr = items[0][0] if items else None
317
+ self.name = items[0][1] if items else None
318
+ self.body = body or []
319
+ self.is_async = is_async
320
+ # ---------------------------------------------------------------------------
321
+ # Import nodes
322
+ # ---------------------------------------------------------------------------
323
+ class ImportStatement(ASTNode):
324
+ """Simple import: import module as alias."""
325
+ def __init__(self, module, alias=None, line=0, column=0):
326
+ super().__init__(line, column)
327
+ self.module = module
328
+ self.alias = alias
329
+ class FromImportStatement(ASTNode):
330
+ """From-import: from module import name1 as alias1, name2."""
331
+ def __init__(self, module, names, line=0, column=0):
332
+ super().__init__(line, column)
333
+ self.module = module
334
+ self.names = names
335
+ # ---------------------------------------------------------------------------
336
+ # Extended expression nodes
337
+ # ---------------------------------------------------------------------------
338
+ class SliceExpr(ASTNode):
339
+ """Slice expression: start:stop or start:stop:step."""
340
+ def __init__(self, start=None, stop=None, step=None, line=0, column=0):
341
+ super().__init__(line, column)
342
+ self.start = start
343
+ self.stop = stop
344
+ self.step = step
345
+ class Parameter(ASTNode):
346
+ """Function parameter with optional default, *args, **kwargs."""
347
+ def __init__(self, name, default=None, is_vararg=False,
348
+ is_kwarg=False, annotation=None, line=0, column=0):
349
+ super().__init__(line, column)
350
+ self.name = name
351
+ self.default = default
352
+ self.is_vararg = is_vararg
353
+ self.is_kwarg = is_kwarg
354
+ self.annotation = annotation
355
+ class StarredExpr(ASTNode):
356
+ """Starred expression in call: *args or **kwargs."""
357
+ def __init__(self, value, is_double=False, line=0, column=0):
358
+ super().__init__(line, column)
359
+ self.value = value
360
+ self.is_double = is_double
361
+ class TupleLiteral(ASTNode):
362
+ """Tuple literal or tuple unpacking target: a, b, c."""
363
+ def __init__(self, elements, line=0, column=0):
364
+ super().__init__(line, column)
365
+ self.elements = elements
366
+ class ComprehensionClause(ASTNode):
367
+ """Single comprehension clause: for target in iterable [if cond]..."""
368
+ def __init__(self, target, iterable, conditions=None, line=0, column=0):
369
+ super().__init__(line, column)
370
+ self.target = target
371
+ self.iterable = iterable
372
+ self.conditions = conditions or []
373
+ class ListComprehension(ASTNode):
374
+ """List comprehension: [expr for target in iterable if cond]."""
375
+ def __init__(self, element, target, iterable, conditions=None,
376
+ clauses=None, line=0, column=0):
377
+ super().__init__(line, column)
378
+ self.element = element
379
+ self.clauses = clauses or [
380
+ ComprehensionClause(
381
+ target, iterable, conditions or [], line=line, column=column
382
+ )
383
+ ]
384
+ first = self.clauses[0]
385
+ # Backward compatibility: expose first-clause fields.
386
+ self.target = first.target
387
+ self.iterable = first.iterable
388
+ self.conditions = first.conditions
389
+ class DictComprehension(ASTNode):
390
+ """Dict comprehension: {key: val for target in iterable if cond}."""
391
+ def __init__(self, key, value, target, iterable, conditions=None,
392
+ clauses=None, **kwargs):
393
+ line = kwargs.pop("line", 0)
394
+ column = kwargs.pop("column", 0)
395
+ if kwargs:
396
+ extra = ", ".join(sorted(kwargs.keys()))
397
+ raise TypeError(f"Unexpected keyword argument(s): {extra}")
398
+ super().__init__(line, column)
399
+ self.key = key
400
+ self.value = value
401
+ self.clauses = clauses or [
402
+ ComprehensionClause(
403
+ target, iterable, conditions or [], line=line, column=column
404
+ )
405
+ ]
406
+ first = self.clauses[0]
407
+ # Backward compatibility: expose first-clause fields.
408
+ self.target = first.target
409
+ self.iterable = first.iterable
410
+ self.conditions = first.conditions
411
+ class GeneratorExpr(ASTNode):
412
+ """Generator expression: (expr for target in iterable if cond)."""
413
+ def __init__(self, element, target, iterable, conditions=None,
414
+ clauses=None, line=0, column=0):
415
+ super().__init__(line, column)
416
+ self.element = element
417
+ self.clauses = clauses or [
418
+ ComprehensionClause(
419
+ target, iterable, conditions or [], line=line, column=column
420
+ )
421
+ ]
422
+ first = self.clauses[0]
423
+ # Backward compatibility: expose first-clause fields.
424
+ self.target = first.target
425
+ self.iterable = first.iterable
426
+ self.conditions = first.conditions
427
+ class SetComprehension(ASTNode):
428
+ """Set comprehension: {expr for target in iterable if cond}."""
429
+ def __init__(self, element, target, iterable, conditions=None,
430
+ clauses=None, line=0, column=0):
431
+ super().__init__(line, column)
432
+ self.element = element
433
+ self.clauses = clauses or [
434
+ ComprehensionClause(
435
+ target, iterable, conditions or [], line=line, column=column
436
+ )
437
+ ]
438
+ first = self.clauses[0]
439
+ self.target = first.target
440
+ self.iterable = first.iterable
441
+ self.conditions = first.conditions
442
+ class FStringLiteral(ASTNode):
443
+ """F-string with interpolated expressions: f"text {expr} text"."""
444
+ def __init__(self, parts, line=0, column=0):
445
+ super().__init__(line, column)
446
+ # parts: list of (str | ASTNode) alternating text and expressions
447
+ self.parts = parts
448
+ class AssertStatement(ASTNode):
449
+ """Assert statement: assert test [, msg]."""
450
+ def __init__(self, test, msg=None, line=0, column=0):
451
+ super().__init__(line, column)
452
+ self.test = test
453
+ self.msg = msg
454
+ class ChainedAssignment(ASTNode):
455
+ """Chained assignment: a = b = c = value."""
456
+ def __init__(self, targets, value, line=0, column=0):
457
+ super().__init__(line, column)
458
+ self.targets = targets
459
+ self.value = value