jaclang 0.5.6__py3-none-any.whl → 0.5.8__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.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/__init__.py +6 -1
- jaclang/cli/cli.py +63 -20
- jaclang/cli/cmdreg.py +42 -12
- jaclang/compiler/__init__.py +6 -3
- jaclang/compiler/__jac_gen__/jac_parser.py +2 -2
- jaclang/compiler/absyntree.py +1740 -61
- jaclang/compiler/codeloc.py +7 -0
- jaclang/compiler/compile.py +4 -5
- jaclang/compiler/constant.py +52 -6
- jaclang/compiler/parser.py +220 -129
- jaclang/compiler/passes/main/def_impl_match_pass.py +19 -3
- jaclang/compiler/passes/main/def_use_pass.py +1 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +357 -0
- jaclang/compiler/passes/main/import_pass.py +7 -3
- jaclang/compiler/passes/main/pyast_gen_pass.py +333 -93
- jaclang/compiler/passes/main/pyast_load_pass.py +1779 -206
- jaclang/compiler/passes/main/pyout_pass.py +2 -2
- jaclang/compiler/passes/main/schedules.py +2 -1
- jaclang/compiler/passes/main/sym_tab_build_pass.py +20 -28
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +4 -4
- jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +14 -5
- jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +8 -8
- jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +7 -0
- jaclang/compiler/passes/main/type_check_pass.py +0 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +8 -17
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +43 -0
- jaclang/compiler/passes/utils/mypy_ast_build.py +28 -14
- jaclang/compiler/symtable.py +23 -2
- jaclang/compiler/tests/test_parser.py +53 -0
- jaclang/compiler/workspace.py +52 -26
- jaclang/core/aott.py +68 -0
- jaclang/core/construct.py +58 -6
- jaclang/core/importer.py +9 -10
- jaclang/core/utils.py +65 -3
- jaclang/plugin/builtin.py +42 -0
- jaclang/plugin/default.py +163 -18
- jaclang/plugin/feature.py +38 -10
- jaclang/plugin/spec.py +33 -6
- jaclang/utils/helpers.py +25 -0
- jaclang/utils/lang_tools.py +4 -1
- jaclang/utils/test.py +1 -0
- jaclang/utils/tests/test_lang_tools.py +12 -15
- jaclang/utils/treeprinter.py +10 -2
- {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/METADATA +1 -1
- {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/RECORD +48 -46
- {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/WHEEL +1 -1
- jaclang/compiler/tests/fixtures/__jac_gen__/__init__.py +0 -0
- jaclang/compiler/tests/fixtures/__jac_gen__/hello_world.py +0 -5
- jaclang/core/jacbuiltins.py +0 -10
- {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/entry_points.txt +0 -0
- {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
# type: ignore
|
|
2
1
|
"""Lark parser for Jac Lang."""
|
|
3
2
|
|
|
4
3
|
from __future__ import annotations
|
|
5
4
|
|
|
6
5
|
import ast as py_ast
|
|
7
6
|
import os
|
|
8
|
-
from typing import Optional,
|
|
7
|
+
from typing import Optional, TypeAlias, TypeVar
|
|
9
8
|
|
|
10
9
|
import jaclang.compiler.absyntree as ast
|
|
11
10
|
from jaclang.compiler.constant import Tokens as Tok
|
|
@@ -36,17 +35,53 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
36
35
|
|
|
37
36
|
def convert(self, node: py_ast.AST) -> ast.AstNode:
|
|
38
37
|
"""Get python node type."""
|
|
39
|
-
print(
|
|
38
|
+
# print(
|
|
39
|
+
# f"working on {type(node).__name__} line {node.lineno if hasattr(node, 'lineno') else 0}"
|
|
40
|
+
# )
|
|
40
41
|
if hasattr(self, f"proc_{pascal_to_snake(type(node).__name__)}"):
|
|
41
|
-
|
|
42
|
+
ret = getattr(self, f"proc_{pascal_to_snake(type(node).__name__)}")(node)
|
|
42
43
|
else:
|
|
43
44
|
raise self.ice(f"Unknown node type {type(node).__name__}")
|
|
45
|
+
# print(f"finshed {type(node).__name__} ---------------------")
|
|
46
|
+
# print("normalizing", ret.__class__.__name__)
|
|
47
|
+
# print(ret.unparse())
|
|
48
|
+
return ret
|
|
44
49
|
|
|
45
50
|
def transform(self, ir: ast.PythonModuleAst) -> ast.Module:
|
|
46
51
|
"""Transform input IR."""
|
|
47
52
|
self.ir: ast.Module = self.proc_module(ir.ast)
|
|
48
53
|
return self.ir
|
|
49
54
|
|
|
55
|
+
def extract_with_entry(
|
|
56
|
+
self, body: list[ast.AstNode], exclude_types: TypeAlias = T
|
|
57
|
+
) -> list[T | ast.ModuleCode]:
|
|
58
|
+
"""Extract with entry from a body."""
|
|
59
|
+
|
|
60
|
+
def gen_mod_code(with_entry_body: list[ast.CodeBlockStmt]) -> ast.ModuleCode:
|
|
61
|
+
with_entry_subnodelist = ast.SubNodeList[ast.CodeBlockStmt](
|
|
62
|
+
items=with_entry_body, delim=Tok.WS, kid=with_entry_body
|
|
63
|
+
)
|
|
64
|
+
return ast.ModuleCode(
|
|
65
|
+
name=None,
|
|
66
|
+
body=with_entry_subnodelist,
|
|
67
|
+
kid=with_entry_body,
|
|
68
|
+
doc=None,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
extracted: list[T | ast.ModuleCode] = []
|
|
72
|
+
with_entry_body: list[ast.CodeBlockStmt] = []
|
|
73
|
+
for i in body:
|
|
74
|
+
if isinstance(i, exclude_types):
|
|
75
|
+
extracted.append(i)
|
|
76
|
+
elif isinstance(i, ast.CodeBlockStmt):
|
|
77
|
+
with_entry_body.append(i)
|
|
78
|
+
else:
|
|
79
|
+
self.ice("Invalid type for with entry body")
|
|
80
|
+
|
|
81
|
+
if len(with_entry_body):
|
|
82
|
+
extracted.append(gen_mod_code(with_entry_body))
|
|
83
|
+
return extracted
|
|
84
|
+
|
|
50
85
|
def proc_module(self, node: py_ast.Module) -> ast.Module:
|
|
51
86
|
"""Process python node.
|
|
52
87
|
|
|
@@ -56,20 +91,22 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
56
91
|
type_ignores: list[TypeIgnore]
|
|
57
92
|
"""
|
|
58
93
|
elements: list[ast.AstNode] = [self.convert(i) for i in node.body]
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
94
|
+
elements[0] = (
|
|
95
|
+
elements[0].expr
|
|
96
|
+
if isinstance(elements[0], ast.ExprStmt)
|
|
97
|
+
and isinstance(elements[0].expr, ast.String)
|
|
98
|
+
else elements[0]
|
|
99
|
+
)
|
|
100
|
+
valid = (
|
|
101
|
+
[elements[0]] if isinstance(elements[0], ast.String) else []
|
|
102
|
+
) + self.extract_with_entry(elements[1:], (ast.ElementStmt, ast.EmptyToken))
|
|
66
103
|
ret = ast.Module(
|
|
67
104
|
name=self.mod_path.split(os.path.sep)[-1].split(".")[0],
|
|
68
105
|
source=ast.JacSource("", mod_path=self.mod_path),
|
|
69
|
-
doc=elements[0] if isinstance(elements[0], ast.String) else None,
|
|
70
|
-
body=valid,
|
|
106
|
+
doc=(elements[0] if isinstance(elements[0], ast.String) else None),
|
|
107
|
+
body=valid[1:] if isinstance(valid[0], ast.String) else valid,
|
|
71
108
|
is_imported=False,
|
|
72
|
-
kid=
|
|
109
|
+
kid=valid,
|
|
73
110
|
)
|
|
74
111
|
ret.gen.py_ast = [node]
|
|
75
112
|
return self.nu(ret)
|
|
@@ -80,8 +117,6 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
80
117
|
"""Process python node.
|
|
81
118
|
|
|
82
119
|
class FunctionDef(stmt):
|
|
83
|
-
__match_args__ = ("name", "args", "body", "decorator_list",
|
|
84
|
-
"returns", "type_comment", "type_params")
|
|
85
120
|
name: _Identifier
|
|
86
121
|
args: arguments
|
|
87
122
|
body: list[stmt]
|
|
@@ -99,41 +134,57 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
99
134
|
col_end=node.col_offset + len(node.name),
|
|
100
135
|
pos_start=0,
|
|
101
136
|
pos_end=0,
|
|
102
|
-
kid=[],
|
|
103
137
|
)
|
|
104
138
|
body = [self.convert(i) for i in node.body]
|
|
105
|
-
valid = [i for i in body if isinstance(i, ast.CodeBlockStmt)]
|
|
139
|
+
valid = [i for i in body if isinstance(i, (ast.CodeBlockStmt))]
|
|
106
140
|
if len(valid) != len(body):
|
|
107
|
-
self.
|
|
108
|
-
|
|
109
|
-
|
|
141
|
+
raise self.ice("Length mismatch in function body")
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
len(valid)
|
|
145
|
+
and isinstance(valid[0], ast.ExprStmt)
|
|
146
|
+
and isinstance(valid[0].expr, ast.String)
|
|
147
|
+
):
|
|
148
|
+
doc = valid[0].expr
|
|
149
|
+
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
150
|
+
items=valid[1:], delim=Tok.WS, kid=valid[1:]
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
doc = None
|
|
154
|
+
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
155
|
+
items=valid, delim=Tok.WS, kid=valid
|
|
156
|
+
)
|
|
110
157
|
decorators = [self.convert(i) for i in node.decorator_list]
|
|
111
158
|
valid_dec = [i for i in decorators if isinstance(i, ast.Expr)]
|
|
112
159
|
if len(valid_dec) != len(decorators):
|
|
113
|
-
self.
|
|
160
|
+
raise self.ice("Length mismatch in decorators on function")
|
|
114
161
|
valid_decorators = (
|
|
115
|
-
ast.SubNodeList[ast.Expr](
|
|
162
|
+
ast.SubNodeList[ast.Expr](
|
|
163
|
+
items=valid_dec, delim=Tok.DECOR_OP, kid=decorators
|
|
164
|
+
)
|
|
116
165
|
if len(valid_dec)
|
|
117
166
|
else None
|
|
118
167
|
)
|
|
119
168
|
res = self.convert(node.args)
|
|
120
|
-
sig: Optional[ast.FuncSignature]
|
|
169
|
+
sig: Optional[ast.FuncSignature] = (
|
|
121
170
|
res if isinstance(res, ast.FuncSignature) else None
|
|
122
171
|
)
|
|
123
172
|
ret_sig = self.convert(node.returns) if node.returns else None
|
|
124
173
|
if isinstance(ret_sig, ast.Expr):
|
|
125
174
|
if not sig:
|
|
126
|
-
sig = ret_sig
|
|
175
|
+
sig = ast.FuncSignature(params=None, return_type=ret_sig, kid=[ret_sig])
|
|
127
176
|
else:
|
|
128
|
-
sig.return_type =
|
|
177
|
+
sig.return_type = ret_sig
|
|
129
178
|
sig.add_kids_right([sig.return_type])
|
|
130
|
-
kid = [
|
|
131
|
-
|
|
179
|
+
kid = ([doc] if doc else []) + (
|
|
180
|
+
[name, sig, valid_body] if sig else [name, valid_body]
|
|
181
|
+
)
|
|
182
|
+
ret = ast.Ability(
|
|
132
183
|
name_ref=name,
|
|
133
|
-
is_func=True,
|
|
134
184
|
is_async=False,
|
|
135
185
|
is_static=False,
|
|
136
186
|
is_abstract=False,
|
|
187
|
+
is_override=False,
|
|
137
188
|
access=None,
|
|
138
189
|
signature=sig,
|
|
139
190
|
body=valid_body,
|
|
@@ -141,6 +192,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
141
192
|
doc=doc,
|
|
142
193
|
kid=kid,
|
|
143
194
|
)
|
|
195
|
+
return ret
|
|
144
196
|
|
|
145
197
|
def proc_async_function_def(self, node: py_ast.AsyncFunctionDef) -> ast.Ability:
|
|
146
198
|
"""Process python node.
|
|
@@ -183,7 +235,6 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
183
235
|
col_end=node.col_offset + len(node.name),
|
|
184
236
|
pos_start=0,
|
|
185
237
|
pos_end=0,
|
|
186
|
-
kid=[],
|
|
187
238
|
)
|
|
188
239
|
arch_type = ast.Token(
|
|
189
240
|
file_path=self.mod_path,
|
|
@@ -194,30 +245,36 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
194
245
|
col_end=0,
|
|
195
246
|
pos_start=0,
|
|
196
247
|
pos_end=0,
|
|
197
|
-
kid=[],
|
|
198
248
|
)
|
|
249
|
+
body = [self.convert(i) for i in node.body]
|
|
250
|
+
valid: list[ast.ArchBlockStmt] = self.extract_with_entry(
|
|
251
|
+
body, ast.ArchBlockStmt
|
|
252
|
+
)
|
|
253
|
+
valid_body = ast.SubNodeList[ast.ArchBlockStmt](
|
|
254
|
+
items=valid, delim=Tok.WS, kid=body
|
|
255
|
+
)
|
|
256
|
+
|
|
199
257
|
base_classes = [self.convert(base) for base in node.bases]
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
258
|
+
valid2: list[ast.Expr] = [
|
|
259
|
+
base for base in base_classes if isinstance(base, ast.Expr)
|
|
260
|
+
]
|
|
261
|
+
if len(valid2) != len(base_classes):
|
|
262
|
+
raise self.ice("Length mismatch in base classes")
|
|
203
263
|
valid_bases = (
|
|
204
|
-
ast.SubNodeList[ast.
|
|
205
|
-
if len(
|
|
264
|
+
ast.SubNodeList[ast.Expr](items=valid2, delim=Tok.COMMA, kid=base_classes)
|
|
265
|
+
if len(valid2)
|
|
206
266
|
else None
|
|
207
267
|
)
|
|
208
|
-
body = [self.convert(i) for i in node.body]
|
|
209
|
-
valid_body = [i for i in body if isinstance(i, ast.ArchBlockStmt)]
|
|
210
|
-
if len(valid_body) != len(body):
|
|
211
|
-
self.error("Length mismatch in classes body")
|
|
212
|
-
valid_body = ast.SubNodeList[ast.ArchBlockStmt](items=valid_body, kid=body)
|
|
213
268
|
doc = None
|
|
214
269
|
decorators = [self.convert(i) for i in node.decorator_list]
|
|
215
|
-
|
|
216
|
-
if len(
|
|
217
|
-
self.
|
|
270
|
+
valid_dec = [i for i in decorators if isinstance(i, ast.Expr)]
|
|
271
|
+
if len(valid_dec) != len(decorators):
|
|
272
|
+
raise self.ice("Length mismatch in decorators in class")
|
|
218
273
|
valid_decorators = (
|
|
219
|
-
ast.SubNodeList[ast.Expr](
|
|
220
|
-
|
|
274
|
+
ast.SubNodeList[ast.Expr](
|
|
275
|
+
items=valid_dec, delim=Tok.DECOR_OP, kid=decorators
|
|
276
|
+
)
|
|
277
|
+
if len(valid_dec)
|
|
221
278
|
else None
|
|
222
279
|
)
|
|
223
280
|
kid = [name, valid_bases, valid_body] if valid_bases else [name, valid_body]
|
|
@@ -232,7 +289,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
232
289
|
decorators=valid_decorators,
|
|
233
290
|
)
|
|
234
291
|
|
|
235
|
-
def proc_return(self, node: py_ast.Return) -> ast.
|
|
292
|
+
def proc_return(self, node: py_ast.Return) -> ast.ReturnStmt | None:
|
|
236
293
|
"""Process python node.
|
|
237
294
|
|
|
238
295
|
class Return(stmt):
|
|
@@ -240,10 +297,14 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
240
297
|
value: expr | None
|
|
241
298
|
"""
|
|
242
299
|
value = self.convert(node.value) if node.value else None
|
|
243
|
-
if
|
|
244
|
-
|
|
300
|
+
if not value:
|
|
301
|
+
return ast.ReturnStmt(
|
|
302
|
+
expr=None, kid=[self.operator(Tok.KW_RETURN, "return")]
|
|
303
|
+
)
|
|
304
|
+
elif value and isinstance(value, ast.Expr):
|
|
305
|
+
return ast.ReturnStmt(expr=value, kid=[value])
|
|
245
306
|
else:
|
|
246
|
-
return value
|
|
307
|
+
raise self.ice("Invalid return value")
|
|
247
308
|
|
|
248
309
|
def proc_delete(self, node: py_ast.Delete) -> ast.DeleteStmt:
|
|
249
310
|
"""Process python node.
|
|
@@ -253,11 +314,18 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
253
314
|
targets: list[expr]
|
|
254
315
|
"""
|
|
255
316
|
exprs = [self.convert(target) for target in node.targets]
|
|
256
|
-
valid_exprs = [expr for expr in exprs if isinstance(expr, ast.
|
|
317
|
+
valid_exprs = [expr for expr in exprs if isinstance(expr, ast.Expr)]
|
|
257
318
|
if not len(valid_exprs) or len(valid_exprs) != len(exprs):
|
|
258
|
-
self.
|
|
319
|
+
raise self.ice("Length mismatch in delete targets")
|
|
320
|
+
target = ast.SubNodeList[ast.Expr | ast.KWPair](
|
|
321
|
+
items=[*valid_exprs], delim=Tok.COMMA, kid=exprs
|
|
322
|
+
)
|
|
259
323
|
return ast.DeleteStmt(
|
|
260
|
-
target=
|
|
324
|
+
target=(
|
|
325
|
+
valid_exprs[0]
|
|
326
|
+
if len(valid_exprs) > 1
|
|
327
|
+
else ast.TupleVal(values=target, kid=[target])
|
|
328
|
+
),
|
|
261
329
|
kid=exprs,
|
|
262
330
|
)
|
|
263
331
|
|
|
@@ -268,17 +336,15 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
268
336
|
targets: list[expr]
|
|
269
337
|
value: expr
|
|
270
338
|
"""
|
|
339
|
+
value = self.convert(node.value)
|
|
271
340
|
targets = [self.convert(target) for target in node.targets]
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
valid_targets = ast.SubNodeList[ast.AtomExpr](
|
|
277
|
-
items=valid_targets, kid=targets
|
|
341
|
+
valid = [target for target in targets if isinstance(target, ast.Expr)]
|
|
342
|
+
if len(valid) == len(targets):
|
|
343
|
+
valid_targets = ast.SubNodeList[ast.Expr](
|
|
344
|
+
items=valid, delim=Tok.EQ, kid=valid
|
|
278
345
|
)
|
|
279
346
|
else:
|
|
280
347
|
raise self.ice("Length mismatch in assignment targets")
|
|
281
|
-
value = self.convert(node.value)
|
|
282
348
|
if isinstance(value, ast.Expr):
|
|
283
349
|
return ast.Assignment(
|
|
284
350
|
target=valid_targets,
|
|
@@ -289,7 +355,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
289
355
|
else:
|
|
290
356
|
raise self.ice()
|
|
291
357
|
|
|
292
|
-
def proc_aug_assign(self, node: py_ast.AugAssign) -> ast.
|
|
358
|
+
def proc_aug_assign(self, node: py_ast.AugAssign) -> ast.Assignment:
|
|
293
359
|
"""Process python node.
|
|
294
360
|
|
|
295
361
|
class AugAssign(stmt):
|
|
@@ -306,10 +372,15 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
306
372
|
and isinstance(target, ast.Expr)
|
|
307
373
|
and isinstance(op, ast.Token)
|
|
308
374
|
):
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
375
|
+
targ = ast.SubNodeList[ast.Expr](
|
|
376
|
+
items=[target], delim=Tok.COMMA, kid=[target]
|
|
377
|
+
)
|
|
378
|
+
return ast.Assignment(
|
|
379
|
+
target=targ,
|
|
380
|
+
type_tag=None,
|
|
381
|
+
mutable=True,
|
|
382
|
+
aug_op=op,
|
|
383
|
+
value=value,
|
|
313
384
|
kid=[target, op, value],
|
|
314
385
|
)
|
|
315
386
|
else:
|
|
@@ -328,21 +399,26 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
328
399
|
target = self.convert(node.target)
|
|
329
400
|
annotation = self.convert(node.annotation)
|
|
330
401
|
if isinstance(annotation, ast.Expr):
|
|
331
|
-
|
|
402
|
+
annotation_subtag = ast.SubTag[ast.Expr](tag=annotation, kid=[annotation])
|
|
332
403
|
else:
|
|
333
404
|
raise self.ice()
|
|
334
405
|
value = self.convert(node.value) if node.value else None
|
|
335
|
-
valid_types = Union[ast.Expr, ast.YieldExpr]
|
|
336
406
|
if (
|
|
337
|
-
isinstance(
|
|
338
|
-
and (isinstance(value, valid_types) or not value)
|
|
407
|
+
(isinstance(value, (ast.Expr, ast.YieldExpr)) or not value)
|
|
339
408
|
and isinstance(annotation, ast.Expr)
|
|
409
|
+
and isinstance(target, ast.Expr)
|
|
340
410
|
):
|
|
341
411
|
return ast.Assignment(
|
|
342
|
-
target=
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
412
|
+
target=ast.SubNodeList[ast.Expr](
|
|
413
|
+
items=[target], delim=Tok.EQ, kid=[target]
|
|
414
|
+
),
|
|
415
|
+
value=value if isinstance(value, (ast.Expr, ast.YieldExpr)) else None,
|
|
416
|
+
type_tag=annotation_subtag,
|
|
417
|
+
kid=(
|
|
418
|
+
[target, annotation_subtag, value]
|
|
419
|
+
if value
|
|
420
|
+
else [target, annotation_subtag]
|
|
421
|
+
),
|
|
346
422
|
)
|
|
347
423
|
else:
|
|
348
424
|
raise self.ice()
|
|
@@ -360,18 +436,43 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
360
436
|
target = self.convert(node.target)
|
|
361
437
|
iter = self.convert(node.iter)
|
|
362
438
|
body = [self.convert(i) for i in node.body]
|
|
363
|
-
|
|
364
|
-
if len(
|
|
365
|
-
self.
|
|
366
|
-
|
|
439
|
+
val_body = [i for i in body if isinstance(i, ast.CodeBlockStmt)]
|
|
440
|
+
if len(val_body) != len(body):
|
|
441
|
+
raise self.ice("Length mismatch in for body")
|
|
442
|
+
|
|
443
|
+
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
444
|
+
items=val_body, delim=Tok.WS, kid=val_body
|
|
445
|
+
)
|
|
367
446
|
orelse = [self.convert(i) for i in node.orelse]
|
|
368
|
-
|
|
369
|
-
if len(
|
|
370
|
-
self.
|
|
371
|
-
|
|
372
|
-
|
|
447
|
+
val_orelse = [i for i in orelse if isinstance(i, ast.CodeBlockStmt)]
|
|
448
|
+
if len(val_orelse) != len(orelse):
|
|
449
|
+
raise self.ice("Length mismatch in for orelse")
|
|
450
|
+
if orelse:
|
|
451
|
+
valid_orelse = ast.SubNodeList[ast.CodeBlockStmt](
|
|
452
|
+
items=val_orelse, delim=Tok.WS, kid=orelse
|
|
453
|
+
)
|
|
454
|
+
else:
|
|
455
|
+
valid_orelse = None
|
|
456
|
+
fin_orelse = (
|
|
457
|
+
ast.ElseStmt(body=valid_orelse, kid=[valid_orelse])
|
|
458
|
+
if valid_orelse
|
|
459
|
+
else None
|
|
373
460
|
)
|
|
374
|
-
|
|
461
|
+
if isinstance(target, ast.Expr) and isinstance(iter, ast.Expr):
|
|
462
|
+
return ast.InForStmt(
|
|
463
|
+
target=target,
|
|
464
|
+
is_async=False,
|
|
465
|
+
collection=iter,
|
|
466
|
+
body=valid_body,
|
|
467
|
+
else_body=fin_orelse,
|
|
468
|
+
kid=(
|
|
469
|
+
[target, iter, valid_body, fin_orelse]
|
|
470
|
+
if fin_orelse
|
|
471
|
+
else [target, iter, valid_body]
|
|
472
|
+
),
|
|
473
|
+
)
|
|
474
|
+
else:
|
|
475
|
+
raise self.ice()
|
|
375
476
|
|
|
376
477
|
def proc_async_for(self, node: py_ast.AsyncFor) -> ast.InForStmt:
|
|
377
478
|
"""Process AsyncFor node.
|
|
@@ -385,19 +486,46 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
385
486
|
"""
|
|
386
487
|
target = self.convert(node.target)
|
|
387
488
|
iter = self.convert(node.iter)
|
|
388
|
-
body = [self.convert(
|
|
389
|
-
|
|
390
|
-
if len(
|
|
391
|
-
self.
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
489
|
+
body = [self.convert(i) for i in node.body]
|
|
490
|
+
val_body = [i for i in body if isinstance(i, ast.CodeBlockStmt)]
|
|
491
|
+
if len(val_body) != len(body):
|
|
492
|
+
raise self.ice("Length mismatch in for body")
|
|
493
|
+
|
|
494
|
+
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
495
|
+
items=val_body, delim=Tok.WS, kid=val_body
|
|
496
|
+
)
|
|
497
|
+
orelse = [self.convert(i) for i in node.orelse]
|
|
498
|
+
val_orelse = [i for i in orelse if isinstance(i, ast.CodeBlockStmt)]
|
|
499
|
+
if len(val_orelse) != len(orelse):
|
|
500
|
+
raise self.ice("Length mismatch in for orelse")
|
|
501
|
+
if orelse:
|
|
502
|
+
valid_orelse = ast.SubNodeList[ast.CodeBlockStmt](
|
|
503
|
+
items=val_orelse, delim=Tok.WS, kid=orelse
|
|
504
|
+
)
|
|
505
|
+
else:
|
|
506
|
+
valid_orelse = None
|
|
507
|
+
fin_orelse = (
|
|
508
|
+
ast.ElseStmt(body=valid_orelse, kid=[valid_orelse])
|
|
509
|
+
if valid_orelse
|
|
510
|
+
else None
|
|
511
|
+
)
|
|
512
|
+
if isinstance(target, ast.Expr) and isinstance(iter, ast.Expr):
|
|
513
|
+
return ast.InForStmt(
|
|
514
|
+
target=target,
|
|
515
|
+
is_async=True,
|
|
516
|
+
collection=iter,
|
|
517
|
+
body=valid_body,
|
|
518
|
+
else_body=fin_orelse,
|
|
519
|
+
kid=(
|
|
520
|
+
[target, iter, valid_body, fin_orelse]
|
|
521
|
+
if fin_orelse
|
|
522
|
+
else [target, iter, valid_body]
|
|
523
|
+
),
|
|
524
|
+
)
|
|
525
|
+
else:
|
|
526
|
+
raise self.ice()
|
|
399
527
|
|
|
400
|
-
def proc_while(self, node: py_ast.While) -> ast.
|
|
528
|
+
def proc_while(self, node: py_ast.While) -> ast.WhileStmt:
|
|
401
529
|
"""Process While node.
|
|
402
530
|
|
|
403
531
|
class While(stmt):
|
|
@@ -410,16 +538,20 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
410
538
|
body = [self.convert(stmt) for stmt in node.body]
|
|
411
539
|
valid_body = [stmt for stmt in body if isinstance(stmt, ast.CodeBlockStmt)]
|
|
412
540
|
if len(valid_body) != len(body):
|
|
413
|
-
self.
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
541
|
+
raise self.ice("Length mismatch in while body")
|
|
542
|
+
fin_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
543
|
+
items=valid_body, delim=Tok.WS, kid=valid_body
|
|
544
|
+
)
|
|
545
|
+
if isinstance(test, ast.Expr):
|
|
546
|
+
return ast.WhileStmt(
|
|
547
|
+
condition=test,
|
|
548
|
+
body=fin_body,
|
|
549
|
+
kid=[test, fin_body],
|
|
550
|
+
)
|
|
551
|
+
else:
|
|
552
|
+
raise self.ice()
|
|
421
553
|
|
|
422
|
-
def proc_if(self, node: py_ast.If) -> ast.
|
|
554
|
+
def proc_if(self, node: py_ast.If) -> ast.IfStmt:
|
|
423
555
|
"""Process If node.
|
|
424
556
|
|
|
425
557
|
class If(stmt):
|
|
@@ -433,15 +565,44 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
433
565
|
valid_body = [stmt for stmt in body if isinstance(stmt, ast.CodeBlockStmt)]
|
|
434
566
|
if len(valid_body) != len(body):
|
|
435
567
|
self.error("Length mismatch in async for body")
|
|
436
|
-
|
|
568
|
+
body2 = ast.SubNodeList[ast.CodeBlockStmt](
|
|
569
|
+
items=valid_body, delim=Tok.WS, kid=body
|
|
570
|
+
)
|
|
571
|
+
|
|
437
572
|
orelse = [self.convert(stmt) for stmt in node.orelse]
|
|
438
|
-
valid_orelse = [
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
573
|
+
valid_orelse = [
|
|
574
|
+
stmt for stmt in orelse if isinstance(stmt, (ast.CodeBlockStmt))
|
|
575
|
+
]
|
|
576
|
+
if valid_orelse:
|
|
577
|
+
first_elm = valid_orelse[0]
|
|
578
|
+
if isinstance(first_elm, ast.IfStmt):
|
|
579
|
+
else_body: Optional[ast.ElseIf | ast.ElseStmt] = ast.ElseIf(
|
|
580
|
+
condition=first_elm.condition,
|
|
581
|
+
body=first_elm.body,
|
|
582
|
+
else_body=first_elm.else_body,
|
|
583
|
+
kid=first_elm.kid,
|
|
584
|
+
)
|
|
585
|
+
else:
|
|
586
|
+
orelse2 = ast.SubNodeList[ast.CodeBlockStmt](
|
|
587
|
+
items=valid_orelse, delim=Tok.WS, kid=orelse
|
|
588
|
+
)
|
|
589
|
+
else_body = ast.ElseStmt(body=orelse2, kid=[orelse2])
|
|
590
|
+
else:
|
|
591
|
+
else_body = None
|
|
592
|
+
if isinstance(test, ast.Expr):
|
|
593
|
+
ret = ast.IfStmt(
|
|
594
|
+
condition=test,
|
|
595
|
+
body=body2,
|
|
596
|
+
else_body=else_body,
|
|
597
|
+
kid=(
|
|
598
|
+
[test, body2, else_body] if else_body is not None else [test, body2]
|
|
599
|
+
),
|
|
600
|
+
)
|
|
601
|
+
else:
|
|
602
|
+
raise self.ice()
|
|
603
|
+
return ret
|
|
443
604
|
|
|
444
|
-
def proc_with(self, node: py_ast.With) -> ast.
|
|
605
|
+
def proc_with(self, node: py_ast.With) -> ast.WithStmt:
|
|
445
606
|
"""Process With node.
|
|
446
607
|
|
|
447
608
|
class With(stmt):
|
|
@@ -452,16 +613,22 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
452
613
|
items = [self.convert(item) for item in node.items]
|
|
453
614
|
valid_items = [item for item in items if isinstance(item, ast.ExprAsItem)]
|
|
454
615
|
if len(valid_items) != len(items):
|
|
455
|
-
self.
|
|
456
|
-
|
|
616
|
+
raise self.ice("Length mismatch in with items")
|
|
617
|
+
items_sub = ast.SubNodeList[ast.ExprAsItem](
|
|
618
|
+
items=valid_items, delim=Tok.COMMA, kid=items
|
|
619
|
+
)
|
|
457
620
|
body = [self.convert(stmt) for stmt in node.body]
|
|
458
621
|
valid_body = [stmt for stmt in body if isinstance(stmt, ast.CodeBlockStmt)]
|
|
459
622
|
if len(valid_body) != len(body):
|
|
460
|
-
self.
|
|
461
|
-
|
|
462
|
-
|
|
623
|
+
raise self.ice("Length mismatch in async for body")
|
|
624
|
+
body_sub = ast.SubNodeList[ast.CodeBlockStmt](
|
|
625
|
+
items=valid_body, delim=Tok.WS, kid=body
|
|
626
|
+
)
|
|
627
|
+
return ast.WithStmt(
|
|
628
|
+
is_async=False, exprs=items_sub, body=body_sub, kid=[items_sub, body_sub]
|
|
629
|
+
)
|
|
463
630
|
|
|
464
|
-
def proc_async_with(self, node: py_ast.AsyncWith) -> ast.
|
|
631
|
+
def proc_async_with(self, node: py_ast.AsyncWith) -> ast.WithStmt:
|
|
465
632
|
"""Process AsyncWith node.
|
|
466
633
|
|
|
467
634
|
class AsyncWith(stmt):
|
|
@@ -472,41 +639,260 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
472
639
|
items = [self.convert(item) for item in node.items]
|
|
473
640
|
valid_items = [item for item in items if isinstance(item, ast.ExprAsItem)]
|
|
474
641
|
if len(valid_items) != len(items):
|
|
475
|
-
self.
|
|
476
|
-
|
|
642
|
+
raise self.ice("Length mismatch in with items")
|
|
643
|
+
items_sub = ast.SubNodeList[ast.ExprAsItem](
|
|
644
|
+
items=valid_items, delim=Tok.COMMA, kid=items
|
|
645
|
+
)
|
|
477
646
|
body = [self.convert(stmt) for stmt in node.body]
|
|
478
647
|
valid_body = [stmt for stmt in body if isinstance(stmt, ast.CodeBlockStmt)]
|
|
479
648
|
if len(valid_body) != len(body):
|
|
480
|
-
self.
|
|
481
|
-
|
|
482
|
-
|
|
649
|
+
raise self.ice("Length mismatch in async for body")
|
|
650
|
+
body_sub = ast.SubNodeList[ast.CodeBlockStmt](
|
|
651
|
+
items=valid_body, delim=Tok.WS, kid=body
|
|
652
|
+
)
|
|
653
|
+
return ast.WithStmt(
|
|
654
|
+
is_async=True, exprs=items_sub, body=body_sub, kid=[items_sub, body_sub]
|
|
655
|
+
)
|
|
483
656
|
|
|
484
|
-
def proc_raise(self, node: py_ast.Raise) ->
|
|
485
|
-
"""Process python node.
|
|
657
|
+
def proc_raise(self, node: py_ast.Raise) -> ast.RaiseStmt:
|
|
658
|
+
"""Process python node.
|
|
486
659
|
|
|
487
|
-
|
|
488
|
-
|
|
660
|
+
class Raise(stmt):
|
|
661
|
+
exc: expr | None
|
|
662
|
+
cause: expr | None
|
|
663
|
+
"""
|
|
664
|
+
exc = self.convert(node.exc) if node.exc else None
|
|
665
|
+
cause = self.convert(node.cause) if node.cause else None
|
|
666
|
+
kid: list[ast.Expr | ast.Token] = []
|
|
667
|
+
if isinstance(exc, ast.Expr):
|
|
668
|
+
kid = [exc]
|
|
669
|
+
if isinstance(cause, ast.Expr):
|
|
670
|
+
kid.append(cause)
|
|
671
|
+
if not (exc and cause):
|
|
672
|
+
kid.append(self.operator(Tok.KW_RAISE, "raise"))
|
|
673
|
+
if (isinstance(cause, ast.Expr) or cause is None) and (
|
|
674
|
+
isinstance(exc, ast.Expr) or exc is None
|
|
675
|
+
):
|
|
676
|
+
if node.exc and not node.cause:
|
|
677
|
+
return ast.RaiseStmt(
|
|
678
|
+
cause=None,
|
|
679
|
+
from_target=None,
|
|
680
|
+
kid=[self.operator(Tok.KW_RAISE, "raise")],
|
|
681
|
+
)
|
|
682
|
+
else:
|
|
683
|
+
return ast.RaiseStmt(cause=cause, from_target=exc, kid=kid)
|
|
684
|
+
else:
|
|
685
|
+
raise self.ice()
|
|
489
686
|
|
|
490
|
-
def
|
|
491
|
-
"""Process python node.
|
|
687
|
+
def proc_assert(self, node: py_ast.Assert) -> ast.AssertStmt:
|
|
688
|
+
"""Process python node.
|
|
492
689
|
|
|
493
|
-
|
|
494
|
-
|
|
690
|
+
class Assert(stmt):
|
|
691
|
+
test: expr
|
|
692
|
+
msg: expr | None
|
|
693
|
+
"""
|
|
694
|
+
test = self.convert(node.test)
|
|
695
|
+
msg = self.convert(node.msg) if node.msg is not None else None
|
|
696
|
+
if isinstance(test, ast.Expr) and (isinstance(msg, ast.Expr) or msg is None):
|
|
697
|
+
return ast.AssertStmt(
|
|
698
|
+
condition=test,
|
|
699
|
+
error_msg=msg,
|
|
700
|
+
kid=[test, msg] if msg is not None else [test],
|
|
701
|
+
)
|
|
702
|
+
else:
|
|
703
|
+
raise self.ice()
|
|
495
704
|
|
|
496
|
-
def
|
|
497
|
-
"""
|
|
705
|
+
def proc_attribute(self, node: py_ast.Attribute) -> ast.AtomTrailer:
|
|
706
|
+
"""Proassignment targetscess python node.
|
|
498
707
|
|
|
499
|
-
|
|
500
|
-
|
|
708
|
+
class Attribute(expr):
|
|
709
|
+
if sys.version_info >= (3, 10):
|
|
710
|
+
__match_args__ = ("value", "attr", "ctx")
|
|
711
|
+
value: expr
|
|
712
|
+
attr: _Identifier
|
|
713
|
+
ctx: expr_context
|
|
714
|
+
"""
|
|
715
|
+
value = self.convert(node.value)
|
|
501
716
|
|
|
502
|
-
|
|
503
|
-
|
|
717
|
+
attribute = ast.Name(
|
|
718
|
+
file_path=self.mod_path,
|
|
719
|
+
name=Tok.NAME,
|
|
720
|
+
value=node.attr,
|
|
721
|
+
line=node.lineno,
|
|
722
|
+
col_start=node.col_offset,
|
|
723
|
+
col_end=node.col_offset + len(node.attr),
|
|
724
|
+
pos_start=0,
|
|
725
|
+
pos_end=0,
|
|
726
|
+
)
|
|
727
|
+
if isinstance(value, ast.Expr):
|
|
728
|
+
return ast.AtomTrailer(
|
|
729
|
+
target=value,
|
|
730
|
+
right=attribute,
|
|
731
|
+
is_attr=True,
|
|
732
|
+
is_null_ok=False,
|
|
733
|
+
kid=[value, attribute],
|
|
734
|
+
)
|
|
735
|
+
else:
|
|
736
|
+
raise self.ice()
|
|
504
737
|
|
|
505
|
-
def
|
|
506
|
-
"""Process python node.
|
|
738
|
+
def proc_await(self, node: py_ast.Await) -> ast.AwaitExpr:
|
|
739
|
+
"""Process python node.
|
|
740
|
+
|
|
741
|
+
class Await(expr):
|
|
742
|
+
value: expr
|
|
743
|
+
"""
|
|
744
|
+
value = self.convert(node.value)
|
|
745
|
+
if isinstance(value, ast.Expr):
|
|
746
|
+
return ast.AwaitExpr(target=value, kid=[value])
|
|
747
|
+
else:
|
|
748
|
+
raise self.ice()
|
|
749
|
+
|
|
750
|
+
def proc_bin_op(self, node: py_ast.BinOp) -> ast.BinaryExpr:
|
|
751
|
+
"""Process python node.
|
|
752
|
+
|
|
753
|
+
class BinOp(expr):
|
|
754
|
+
if sys.version_info >= (3, 10):
|
|
755
|
+
__match_args__ = ("left", "op", "right")
|
|
756
|
+
left: expr
|
|
757
|
+
op: operator
|
|
758
|
+
right: expr
|
|
759
|
+
"""
|
|
760
|
+
left = self.convert(node.left)
|
|
761
|
+
op = self.convert(node.op)
|
|
762
|
+
right = self.convert(node.right)
|
|
763
|
+
if (
|
|
764
|
+
isinstance(left, ast.Expr)
|
|
765
|
+
and isinstance(op, ast.Token)
|
|
766
|
+
and isinstance(right, ast.Expr)
|
|
767
|
+
):
|
|
768
|
+
return ast.BinaryExpr(
|
|
769
|
+
left=left,
|
|
770
|
+
op=op,
|
|
771
|
+
right=right,
|
|
772
|
+
kid=[left, op, right],
|
|
773
|
+
)
|
|
774
|
+
else:
|
|
775
|
+
raise self.ice()
|
|
776
|
+
|
|
777
|
+
def proc_unary_op(self, node: py_ast.UnaryOp) -> ast.UnaryExpr:
|
|
778
|
+
"""Process python node.
|
|
779
|
+
|
|
780
|
+
class UnaryOp(expr):
|
|
781
|
+
op: unaryop
|
|
782
|
+
operand: expr
|
|
783
|
+
"""
|
|
784
|
+
op = self.convert(node.op)
|
|
785
|
+
operand = self.convert(node.operand)
|
|
786
|
+
if isinstance(op, ast.Token) and isinstance(operand, ast.Expr):
|
|
787
|
+
return ast.UnaryExpr(
|
|
788
|
+
op=op,
|
|
789
|
+
operand=operand,
|
|
790
|
+
kid=[op, operand],
|
|
791
|
+
)
|
|
792
|
+
else:
|
|
793
|
+
raise self.ice()
|
|
794
|
+
|
|
795
|
+
def proc_bool_op(self, node: py_ast.BoolOp) -> ast.BoolExpr:
|
|
796
|
+
"""Process python node.
|
|
797
|
+
|
|
798
|
+
class BoolOp(expr): a and b and c
|
|
799
|
+
op: boolop
|
|
800
|
+
values: list[expr]
|
|
801
|
+
"""
|
|
802
|
+
op = self.convert(node.op)
|
|
803
|
+
values = [self.convert(value) for value in node.values]
|
|
804
|
+
valid = [value for value in values if isinstance(value, ast.Expr)]
|
|
805
|
+
valid_values = ast.SubNodeList[ast.Expr](
|
|
806
|
+
items=valid, delim=Tok.COMMA, kid=values
|
|
807
|
+
)
|
|
808
|
+
if isinstance(op, ast.Token) and len(valid) == len(values):
|
|
809
|
+
return ast.BoolExpr(op=op, values=valid, kid=[op, valid_values])
|
|
810
|
+
else:
|
|
811
|
+
raise self.ice()
|
|
507
812
|
|
|
508
|
-
def
|
|
813
|
+
def proc_break(self, node: py_ast.Break) -> ast.CtrlStmt:
|
|
509
814
|
"""Process python node."""
|
|
815
|
+
break_tok = ast.Token(
|
|
816
|
+
file_path=self.mod_path,
|
|
817
|
+
name=Tok.KW_BREAK,
|
|
818
|
+
value="break",
|
|
819
|
+
line=0,
|
|
820
|
+
col_start=0,
|
|
821
|
+
col_end=0,
|
|
822
|
+
pos_start=0,
|
|
823
|
+
pos_end=0,
|
|
824
|
+
)
|
|
825
|
+
return ast.CtrlStmt(ctrl=break_tok, kid=[break_tok])
|
|
826
|
+
|
|
827
|
+
def proc_call(self, node: py_ast.Call) -> ast.FuncCall:
|
|
828
|
+
"""Process python node.
|
|
829
|
+
|
|
830
|
+
class Call(expr):
|
|
831
|
+
if sys.version_info >= (3, 10):
|
|
832
|
+
__match_args__ = ("func", "args", "keywords")
|
|
833
|
+
func: expr
|
|
834
|
+
args: list[expr]
|
|
835
|
+
keywords: list[keyword]
|
|
836
|
+
"""
|
|
837
|
+
func = self.convert(node.func)
|
|
838
|
+
params_in: list[ast.Expr | ast.KWPair] = []
|
|
839
|
+
args = [self.convert(arg) for arg in node.args]
|
|
840
|
+
keywords = [self.convert(keyword) for keyword in node.keywords]
|
|
841
|
+
|
|
842
|
+
for i in args:
|
|
843
|
+
if isinstance(i, ast.Expr):
|
|
844
|
+
params_in.append(i)
|
|
845
|
+
for i in keywords:
|
|
846
|
+
if isinstance(i, ast.KWPair):
|
|
847
|
+
params_in.append(i)
|
|
848
|
+
if len(params_in) != 0:
|
|
849
|
+
params_in2 = ast.SubNodeList[ast.Expr | ast.KWPair](
|
|
850
|
+
items=params_in, delim=Tok.COMMA, kid=params_in
|
|
851
|
+
)
|
|
852
|
+
else:
|
|
853
|
+
params_in2 = None
|
|
854
|
+
if isinstance(func, ast.Expr):
|
|
855
|
+
return ast.FuncCall(
|
|
856
|
+
target=func,
|
|
857
|
+
params=params_in2,
|
|
858
|
+
kid=[func, params_in2] if params_in2 else [func],
|
|
859
|
+
)
|
|
860
|
+
else:
|
|
861
|
+
raise self.ice()
|
|
862
|
+
|
|
863
|
+
def proc_compare(self, node: py_ast.Compare) -> ast.CompareExpr:
|
|
864
|
+
"""Process python node.
|
|
865
|
+
|
|
866
|
+
class Compare(expr):
|
|
867
|
+
if sys.version_info >= (3, 10):
|
|
868
|
+
__match_args__ = ("left", "ops", "comparators")
|
|
869
|
+
left: expr
|
|
870
|
+
ops: list[cmpop]
|
|
871
|
+
comparators: list[expr]
|
|
872
|
+
"""
|
|
873
|
+
left = self.convert(node.left)
|
|
874
|
+
comparators = [self.convert(comparator) for comparator in node.comparators]
|
|
875
|
+
valid_comparators = [
|
|
876
|
+
comparator for comparator in comparators if isinstance(comparator, ast.Expr)
|
|
877
|
+
]
|
|
878
|
+
comparators2 = ast.SubNodeList[ast.Expr](
|
|
879
|
+
items=valid_comparators, delim=Tok.COMMA, kid=comparators
|
|
880
|
+
)
|
|
881
|
+
ops = [self.convert(op) for op in node.ops]
|
|
882
|
+
valid_ops = [op for op in ops if isinstance(op, ast.Token)]
|
|
883
|
+
ops2 = ast.SubNodeList[ast.Token](items=valid_ops, delim=Tok.COMMA, kid=ops)
|
|
884
|
+
|
|
885
|
+
kids = [left, ops2, comparators2]
|
|
886
|
+
if (
|
|
887
|
+
isinstance(left, ast.Expr)
|
|
888
|
+
and len(ops) == len(valid_ops)
|
|
889
|
+
and len(comparators) == len(valid_comparators)
|
|
890
|
+
):
|
|
891
|
+
return ast.CompareExpr(
|
|
892
|
+
left=left, rights=valid_comparators, ops=valid_ops, kid=kids
|
|
893
|
+
)
|
|
894
|
+
else:
|
|
895
|
+
raise self.ice()
|
|
510
896
|
|
|
511
897
|
def proc_constant(self, node: py_ast.Constant) -> ast.Literal:
|
|
512
898
|
"""Process python node.
|
|
@@ -518,37 +904,155 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
518
904
|
s: Any
|
|
519
905
|
n: int | float | complex
|
|
520
906
|
"""
|
|
521
|
-
|
|
522
|
-
|
|
907
|
+
type_mapping = {
|
|
908
|
+
int: ast.Int,
|
|
909
|
+
float: ast.Float,
|
|
910
|
+
str: ast.String,
|
|
911
|
+
bytes: ast.String,
|
|
912
|
+
bool: ast.Bool,
|
|
913
|
+
type(None): ast.Null,
|
|
914
|
+
}
|
|
915
|
+
value_type = type(node.value)
|
|
916
|
+
if value_type in type_mapping:
|
|
917
|
+
if value_type is None:
|
|
918
|
+
token_type = "NULL"
|
|
919
|
+
elif value_type == str:
|
|
920
|
+
token_type = "STRING"
|
|
921
|
+
else:
|
|
922
|
+
token_type = f"{value_type.__name__.upper()}"
|
|
923
|
+
|
|
924
|
+
return type_mapping[value_type](
|
|
523
925
|
file_path=self.mod_path,
|
|
524
|
-
name=
|
|
525
|
-
value=node.value,
|
|
926
|
+
name=token_type,
|
|
927
|
+
value=str(node.value),
|
|
526
928
|
line=node.lineno,
|
|
527
929
|
col_start=node.col_offset,
|
|
528
|
-
col_end=node.col_offset + len(node.value),
|
|
930
|
+
col_end=node.col_offset + len(str(node.value)),
|
|
529
931
|
pos_start=0,
|
|
530
932
|
pos_end=0,
|
|
531
|
-
kid=[],
|
|
532
933
|
)
|
|
533
934
|
else:
|
|
534
|
-
raise self.ice()
|
|
935
|
+
raise self.ice("Invalid type for constant")
|
|
535
936
|
|
|
536
|
-
def proc_continue(self, node: py_ast.Continue) ->
|
|
937
|
+
def proc_continue(self, node: py_ast.Continue) -> ast.CtrlStmt:
|
|
537
938
|
"""Process python node."""
|
|
939
|
+
continue_tok = ast.Token(
|
|
940
|
+
file_path=self.mod_path,
|
|
941
|
+
name=Tok.KW_CONTINUE,
|
|
942
|
+
value="continue",
|
|
943
|
+
line=0,
|
|
944
|
+
col_start=0,
|
|
945
|
+
col_end=0,
|
|
946
|
+
pos_start=0,
|
|
947
|
+
pos_end=0,
|
|
948
|
+
)
|
|
949
|
+
return ast.CtrlStmt(ctrl=continue_tok, kid=[continue_tok])
|
|
538
950
|
|
|
539
|
-
def proc_dict(self, node: py_ast.Dict) ->
|
|
540
|
-
"""Process python node.
|
|
951
|
+
def proc_dict(self, node: py_ast.Dict) -> ast.DictVal:
|
|
952
|
+
"""Process python node.
|
|
541
953
|
|
|
542
|
-
|
|
543
|
-
|
|
954
|
+
class Dict(expr):
|
|
955
|
+
keys: list[expr | None]
|
|
956
|
+
values: list[expr]
|
|
957
|
+
"""
|
|
958
|
+
keys = [self.convert(i) if i else None for i in node.keys]
|
|
959
|
+
values = [self.convert(i) for i in node.values]
|
|
960
|
+
valid_keys = [i for i in keys if isinstance(i, ast.Expr) or i is None]
|
|
961
|
+
valid_values = [i for i in values if isinstance(i, ast.Expr)]
|
|
962
|
+
kvpair: list[ast.KVPair] = []
|
|
963
|
+
for i in range(len(values)):
|
|
964
|
+
key_pluck = valid_keys[i]
|
|
965
|
+
kvp = ast.KVPair(
|
|
966
|
+
key=key_pluck,
|
|
967
|
+
value=valid_values[i],
|
|
968
|
+
kid=(
|
|
969
|
+
[key_pluck, valid_values[i]]
|
|
970
|
+
if key_pluck is not None
|
|
971
|
+
else [valid_values[i]]
|
|
972
|
+
),
|
|
973
|
+
)
|
|
974
|
+
kvpair.append(kvp)
|
|
975
|
+
return ast.DictVal(
|
|
976
|
+
kv_pairs=kvpair,
|
|
977
|
+
kid=(
|
|
978
|
+
[*kvpair]
|
|
979
|
+
if len(kvpair)
|
|
980
|
+
else [self.operator(Tok.LBRACE, "{"), self.operator(Tok.RBRACE, "}")]
|
|
981
|
+
),
|
|
982
|
+
)
|
|
983
|
+
|
|
984
|
+
def proc_dict_comp(self, node: py_ast.DictComp) -> ast.DictCompr:
|
|
985
|
+
"""Process python node.
|
|
986
|
+
|
|
987
|
+
class DictComp(expr):
|
|
988
|
+
key: expr
|
|
989
|
+
value: expr
|
|
990
|
+
generators: list[comprehension]
|
|
991
|
+
"""
|
|
992
|
+
key = self.convert(node.key)
|
|
993
|
+
value = self.convert(node.value)
|
|
994
|
+
if isinstance(key, ast.Expr) and isinstance(value, ast.Expr):
|
|
995
|
+
kv_pair = ast.KVPair(key=key, value=value, kid=[key, value])
|
|
996
|
+
else:
|
|
997
|
+
raise self.ice()
|
|
998
|
+
generators = [self.convert(i) for i in node.generators]
|
|
999
|
+
valid = [i for i in generators if isinstance(i, (ast.InnerCompr))]
|
|
1000
|
+
if len(valid) != len(generators):
|
|
1001
|
+
raise self.ice("Length mismatch in dict compr generators")
|
|
1002
|
+
compr = ast.SubNodeList[ast.InnerCompr](items=valid, delim=Tok.COMMA, kid=valid)
|
|
1003
|
+
return ast.DictCompr(kv_pair=kv_pair, compr=valid, kid=[kv_pair, compr])
|
|
544
1004
|
|
|
545
1005
|
def proc_ellipsis(self, node: py_ast.Ellipsis) -> None:
|
|
546
1006
|
"""Process python node."""
|
|
547
1007
|
|
|
548
|
-
def proc_except_handler(self, node: py_ast.ExceptHandler) ->
|
|
549
|
-
"""Process python node.
|
|
1008
|
+
def proc_except_handler(self, node: py_ast.ExceptHandler) -> ast.Except:
|
|
1009
|
+
"""Process python node.
|
|
1010
|
+
|
|
1011
|
+
class ExceptHandler(excepthandler):
|
|
1012
|
+
type: expr | None
|
|
1013
|
+
name: _Identifier | None
|
|
1014
|
+
body: list[stmt]
|
|
1015
|
+
"""
|
|
1016
|
+
type = self.convert(node.type) if node.type is not None else None
|
|
1017
|
+
name = (
|
|
1018
|
+
ast.Name(
|
|
1019
|
+
file_path=self.mod_path,
|
|
1020
|
+
name=Tok.NAME,
|
|
1021
|
+
value=node.name,
|
|
1022
|
+
line=node.lineno,
|
|
1023
|
+
col_start=node.col_offset,
|
|
1024
|
+
col_end=node.col_offset + len(node.name),
|
|
1025
|
+
pos_start=0,
|
|
1026
|
+
pos_end=0,
|
|
1027
|
+
)
|
|
1028
|
+
if node.name is not None
|
|
1029
|
+
else None
|
|
1030
|
+
)
|
|
1031
|
+
|
|
1032
|
+
body = [self.convert(i) for i in node.body]
|
|
1033
|
+
valid = [i for i in body if isinstance(i, (ast.CodeBlockStmt))]
|
|
1034
|
+
if len(valid) != len(body):
|
|
1035
|
+
raise self.ice("Length mismatch in except handler body")
|
|
1036
|
+
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1037
|
+
items=valid, delim=Tok.WS, kid=valid
|
|
1038
|
+
)
|
|
1039
|
+
kid = []
|
|
1040
|
+
if type:
|
|
1041
|
+
kid.append(type)
|
|
1042
|
+
if name:
|
|
1043
|
+
kid.append(name)
|
|
1044
|
+
kid.append(valid_body)
|
|
1045
|
+
if isinstance(type, ast.Expr) and (isinstance(name, ast.Name) or not name):
|
|
1046
|
+
return ast.Except(
|
|
1047
|
+
ex_type=type,
|
|
1048
|
+
name=name,
|
|
1049
|
+
body=valid_body,
|
|
1050
|
+
kid=kid,
|
|
1051
|
+
)
|
|
1052
|
+
else:
|
|
1053
|
+
raise self.ice()
|
|
550
1054
|
|
|
551
|
-
def proc_expr(self, node: py_ast.Expr) -> ast.
|
|
1055
|
+
def proc_expr(self, node: py_ast.Expr) -> ast.ExprStmt:
|
|
552
1056
|
"""Process python node.
|
|
553
1057
|
|
|
554
1058
|
class Expr(stmt):
|
|
@@ -556,135 +1060,1204 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
556
1060
|
"""
|
|
557
1061
|
value = self.convert(node.value)
|
|
558
1062
|
if isinstance(value, ast.Expr):
|
|
559
|
-
return value
|
|
1063
|
+
return ast.ExprStmt(expr=value, in_fstring=False, kid=[value])
|
|
560
1064
|
else:
|
|
561
1065
|
raise self.ice()
|
|
562
1066
|
|
|
563
|
-
def proc_formatted_value(self, node: py_ast.FormattedValue) ->
|
|
564
|
-
"""Process python node.
|
|
1067
|
+
def proc_formatted_value(self, node: py_ast.FormattedValue) -> ast.ExprStmt:
|
|
1068
|
+
"""Process python node.
|
|
1069
|
+
|
|
1070
|
+
class FormattedValue(expr):
|
|
1071
|
+
if sys.version_info >= (3, 10):
|
|
1072
|
+
__match_args__ = ("value", "conversion", "format_spec")
|
|
1073
|
+
value: expr
|
|
1074
|
+
conversion: int
|
|
1075
|
+
format_spec: expr | None
|
|
1076
|
+
"""
|
|
1077
|
+
value = self.convert(node.value)
|
|
1078
|
+
if isinstance(value, ast.Expr):
|
|
1079
|
+
ret = ast.ExprStmt(
|
|
1080
|
+
expr=value,
|
|
1081
|
+
in_fstring=True,
|
|
1082
|
+
kid=[value],
|
|
1083
|
+
)
|
|
1084
|
+
else:
|
|
1085
|
+
raise self.ice()
|
|
1086
|
+
return ret
|
|
565
1087
|
|
|
566
1088
|
def proc_function_type(self, node: py_ast.FunctionType) -> None:
|
|
567
1089
|
"""Process python node."""
|
|
568
1090
|
|
|
569
|
-
def proc_generator_exp(self, node: py_ast.GeneratorExp) ->
|
|
570
|
-
"""Process python node
|
|
1091
|
+
def proc_generator_exp(self, node: py_ast.GeneratorExp) -> ast.GenCompr:
|
|
1092
|
+
"""Process python node..
|
|
571
1093
|
|
|
572
|
-
|
|
573
|
-
|
|
1094
|
+
class SetComp(expr):
|
|
1095
|
+
elt: expr
|
|
1096
|
+
generators: list[comprehension]
|
|
1097
|
+
"""
|
|
1098
|
+
elt = self.convert(node.elt)
|
|
1099
|
+
generators = [self.convert(gen) for gen in node.generators]
|
|
1100
|
+
valid = [gen for gen in generators if isinstance(gen, ast.InnerCompr)]
|
|
1101
|
+
if len(generators) != len(valid):
|
|
1102
|
+
raise self.ice("Length mismatch in list comp generators")
|
|
1103
|
+
compr = ast.SubNodeList[ast.InnerCompr](items=valid, delim=Tok.COMMA, kid=valid)
|
|
1104
|
+
if isinstance(elt, ast.Expr):
|
|
1105
|
+
return ast.GenCompr(out_expr=elt, compr=valid, kid=[elt, compr])
|
|
1106
|
+
else:
|
|
1107
|
+
raise self.ice()
|
|
574
1108
|
|
|
575
|
-
def
|
|
576
|
-
"""Process python node.
|
|
1109
|
+
def proc_global(self, node: py_ast.Global) -> ast.GlobalStmt:
|
|
1110
|
+
"""Process python node.
|
|
577
1111
|
|
|
578
|
-
|
|
579
|
-
|
|
1112
|
+
class Global(stmt):
|
|
1113
|
+
names: list[_Identifier]
|
|
1114
|
+
"""
|
|
1115
|
+
names: list[ast.NameSpec] = []
|
|
1116
|
+
for id in node.names:
|
|
1117
|
+
names.append(
|
|
1118
|
+
ast.Name(
|
|
1119
|
+
file_path=self.mod_path,
|
|
1120
|
+
name=Tok.NAME,
|
|
1121
|
+
value=id,
|
|
1122
|
+
line=node.lineno,
|
|
1123
|
+
col_start=node.col_offset,
|
|
1124
|
+
col_end=node.col_offset + len(id),
|
|
1125
|
+
pos_start=0,
|
|
1126
|
+
pos_end=0,
|
|
1127
|
+
)
|
|
1128
|
+
)
|
|
1129
|
+
target = ast.SubNodeList[ast.NameSpec](items=names, delim=Tok.COMMA, kid=names)
|
|
1130
|
+
return ast.GlobalStmt(target=target, kid=[target])
|
|
580
1131
|
|
|
581
|
-
def
|
|
582
|
-
"""Process python node.
|
|
1132
|
+
def proc_if_exp(self, node: py_ast.IfExp) -> ast.IfElseExpr:
|
|
1133
|
+
"""Process python node.
|
|
583
1134
|
|
|
584
|
-
|
|
585
|
-
|
|
1135
|
+
class IfExp(expr):
|
|
1136
|
+
test: expr
|
|
1137
|
+
body: expr
|
|
1138
|
+
orelse: expr
|
|
1139
|
+
"""
|
|
1140
|
+
test = self.convert(node.test)
|
|
1141
|
+
body = self.convert(node.body)
|
|
1142
|
+
orelse = self.convert(node.orelse)
|
|
1143
|
+
if (
|
|
1144
|
+
isinstance(test, ast.Expr)
|
|
1145
|
+
and isinstance(body, ast.Expr)
|
|
1146
|
+
and isinstance(orelse, ast.Expr)
|
|
1147
|
+
):
|
|
1148
|
+
return ast.IfElseExpr(
|
|
1149
|
+
value=body, condition=test, else_value=orelse, kid=[body, test, orelse]
|
|
1150
|
+
)
|
|
1151
|
+
else:
|
|
1152
|
+
raise self.ice()
|
|
586
1153
|
|
|
587
|
-
def
|
|
588
|
-
"""Process python node.
|
|
1154
|
+
def proc_import(self, node: py_ast.Import) -> ast.Import:
|
|
1155
|
+
"""Process python node.
|
|
589
1156
|
|
|
590
|
-
|
|
591
|
-
|
|
1157
|
+
class Import(stmt):
|
|
1158
|
+
names: list[alias]
|
|
1159
|
+
"""
|
|
1160
|
+
names = [self.convert(name) for name in node.names]
|
|
1161
|
+
valid_names = [name for name in names if isinstance(name, ast.ExprAsItem)]
|
|
1162
|
+
if len(valid_names) != len(names):
|
|
1163
|
+
self.error("Length mismatch in import names")
|
|
1164
|
+
paths = []
|
|
1165
|
+
for name in valid_names:
|
|
1166
|
+
if isinstance(name.expr, ast.Name) and (
|
|
1167
|
+
isinstance(name.alias, ast.Name) or name.alias is None
|
|
1168
|
+
):
|
|
1169
|
+
paths.append(
|
|
1170
|
+
ast.ModulePath(
|
|
1171
|
+
path=[name.expr],
|
|
1172
|
+
level=0,
|
|
1173
|
+
alias=name.alias,
|
|
1174
|
+
kid=[i for i in name.kid if i],
|
|
1175
|
+
)
|
|
1176
|
+
)
|
|
1177
|
+
# Need to unravel atom trailers
|
|
1178
|
+
else:
|
|
1179
|
+
raise self.ice()
|
|
1180
|
+
lang = ast.Name(
|
|
1181
|
+
file_path=self.mod_path,
|
|
1182
|
+
name=Tok.NAME,
|
|
1183
|
+
value="py",
|
|
1184
|
+
line=node.lineno,
|
|
1185
|
+
col_start=node.col_offset,
|
|
1186
|
+
col_end=0,
|
|
1187
|
+
pos_start=0,
|
|
1188
|
+
pos_end=0,
|
|
1189
|
+
)
|
|
1190
|
+
pytag = ast.SubTag[ast.Name](tag=lang, kid=[lang])
|
|
1191
|
+
ret = ast.Import(
|
|
1192
|
+
lang=pytag,
|
|
1193
|
+
paths=paths,
|
|
1194
|
+
items=None,
|
|
1195
|
+
is_absorb=False,
|
|
1196
|
+
kid=[pytag, *paths],
|
|
1197
|
+
)
|
|
1198
|
+
return ret
|
|
592
1199
|
|
|
593
|
-
def
|
|
594
|
-
"""Process python node.
|
|
1200
|
+
def proc_import_from(self, node: py_ast.ImportFrom) -> ast.Import:
|
|
1201
|
+
"""Process python node.
|
|
1202
|
+
|
|
1203
|
+
class ImportFrom(stmt):
|
|
1204
|
+
module: str | None
|
|
1205
|
+
names: list[alias]
|
|
1206
|
+
level: int
|
|
1207
|
+
"""
|
|
1208
|
+
lang = ast.Name(
|
|
1209
|
+
file_path=self.mod_path,
|
|
1210
|
+
name=Tok.NAME,
|
|
1211
|
+
value="py",
|
|
1212
|
+
line=node.lineno,
|
|
1213
|
+
col_start=node.col_offset,
|
|
1214
|
+
col_end=0,
|
|
1215
|
+
pos_start=0,
|
|
1216
|
+
pos_end=0,
|
|
1217
|
+
)
|
|
1218
|
+
modpaths: list[ast.Name] = []
|
|
1219
|
+
if node.module:
|
|
1220
|
+
for i in node.module.split("."):
|
|
1221
|
+
modpaths.append(
|
|
1222
|
+
ast.Name(
|
|
1223
|
+
file_path=self.mod_path,
|
|
1224
|
+
name=Tok.NAME,
|
|
1225
|
+
value=i,
|
|
1226
|
+
line=node.lineno,
|
|
1227
|
+
col_start=0,
|
|
1228
|
+
col_end=0,
|
|
1229
|
+
pos_start=0,
|
|
1230
|
+
pos_end=0,
|
|
1231
|
+
)
|
|
1232
|
+
)
|
|
1233
|
+
path = ast.ModulePath(
|
|
1234
|
+
path=modpaths,
|
|
1235
|
+
level=node.level,
|
|
1236
|
+
alias=None,
|
|
1237
|
+
kid=modpaths,
|
|
1238
|
+
)
|
|
1239
|
+
names = [self.convert(name) for name in node.names]
|
|
1240
|
+
valid_names = []
|
|
1241
|
+
for name in names:
|
|
1242
|
+
if (
|
|
1243
|
+
isinstance(name, ast.ExprAsItem)
|
|
1244
|
+
and isinstance(name.expr, ast.Name)
|
|
1245
|
+
and (isinstance(name.alias, ast.Name) or name.alias is None)
|
|
1246
|
+
):
|
|
1247
|
+
valid_names.append(
|
|
1248
|
+
ast.ModuleItem(
|
|
1249
|
+
name=name.expr,
|
|
1250
|
+
alias=name.alias if name.alias is not None else None,
|
|
1251
|
+
kid=[i for i in name.kid if i],
|
|
1252
|
+
)
|
|
1253
|
+
)
|
|
1254
|
+
else:
|
|
1255
|
+
raise self.ice()
|
|
1256
|
+
items = (
|
|
1257
|
+
ast.SubNodeList[ast.ModuleItem](
|
|
1258
|
+
items=valid_names, delim=Tok.COMMA, kid=valid_names
|
|
1259
|
+
)
|
|
1260
|
+
if valid_names
|
|
1261
|
+
else None
|
|
1262
|
+
)
|
|
1263
|
+
if not items:
|
|
1264
|
+
raise self.ice("No valid names in import from")
|
|
1265
|
+
pytag = ast.SubTag[ast.Name](tag=lang, kid=[lang])
|
|
1266
|
+
ret = ast.Import(
|
|
1267
|
+
lang=pytag,
|
|
1268
|
+
paths=[path],
|
|
1269
|
+
items=items,
|
|
1270
|
+
is_absorb=False,
|
|
1271
|
+
kid=[pytag, path, items],
|
|
1272
|
+
)
|
|
1273
|
+
return ret
|
|
1274
|
+
|
|
1275
|
+
def proc_joined_str(self, node: py_ast.JoinedStr) -> ast.FString:
|
|
1276
|
+
"""Process python node.
|
|
1277
|
+
|
|
1278
|
+
class JoinedStr(expr):
|
|
1279
|
+
if sys.version_info >= (3, 10):
|
|
1280
|
+
__match_args__ = ("values",)
|
|
1281
|
+
values: list[expr]
|
|
1282
|
+
"""
|
|
1283
|
+
values = [self.convert(value) for value in node.values]
|
|
1284
|
+
valid = [
|
|
1285
|
+
value for value in values if isinstance(value, (ast.String, ast.ExprStmt))
|
|
1286
|
+
]
|
|
1287
|
+
valid_values = ast.SubNodeList[ast.String | ast.ExprStmt](
|
|
1288
|
+
items=valid, delim=None, kid=valid
|
|
1289
|
+
)
|
|
1290
|
+
return ast.FString(parts=valid_values, kid=[valid_values])
|
|
1291
|
+
|
|
1292
|
+
def proc_lambda(self, node: py_ast.Lambda) -> ast.LambdaExpr:
|
|
1293
|
+
"""Process python node.
|
|
1294
|
+
|
|
1295
|
+
class Lambda(expr):
|
|
1296
|
+
args: arguments
|
|
1297
|
+
body: expr
|
|
1298
|
+
"""
|
|
1299
|
+
args = self.convert(node.args)
|
|
1300
|
+
body = self.convert(node.body)
|
|
1301
|
+
if isinstance(args, ast.FuncSignature) and isinstance(body, ast.Expr):
|
|
1302
|
+
return ast.LambdaExpr(signature=args, body=body, kid=[args, body])
|
|
1303
|
+
else:
|
|
1304
|
+
raise self.ice()
|
|
1305
|
+
|
|
1306
|
+
def proc_list(self, node: py_ast.List) -> ast.ListVal:
|
|
1307
|
+
"""Process python node.
|
|
1308
|
+
|
|
1309
|
+
class List(expr):
|
|
1310
|
+
elts: list[expr]
|
|
1311
|
+
ctx: expr_context
|
|
1312
|
+
"""
|
|
1313
|
+
elts = [self.convert(elt) for elt in node.elts]
|
|
1314
|
+
valid_elts = [elt for elt in elts if isinstance(elt, ast.Expr)]
|
|
1315
|
+
if len(valid_elts) != len(elts):
|
|
1316
|
+
raise self.ice("Length mismatch in list elements")
|
|
1317
|
+
l_square = self.operator(Tok.LSQUARE, "[")
|
|
1318
|
+
r_square = self.operator(Tok.RSQUARE, "]")
|
|
1319
|
+
return ast.ListVal(
|
|
1320
|
+
values=(
|
|
1321
|
+
ast.SubNodeList[ast.Expr](
|
|
1322
|
+
items=valid_elts, delim=Tok.COMMA, kid=valid_elts
|
|
1323
|
+
)
|
|
1324
|
+
if valid_elts
|
|
1325
|
+
else None
|
|
1326
|
+
),
|
|
1327
|
+
kid=[*valid_elts] if valid_elts else [l_square, r_square],
|
|
1328
|
+
)
|
|
1329
|
+
|
|
1330
|
+
def proc_list_comp(self, node: py_ast.ListComp) -> ast.ListCompr:
|
|
1331
|
+
"""Process python node.
|
|
1332
|
+
|
|
1333
|
+
class ListComp(expr):
|
|
1334
|
+
elt: expr
|
|
1335
|
+
generators: list[comprehension]
|
|
1336
|
+
"""
|
|
1337
|
+
elt = self.convert(node.elt)
|
|
1338
|
+
generators = [self.convert(gen) for gen in node.generators]
|
|
1339
|
+
valid = [gen for gen in generators if isinstance(gen, ast.InnerCompr)]
|
|
1340
|
+
if len(generators) != len(valid):
|
|
1341
|
+
raise self.ice("Length mismatch in list comp generators")
|
|
1342
|
+
compr = ast.SubNodeList[ast.InnerCompr](items=valid, delim=Tok.COMMA, kid=valid)
|
|
1343
|
+
if isinstance(elt, ast.Expr):
|
|
1344
|
+
return ast.ListCompr(out_expr=elt, compr=valid, kid=[elt, compr])
|
|
1345
|
+
else:
|
|
1346
|
+
raise self.ice()
|
|
1347
|
+
|
|
1348
|
+
def proc_match(self, node: py_ast.Match) -> ast.MatchStmt:
|
|
1349
|
+
"""Process python node.
|
|
1350
|
+
|
|
1351
|
+
class Match(stmt):
|
|
1352
|
+
subject: expr
|
|
1353
|
+
cases: list[match_case]
|
|
1354
|
+
"""
|
|
1355
|
+
subject = self.convert(node.subject)
|
|
1356
|
+
cases = [self.convert(i) for i in node.cases]
|
|
1357
|
+
valid = [case for case in cases if isinstance(case, ast.MatchCase)]
|
|
1358
|
+
if isinstance(subject, ast.Expr):
|
|
1359
|
+
return ast.MatchStmt(target=subject, cases=valid, kid=[subject, *valid])
|
|
1360
|
+
else:
|
|
1361
|
+
raise self.ice()
|
|
1362
|
+
|
|
1363
|
+
def proc_match_as(self, node: py_ast.MatchAs) -> ast.MatchAs:
|
|
1364
|
+
"""Process python node.
|
|
1365
|
+
|
|
1366
|
+
class MatchAs(pattern):
|
|
1367
|
+
pattern: _Pattern | None
|
|
1368
|
+
name: _Identifier | None
|
|
1369
|
+
"""
|
|
1370
|
+
pattern = self.convert(node.pattern) if node.pattern is not None else None
|
|
1371
|
+
name = ast.Name(
|
|
1372
|
+
file_path=self.mod_path,
|
|
1373
|
+
name=Tok.NAME,
|
|
1374
|
+
value=node.name if node.name is not None else "_",
|
|
1375
|
+
line=node.lineno,
|
|
1376
|
+
col_start=node.col_offset,
|
|
1377
|
+
col_end=node.col_offset + len(node.name if node.name is not None else "_"),
|
|
1378
|
+
pos_start=0,
|
|
1379
|
+
pos_end=0,
|
|
1380
|
+
)
|
|
1381
|
+
if isinstance(pattern, ast.MatchPattern) or pattern is None:
|
|
1382
|
+
return ast.MatchAs(
|
|
1383
|
+
name=name,
|
|
1384
|
+
pattern=pattern,
|
|
1385
|
+
kid=[name, pattern] if pattern is not None else [name],
|
|
1386
|
+
)
|
|
1387
|
+
else:
|
|
1388
|
+
raise self.ice()
|
|
1389
|
+
|
|
1390
|
+
def proc_match_class(self, node: py_ast.MatchClass) -> ast.MatchArch:
|
|
1391
|
+
"""Process python node.
|
|
1392
|
+
|
|
1393
|
+
class MatchClass(pattern):
|
|
1394
|
+
cls: expr
|
|
1395
|
+
patterns: list[pattern]
|
|
1396
|
+
kwd_attrs: list[_Identifier]
|
|
1397
|
+
kwd_patterns: list[pattern]
|
|
1398
|
+
"""
|
|
1399
|
+
cls = self.convert(node.cls)
|
|
1400
|
+
kid = [cls]
|
|
1401
|
+
if len(node.patterns) != 0:
|
|
1402
|
+
patterns = [self.convert(i) for i in node.patterns]
|
|
1403
|
+
valid_patterns = [i for i in patterns if isinstance(i, ast.MatchPattern)]
|
|
1404
|
+
if len(patterns) == len(valid_patterns):
|
|
1405
|
+
patterns_sub = ast.SubNodeList[ast.MatchPattern](
|
|
1406
|
+
items=valid_patterns, delim=Tok.COMMA, kid=valid_patterns
|
|
1407
|
+
)
|
|
1408
|
+
kid.append(patterns_sub)
|
|
1409
|
+
else:
|
|
1410
|
+
raise self.ice()
|
|
1411
|
+
else:
|
|
1412
|
+
patterns_sub = None
|
|
1413
|
+
|
|
1414
|
+
if len(node.kwd_patterns):
|
|
1415
|
+
names: list[ast.Name] = []
|
|
1416
|
+
kv_pairs: list[ast.MatchKVPair] = []
|
|
1417
|
+
for kwd_attrs in node.kwd_attrs:
|
|
1418
|
+
names.append(
|
|
1419
|
+
ast.Name(
|
|
1420
|
+
file_path=self.mod_path,
|
|
1421
|
+
name=Tok.NAME,
|
|
1422
|
+
value=kwd_attrs,
|
|
1423
|
+
line=node.lineno,
|
|
1424
|
+
col_start=node.col_offset,
|
|
1425
|
+
col_end=node.col_offset + len(kwd_attrs),
|
|
1426
|
+
pos_start=0,
|
|
1427
|
+
pos_end=0,
|
|
1428
|
+
)
|
|
1429
|
+
)
|
|
1430
|
+
kwd_patterns = [self.convert(i) for i in node.kwd_patterns]
|
|
1431
|
+
valid_kwd_patterns = [
|
|
1432
|
+
i for i in kwd_patterns if isinstance(i, ast.MatchPattern)
|
|
1433
|
+
]
|
|
1434
|
+
for i in range(len(kwd_patterns)):
|
|
1435
|
+
kv_pairs.append(
|
|
1436
|
+
ast.MatchKVPair(
|
|
1437
|
+
key=names[i],
|
|
1438
|
+
value=valid_kwd_patterns[i],
|
|
1439
|
+
kid=[names[i], valid_kwd_patterns[i]],
|
|
1440
|
+
)
|
|
1441
|
+
)
|
|
1442
|
+
kw_patterns = ast.SubNodeList[ast.MatchKVPair](
|
|
1443
|
+
items=kv_pairs, delim=Tok.COMMA, kid=kv_pairs
|
|
1444
|
+
)
|
|
1445
|
+
kid.append(kw_patterns)
|
|
1446
|
+
if isinstance(cls, ast.NameSpec):
|
|
1447
|
+
return ast.MatchArch(
|
|
1448
|
+
name=cls, arg_patterns=patterns_sub, kw_patterns=kw_patterns, kid=kid
|
|
1449
|
+
)
|
|
1450
|
+
else:
|
|
1451
|
+
raise self.ice()
|
|
1452
|
+
|
|
1453
|
+
def proc_match_mapping(self, node: py_ast.MatchMapping) -> ast.MatchMapping:
|
|
1454
|
+
"""Process python node.
|
|
1455
|
+
|
|
1456
|
+
class MatchMapping(pattern):
|
|
1457
|
+
keys: list[expr]
|
|
1458
|
+
patterns: list[pattern]
|
|
1459
|
+
rest: _Identifier | None
|
|
1460
|
+
"""
|
|
1461
|
+
values: list[ast.MatchKVPair | ast.MatchStar] = []
|
|
1462
|
+
keys = [self.convert(i) for i in node.keys]
|
|
1463
|
+
valid_keys = [
|
|
1464
|
+
i for i in keys if isinstance(i, (ast.MatchPattern, ast.NameSpec))
|
|
1465
|
+
]
|
|
1466
|
+
patterns = [self.convert(i) for i in node.patterns]
|
|
1467
|
+
valid_patterns = [i for i in patterns if isinstance(i, ast.MatchPattern)]
|
|
1468
|
+
for i in range(len(valid_keys)):
|
|
1469
|
+
kv_pair = ast.MatchKVPair(
|
|
1470
|
+
key=valid_keys[i],
|
|
1471
|
+
value=valid_patterns[i],
|
|
1472
|
+
kid=[valid_keys[i], valid_patterns[i]],
|
|
1473
|
+
)
|
|
1474
|
+
values.append(kv_pair)
|
|
1475
|
+
if node.rest:
|
|
1476
|
+
name = ast.Name(
|
|
1477
|
+
file_path=self.mod_path,
|
|
1478
|
+
name=Tok.NAME,
|
|
1479
|
+
value=node.rest,
|
|
1480
|
+
line=node.lineno,
|
|
1481
|
+
col_start=node.col_offset,
|
|
1482
|
+
col_end=node.col_offset + len(node.rest),
|
|
1483
|
+
pos_start=0,
|
|
1484
|
+
pos_end=0,
|
|
1485
|
+
)
|
|
1486
|
+
values.append(ast.MatchStar(name=name, is_list=True, kid=[name]))
|
|
1487
|
+
return ast.MatchMapping(values=values, kid=values)
|
|
1488
|
+
|
|
1489
|
+
def proc_match_or(self, node: py_ast.MatchOr) -> ast.MatchOr:
|
|
1490
|
+
"""Process python node.
|
|
1491
|
+
|
|
1492
|
+
class MatchOr(pattern):
|
|
1493
|
+
patterns: list[pattern]
|
|
1494
|
+
"""
|
|
1495
|
+
patterns = [self.convert(i) for i in node.patterns]
|
|
1496
|
+
valid = [i for i in patterns if isinstance(i, ast.MatchPattern)]
|
|
1497
|
+
return ast.MatchOr(patterns=valid, kid=valid)
|
|
1498
|
+
|
|
1499
|
+
def proc_match_sequence(self, node: py_ast.MatchSequence) -> ast.MatchSequence:
|
|
1500
|
+
"""Process python node.
|
|
1501
|
+
|
|
1502
|
+
class MatchSequence(pattern):
|
|
1503
|
+
patterns: list[pattern]
|
|
1504
|
+
"""
|
|
1505
|
+
patterns = [self.convert(i) for i in node.patterns]
|
|
1506
|
+
valid = [i for i in patterns if isinstance(i, ast.MatchPattern)]
|
|
1507
|
+
if len(patterns) == len(valid):
|
|
1508
|
+
return ast.MatchSequence(values=valid, kid=valid)
|
|
1509
|
+
else:
|
|
1510
|
+
raise self.ice()
|
|
1511
|
+
|
|
1512
|
+
def proc_match_singleton(self, node: py_ast.MatchSingleton) -> ast.MatchSingleton:
|
|
1513
|
+
"""Process python node.
|
|
1514
|
+
|
|
1515
|
+
class MatchSingleton(pattern):
|
|
1516
|
+
value: Literal[True, False] | None
|
|
1517
|
+
"""
|
|
1518
|
+
type = Tok.NULL if node.value is None else Tok.BOOL
|
|
1519
|
+
ret_type = ast.Null if node.value is None else ast.Bool
|
|
1520
|
+
value = ret_type(
|
|
1521
|
+
file_path=self.mod_path,
|
|
1522
|
+
name=type,
|
|
1523
|
+
value=str(node.value),
|
|
1524
|
+
line=node.lineno,
|
|
1525
|
+
col_start=node.col_offset,
|
|
1526
|
+
col_end=node.col_offset + len(str(node.value)),
|
|
1527
|
+
pos_start=0,
|
|
1528
|
+
pos_end=0,
|
|
1529
|
+
)
|
|
1530
|
+
if isinstance(value, (ast.Bool, ast.Null)):
|
|
1531
|
+
return ast.MatchSingleton(value=value, kid=[value])
|
|
1532
|
+
else:
|
|
1533
|
+
raise self.ice()
|
|
1534
|
+
|
|
1535
|
+
def proc_match_star(self, node: py_ast.MatchStar) -> ast.MatchStar:
|
|
1536
|
+
"""Process python node.
|
|
1537
|
+
|
|
1538
|
+
class MatchStar(pattern):
|
|
1539
|
+
name: _Identifier | None
|
|
1540
|
+
"""
|
|
1541
|
+
name = ast.Name(
|
|
1542
|
+
file_path=self.mod_path,
|
|
1543
|
+
name=Tok.NAME,
|
|
1544
|
+
value=node.name if node.name is not None else "_",
|
|
1545
|
+
line=node.lineno,
|
|
1546
|
+
col_start=node.col_offset,
|
|
1547
|
+
col_end=node.col_offset + len(node.name if node.name is not None else "_"),
|
|
1548
|
+
pos_start=0,
|
|
1549
|
+
pos_end=0,
|
|
1550
|
+
)
|
|
1551
|
+
return ast.MatchStar(name=name, is_list=True, kid=[name])
|
|
1552
|
+
|
|
1553
|
+
def proc_match_value(self, node: py_ast.MatchValue) -> ast.MatchValue:
|
|
1554
|
+
"""Process python node.
|
|
1555
|
+
|
|
1556
|
+
class MatchValue(pattern):
|
|
1557
|
+
value: expr
|
|
1558
|
+
"""
|
|
1559
|
+
value = self.convert(node.value)
|
|
1560
|
+
if isinstance(value, ast.Expr):
|
|
1561
|
+
return ast.MatchValue(value=value, kid=[value])
|
|
1562
|
+
else:
|
|
1563
|
+
raise self.ice()
|
|
1564
|
+
|
|
1565
|
+
def proc_name(self, node: py_ast.Name) -> ast.Name:
|
|
1566
|
+
"""Process python node.
|
|
595
1567
|
|
|
596
|
-
|
|
1568
|
+
class Name(expr):
|
|
1569
|
+
if sys.version_info >= (3, 10):
|
|
1570
|
+
__match_args__ = ("id", "ctx")
|
|
1571
|
+
id: _Identifier
|
|
1572
|
+
ctx: expr_context
|
|
1573
|
+
"""
|
|
1574
|
+
ret = ast.Name(
|
|
1575
|
+
file_path=self.mod_path,
|
|
1576
|
+
name=Tok.NAME,
|
|
1577
|
+
value=node.id,
|
|
1578
|
+
line=node.lineno,
|
|
1579
|
+
col_start=node.col_offset,
|
|
1580
|
+
col_end=node.col_offset + len(node.id),
|
|
1581
|
+
pos_start=0,
|
|
1582
|
+
pos_end=0,
|
|
1583
|
+
)
|
|
1584
|
+
return ret
|
|
1585
|
+
|
|
1586
|
+
def proc_named_expr(self, node: py_ast.NamedExpr) -> ast.BinaryExpr:
|
|
1587
|
+
"""Process python node.
|
|
1588
|
+
|
|
1589
|
+
class NamedExpr(expr):
|
|
1590
|
+
target: Name
|
|
1591
|
+
value: expr
|
|
1592
|
+
"""
|
|
1593
|
+
target = self.convert(node.target)
|
|
1594
|
+
value = self.convert(node.value)
|
|
1595
|
+
if isinstance(value, ast.Expr) and isinstance(target, ast.Name):
|
|
1596
|
+
return ast.BinaryExpr(
|
|
1597
|
+
left=target,
|
|
1598
|
+
op=self.operator(Tok.WALRUS_EQ, ":="),
|
|
1599
|
+
right=value,
|
|
1600
|
+
kid=[target, value],
|
|
1601
|
+
)
|
|
1602
|
+
else:
|
|
1603
|
+
raise self.ice()
|
|
1604
|
+
|
|
1605
|
+
def proc_nonlocal(self, node: py_ast.Nonlocal) -> ast.NonLocalStmt:
|
|
1606
|
+
"""Process python node.
|
|
1607
|
+
|
|
1608
|
+
class Nonlocal(stmt):
|
|
1609
|
+
names: list[_Identifier]
|
|
1610
|
+
"""
|
|
1611
|
+
names: list[ast.NameSpec] = []
|
|
1612
|
+
for name in node.names:
|
|
1613
|
+
names.append(
|
|
1614
|
+
ast.Name(
|
|
1615
|
+
file_path=self.mod_path,
|
|
1616
|
+
name=Tok.NAME,
|
|
1617
|
+
value=name,
|
|
1618
|
+
line=node.lineno,
|
|
1619
|
+
col_start=node.col_offset,
|
|
1620
|
+
col_end=node.col_offset + len(name),
|
|
1621
|
+
pos_start=0,
|
|
1622
|
+
pos_end=0,
|
|
1623
|
+
)
|
|
1624
|
+
)
|
|
1625
|
+
target = ast.SubNodeList[ast.NameSpec](items=names, delim=Tok.COMMA, kid=names)
|
|
1626
|
+
return ast.NonLocalStmt(target=target, kid=names)
|
|
1627
|
+
|
|
1628
|
+
def proc_pass(self, node: py_ast.Pass) -> ast.Semi:
|
|
597
1629
|
"""Process python node."""
|
|
1630
|
+
return ast.Semi(
|
|
1631
|
+
file_path=self.mod_path,
|
|
1632
|
+
name=Tok.SEMI,
|
|
1633
|
+
value=";",
|
|
1634
|
+
line=0,
|
|
1635
|
+
col_start=0,
|
|
1636
|
+
col_end=0,
|
|
1637
|
+
pos_start=0,
|
|
1638
|
+
pos_end=0,
|
|
1639
|
+
)
|
|
1640
|
+
|
|
1641
|
+
def proc_set(self, node: py_ast.Set) -> ast.SetVal:
|
|
1642
|
+
"""Process python node.
|
|
1643
|
+
|
|
1644
|
+
class Set(expr):
|
|
1645
|
+
elts: list[expr]
|
|
1646
|
+
"""
|
|
1647
|
+
if len(node.elts) != 0:
|
|
1648
|
+
elts = [self.convert(i) for i in node.elts]
|
|
1649
|
+
valid = [i for i in elts if isinstance(i, (ast.Expr))]
|
|
1650
|
+
if len(valid) != len(elts):
|
|
1651
|
+
raise self.ice("Length mismatch in set body")
|
|
1652
|
+
valid_elts = ast.SubNodeList[ast.Expr](
|
|
1653
|
+
items=valid, delim=Tok.COMMA, kid=valid
|
|
1654
|
+
)
|
|
1655
|
+
kid: list[ast.AstNode] = [*valid]
|
|
1656
|
+
else:
|
|
1657
|
+
valid_elts = None
|
|
1658
|
+
l_brace = self.operator(Tok.LBRACE, "{")
|
|
1659
|
+
r_brace = self.operator(Tok.RBRACE, "}")
|
|
1660
|
+
kid = [l_brace, r_brace]
|
|
1661
|
+
return ast.SetVal(values=valid_elts, kid=kid)
|
|
1662
|
+
|
|
1663
|
+
def proc_set_comp(self, node: py_ast.SetComp) -> ast.ListCompr:
|
|
1664
|
+
"""Process python node.
|
|
1665
|
+
|
|
1666
|
+
class SetComp(expr):
|
|
1667
|
+
elt: expr
|
|
1668
|
+
generators: list[comprehension]
|
|
1669
|
+
"""
|
|
1670
|
+
elt = self.convert(node.elt)
|
|
1671
|
+
generators = [self.convert(gen) for gen in node.generators]
|
|
1672
|
+
valid = [gen for gen in generators if isinstance(gen, ast.InnerCompr)]
|
|
1673
|
+
if len(generators) != len(valid):
|
|
1674
|
+
raise self.ice("Length mismatch in list comp generators")
|
|
1675
|
+
compr = ast.SubNodeList[ast.InnerCompr](items=valid, delim=Tok.COMMA, kid=valid)
|
|
1676
|
+
if isinstance(elt, ast.Expr):
|
|
1677
|
+
return ast.SetCompr(out_expr=elt, compr=valid, kid=[elt, compr])
|
|
1678
|
+
else:
|
|
1679
|
+
raise self.ice()
|
|
1680
|
+
|
|
1681
|
+
def proc_slice(self, node: py_ast.Slice) -> ast.IndexSlice:
|
|
1682
|
+
"""Process python node.
|
|
1683
|
+
|
|
1684
|
+
class Slice(_Slice):
|
|
1685
|
+
lower: expr | None
|
|
1686
|
+
upper: expr | None
|
|
1687
|
+
step: expr | None
|
|
1688
|
+
"""
|
|
1689
|
+
lower = self.convert(node.lower) if node.lower else None
|
|
1690
|
+
upper = self.convert(node.upper) if node.upper else None
|
|
1691
|
+
step = self.convert(node.step) if node.step else None
|
|
1692
|
+
valid_kid = [i for i in [lower, upper, step] if i]
|
|
1693
|
+
if not valid_kid:
|
|
1694
|
+
valid_kid = [self.operator(Tok.COLON, ":")]
|
|
1695
|
+
if (
|
|
1696
|
+
(isinstance(lower, ast.Expr) or lower is None)
|
|
1697
|
+
and (isinstance(upper, ast.Expr) or upper is None)
|
|
1698
|
+
and (isinstance(step, ast.Expr) or step is None)
|
|
1699
|
+
):
|
|
1700
|
+
return ast.IndexSlice(
|
|
1701
|
+
start=lower,
|
|
1702
|
+
stop=upper,
|
|
1703
|
+
step=step,
|
|
1704
|
+
is_range=True,
|
|
1705
|
+
kid=valid_kid,
|
|
1706
|
+
)
|
|
1707
|
+
else:
|
|
1708
|
+
raise self.ice()
|
|
1709
|
+
|
|
1710
|
+
def proc_starred(self, node: py_ast.Starred) -> ast.UnaryExpr:
|
|
1711
|
+
"""Process python node.
|
|
1712
|
+
|
|
1713
|
+
class Starred(expr):
|
|
1714
|
+
value: expr
|
|
1715
|
+
ctx: expr_context
|
|
1716
|
+
"""
|
|
1717
|
+
star_tok = self.operator(Tok.STAR_MUL, "*")
|
|
1718
|
+
value = self.convert(node.value)
|
|
1719
|
+
if isinstance(value, ast.Expr):
|
|
1720
|
+
return ast.UnaryExpr(operand=value, op=star_tok, kid=[value, star_tok])
|
|
1721
|
+
else:
|
|
1722
|
+
raise self.ice()
|
|
1723
|
+
|
|
1724
|
+
def proc_subscript(self, node: py_ast.Subscript) -> ast.AtomTrailer:
|
|
1725
|
+
"""Process python node.
|
|
1726
|
+
|
|
1727
|
+
class Subscript(expr):
|
|
1728
|
+
value: expr
|
|
1729
|
+
slice: _Slice
|
|
1730
|
+
ctx: expr_context
|
|
1731
|
+
"""
|
|
1732
|
+
value = self.convert(node.value)
|
|
1733
|
+
slice = self.convert(node.slice)
|
|
1734
|
+
if not isinstance(slice, ast.IndexSlice) and isinstance(slice, ast.Expr):
|
|
1735
|
+
slice = ast.IndexSlice(
|
|
1736
|
+
start=slice,
|
|
1737
|
+
stop=None,
|
|
1738
|
+
step=None,
|
|
1739
|
+
is_range=False,
|
|
1740
|
+
kid=[slice],
|
|
1741
|
+
)
|
|
1742
|
+
if isinstance(value, ast.Expr) and isinstance(slice, ast.IndexSlice):
|
|
1743
|
+
return ast.AtomTrailer(
|
|
1744
|
+
target=value,
|
|
1745
|
+
right=slice,
|
|
1746
|
+
is_attr=False,
|
|
1747
|
+
is_null_ok=False,
|
|
1748
|
+
kid=[value, slice],
|
|
1749
|
+
)
|
|
1750
|
+
else:
|
|
1751
|
+
raise self.ice()
|
|
1752
|
+
|
|
1753
|
+
def proc_try(self, node: py_ast.Try | py_ast.TryStar) -> ast.TryStmt:
|
|
1754
|
+
"""Process python node.
|
|
1755
|
+
|
|
1756
|
+
class Try(stmt):
|
|
1757
|
+
body: list[stmt]
|
|
1758
|
+
handlers: list[ExceptHandler]
|
|
1759
|
+
orelse: list[stmt]
|
|
1760
|
+
finalbody: list[stmt]
|
|
1761
|
+
"""
|
|
1762
|
+
body = [self.convert(i) for i in node.body]
|
|
1763
|
+
valid = [i for i in body if isinstance(i, (ast.CodeBlockStmt))]
|
|
1764
|
+
if len(valid) != len(body):
|
|
1765
|
+
raise self.ice("Length mismatch in try body")
|
|
1766
|
+
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1767
|
+
items=valid, delim=Tok.WS, kid=valid
|
|
1768
|
+
)
|
|
1769
|
+
kid: list[ast.AstNode] = [valid_body]
|
|
1770
|
+
|
|
1771
|
+
if len(node.handlers) != 0:
|
|
1772
|
+
handlers = [self.convert(i) for i in node.handlers]
|
|
1773
|
+
valid_handlers = [i for i in handlers if isinstance(i, (ast.Except))]
|
|
1774
|
+
if len(handlers) != len(valid_handlers):
|
|
1775
|
+
raise self.ice("Length mismatch in try handlers")
|
|
1776
|
+
excepts = ast.SubNodeList[ast.Except](
|
|
1777
|
+
items=valid_handlers, delim=Tok.WS, kid=valid_handlers
|
|
1778
|
+
)
|
|
1779
|
+
kid.append(excepts)
|
|
1780
|
+
else:
|
|
1781
|
+
excepts = None
|
|
1782
|
+
|
|
1783
|
+
if len(node.orelse) != 0:
|
|
1784
|
+
orelse = [self.convert(i) for i in node.orelse]
|
|
1785
|
+
valid_orelse = [i for i in orelse if isinstance(i, (ast.CodeBlockStmt))]
|
|
1786
|
+
if len(orelse) != len(valid_orelse):
|
|
1787
|
+
raise self.ice("Length mismatch in try orelse")
|
|
1788
|
+
else_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1789
|
+
items=valid_orelse, delim=Tok.WS, kid=valid_orelse
|
|
1790
|
+
)
|
|
1791
|
+
kid.append(else_body)
|
|
1792
|
+
else:
|
|
1793
|
+
else_body = None
|
|
1794
|
+
|
|
1795
|
+
if len(node.finalbody) != 0:
|
|
1796
|
+
finalbody = [self.convert(i) for i in node.finalbody]
|
|
1797
|
+
valid_finalbody = [
|
|
1798
|
+
i for i in finalbody if isinstance(i, (ast.CodeBlockStmt))
|
|
1799
|
+
]
|
|
1800
|
+
if len(finalbody) != len(valid_finalbody):
|
|
1801
|
+
raise self.ice("Length mismatch in try finalbody")
|
|
1802
|
+
finally_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1803
|
+
items=valid_finalbody, delim=Tok.WS, kid=valid_finalbody
|
|
1804
|
+
)
|
|
1805
|
+
kid.append(finally_body)
|
|
1806
|
+
else:
|
|
1807
|
+
finally_body = None
|
|
1808
|
+
|
|
1809
|
+
return ast.TryStmt(
|
|
1810
|
+
body=valid_body,
|
|
1811
|
+
excepts=excepts,
|
|
1812
|
+
else_body=(
|
|
1813
|
+
ast.ElseStmt(body=else_body, kid=[else_body]) if else_body else None
|
|
1814
|
+
),
|
|
1815
|
+
finally_body=(
|
|
1816
|
+
ast.FinallyStmt(body=finally_body, kid=[finally_body])
|
|
1817
|
+
if finally_body
|
|
1818
|
+
else None
|
|
1819
|
+
),
|
|
1820
|
+
kid=kid,
|
|
1821
|
+
)
|
|
1822
|
+
|
|
1823
|
+
def proc_try_star(self, node: py_ast.TryStar) -> ast.TryStmt:
|
|
1824
|
+
"""Process python node.
|
|
1825
|
+
|
|
1826
|
+
class Try(stmt):
|
|
1827
|
+
body: list[stmt]
|
|
1828
|
+
handlers: list[ExceptHandler]
|
|
1829
|
+
orelse: list[stmt]
|
|
1830
|
+
finalbody: list[stmt]
|
|
1831
|
+
"""
|
|
1832
|
+
return self.proc_try(node)
|
|
598
1833
|
|
|
599
|
-
def
|
|
1834
|
+
def proc_tuple(self, node: py_ast.Tuple) -> ast.TupleVal:
|
|
1835
|
+
"""Process python node.
|
|
1836
|
+
|
|
1837
|
+
class Tuple(expr):
|
|
1838
|
+
elts: list[expr]
|
|
1839
|
+
ctx: expr_context
|
|
1840
|
+
"""
|
|
1841
|
+
elts = [self.convert(elt) for elt in node.elts]
|
|
1842
|
+
if len(node.elts) != 0:
|
|
1843
|
+
valid = [i for i in elts if isinstance(i, (ast.Expr, ast.KWPair))]
|
|
1844
|
+
if len(elts) != len(valid):
|
|
1845
|
+
raise self.ice("Length mismatch in tuple elts")
|
|
1846
|
+
valid_elts = ast.SubNodeList[ast.Expr | ast.KWPair](
|
|
1847
|
+
items=valid, delim=Tok.COMMA, kid=valid
|
|
1848
|
+
)
|
|
1849
|
+
kid = elts
|
|
1850
|
+
else:
|
|
1851
|
+
l_paren = self.operator(Tok.LPAREN, "(")
|
|
1852
|
+
r_paren = self.operator(Tok.RPAREN, ")")
|
|
1853
|
+
valid_elts = None
|
|
1854
|
+
kid = [l_paren, r_paren]
|
|
1855
|
+
return ast.TupleVal(values=valid_elts, kid=kid)
|
|
1856
|
+
|
|
1857
|
+
def proc_yield(self, node: py_ast.Yield) -> ast.YieldExpr:
|
|
1858
|
+
"""Process python node.
|
|
1859
|
+
|
|
1860
|
+
class Yield(expr):
|
|
1861
|
+
value: expr | None
|
|
1862
|
+
"""
|
|
1863
|
+
value = self.convert(node.value) if node.value else None
|
|
1864
|
+
if isinstance(value, ast.Expr):
|
|
1865
|
+
return ast.YieldExpr(expr=value, with_from=False, kid=[value])
|
|
1866
|
+
else:
|
|
1867
|
+
raise self.ice()
|
|
1868
|
+
|
|
1869
|
+
def proc_yield_from(self, node: py_ast.YieldFrom) -> ast.YieldExpr:
|
|
600
1870
|
"""Process python node."""
|
|
1871
|
+
value = self.convert(node.value)
|
|
1872
|
+
if isinstance(value, ast.Expr):
|
|
1873
|
+
return ast.YieldExpr(expr=value, with_from=True, kid=[value])
|
|
1874
|
+
else:
|
|
1875
|
+
raise self.ice()
|
|
1876
|
+
|
|
1877
|
+
def proc_alias(self, node: py_ast.alias) -> ast.ExprAsItem:
|
|
1878
|
+
"""Process python node.
|
|
1879
|
+
|
|
1880
|
+
class alias(AST):
|
|
1881
|
+
name: _Identifier
|
|
1882
|
+
asname: _Identifier | None
|
|
1883
|
+
"""
|
|
1884
|
+
name = ast.Name(
|
|
1885
|
+
file_path=self.mod_path,
|
|
1886
|
+
name=Tok.NAME,
|
|
1887
|
+
value=node.name,
|
|
1888
|
+
line=node.lineno,
|
|
1889
|
+
col_start=node.col_offset,
|
|
1890
|
+
col_end=node.col_offset + len(node.name),
|
|
1891
|
+
pos_start=0,
|
|
1892
|
+
pos_end=0,
|
|
1893
|
+
)
|
|
1894
|
+
asname = (
|
|
1895
|
+
ast.Name(
|
|
1896
|
+
file_path=self.mod_path,
|
|
1897
|
+
name=Tok.NAME,
|
|
1898
|
+
value=node.asname,
|
|
1899
|
+
line=node.lineno,
|
|
1900
|
+
col_start=node.col_offset,
|
|
1901
|
+
col_end=node.col_offset + len(node.asname),
|
|
1902
|
+
pos_start=0,
|
|
1903
|
+
pos_end=0,
|
|
1904
|
+
)
|
|
1905
|
+
if node.asname
|
|
1906
|
+
else None
|
|
1907
|
+
)
|
|
1908
|
+
return ast.ExprAsItem(
|
|
1909
|
+
expr=name, alias=asname, kid=[name, asname] if asname else [name]
|
|
1910
|
+
)
|
|
1911
|
+
|
|
1912
|
+
def proc_arg(self, node: py_ast.arg) -> ast.ParamVar:
|
|
1913
|
+
"""Process python node.
|
|
1914
|
+
|
|
1915
|
+
class arg(AST):
|
|
1916
|
+
arg: _Identifier
|
|
1917
|
+
annotation: expr | None
|
|
1918
|
+
"""
|
|
1919
|
+
name = ast.Name(
|
|
1920
|
+
file_path=self.mod_path,
|
|
1921
|
+
name=Tok.NAME,
|
|
1922
|
+
value=node.arg,
|
|
1923
|
+
line=node.lineno,
|
|
1924
|
+
col_start=node.col_offset,
|
|
1925
|
+
col_end=node.col_offset + len(node.arg),
|
|
1926
|
+
pos_start=0,
|
|
1927
|
+
pos_end=0,
|
|
1928
|
+
)
|
|
1929
|
+
ann_expr = (
|
|
1930
|
+
self.convert(node.annotation)
|
|
1931
|
+
if node.annotation
|
|
1932
|
+
else ast.Name(
|
|
1933
|
+
file_path=self.mod_path,
|
|
1934
|
+
name=Tok.NAME,
|
|
1935
|
+
value="Any",
|
|
1936
|
+
line=node.lineno,
|
|
1937
|
+
col_start=node.col_offset,
|
|
1938
|
+
col_end=node.col_offset + 3,
|
|
1939
|
+
pos_start=0,
|
|
1940
|
+
pos_end=0,
|
|
1941
|
+
)
|
|
1942
|
+
)
|
|
1943
|
+
if not isinstance(ann_expr, ast.Expr):
|
|
1944
|
+
raise self.ice("Expected annotation to be an expression")
|
|
1945
|
+
annot = ast.SubTag[ast.Expr](tag=ann_expr, kid=[ann_expr])
|
|
1946
|
+
paramvar = ast.ParamVar(
|
|
1947
|
+
name=name, type_tag=annot, unpack=None, value=None, kid=[name, annot]
|
|
1948
|
+
)
|
|
1949
|
+
return paramvar
|
|
1950
|
+
|
|
1951
|
+
def proc_arguments(self, node: py_ast.arguments) -> ast.FuncSignature:
|
|
1952
|
+
"""Process python node.
|
|
1953
|
+
|
|
1954
|
+
class arguments(AST):
|
|
1955
|
+
args: list[arg]
|
|
1956
|
+
vararg: arg | None
|
|
1957
|
+
kwonlyargs: list[arg]
|
|
1958
|
+
kw_defaults: list[expr | None]
|
|
1959
|
+
kwarg: arg | None
|
|
1960
|
+
defaults: list[expr]
|
|
1961
|
+
"""
|
|
1962
|
+
args = [self.convert(arg) for arg in node.args]
|
|
1963
|
+
vararg = self.convert(node.vararg) if node.vararg else None
|
|
1964
|
+
if vararg and isinstance(vararg, ast.ParamVar):
|
|
1965
|
+
vararg.unpack = ast.Token(
|
|
1966
|
+
file_path=self.mod_path,
|
|
1967
|
+
name=Tok.STAR_MUL,
|
|
1968
|
+
value="*",
|
|
1969
|
+
line=vararg.loc.first_line,
|
|
1970
|
+
col_start=vararg.loc.col_start,
|
|
1971
|
+
col_end=vararg.loc.col_end,
|
|
1972
|
+
pos_start=0,
|
|
1973
|
+
pos_end=0,
|
|
1974
|
+
)
|
|
1975
|
+
vararg.add_kids_left([vararg.unpack])
|
|
1976
|
+
kwonlyargs = [self.convert(arg) for arg in node.kwonlyargs]
|
|
1977
|
+
for i in range(len(kwonlyargs)):
|
|
1978
|
+
kwa = kwonlyargs[i]
|
|
1979
|
+
kwd = node.kw_defaults[i]
|
|
1980
|
+
kwdefault = self.convert(kwd) if kwd else None
|
|
1981
|
+
if (
|
|
1982
|
+
kwdefault
|
|
1983
|
+
and isinstance(kwa, ast.ParamVar)
|
|
1984
|
+
and isinstance(kwdefault, ast.Expr)
|
|
1985
|
+
):
|
|
1986
|
+
kwa.value = kwdefault
|
|
1987
|
+
kwa.add_kids_right([kwa.value])
|
|
1988
|
+
kwarg = self.convert(node.kwarg) if node.kwarg else None
|
|
1989
|
+
if kwarg and isinstance(kwarg, ast.ParamVar):
|
|
1990
|
+
kwarg.unpack = ast.Token(
|
|
1991
|
+
file_path=self.mod_path,
|
|
1992
|
+
name=Tok.STAR_POW,
|
|
1993
|
+
value="**",
|
|
1994
|
+
line=kwarg.loc.first_line,
|
|
1995
|
+
col_start=kwarg.loc.col_start,
|
|
1996
|
+
col_end=kwarg.loc.col_end,
|
|
1997
|
+
pos_start=0,
|
|
1998
|
+
pos_end=0,
|
|
1999
|
+
)
|
|
2000
|
+
kwarg.add_kids_left([kwarg.unpack])
|
|
2001
|
+
defaults = [self.convert(expr) for expr in node.defaults if type(expr) is None]
|
|
2002
|
+
|
|
2003
|
+
params = [*args]
|
|
2004
|
+
if vararg:
|
|
2005
|
+
params.append(vararg)
|
|
2006
|
+
params += kwonlyargs
|
|
2007
|
+
if kwarg:
|
|
2008
|
+
params.append(kwarg)
|
|
2009
|
+
params += defaults
|
|
2010
|
+
|
|
2011
|
+
valid_params = [param for param in params if isinstance(param, ast.ParamVar)]
|
|
2012
|
+
if len(valid_params) != len(params):
|
|
2013
|
+
raise self.ice("Length mismatch in arguments")
|
|
2014
|
+
if valid_params:
|
|
2015
|
+
fs_params = ast.SubNodeList[ast.ParamVar](
|
|
2016
|
+
items=valid_params, delim=Tok.COMMA, kid=valid_params
|
|
2017
|
+
)
|
|
2018
|
+
return ast.FuncSignature(
|
|
2019
|
+
params=fs_params,
|
|
2020
|
+
return_type=None,
|
|
2021
|
+
kid=[fs_params],
|
|
2022
|
+
)
|
|
2023
|
+
else:
|
|
2024
|
+
_lparen = self.operator(Tok.LPAREN, "(")
|
|
2025
|
+
_rparen = self.operator(Tok.RPAREN, ")")
|
|
2026
|
+
return ast.FuncSignature(
|
|
2027
|
+
params=None,
|
|
2028
|
+
return_type=None,
|
|
2029
|
+
kid=[_lparen, _rparen],
|
|
2030
|
+
)
|
|
2031
|
+
|
|
2032
|
+
def operator(self, tok: Tok, value: str) -> ast.Token:
|
|
2033
|
+
"""Create an operator token."""
|
|
2034
|
+
return ast.Token(
|
|
2035
|
+
file_path=self.mod_path,
|
|
2036
|
+
name=tok,
|
|
2037
|
+
value=value,
|
|
2038
|
+
line=0,
|
|
2039
|
+
col_start=0,
|
|
2040
|
+
col_end=0,
|
|
2041
|
+
pos_start=0,
|
|
2042
|
+
pos_end=0,
|
|
2043
|
+
)
|
|
601
2044
|
|
|
602
|
-
def
|
|
2045
|
+
def proc_and(self, node: py_ast.And) -> ast.Token:
|
|
603
2046
|
"""Process python node."""
|
|
2047
|
+
return self.operator(Tok.KW_AND, "and")
|
|
604
2048
|
|
|
605
|
-
def
|
|
2049
|
+
def proc_or(self, node: py_ast.Or) -> ast.Token:
|
|
606
2050
|
"""Process python node."""
|
|
2051
|
+
return self.operator(Tok.KW_OR, "or")
|
|
607
2052
|
|
|
608
|
-
def
|
|
2053
|
+
def proc_add(self, node: py_ast.Add) -> ast.Token:
|
|
609
2054
|
"""Process python node."""
|
|
2055
|
+
return self.operator(Tok.PLUS, "+")
|
|
610
2056
|
|
|
611
|
-
def
|
|
2057
|
+
def proc_bit_and(self, node: py_ast.BitAnd) -> ast.Token:
|
|
612
2058
|
"""Process python node."""
|
|
2059
|
+
return self.operator(Tok.BW_AND, "&")
|
|
613
2060
|
|
|
614
|
-
def
|
|
2061
|
+
def proc_bit_or(self, node: py_ast.BitOr) -> ast.Token:
|
|
615
2062
|
"""Process python node."""
|
|
2063
|
+
return self.operator(Tok.BW_OR, "|")
|
|
616
2064
|
|
|
617
|
-
def
|
|
2065
|
+
def proc_bit_xor(self, node: py_ast.BitXor) -> ast.Token:
|
|
618
2066
|
"""Process python node."""
|
|
2067
|
+
return self.operator(Tok.BW_XOR, "^")
|
|
619
2068
|
|
|
620
|
-
def
|
|
2069
|
+
def proc_div(self, node: py_ast.Div) -> ast.Token:
|
|
621
2070
|
"""Process python node."""
|
|
2071
|
+
return self.operator(Tok.DIV, "/")
|
|
622
2072
|
|
|
623
|
-
def
|
|
2073
|
+
def proc_floor_div(self, node: py_ast.FloorDiv) -> ast.Token:
|
|
624
2074
|
"""Process python node."""
|
|
2075
|
+
return self.operator(Tok.FLOOR_DIV, "//")
|
|
625
2076
|
|
|
626
|
-
def
|
|
2077
|
+
def proc_l_shift(self, node: py_ast.LShift) -> ast.Token:
|
|
627
2078
|
"""Process python node."""
|
|
2079
|
+
return self.operator(Tok.LSHIFT, "<<")
|
|
628
2080
|
|
|
629
|
-
def
|
|
2081
|
+
def proc_mod(self, node: py_ast.Mod) -> ast.Token:
|
|
630
2082
|
"""Process python node."""
|
|
2083
|
+
return self.operator(Tok.MOD, "%")
|
|
631
2084
|
|
|
632
|
-
def
|
|
2085
|
+
def proc_mult(self, node: py_ast.Mult) -> ast.Token:
|
|
633
2086
|
"""Process python node."""
|
|
2087
|
+
return self.operator(Tok.STAR_MUL, "*")
|
|
634
2088
|
|
|
635
|
-
def
|
|
2089
|
+
def proc_mat_mult(self, node: py_ast.MatMult) -> ast.Token:
|
|
636
2090
|
"""Process python node."""
|
|
2091
|
+
return self.operator(Tok.DECOR_OP, "@")
|
|
637
2092
|
|
|
638
|
-
def
|
|
2093
|
+
def proc_pow(self, node: py_ast.Pow) -> ast.Token:
|
|
639
2094
|
"""Process python node."""
|
|
2095
|
+
return self.operator(Tok.STAR_POW, "**")
|
|
640
2096
|
|
|
641
|
-
def
|
|
2097
|
+
def proc_r_shift(self, node: py_ast.RShift) -> ast.Token:
|
|
642
2098
|
"""Process python node."""
|
|
2099
|
+
return self.operator(Tok.RSHIFT, ">>")
|
|
643
2100
|
|
|
644
|
-
def
|
|
2101
|
+
def proc_sub(self, node: py_ast.Sub) -> ast.Token:
|
|
645
2102
|
"""Process python node."""
|
|
2103
|
+
return self.operator(Tok.MINUS, "-")
|
|
646
2104
|
|
|
647
|
-
def
|
|
2105
|
+
def proc_invert(self, node: py_ast.Invert) -> ast.Token:
|
|
648
2106
|
"""Process python node."""
|
|
2107
|
+
return self.operator(Tok.BW_NOT, "~")
|
|
649
2108
|
|
|
650
|
-
def
|
|
2109
|
+
def proc_not(self, node: py_ast.Not) -> ast.Token:
|
|
651
2110
|
"""Process python node."""
|
|
2111
|
+
return self.operator(Tok.NOT, "not")
|
|
652
2112
|
|
|
653
|
-
def
|
|
2113
|
+
def proc_u_add(self, node: py_ast.UAdd) -> ast.Token:
|
|
654
2114
|
"""Process python node."""
|
|
2115
|
+
return self.operator(Tok.PLUS, "+")
|
|
655
2116
|
|
|
656
|
-
def
|
|
2117
|
+
def proc_u_sub(self, node: py_ast.USub) -> ast.Token:
|
|
657
2118
|
"""Process python node."""
|
|
2119
|
+
return self.operator(Tok.MINUS, "-")
|
|
658
2120
|
|
|
659
|
-
def
|
|
2121
|
+
def proc_eq(self, node: py_ast.Eq) -> ast.Token:
|
|
660
2122
|
"""Process python node."""
|
|
2123
|
+
return self.operator(Tok.EE, "==")
|
|
661
2124
|
|
|
662
|
-
def
|
|
2125
|
+
def proc_gt(self, node: py_ast.Gt) -> ast.Token:
|
|
663
2126
|
"""Process python node."""
|
|
2127
|
+
return self.operator(Tok.GT, ">")
|
|
664
2128
|
|
|
665
|
-
def
|
|
2129
|
+
def proc_gt_e(self, node: py_ast.GtE) -> ast.Token:
|
|
666
2130
|
"""Process python node."""
|
|
2131
|
+
return self.operator(Tok.GTE, ">=")
|
|
667
2132
|
|
|
668
|
-
def
|
|
2133
|
+
def proc_in(self, node: py_ast.In) -> ast.Token:
|
|
669
2134
|
"""Process python node."""
|
|
2135
|
+
return self.operator(Tok.KW_IN, "in")
|
|
670
2136
|
|
|
671
|
-
def
|
|
2137
|
+
def proc_is(self, node: py_ast.Is) -> ast.Token:
|
|
672
2138
|
"""Process python node."""
|
|
2139
|
+
return self.operator(Tok.KW_IS, "is")
|
|
673
2140
|
|
|
674
|
-
def
|
|
2141
|
+
def proc_is_not(self, node: py_ast.IsNot) -> ast.Token:
|
|
675
2142
|
"""Process python node."""
|
|
2143
|
+
return self.operator(Tok.KW_ISN, "is not")
|
|
676
2144
|
|
|
677
|
-
def
|
|
2145
|
+
def proc_lt(self, node: py_ast.Lt) -> ast.Token:
|
|
678
2146
|
"""Process python node."""
|
|
2147
|
+
return self.operator(Tok.LT, "<")
|
|
679
2148
|
|
|
680
|
-
def
|
|
2149
|
+
def proc_lt_e(self, node: py_ast.LtE) -> ast.Token:
|
|
681
2150
|
"""Process python node."""
|
|
2151
|
+
return self.operator(Tok.LTE, "<=")
|
|
682
2152
|
|
|
683
|
-
def
|
|
2153
|
+
def proc_not_eq(self, node: py_ast.NotEq) -> ast.Token:
|
|
684
2154
|
"""Process python node."""
|
|
2155
|
+
return self.operator(Tok.NE, "!=")
|
|
685
2156
|
|
|
686
|
-
def
|
|
2157
|
+
def proc_not_in(self, node: py_ast.NotIn) -> ast.Token:
|
|
687
2158
|
"""Process python node."""
|
|
2159
|
+
return self.operator(Tok.KW_NIN, "not in")
|
|
2160
|
+
|
|
2161
|
+
def proc_comprehension(self, node: py_ast.comprehension) -> ast.InnerCompr:
|
|
2162
|
+
"""Process python node.
|
|
2163
|
+
|
|
2164
|
+
class comprehension(AST):
|
|
2165
|
+
target: expr
|
|
2166
|
+
iter: expr
|
|
2167
|
+
ifs: list[expr]
|
|
2168
|
+
is_async: int
|
|
2169
|
+
"""
|
|
2170
|
+
target = self.convert(node.target)
|
|
2171
|
+
iter = self.convert(node.iter)
|
|
2172
|
+
if len(node.ifs) != 0:
|
|
2173
|
+
ifs_list = [self.convert(ifs) for ifs in node.ifs]
|
|
2174
|
+
valid = [ifs for ifs in ifs_list if isinstance(ifs, ast.Expr)]
|
|
2175
|
+
else:
|
|
2176
|
+
valid = None
|
|
2177
|
+
is_async = node.is_async > 0
|
|
2178
|
+
if isinstance(target, ast.Expr) and isinstance(iter, ast.Expr):
|
|
2179
|
+
return ast.InnerCompr(
|
|
2180
|
+
is_async=is_async,
|
|
2181
|
+
target=target,
|
|
2182
|
+
collection=iter,
|
|
2183
|
+
conditional=valid,
|
|
2184
|
+
kid=[target, iter, *valid] if valid else [target, iter],
|
|
2185
|
+
)
|
|
2186
|
+
else:
|
|
2187
|
+
raise self.ice()
|
|
2188
|
+
|
|
2189
|
+
def proc_keyword(self, node: py_ast.keyword) -> ast.KWPair:
|
|
2190
|
+
"""Process python node.
|
|
2191
|
+
|
|
2192
|
+
class keyword(AST):
|
|
2193
|
+
if sys.version_info >= (3, 10):
|
|
2194
|
+
__match_args__ = ("arg", "value")
|
|
2195
|
+
arg: _Identifier | None
|
|
2196
|
+
value: expr
|
|
2197
|
+
"""
|
|
2198
|
+
arg = ast.Name(
|
|
2199
|
+
file_path=self.mod_path,
|
|
2200
|
+
name=Tok.NAME,
|
|
2201
|
+
value=node.arg if node.arg is not None else "_",
|
|
2202
|
+
line=node.lineno,
|
|
2203
|
+
col_start=node.col_offset,
|
|
2204
|
+
col_end=node.col_offset + len(node.arg if node.arg is not None else "_"),
|
|
2205
|
+
pos_start=0,
|
|
2206
|
+
pos_end=0,
|
|
2207
|
+
)
|
|
2208
|
+
value = self.convert(node.value)
|
|
2209
|
+
if isinstance(value, ast.Expr):
|
|
2210
|
+
return ast.KWPair(key=arg, value=value, kid=[arg, value])
|
|
2211
|
+
else:
|
|
2212
|
+
raise self.ice()
|
|
2213
|
+
|
|
2214
|
+
def proc_match_case(self, node: py_ast.match_case) -> ast.MatchCase:
|
|
2215
|
+
"""Process python node.
|
|
2216
|
+
|
|
2217
|
+
class match_case(AST):
|
|
2218
|
+
pattern: _Pattern
|
|
2219
|
+
guard: expr | None
|
|
2220
|
+
body: list[stmt]
|
|
2221
|
+
"""
|
|
2222
|
+
pattern = self.convert(node.pattern)
|
|
2223
|
+
guard = self.convert(node.guard) if node.guard is not None else None
|
|
2224
|
+
body = [self.convert(i) for i in node.body]
|
|
2225
|
+
valid = [i for i in body if isinstance(i, ast.CodeBlockStmt)]
|
|
2226
|
+
if isinstance(pattern, ast.MatchPattern) and (
|
|
2227
|
+
isinstance(guard, ast.Expr) or guard is None
|
|
2228
|
+
):
|
|
2229
|
+
return ast.MatchCase(
|
|
2230
|
+
pattern=pattern,
|
|
2231
|
+
guard=guard,
|
|
2232
|
+
body=valid,
|
|
2233
|
+
kid=(
|
|
2234
|
+
[pattern, guard, *valid] if guard is not None else [pattern, *valid]
|
|
2235
|
+
),
|
|
2236
|
+
)
|
|
2237
|
+
else:
|
|
2238
|
+
raise self.ice()
|
|
2239
|
+
|
|
2240
|
+
def proc_withitem(self, node: py_ast.withitem) -> ast.ExprAsItem:
|
|
2241
|
+
"""Process python node.
|
|
2242
|
+
|
|
2243
|
+
class withitem(AST):
|
|
2244
|
+
context_expr: expr
|
|
2245
|
+
optional_vars: expr | None
|
|
2246
|
+
"""
|
|
2247
|
+
context_expr = self.convert(node.context_expr)
|
|
2248
|
+
optional_vars = (
|
|
2249
|
+
self.convert(node.optional_vars) if node.optional_vars is not None else None
|
|
2250
|
+
)
|
|
2251
|
+
if isinstance(context_expr, ast.Expr) and (
|
|
2252
|
+
isinstance(optional_vars, ast.Expr) or optional_vars is None
|
|
2253
|
+
):
|
|
2254
|
+
return ast.ExprAsItem(
|
|
2255
|
+
expr=context_expr,
|
|
2256
|
+
alias=optional_vars if optional_vars else None,
|
|
2257
|
+
kid=[context_expr, optional_vars] if optional_vars else [context_expr],
|
|
2258
|
+
)
|
|
2259
|
+
else:
|
|
2260
|
+
raise self.ice()
|
|
688
2261
|
|
|
689
2262
|
def proc_param_spec(self, node: py_ast.ParamSpec) -> None:
|
|
690
2263
|
"""Process python node."""
|