jaclang 0.4.6__py3-none-any.whl → 0.5.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.

Potentially problematic release.


This version of jaclang might be problematic. Click here for more details.

Files changed (152) hide show
  1. jaclang/__init__.py +5 -2
  2. jaclang/cli/cli.py +57 -10
  3. jaclang/cli/cmdreg.py +16 -9
  4. jaclang/compiler/__jac_gen__/jac_parser.py +11 -15
  5. jaclang/compiler/absyntree.py +53 -19
  6. jaclang/compiler/codeloc.py +3 -1
  7. jaclang/compiler/{transpiler.py → compile.py} +3 -2
  8. jaclang/compiler/constant.py +4 -0
  9. jaclang/compiler/parser.py +156 -108
  10. jaclang/compiler/passes/ir_pass.py +1 -0
  11. jaclang/compiler/passes/main/__init__.py +2 -1
  12. jaclang/compiler/passes/main/def_impl_match_pass.py +1 -0
  13. jaclang/compiler/passes/main/def_use_pass.py +1 -0
  14. jaclang/compiler/passes/main/import_pass.py +18 -18
  15. jaclang/compiler/passes/main/pyast_gen_pass.py +1228 -853
  16. jaclang/compiler/passes/main/pyast_load_pass.py +3 -1
  17. jaclang/compiler/passes/main/pybc_gen_pass.py +46 -0
  18. jaclang/compiler/passes/main/pyout_pass.py +6 -7
  19. jaclang/compiler/passes/main/schedules.py +5 -9
  20. jaclang/compiler/passes/main/sub_node_tab_pass.py +1 -0
  21. jaclang/compiler/passes/main/sym_tab_build_pass.py +21 -9
  22. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +2 -1
  23. jaclang/compiler/passes/main/tests/test_def_use_pass.py +2 -1
  24. jaclang/compiler/passes/main/tests/test_import_pass.py +2 -1
  25. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +1 -0
  26. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +15 -38
  27. jaclang/compiler/passes/main/tests/test_pybc_gen_pass.py +25 -0
  28. jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -1
  29. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +2 -1
  30. jaclang/compiler/passes/main/tests/test_type_check_pass.py +17 -1
  31. jaclang/compiler/passes/main/type_check_pass.py +9 -6
  32. jaclang/compiler/passes/tool/__init__.py +1 -0
  33. jaclang/compiler/passes/tool/ast_printer_pass.py +1 -0
  34. jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -1
  35. jaclang/compiler/passes/tool/jac_formatter_pass.py +69 -32
  36. jaclang/compiler/passes/tool/schedules.py +1 -0
  37. jaclang/compiler/passes/tool/sym_tab_printer_pass.py +1 -0
  38. jaclang/compiler/passes/tool/tests/test_ast_print_pass.py +2 -1
  39. jaclang/compiler/passes/tool/tests/test_fuse_comments_pass.py +1 -0
  40. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -3
  41. jaclang/compiler/passes/tool/tests/test_symtab_print_pass.py +2 -1
  42. jaclang/compiler/passes/transform.py +1 -0
  43. jaclang/compiler/passes/utils/mypy_ast_build.py +203 -17
  44. jaclang/compiler/symtable.py +1 -0
  45. jaclang/compiler/tests/test_importer.py +3 -2
  46. jaclang/compiler/tests/test_parser.py +1 -0
  47. jaclang/compiler/tests/test_workspace.py +1 -0
  48. jaclang/compiler/workspace.py +18 -5
  49. jaclang/core/construct.py +9 -32
  50. jaclang/{compiler → core}/importer.py +95 -85
  51. jaclang/core/utils.py +17 -12
  52. jaclang/plugin/__init__.py +1 -0
  53. jaclang/plugin/default.py +145 -43
  54. jaclang/plugin/feature.py +65 -19
  55. jaclang/plugin/spec.py +56 -34
  56. jaclang/plugin/tests/test_features.py +9 -0
  57. jaclang/utils/helpers.py +1 -0
  58. jaclang/utils/lang_tools.py +13 -19
  59. jaclang/utils/tests/test_lang_tools.py +2 -1
  60. jaclang/utils/treeprinter.py +2 -1
  61. jaclang/vendor/lark/common.py +3 -1
  62. jaclang/vendor/lark/lexer.py +6 -12
  63. jaclang/vendor/lark/parsers/lalr_parser.py +1 -0
  64. jaclang/vendor/mypy/applytype.py +2 -1
  65. jaclang/vendor/mypy/binder.py +1 -1
  66. jaclang/vendor/mypy/build.py +7 -9
  67. jaclang/vendor/mypy/checker.py +57 -33
  68. jaclang/vendor/mypy/checkexpr.py +42 -29
  69. jaclang/vendor/mypy/checkmember.py +13 -1
  70. jaclang/vendor/mypy/checkpattern.py +1 -1
  71. jaclang/vendor/mypy/checkstrformat.py +2 -4
  72. jaclang/vendor/mypy/constraints.py +10 -5
  73. jaclang/vendor/mypy/dmypy_server.py +3 -3
  74. jaclang/vendor/mypy/dmypy_util.py +62 -3
  75. jaclang/vendor/mypy/errors.py +1 -1
  76. jaclang/vendor/mypy/evalexpr.py +1 -0
  77. jaclang/vendor/mypy/expandtype.py +29 -29
  78. jaclang/vendor/mypy/fastparse.py +51 -31
  79. jaclang/vendor/mypy/inspections.py +5 -3
  80. jaclang/vendor/mypy/join.py +4 -4
  81. jaclang/vendor/mypy/main.py +6 -6
  82. jaclang/vendor/mypy/message_registry.py +1 -2
  83. jaclang/vendor/mypy/messages.py +31 -23
  84. jaclang/vendor/mypy/metastore.py +1 -2
  85. jaclang/vendor/mypy/modulefinder.py +2 -22
  86. jaclang/vendor/mypy/nodes.py +22 -20
  87. jaclang/vendor/mypy/options.py +4 -0
  88. jaclang/vendor/mypy/parse.py +6 -2
  89. jaclang/vendor/mypy/patterns.py +6 -6
  90. jaclang/vendor/mypy/plugin.py +3 -1
  91. jaclang/vendor/mypy/plugins/attrs.py +52 -10
  92. jaclang/vendor/mypy/plugins/common.py +2 -1
  93. jaclang/vendor/mypy/plugins/enums.py +3 -2
  94. jaclang/vendor/mypy/plugins/functools.py +1 -0
  95. jaclang/vendor/mypy/renaming.py +1 -1
  96. jaclang/vendor/mypy/report.py +15 -15
  97. jaclang/vendor/mypy/semanal.py +22 -13
  98. jaclang/vendor/mypy/semanal_enum.py +1 -1
  99. jaclang/vendor/mypy/semanal_namedtuple.py +1 -2
  100. jaclang/vendor/mypy/semanal_shared.py +3 -6
  101. jaclang/vendor/mypy/semanal_typeddict.py +16 -5
  102. jaclang/vendor/mypy/server/astdiff.py +15 -9
  103. jaclang/vendor/mypy/server/astmerge.py +5 -5
  104. jaclang/vendor/mypy/stats.py +0 -5
  105. jaclang/vendor/mypy/stubdoc.py +1 -1
  106. jaclang/vendor/mypy/stubgen.py +12 -21
  107. jaclang/vendor/mypy/stubgenc.py +16 -8
  108. jaclang/vendor/mypy/stubtest.py +57 -48
  109. jaclang/vendor/mypy/stubutil.py +28 -15
  110. jaclang/vendor/mypy/subtypes.py +4 -4
  111. jaclang/vendor/mypy/test/helpers.py +2 -2
  112. jaclang/vendor/mypy/test/meta/test_parse_data.py +1 -0
  113. jaclang/vendor/mypy/test/meta/test_update_data.py +1 -0
  114. jaclang/vendor/mypy/test/testargs.py +1 -0
  115. jaclang/vendor/mypy/test/testcheck.py +4 -1
  116. jaclang/vendor/mypy/test/testconstraints.py +25 -7
  117. jaclang/vendor/mypy/test/testerrorstream.py +1 -0
  118. jaclang/vendor/mypy/test/testformatter.py +2 -2
  119. jaclang/vendor/mypy/test/testparse.py +6 -4
  120. jaclang/vendor/mypy/test/testpythoneval.py +1 -0
  121. jaclang/vendor/mypy/test/testreports.py +1 -0
  122. jaclang/vendor/mypy/test/teststubgen.py +1 -2
  123. jaclang/vendor/mypy/test/teststubtest.py +98 -4
  124. jaclang/vendor/mypy/test/testtypes.py +1 -1
  125. jaclang/vendor/mypy/test/testutil.py +22 -0
  126. jaclang/vendor/mypy/typeanal.py +302 -158
  127. jaclang/vendor/mypy/typeops.py +22 -13
  128. jaclang/vendor/mypy/types.py +33 -34
  129. jaclang/vendor/mypy/typestate.py +2 -2
  130. jaclang/vendor/mypy/util.py +7 -6
  131. jaclang/vendor/mypy/version.py +1 -1
  132. jaclang/vendor/mypyc/analysis/ircheck.py +1 -0
  133. jaclang/vendor/mypyc/codegen/emitfunc.py +5 -3
  134. jaclang/vendor/mypyc/codegen/emitmodule.py +12 -12
  135. jaclang/vendor/mypyc/codegen/emitwrapper.py +2 -2
  136. jaclang/vendor/mypyc/ir/class_ir.py +10 -6
  137. jaclang/vendor/mypyc/irbuild/builder.py +3 -4
  138. jaclang/vendor/mypyc/irbuild/function.py +5 -3
  139. jaclang/vendor/mypyc/irbuild/nonlocalcontrol.py +1 -2
  140. jaclang/vendor/mypyc/irbuild/prepare.py +6 -6
  141. jaclang/vendor/mypyc/primitives/registry.py +15 -5
  142. jaclang/vendor/mypyc/test/test_run.py +1 -2
  143. jaclang/vendor/mypyc/transform/uninit.py +3 -3
  144. jaclang/vendor/pluggy/_callers.py +1 -0
  145. jaclang/vendor/pluggy/_hooks.py +6 -10
  146. jaclang/vendor/pluggy/_result.py +1 -0
  147. jaclang/vendor/pluggy/_tracing.py +1 -0
  148. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/METADATA +1 -1
  149. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/RECORD +152 -150
  150. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/WHEEL +0 -0
  151. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/entry_points.txt +0 -0
  152. {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@
3
3
  At the end of this pass a meta['py_code'] is present with pure python code
4
4
  in each node. Module nodes contain the entire module code.
5
5
  """
6
+
6
7
  import ast as ast3
7
8
  from typing import Optional, Sequence, TypeVar
8
9
 
@@ -16,6 +17,25 @@ T = TypeVar("T", bound=ast3.AST)
16
17
  class PyastGenPass(Pass):
17
18
  """Jac blue transpilation to python pass."""
18
19
 
20
+ @staticmethod
21
+ def node_compilable_test(node: ast3.AST) -> None:
22
+ """Convert any AST node to a compilable module node."""
23
+ if isinstance(node, ast3.Module):
24
+ pass
25
+ elif isinstance(node, (ast3.Expr, ast3.stmt)):
26
+ node = ast3.Module(body=[node], type_ignores=[])
27
+ elif isinstance(node, list) and all(isinstance(n, ast3.stmt) for n in node):
28
+ node = ast3.Module(body=node, type_ignores=[])
29
+ else:
30
+ node = ast3.Module(body=[], type_ignores=[])
31
+ try:
32
+ compile(node, "<ast>", "exec")
33
+ except TypeError as e:
34
+ print(ast3.dump(node, indent=2))
35
+ raise e
36
+ except Exception:
37
+ pass
38
+
19
39
  def before_pass(self) -> None:
20
40
  """Initialize pass."""
21
41
  self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
@@ -31,9 +51,15 @@ class PyastGenPass(Pass):
31
51
  )
32
52
  ]
33
53
 
34
- def ds_feature_warn(self) -> None:
35
- """Warn about feature."""
36
- self.warning("Data spatial features not supported in bootstrap Jac.")
54
+ def exit_node(self, node: ast.AstNode) -> None:
55
+ """Exit node."""
56
+ super().exit_node(node)
57
+ # for i in node.gen.py_ast: # Internal validation
58
+ # self.node_compilable_test(i)
59
+
60
+ # TODO: USE THIS TO SYNC
61
+ # if isinstance(i, ast3.AST):
62
+ # i.jac_link = node
37
63
 
38
64
  def needs_jac_import(self) -> None:
39
65
  """Check if import is needed."""
@@ -135,33 +161,52 @@ class PyastGenPass(Pass):
135
161
  i.col_offset = jac_node.loc.col_start
136
162
  i.end_lineno = jac_node.loc.last_line
137
163
  i.end_col_offset = jac_node.loc.col_end
138
- i.jac_link = jac_node
164
+ i.jac_link = jac_node # type: ignore
139
165
  return py_node
140
166
 
167
+ def pyinline_sync(
168
+ self,
169
+ py_nodes: list[ast3.AST],
170
+ ) -> list[ast3.AST]:
171
+ """Sync ast locations."""
172
+ for node in py_nodes:
173
+ for i in ast3.walk(node):
174
+ if isinstance(i, ast3.AST):
175
+ if hasattr(i, "lineno") and i.lineno is not None:
176
+ i.lineno += self.cur_node.loc.first_line
177
+ if hasattr(i, "end_lineno") and i.end_lineno is not None:
178
+ i.end_lineno += self.cur_node.loc.first_line
179
+ i.jac_link = self.cur_node # type: ignore
180
+ return py_nodes
181
+
141
182
  def resolve_stmt_block(
142
183
  self,
143
- node: ast.SubNodeList[ast.CodeBlockStmt]
144
- | ast.SubNodeList[ast.ArchBlockStmt]
145
- | ast.SubNodeList[ast.EnumBlockStmt]
146
- | None,
184
+ node: (
185
+ ast.SubNodeList[ast.CodeBlockStmt]
186
+ | ast.SubNodeList[ast.ArchBlockStmt]
187
+ | ast.SubNodeList[ast.EnumBlockStmt]
188
+ | None
189
+ ),
147
190
  doc: Optional[ast.String] = None,
148
191
  ) -> list[ast3.AST]:
149
192
  """Unwind codeblock."""
150
193
  ret: list[ast3.AST] = (
151
194
  [self.sync(ast3.Pass(), node)]
152
195
  if isinstance(node, ast.SubNodeList) and not node.items
153
- else self.flatten(
154
- [
155
- x.gen.py_ast
156
- for x in node.items
157
- # if not isinstance(x, ast.AstImplOnlyNode)
158
- ]
196
+ else (
197
+ self.flatten(
198
+ [
199
+ x.gen.py_ast
200
+ for x in node.items
201
+ # if not isinstance(x, ast.AstImplOnlyNode)
202
+ ]
203
+ )
204
+ if node and isinstance(node.gen.py_ast, list)
205
+ else []
159
206
  )
160
- if node and isinstance(node.gen.py_ast, list)
161
- else []
162
207
  )
163
208
  if doc:
164
- ret = [self.sync(ast3.Expr(value=doc.gen.py_ast), jac_node=doc), *ret]
209
+ ret = [self.sync(ast3.Expr(value=doc.gen.py_ast[0]), jac_node=doc), *ret]
165
210
  return ret
166
211
 
167
212
  def sync_many(self, py_nodes: list[T], jac_node: ast.AstNode) -> list[T]:
@@ -213,7 +258,7 @@ class PyastGenPass(Pass):
213
258
  """
214
259
  body = (
215
260
  [
216
- self.sync(ast3.Expr(value=node.doc.gen.py_ast), jac_node=node.doc),
261
+ self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc),
217
262
  *self.preamble,
218
263
  *[
219
264
  x.gen.py_ast
@@ -230,13 +275,15 @@ class PyastGenPass(Pass):
230
275
  new_body += i
231
276
  else:
232
277
  new_body.append(i) if i else None
233
- node.gen.py_ast = self.sync(
234
- ast3.Module(
235
- body=new_body,
236
- type_ignores=[],
278
+ node.gen.py_ast = [
279
+ self.sync(
280
+ ast3.Module(
281
+ body=new_body,
282
+ type_ignores=[],
283
+ )
237
284
  )
238
- )
239
- node.gen.py = ast3.unparse(node.gen.py_ast)
285
+ ]
286
+ node.gen.py = ast3.unparse(node.gen.py_ast[0])
240
287
 
241
288
  def exit_global_vars(self, node: ast.GlobalVars) -> None:
242
289
  """Sub objects.
@@ -247,7 +294,7 @@ class PyastGenPass(Pass):
247
294
  doc: Optional[String],
248
295
  """
249
296
  if node.doc:
250
- doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast), jac_node=node.doc)
297
+ doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
251
298
  if isinstance(doc, ast3.AST) and isinstance(
252
299
  node.assignments.gen.py_ast, list
253
300
  ):
@@ -264,6 +311,7 @@ class PyastGenPass(Pass):
264
311
  body: SubNodeList[CodeBlockStmt],
265
312
  doc: Optional[String],
266
313
  """
314
+ self.needs_jac_feature()
267
315
  test_name = node.name.sym_name
268
316
  func = self.sync(
269
317
  ast3.FunctionDef(
@@ -296,7 +344,7 @@ class PyastGenPass(Pass):
296
344
  type_params=[],
297
345
  ),
298
346
  )
299
- node.gen.py_ast = func
347
+ node.gen.py_ast = [func]
300
348
 
301
349
  def exit_module_code(self, node: ast.ModuleCode) -> None:
302
350
  """Sub objects.
@@ -306,7 +354,7 @@ class PyastGenPass(Pass):
306
354
  doc: Optional[String],
307
355
  """
308
356
  if node.doc:
309
- doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast), jac_node=node.doc)
357
+ doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
310
358
  if isinstance(node.body.gen.py_ast, list):
311
359
  node.gen.py_ast = [doc] + node.body.gen.py_ast
312
360
  else:
@@ -314,21 +362,27 @@ class PyastGenPass(Pass):
314
362
  else:
315
363
  node.gen.py_ast = node.body.gen.py_ast
316
364
  if node.name:
317
- node.gen.py_ast = self.sync(
318
- ast3.If(
319
- test=self.sync(
320
- ast3.Compare(
321
- left=self.sync(ast3.Name(id="__name__", ctx=ast3.Load())),
322
- ops=[self.sync(ast3.Eq())],
323
- comparators=[
324
- self.sync(ast3.Constant(value=node.name.tag.sym_name))
325
- ],
326
- )
327
- ),
328
- body=node.gen.py_ast,
329
- orelse=[],
365
+ node.gen.py_ast = [
366
+ self.sync(
367
+ ast3.If(
368
+ test=self.sync(
369
+ ast3.Compare(
370
+ left=self.sync(
371
+ ast3.Name(id="__name__", ctx=ast3.Load())
372
+ ),
373
+ ops=[self.sync(ast3.Eq())],
374
+ comparators=[
375
+ self.sync(
376
+ ast3.Constant(value=node.name.tag.sym_name)
377
+ )
378
+ ],
379
+ )
380
+ ),
381
+ body=node.gen.py_ast,
382
+ orelse=[],
383
+ )
330
384
  )
331
- )
385
+ ]
332
386
 
333
387
  def exit_py_inline_code(self, node: ast.PyInlineCode) -> None:
334
388
  """Sub objects.
@@ -337,19 +391,22 @@ class PyastGenPass(Pass):
337
391
  doc: Optional[String],
338
392
  """
339
393
  if node.doc:
340
- doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast), jac_node=node.doc)
394
+ doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
341
395
  if isinstance(doc, ast3.AST):
342
- node.gen.py_ast = [doc] + [*ast3.parse(node.code.value).body]
396
+ node.gen.py_ast = self.pyinline_sync(
397
+ [doc, *ast3.parse(node.code.value).body]
398
+ )
399
+
343
400
  else:
344
401
  raise self.ice()
345
402
  else:
346
- node.gen.py_ast = [*ast3.parse(node.code.value).body]
403
+ node.gen.py_ast = self.pyinline_sync([*ast3.parse(node.code.value).body])
347
404
 
348
405
  def exit_import(self, node: ast.Import) -> None:
349
406
  """Sub objects.
350
407
 
351
408
  lang: SubTag[Name],
352
- path: ModulePath,
409
+ paths: list[ModulePath],
353
410
  alias: Optional[Name],
354
411
  items: Optional[SubNodeList[ModuleItem]],
355
412
  is_absorb: bool,
@@ -359,51 +416,67 @@ class PyastGenPass(Pass):
359
416
  py_nodes: list[ast3.AST] = []
360
417
  if node.doc:
361
418
  py_nodes.append(
362
- self.sync(ast3.Expr(value=node.doc.gen.py_ast), jac_node=node.doc)
419
+ self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
363
420
  )
364
- py_compat_path_str = node.path.path_str.lstrip(".")
421
+ py_compat_path_str = []
422
+ for path in node.paths:
423
+ py_compat_path_str.append(path.path_str.lstrip("."))
365
424
  if node.lang.tag.value == Con.JAC_LANG_IMP:
366
425
  self.needs_jac_import()
367
- py_nodes.append(
368
- self.sync(
369
- ast3.Expr(
370
- value=self.sync(
371
- ast3.Call(
372
- func=self.sync(
373
- ast3.Name(id="__jac_import__", ctx=ast3.Load())
374
- ),
375
- args=[],
376
- keywords=[
377
- self.sync(
378
- ast3.keyword(
379
- arg="target",
380
- value=self.sync(
381
- ast3.Constant(value=node.path.path_str),
382
- node.path,
383
- ),
384
- )
385
- ),
386
- self.sync(
387
- ast3.keyword(
388
- arg="base_path",
389
- value=self.sync(
390
- ast3.Name(
391
- id="__file__", ctx=ast3.Load()
392
- )
393
- ),
394
- )
426
+ for p in range(len(py_compat_path_str)):
427
+ py_nodes.append(
428
+ self.sync(
429
+ ast3.Expr(
430
+ value=self.sync(
431
+ ast3.Call(
432
+ func=self.sync(
433
+ ast3.Name(id="__jac_import__", ctx=ast3.Load())
395
434
  ),
396
- ],
435
+ args=[],
436
+ keywords=[
437
+ self.sync(
438
+ ast3.keyword(
439
+ arg="target",
440
+ value=self.sync(
441
+ ast3.Constant(
442
+ value=node.paths[p].path_str
443
+ ),
444
+ node.paths[p],
445
+ ),
446
+ )
447
+ ),
448
+ self.sync(
449
+ ast3.keyword(
450
+ arg="base_path",
451
+ value=self.sync(
452
+ ast3.Name(
453
+ id="__file__", ctx=ast3.Load()
454
+ )
455
+ ),
456
+ )
457
+ ),
458
+ self.sync(
459
+ ast3.keyword(
460
+ arg="mod_bundle",
461
+ value=self.sync(
462
+ ast3.Name(
463
+ id="__jac_mod_bundle__",
464
+ ctx=ast3.Load(),
465
+ )
466
+ ),
467
+ )
468
+ ),
469
+ ],
470
+ )
397
471
  )
398
- )
399
- ),
472
+ ),
473
+ )
400
474
  )
401
- )
402
475
  if node.is_absorb:
403
476
  py_nodes.append(
404
477
  self.sync(
405
478
  py_node=ast3.ImportFrom(
406
- module=py_compat_path_str,
479
+ module=py_compat_path_str[0],
407
480
  names=[self.sync(ast3.alias(name="*"), node)],
408
481
  level=0,
409
482
  ),
@@ -415,12 +488,14 @@ class PyastGenPass(Pass):
415
488
  "Includes import * in target module into current namespace."
416
489
  )
417
490
  if not node.items:
418
- py_nodes.append(self.sync(ast3.Import(names=[node.path.gen.py_ast])))
491
+ py_nodes.append(
492
+ self.sync(ast3.Import(names=[i.gen.py_ast[0] for i in node.paths]))
493
+ )
419
494
  else:
420
495
  py_nodes.append(
421
496
  self.sync(
422
497
  ast3.ImportFrom(
423
- module=py_compat_path_str,
498
+ module=py_compat_path_str[0],
424
499
  names=node.items.gen.py_ast,
425
500
  level=0,
426
501
  )
@@ -435,12 +510,14 @@ class PyastGenPass(Pass):
435
510
  alias: Optional[Name],
436
511
  path_str: str,
437
512
  """
438
- node.gen.py_ast = self.sync(
439
- ast3.alias(
440
- name=f"{node.path_str}",
441
- asname=node.alias.sym_name if node.alias else None,
513
+ node.gen.py_ast = [
514
+ self.sync(
515
+ ast3.alias(
516
+ name=f"{node.path_str}",
517
+ asname=node.alias.sym_name if node.alias else None,
518
+ )
442
519
  )
443
- )
520
+ ]
444
521
 
445
522
  def exit_module_item(self, node: ast.ModuleItem) -> None:
446
523
  """Sub objects.
@@ -448,12 +525,14 @@ class PyastGenPass(Pass):
448
525
  name: Name,
449
526
  alias: Optional[Name],
450
527
  """
451
- node.gen.py_ast = self.sync(
452
- ast3.alias(
453
- name=f"{node.name.sym_name}",
454
- asname=node.alias.sym_name if node.alias else None,
528
+ node.gen.py_ast = [
529
+ self.sync(
530
+ ast3.alias(
531
+ name=f"{node.name.sym_name}",
532
+ asname=node.alias.sym_name if node.alias else None,
533
+ )
455
534
  )
456
- )
535
+ ]
457
536
 
458
537
  def exit_architype(self, node: ast.Architype) -> None:
459
538
  """Sub objects.
@@ -477,7 +556,7 @@ class PyastGenPass(Pass):
477
556
  else []
478
557
  )
479
558
  ds_on_entry, ds_on_exit = self.collect_events(node)
480
- if isinstance(decorators, list):
559
+ if node.arch_type.name != Tok.KW_CLASS:
481
560
  decorators.append(
482
561
  self.sync(
483
562
  ast3.Call(
@@ -486,11 +565,11 @@ class PyastGenPass(Pass):
486
565
  value=self.sync(
487
566
  ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
488
567
  ),
489
- attr="make_architype",
568
+ attr=f"make_{node.arch_type.value}",
490
569
  ctx=ast3.Load(),
491
570
  )
492
571
  ),
493
- args=[self.sync(ast3.Constant(value=node.arch_type.value))],
572
+ args=[],
494
573
  keywords=[
495
574
  self.sync(
496
575
  ast3.keyword(
@@ -512,19 +591,38 @@ class PyastGenPass(Pass):
512
591
  )
513
592
  )
514
593
  )
515
- else:
516
- raise self.ice()
517
594
  base_classes = node.base_classes.gen.py_ast if node.base_classes else []
518
- node.gen.py_ast = self.sync(
519
- ast3.ClassDef(
520
- name=node.name.sym_name,
521
- bases=base_classes,
522
- keywords=[],
523
- body=body,
524
- decorator_list=decorators,
525
- type_params=[],
595
+ if node.is_abstract:
596
+ self.needs_jac_feature()
597
+ base_classes.append(
598
+ self.sync(
599
+ ast3.Attribute(
600
+ value=self.sync(
601
+ ast3.Attribute(
602
+ value=self.sync(
603
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
604
+ ),
605
+ attr="abc",
606
+ ctx=ast3.Load(),
607
+ )
608
+ ),
609
+ attr="ABC",
610
+ ctx=ast3.Load(),
611
+ )
612
+ )
526
613
  )
527
- )
614
+ node.gen.py_ast = [
615
+ self.sync(
616
+ ast3.ClassDef(
617
+ name=node.name.sym_name,
618
+ bases=base_classes,
619
+ keywords=[],
620
+ body=body,
621
+ decorator_list=decorators,
622
+ type_params=[],
623
+ )
624
+ )
625
+ ]
528
626
 
529
627
  def collect_events(
530
628
  self, node: ast.Architype
@@ -535,9 +633,7 @@ class PyastGenPass(Pass):
535
633
  for i in (
536
634
  node.body.body.items
537
635
  if isinstance(node.body, ast.ArchDef)
538
- else node.body.items
539
- if node.body
540
- else []
636
+ else node.body.items if node.body else []
541
637
  ):
542
638
  if isinstance(i, ast.Ability) and isinstance(
543
639
  i.signature, ast.EventSignature
@@ -555,17 +651,19 @@ class PyastGenPass(Pass):
555
651
  ),
556
652
  args=[
557
653
  self.sync(ast3.Constant(value=i.sym_name)),
558
- i.signature.arch_tag_info.gen.py_ast
559
- if i.signature.arch_tag_info
560
- else self.sync(ast3.Constant(value=None)),
654
+ (
655
+ i.signature.arch_tag_info.gen.py_ast[0]
656
+ if i.signature.arch_tag_info
657
+ else self.sync(ast3.Constant(value=None))
658
+ ),
561
659
  ],
562
660
  keywords=[],
563
661
  )
564
662
  )
565
- ds_on_entry.append(
566
- func_spec
567
- ) if i.signature.event.name == Tok.KW_ENTRY else ds_on_exit.append(
568
- func_spec
663
+ (
664
+ ds_on_entry.append(func_spec)
665
+ if i.signature.event.name == Tok.KW_ENTRY
666
+ else ds_on_exit.append(func_spec)
569
667
  )
570
668
  return ds_on_entry, ds_on_exit
571
669
 
@@ -605,16 +703,18 @@ class PyastGenPass(Pass):
605
703
  )
606
704
  else:
607
705
  raise self.ice()
608
- node.gen.py_ast = self.sync(
609
- ast3.ClassDef(
610
- name=node.name.sym_name,
611
- bases=base_classes,
612
- keywords=[],
613
- body=body,
614
- decorator_list=decorators,
615
- type_params=[],
706
+ node.gen.py_ast = [
707
+ self.sync(
708
+ ast3.ClassDef(
709
+ name=node.name.sym_name,
710
+ bases=base_classes,
711
+ keywords=[],
712
+ body=body,
713
+ decorator_list=decorators,
714
+ type_params=[],
715
+ )
616
716
  )
617
- )
717
+ ]
618
718
 
619
719
  def exit_enum_def(self, node: ast.EnumDef) -> None:
620
720
  """Sub objects.
@@ -642,15 +742,21 @@ class PyastGenPass(Pass):
642
742
  func_type = ast3.AsyncFunctionDef if node.is_async else ast3.FunctionDef
643
743
  body = (
644
744
  [
645
- self.sync(ast3.Expr(value=node.doc.gen.py_ast), jac_node=node.doc),
745
+ self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc),
646
746
  self.sync(ast3.Pass(), node.body),
647
747
  ]
648
748
  if node.doc and node.is_abstract
649
- else [self.sync(ast3.Pass(), node.body)]
650
- if node.is_abstract
651
- else self.resolve_stmt_block(
652
- node.body.body if isinstance(node.body, ast.AbilityDef) else node.body,
653
- doc=node.doc,
749
+ else (
750
+ [self.sync(ast3.Pass(), node.body)]
751
+ if node.is_abstract
752
+ else self.resolve_stmt_block(
753
+ (
754
+ node.body.body
755
+ if isinstance(node.body, ast.AbilityDef)
756
+ else node.body
757
+ ),
758
+ doc=node.doc,
759
+ )
654
760
  )
655
761
  )
656
762
  if node.is_abstract and node.body:
@@ -659,24 +765,58 @@ class PyastGenPass(Pass):
659
765
  node,
660
766
  )
661
767
  decorator_list = node.decorators.gen.py_ast if node.decorators else []
768
+ if node.is_abstract:
769
+ self.needs_jac_feature()
770
+ decorator_list.append(
771
+ self.sync(
772
+ ast3.Attribute(
773
+ value=self.sync(
774
+ ast3.Attribute(
775
+ value=self.sync(
776
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
777
+ ),
778
+ attr="abc",
779
+ ctx=ast3.Load(),
780
+ )
781
+ ),
782
+ attr="abstractmethod",
783
+ ctx=ast3.Load(),
784
+ )
785
+ )
786
+ )
787
+ if node.is_override:
788
+ self.needs_typing()
789
+ decorator_list.append(
790
+ self.sync(
791
+ ast3.Attribute(
792
+ value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
793
+ attr="override",
794
+ ctx=ast3.Load(),
795
+ )
796
+ )
797
+ )
662
798
  if node.is_static:
663
799
  decorator_list.insert(
664
800
  0, self.sync(ast3.Name(id="staticmethod", ctx=ast3.Load()))
665
801
  )
666
802
  if not body:
667
803
  self.error("Ability has no body. Perhaps an impl must be imported.", node)
668
- node.gen.py_ast = self.sync(
669
- func_type(
670
- name=node.name_ref.sym_name,
671
- args=node.signature.gen.py_ast if node.signature else [],
672
- body=body,
673
- decorator_list=decorator_list,
674
- returns=node.signature.return_type.gen.py_ast
675
- if node.signature and node.signature.return_type
676
- else self.sync(ast3.Constant(value=None)),
677
- type_params=[],
804
+ node.gen.py_ast = [
805
+ self.sync(
806
+ func_type(
807
+ name=node.name_ref.sym_name,
808
+ args=node.signature.gen.py_ast[0] if node.signature else [],
809
+ body=body,
810
+ decorator_list=decorator_list,
811
+ returns=(
812
+ node.signature.return_type.gen.py_ast[0]
813
+ if node.signature and node.signature.return_type
814
+ else self.sync(ast3.Constant(value=None))
815
+ ),
816
+ type_params=[],
817
+ )
678
818
  )
679
- )
819
+ ]
680
820
 
681
821
  def exit_ability_def(self, node: ast.AbilityDef) -> None:
682
822
  """Sub objects.
@@ -704,29 +844,33 @@ class PyastGenPass(Pass):
704
844
  if isinstance(node.params, ast.SubNodeList):
705
845
  for i in node.params.items:
706
846
  if i.unpack and i.unpack.value == "*":
707
- vararg = i.gen.py_ast
847
+ vararg = i.gen.py_ast[0]
708
848
  elif i.unpack and i.unpack.value == "**":
709
- kwarg = i.gen.py_ast
849
+ kwarg = i.gen.py_ast[0]
710
850
  else:
711
- params.append(i.gen.py_ast) if isinstance(
712
- i.gen.py_ast, ast3.arg
713
- ) else self.ice("This list should only be Args")
851
+ (
852
+ params.append(i.gen.py_ast[0])
853
+ if isinstance(i.gen.py_ast[0], ast3.arg)
854
+ else self.ice("This list should only be Args")
855
+ )
714
856
  defaults = (
715
- [x.value.gen.py_ast for x in node.params.items if x.value]
857
+ [x.value.gen.py_ast[0] for x in node.params.items if x.value]
716
858
  if node.params
717
859
  else []
718
860
  )
719
- node.gen.py_ast = self.sync(
720
- ast3.arguments(
721
- posonlyargs=[],
722
- args=params,
723
- kwonlyargs=[],
724
- vararg=vararg,
725
- kwarg=kwarg,
726
- kw_defaults=[],
727
- defaults=defaults,
861
+ node.gen.py_ast = [
862
+ self.sync(
863
+ ast3.arguments(
864
+ posonlyargs=[],
865
+ args=params,
866
+ kwonlyargs=[],
867
+ vararg=vararg,
868
+ kwarg=kwarg,
869
+ kw_defaults=[],
870
+ defaults=defaults,
871
+ )
728
872
  )
729
- )
873
+ ]
730
874
 
731
875
  def exit_event_signature(self, node: ast.EventSignature) -> None:
732
876
  """Sub objects.
@@ -738,25 +882,29 @@ class PyastGenPass(Pass):
738
882
  here = self.sync(
739
883
  ast3.arg(
740
884
  arg=f"{Con.HERE.value}",
741
- annotation=node.arch_tag_info.gen.py_ast
742
- if node.arch_tag_info
743
- else None,
885
+ annotation=(
886
+ node.arch_tag_info.gen.py_ast[0] if node.arch_tag_info else None
887
+ ),
744
888
  ),
745
889
  jac_node=node.arch_tag_info if node.arch_tag_info else node,
746
890
  )
747
- node.gen.py_ast = self.sync(
748
- ast3.arguments(
749
- posonlyargs=[],
750
- args=[self.sync(ast3.arg(arg="self", annotation=None)), here]
751
- if node.is_method
752
- else [here],
753
- kwonlyargs=[],
754
- vararg=None,
755
- kwargs=None,
756
- kw_defaults=[],
757
- defaults=[],
891
+ node.gen.py_ast = [
892
+ self.sync(
893
+ ast3.arguments(
894
+ posonlyargs=[],
895
+ args=(
896
+ [self.sync(ast3.arg(arg="self", annotation=None)), here]
897
+ if node.is_method
898
+ else [here]
899
+ ),
900
+ kwonlyargs=[],
901
+ vararg=None,
902
+ kwargs=None,
903
+ kw_defaults=[],
904
+ defaults=[],
905
+ )
758
906
  )
759
- )
907
+ ]
760
908
 
761
909
  def exit_arch_ref(self, node: ast.ArchRef) -> None:
762
910
  """Sub objects.
@@ -769,24 +917,28 @@ class PyastGenPass(Pass):
769
917
  isinstance(node.name_ref, ast.SpecialVarRef)
770
918
  and node.name_ref.var.name == Tok.ROOT_OP
771
919
  ):
772
- node.gen.py_ast = self.sync(
773
- ast3.Attribute(
774
- value=self.sync(
775
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
776
- ),
777
- attr="RootType",
778
- ctx=ast3.Load(),
920
+ node.gen.py_ast = [
921
+ self.sync(
922
+ ast3.Attribute(
923
+ value=self.sync(
924
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
925
+ ),
926
+ attr="RootType",
927
+ ctx=ast3.Load(),
928
+ )
779
929
  )
780
- )
930
+ ]
781
931
  else:
782
932
  self.needs_typing()
783
- node.gen.py_ast = self.sync(
784
- ast3.Attribute(
785
- value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
786
- attr=node.name_ref.sym_name,
787
- ctx=ast3.Load(),
933
+ node.gen.py_ast = [
934
+ self.sync(
935
+ ast3.Attribute(
936
+ value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
937
+ attr=node.name_ref.sym_name,
938
+ ctx=ast3.Load(),
939
+ )
788
940
  )
789
- )
941
+ ]
790
942
  else:
791
943
  node.gen.py_ast = node.name_ref.gen.py_ast
792
944
 
@@ -796,10 +948,10 @@ class PyastGenPass(Pass):
796
948
  archs: Sequence[ArchRef],
797
949
  """
798
950
 
799
- def make_attr_chain(arch: list[ast.ArchRef]) -> ast3.AST | None:
951
+ def make_attr_chain(arch: list[ast.ArchRef]) -> list[ast3.AST]:
800
952
  """Make attr chain."""
801
953
  if len(arch) == 0:
802
- return None
954
+ return []
803
955
  if len(arch) == 1 and isinstance(arch[0].gen.py_ast, ast3.AST):
804
956
  return arch[0].gen.py_ast
805
957
  cur = arch[-1]
@@ -811,7 +963,7 @@ class PyastGenPass(Pass):
811
963
  ),
812
964
  jac_node=cur,
813
965
  )
814
- return attr
966
+ return [attr]
815
967
 
816
968
  node.gen.py_ast = make_attr_chain(node.archs)
817
969
 
@@ -823,12 +975,14 @@ class PyastGenPass(Pass):
823
975
  type_tag: SubTag[ExprType],
824
976
  value: Optional[ExprType],
825
977
  """
826
- node.gen.py_ast = self.sync(
827
- ast3.arg(
828
- arg=node.name.sym_name,
829
- annotation=node.type_tag.gen.py_ast if node.type_tag else None,
978
+ node.gen.py_ast = [
979
+ self.sync(
980
+ ast3.arg(
981
+ arg=node.name.sym_name,
982
+ annotation=node.type_tag.gen.py_ast[0] if node.type_tag else None,
983
+ )
830
984
  )
831
- )
985
+ ]
832
986
 
833
987
  def exit_arch_has(self, node: ast.ArchHas) -> None:
834
988
  """Sub objects.
@@ -840,7 +994,7 @@ class PyastGenPass(Pass):
840
994
  doc: Optional[String],
841
995
  """
842
996
  if node.doc:
843
- doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast), jac_node=node.doc)
997
+ doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
844
998
  if isinstance(doc, ast3.AST) and isinstance(node.vars.gen.py_ast, list):
845
999
  node.gen.py_ast = [doc] + node.vars.gen.py_ast
846
1000
  else:
@@ -856,14 +1010,30 @@ class PyastGenPass(Pass):
856
1010
  value: Optional[Expr],
857
1011
  semstr: Optional[String] = None,
858
1012
  """
859
- annotation = node.type_tag.gen.py_ast if node.type_tag else None
860
- is_class_var = (
1013
+ annotation = node.type_tag.gen.py_ast[0] if node.type_tag else None
1014
+ is_static_var = (
861
1015
  node.parent
862
1016
  and node.parent.parent
863
1017
  and isinstance(node.parent.parent, ast.ArchHas)
864
1018
  and node.parent.parent.is_static
865
1019
  )
866
- if is_class_var:
1020
+ is_in_class = (
1021
+ node.parent
1022
+ and node.parent.parent
1023
+ and node.parent.parent.parent
1024
+ and (
1025
+ (
1026
+ isinstance(node.parent.parent.parent, ast.Architype)
1027
+ and node.parent.parent.parent.arch_type.name == Tok.KW_CLASS
1028
+ )
1029
+ or (
1030
+ node.parent.parent.parent.parent
1031
+ and isinstance(node.parent.parent.parent.parent, ast.Architype)
1032
+ and node.parent.parent.parent.parent.arch_type.name == Tok.KW_CLASS
1033
+ )
1034
+ )
1035
+ )
1036
+ if is_static_var:
867
1037
  self.needs_typing()
868
1038
  annotation = self.sync(
869
1039
  ast3.Subscript(
@@ -878,55 +1048,61 @@ class PyastGenPass(Pass):
878
1048
  ctx=ast3.Load(),
879
1049
  )
880
1050
  )
881
-
882
- node.gen.py_ast = self.sync(
883
- ast3.AnnAssign(
884
- target=node.name.gen.py_ast,
885
- annotation=annotation,
886
- value=self.sync(
887
- ast3.Call(
888
- func=self.sync(
889
- ast3.Attribute(
890
- value=self.sync(
891
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
892
- ),
893
- attr="has_instance_default",
894
- ctx=ast3.Load(),
895
- )
896
- ),
897
- args=[],
898
- keywords=[
1051
+ node.gen.py_ast = [
1052
+ (
1053
+ self.sync(
1054
+ ast3.AnnAssign(
1055
+ target=node.name.gen.py_ast[0],
1056
+ annotation=annotation,
1057
+ value=(
899
1058
  self.sync(
900
- ast3.keyword(
901
- arg="gen_func",
902
- value=self.sync(
903
- ast3.Lambda(
904
- args=self.sync(
905
- ast3.arguments(
906
- posonlyargs=[],
907
- args=[],
908
- kwonlyargs=[],
909
- vararg=None,
910
- kwargs=None,
911
- kw_defaults=[],
912
- defaults=[],
1059
+ ast3.Call(
1060
+ func=self.sync(
1061
+ ast3.Attribute(
1062
+ value=self.sync(
1063
+ ast3.Name(
1064
+ id=Con.JAC_FEATURE.value,
1065
+ ctx=ast3.Load(),
913
1066
  )
914
1067
  ),
915
- body=node.value.gen.py_ast,
1068
+ attr="has_instance_default",
1069
+ ctx=ast3.Load(),
916
1070
  )
917
1071
  ),
1072
+ args=[],
1073
+ keywords=[
1074
+ self.sync(
1075
+ ast3.keyword(
1076
+ arg="gen_func",
1077
+ value=self.sync(
1078
+ ast3.Lambda(
1079
+ args=self.sync(
1080
+ ast3.arguments(
1081
+ posonlyargs=[],
1082
+ args=[],
1083
+ kwonlyargs=[],
1084
+ vararg=None,
1085
+ kwargs=None,
1086
+ kw_defaults=[],
1087
+ defaults=[],
1088
+ )
1089
+ ),
1090
+ body=node.value.gen.py_ast[0],
1091
+ )
1092
+ ),
1093
+ )
1094
+ )
1095
+ ],
918
1096
  )
919
1097
  )
920
- ],
1098
+ if node.value and not (is_static_var or is_in_class)
1099
+ else node.value.gen.py_ast[0] if node.value else None
1100
+ ),
1101
+ simple=int(isinstance(node.name, ast.Name)),
921
1102
  )
922
1103
  )
923
- if node.value and not is_class_var
924
- else node.value.gen.py_ast
925
- if node.value
926
- else None,
927
- simple=int(isinstance(node.name, ast.Name)),
928
1104
  )
929
- )
1105
+ ]
930
1106
 
931
1107
  def exit_typed_ctx_block(self, node: ast.TypedCtxBlock) -> None:
932
1108
  """Sub objects.
@@ -943,13 +1119,15 @@ class PyastGenPass(Pass):
943
1119
  body: SubNodeList[CodeBlockStmt],
944
1120
  else_body: Optional[ElseStmt | ElseIf],
945
1121
  """
946
- node.gen.py_ast = self.sync(
947
- ast3.If(
948
- test=node.condition.gen.py_ast,
949
- body=self.resolve_stmt_block(node.body),
950
- orelse=node.else_body.gen.py_ast if node.else_body else [],
1122
+ node.gen.py_ast = [
1123
+ self.sync(
1124
+ ast3.If(
1125
+ test=node.condition.gen.py_ast[0],
1126
+ body=self.resolve_stmt_block(node.body),
1127
+ orelse=node.else_body.gen.py_ast if node.else_body else [],
1128
+ )
951
1129
  )
952
- )
1130
+ ]
953
1131
 
954
1132
  def exit_else_if(self, node: ast.ElseIf) -> None:
955
1133
  """Sub objects.
@@ -961,7 +1139,7 @@ class PyastGenPass(Pass):
961
1139
  node.gen.py_ast = [
962
1140
  self.sync(
963
1141
  ast3.If(
964
- test=node.condition.gen.py_ast,
1142
+ test=node.condition.gen.py_ast[0],
965
1143
  body=self.resolve_stmt_block(node.body),
966
1144
  orelse=node.else_body.gen.py_ast if node.else_body else [],
967
1145
  )
@@ -981,17 +1159,19 @@ class PyastGenPass(Pass):
981
1159
  expr: ExprType,
982
1160
  in_fstring: bool,
983
1161
  """
984
- node.gen.py_ast = (
985
- self.sync(ast3.Expr(value=node.expr.gen.py_ast))
986
- if not node.in_fstring
987
- else self.sync(
988
- ast3.FormattedValue(
989
- value=node.expr.gen.py_ast,
990
- conversion=-1,
991
- format_spec=None,
1162
+ node.gen.py_ast = [
1163
+ (
1164
+ self.sync(ast3.Expr(value=node.expr.gen.py_ast[0]))
1165
+ if not node.in_fstring
1166
+ else self.sync(
1167
+ ast3.FormattedValue(
1168
+ value=node.expr.gen.py_ast[0],
1169
+ conversion=-1,
1170
+ format_spec=None,
1171
+ )
992
1172
  )
993
1173
  )
994
- )
1174
+ ]
995
1175
 
996
1176
  def exit_try_stmt(self, node: ast.TryStmt) -> None:
997
1177
  """Sub objects.
@@ -1001,14 +1181,16 @@ class PyastGenPass(Pass):
1001
1181
  else_body: Optional[ElseStmt],
1002
1182
  finally_body: Optional[FinallyStmt],
1003
1183
  """
1004
- node.gen.py_ast = self.sync(
1005
- ast3.Try(
1006
- body=self.resolve_stmt_block(node.body),
1007
- handlers=node.excepts.gen.py_ast if node.excepts else None,
1008
- orelse=node.else_body.gen.py_ast if node.else_body else [],
1009
- finalbody=node.finally_body.gen.py_ast if node.finally_body else [],
1184
+ node.gen.py_ast = [
1185
+ self.sync(
1186
+ ast3.Try(
1187
+ body=self.resolve_stmt_block(node.body),
1188
+ handlers=node.excepts.gen.py_ast if node.excepts else None,
1189
+ orelse=node.else_body.gen.py_ast if node.else_body else [],
1190
+ finalbody=node.finally_body.gen.py_ast if node.finally_body else [],
1191
+ )
1010
1192
  )
1011
- )
1193
+ ]
1012
1194
 
1013
1195
  def exit_except(self, node: ast.Except) -> None:
1014
1196
  """Sub objects.
@@ -1017,13 +1199,15 @@ class PyastGenPass(Pass):
1017
1199
  name: Optional[Name],
1018
1200
  body: SubNodeList[CodeBlockStmt],
1019
1201
  """
1020
- node.gen.py_ast = self.sync(
1021
- ast3.ExceptHandler(
1022
- type=node.ex_type.gen.py_ast,
1023
- name=node.name.sym_name if node.name else None,
1024
- body=self.resolve_stmt_block(node.body),
1202
+ node.gen.py_ast = [
1203
+ self.sync(
1204
+ ast3.ExceptHandler(
1205
+ type=node.ex_type.gen.py_ast[0],
1206
+ name=node.name.sym_name if node.name else None,
1207
+ body=self.resolve_stmt_block(node.body),
1208
+ )
1025
1209
  )
1026
- )
1210
+ ]
1027
1211
 
1028
1212
  def exit_finally_stmt(self, node: ast.FinallyStmt) -> None:
1029
1213
  """Sub objects.
@@ -1042,21 +1226,21 @@ class PyastGenPass(Pass):
1042
1226
  body: SubNodeList[CodeBlockStmt],
1043
1227
  else_body: Optional[ElseStmt],
1044
1228
  """
1045
- py_nodes = []
1229
+ py_nodes: list[ast3.AST] = []
1046
1230
  body = node.body.gen.py_ast
1047
1231
  if (
1048
1232
  isinstance(body, list)
1049
- and isinstance(node.count_by.gen.py_ast, ast3.AST)
1050
- and isinstance(node.iter.gen.py_ast, ast3.AST)
1233
+ and isinstance(node.count_by.gen.py_ast[0], ast3.AST)
1234
+ and isinstance(node.iter.gen.py_ast[0], ast3.AST)
1051
1235
  ):
1052
- body += [node.count_by.gen.py_ast]
1236
+ body += [node.count_by.gen.py_ast[0]]
1053
1237
  else:
1054
1238
  raise self.ice()
1055
- py_nodes.append(node.iter.gen.py_ast)
1239
+ py_nodes.append(node.iter.gen.py_ast[0])
1056
1240
  py_nodes.append(
1057
1241
  self.sync(
1058
1242
  ast3.While(
1059
- test=node.condition.gen.py_ast,
1243
+ test=node.condition.gen.py_ast[0],
1060
1244
  body=body,
1061
1245
  orelse=node.else_body.gen.py_ast if node.else_body else [],
1062
1246
  )
@@ -1067,21 +1251,23 @@ class PyastGenPass(Pass):
1067
1251
  def exit_in_for_stmt(self, node: ast.InForStmt) -> None:
1068
1252
  """Sub objects.
1069
1253
 
1070
- target: ExprType,
1254
+ target: Expr,
1071
1255
  is_async: bool,
1072
- collection: ExprType,
1256
+ collection: Expr,
1073
1257
  body: SubNodeList[CodeBlockStmt],
1074
1258
  else_body: Optional[ElseStmt],
1075
1259
  """
1076
1260
  for_node = ast3.AsyncFor if node.is_async else ast3.For
1077
- node.gen.py_ast = self.sync(
1078
- for_node(
1079
- target=node.target.gen.py_ast,
1080
- iter=node.collection.gen.py_ast,
1081
- body=self.resolve_stmt_block(node.body),
1082
- orelse=node.else_body.gen.py_ast if node.else_body else [],
1261
+ node.gen.py_ast = [
1262
+ self.sync(
1263
+ for_node(
1264
+ target=node.target.gen.py_ast[0],
1265
+ iter=node.collection.gen.py_ast[0],
1266
+ body=self.resolve_stmt_block(node.body),
1267
+ orelse=node.else_body.gen.py_ast if node.else_body else [],
1268
+ )
1083
1269
  )
1084
- )
1270
+ ]
1085
1271
 
1086
1272
  def exit_while_stmt(self, node: ast.WhileStmt) -> None:
1087
1273
  """Sub objects.
@@ -1089,13 +1275,15 @@ class PyastGenPass(Pass):
1089
1275
  condition: ExprType,
1090
1276
  body: SubNodeList[CodeBlockStmt],
1091
1277
  """
1092
- node.gen.py_ast = self.sync(
1093
- ast3.While(
1094
- test=node.condition.gen.py_ast,
1095
- body=self.resolve_stmt_block(node.body),
1096
- orelse=[],
1278
+ node.gen.py_ast = [
1279
+ self.sync(
1280
+ ast3.While(
1281
+ test=node.condition.gen.py_ast[0],
1282
+ body=self.resolve_stmt_block(node.body),
1283
+ orelse=[],
1284
+ )
1097
1285
  )
1098
- )
1286
+ ]
1099
1287
 
1100
1288
  def exit_with_stmt(self, node: ast.WithStmt) -> None:
1101
1289
  """Sub objects.
@@ -1105,11 +1293,13 @@ class PyastGenPass(Pass):
1105
1293
  body: SubNodeList[CodeBlockStmt],
1106
1294
  """
1107
1295
  with_node = ast3.AsyncWith if node.is_async else ast3.With
1108
- node.gen.py_ast = self.sync(
1109
- with_node(
1110
- items=node.exprs.gen.py_ast, body=self.resolve_stmt_block(node.body)
1296
+ node.gen.py_ast = [
1297
+ self.sync(
1298
+ with_node(
1299
+ items=node.exprs.gen.py_ast, body=self.resolve_stmt_block(node.body)
1300
+ )
1111
1301
  )
1112
- )
1302
+ ]
1113
1303
 
1114
1304
  def exit_expr_as_item(self, node: ast.ExprAsItem) -> None:
1115
1305
  """Sub objects.
@@ -1117,12 +1307,14 @@ class PyastGenPass(Pass):
1117
1307
  expr: ExprType,
1118
1308
  alias: Optional[ExprType],
1119
1309
  """
1120
- node.gen.py_ast = self.sync(
1121
- ast3.withitem(
1122
- context_expr=node.expr.gen.py_ast,
1123
- optional_vars=node.alias.gen.py_ast if node.alias else None,
1310
+ node.gen.py_ast = [
1311
+ self.sync(
1312
+ ast3.withitem(
1313
+ context_expr=node.expr.gen.py_ast[0],
1314
+ optional_vars=node.alias.gen.py_ast[0] if node.alias else None,
1315
+ )
1124
1316
  )
1125
- )
1317
+ ]
1126
1318
 
1127
1319
  def exit_raise_stmt(self, node: ast.RaiseStmt) -> None:
1128
1320
  """Sub objects.
@@ -1130,12 +1322,14 @@ class PyastGenPass(Pass):
1130
1322
  cause: Optional[ExprType],
1131
1323
  from_target: Optional[ExprType],
1132
1324
  """
1133
- node.gen.py_ast = self.sync(
1134
- ast3.Raise(
1135
- exc=node.cause.gen.py_ast if node.cause else None,
1136
- cause=node.from_target.gen.py_ast if node.from_target else None,
1325
+ node.gen.py_ast = [
1326
+ self.sync(
1327
+ ast3.Raise(
1328
+ exc=node.cause.gen.py_ast[0] if node.cause else None,
1329
+ cause=node.from_target.gen.py_ast[0] if node.from_target else None,
1330
+ )
1137
1331
  )
1138
- )
1332
+ ]
1139
1333
 
1140
1334
  def exit_assert_stmt(self, node: ast.AssertStmt) -> None:
1141
1335
  """Sub objects.
@@ -1143,12 +1337,14 @@ class PyastGenPass(Pass):
1143
1337
  condition: ExprType,
1144
1338
  error_msg: Optional[ExprType],
1145
1339
  """
1146
- node.gen.py_ast = self.sync(
1147
- ast3.Assert(
1148
- test=node.condition.gen.py_ast,
1149
- msg=node.error_msg.gen.py_ast if node.error_msg else None,
1340
+ node.gen.py_ast = [
1341
+ self.sync(
1342
+ ast3.Assert(
1343
+ test=node.condition.gen.py_ast[0],
1344
+ msg=node.error_msg.gen.py_ast[0] if node.error_msg else None,
1345
+ )
1150
1346
  )
1151
- )
1347
+ ]
1152
1348
 
1153
1349
  def exit_ctrl_stmt(self, node: ast.CtrlStmt) -> None:
1154
1350
  """Sub objects.
@@ -1156,62 +1352,69 @@ class PyastGenPass(Pass):
1156
1352
  ctrl: Token,
1157
1353
  """
1158
1354
  if node.ctrl.name == Tok.KW_BREAK:
1159
- node.gen.py_ast = self.sync(ast3.Break())
1355
+ node.gen.py_ast = [self.sync(ast3.Break())]
1160
1356
  elif node.ctrl.name == Tok.KW_CONTINUE:
1161
- node.gen.py_ast = self.sync(ast3.Continue())
1357
+ node.gen.py_ast = [self.sync(ast3.Continue())]
1162
1358
  elif node.ctrl.name == Tok.KW_SKIP:
1163
- node.gen.py_ast = self.sync(ast3.Return(value=None))
1359
+ node.gen.py_ast = [self.sync(ast3.Return(value=None))]
1164
1360
 
1165
1361
  def exit_delete_stmt(self, node: ast.DeleteStmt) -> None:
1166
1362
  """Sub objects.
1167
1363
 
1168
1364
  target: SubNodeList[AtomType],
1169
1365
  """
1170
- node.gen.py_ast = self.sync(
1171
- ast3.Delete(
1172
- targets=node.target.values.gen.py_ast
1173
- if isinstance(node.target, ast.TupleVal)
1174
- else [node.target.gen.py_ast]
1366
+ node.gen.py_ast = [
1367
+ self.sync(
1368
+ ast3.Delete(
1369
+ targets=(
1370
+ node.target.values.gen.py_ast
1371
+ if isinstance(node.target, ast.TupleVal) and node.target.values
1372
+ else node.target.gen.py_ast
1373
+ )
1374
+ )
1175
1375
  )
1176
- )
1376
+ ]
1177
1377
 
1178
1378
  def exit_report_stmt(self, node: ast.ReportStmt) -> None:
1179
1379
  """Sub objects.
1180
1380
 
1181
1381
  expr: ExprType,
1182
1382
  """
1183
- node.gen.py_ast = self.sync(
1184
- ast3.Expr(
1185
- value=self.sync(
1186
- self.sync(
1187
- ast3.Call(
1188
- func=self.sync(
1189
- ast3.Attribute(
1190
- value=self.sync(
1191
- ast3.Name(
1192
- id=Con.JAC_FEATURE.value, ctx=ast3.Load()
1193
- )
1194
- ),
1195
- attr="report",
1196
- ctx=ast3.Load(),
1197
- )
1198
- ),
1199
- args=[node.expr.gen.py_ast],
1200
- keywords=[],
1383
+ node.gen.py_ast = [
1384
+ self.sync(
1385
+ ast3.Expr(
1386
+ value=self.sync(
1387
+ self.sync(
1388
+ ast3.Call(
1389
+ func=self.sync(
1390
+ ast3.Attribute(
1391
+ value=self.sync(
1392
+ ast3.Name(
1393
+ id=Con.JAC_FEATURE.value,
1394
+ ctx=ast3.Load(),
1395
+ )
1396
+ ),
1397
+ attr="report",
1398
+ ctx=ast3.Load(),
1399
+ )
1400
+ ),
1401
+ args=node.expr.gen.py_ast,
1402
+ keywords=[],
1403
+ )
1201
1404
  )
1202
1405
  )
1203
1406
  )
1204
1407
  )
1205
- )
1408
+ ]
1206
1409
 
1207
1410
  def exit_return_stmt(self, node: ast.ReturnStmt) -> None:
1208
1411
  """Sub objects.
1209
1412
 
1210
1413
  expr: Optional[ExprType],
1211
1414
  """
1212
- node.gen.py_ast = self.sync(
1213
- ast3.Return(value=node.expr.gen.py_ast if node.expr else None)
1214
- )
1415
+ node.gen.py_ast = [
1416
+ self.sync(ast3.Return(value=node.expr.gen.py_ast[0] if node.expr else None))
1417
+ ]
1215
1418
 
1216
1419
  def exit_yield_expr(self, node: ast.YieldExpr) -> None:
1217
1420
  """Sub objects.
@@ -1219,13 +1422,17 @@ class PyastGenPass(Pass):
1219
1422
  expr: Optional[ExprType],
1220
1423
  """
1221
1424
  if not node.with_from:
1222
- node.gen.py_ast = self.sync(
1223
- ast3.Yield(value=node.expr.gen.py_ast if node.expr else None)
1224
- )
1425
+ node.gen.py_ast = [
1426
+ self.sync(
1427
+ ast3.Yield(value=node.expr.gen.py_ast[0] if node.expr else None)
1428
+ )
1429
+ ]
1225
1430
  else:
1226
- node.gen.py_ast = self.sync(
1227
- ast3.YieldFrom(value=node.expr.gen.py_ast if node.expr else None)
1228
- )
1431
+ node.gen.py_ast = [
1432
+ self.sync(
1433
+ ast3.YieldFrom(value=node.expr.gen.py_ast[0] if node.expr else None)
1434
+ )
1435
+ ]
1229
1436
 
1230
1437
  def exit_ignore_stmt(self, node: ast.IgnoreStmt) -> None:
1231
1438
  """Sub objects.
@@ -1237,25 +1444,29 @@ class PyastGenPass(Pass):
1237
1444
  if node.from_walker
1238
1445
  else ast3.Name(id=Con.HERE.value, ctx=ast3.Load())
1239
1446
  )
1240
- node.gen.py_ast = self.sync(
1241
- ast3.Expr(
1242
- value=self.sync(
1243
- ast3.Call(
1244
- func=self.sync(
1245
- ast3.Attribute(
1246
- value=self.sync(
1247
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1248
- ),
1249
- attr="ignore",
1250
- ctx=ast3.Load(),
1251
- )
1252
- ),
1253
- args=[loc, node.target.gen.py_ast],
1254
- keywords=[],
1447
+ node.gen.py_ast = [
1448
+ self.sync(
1449
+ ast3.Expr(
1450
+ value=self.sync(
1451
+ ast3.Call(
1452
+ func=self.sync(
1453
+ ast3.Attribute(
1454
+ value=self.sync(
1455
+ ast3.Name(
1456
+ id=Con.JAC_FEATURE.value, ctx=ast3.Load()
1457
+ )
1458
+ ),
1459
+ attr="ignore",
1460
+ ctx=ast3.Load(),
1461
+ )
1462
+ ),
1463
+ args=[loc, node.target.gen.py_ast[0]],
1464
+ keywords=[],
1465
+ )
1255
1466
  )
1256
1467
  )
1257
1468
  )
1258
- )
1469
+ ]
1259
1470
 
1260
1471
  def exit_visit_stmt(self, node: ast.VisitStmt) -> None:
1261
1472
  """Sub objects.
@@ -1285,7 +1496,7 @@ class PyastGenPass(Pass):
1285
1496
  ctx=ast3.Load(),
1286
1497
  )
1287
1498
  ),
1288
- args=[loc, node.target.gen.py_ast],
1499
+ args=[loc, node.target.gen.py_ast[0]],
1289
1500
  keywords=[],
1290
1501
  )
1291
1502
  ),
@@ -1301,10 +1512,10 @@ class PyastGenPass(Pass):
1301
1512
  hops: Optional[ExprType],
1302
1513
  else_body: Optional[ElseStmt],
1303
1514
  """
1304
- self.ds_feature_warn()
1305
- node.gen.py_ast = self.sync(
1306
- ast3.Expr(value=self.sync(ast3.Constant(value=None)))
1307
- )
1515
+ self.warning("Revisit not used in Jac", node)
1516
+ node.gen.py_ast = [
1517
+ self.sync(ast3.Expr(value=self.sync(ast3.Constant(value=None))))
1518
+ ]
1308
1519
 
1309
1520
  def exit_disengage_stmt(self, node: ast.DisengageStmt) -> None:
1310
1521
  """Sub objects."""
@@ -1346,7 +1557,7 @@ class PyastGenPass(Pass):
1346
1557
 
1347
1558
  target: ExprType,
1348
1559
  """
1349
- node.gen.py_ast = self.sync(ast3.Await(value=node.target.gen.py_ast))
1560
+ node.gen.py_ast = [self.sync(ast3.Await(value=node.target.gen.py_ast[0]))]
1350
1561
 
1351
1562
  def exit_global_stmt(self, node: ast.GlobalStmt) -> None:
1352
1563
  """Sub objects.
@@ -1387,28 +1598,36 @@ class PyastGenPass(Pass):
1387
1598
  mutable: bool =True,
1388
1599
  """
1389
1600
  if node.type_tag:
1390
- node.gen.py_ast = self.sync(
1391
- ast3.AnnAssign(
1392
- target=node.target.gen.py_ast,
1393
- annotation=node.type_tag.gen.py_ast,
1394
- value=node.value.gen.py_ast if node.value else None,
1395
- simple=int(isinstance(node.target.gen.py_ast, ast3.Name)),
1601
+ node.gen.py_ast = [
1602
+ self.sync(
1603
+ ast3.AnnAssign(
1604
+ target=node.target.items[0].gen.py_ast[0],
1605
+ annotation=node.type_tag.gen.py_ast[0],
1606
+ value=node.value.gen.py_ast[0] if node.value else None,
1607
+ simple=int(isinstance(node.target.gen.py_ast[0], ast3.Name)),
1608
+ )
1396
1609
  )
1397
- )
1610
+ ]
1398
1611
  elif not node.value:
1399
1612
  self.ice()
1400
1613
  elif node.aug_op:
1401
- node.gen.py_ast = self.sync(
1402
- ast3.AugAssign(
1403
- target=node.target.items[0].gen.py_ast,
1404
- op=node.aug_op.gen.py_ast,
1405
- value=node.value.gen.py_ast,
1614
+ node.gen.py_ast = [
1615
+ self.sync(
1616
+ ast3.AugAssign(
1617
+ target=node.target.items[0].gen.py_ast[0],
1618
+ op=node.aug_op.gen.py_ast[0],
1619
+ value=node.value.gen.py_ast[0],
1620
+ )
1406
1621
  )
1407
- )
1622
+ ]
1408
1623
  else:
1409
- node.gen.py_ast = self.sync(
1410
- ast3.Assign(targets=node.target.gen.py_ast, value=node.value.gen.py_ast)
1411
- )
1624
+ node.gen.py_ast = [
1625
+ self.sync(
1626
+ ast3.Assign(
1627
+ targets=node.target.gen.py_ast, value=node.value.gen.py_ast[0]
1628
+ )
1629
+ )
1630
+ ]
1412
1631
 
1413
1632
  def exit_binary_expr(self, node: ast.BinaryExpr) -> None:
1414
1633
  """Sub objects.
@@ -1418,74 +1637,84 @@ class PyastGenPass(Pass):
1418
1637
  op: Token | DisconnectOp | ConnectOp,
1419
1638
  """
1420
1639
  if isinstance(node.op, ast.ConnectOp):
1421
- node.gen.py_ast = self.sync(
1422
- ast3.Call(
1423
- func=self.sync(
1424
- ast3.Attribute(
1425
- value=self.sync(
1426
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1427
- ),
1428
- attr="connect",
1429
- ctx=ast3.Load(),
1430
- )
1431
- ),
1432
- args=[
1433
- node.left.gen.py_ast,
1434
- node.right.gen.py_ast,
1435
- node.op.gen.py_ast,
1436
- ],
1437
- keywords=[],
1640
+ node.gen.py_ast = [
1641
+ self.sync(
1642
+ ast3.Call(
1643
+ func=self.sync(
1644
+ ast3.Attribute(
1645
+ value=self.sync(
1646
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1647
+ ),
1648
+ attr="connect",
1649
+ ctx=ast3.Load(),
1650
+ )
1651
+ ),
1652
+ args=[
1653
+ node.left.gen.py_ast[0],
1654
+ node.right.gen.py_ast[0],
1655
+ node.op.gen.py_ast[0],
1656
+ ],
1657
+ keywords=[],
1658
+ )
1438
1659
  )
1439
- )
1660
+ ]
1440
1661
  elif isinstance(node.op, ast.DisconnectOp):
1441
- node.gen.py_ast = self.sync(
1442
- ast3.Call(
1443
- func=self.sync(
1444
- ast3.Attribute(
1445
- value=self.sync(
1446
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1447
- ),
1448
- attr="disconnect",
1449
- ctx=ast3.Load(),
1450
- )
1451
- ),
1452
- args=[
1453
- node.left.gen.py_ast,
1454
- node.right.gen.py_ast,
1455
- node.op.gen.py_ast,
1456
- ],
1457
- keywords=[],
1662
+ node.gen.py_ast = [
1663
+ self.sync(
1664
+ ast3.Call(
1665
+ func=self.sync(
1666
+ ast3.Attribute(
1667
+ value=self.sync(
1668
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1669
+ ),
1670
+ attr="disconnect",
1671
+ ctx=ast3.Load(),
1672
+ )
1673
+ ),
1674
+ args=[
1675
+ node.left.gen.py_ast[0],
1676
+ node.right.gen.py_ast[0],
1677
+ node.op.gen.py_ast[0],
1678
+ ],
1679
+ keywords=[],
1680
+ )
1458
1681
  )
1459
- )
1682
+ ]
1460
1683
  elif node.op.name in [Tok.KW_AND, Tok.KW_OR]:
1461
- node.gen.py_ast = self.sync(
1462
- ast3.BoolOp(
1463
- op=node.op.gen.py_ast,
1464
- values=[node.left.gen.py_ast, node.right.gen.py_ast],
1684
+ node.gen.py_ast = [
1685
+ self.sync(
1686
+ ast3.BoolOp(
1687
+ op=node.op.gen.py_ast[0],
1688
+ values=[node.left.gen.py_ast[0], node.right.gen.py_ast[0]],
1689
+ )
1465
1690
  )
1466
- )
1467
- elif node.op.name in [Tok.WALRUS_EQ]:
1468
- node.left.gen.py_ast.ctx = ast3.Store() # TODO: Short term fix
1469
- node.gen.py_ast = self.sync(
1470
- ast3.NamedExpr(
1471
- target=node.left.gen.py_ast,
1472
- value=node.right.gen.py_ast,
1691
+ ]
1692
+ elif node.op.name in [Tok.WALRUS_EQ] and isinstance(
1693
+ node.left.gen.py_ast[0], ast3.Name
1694
+ ):
1695
+ node.left.gen.py_ast[0].ctx = ast3.Store() # TODO: Short term fix
1696
+ node.gen.py_ast = [
1697
+ self.sync(
1698
+ ast3.NamedExpr(
1699
+ target=node.left.gen.py_ast[0],
1700
+ value=node.right.gen.py_ast[0],
1701
+ )
1473
1702
  )
1474
- )
1475
- elif isinstance(node.op.gen.py_ast, ast3.AST):
1476
- node.gen.py_ast = self.sync(
1477
- ast3.BinOp(
1478
- left=node.left.gen.py_ast,
1479
- right=node.right.gen.py_ast,
1480
- op=node.op.gen.py_ast,
1703
+ ]
1704
+ elif node.op.gen.py_ast and isinstance(node.op.gen.py_ast[0], ast3.AST):
1705
+ node.gen.py_ast = [
1706
+ self.sync(
1707
+ ast3.BinOp(
1708
+ left=node.left.gen.py_ast[0],
1709
+ right=node.right.gen.py_ast[0],
1710
+ op=node.op.gen.py_ast[0],
1711
+ )
1481
1712
  )
1482
- )
1713
+ ]
1483
1714
  else:
1484
1715
  node.gen.py_ast = self.translate_jac_bin_op(node)
1485
1716
 
1486
- def translate_jac_bin_op(
1487
- self, node: ast.BinaryExpr
1488
- ) -> Optional[ast3.AST] | list[ast3.AST]:
1717
+ def translate_jac_bin_op(self, node: ast.BinaryExpr) -> list[ast3.AST]:
1489
1718
  """Translate jac binary op."""
1490
1719
  if isinstance(node.op, (ast.DisconnectOp, ast.ConnectOp)):
1491
1720
  raise self.ice()
@@ -1495,36 +1724,42 @@ class PyastGenPass(Pass):
1495
1724
  ]:
1496
1725
  func_node = ast.FuncCall(
1497
1726
  target=node.right,
1498
- params=node.left.values
1499
- if isinstance(node.left, ast.TupleVal)
1500
- else ast.SubNodeList(items=[node.left], kid=[node.left]),
1727
+ params=(
1728
+ node.left.values
1729
+ if isinstance(node.left, ast.TupleVal)
1730
+ else ast.SubNodeList(items=[node.left], kid=[node.left])
1731
+ ),
1501
1732
  kid=node.kid,
1502
1733
  )
1503
1734
  self.exit_func_call(func_node)
1504
1735
  return func_node.gen.py_ast
1505
1736
  elif node.op.name in [Tok.KW_SPAWN]:
1506
1737
  self.needs_jac_feature()
1507
- return self.sync(
1508
- ast3.Call(
1509
- func=self.sync(
1510
- ast3.Attribute(
1511
- value=self.sync(
1512
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1513
- ),
1514
- attr="spawn_call",
1515
- ctx=ast3.Load(),
1516
- )
1517
- ),
1518
- args=[node.left.gen.py_ast, node.right.gen.py_ast],
1519
- keywords=[],
1738
+ return [
1739
+ self.sync(
1740
+ ast3.Call(
1741
+ func=self.sync(
1742
+ ast3.Attribute(
1743
+ value=self.sync(
1744
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1745
+ ),
1746
+ attr="spawn_call",
1747
+ ctx=ast3.Load(),
1748
+ )
1749
+ ),
1750
+ args=[node.left.gen.py_ast[0], node.right.gen.py_ast[0]],
1751
+ keywords=[],
1752
+ )
1520
1753
  )
1521
- )
1754
+ ]
1522
1755
  elif node.op.name in [Tok.PIPE_BKWD, Tok.A_PIPE_BKWD]:
1523
1756
  func_node = ast.FuncCall(
1524
1757
  target=node.left,
1525
- params=node.right.values
1526
- if isinstance(node.right, ast.TupleVal)
1527
- else ast.SubNodeList(items=[node.right], kid=[node.right]),
1758
+ params=(
1759
+ node.right.values
1760
+ if isinstance(node.right, ast.TupleVal)
1761
+ else ast.SubNodeList(items=[node.right], kid=[node.right])
1762
+ ),
1528
1763
  kid=node.kid,
1529
1764
  )
1530
1765
  self.exit_func_call(func_node)
@@ -1533,41 +1768,45 @@ class PyastGenPass(Pass):
1533
1768
  self.error("Invalid pipe target.")
1534
1769
  elif node.op.name == Tok.ELVIS_OP:
1535
1770
  self.needs_jac_feature()
1536
- return self.sync(
1537
- ast3.Call(
1538
- func=self.sync(
1539
- ast3.Attribute(
1540
- value=self.sync(
1541
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1542
- ),
1543
- attr="elvis",
1544
- ctx=ast3.Load(),
1545
- )
1546
- ),
1547
- args=[node.left.gen.py_ast, node.right.gen.py_ast],
1548
- keywords=[],
1771
+ return [
1772
+ self.sync(
1773
+ ast3.Call(
1774
+ func=self.sync(
1775
+ ast3.Attribute(
1776
+ value=self.sync(
1777
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1778
+ ),
1779
+ attr="elvis",
1780
+ ctx=ast3.Load(),
1781
+ )
1782
+ ),
1783
+ args=[node.left.gen.py_ast[0], node.right.gen.py_ast[0]],
1784
+ keywords=[],
1785
+ )
1549
1786
  )
1550
- )
1787
+ ]
1551
1788
  else:
1552
1789
  self.error(
1553
1790
  f"Binary operator {node.op.value} not supported in bootstrap Jac"
1554
1791
  )
1555
- return None
1792
+ return []
1556
1793
 
1557
1794
  def exit_compare_expr(self, node: ast.CompareExpr) -> None:
1558
1795
  """Sub objects.
1559
1796
 
1560
- left: ExprType,
1561
- right: ExprType,
1562
- op: Token,
1797
+ left: Expr,
1798
+ rights: list[Expr],
1799
+ ops: list[Token],
1563
1800
  """
1564
- node.gen.py_ast = self.sync(
1565
- ast3.Compare(
1566
- left=node.left.gen.py_ast,
1567
- comparators=[i.gen.py_ast for i in node.rights],
1568
- ops=[i.gen.py_ast for i in node.ops],
1801
+ node.gen.py_ast = [
1802
+ self.sync(
1803
+ ast3.Compare(
1804
+ left=node.left.gen.py_ast[0],
1805
+ comparators=[i.gen.py_ast[0] for i in node.rights],
1806
+ ops=[i.gen.py_ast[0] for i in node.ops],
1807
+ )
1569
1808
  )
1570
- )
1809
+ ]
1571
1810
 
1572
1811
  def exit_lambda_expr(self, node: ast.LambdaExpr) -> None:
1573
1812
  """Sub objects.
@@ -1575,12 +1814,14 @@ class PyastGenPass(Pass):
1575
1814
  signature: FuncSignature,
1576
1815
  body: ExprType,
1577
1816
  """
1578
- node.gen.py_ast = self.sync(
1579
- ast3.Lambda(
1580
- args=node.signature.gen.py_ast,
1581
- body=node.body.gen.py_ast,
1817
+ node.gen.py_ast = [
1818
+ self.sync(
1819
+ ast3.Lambda(
1820
+ args=node.signature.gen.py_ast[0],
1821
+ body=node.body.gen.py_ast[0],
1822
+ )
1582
1823
  )
1583
- )
1824
+ ]
1584
1825
 
1585
1826
  def exit_unary_expr(self, node: ast.UnaryExpr) -> None:
1586
1827
  """Sub objects.
@@ -1589,42 +1830,58 @@ class PyastGenPass(Pass):
1589
1830
  op: Token,
1590
1831
  """
1591
1832
  if node.op.name == Tok.NOT:
1592
- node.gen.py_ast = self.sync(
1593
- ast3.UnaryOp(
1594
- op=self.sync(ast3.Not()),
1595
- operand=node.operand.gen.py_ast,
1833
+ node.gen.py_ast = [
1834
+ self.sync(
1835
+ ast3.UnaryOp(
1836
+ op=self.sync(ast3.Not()),
1837
+ operand=node.operand.gen.py_ast[0],
1838
+ )
1596
1839
  )
1597
- )
1840
+ ]
1598
1841
  elif node.op.name == Tok.BW_NOT:
1599
- node.gen.py_ast = self.sync(
1600
- ast3.UnaryOp(
1601
- op=self.sync(ast3.Invert()),
1602
- operand=node.operand.gen.py_ast,
1842
+ node.gen.py_ast = [
1843
+ self.sync(
1844
+ ast3.UnaryOp(
1845
+ op=self.sync(ast3.Invert()),
1846
+ operand=node.operand.gen.py_ast[0],
1847
+ )
1603
1848
  )
1604
- )
1849
+ ]
1605
1850
  elif node.op.name == Tok.PLUS:
1606
- node.gen.py_ast = self.sync(
1607
- ast3.UnaryOp(
1608
- op=self.sync(ast3.UAdd()),
1609
- operand=node.operand.gen.py_ast,
1851
+ node.gen.py_ast = [
1852
+ self.sync(
1853
+ ast3.UnaryOp(
1854
+ op=self.sync(ast3.UAdd()),
1855
+ operand=node.operand.gen.py_ast[0],
1856
+ )
1610
1857
  )
1611
- )
1858
+ ]
1612
1859
  elif node.op.name == Tok.MINUS:
1613
- node.gen.py_ast = self.sync(
1614
- ast3.UnaryOp(
1615
- op=self.sync(ast3.USub()),
1616
- operand=node.operand.gen.py_ast,
1860
+ node.gen.py_ast = [
1861
+ self.sync(
1862
+ ast3.UnaryOp(
1863
+ op=self.sync(ast3.USub()),
1864
+ operand=node.operand.gen.py_ast[0],
1865
+ )
1617
1866
  )
1618
- )
1867
+ ]
1619
1868
  elif node.op.name in [Tok.PIPE_FWD, Tok.KW_SPAWN, Tok.A_PIPE_FWD]:
1620
- node.gen.py_ast = self.sync(
1621
- ast3.Call(
1622
- func=node.operand.gen.py_ast,
1623
- args=[],
1624
- keywords=[],
1869
+ node.gen.py_ast = [
1870
+ self.sync(
1871
+ ast3.Call(
1872
+ func=node.operand.gen.py_ast[0],
1873
+ args=[],
1874
+ keywords=[],
1875
+ )
1625
1876
  )
1626
- )
1627
- elif node.op.name in [Tok.STAR_MUL, Tok.STAR_POW]:
1877
+ ]
1878
+ elif node.op.name in [Tok.STAR_MUL]:
1879
+ node.gen.py_ast = [
1880
+ self.sync(
1881
+ ast3.Starred(value=node.operand.gen.py_ast[0], ctx=ast3.Load())
1882
+ )
1883
+ ]
1884
+ elif node.op.name in [Tok.STAR_POW]:
1628
1885
  node.gen.py_ast = node.operand.gen.py_ast
1629
1886
  else:
1630
1887
  self.ice(f"Unknown Unary operator {node.op.value}")
@@ -1636,13 +1893,15 @@ class PyastGenPass(Pass):
1636
1893
  value: ExprType,
1637
1894
  else_value: ExprType,
1638
1895
  """
1639
- node.gen.py_ast = self.sync(
1640
- ast3.IfExp(
1641
- test=node.condition.gen.py_ast,
1642
- body=node.value.gen.py_ast,
1643
- orelse=node.else_value.gen.py_ast,
1896
+ node.gen.py_ast = [
1897
+ self.sync(
1898
+ ast3.IfExp(
1899
+ test=node.condition.gen.py_ast[0],
1900
+ body=node.value.gen.py_ast[0],
1901
+ orelse=node.else_value.gen.py_ast[0],
1902
+ )
1644
1903
  )
1645
- )
1904
+ ]
1646
1905
 
1647
1906
  def exit_multi_string(self, node: ast.MultiString) -> None:
1648
1907
  """Sub objects.
@@ -1659,16 +1918,23 @@ class PyastGenPass(Pass):
1659
1918
  elif isinstance(i, ast.FString):
1660
1919
  pieces.extend(get_pieces(i.parts.items)) if i.parts else None
1661
1920
  elif isinstance(i, ast.ExprStmt):
1662
- pieces.append(i.gen.py_ast)
1921
+ pieces.append(i.gen.py_ast[0])
1663
1922
  else:
1664
1923
  raise self.ice("Multi string made of something weird.")
1665
1924
  return pieces
1666
1925
 
1667
- combined_multi: list[str | ast3.AST] = []
1926
+ combined_multi: list[str | bytes | ast3.AST] = []
1668
1927
  for item in get_pieces(node.strings):
1669
- if combined_multi and (
1670
- (isinstance(item, str) and isinstance(combined_multi[-1], str))
1671
- or (isinstance(item, bytes) and isinstance(combined_multi[-1], bytes))
1928
+ if (
1929
+ combined_multi # noqa: SIM114
1930
+ and isinstance(item, str)
1931
+ and isinstance(combined_multi[-1], str)
1932
+ ):
1933
+ combined_multi[-1] += item
1934
+ elif (
1935
+ combined_multi
1936
+ and isinstance(item, bytes)
1937
+ and isinstance(combined_multi[-1], bytes)
1672
1938
  ):
1673
1939
  combined_multi[-1] += item
1674
1940
  else:
@@ -1677,13 +1943,15 @@ class PyastGenPass(Pass):
1677
1943
  if isinstance(combined_multi[i], (str, bytes)):
1678
1944
  combined_multi[i] = self.sync(ast3.Constant(value=combined_multi[i]))
1679
1945
  if len(combined_multi) > 1 or not isinstance(combined_multi[0], ast3.Constant):
1680
- node.gen.py_ast = self.sync(
1681
- ast3.JoinedStr(
1682
- values=combined_multi,
1946
+ node.gen.py_ast = [
1947
+ self.sync(
1948
+ ast3.JoinedStr(
1949
+ values=combined_multi,
1950
+ )
1683
1951
  )
1684
- )
1952
+ ]
1685
1953
  else:
1686
- node.gen.py_ast = combined_multi[0]
1954
+ node.gen.py_ast = [combined_multi[0]]
1687
1955
 
1688
1956
  def exit_f_string(self, node: ast.FString) -> None:
1689
1957
  """Sub objects.
@@ -1691,7 +1959,9 @@ class PyastGenPass(Pass):
1691
1959
  parts: Optional[SubNodeList[String | ExprType]],
1692
1960
  """
1693
1961
  node.gen.py_ast = (
1694
- node.parts.gen.py_ast if node.parts else self.sync(ast3.Constant(value=""))
1962
+ node.parts.gen.py_ast
1963
+ if node.parts
1964
+ else [self.sync(ast3.Constant(value=""))]
1695
1965
  )
1696
1966
 
1697
1967
  def exit_expr_list(self, node: ast.ExprList) -> None:
@@ -1706,48 +1976,58 @@ class PyastGenPass(Pass):
1706
1976
 
1707
1977
  values: Optional[SubNodeList[ExprType]],
1708
1978
  """
1709
- node.gen.py_ast = self.sync(
1710
- ast3.List(
1711
- elts=node.values.gen.py_ast if node.values else [],
1712
- ctx=node.py_ctx_func(),
1979
+ node.gen.py_ast = [
1980
+ self.sync(
1981
+ ast3.List(
1982
+ elts=node.values.gen.py_ast if node.values else [],
1983
+ ctx=node.py_ctx_func(),
1984
+ )
1713
1985
  )
1714
- )
1986
+ ]
1715
1987
 
1716
1988
  def exit_set_val(self, node: ast.SetVal) -> None:
1717
1989
  """Sub objects.
1718
1990
 
1719
1991
  values: Optional[SubNodeList[ExprType]],
1720
1992
  """
1721
- node.gen.py_ast = self.sync(
1722
- ast3.Set(
1723
- elts=node.values.gen.py_ast if node.values else [],
1724
- ctx=node.py_ctx_func(),
1993
+ node.gen.py_ast = [
1994
+ self.sync(
1995
+ ast3.Set(
1996
+ elts=node.values.gen.py_ast if node.values else [],
1997
+ ctx=node.py_ctx_func(),
1998
+ )
1725
1999
  )
1726
- )
2000
+ ]
1727
2001
 
1728
2002
  def exit_tuple_val(self, node: ast.TupleVal) -> None:
1729
2003
  """Sub objects.
1730
2004
 
1731
2005
  values: Optional[SubNodeList[ExprType | Assignment]],
1732
2006
  """
1733
- node.gen.py_ast = self.sync(
1734
- ast3.Tuple(
1735
- elts=node.values.gen.py_ast if node.values else [],
1736
- ctx=node.py_ctx_func(),
2007
+ node.gen.py_ast = [
2008
+ self.sync(
2009
+ ast3.Tuple(
2010
+ elts=node.values.gen.py_ast if node.values else [],
2011
+ ctx=node.py_ctx_func(),
2012
+ )
1737
2013
  )
1738
- )
2014
+ ]
1739
2015
 
1740
2016
  def exit_dict_val(self, node: ast.DictVal) -> None:
1741
2017
  """Sub objects.
1742
2018
 
1743
2019
  kv_pairs: Sequence[KVPair],
1744
2020
  """
1745
- node.gen.py_ast = self.sync(
1746
- ast3.Dict(
1747
- keys=[x.key.gen.py_ast for x in node.kv_pairs],
1748
- values=[x.value.gen.py_ast for x in node.kv_pairs],
2021
+ node.gen.py_ast = [
2022
+ self.sync(
2023
+ ast3.Dict(
2024
+ keys=[
2025
+ (x.key.gen.py_ast[0] if x.key else None) for x in node.kv_pairs
2026
+ ],
2027
+ values=[x.value.gen.py_ast[0] for x in node.kv_pairs],
2028
+ )
1749
2029
  )
1750
- )
2030
+ ]
1751
2031
 
1752
2032
  def exit_k_v_pair(self, node: ast.KVPair) -> None:
1753
2033
  """Sub objects.
@@ -1763,12 +2043,14 @@ class PyastGenPass(Pass):
1763
2043
  key: NameType,
1764
2044
  value: ExprType,
1765
2045
  """
1766
- node.gen.py_ast = self.sync(
1767
- ast3.keyword(
1768
- arg=node.key.sym_name,
1769
- value=node.value.gen.py_ast,
2046
+ node.gen.py_ast = [
2047
+ self.sync(
2048
+ ast3.keyword(
2049
+ arg=node.key.sym_name if node.key else None,
2050
+ value=node.value.gen.py_ast[0],
2051
+ )
1770
2052
  )
1771
- )
2053
+ ]
1772
2054
 
1773
2055
  def exit_inner_compr(self, node: ast.InnerCompr) -> None:
1774
2056
  """Sub objects.
@@ -1778,14 +2060,16 @@ class PyastGenPass(Pass):
1778
2060
  collection: ExprType,
1779
2061
  conditional: Optional[ExprType],
1780
2062
  """
1781
- node.gen.py_ast = self.sync(
1782
- ast3.comprehension(
1783
- target=node.target.gen.py_ast,
1784
- iter=node.collection.gen.py_ast,
1785
- ifs=[node.conditional.gen.py_ast] if node.conditional else [],
1786
- is_async=0,
2063
+ node.gen.py_ast = [
2064
+ self.sync(
2065
+ ast3.comprehension(
2066
+ target=node.target.gen.py_ast[0],
2067
+ iter=node.collection.gen.py_ast[0],
2068
+ ifs=node.conditional.gen.py_ast if node.conditional else [],
2069
+ is_async=0,
2070
+ )
1787
2071
  )
1788
- )
2072
+ ]
1789
2073
 
1790
2074
  def exit_list_compr(self, node: ast.ListCompr) -> None:
1791
2075
  """Sub objects.
@@ -1793,12 +2077,14 @@ class PyastGenPass(Pass):
1793
2077
  out_expr: ExprType,
1794
2078
  compr: InnerCompr,
1795
2079
  """
1796
- node.gen.py_ast = self.sync(
1797
- ast3.ListComp(
1798
- elt=node.out_expr.gen.py_ast,
1799
- generators=[i.gen.py_ast for i in node.compr],
2080
+ node.gen.py_ast = [
2081
+ self.sync(
2082
+ ast3.ListComp(
2083
+ elt=node.out_expr.gen.py_ast[0],
2084
+ generators=[i.gen.py_ast[0] for i in node.compr],
2085
+ )
1800
2086
  )
1801
- )
2087
+ ]
1802
2088
 
1803
2089
  def exit_gen_compr(self, node: ast.GenCompr) -> None:
1804
2090
  """Sub objects.
@@ -1806,12 +2092,14 @@ class PyastGenPass(Pass):
1806
2092
  out_expr: ExprType,
1807
2093
  compr: InnerCompr,
1808
2094
  """
1809
- node.gen.py_ast = self.sync(
1810
- ast3.GeneratorExp(
1811
- elt=node.out_expr.gen.py_ast,
1812
- generators=[i.gen.py_ast for i in node.compr],
2095
+ node.gen.py_ast = [
2096
+ self.sync(
2097
+ ast3.GeneratorExp(
2098
+ elt=node.out_expr.gen.py_ast[0],
2099
+ generators=[i.gen.py_ast[0] for i in node.compr],
2100
+ )
1813
2101
  )
1814
- )
2102
+ ]
1815
2103
 
1816
2104
  def exit_set_compr(self, node: ast.SetCompr) -> None:
1817
2105
  """Sub objects.
@@ -1819,12 +2107,14 @@ class PyastGenPass(Pass):
1819
2107
  out_expr: ExprType,
1820
2108
  compr: InnerCompr,
1821
2109
  """
1822
- node.gen.py_ast = self.sync(
1823
- ast3.SetComp(
1824
- elt=node.out_expr.gen.py_ast,
1825
- generators=[i.gen.py_ast for i in node.compr],
2110
+ node.gen.py_ast = [
2111
+ self.sync(
2112
+ ast3.SetComp(
2113
+ elt=node.out_expr.gen.py_ast[0],
2114
+ generators=[i.gen.py_ast[0] for i in node.compr],
2115
+ )
1826
2116
  )
1827
- )
2117
+ ]
1828
2118
 
1829
2119
  def exit_dict_compr(self, node: ast.DictCompr) -> None:
1830
2120
  """Sub objects.
@@ -1834,13 +2124,15 @@ class PyastGenPass(Pass):
1834
2124
  collection: ExprType,
1835
2125
  conditional: Optional[ExprType],
1836
2126
  """
1837
- node.gen.py_ast = self.sync(
1838
- ast3.DictComp(
1839
- key=node.kv_pair.key.gen.py_ast,
1840
- value=node.kv_pair.value.gen.py_ast,
1841
- generators=[i.gen.py_ast for i in node.compr],
2127
+ node.gen.py_ast = [
2128
+ self.sync(
2129
+ ast3.DictComp(
2130
+ key=node.kv_pair.key.gen.py_ast[0] if node.kv_pair.key else None,
2131
+ value=node.kv_pair.value.gen.py_ast[0],
2132
+ generators=[i.gen.py_ast[0] for i in node.compr],
2133
+ )
1842
2134
  )
1843
- )
2135
+ ]
1844
2136
 
1845
2137
  def exit_atom_trailer(self, node: ast.AtomTrailer) -> None:
1846
2138
  """Sub objects.
@@ -1851,68 +2143,91 @@ class PyastGenPass(Pass):
1851
2143
  is_attr: bool,
1852
2144
  """
1853
2145
  if node.is_attr:
1854
- node.gen.py_ast = self.sync(
1855
- ast3.Attribute(
1856
- value=node.target.gen.py_ast,
1857
- attr=node.right.sym_name,
1858
- ctx=node.right.py_ctx_func(),
2146
+ node.gen.py_ast = [
2147
+ self.sync(
2148
+ ast3.Attribute(
2149
+ value=node.target.gen.py_ast[0],
2150
+ attr=(
2151
+ node.right.sym_name
2152
+ if isinstance(node.right, ast.AstSymbolNode)
2153
+ else ""
2154
+ ),
2155
+ ctx=(
2156
+ node.right.py_ctx_func()
2157
+ if isinstance(node.right, ast.AstSymbolNode)
2158
+ else ast3.Load()
2159
+ ),
2160
+ )
1859
2161
  )
1860
- )
2162
+ ]
1861
2163
  elif isinstance(node.right, ast.FilterCompr):
1862
- node.gen.py_ast = self.sync(
1863
- ast3.Call(
1864
- func=node.right.gen.py_ast,
1865
- args=[node.target.gen.py_ast],
1866
- keywords=[],
2164
+ node.gen.py_ast = [
2165
+ self.sync(
2166
+ ast3.Call(
2167
+ func=node.right.gen.py_ast[0],
2168
+ args=[node.target.gen.py_ast[0]],
2169
+ keywords=[],
2170
+ )
1867
2171
  )
1868
- )
2172
+ ]
1869
2173
  elif isinstance(node.right, ast.AssignCompr):
1870
- node.gen.py_ast = self.sync(
1871
- ast3.Call(
1872
- func=self.sync(
1873
- ast3.Attribute(
1874
- value=self.sync(
1875
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1876
- ),
1877
- attr="assign_compr",
1878
- ctx=ast3.Load(),
1879
- )
1880
- ),
1881
- args=[node.target.gen.py_ast, node.right.gen.py_ast],
1882
- keywords=[],
2174
+ node.gen.py_ast = [
2175
+ self.sync(
2176
+ ast3.Call(
2177
+ func=self.sync(
2178
+ ast3.Attribute(
2179
+ value=self.sync(
2180
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2181
+ ),
2182
+ attr="assign_compr",
2183
+ ctx=ast3.Load(),
2184
+ )
2185
+ ),
2186
+ args=[node.target.gen.py_ast[0], node.right.gen.py_ast[0]],
2187
+ keywords=[],
2188
+ )
1883
2189
  )
1884
- )
2190
+ ]
1885
2191
  elif isinstance(node.right, ast.EdgeOpRef):
1886
- node.gen.py_ast = self.translate_edge_op_ref(
1887
- node.target.gen.py_ast, node.right
1888
- )
2192
+ node.gen.py_ast = [
2193
+ self.translate_edge_op_ref(node.target.gen.py_ast[0], node.right)
2194
+ ]
1889
2195
  else:
1890
- node.gen.py_ast = self.sync(
1891
- ast3.Subscript(
1892
- value=node.target.gen.py_ast,
1893
- slice=node.right.gen.py_ast,
1894
- ctx=node.right.py_ctx_func(),
2196
+ node.gen.py_ast = [
2197
+ self.sync(
2198
+ ast3.Subscript(
2199
+ value=node.target.gen.py_ast[0],
2200
+ slice=node.right.gen.py_ast[0],
2201
+ ctx=(
2202
+ node.right.py_ctx_func()
2203
+ if isinstance(node.right, ast.AstSymbolNode)
2204
+ else ast3.Load()
2205
+ ),
2206
+ )
1895
2207
  )
1896
- )
1897
- node.right.gen.py_ast.ctx = ast3.Load() # type: ignore
2208
+ ]
2209
+ node.right.gen.py_ast[0].ctx = ast3.Load() # type: ignore
1898
2210
  if node.is_null_ok:
1899
- node.gen.py_ast.value = self.sync(
1900
- ast3.Name(id="__jac_tmp", ctx=ast3.Load())
1901
- )
1902
- node.gen.py_ast = self.sync(
1903
- ast3.IfExp(
1904
- test=self.sync(
1905
- ast3.NamedExpr(
1906
- target=self.sync(
1907
- ast3.Name(id="__jac_tmp", ctx=ast3.Store())
1908
- ),
1909
- value=node.target.gen.py_ast,
1910
- )
1911
- ),
1912
- body=node.gen.py_ast,
1913
- orelse=self.sync(ast3.Constant(value=None)),
2211
+ if isinstance(node.gen.py_ast[0], ast3.Attribute):
2212
+ node.gen.py_ast[0].value = self.sync(
2213
+ ast3.Name(id="__jac_tmp", ctx=ast3.Load())
1914
2214
  )
1915
- )
2215
+ node.gen.py_ast = [
2216
+ self.sync(
2217
+ ast3.IfExp(
2218
+ test=self.sync(
2219
+ ast3.NamedExpr(
2220
+ target=self.sync(
2221
+ ast3.Name(id="__jac_tmp", ctx=ast3.Store())
2222
+ ),
2223
+ value=node.target.gen.py_ast[0],
2224
+ )
2225
+ ),
2226
+ body=node.gen.py_ast[0],
2227
+ orelse=self.sync(ast3.Constant(value=None)),
2228
+ )
2229
+ )
2230
+ ]
1916
2231
 
1917
2232
  def exit_atom_unit(self, node: ast.AtomUnit) -> None:
1918
2233
  """Sub objects.
@@ -1925,36 +2240,32 @@ class PyastGenPass(Pass):
1925
2240
  def exit_func_call(self, node: ast.FuncCall) -> None:
1926
2241
  """Sub objects.
1927
2242
 
1928
- target: AtomType,
1929
- params: Optional[SubNodeList[ExprType | KVPair]],
2243
+ target: Expr,
2244
+ params: Optional[SubNodeList[Expr | KWPair]],
1930
2245
  """
1931
- node.gen.py_ast = self.sync(self.gen_func_call(node.target, node.params))
2246
+ node.gen.py_ast = [self.sync(self.gen_func_call(node.target, node.params))]
1932
2247
 
1933
2248
  def gen_func_call(
1934
2249
  self,
1935
- target: ast.AtomExpr,
1936
- params: Optional[ast.SubNodeList[ast.Expr | ast.Assignment]],
2250
+ target: ast.Expr,
2251
+ params: Optional[ast.SubNodeList[ast.Expr | ast.KWPair]],
1937
2252
  ) -> ast3.Call:
1938
2253
  """Generate a function call."""
1939
- func = target.gen.py_ast
2254
+ func = target.gen.py_ast[0]
1940
2255
  args = []
1941
2256
  keywords = []
1942
2257
  if params and len(params.items) > 0:
1943
2258
  for x in params.items:
1944
- if isinstance(x, ast.UnaryExpr) and x.op.name == Tok.STAR_MUL:
1945
- args.append(
1946
- self.sync(
1947
- ast3.Starred(value=x.operand.gen.py_ast, ctx=ast3.Load()), x
1948
- )
1949
- )
1950
- elif isinstance(x, ast.UnaryExpr) and x.op.name == Tok.STAR_POW:
2259
+ if isinstance(x, ast.UnaryExpr) and x.op.name == Tok.STAR_POW:
1951
2260
  keywords.append(
1952
- self.sync(ast3.keyword(value=x.operand.gen.py_ast), x)
2261
+ self.sync(ast3.keyword(value=x.operand.gen.py_ast[0]), x)
1953
2262
  )
1954
2263
  elif isinstance(x, ast.Expr):
1955
- args.append(x.gen.py_ast)
1956
- elif isinstance(x, ast.KWPair):
1957
- keywords.append(x.gen.py_ast)
2264
+ args.append(x.gen.py_ast[0])
2265
+ elif isinstance(x, ast.KWPair) and isinstance(
2266
+ x.gen.py_ast[0], ast3.keyword
2267
+ ):
2268
+ keywords.append(x.gen.py_ast[0])
1958
2269
  else:
1959
2270
  self.ice("Invalid Parameter")
1960
2271
  return ast3.Call(func=func, args=args, keywords=keywords)
@@ -1968,15 +2279,17 @@ class PyastGenPass(Pass):
1968
2279
  is_range: bool,
1969
2280
  """
1970
2281
  if node.is_range:
1971
- node.gen.py_ast = self.sync(
1972
- ast3.Slice(
1973
- lower=node.start.gen.py_ast if node.start else None,
1974
- upper=node.stop.gen.py_ast if node.stop else None,
1975
- step=node.step.gen.py_ast if node.step else None,
2282
+ node.gen.py_ast = [
2283
+ self.sync(
2284
+ ast3.Slice(
2285
+ lower=node.start.gen.py_ast if node.start else None,
2286
+ upper=node.stop.gen.py_ast if node.stop else None,
2287
+ step=node.step.gen.py_ast if node.step else None,
2288
+ )
1976
2289
  )
1977
- )
2290
+ ]
1978
2291
  else:
1979
- node.gen.py_ast = node.start.gen.py_ast if node.start else None
2292
+ node.gen.py_ast = node.start.gen.py_ast if node.start else []
1980
2293
 
1981
2294
  def exit_special_var_ref(self, node: ast.SpecialVarRef) -> None:
1982
2295
  """Sub objects.
@@ -1990,7 +2303,7 @@ class PyastGenPass(Pass):
1990
2303
  var_ast = var_ast_expr.value
1991
2304
  except Exception:
1992
2305
  raise self.ice("Invalid special var ref for pyast generation")
1993
- node.gen.py_ast = self.sync(var_ast, deep=True)
2306
+ node.gen.py_ast = [self.sync(var_ast, deep=True)]
1994
2307
 
1995
2308
  def exit_edge_op_ref(self, node: ast.EdgeOpRef) -> None:
1996
2309
  """Sub objects.
@@ -2004,7 +2317,7 @@ class PyastGenPass(Pass):
2004
2317
  if node.from_walker
2005
2318
  else ast3.Name(id="self", ctx=ast3.Load())
2006
2319
  )
2007
- node.gen.py_ast = self.translate_edge_op_ref(loc, node)
2320
+ node.gen.py_ast = [self.translate_edge_op_ref(loc, node)]
2008
2321
 
2009
2322
  def translate_edge_op_ref(self, loc: ast3.AST, node: ast.EdgeOpRef) -> ast3.AST:
2010
2323
  """Generate ast for edge op ref call."""
@@ -2038,12 +2351,16 @@ class PyastGenPass(Pass):
2038
2351
  ctx=ast3.Load(),
2039
2352
  )
2040
2353
  ),
2041
- node.filter_type.gen.py_ast
2042
- if node.filter_type
2043
- else self.sync(ast3.Constant(value=None)),
2044
- node.filter_cond.gen.py_ast
2045
- if node.filter_cond
2046
- else self.sync(ast3.Constant(value=None)),
2354
+ (
2355
+ node.filter_type.gen.py_ast[0]
2356
+ if node.filter_type
2357
+ else self.sync(ast3.Constant(value=None))
2358
+ ),
2359
+ (
2360
+ node.filter_cond.gen.py_ast[0]
2361
+ if node.filter_cond
2362
+ else self.sync(ast3.Constant(value=None))
2363
+ ),
2047
2364
  ],
2048
2365
  keywords=[],
2049
2366
  )
@@ -2064,103 +2381,123 @@ class PyastGenPass(Pass):
2064
2381
  conn_assign: Optional[AssignCompr],
2065
2382
  edge_dir: EdgeDir,
2066
2383
  """
2067
- node.gen.py_ast = self.sync(
2068
- ast3.Call(
2069
- func=self.sync(
2070
- ast3.Attribute(
2071
- value=self.sync(
2072
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2073
- ),
2074
- attr="build_edge",
2075
- ctx=ast3.Load(),
2076
- )
2077
- ),
2078
- args=[
2079
- self.sync(
2384
+ node.gen.py_ast = [
2385
+ self.sync(
2386
+ ast3.Call(
2387
+ func=self.sync(
2080
2388
  ast3.Attribute(
2081
2389
  value=self.sync(
2082
- ast3.Attribute(
2083
- value=self.sync(
2084
- ast3.Name(
2085
- id=Con.JAC_FEATURE.value, ctx=ast3.Load()
2086
- )
2087
- ),
2088
- attr="EdgeDir",
2089
- ctx=ast3.Load(),
2090
- )
2390
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2091
2391
  ),
2092
- attr=node.edge_dir.name,
2392
+ attr="build_edge",
2093
2393
  ctx=ast3.Load(),
2094
2394
  )
2095
2395
  ),
2096
- node.conn_type.gen.py_ast
2097
- if node.conn_type
2098
- else self.sync(ast3.Constant(value=None)),
2099
- node.conn_assign.gen.py_ast
2100
- if node.conn_assign
2101
- else self.sync(ast3.Constant(value=None)),
2102
- ],
2103
- keywords=[],
2396
+ args=[
2397
+ self.sync(
2398
+ ast3.Attribute(
2399
+ value=self.sync(
2400
+ ast3.Attribute(
2401
+ value=self.sync(
2402
+ ast3.Name(
2403
+ id=Con.JAC_FEATURE.value,
2404
+ ctx=ast3.Load(),
2405
+ )
2406
+ ),
2407
+ attr="EdgeDir",
2408
+ ctx=ast3.Load(),
2409
+ )
2410
+ ),
2411
+ attr=node.edge_dir.name,
2412
+ ctx=ast3.Load(),
2413
+ )
2414
+ ),
2415
+ (
2416
+ node.conn_type.gen.py_ast[0]
2417
+ if node.conn_type
2418
+ else self.sync(ast3.Constant(value=None))
2419
+ ),
2420
+ (
2421
+ node.conn_assign.gen.py_ast[0]
2422
+ if node.conn_assign
2423
+ else self.sync(ast3.Constant(value=None))
2424
+ ),
2425
+ ],
2426
+ keywords=[],
2427
+ )
2104
2428
  )
2105
- )
2429
+ ]
2106
2430
 
2107
2431
  def exit_filter_compr(self, node: ast.FilterCompr) -> None:
2108
2432
  """Sub objects.
2109
2433
 
2110
2434
  compares: SubNodeList[BinaryExpr],
2111
2435
  """
2112
- node.gen.py_ast = self.sync(
2113
- ast3.Lambda(
2114
- args=self.sync(
2115
- ast3.arguments(
2116
- posonlyargs=[],
2117
- args=[self.sync(ast3.arg(arg="x"))],
2118
- kwonlyargs=[],
2119
- kw_defaults=[],
2120
- defaults=[],
2121
- )
2122
- ),
2123
- body=self.sync(
2124
- ast3.ListComp(
2125
- elt=self.sync(ast3.Name(id="i", ctx=ast3.Load())),
2126
- generators=[
2127
- self.sync(
2128
- ast3.comprehension(
2129
- target=self.sync(
2130
- ast3.Name(id="i", ctx=ast3.Store())
2131
- ),
2132
- iter=self.sync(ast3.Name(id="x", ctx=ast3.Load())),
2133
- ifs=[
2134
- self.sync(
2135
- ast3.Compare(
2136
- left=self.sync(
2137
- ast3.Attribute(
2138
- value=self.sync(
2139
- ast3.Name(
2140
- id="i", ctx=ast3.Load()
2436
+ node.gen.py_ast = [
2437
+ self.sync(
2438
+ ast3.Lambda(
2439
+ args=self.sync(
2440
+ ast3.arguments(
2441
+ posonlyargs=[],
2442
+ args=[self.sync(ast3.arg(arg="x"))],
2443
+ kwonlyargs=[],
2444
+ kw_defaults=[],
2445
+ defaults=[],
2446
+ )
2447
+ ),
2448
+ body=self.sync(
2449
+ ast3.ListComp(
2450
+ elt=self.sync(ast3.Name(id="i", ctx=ast3.Load())),
2451
+ generators=[
2452
+ self.sync(
2453
+ ast3.comprehension(
2454
+ target=self.sync(
2455
+ ast3.Name(id="i", ctx=ast3.Store())
2456
+ ),
2457
+ iter=self.sync(
2458
+ ast3.Name(id="x", ctx=ast3.Load())
2459
+ ),
2460
+ ifs=[
2461
+ self.sync(
2462
+ ast3.Compare(
2463
+ left=self.sync(
2464
+ ast3.Attribute(
2465
+ value=self.sync(
2466
+ ast3.Name(
2467
+ id="i",
2468
+ ctx=ast3.Load(),
2469
+ ),
2470
+ jac_node=x,
2141
2471
  ),
2142
- jac_node=x,
2472
+ attr=x.gen.py_ast[
2473
+ 0
2474
+ ].left.id,
2475
+ ctx=ast3.Load(),
2143
2476
  ),
2144
- attr=x.gen.py_ast.left.id,
2145
- ctx=ast3.Load(),
2477
+ jac_node=x,
2146
2478
  ),
2147
- jac_node=x,
2479
+ ops=x.gen.py_ast[0].ops,
2480
+ comparators=x.gen.py_ast[
2481
+ 0
2482
+ ].comparators,
2148
2483
  ),
2149
- ops=x.gen.py_ast.ops,
2150
- comparators=x.gen.py_ast.comparators,
2151
- ),
2152
- jac_node=x,
2153
- )
2154
- for x in node.compares.items
2155
- ],
2156
- is_async=0,
2484
+ jac_node=x,
2485
+ )
2486
+ for x in node.compares.items
2487
+ if isinstance(x.gen.py_ast[0], ast3.Compare)
2488
+ and isinstance(
2489
+ x.gen.py_ast[0].left, ast3.Name
2490
+ )
2491
+ ],
2492
+ is_async=0,
2493
+ )
2157
2494
  )
2158
- )
2159
- ],
2160
- )
2161
- ),
2495
+ ],
2496
+ )
2497
+ ),
2498
+ )
2162
2499
  )
2163
- )
2500
+ ]
2164
2501
 
2165
2502
  def exit_assign_compr(self, node: ast.AssignCompr) -> None:
2166
2503
  """Sub objects.
@@ -2170,24 +2507,29 @@ class PyastGenPass(Pass):
2170
2507
  keys = []
2171
2508
  values = []
2172
2509
  for i in node.assigns.items:
2173
- keys.append(self.sync(ast3.Constant(i.key.sym_name)))
2174
- values.append(i.value.gen.py_ast)
2175
- keys = self.sync(ast3.Tuple(elts=keys, ctx=ast3.Load()))
2176
- values = self.sync(ast3.Tuple(elts=values, ctx=ast3.Load()))
2177
- node.gen.py_ast = self.sync(ast3.Tuple(elts=[keys, values], ctx=ast3.Load()))
2510
+ if i.key: # TODO: add support for **kwargs in assign_compr
2511
+ keys.append(self.sync(ast3.Constant(i.key.sym_name)))
2512
+ values.append(i.value.gen.py_ast[0])
2513
+ key_tup = self.sync(ast3.Tuple(elts=keys, ctx=ast3.Load()))
2514
+ val_tup = self.sync(ast3.Tuple(elts=values, ctx=ast3.Load()))
2515
+ node.gen.py_ast = [
2516
+ self.sync(ast3.Tuple(elts=[key_tup, val_tup], ctx=ast3.Load()))
2517
+ ]
2178
2518
 
2179
2519
  def exit_match_stmt(self, node: ast.MatchStmt) -> None:
2180
2520
  """Sub objects.
2181
2521
 
2182
- target: SubNodeList[ExprType],
2522
+ target: Expr,
2183
2523
  cases: list[MatchCase],
2184
2524
  """
2185
- node.gen.py_ast = self.sync(
2186
- ast3.Match(
2187
- subject=node.target.gen.py_ast,
2188
- cases=[x.gen.py_ast for x in node.cases],
2525
+ node.gen.py_ast = [
2526
+ self.sync(
2527
+ ast3.Match(
2528
+ subject=node.target.gen.py_ast[0],
2529
+ cases=[x.gen.py_ast[0] for x in node.cases],
2530
+ )
2189
2531
  )
2190
- )
2532
+ ]
2191
2533
 
2192
2534
  def exit_match_case(self, node: ast.MatchCase) -> None:
2193
2535
  """Sub objects.
@@ -2196,24 +2538,28 @@ class PyastGenPass(Pass):
2196
2538
  guard: Optional[ExprType],
2197
2539
  body: SubNodeList[CodeBlockStmt],
2198
2540
  """
2199
- node.gen.py_ast = self.sync(
2200
- ast3.match_case(
2201
- pattern=node.pattern.gen.py_ast,
2202
- guard=node.guard.gen.py_ast if node.guard else None,
2203
- body=self.resolve_stmt_block(node.body),
2541
+ node.gen.py_ast = [
2542
+ self.sync(
2543
+ ast3.match_case(
2544
+ pattern=node.pattern.gen.py_ast[0],
2545
+ guard=node.guard.gen.py_ast[0] if node.guard else None,
2546
+ body=self.resolve_stmt_block(node.body),
2547
+ )
2204
2548
  )
2205
- )
2549
+ ]
2206
2550
 
2207
2551
  def exit_match_or(self, node: ast.MatchOr) -> None:
2208
2552
  """Sub objects.
2209
2553
 
2210
2554
  patterns: list[MatchPattern],
2211
2555
  """
2212
- node.gen.py_ast = self.sync(
2213
- ast3.MatchOr(
2214
- patterns=[x.gen.py_ast for x in node.patterns],
2556
+ node.gen.py_ast = [
2557
+ self.sync(
2558
+ ast3.MatchOr(
2559
+ patterns=[x.gen.py_ast[0] for x in node.patterns],
2560
+ )
2215
2561
  )
2216
- )
2562
+ ]
2217
2563
 
2218
2564
  def exit_match_as(self, node: ast.MatchAs) -> None:
2219
2565
  """Sub objects.
@@ -2221,41 +2567,45 @@ class PyastGenPass(Pass):
2221
2567
  name: NameType,
2222
2568
  pattern: MatchPattern,
2223
2569
  """
2224
- node.gen.py_ast = self.sync(
2225
- ast3.MatchAs(
2226
- name=node.name.sym_name,
2227
- pattern=node.pattern.gen.py_ast if node.pattern else None,
2570
+ node.gen.py_ast = [
2571
+ self.sync(
2572
+ ast3.MatchAs(
2573
+ name=node.name.sym_name,
2574
+ pattern=node.pattern.gen.py_ast[0] if node.pattern else None,
2575
+ )
2228
2576
  )
2229
- )
2577
+ ]
2230
2578
 
2231
2579
  def exit_match_wild(self, node: ast.MatchWild) -> None:
2232
2580
  """Sub objects."""
2233
- node.gen.py_ast = self.sync(ast3.MatchAs())
2581
+ node.gen.py_ast = [self.sync(ast3.MatchAs())]
2234
2582
 
2235
2583
  def exit_match_value(self, node: ast.MatchValue) -> None:
2236
2584
  """Sub objects.
2237
2585
 
2238
2586
  value: ExprType,
2239
2587
  """
2240
- node.gen.py_ast = self.sync(ast3.MatchValue(value=node.value.gen.py_ast))
2588
+ node.gen.py_ast = [self.sync(ast3.MatchValue(value=node.value.gen.py_ast[0]))]
2241
2589
 
2242
2590
  def exit_match_singleton(self, node: ast.MatchSingleton) -> None:
2243
2591
  """Sub objects.
2244
2592
 
2245
2593
  value: Bool | Null,
2246
2594
  """
2247
- node.gen.py_ast = self.sync(ast3.MatchSingleton(value=node.value.lit_value))
2595
+ node.gen.py_ast = [self.sync(ast3.MatchSingleton(value=node.value.lit_value))]
2248
2596
 
2249
2597
  def exit_match_sequence(self, node: ast.MatchSequence) -> None:
2250
2598
  """Sub objects.
2251
2599
 
2252
2600
  values: list[MatchPattern],
2253
2601
  """
2254
- node.gen.py_ast = self.sync(
2255
- ast3.MatchSequence(
2256
- patterns=[x.gen.py_ast for x in node.values],
2602
+ node.gen.py_ast = [
2603
+ self.sync(
2604
+ ast3.MatchSequence(
2605
+ patterns=[x.gen.py_ast[0] for x in node.values],
2606
+ )
2257
2607
  )
2258
- )
2608
+ ]
2259
2609
 
2260
2610
  def exit_match_mapping(self, node: ast.MatchMapping) -> None:
2261
2611
  """Sub objects.
@@ -2264,12 +2614,17 @@ class PyastGenPass(Pass):
2264
2614
  """
2265
2615
  mapping = self.sync(ast3.MatchMapping(keys=[], patterns=[], rest=None))
2266
2616
  for i in node.values:
2267
- if isinstance(i, ast.MatchKVPair):
2268
- mapping.keys.append(i.key.value.gen.py_ast)
2269
- mapping.patterns.append(i.value.gen.py_ast)
2617
+ if (
2618
+ isinstance(i, ast.MatchKVPair)
2619
+ and isinstance(i.key, ast.MatchValue)
2620
+ and isinstance(i.key.value.gen.py_ast[0], ast3.expr)
2621
+ and isinstance(i.value.gen.py_ast[0], ast3.pattern)
2622
+ ):
2623
+ mapping.keys.append(i.key.value.gen.py_ast[0])
2624
+ mapping.patterns.append(i.value.gen.py_ast[0])
2270
2625
  elif isinstance(i, ast.MatchStar):
2271
2626
  mapping.rest = i.name.sym_name
2272
- node.gen.py_ast = mapping
2627
+ node.gen.py_ast = [mapping]
2273
2628
 
2274
2629
  def exit_match_k_v_pair(self, node: ast.MatchKVPair) -> None:
2275
2630
  """Sub objects.
@@ -2277,11 +2632,13 @@ class PyastGenPass(Pass):
2277
2632
  key: MatchPattern | NameType,
2278
2633
  value: MatchPattern,
2279
2634
  """
2280
- node.gen.py_ast = self.sync(
2281
- ast3.MatchMapping(
2282
- patterns=[node.key.gen.py_ast, node.value.gen.py_ast],
2635
+ node.gen.py_ast = [
2636
+ self.sync(
2637
+ ast3.MatchMapping(
2638
+ patterns=[node.key.gen.py_ast[0], node.value.gen.py_ast[0]],
2639
+ )
2283
2640
  )
2284
- )
2641
+ ]
2285
2642
 
2286
2643
  def exit_match_star(self, node: ast.MatchStar) -> None:
2287
2644
  """Sub objects.
@@ -2289,7 +2646,7 @@ class PyastGenPass(Pass):
2289
2646
  name: NameType,
2290
2647
  is_list: bool,
2291
2648
  """
2292
- node.gen.py_ast = self.sync(ast3.MatchStar(name=node.name.sym_name))
2649
+ node.gen.py_ast = [self.sync(ast3.MatchStar(name=node.name.sym_name))]
2293
2650
 
2294
2651
  def exit_match_arch(self, node: ast.MatchArch) -> None:
2295
2652
  """Sub objects.
@@ -2298,20 +2655,32 @@ class PyastGenPass(Pass):
2298
2655
  arg_patterns: Optional[SubNodeList[MatchPattern]],
2299
2656
  kw_patterns: Optional[SubNodeList[MatchKVPair]],
2300
2657
  """
2301
- node.gen.py_ast = self.sync(
2302
- ast3.MatchClass(
2303
- cls=node.name.gen.py_ast,
2304
- patterns=[x.gen.py_ast for x in node.arg_patterns.items]
2305
- if node.arg_patterns
2306
- else [],
2307
- kwd_attrs=[x.key.sym_name for x in node.kw_patterns.items]
2308
- if node.kw_patterns
2309
- else [],
2310
- kwd_patterns=[x.value.gen.py_ast for x in node.kw_patterns.items]
2311
- if node.kw_patterns
2312
- else [],
2658
+ node.gen.py_ast = [
2659
+ self.sync(
2660
+ ast3.MatchClass(
2661
+ cls=node.name.gen.py_ast[0],
2662
+ patterns=(
2663
+ [x.gen.py_ast[0] for x in node.arg_patterns.items]
2664
+ if node.arg_patterns
2665
+ else []
2666
+ ),
2667
+ kwd_attrs=(
2668
+ [
2669
+ x.key.sym_name
2670
+ for x in node.kw_patterns.items
2671
+ if isinstance(x.key, ast.NameSpec)
2672
+ ]
2673
+ if node.kw_patterns
2674
+ else []
2675
+ ),
2676
+ kwd_patterns=(
2677
+ [x.value.gen.py_ast[0] for x in node.kw_patterns.items]
2678
+ if node.kw_patterns
2679
+ else []
2680
+ ),
2681
+ )
2313
2682
  )
2314
- )
2683
+ ]
2315
2684
 
2316
2685
  def exit_token(self, node: ast.Token) -> None:
2317
2686
  """Sub objects.
@@ -2325,61 +2694,61 @@ class PyastGenPass(Pass):
2325
2694
  pos_end: int,
2326
2695
  """
2327
2696
  if node.name == Tok.KW_AND:
2328
- node.gen.py_ast = self.sync(ast3.And())
2697
+ node.gen.py_ast = [self.sync(ast3.And())]
2329
2698
  elif node.name == Tok.KW_OR:
2330
- node.gen.py_ast = self.sync(ast3.Or())
2699
+ node.gen.py_ast = [self.sync(ast3.Or())]
2331
2700
  elif node.name in [Tok.PLUS, Tok.ADD_EQ]:
2332
- node.gen.py_ast = self.sync(ast3.Add())
2701
+ node.gen.py_ast = [self.sync(ast3.Add())]
2333
2702
  elif node.name in [Tok.BW_AND, Tok.BW_AND_EQ]:
2334
- node.gen.py_ast = self.sync(ast3.BitAnd())
2703
+ node.gen.py_ast = [self.sync(ast3.BitAnd())]
2335
2704
  elif node.name in [Tok.BW_OR, Tok.BW_OR_EQ]:
2336
- node.gen.py_ast = self.sync(ast3.BitOr())
2705
+ node.gen.py_ast = [self.sync(ast3.BitOr())]
2337
2706
  elif node.name in [Tok.BW_XOR, Tok.BW_XOR_EQ]:
2338
- node.gen.py_ast = self.sync(ast3.BitXor())
2707
+ node.gen.py_ast = [self.sync(ast3.BitXor())]
2339
2708
  elif node.name in [Tok.DIV, Tok.DIV_EQ]:
2340
- node.gen.py_ast = self.sync(ast3.Div())
2709
+ node.gen.py_ast = [self.sync(ast3.Div())]
2341
2710
  elif node.name in [Tok.FLOOR_DIV, Tok.FLOOR_DIV_EQ]:
2342
- node.gen.py_ast = self.sync(ast3.FloorDiv())
2711
+ node.gen.py_ast = [self.sync(ast3.FloorDiv())]
2343
2712
  elif node.name in [Tok.LSHIFT, Tok.LSHIFT_EQ]:
2344
- node.gen.py_ast = self.sync(ast3.LShift())
2713
+ node.gen.py_ast = [self.sync(ast3.LShift())]
2345
2714
  elif node.name in [Tok.MOD, Tok.MOD_EQ]:
2346
- node.gen.py_ast = self.sync(ast3.Mod())
2715
+ node.gen.py_ast = [self.sync(ast3.Mod())]
2347
2716
  elif node.name in [Tok.STAR_MUL, Tok.MUL_EQ]:
2348
- node.gen.py_ast = self.sync(ast3.Mult())
2717
+ node.gen.py_ast = [self.sync(ast3.Mult())]
2349
2718
  elif node.name in [Tok.DECOR_OP, Tok.MATMUL_EQ]:
2350
- node.gen.py_ast = self.sync(ast3.MatMult())
2719
+ node.gen.py_ast = [self.sync(ast3.MatMult())]
2351
2720
  elif node.name in [Tok.STAR_POW, Tok.STAR_POW_EQ]:
2352
- node.gen.py_ast = self.sync(ast3.Pow())
2721
+ node.gen.py_ast = [self.sync(ast3.Pow())]
2353
2722
  elif node.name in [Tok.RSHIFT, Tok.RSHIFT_EQ]:
2354
- node.gen.py_ast = self.sync(ast3.RShift())
2723
+ node.gen.py_ast = [self.sync(ast3.RShift())]
2355
2724
  elif node.name in [Tok.MINUS, Tok.SUB_EQ]:
2356
- node.gen.py_ast = self.sync(ast3.Sub())
2725
+ node.gen.py_ast = [self.sync(ast3.Sub())]
2357
2726
  elif node.name in [Tok.BW_NOT, Tok.BW_NOT_EQ]:
2358
- node.gen.py_ast = self.sync(ast3.Invert())
2727
+ node.gen.py_ast = [self.sync(ast3.Invert())]
2359
2728
  elif node.name in [Tok.NOT]:
2360
- node.gen.py_ast = self.sync(ast3.Not())
2729
+ node.gen.py_ast = [self.sync(ast3.Not())]
2361
2730
  elif node.name in [Tok.EQ]:
2362
- node.gen.py_ast = self.sync(ast3.NotEq())
2731
+ node.gen.py_ast = [self.sync(ast3.NotEq())]
2363
2732
  elif node.name == Tok.EE:
2364
- node.gen.py_ast = self.sync(ast3.Eq())
2733
+ node.gen.py_ast = [self.sync(ast3.Eq())]
2365
2734
  elif node.name == Tok.GT:
2366
- node.gen.py_ast = self.sync(ast3.Gt())
2735
+ node.gen.py_ast = [self.sync(ast3.Gt())]
2367
2736
  elif node.name == Tok.GTE:
2368
- node.gen.py_ast = self.sync(ast3.GtE())
2737
+ node.gen.py_ast = [self.sync(ast3.GtE())]
2369
2738
  elif node.name == Tok.KW_IN:
2370
- node.gen.py_ast = self.sync(ast3.In())
2739
+ node.gen.py_ast = [self.sync(ast3.In())]
2371
2740
  elif node.name == Tok.KW_IS:
2372
- node.gen.py_ast = self.sync(ast3.Is())
2741
+ node.gen.py_ast = [self.sync(ast3.Is())]
2373
2742
  elif node.name == Tok.KW_ISN:
2374
- node.gen.py_ast = self.sync(ast3.IsNot())
2743
+ node.gen.py_ast = [self.sync(ast3.IsNot())]
2375
2744
  elif node.name == Tok.LT:
2376
- node.gen.py_ast = self.sync(ast3.Lt())
2745
+ node.gen.py_ast = [self.sync(ast3.Lt())]
2377
2746
  elif node.name == Tok.LTE:
2378
- node.gen.py_ast = self.sync(ast3.LtE())
2747
+ node.gen.py_ast = [self.sync(ast3.LtE())]
2379
2748
  elif node.name == Tok.NE:
2380
- node.gen.py_ast = self.sync(ast3.NotEq())
2749
+ node.gen.py_ast = [self.sync(ast3.NotEq())]
2381
2750
  elif node.name == Tok.KW_NIN:
2382
- node.gen.py_ast = self.sync(ast3.NotIn())
2751
+ node.gen.py_ast = [self.sync(ast3.NotIn())]
2383
2752
 
2384
2753
  def exit_name(self, node: ast.Name) -> None:
2385
2754
  """Sub objects.
@@ -2392,23 +2761,27 @@ class PyastGenPass(Pass):
2392
2761
  pos_start: int,
2393
2762
  pos_end: int,
2394
2763
  """
2395
- node.gen.py_ast = self.sync(ast3.Name(id=node.sym_name, ctx=node.py_ctx_func()))
2396
- if node.is_enum_singleton:
2397
- node.gen.py_ast.ctx = ast3.Store()
2398
- node.gen.py_ast = self.sync(
2399
- ast3.Assign(
2400
- targets=[node.gen.py_ast],
2401
- value=self.sync(
2402
- ast3.Call(
2403
- func=self.sync(
2404
- ast3.Name(id="__jac_auto__", ctx=ast3.Load())
2405
- ),
2406
- args=[],
2407
- keywords=[],
2408
- )
2409
- ),
2764
+ node.gen.py_ast = [
2765
+ self.sync(ast3.Name(id=node.sym_name, ctx=node.py_ctx_func()))
2766
+ ]
2767
+ if node.is_enum_singleton and isinstance(node.gen.py_ast[0], ast3.Name):
2768
+ node.gen.py_ast[0].ctx = ast3.Store()
2769
+ node.gen.py_ast = [
2770
+ self.sync(
2771
+ ast3.Assign(
2772
+ targets=node.gen.py_ast,
2773
+ value=self.sync(
2774
+ ast3.Call(
2775
+ func=self.sync(
2776
+ ast3.Name(id="__jac_auto__", ctx=ast3.Load())
2777
+ ),
2778
+ args=[],
2779
+ keywords=[],
2780
+ )
2781
+ ),
2782
+ )
2410
2783
  )
2411
- )
2784
+ ]
2412
2785
 
2413
2786
  def exit_float(self, node: ast.Float) -> None:
2414
2787
  """Sub objects.
@@ -2421,7 +2794,7 @@ class PyastGenPass(Pass):
2421
2794
  pos_start: int,
2422
2795
  pos_end: int,
2423
2796
  """
2424
- node.gen.py_ast = self.sync(ast3.Constant(value=float(node.value)))
2797
+ node.gen.py_ast = [self.sync(ast3.Constant(value=float(node.value)))]
2425
2798
 
2426
2799
  def exit_int(self, node: ast.Int) -> None:
2427
2800
  """Sub objects.
@@ -2434,7 +2807,7 @@ class PyastGenPass(Pass):
2434
2807
  pos_start: int,
2435
2808
  pos_end: int,
2436
2809
  """
2437
- node.gen.py_ast = self.sync(ast3.Constant(value=int(node.value)))
2810
+ node.gen.py_ast = [self.sync(ast3.Constant(value=int(node.value)))]
2438
2811
 
2439
2812
  def exit_string(self, node: ast.String) -> None:
2440
2813
  """Sub objects.
@@ -2447,7 +2820,7 @@ class PyastGenPass(Pass):
2447
2820
  pos_start: int,
2448
2821
  pos_end: int,
2449
2822
  """
2450
- node.gen.py_ast = self.sync(ast3.Constant(value=node.lit_value))
2823
+ node.gen.py_ast = [self.sync(ast3.Constant(value=node.lit_value))]
2451
2824
 
2452
2825
  def exit_bool(self, node: ast.Bool) -> None:
2453
2826
  """Sub objects.
@@ -2460,7 +2833,7 @@ class PyastGenPass(Pass):
2460
2833
  pos_start: int,
2461
2834
  pos_end: int,
2462
2835
  """
2463
- node.gen.py_ast = self.sync(ast3.Constant(value=node.value == "True"))
2836
+ node.gen.py_ast = [self.sync(ast3.Constant(value=node.value == "True"))]
2464
2837
 
2465
2838
  def exit_builtin_type(self, node: ast.BuiltinType) -> None:
2466
2839
  """Sub objects.
@@ -2473,7 +2846,9 @@ class PyastGenPass(Pass):
2473
2846
  pos_start: int,
2474
2847
  pos_end: int,
2475
2848
  """
2476
- node.gen.py_ast = self.sync(ast3.Name(id=node.sym_name, ctx=node.py_ctx_func()))
2849
+ node.gen.py_ast = [
2850
+ self.sync(ast3.Name(id=node.sym_name, ctx=node.py_ctx_func()))
2851
+ ]
2477
2852
 
2478
2853
  def exit_null(self, node: ast.Null) -> None:
2479
2854
  """Sub objects.
@@ -2486,7 +2861,7 @@ class PyastGenPass(Pass):
2486
2861
  pos_start: int,
2487
2862
  pos_end: int,
2488
2863
  """
2489
- node.gen.py_ast = self.sync(ast3.Constant(value=None))
2864
+ node.gen.py_ast = [self.sync(ast3.Constant(value=None))]
2490
2865
 
2491
2866
  def exit_semi(self, node: ast.Semi) -> None:
2492
2867
  """Sub objects.