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.
- multilingualprogramming/__init__.py +74 -0
- multilingualprogramming/__main__.py +194 -0
- multilingualprogramming/codegen/__init__.py +12 -0
- multilingualprogramming/codegen/executor.py +215 -0
- multilingualprogramming/codegen/python_generator.py +592 -0
- multilingualprogramming/codegen/repl.py +489 -0
- multilingualprogramming/codegen/runtime_builtins.py +308 -0
- multilingualprogramming/core/__init__.py +12 -0
- multilingualprogramming/core/ir.py +29 -0
- multilingualprogramming/core/lowering.py +24 -0
- multilingualprogramming/datetime/__init__.py +11 -0
- multilingualprogramming/datetime/date_parser.py +190 -0
- multilingualprogramming/datetime/mp_date.py +210 -0
- multilingualprogramming/datetime/mp_datetime.py +153 -0
- multilingualprogramming/datetime/mp_time.py +147 -0
- multilingualprogramming/datetime/resource_loader.py +18 -0
- multilingualprogramming/exceptions.py +158 -0
- multilingualprogramming/imports.py +150 -0
- multilingualprogramming/keyword/__init__.py +13 -0
- multilingualprogramming/keyword/keyword_registry.py +249 -0
- multilingualprogramming/keyword/keyword_validator.py +59 -0
- multilingualprogramming/keyword/language_pack_validator.py +110 -0
- multilingualprogramming/lexer/__init__.py +11 -0
- multilingualprogramming/lexer/lexer.py +570 -0
- multilingualprogramming/lexer/source_reader.py +91 -0
- multilingualprogramming/lexer/token.py +54 -0
- multilingualprogramming/lexer/token_types.py +38 -0
- multilingualprogramming/numeral/__init__.py +11 -0
- multilingualprogramming/numeral/abstract_numeral.py +232 -0
- multilingualprogramming/numeral/complex_numeral.py +190 -0
- multilingualprogramming/numeral/fraction_numeral.py +165 -0
- multilingualprogramming/numeral/mp_numeral.py +243 -0
- multilingualprogramming/numeral/numeral_converter.py +151 -0
- multilingualprogramming/numeral/roman_numeral.py +301 -0
- multilingualprogramming/numeral/unicode_numeral.py +292 -0
- multilingualprogramming/parser/__init__.py +28 -0
- multilingualprogramming/parser/ast_nodes.py +459 -0
- multilingualprogramming/parser/ast_printer.py +677 -0
- multilingualprogramming/parser/error_messages.py +75 -0
- multilingualprogramming/parser/parser.py +1796 -0
- multilingualprogramming/parser/semantic_analyzer.py +689 -0
- multilingualprogramming/parser/surface_normalizer.py +282 -0
- multilingualprogramming/resources/datetime/eras.json +23 -0
- multilingualprogramming/resources/datetime/formats.json +32 -0
- multilingualprogramming/resources/datetime/months.json +150 -0
- multilingualprogramming/resources/datetime/weekdays.json +90 -0
- multilingualprogramming/resources/parser/error_messages.json +310 -0
- multilingualprogramming/resources/repl/commands.json +636 -0
- multilingualprogramming/resources/usm/builtins_aliases.json +731 -0
- multilingualprogramming/resources/usm/keywords.json +1063 -0
- multilingualprogramming/resources/usm/operators.json +532 -0
- multilingualprogramming/resources/usm/schema.json +34 -0
- multilingualprogramming/resources/usm/surface_patterns.json +1523 -0
- multilingualprogramming/unicode_string.py +140 -0
- multilingualprogramming/version.py +9 -0
- multilingualprogramming-0.2.0.dist-info/METADATA +350 -0
- multilingualprogramming-0.2.0.dist-info/RECORD +61 -0
- multilingualprogramming-0.2.0.dist-info/WHEEL +5 -0
- multilingualprogramming-0.2.0.dist-info/entry_points.txt +3 -0
- multilingualprogramming-0.2.0.dist-info/licenses/LICENSE +674 -0
- 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
|