jaclang 0.8.0__py3-none-any.whl → 0.8.2__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 (124) hide show
  1. jaclang/__init__.py +6 -0
  2. jaclang/cli/cli.py +23 -50
  3. jaclang/compiler/codeinfo.py +0 -1
  4. jaclang/compiler/jac.lark +14 -22
  5. jaclang/compiler/larkparse/jac_parser.py +2 -2
  6. jaclang/compiler/parser.py +378 -531
  7. jaclang/compiler/passes/main/__init__.py +0 -14
  8. jaclang/compiler/passes/main/annex_pass.py +2 -8
  9. jaclang/compiler/passes/main/cfg_build_pass.py +39 -13
  10. jaclang/compiler/passes/main/def_impl_match_pass.py +14 -13
  11. jaclang/compiler/passes/main/def_use_pass.py +4 -7
  12. jaclang/compiler/passes/main/import_pass.py +6 -14
  13. jaclang/compiler/passes/main/inheritance_pass.py +2 -2
  14. jaclang/compiler/passes/main/pyast_gen_pass.py +428 -799
  15. jaclang/compiler/passes/main/pyast_load_pass.py +115 -311
  16. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +8 -7
  17. jaclang/compiler/passes/main/sym_tab_build_pass.py +3 -3
  18. jaclang/compiler/passes/main/sym_tab_link_pass.py +6 -9
  19. jaclang/compiler/passes/main/tests/fixtures/symtab_link_tests/action/actions.jac +1 -5
  20. jaclang/compiler/passes/main/tests/fixtures/symtab_link_tests/main.jac +1 -8
  21. jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +5 -9
  22. jaclang/compiler/passes/main/tests/test_decl_impl_match_pass.py +7 -8
  23. jaclang/compiler/passes/main/tests/test_import_pass.py +5 -18
  24. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -6
  25. jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -3
  26. jaclang/compiler/passes/main/tests/test_sym_tab_link_pass.py +20 -17
  27. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +425 -216
  28. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -0
  29. jaclang/compiler/passes/tool/tests/fixtures/archetype_frmt.jac +14 -0
  30. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +5 -4
  31. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +6 -0
  32. jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +3 -3
  33. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +9 -0
  34. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +18 -3
  35. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +2 -2
  36. jaclang/compiler/program.py +22 -66
  37. jaclang/compiler/tests/fixtures/fam.jac +2 -2
  38. jaclang/compiler/tests/fixtures/pkg_import_lib/__init__.jac +1 -0
  39. jaclang/compiler/tests/fixtures/pkg_import_lib/sub/__init__.jac +1 -0
  40. jaclang/compiler/tests/fixtures/pkg_import_lib/sub/helper.jac +3 -0
  41. jaclang/compiler/tests/fixtures/pkg_import_lib/tools.jac +3 -0
  42. jaclang/compiler/tests/fixtures/pkg_import_lib_py/__init__.py +5 -0
  43. jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/__init__.py +3 -0
  44. jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/helper.jac +3 -0
  45. jaclang/compiler/tests/fixtures/pkg_import_lib_py/tools.jac +3 -0
  46. jaclang/compiler/tests/fixtures/pkg_import_main.jac +10 -0
  47. jaclang/compiler/tests/fixtures/pkg_import_main_py.jac +11 -0
  48. jaclang/compiler/tests/test_importer.py +30 -13
  49. jaclang/compiler/tests/test_parser.py +1 -0
  50. jaclang/compiler/unitree.py +488 -320
  51. jaclang/langserve/__init__.jac +1 -0
  52. jaclang/langserve/engine.jac +503 -0
  53. jaclang/langserve/sem_manager.jac +309 -0
  54. jaclang/langserve/server.jac +201 -0
  55. jaclang/langserve/tests/server_test/test_lang_serve.py +139 -48
  56. jaclang/langserve/tests/server_test/utils.py +35 -6
  57. jaclang/langserve/tests/session.jac +294 -0
  58. jaclang/langserve/tests/test_sem_tokens.py +2 -2
  59. jaclang/langserve/tests/test_server.py +8 -7
  60. jaclang/langserve/utils.jac +51 -30
  61. jaclang/runtimelib/archetype.py +128 -6
  62. jaclang/runtimelib/builtin.py +17 -14
  63. jaclang/runtimelib/importer.py +51 -76
  64. jaclang/runtimelib/machine.py +469 -305
  65. jaclang/runtimelib/meta_importer.py +86 -0
  66. jaclang/runtimelib/tests/fixtures/graph_purger.jac +24 -26
  67. jaclang/runtimelib/tests/fixtures/other_root_access.jac +25 -16
  68. jaclang/runtimelib/tests/fixtures/traversing_save.jac +7 -5
  69. jaclang/runtimelib/tests/test_jaseci.py +3 -1
  70. jaclang/runtimelib/utils.py +3 -3
  71. jaclang/tests/fixtures/arch_rel_import_creation.jac +23 -23
  72. jaclang/tests/fixtures/async_ability.jac +43 -10
  73. jaclang/tests/fixtures/async_function.jac +18 -0
  74. jaclang/tests/fixtures/async_walker.jac +17 -12
  75. jaclang/tests/fixtures/backward_edge_visit.jac +31 -0
  76. jaclang/tests/fixtures/builtin_printgraph.jac +85 -0
  77. jaclang/tests/fixtures/builtin_printgraph_json.jac +21 -0
  78. jaclang/tests/fixtures/builtin_printgraph_mermaid.jac +16 -0
  79. jaclang/tests/fixtures/chandra_bugs2.jac +20 -13
  80. jaclang/tests/fixtures/concurrency.jac +1 -1
  81. jaclang/tests/fixtures/create_dynamic_archetype.jac +25 -28
  82. jaclang/tests/fixtures/deep/deeper/deep_outer_import.jac +7 -4
  83. jaclang/tests/fixtures/deep/deeper/snd_lev.jac +2 -2
  84. jaclang/tests/fixtures/deep/deeper/snd_lev_dup.jac +6 -0
  85. jaclang/tests/fixtures/deep/one_lev.jac +2 -2
  86. jaclang/tests/fixtures/deep/one_lev_dup.jac +4 -3
  87. jaclang/tests/fixtures/dynamic_archetype.jac +19 -12
  88. jaclang/tests/fixtures/edge_ability.jac +49 -0
  89. jaclang/tests/fixtures/foo.jac +14 -22
  90. jaclang/tests/fixtures/guess_game.jac +1 -1
  91. jaclang/tests/fixtures/here_usage_error.jac +21 -0
  92. jaclang/tests/fixtures/here_visitor_usage.jac +21 -0
  93. jaclang/tests/fixtures/jac_from_py.py +1 -1
  94. jaclang/tests/fixtures/jp_importer.jac +6 -6
  95. jaclang/tests/fixtures/jp_importer_auto.jac +5 -3
  96. jaclang/tests/fixtures/node_del.jac +30 -36
  97. jaclang/tests/fixtures/unicode_strings.jac +24 -0
  98. jaclang/tests/fixtures/visit_traversal.jac +47 -0
  99. jaclang/tests/fixtures/walker_update.jac +5 -7
  100. jaclang/tests/test_cli.py +12 -7
  101. jaclang/tests/test_language.py +218 -145
  102. jaclang/tests/test_reference.py +9 -4
  103. jaclang/tests/test_typecheck.py +13 -26
  104. jaclang/utils/helpers.py +14 -6
  105. jaclang/utils/lang_tools.py +9 -8
  106. jaclang/utils/module_resolver.py +23 -0
  107. jaclang/utils/tests/test_lang_tools.py +2 -1
  108. jaclang/utils/treeprinter.py +3 -4
  109. {jaclang-0.8.0.dist-info → jaclang-0.8.2.dist-info}/METADATA +4 -3
  110. {jaclang-0.8.0.dist-info → jaclang-0.8.2.dist-info}/RECORD +112 -94
  111. {jaclang-0.8.0.dist-info → jaclang-0.8.2.dist-info}/WHEEL +1 -1
  112. jaclang/compiler/passes/main/tests/fixtures/main_err.jac +0 -6
  113. jaclang/compiler/passes/main/tests/fixtures/second_err.jac +0 -4
  114. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +0 -644
  115. jaclang/compiler/passes/tool/tests/test_doc_ir_gen_pass.py +0 -29
  116. jaclang/langserve/__init__.py +0 -1
  117. jaclang/langserve/engine.py +0 -553
  118. jaclang/langserve/sem_manager.py +0 -383
  119. jaclang/langserve/server.py +0 -167
  120. jaclang/langserve/tests/session.py +0 -255
  121. jaclang/tests/fixtures/builtin_dotgen.jac +0 -42
  122. jaclang/tests/fixtures/builtin_dotgen_json.jac +0 -21
  123. jaclang/tests/fixtures/deep/deeper/__init__.jac +0 -1
  124. {jaclang-0.8.0.dist-info → jaclang-0.8.2.dist-info}/entry_points.txt +0 -0
@@ -32,10 +32,10 @@ from jaclang.compiler.constant import (
32
32
  from jaclang.compiler.constant import DELIM_MAP, SymbolAccess, Tokens as Tok
33
33
  from jaclang.utils import resolve_relative_path
34
34
  from jaclang.utils.treeprinter import (
35
- dotgen_ast_tree,
36
- dotgen_symtab_tree,
37
35
  print_ast_tree,
38
36
  print_symtab_tree,
37
+ printgraph_ast_tree,
38
+ printgraph_symtab_tree,
39
39
  )
40
40
 
41
41
 
@@ -203,9 +203,9 @@ class UniNode:
203
203
  """Print ast."""
204
204
  return print_ast_tree(self, max_depth=depth)
205
205
 
206
- def dotgen(self) -> str:
206
+ def printgraph(self) -> str:
207
207
  """Print ast."""
208
- return dotgen_ast_tree(self)
208
+ return printgraph_ast_tree(self)
209
209
 
210
210
  def flatten(self) -> list[UniNode]:
211
211
  """Flatten ast."""
@@ -471,7 +471,7 @@ class UniScopeNode(UniNode):
471
471
  if isinstance(item.operand, AstSymbolNode):
472
472
  item.operand.name_spec.py_ctx_func = ast3.Store
473
473
  elif isinstance(item, (TupleVal, ListVal)):
474
- for i in item.values.items if item.values else []:
474
+ for i in item.values:
475
475
  if isinstance(i, AstSymbolNode):
476
476
  i.name_spec.py_ctx_func = ast3.Store
477
477
  elif isinstance(i, AtomTrailer):
@@ -484,7 +484,7 @@ class UniScopeNode(UniNode):
484
484
  def inherit_baseclasses_sym(self, node: Archetype | Enum) -> None:
485
485
  """Inherit base classes symbol tables."""
486
486
  if node.base_classes:
487
- for base_cls in node.base_classes.items:
487
+ for base_cls in node.base_classes:
488
488
  if (
489
489
  isinstance(base_cls, AstSymbolNode)
490
490
  and (found := self.use_lookup(base_cls))
@@ -501,9 +501,9 @@ class UniScopeNode(UniNode):
501
501
  """Pretty print."""
502
502
  return print_symtab_tree(root=self, depth=depth)
503
503
 
504
- def sym_dotgen(self) -> str:
504
+ def sym_printgraph(self) -> str:
505
505
  """Generate dot graph for sym table."""
506
- return dotgen_symtab_tree(self)
506
+ return printgraph_symtab_tree(self)
507
507
 
508
508
  def __repr__(self) -> str:
509
509
  """Repr."""
@@ -747,6 +747,9 @@ class ArchBlockStmt(UniNode):
747
747
  class EnumBlockStmt(UniNode):
748
748
  """EnumBlockStmt node type for Jac Ast."""
749
749
 
750
+ def __init__(self, is_enum_stmt: bool) -> None:
751
+ self.is_enum_stmt = is_enum_stmt
752
+
750
753
 
751
754
  class CodeBlockStmt(UniCFGNode):
752
755
  """CodeBlockStmt node type for Jac Ast."""
@@ -770,13 +773,14 @@ class AstImplNeedingNode(AstSymbolNode, Generic[T]):
770
773
  class NameAtom(AtomExpr, EnumBlockStmt):
771
774
  """NameAtom node type for Jac Ast."""
772
775
 
773
- def __init__(self) -> None:
776
+ def __init__(self, is_enum_stmt: bool) -> None:
774
777
  self.name_of: AstSymbolNode = self
775
778
  self._sym: Optional[Symbol] = None
776
779
  self._sym_name: str = ""
777
780
  self._sym_category: SymbolType = SymbolType.UNKNOWN
778
781
  self._py_ctx_func: Type[ast3.expr_context] = ast3.Load
779
782
  AtomExpr.__init__(self)
783
+ EnumBlockStmt.__init__(self, is_enum_stmt=is_enum_stmt)
780
784
 
781
785
  @property
782
786
  def sym(self) -> Optional[Symbol]:
@@ -845,15 +849,15 @@ class NameAtom(AtomExpr, EnumBlockStmt):
845
849
  return None
846
850
 
847
851
 
848
- class ArchSpec(ElementStmt, CodeBlockStmt, AstSymbolNode, AstDocNode):
852
+ class ArchSpec(ElementStmt, CodeBlockStmt, AstSymbolNode, AstAsyncNode, AstDocNode):
849
853
  """ArchSpec node type for Jac Ast."""
850
854
 
851
855
  def __init__(
852
- self, decorators: Optional[SubNodeList[Expr]] = None, is_async: bool = False
856
+ self, decorators: Sequence[Expr] | None, is_async: bool = False
853
857
  ) -> None:
854
858
  self.decorators = decorators
855
- self.is_async = is_async
856
859
  CodeBlockStmt.__init__(self)
860
+ AstAsyncNode.__init__(self, is_async=is_async)
857
861
 
858
862
 
859
863
  class MatchPattern(UniNode):
@@ -877,47 +881,6 @@ class SubTag(UniNode, Generic[T]):
877
881
  return res
878
882
 
879
883
 
880
- # SubNodeList were created to simplify the type safety of the
881
- # parser's implementation. We basically need to maintain tokens
882
- # of mixed type in the kid list of the subnodelist as well as
883
- # separating out typed items of interest in the ast node class body.
884
- class SubNodeList(UniNode, Generic[T]):
885
- """SubNodeList node type for Jac Ast."""
886
-
887
- def __init__(
888
- self,
889
- items: list[T],
890
- delim: Optional[Tok],
891
- kid: Sequence[UniNode],
892
- left_enc: Optional[Token] = None,
893
- right_enc: Optional[Token] = None,
894
- ) -> None:
895
- self.items: list[T] = items
896
- self.delim = delim
897
- self.left_enc = left_enc
898
- self.right_enc = right_enc
899
- UniNode.__init__(self, kid=kid)
900
-
901
- def normalize(self, deep: bool = False) -> bool:
902
- res = True
903
- if deep:
904
- for i in self.items:
905
- res = res and i.normalize()
906
- new_kid: list[UniNode] = []
907
- if self.left_enc:
908
- new_kid.append(self.left_enc)
909
- for i in self.items:
910
- new_kid.append(i)
911
- if self.delim:
912
- new_kid.append(self.gen_token(self.delim))
913
- if self.delim and self.items:
914
- new_kid.pop()
915
- if self.right_enc:
916
- new_kid.append(self.right_enc)
917
- self.set_kids(nodes=new_kid if len(new_kid) else [EmptyToken()])
918
- return res
919
-
920
-
921
884
  # AST Mid Level Node Types
922
885
  # --------------------------
923
886
  class Module(AstDocNode, UniScopeNode):
@@ -1053,7 +1016,7 @@ class GlobalVars(ElementStmt, AstAccessNode):
1053
1016
  def __init__(
1054
1017
  self,
1055
1018
  access: Optional[SubTag[Token]],
1056
- assignments: SubNodeList[Assignment],
1019
+ assignments: Sequence[Assignment],
1057
1020
  is_frozen: bool,
1058
1021
  kid: Sequence[UniNode],
1059
1022
  doc: Optional[String] = None,
@@ -1068,7 +1031,8 @@ class GlobalVars(ElementStmt, AstAccessNode):
1068
1031
  res = True
1069
1032
  if deep:
1070
1033
  res = self.access.normalize(deep) if self.access else True
1071
- res = res and self.assignments.normalize(deep)
1034
+ for assign in self.assignments:
1035
+ res = res and assign.normalize(deep)
1072
1036
  res = res and self.doc.normalize(deep) if self.doc else res
1073
1037
  new_kid: list[UniNode] = []
1074
1038
  if self.doc:
@@ -1079,7 +1043,10 @@ class GlobalVars(ElementStmt, AstAccessNode):
1079
1043
  new_kid.append(self.gen_token(Tok.KW_GLOBAL))
1080
1044
  if self.access:
1081
1045
  new_kid.append(self.access)
1082
- new_kid.append(self.assignments)
1046
+ for i, assign in enumerate(self.assignments):
1047
+ new_kid.append(assign)
1048
+ if i < len(self.assignments) - 1:
1049
+ new_kid.append(self.gen_token(Tok.COMMA))
1083
1050
  self.set_kids(nodes=new_kid)
1084
1051
  return res
1085
1052
 
@@ -1092,7 +1059,7 @@ class Test(AstSymbolNode, ElementStmt, UniScopeNode):
1092
1059
  def __init__(
1093
1060
  self,
1094
1061
  name: Name | Token,
1095
- body: SubNodeList[CodeBlockStmt],
1062
+ body: Sequence[CodeBlockStmt],
1096
1063
  kid: Sequence[UniNode],
1097
1064
  doc: Optional[String] = None,
1098
1065
  ) -> None:
@@ -1118,7 +1085,7 @@ class Test(AstSymbolNode, ElementStmt, UniScopeNode):
1118
1085
  if not self.name.value.startswith("test_")
1119
1086
  else self.name.value
1120
1087
  )
1121
- self.body = body
1088
+ self.body: list[CodeBlockStmt] = list(body)
1122
1089
  UniNode.__init__(self, kid=kid)
1123
1090
  if self.name not in self.kid:
1124
1091
  self.insert_kids_at_pos([self.name], pos=1, pos_update=False)
@@ -1135,14 +1102,18 @@ class Test(AstSymbolNode, ElementStmt, UniScopeNode):
1135
1102
  res = True
1136
1103
  if deep:
1137
1104
  res = self.name.normalize(deep)
1138
- res = res and self.body.normalize(deep)
1105
+ for stmt in self.body:
1106
+ res = res and stmt.normalize(deep)
1139
1107
  res = res and self.doc.normalize(deep) if self.doc else res
1140
1108
  new_kid: list[UniNode] = []
1141
1109
  if self.doc:
1142
1110
  new_kid.append(self.doc)
1143
1111
  new_kid.append(self.gen_token(Tok.KW_TEST))
1144
1112
  new_kid.append(self.name)
1145
- new_kid.append(self.body)
1113
+ new_kid.append(self.gen_token(Tok.LBRACE))
1114
+ for stmt in self.body:
1115
+ new_kid.append(stmt)
1116
+ new_kid.append(self.gen_token(Tok.RBRACE))
1146
1117
  self.set_kids(nodes=new_kid)
1147
1118
  return res
1148
1119
 
@@ -1153,20 +1124,23 @@ class ModuleCode(ElementStmt, ArchBlockStmt, EnumBlockStmt):
1153
1124
  def __init__(
1154
1125
  self,
1155
1126
  name: Optional[Name],
1156
- body: SubNodeList[CodeBlockStmt],
1127
+ body: Sequence[CodeBlockStmt],
1157
1128
  kid: Sequence[UniNode],
1129
+ is_enum_stmt: bool = False,
1158
1130
  doc: Optional[String] = None,
1159
1131
  ) -> None:
1160
1132
  self.name = name
1161
1133
  self.body = body
1162
1134
  UniNode.__init__(self, kid=kid)
1163
1135
  AstDocNode.__init__(self, doc=doc)
1136
+ EnumBlockStmt.__init__(self, is_enum_stmt=is_enum_stmt)
1164
1137
 
1165
1138
  def normalize(self, deep: bool = False) -> bool:
1166
1139
  res = True
1167
1140
  if deep:
1168
1141
  res = self.name.normalize(deep) if self.name else res
1169
- res = res and self.body.normalize(deep)
1142
+ for stmt in self.body:
1143
+ res = res and stmt.normalize(deep)
1170
1144
  res = res and self.doc.normalize(deep) if self.doc else res
1171
1145
  new_kid: list[UniNode] = []
1172
1146
  if self.doc:
@@ -1176,7 +1150,10 @@ class ModuleCode(ElementStmt, ArchBlockStmt, EnumBlockStmt):
1176
1150
  if self.name:
1177
1151
  new_kid.append(self.gen_token(Tok.COLON))
1178
1152
  new_kid.append(self.name)
1179
- new_kid.append(self.body)
1153
+ new_kid.append(self.gen_token(Tok.LBRACE))
1154
+ for stmt in self.body:
1155
+ new_kid.append(stmt)
1156
+ new_kid.append(self.gen_token(Tok.RBRACE))
1180
1157
  self.set_kids(nodes=new_kid)
1181
1158
  return res
1182
1159
 
@@ -1188,12 +1165,14 @@ class PyInlineCode(ElementStmt, ArchBlockStmt, EnumBlockStmt, CodeBlockStmt):
1188
1165
  self,
1189
1166
  code: Token,
1190
1167
  kid: Sequence[UniNode],
1168
+ is_enum_stmt: bool = False,
1191
1169
  doc: Optional[String] = None,
1192
1170
  ) -> None:
1193
1171
  self.code = code
1194
1172
  UniNode.__init__(self, kid=kid)
1195
1173
  AstDocNode.__init__(self, doc=doc)
1196
1174
  CodeBlockStmt.__init__(self)
1175
+ EnumBlockStmt.__init__(self, is_enum_stmt=is_enum_stmt)
1197
1176
 
1198
1177
  def normalize(self, deep: bool = False) -> bool:
1199
1178
  res = True
@@ -1214,7 +1193,7 @@ class Import(ElementStmt, CodeBlockStmt):
1214
1193
  def __init__(
1215
1194
  self,
1216
1195
  from_loc: Optional[ModulePath],
1217
- items: SubNodeList[ModuleItem] | SubNodeList[ModulePath],
1196
+ items: Sequence[ModuleItem] | Sequence[ModulePath],
1218
1197
  is_absorb: bool, # For includes
1219
1198
  kid: Sequence[UniNode],
1220
1199
  doc: Optional[String] = None,
@@ -1256,7 +1235,7 @@ class Import(ElementStmt, CodeBlockStmt):
1256
1235
  os.path.join(self.from_loc.resolve_relative_path(), "__init__.jac")
1257
1236
  ):
1258
1237
  return True
1259
- for i in self.items.items:
1238
+ for i in self.items:
1260
1239
  if isinstance(
1261
1240
  i, ModuleItem
1262
1241
  ) and self.from_loc.resolve_relative_path(i.name.value).endswith(
@@ -1265,7 +1244,7 @@ class Import(ElementStmt, CodeBlockStmt):
1265
1244
  return True
1266
1245
  return any(
1267
1246
  isinstance(i, ModulePath) and i.resolve_relative_path().endswith(".jac")
1268
- for i in self.items.items
1247
+ for i in self.items
1269
1248
  )
1270
1249
 
1271
1250
  def normalize(self, deep: bool = False) -> bool:
@@ -1273,7 +1252,8 @@ class Import(ElementStmt, CodeBlockStmt):
1273
1252
  if deep:
1274
1253
  res = self.hint.normalize(deep) if self.hint else res
1275
1254
  res = res and self.from_loc.normalize(deep) if self.from_loc else res
1276
- res = res and self.items.normalize(deep)
1255
+ for item in self.items:
1256
+ res = res and item.normalize(deep)
1277
1257
  res = res and self.doc.normalize(deep) if self.doc else res
1278
1258
  new_kid: list[UniNode] = []
1279
1259
  if self.doc:
@@ -1286,7 +1266,10 @@ class Import(ElementStmt, CodeBlockStmt):
1286
1266
  new_kid.append(self.gen_token(Tok.KW_FROM))
1287
1267
  new_kid.append(self.from_loc)
1288
1268
  new_kid.append(self.gen_token(Tok.LBRACE))
1289
- new_kid.append(self.items)
1269
+ for idx, itm in enumerate(self.items):
1270
+ new_kid.append(itm)
1271
+ if idx < len(self.items) - 1:
1272
+ new_kid.append(self.gen_token(Tok.COMMA))
1290
1273
  if self.from_loc:
1291
1274
  new_kid.append(self.gen_token(Tok.RBRACE))
1292
1275
  else:
@@ -1300,7 +1283,7 @@ class ModulePath(AstSymbolNode):
1300
1283
 
1301
1284
  def __init__(
1302
1285
  self,
1303
- path: Optional[SubNodeList[Name]],
1286
+ path: Optional[Sequence[Name]],
1304
1287
  level: int,
1305
1288
  alias: Optional[Name],
1306
1289
  kid: Sequence[UniNode],
@@ -1310,7 +1293,7 @@ class ModulePath(AstSymbolNode):
1310
1293
  self.alias = alias
1311
1294
  self.abs_path: Optional[str] = None
1312
1295
 
1313
- name_spec = alias if alias else path.items[0] if path else None
1296
+ name_spec = alias if alias else path[0] if path else None
1314
1297
 
1315
1298
  UniNode.__init__(self, kid=kid)
1316
1299
  if not name_spec:
@@ -1333,21 +1316,24 @@ class ModulePath(AstSymbolNode):
1333
1316
  def dot_path_str(self) -> str:
1334
1317
  """Get path string."""
1335
1318
  return ("." * self.level) + ".".join(
1336
- [p.value for p in self.path.items]
1337
- if self.path
1338
- else [self.name_spec.sym_name]
1319
+ [p.value for p in self.path] if self.path else [self.name_spec.sym_name]
1339
1320
  )
1340
1321
 
1341
1322
  def normalize(self, deep: bool = False) -> bool:
1342
1323
  res = True
1343
1324
  if deep:
1344
- res = self.path.normalize(deep) if self.path else res
1325
+ if self.path:
1326
+ for item in self.path:
1327
+ res = res and item.normalize(deep)
1345
1328
  res = res and self.alias.normalize(deep) if self.alias else res
1346
1329
  new_kid: list[UniNode] = []
1347
1330
  for _ in range(self.level):
1348
1331
  new_kid.append(self.gen_token(Tok.DOT))
1349
1332
  if self.path:
1350
- new_kid.append(self.path)
1333
+ for idx, item in enumerate(self.path):
1334
+ new_kid.append(item)
1335
+ if idx < len(self.path) - 1:
1336
+ new_kid.append(self.gen_token(Tok.DOT))
1351
1337
  if self.alias:
1352
1338
  new_kid.append(self.gen_token(Tok.KW_AS))
1353
1339
  new_kid.append(self.alias)
@@ -1426,15 +1412,15 @@ class Archetype(
1426
1412
  name: Name,
1427
1413
  arch_type: Token,
1428
1414
  access: Optional[SubTag[Token]],
1429
- base_classes: Optional[SubNodeList[Expr]],
1430
- body: Optional[SubNodeList[ArchBlockStmt] | ImplDef],
1415
+ base_classes: Sequence[Expr] | None,
1416
+ body: Sequence[ArchBlockStmt] | ImplDef | None,
1431
1417
  kid: Sequence[UniNode],
1432
1418
  doc: Optional[String] = None,
1433
- decorators: Optional[SubNodeList[Expr]] = None,
1419
+ decorators: Sequence[Expr] | None = None,
1434
1420
  ) -> None:
1435
1421
  self.name = name
1436
1422
  self.arch_type = arch_type
1437
- self.base_classes = base_classes
1423
+ self.base_classes: list[Expr] = list(base_classes) if base_classes else []
1438
1424
  UniNode.__init__(self, kid=kid)
1439
1425
  AstSymbolNode.__init__(
1440
1426
  self,
@@ -1468,12 +1454,12 @@ class Archetype(
1468
1454
  @property
1469
1455
  def is_abstract(self) -> bool:
1470
1456
  body = (
1471
- self.body.items
1472
- if isinstance(self.body, SubNodeList)
1457
+ list(self.body)
1458
+ if isinstance(self.body, Sequence)
1473
1459
  else (
1474
- self.body.body.items
1460
+ list(self.body.body)
1475
1461
  if isinstance(self.body, ImplDef)
1476
- and isinstance(self.body.body, SubNodeList)
1462
+ and isinstance(self.body.body, Sequence)
1477
1463
  else []
1478
1464
  )
1479
1465
  )
@@ -1485,18 +1471,27 @@ class Archetype(
1485
1471
  res = self.name.normalize(deep)
1486
1472
  res = res and self.arch_type.normalize(deep)
1487
1473
  res = res and self.access.normalize(deep) if self.access else res
1488
- res = (
1489
- res and self.base_classes.normalize(deep) if self.base_classes else res
1490
- )
1491
- res = res and self.body.normalize(deep) if self.body else res
1474
+ for base in self.base_classes:
1475
+ res = res and base.normalize(deep)
1476
+ if isinstance(self.body, ImplDef):
1477
+ res = res and self.body.normalize(deep)
1478
+ elif isinstance(self.body, Sequence):
1479
+ for stmt in self.body:
1480
+ res = res and stmt.normalize(deep)
1481
+ else:
1482
+ res = res and self.body.normalize(deep) if self.body else res
1492
1483
  res = res and self.doc.normalize(deep) if self.doc else res
1493
- res = res and self.decorators.normalize(deep) if self.decorators else res
1484
+ for dec in self.decorators or []:
1485
+ res = res and dec.normalize(deep)
1494
1486
  new_kid: list[UniNode] = []
1495
1487
  if self.doc:
1496
1488
  new_kid.append(self.doc)
1497
1489
  if self.decorators:
1498
1490
  new_kid.append(self.gen_token(Tok.DECOR_OP))
1499
- new_kid.append(self.decorators)
1491
+ for idx, dec in enumerate(self.decorators):
1492
+ new_kid.append(dec)
1493
+ if idx < len(self.decorators) - 1:
1494
+ new_kid.append(self.gen_token(Tok.DECOR_OP))
1500
1495
  if self.is_async:
1501
1496
  new_kid.append(self.gen_token(Tok.KW_ASYNC))
1502
1497
  new_kid.append(self.arch_type)
@@ -1505,13 +1500,19 @@ class Archetype(
1505
1500
  new_kid.append(self.name)
1506
1501
  if self.base_classes:
1507
1502
  new_kid.append(self.gen_token(Tok.LPAREN))
1508
- new_kid.append(self.base_classes)
1503
+ for idx, base in enumerate(self.base_classes):
1504
+ new_kid.append(base)
1505
+ if idx < len(self.base_classes) - 1:
1506
+ new_kid.append(self.gen_token(Tok.COMMA))
1509
1507
  new_kid.append(self.gen_token(Tok.RPAREN))
1510
1508
  if self.body:
1511
1509
  if isinstance(self.body, ImplDef):
1512
1510
  new_kid.append(self.gen_token(Tok.SEMI))
1513
1511
  else:
1514
- new_kid.append(self.body)
1512
+ new_kid.append(self.gen_token(Tok.LBRACE))
1513
+ for stmt in self.body:
1514
+ new_kid.append(stmt)
1515
+ new_kid.append(self.gen_token(Tok.RBRACE))
1515
1516
  else:
1516
1517
  new_kid.append(self.gen_token(Tok.SEMI))
1517
1518
  self.set_kids(nodes=new_kid)
@@ -1523,24 +1524,24 @@ class ImplDef(CodeBlockStmt, ElementStmt, ArchBlockStmt, AstSymbolNode, UniScope
1523
1524
 
1524
1525
  def __init__(
1525
1526
  self,
1526
- decorators: Optional[SubNodeList[Expr]],
1527
- target: SubNodeList[NameAtom],
1528
- spec: SubNodeList[Expr] | FuncSignature | EventSignature | None,
1529
- body: SubNodeList[CodeBlockStmt] | FuncCall,
1527
+ decorators: Optional[Sequence[Expr]],
1528
+ target: Sequence[NameAtom],
1529
+ spec: Sequence[Expr] | FuncSignature | EventSignature | None,
1530
+ body: Sequence[CodeBlockStmt] | Sequence[EnumBlockStmt] | FuncCall,
1530
1531
  kid: Sequence[UniNode],
1531
1532
  doc: Optional[String] = None,
1532
1533
  decl_link: Optional[UniNode] = None,
1533
1534
  ) -> None:
1534
1535
  self.decorators = decorators
1535
1536
  self.target = target
1536
- self.spec = spec
1537
+ self.spec = list(spec) if isinstance(spec, Sequence) else spec
1537
1538
  self.body = body
1538
1539
  self.doc = doc
1539
1540
  self.decl_link = decl_link
1540
1541
  UniNode.__init__(self, kid=kid)
1541
1542
  AstSymbolNode.__init__(
1542
1543
  self,
1543
- sym_name="impl." + ".".join([x.sym_name for x in self.target.items]),
1544
+ sym_name="impl." + ".".join([x.sym_name for x in self.target]),
1544
1545
  name_spec=self.create_impl_name_node(),
1545
1546
  sym_category=SymbolType.IMPL,
1546
1547
  )
@@ -1549,15 +1550,15 @@ class ImplDef(CodeBlockStmt, ElementStmt, ArchBlockStmt, AstSymbolNode, UniScope
1549
1550
 
1550
1551
  def create_impl_name_node(self) -> Name:
1551
1552
  ret = Name(
1552
- orig_src=self.target.items[-1].loc.orig_src,
1553
+ orig_src=self.target[-1].loc.orig_src,
1553
1554
  name=Tok.NAME.value,
1554
- value="impl." + ".".join([x.sym_name for x in self.target.items]),
1555
- col_start=self.target.items[0].loc.col_start,
1556
- col_end=self.target.items[-1].loc.col_end,
1557
- line=self.target.items[0].loc.first_line,
1558
- end_line=self.target.items[-1].loc.last_line,
1559
- pos_start=self.target.items[0].loc.pos_start,
1560
- pos_end=self.target.items[-1].loc.pos_end,
1555
+ value="impl." + ".".join([x.sym_name for x in self.target]),
1556
+ col_start=self.target[0].loc.col_start,
1557
+ col_end=self.target[-1].loc.col_end,
1558
+ line=self.target[0].loc.first_line,
1559
+ end_line=self.target[-1].loc.last_line,
1560
+ pos_start=self.target[0].loc.pos_start,
1561
+ pos_end=self.target[-1].loc.pos_end,
1561
1562
  )
1562
1563
  ret.parent = self
1563
1564
  return ret
@@ -1565,22 +1566,57 @@ class ImplDef(CodeBlockStmt, ElementStmt, ArchBlockStmt, AstSymbolNode, UniScope
1565
1566
  def normalize(self, deep: bool = False) -> bool:
1566
1567
  res = True
1567
1568
  if deep:
1568
- res = self.target.normalize(deep)
1569
- res = res and self.spec.normalize(deep) if self.spec else res
1570
- res = res and self.body.normalize(deep)
1569
+ for item in self.target:
1570
+ res = res and item.normalize(deep)
1571
+ if isinstance(self.spec, Sequence):
1572
+ for sp in self.spec:
1573
+ res = res and sp.normalize(deep)
1574
+ else:
1575
+ res = res and self.spec.normalize(deep) if self.spec else res
1576
+ if isinstance(self.body, FuncCall):
1577
+ res = res and self.body.normalize(deep)
1578
+ else:
1579
+ for stmt in self.body:
1580
+ res = res and stmt.normalize(deep)
1571
1581
  res = res and self.doc.normalize(deep) if self.doc else res
1572
- res = res and self.decorators.normalize(deep) if self.decorators else res
1582
+ if self.decorators:
1583
+ for dec in self.decorators:
1584
+ res = res and dec.normalize(deep)
1573
1585
  new_kid: list[UniNode] = []
1574
1586
  if self.doc:
1575
1587
  new_kid.append(self.doc)
1576
1588
  if self.decorators:
1577
1589
  new_kid.append(self.gen_token(Tok.DECOR_OP))
1578
- new_kid.append(self.decorators)
1590
+ for i, dec in enumerate(self.decorators):
1591
+ new_kid.append(dec)
1592
+ if i < len(self.decorators) - 1:
1593
+ new_kid.append(self.gen_token(Tok.DECOR_OP))
1579
1594
  new_kid.append(self.gen_token(Tok.KW_IMPL))
1580
- new_kid.append(self.target)
1595
+ for idx, item in enumerate(self.target):
1596
+ new_kid.append(item)
1597
+ if idx < len(self.target) - 1:
1598
+ new_kid.append(self.gen_token(Tok.DOT))
1581
1599
  if self.spec:
1582
- new_kid.append(self.spec)
1583
- new_kid.append(self.body)
1600
+ if isinstance(self.spec, Sequence):
1601
+ new_kid.append(self.gen_token(Tok.LPAREN))
1602
+ for idx, sp in enumerate(self.spec):
1603
+ new_kid.append(sp)
1604
+ if idx < len(self.spec) - 1:
1605
+ new_kid.append(self.gen_token(Tok.COMMA))
1606
+ new_kid.append(self.gen_token(Tok.RPAREN))
1607
+ else:
1608
+ new_kid.append(self.spec)
1609
+ if isinstance(self.body, FuncCall):
1610
+ new_kid.append(self.body)
1611
+ else:
1612
+ new_kid.append(self.gen_token(Tok.LBRACE))
1613
+ prev_stmt = None
1614
+ for stmt in self.body:
1615
+ if isinstance(prev_stmt, EnumBlockStmt) and prev_stmt.is_enum_stmt:
1616
+ new_kid.append(self.gen_token(Tok.COMMA))
1617
+ new_kid.append(stmt)
1618
+ prev_stmt = stmt
1619
+ new_kid.append(self.gen_token(Tok.RBRACE))
1584
1620
  self.set_kids(nodes=new_kid)
1585
1621
  return res
1586
1622
 
@@ -1592,14 +1628,14 @@ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt, UniScopeN
1592
1628
  self,
1593
1629
  name: Name,
1594
1630
  access: Optional[SubTag[Token]],
1595
- base_classes: Optional[SubNodeList[Expr]],
1596
- body: Optional[SubNodeList[Assignment] | ImplDef],
1631
+ base_classes: Sequence[Expr] | None,
1632
+ body: Sequence[EnumBlockStmt] | ImplDef | None,
1597
1633
  kid: Sequence[UniNode],
1598
1634
  doc: Optional[String] = None,
1599
- decorators: Optional[SubNodeList[Expr]] = None,
1635
+ decorators: Sequence[Expr] | None = None,
1600
1636
  ) -> None:
1601
1637
  self.name = name
1602
- self.base_classes = base_classes
1638
+ self.base_classes: list[Expr] = list(base_classes) if base_classes else []
1603
1639
  UniNode.__init__(self, kid=kid)
1604
1640
  AstSymbolNode.__init__(
1605
1641
  self,
@@ -1618,16 +1654,25 @@ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt, UniScopeN
1618
1654
  if deep:
1619
1655
  res = self.name.normalize(deep)
1620
1656
  res = res and self.access.normalize(deep) if self.access else res
1621
- res = (
1622
- res and self.base_classes.normalize(deep) if self.base_classes else res
1623
- )
1624
- res = res and self.body.normalize(deep) if self.body else res
1657
+ for base in self.base_classes:
1658
+ res = res and base.normalize(deep)
1659
+ if isinstance(self.body, ImplDef):
1660
+ res = res and self.body.normalize(deep)
1661
+ elif isinstance(self.body, Sequence):
1662
+ for stmt in self.body:
1663
+ res = res and stmt.normalize(deep)
1664
+ else:
1665
+ res = res and self.body.normalize(deep) if self.body else res
1625
1666
  res = res and self.doc.normalize(deep) if self.doc else res
1626
- res = res and self.decorators.normalize(deep) if self.decorators else res
1667
+ for dec in self.decorators or []:
1668
+ res = res and dec.normalize(deep)
1627
1669
  new_kid: list[UniNode] = []
1628
1670
  if self.decorators:
1629
1671
  new_kid.append(self.gen_token(Tok.DECOR_OP))
1630
- new_kid.append(self.decorators)
1672
+ for idx, dec in enumerate(self.decorators):
1673
+ new_kid.append(dec)
1674
+ if idx < len(self.decorators) - 1:
1675
+ new_kid.append(self.gen_token(Tok.DECOR_OP))
1631
1676
  if self.doc:
1632
1677
  new_kid.append(self.doc)
1633
1678
  new_kid.append(self.gen_token(Tok.KW_ENUM))
@@ -1636,13 +1681,23 @@ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt, UniScopeN
1636
1681
  new_kid.append(self.name)
1637
1682
  if self.base_classes:
1638
1683
  new_kid.append(self.gen_token(Tok.COLON))
1639
- new_kid.append(self.base_classes)
1684
+ for idx, base in enumerate(self.base_classes):
1685
+ new_kid.append(base)
1686
+ if idx < len(self.base_classes) - 1:
1687
+ new_kid.append(self.gen_token(Tok.COMMA))
1640
1688
  new_kid.append(self.gen_token(Tok.COLON))
1641
1689
  if self.body:
1642
1690
  if isinstance(self.body, ImplDef):
1643
1691
  new_kid.append(self.gen_token(Tok.SEMI))
1644
1692
  else:
1645
- new_kid.append(self.body)
1693
+ new_kid.append(self.gen_token(Tok.LBRACE))
1694
+ prev_stmt = None
1695
+ for stmt in self.body:
1696
+ if isinstance(prev_stmt, EnumBlockStmt) and prev_stmt.is_enum_stmt:
1697
+ new_kid.append(self.gen_token(Tok.COMMA))
1698
+ new_kid.append(stmt)
1699
+ prev_stmt = stmt
1700
+ new_kid.append(self.gen_token(Tok.RBRACE))
1646
1701
  else:
1647
1702
  new_kid.append(self.gen_token(Tok.SEMI))
1648
1703
  self.set_kids(nodes=new_kid)
@@ -1669,10 +1724,10 @@ class Ability(
1669
1724
  is_abstract: bool,
1670
1725
  access: Optional[SubTag[Token]],
1671
1726
  signature: FuncSignature | EventSignature | None,
1672
- body: Optional[SubNodeList[CodeBlockStmt] | ImplDef | FuncCall],
1727
+ body: Sequence[CodeBlockStmt] | ImplDef | FuncCall | None,
1673
1728
  kid: Sequence[UniNode],
1674
1729
  doc: Optional[String] = None,
1675
- decorators: Optional[SubNodeList[Expr]] = None,
1730
+ decorators: Sequence[Expr] | None = None,
1676
1731
  ) -> None:
1677
1732
  self.name_ref = name_ref
1678
1733
  self.is_override = is_override
@@ -1706,17 +1761,14 @@ class Ability(
1706
1761
  @property
1707
1762
  def method_owner(self) -> Optional[Archetype | Enum]:
1708
1763
  found = (
1709
- self.parent.parent
1710
- if self.parent
1711
- and self.parent.parent
1712
- and isinstance(self.parent.parent, (Archetype, Enum))
1764
+ self.parent
1765
+ if self.parent and isinstance(self.parent, (Archetype, Enum))
1713
1766
  else None
1714
1767
  ) or (
1715
- self.parent.parent.decl_link
1768
+ self.parent.decl_link
1716
1769
  if self.parent
1717
- and self.parent.parent
1718
- and isinstance(self.parent.parent, ImplDef)
1719
- and isinstance(self.parent.parent.decl_link, Archetype)
1770
+ and isinstance(self.parent, ImplDef)
1771
+ and isinstance(self.parent.decl_link, (Archetype, Enum))
1720
1772
  else None
1721
1773
  )
1722
1774
  return found
@@ -1725,6 +1777,22 @@ class Ability(
1725
1777
  def is_genai_ability(self) -> bool:
1726
1778
  return isinstance(self.body, FuncCall)
1727
1779
 
1780
+ def get_pos_argc_range(self) -> tuple[int, int]:
1781
+ """Get the range of positional arguments for this ability.
1782
+
1783
+ Returns -1 for maximum number of arguments if there is an unpacked parameter (e.g., *args).
1784
+ """
1785
+ mn, mx = 0, 0
1786
+ if isinstance(self.signature, FuncSignature):
1787
+ for param in self.signature.params:
1788
+ if param.unpack:
1789
+ if param.unpack == Tok.STAR_MUL:
1790
+ mx = -1
1791
+ break
1792
+ mn += 1
1793
+ mx += 1
1794
+ return mn, mx
1795
+
1728
1796
  def py_resolve_name(self) -> str:
1729
1797
  if isinstance(self.name_ref, Name):
1730
1798
  return self.name_ref.value
@@ -1739,15 +1807,25 @@ class Ability(
1739
1807
  res = self.name_ref.normalize(deep)
1740
1808
  res = res and self.access.normalize(deep) if self.access else res
1741
1809
  res = res and self.signature.normalize(deep) if self.signature else res
1742
- res = res and self.body.normalize(deep) if self.body else res
1743
- res = res and self.decorators.normalize(deep) if self.decorators else res
1810
+ if isinstance(self.body, ImplDef):
1811
+ res = res and self.body.normalize(deep)
1812
+ elif isinstance(self.body, Sequence):
1813
+ for stmt in self.body:
1814
+ res = res and stmt.normalize(deep)
1815
+ else:
1816
+ res = res and self.body.normalize(deep) if self.body else res
1817
+ for dec in self.decorators or []:
1818
+ res = res and dec.normalize(deep)
1744
1819
  res = res and self.doc.normalize(deep) if self.doc else res
1745
1820
  new_kid: list[UniNode] = []
1746
1821
  if self.doc:
1747
1822
  new_kid.append(self.doc)
1748
1823
  if self.decorators:
1749
1824
  new_kid.append(self.gen_token(Tok.DECOR_OP))
1750
- new_kid.append(self.decorators)
1825
+ for idx, dec in enumerate(self.decorators):
1826
+ new_kid.append(dec)
1827
+ if idx < len(self.decorators) - 1:
1828
+ new_kid.append(self.gen_token(Tok.DECOR_OP))
1751
1829
  new_kid.append(self.gen_token(Tok.WS))
1752
1830
  if self.is_async:
1753
1831
  new_kid.append(self.gen_token(Tok.KW_ASYNC))
@@ -1769,9 +1847,14 @@ class Ability(
1769
1847
  new_kid.append(self.gen_token(Tok.KW_BY))
1770
1848
  if self.is_abstract:
1771
1849
  new_kid.append(self.gen_token(Tok.KW_ABSTRACT))
1772
- if self.body:
1850
+ if self.body is not None:
1773
1851
  if isinstance(self.body, ImplDef):
1774
1852
  new_kid.append(self.gen_token(Tok.SEMI))
1853
+ elif isinstance(self.body, Sequence):
1854
+ new_kid.append(self.gen_token(Tok.LBRACE))
1855
+ for stmt in self.body:
1856
+ new_kid.append(stmt)
1857
+ new_kid.append(self.gen_token(Tok.RBRACE))
1775
1858
  else:
1776
1859
  new_kid.append(self.body)
1777
1860
  if self.is_genai_ability:
@@ -1787,11 +1870,11 @@ class FuncSignature(UniNode):
1787
1870
 
1788
1871
  def __init__(
1789
1872
  self,
1790
- params: Optional[SubNodeList[ParamVar]],
1873
+ params: Sequence[ParamVar] | None,
1791
1874
  return_type: Optional[Expr],
1792
1875
  kid: Sequence[UniNode],
1793
1876
  ) -> None:
1794
- self.params = params
1877
+ self.params: list[ParamVar] = list(params) if params else []
1795
1878
  self.return_type = return_type
1796
1879
  UniNode.__init__(self, kid=kid)
1797
1880
 
@@ -1799,11 +1882,14 @@ class FuncSignature(UniNode):
1799
1882
  res = True
1800
1883
  is_lambda = self.parent and isinstance(self.parent, LambdaExpr)
1801
1884
  if deep:
1802
- res = self.params.normalize(deep) if self.params else res
1885
+ for prm in self.params:
1886
+ res = res and prm.normalize(deep)
1803
1887
  res = res and self.return_type.normalize(deep) if self.return_type else res
1804
1888
  new_kid: list[UniNode] = [self.gen_token(Tok.LPAREN)] if not is_lambda else []
1805
- if self.params:
1806
- new_kid.append(self.params)
1889
+ for idx, prm in enumerate(self.params):
1890
+ new_kid.append(prm)
1891
+ if idx < len(self.params) - 1:
1892
+ new_kid.append(self.gen_token(Tok.COMMA))
1807
1893
  if not is_lambda:
1808
1894
  new_kid.append(self.gen_token(Tok.RPAREN))
1809
1895
  if self.return_type:
@@ -1837,20 +1923,19 @@ class FuncSignature(UniNode):
1837
1923
  )
1838
1924
 
1839
1925
 
1840
- class EventSignature(UniNode):
1926
+ class EventSignature(WalkerStmtOnlyNode):
1841
1927
  """EventSignature node type for Jac Ast."""
1842
1928
 
1843
1929
  def __init__(
1844
1930
  self,
1845
1931
  event: Token,
1846
1932
  arch_tag_info: Optional[Expr],
1847
- return_type: Optional[Expr],
1848
1933
  kid: Sequence[UniNode],
1849
1934
  ) -> None:
1850
1935
  self.event = event
1851
1936
  self.arch_tag_info = arch_tag_info
1852
- self.return_type = return_type
1853
1937
  UniNode.__init__(self, kid=kid)
1938
+ WalkerStmtOnlyNode.__init__(self)
1854
1939
 
1855
1940
  def normalize(self, deep: bool = False) -> bool:
1856
1941
  res = True
@@ -1861,14 +1946,10 @@ class EventSignature(UniNode):
1861
1946
  if self.arch_tag_info
1862
1947
  else res
1863
1948
  )
1864
- res = res and self.return_type.normalize(deep) if self.return_type else res
1865
1949
  new_kid: list[UniNode] = [self.gen_token(Tok.KW_WITH)]
1866
1950
  if self.arch_tag_info:
1867
1951
  new_kid.append(self.arch_tag_info)
1868
1952
  new_kid.append(self.event)
1869
- if self.return_type:
1870
- new_kid.append(self.gen_token(Tok.RETURN_HINT))
1871
- new_kid.append(self.return_type)
1872
1953
  self.set_kids(nodes=new_kid)
1873
1954
  return res
1874
1955
 
@@ -1926,13 +2007,13 @@ class ArchHas(AstAccessNode, AstDocNode, ArchBlockStmt, CodeBlockStmt):
1926
2007
  self,
1927
2008
  is_static: bool,
1928
2009
  access: Optional[SubTag[Token]],
1929
- vars: SubNodeList[HasVar],
2010
+ vars: Sequence[HasVar],
1930
2011
  is_frozen: bool,
1931
2012
  kid: Sequence[UniNode],
1932
2013
  doc: Optional[String] = None,
1933
2014
  ) -> None:
1934
2015
  self.is_static = is_static
1935
- self.vars = vars
2016
+ self.vars: list[HasVar] = list(vars)
1936
2017
  self.is_frozen = is_frozen
1937
2018
  UniNode.__init__(self, kid=kid)
1938
2019
  AstAccessNode.__init__(self, access=access)
@@ -1943,7 +2024,8 @@ class ArchHas(AstAccessNode, AstDocNode, ArchBlockStmt, CodeBlockStmt):
1943
2024
  res = True
1944
2025
  if deep:
1945
2026
  res = self.access.normalize(deep) if self.access else res
1946
- res = res and self.vars.normalize(deep) if self.vars else res
2027
+ for var in self.vars:
2028
+ res = res and var.normalize(deep)
1947
2029
  res = res and self.doc.normalize(deep) if self.doc else res
1948
2030
  new_kid: list[UniNode] = []
1949
2031
  if self.doc:
@@ -1957,7 +2039,10 @@ class ArchHas(AstAccessNode, AstDocNode, ArchBlockStmt, CodeBlockStmt):
1957
2039
  )
1958
2040
  if self.access:
1959
2041
  new_kid.append(self.access)
1960
- new_kid.append(self.vars)
2042
+ for i, var in enumerate(self.vars):
2043
+ new_kid.append(var)
2044
+ if i < len(self.vars) - 1:
2045
+ new_kid.append(self.gen_token(Tok.COMMA))
1961
2046
  new_kid.append(self.gen_token(Tok.SEMI))
1962
2047
  self.set_kids(nodes=new_kid)
1963
2048
  return res
@@ -2011,7 +2096,7 @@ class TypedCtxBlock(CodeBlockStmt, UniScopeNode):
2011
2096
  def __init__(
2012
2097
  self,
2013
2098
  type_ctx: Expr,
2014
- body: SubNodeList[CodeBlockStmt],
2099
+ body: Sequence[CodeBlockStmt],
2015
2100
  kid: Sequence[UniNode],
2016
2101
  ) -> None:
2017
2102
  self.type_ctx = type_ctx
@@ -2024,12 +2109,16 @@ class TypedCtxBlock(CodeBlockStmt, UniScopeNode):
2024
2109
  res = True
2025
2110
  if deep:
2026
2111
  res = self.type_ctx.normalize(deep)
2027
- res = res and self.body.normalize(deep)
2112
+ for stmt in self.body:
2113
+ res = res and stmt.normalize(deep)
2028
2114
  new_kid: list[UniNode] = [
2029
2115
  self.gen_token(Tok.RETURN_HINT),
2030
2116
  self.type_ctx,
2031
- self.body,
2117
+ self.gen_token(Tok.LBRACE),
2032
2118
  ]
2119
+ for stmt in self.body:
2120
+ new_kid.append(stmt)
2121
+ new_kid.append(self.gen_token(Tok.RBRACE))
2033
2122
  self.set_kids(nodes=new_kid)
2034
2123
  return res
2035
2124
 
@@ -2040,12 +2129,12 @@ class IfStmt(CodeBlockStmt, AstElseBodyNode, UniScopeNode):
2040
2129
  def __init__(
2041
2130
  self,
2042
2131
  condition: Expr,
2043
- body: SubNodeList[CodeBlockStmt],
2132
+ body: Sequence[CodeBlockStmt],
2044
2133
  else_body: Optional[ElseStmt | ElseIf],
2045
2134
  kid: Sequence[UniNode],
2046
2135
  ) -> None:
2047
2136
  self.condition = condition
2048
- self.body = body
2137
+ self.body: list[CodeBlockStmt] = list(body)
2049
2138
  UniNode.__init__(self, kid=kid)
2050
2139
  AstElseBodyNode.__init__(self, else_body=else_body)
2051
2140
  UniScopeNode.__init__(self, name=f"{self.__class__.__name__}")
@@ -2055,13 +2144,17 @@ class IfStmt(CodeBlockStmt, AstElseBodyNode, UniScopeNode):
2055
2144
  res = True
2056
2145
  if deep:
2057
2146
  res = self.condition.normalize(deep)
2058
- res = res and self.body.normalize(deep)
2147
+ for stmt in self.body:
2148
+ res = res and stmt.normalize(deep)
2059
2149
  res = res and self.else_body.normalize(deep) if self.else_body else res
2060
2150
  new_kid: list[UniNode] = [
2061
2151
  self.gen_token(Tok.KW_IF),
2062
2152
  self.condition,
2063
- self.body,
2153
+ self.gen_token(Tok.LBRACE),
2064
2154
  ]
2155
+ for stmt in self.body:
2156
+ new_kid.append(stmt)
2157
+ new_kid.append(self.gen_token(Tok.RBRACE))
2065
2158
  if self.else_body:
2066
2159
  new_kid.append(self.else_body)
2067
2160
  self.set_kids(nodes=new_kid)
@@ -2075,13 +2168,17 @@ class ElseIf(IfStmt):
2075
2168
  res = True
2076
2169
  if deep:
2077
2170
  res = self.condition.normalize(deep)
2078
- res = res and self.body.normalize(deep)
2171
+ for stmt in self.body:
2172
+ res = res and stmt.normalize(deep)
2079
2173
  res = res and self.else_body.normalize(deep) if self.else_body else res
2080
2174
  new_kid: list[UniNode] = [
2081
2175
  self.gen_token(Tok.KW_ELIF),
2082
2176
  self.condition,
2083
- self.body,
2177
+ self.gen_token(Tok.LBRACE),
2084
2178
  ]
2179
+ for stmt in self.body:
2180
+ new_kid.append(stmt)
2181
+ new_kid.append(self.gen_token(Tok.RBRACE))
2085
2182
  if self.else_body:
2086
2183
  new_kid.append(self.else_body)
2087
2184
  self.set_kids(nodes=new_kid)
@@ -2093,21 +2190,25 @@ class ElseStmt(UniScopeNode):
2093
2190
 
2094
2191
  def __init__(
2095
2192
  self,
2096
- body: SubNodeList[CodeBlockStmt],
2193
+ body: Sequence[CodeBlockStmt],
2097
2194
  kid: Sequence[UniNode],
2098
2195
  ) -> None:
2099
- self.body = body
2196
+ self.body: list[CodeBlockStmt] = list(body)
2100
2197
  UniNode.__init__(self, kid=kid)
2101
2198
  UniScopeNode.__init__(self, name=f"{self.__class__.__name__}")
2102
2199
 
2103
2200
  def normalize(self, deep: bool = False) -> bool:
2104
2201
  res = True
2105
2202
  if deep:
2106
- res = self.body.normalize(deep)
2203
+ for stmt in self.body:
2204
+ res = res and stmt.normalize(deep)
2107
2205
  new_kid: list[UniNode] = [
2108
2206
  self.gen_token(Tok.KW_ELSE),
2109
- self.body,
2207
+ self.gen_token(Tok.LBRACE),
2110
2208
  ]
2209
+ for stmt in self.body:
2210
+ new_kid.append(stmt)
2211
+ new_kid.append(self.gen_token(Tok.RBRACE))
2111
2212
  self.set_kids(nodes=new_kid)
2112
2213
  return res
2113
2214
 
@@ -2144,14 +2245,14 @@ class TryStmt(AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2144
2245
 
2145
2246
  def __init__(
2146
2247
  self,
2147
- body: SubNodeList[CodeBlockStmt],
2148
- excepts: Optional[SubNodeList[Except]],
2248
+ body: Sequence[CodeBlockStmt],
2249
+ excepts: Sequence[Except],
2149
2250
  else_body: Optional[ElseStmt],
2150
2251
  finally_body: Optional[FinallyStmt],
2151
2252
  kid: Sequence[UniNode],
2152
2253
  ) -> None:
2153
- self.body = body
2154
- self.excepts = excepts
2254
+ self.body: list[CodeBlockStmt] = list(body)
2255
+ self.excepts: list[Except] = list(excepts)
2155
2256
  self.finally_body = finally_body
2156
2257
  UniNode.__init__(self, kid=kid)
2157
2258
  AstElseBodyNode.__init__(self, else_body=else_body)
@@ -2161,18 +2262,23 @@ class TryStmt(AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2161
2262
  def normalize(self, deep: bool = False) -> bool:
2162
2263
  res = True
2163
2264
  if deep:
2164
- res = self.body.normalize(deep)
2165
- res = res and self.excepts.normalize(deep) if self.excepts else res
2265
+ for stmt in self.body:
2266
+ res = res and stmt.normalize(deep)
2267
+ for exc in self.excepts:
2268
+ res = res and exc.normalize(deep)
2166
2269
  res = res and self.else_body.normalize(deep) if self.else_body else res
2167
2270
  res = (
2168
2271
  res and self.finally_body.normalize(deep) if self.finally_body else res
2169
2272
  )
2170
2273
  new_kid: list[UniNode] = [
2171
2274
  self.gen_token(Tok.KW_TRY),
2275
+ self.gen_token(Tok.LBRACE),
2172
2276
  ]
2173
- new_kid.append(self.body)
2174
- if self.excepts:
2175
- new_kid.append(self.excepts)
2277
+ for stmt in self.body:
2278
+ new_kid.append(stmt)
2279
+ new_kid.append(self.gen_token(Tok.RBRACE))
2280
+ for exc in self.excepts:
2281
+ new_kid.append(exc)
2176
2282
  if self.else_body:
2177
2283
  new_kid.append(self.else_body)
2178
2284
  if self.finally_body:
@@ -2188,12 +2294,12 @@ class Except(CodeBlockStmt, UniScopeNode):
2188
2294
  self,
2189
2295
  ex_type: Expr,
2190
2296
  name: Optional[Name],
2191
- body: SubNodeList[CodeBlockStmt],
2297
+ body: Sequence[CodeBlockStmt],
2192
2298
  kid: Sequence[UniNode],
2193
2299
  ) -> None:
2194
2300
  self.ex_type = ex_type
2195
2301
  self.name = name
2196
- self.body = body
2302
+ self.body: list[CodeBlockStmt] = list(body)
2197
2303
  UniNode.__init__(self, kid=kid)
2198
2304
  UniScopeNode.__init__(self, name=f"{self.__class__.__name__}")
2199
2305
  CodeBlockStmt.__init__(self)
@@ -2203,7 +2309,8 @@ class Except(CodeBlockStmt, UniScopeNode):
2203
2309
  if deep:
2204
2310
  res = self.ex_type.normalize(deep)
2205
2311
  res = res and self.name.normalize(deep) if self.name else res
2206
- res = res and self.body.normalize(deep) if self.body else res
2312
+ for stmt in self.body:
2313
+ res = res and stmt.normalize(deep)
2207
2314
  new_kid: list[UniNode] = [
2208
2315
  self.gen_token(Tok.KW_EXCEPT),
2209
2316
  self.ex_type,
@@ -2211,7 +2318,10 @@ class Except(CodeBlockStmt, UniScopeNode):
2211
2318
  if self.name:
2212
2319
  new_kid.append(self.gen_token(Tok.KW_AS))
2213
2320
  new_kid.append(self.name)
2214
- new_kid.append(self.body)
2321
+ new_kid.append(self.gen_token(Tok.LBRACE))
2322
+ for stmt in self.body:
2323
+ new_kid.append(stmt)
2324
+ new_kid.append(self.gen_token(Tok.RBRACE))
2215
2325
  self.set_kids(nodes=new_kid)
2216
2326
  return res
2217
2327
 
@@ -2221,10 +2331,10 @@ class FinallyStmt(CodeBlockStmt, UniScopeNode):
2221
2331
 
2222
2332
  def __init__(
2223
2333
  self,
2224
- body: SubNodeList[CodeBlockStmt],
2334
+ body: Sequence[CodeBlockStmt],
2225
2335
  kid: Sequence[UniNode],
2226
2336
  ) -> None:
2227
- self.body = body
2337
+ self.body: list[CodeBlockStmt] = list(body)
2228
2338
  UniNode.__init__(self, kid=kid)
2229
2339
  UniScopeNode.__init__(self, name=f"{self.__class__.__name__}")
2230
2340
  CodeBlockStmt.__init__(self)
@@ -2232,11 +2342,15 @@ class FinallyStmt(CodeBlockStmt, UniScopeNode):
2232
2342
  def normalize(self, deep: bool = False) -> bool:
2233
2343
  res = True
2234
2344
  if deep:
2235
- res = self.body.normalize(deep)
2345
+ for stmt in self.body:
2346
+ res = res and stmt.normalize(deep)
2236
2347
  new_kid: list[UniNode] = [
2237
2348
  self.gen_token(Tok.KW_FINALLY),
2349
+ self.gen_token(Tok.LBRACE),
2238
2350
  ]
2239
- new_kid.append(self.body)
2351
+ for stmt in self.body:
2352
+ new_kid.append(stmt)
2353
+ new_kid.append(self.gen_token(Tok.RBRACE))
2240
2354
  self.set_kids(nodes=new_kid)
2241
2355
  return res
2242
2356
 
@@ -2250,14 +2364,14 @@ class IterForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2250
2364
  is_async: bool,
2251
2365
  condition: Expr,
2252
2366
  count_by: Assignment,
2253
- body: SubNodeList[CodeBlockStmt],
2367
+ body: Sequence[CodeBlockStmt],
2254
2368
  else_body: Optional[ElseStmt],
2255
2369
  kid: Sequence[UniNode],
2256
2370
  ) -> None:
2257
2371
  self.iter = iter
2258
2372
  self.condition = condition
2259
2373
  self.count_by = count_by
2260
- self.body = body
2374
+ self.body: list[CodeBlockStmt] = list(body)
2261
2375
  UniNode.__init__(self, kid=kid)
2262
2376
  AstAsyncNode.__init__(self, is_async=is_async)
2263
2377
  AstElseBodyNode.__init__(self, else_body=else_body)
@@ -2270,8 +2384,9 @@ class IterForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2270
2384
  res = self.iter.normalize(deep)
2271
2385
  res = self.condition.normalize(deep)
2272
2386
  res = self.count_by.normalize(deep)
2273
- res = self.body.normalize(deep)
2274
- res = self.else_body.normalize(deep) if self.else_body else res
2387
+ for stmt in self.body:
2388
+ res = res and stmt.normalize(deep)
2389
+ res = res and self.else_body.normalize(deep) if self.else_body else res
2275
2390
  new_kid: list[UniNode] = []
2276
2391
  if self.is_async:
2277
2392
  new_kid.append(self.gen_token(Tok.KW_ASYNC))
@@ -2281,7 +2396,10 @@ class IterForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2281
2396
  new_kid.append(self.condition)
2282
2397
  new_kid.append(self.gen_token(Tok.KW_BY))
2283
2398
  new_kid.append(self.count_by)
2284
- new_kid.append(self.body)
2399
+ new_kid.append(self.gen_token(Tok.LBRACE))
2400
+ for stmt in self.body:
2401
+ new_kid.append(stmt)
2402
+ new_kid.append(self.gen_token(Tok.RBRACE))
2285
2403
  if self.else_body:
2286
2404
  new_kid.append(self.else_body)
2287
2405
  self.set_kids(nodes=new_kid)
@@ -2296,13 +2414,13 @@ class InForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2296
2414
  target: Expr,
2297
2415
  is_async: bool,
2298
2416
  collection: Expr,
2299
- body: SubNodeList[CodeBlockStmt],
2417
+ body: Sequence[CodeBlockStmt],
2300
2418
  else_body: Optional[ElseStmt],
2301
2419
  kid: Sequence[UniNode],
2302
2420
  ) -> None:
2303
2421
  self.target = target
2304
2422
  self.collection = collection
2305
- self.body = body
2423
+ self.body: list[CodeBlockStmt] = list(body)
2306
2424
  UniNode.__init__(self, kid=kid)
2307
2425
  AstAsyncNode.__init__(self, is_async=is_async)
2308
2426
  AstElseBodyNode.__init__(self, else_body=else_body)
@@ -2312,9 +2430,10 @@ class InForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2312
2430
  def normalize(self, deep: bool = False) -> bool:
2313
2431
  res = True
2314
2432
  if deep:
2315
- res = self.target.normalize(deep)
2433
+ res = res and self.target.normalize(deep)
2316
2434
  res = res and self.collection.normalize(deep)
2317
- res = res and self.body.normalize(deep)
2435
+ for stmt in self.body:
2436
+ res = res and stmt.normalize(deep)
2318
2437
  res = res and self.else_body.normalize(deep) if self.else_body else res
2319
2438
  new_kid: list[UniNode] = []
2320
2439
  if self.is_async:
@@ -2324,8 +2443,10 @@ class InForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt, UniScopeNode):
2324
2443
  new_kid.append(self.gen_token(Tok.KW_IN))
2325
2444
  new_kid.append(self.collection)
2326
2445
 
2327
- if self.body:
2328
- new_kid.append(self.body)
2446
+ new_kid.append(self.gen_token(Tok.LBRACE))
2447
+ for stmt in self.body:
2448
+ new_kid.append(stmt)
2449
+ new_kid.append(self.gen_token(Tok.RBRACE))
2329
2450
  if self.else_body:
2330
2451
  new_kid.append(self.else_body)
2331
2452
  self.set_kids(nodes=new_kid)
@@ -2338,11 +2459,11 @@ class WhileStmt(CodeBlockStmt, UniScopeNode):
2338
2459
  def __init__(
2339
2460
  self,
2340
2461
  condition: Expr,
2341
- body: SubNodeList[CodeBlockStmt],
2462
+ body: Sequence[CodeBlockStmt],
2342
2463
  kid: Sequence[UniNode],
2343
2464
  ) -> None:
2344
2465
  self.condition = condition
2345
- self.body = body
2466
+ self.body: list[CodeBlockStmt] = list(body)
2346
2467
  UniNode.__init__(self, kid=kid)
2347
2468
  UniScopeNode.__init__(self, name=f"{self.__class__.__name__}")
2348
2469
  CodeBlockStmt.__init__(self)
@@ -2351,13 +2472,16 @@ class WhileStmt(CodeBlockStmt, UniScopeNode):
2351
2472
  res = True
2352
2473
  if deep:
2353
2474
  res = self.condition.normalize(deep)
2354
- res = res and self.body.normalize(deep)
2475
+ for stmt in self.body:
2476
+ res = res and stmt.normalize(deep)
2355
2477
  new_kid: list[UniNode] = [
2356
2478
  self.gen_token(Tok.KW_WHILE),
2357
2479
  self.condition,
2480
+ self.gen_token(Tok.LBRACE),
2358
2481
  ]
2359
- if self.body:
2360
- new_kid.append(self.body)
2482
+ for stmt in self.body:
2483
+ new_kid.append(stmt)
2484
+ new_kid.append(self.gen_token(Tok.RBRACE))
2361
2485
  self.set_kids(nodes=new_kid)
2362
2486
  return res
2363
2487
 
@@ -2368,12 +2492,12 @@ class WithStmt(AstAsyncNode, CodeBlockStmt, UniScopeNode):
2368
2492
  def __init__(
2369
2493
  self,
2370
2494
  is_async: bool,
2371
- exprs: SubNodeList[ExprAsItem],
2372
- body: SubNodeList[CodeBlockStmt],
2495
+ exprs: Sequence[ExprAsItem],
2496
+ body: Sequence[CodeBlockStmt],
2373
2497
  kid: Sequence[UniNode],
2374
2498
  ) -> None:
2375
2499
  self.exprs = exprs
2376
- self.body = body
2500
+ self.body: list[CodeBlockStmt] = list(body)
2377
2501
  UniNode.__init__(self, kid=kid)
2378
2502
  AstAsyncNode.__init__(self, is_async=is_async)
2379
2503
  UniScopeNode.__init__(self, name=f"{self.__class__.__name__}")
@@ -2382,14 +2506,22 @@ class WithStmt(AstAsyncNode, CodeBlockStmt, UniScopeNode):
2382
2506
  def normalize(self, deep: bool = False) -> bool:
2383
2507
  res = True
2384
2508
  if deep:
2385
- res = self.exprs.normalize(deep)
2386
- res = res and self.body.normalize(deep)
2509
+ for item in self.exprs:
2510
+ res = res and item.normalize(deep)
2511
+ for stmt in self.body:
2512
+ res = res and stmt.normalize(deep)
2387
2513
  new_kid: list[UniNode] = []
2388
2514
  if self.is_async:
2389
2515
  new_kid.append(self.gen_token(Tok.KW_ASYNC))
2390
2516
  new_kid.append(self.gen_token(Tok.KW_WITH))
2391
- new_kid.append(self.exprs)
2392
- new_kid.append(self.body)
2517
+ for idx, item in enumerate(self.exprs):
2518
+ new_kid.append(item)
2519
+ if idx < len(self.exprs) - 1:
2520
+ new_kid.append(self.gen_token(Tok.COMMA))
2521
+ new_kid.append(self.gen_token(Tok.LBRACE))
2522
+ for stmt in self.body:
2523
+ new_kid.append(stmt)
2524
+ new_kid.append(self.gen_token(Tok.RBRACE))
2393
2525
  self.set_kids(nodes=new_kid)
2394
2526
  return res
2395
2527
 
@@ -2543,7 +2675,7 @@ class DeleteStmt(CodeBlockStmt):
2543
2675
  def py_ast_targets(self) -> list[ast3.AST]:
2544
2676
  """Get Python AST targets (without setting ctx)."""
2545
2677
  return (
2546
- self.target.values.gen.py_ast
2678
+ [i.gen.py_ast[0] for i in self.target.values]
2547
2679
  if isinstance(self.target, TupleVal) and self.target.values
2548
2680
  else self.target.gen.py_ast
2549
2681
  )
@@ -2727,22 +2859,24 @@ class GlobalStmt(CodeBlockStmt):
2727
2859
 
2728
2860
  def __init__(
2729
2861
  self,
2730
- target: SubNodeList[NameAtom],
2862
+ target: Sequence[NameAtom],
2731
2863
  kid: Sequence[UniNode],
2732
2864
  ) -> None:
2733
- self.target = target
2865
+ self.target: list[NameAtom] = list(target)
2734
2866
  UniNode.__init__(self, kid=kid)
2735
2867
  CodeBlockStmt.__init__(self)
2736
2868
 
2737
2869
  def normalize(self, deep: bool = False) -> bool:
2738
2870
  res = True
2739
2871
  if deep:
2740
- res = self.target.normalize(deep)
2741
- new_kid: list[UniNode] = [
2742
- self.gen_token(Tok.GLOBAL_OP),
2743
- self.target,
2744
- self.gen_token(Tok.SEMI),
2745
- ]
2872
+ for item in self.target:
2873
+ res = res and item.normalize(deep)
2874
+ new_kid: list[UniNode] = [self.gen_token(Tok.GLOBAL_OP)]
2875
+ for idx, item in enumerate(self.target):
2876
+ new_kid.append(item)
2877
+ if idx < len(self.target) - 1:
2878
+ new_kid.append(self.gen_token(Tok.COMMA))
2879
+ new_kid.append(self.gen_token(Tok.SEMI))
2746
2880
  self.set_kids(nodes=new_kid)
2747
2881
  return res
2748
2882
 
@@ -2753,12 +2887,14 @@ class NonLocalStmt(GlobalStmt):
2753
2887
  def normalize(self, deep: bool = False) -> bool:
2754
2888
  res = True
2755
2889
  if deep:
2756
- res = self.target.normalize(deep)
2757
- new_kid: list[UniNode] = [
2758
- self.gen_token(Tok.NONLOCAL_OP),
2759
- self.target,
2760
- self.gen_token(Tok.SEMI),
2761
- ]
2890
+ for item in self.target:
2891
+ res = res and item.normalize(deep)
2892
+ new_kid: list[UniNode] = [self.gen_token(Tok.NONLOCAL_OP)]
2893
+ for idx, item in enumerate(self.target):
2894
+ new_kid.append(item)
2895
+ if idx < len(self.target) - 1:
2896
+ new_kid.append(self.gen_token(Tok.COMMA))
2897
+ new_kid.append(self.gen_token(Tok.SEMI))
2762
2898
  self.set_kids(nodes=new_kid)
2763
2899
  return res
2764
2900
 
@@ -2768,7 +2904,7 @@ class Assignment(AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
2768
2904
 
2769
2905
  def __init__(
2770
2906
  self,
2771
- target: SubNodeList[Expr],
2907
+ target: Sequence[Expr],
2772
2908
  value: Optional[Expr | YieldExpr],
2773
2909
  type_tag: Optional[SubTag[Expr]],
2774
2910
  kid: Sequence[UniNode],
@@ -2776,24 +2912,28 @@ class Assignment(AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
2776
2912
  aug_op: Optional[Token] = None,
2777
2913
  is_enum_stmt: bool = False,
2778
2914
  ) -> None:
2779
- self.target = target
2915
+ self.target: list[Expr] = list(target)
2780
2916
  self.value = value
2781
2917
  self.mutable = mutable
2782
2918
  self.aug_op = aug_op
2783
- self.is_enum_stmt = is_enum_stmt
2784
2919
  UniNode.__init__(self, kid=kid)
2785
2920
  AstTypedVarNode.__init__(self, type_tag=type_tag)
2786
2921
  CodeBlockStmt.__init__(self)
2922
+ EnumBlockStmt.__init__(self, is_enum_stmt=is_enum_stmt)
2787
2923
 
2788
2924
  def normalize(self, deep: bool = True) -> bool:
2789
2925
  res = True
2790
2926
  if deep:
2791
- res = self.target.normalize(deep)
2927
+ for t in self.target:
2928
+ res = res and t.normalize(deep)
2792
2929
  res = res and self.value.normalize(deep) if self.value else res
2793
2930
  res = res and self.type_tag.normalize(deep) if self.type_tag else res
2794
2931
  res = res and self.aug_op.normalize(deep) if self.aug_op else res
2795
2932
  new_kid: list[UniNode] = []
2796
- new_kid.append(self.target)
2933
+ for idx, targ in enumerate(self.target):
2934
+ new_kid.append(targ)
2935
+ if idx < len(self.target) - 1:
2936
+ new_kid.append(self.gen_token(Tok.EQ))
2797
2937
  if self.type_tag:
2798
2938
  new_kid.append(self.type_tag)
2799
2939
  if self.aug_op:
@@ -2802,12 +2942,13 @@ class Assignment(AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
2802
2942
  if not self.aug_op:
2803
2943
  new_kid.append(self.gen_token(Tok.EQ))
2804
2944
  new_kid.append(self.value)
2805
- if isinstance(self.parent, SubNodeList) and isinstance(
2806
- self.parent.parent, GlobalVars
2807
- ):
2808
- if self.parent.kid.index(self) == len(self.parent.kid) - 1:
2945
+ if isinstance(self.parent, GlobalVars):
2946
+ if self.parent.assignments.index(self) == len(self.parent.assignments) - 1:
2809
2947
  new_kid.append(self.gen_token(Tok.SEMI))
2810
- elif (not self.is_enum_stmt) and not isinstance(self.parent, IterForStmt):
2948
+ elif (not self.is_enum_stmt) and not (
2949
+ isinstance(self.parent, IterForStmt)
2950
+ and self in [self.parent.iter, self.parent.count_by]
2951
+ ):
2811
2952
  new_kid.append(self.gen_token(Tok.SEMI))
2812
2953
  self.set_kids(nodes=new_kid)
2813
2954
  return res
@@ -3045,10 +3186,10 @@ class FString(AtomExpr):
3045
3186
 
3046
3187
  def __init__(
3047
3188
  self,
3048
- parts: Optional[SubNodeList[String | ExprStmt]],
3189
+ parts: Sequence[String | ExprStmt],
3049
3190
  kid: Sequence[UniNode],
3050
3191
  ) -> None:
3051
- self.parts = parts
3192
+ self.parts: list[String | ExprStmt] = list(parts)
3052
3193
  UniNode.__init__(self, kid=kid)
3053
3194
  Expr.__init__(self)
3054
3195
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.STRING)
@@ -3056,26 +3197,30 @@ class FString(AtomExpr):
3056
3197
  def normalize(self, deep: bool = False) -> bool:
3057
3198
  res = True
3058
3199
  if deep:
3059
- res = self.parts.normalize(deep) if self.parts else res
3200
+ for part in self.parts:
3201
+ res = res and part.normalize(deep)
3060
3202
  new_kid: list[UniNode] = []
3061
3203
  is_single_quote = (
3062
3204
  isinstance(self.kid[0], Token) and self.kid[0].name == Tok.FSTR_SQ_START
3063
3205
  )
3064
- if self.parts:
3065
- if is_single_quote:
3066
- new_kid.append(self.gen_token(Tok.FSTR_SQ_START))
3067
- else:
3068
- new_kid.append(self.gen_token(Tok.FSTR_START))
3069
- for i in self.parts.items:
3070
- if isinstance(i, String):
3071
- i.value = (
3072
- "{{" if i.value == "{" else "}}" if i.value == "}" else i.value
3073
- )
3074
- new_kid.append(self.parts)
3075
- if is_single_quote:
3076
- new_kid.append(self.gen_token(Tok.FSTR_SQ_END))
3206
+ if is_single_quote:
3207
+ new_kid.append(self.gen_token(Tok.FSTR_SQ_START))
3208
+ else:
3209
+ new_kid.append(self.gen_token(Tok.FSTR_START))
3210
+ for i in self.parts:
3211
+ if isinstance(i, String):
3212
+ i.value = (
3213
+ "{{" if i.value == "{" else "}}" if i.value == "}" else i.value
3214
+ )
3215
+ new_kid.append(i)
3077
3216
  else:
3078
- new_kid.append(self.gen_token(Tok.FSTR_END))
3217
+ new_kid.append(self.gen_token(Tok.LBRACE))
3218
+ new_kid.append(i)
3219
+ new_kid.append(self.gen_token(Tok.RBRACE))
3220
+ if is_single_quote:
3221
+ new_kid.append(self.gen_token(Tok.FSTR_SQ_END))
3222
+ else:
3223
+ new_kid.append(self.gen_token(Tok.FSTR_END))
3079
3224
  self.set_kids(nodes=new_kid)
3080
3225
  return res
3081
3226
 
@@ -3085,7 +3230,7 @@ class ListVal(AtomExpr):
3085
3230
 
3086
3231
  def __init__(
3087
3232
  self,
3088
- values: Optional[SubNodeList[Expr]],
3233
+ values: Sequence[Expr],
3089
3234
  kid: Sequence[UniNode],
3090
3235
  ) -> None:
3091
3236
  self.values = values
@@ -3096,12 +3241,13 @@ class ListVal(AtomExpr):
3096
3241
  def normalize(self, deep: bool = False) -> bool:
3097
3242
  res = True
3098
3243
  if deep:
3099
- res = self.values.normalize(deep) if self.values else res
3100
- new_kid: list[UniNode] = [
3101
- self.gen_token(Tok.LSQUARE),
3102
- ]
3103
- if self.values:
3104
- new_kid.append(self.values)
3244
+ for i in self.values:
3245
+ res = res and i.normalize(deep)
3246
+ new_kid: list[UniNode] = [self.gen_token(Tok.LSQUARE)]
3247
+ for idx, val in enumerate(self.values):
3248
+ new_kid.append(val)
3249
+ if idx < len(self.values) - 1:
3250
+ new_kid.append(self.gen_token(Tok.COMMA))
3105
3251
  new_kid.append(self.gen_token(Tok.RSQUARE))
3106
3252
  self.set_kids(nodes=new_kid)
3107
3253
  return res
@@ -3112,10 +3258,10 @@ class SetVal(AtomExpr):
3112
3258
 
3113
3259
  def __init__(
3114
3260
  self,
3115
- values: Optional[SubNodeList[Expr]],
3261
+ values: Sequence[Expr] | None,
3116
3262
  kid: Sequence[UniNode],
3117
3263
  ) -> None:
3118
- self.values = values
3264
+ self.values: list[Expr] = list(values) if values else []
3119
3265
  UniNode.__init__(self, kid=kid)
3120
3266
  Expr.__init__(self)
3121
3267
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
@@ -3123,12 +3269,13 @@ class SetVal(AtomExpr):
3123
3269
  def normalize(self, deep: bool = False) -> bool:
3124
3270
  res = True
3125
3271
  if deep:
3126
- res = self.values.normalize(deep) if self.values else res
3127
- new_kid: list[UniNode] = [
3128
- self.gen_token(Tok.LBRACE),
3129
- ]
3130
- if self.values:
3131
- new_kid.append(self.values)
3272
+ for i in self.values:
3273
+ res = res and i.normalize(deep)
3274
+ new_kid: list[UniNode] = [self.gen_token(Tok.LBRACE)]
3275
+ for idx, val in enumerate(self.values):
3276
+ new_kid.append(val)
3277
+ if idx < len(self.values) - 1:
3278
+ new_kid.append(self.gen_token(Tok.COMMA))
3132
3279
  new_kid.append(self.gen_token(Tok.RBRACE))
3133
3280
  self.set_kids(nodes=new_kid)
3134
3281
  return res
@@ -3139,10 +3286,10 @@ class TupleVal(AtomExpr):
3139
3286
 
3140
3287
  def __init__(
3141
3288
  self,
3142
- values: Optional[SubNodeList[Expr | KWPair]],
3289
+ values: Sequence[Expr | KWPair],
3143
3290
  kid: Sequence[UniNode],
3144
3291
  ) -> None:
3145
- self.values = values
3292
+ self.values = list(values)
3146
3293
  UniNode.__init__(self, kid=kid)
3147
3294
  Expr.__init__(self)
3148
3295
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
@@ -3150,7 +3297,8 @@ class TupleVal(AtomExpr):
3150
3297
  def normalize(self, deep: bool = False) -> bool:
3151
3298
  res = True
3152
3299
  if deep:
3153
- res = self.values.normalize(deep) if self.values else res
3300
+ for i in self.values:
3301
+ res = res and i.normalize(deep)
3154
3302
  in_ret_type = (
3155
3303
  self.parent
3156
3304
  and isinstance(self.parent, IndexSlice)
@@ -3166,10 +3314,12 @@ class TupleVal(AtomExpr):
3166
3314
  if not in_ret_type
3167
3315
  else []
3168
3316
  )
3169
- if self.values:
3170
- new_kid.append(self.values)
3171
- if len(self.values.items) < 2:
3317
+ for idx, i in enumerate(self.values):
3318
+ new_kid.append(i)
3319
+ if idx < len(self.values) - 1:
3172
3320
  new_kid.append(self.gen_token(Tok.COMMA))
3321
+ if len(self.values) == 1:
3322
+ new_kid.append(self.gen_token(Tok.COMMA))
3173
3323
  if not in_ret_type:
3174
3324
  new_kid.append(self.gen_token(Tok.RPAREN))
3175
3325
  self.set_kids(nodes=new_kid)
@@ -3516,23 +3666,29 @@ class FuncCall(Expr):
3516
3666
  def __init__(
3517
3667
  self,
3518
3668
  target: Expr,
3519
- params: Optional[SubNodeList[Expr | KWPair]],
3669
+ params: Sequence[Expr | KWPair] | None,
3520
3670
  genai_call: Optional[FuncCall],
3521
3671
  kid: Sequence[UniNode],
3672
+ body_genai_call: Optional[FuncCall] = None,
3522
3673
  ) -> None:
3523
3674
  self.target = target
3524
- self.params = params
3675
+ self.params = list(params) if params else []
3525
3676
  self.genai_call = genai_call
3677
+ self.body_genai_call = body_genai_call
3526
3678
  UniNode.__init__(self, kid=kid)
3527
3679
  Expr.__init__(self)
3528
3680
 
3529
3681
  def normalize(self, deep: bool = True) -> bool:
3682
+ res = True
3530
3683
  if deep:
3531
3684
  res = self.target.normalize(deep)
3532
- res = res and (not self.params or self.params.normalize(deep))
3685
+ for prm in self.params:
3686
+ res = res and prm.normalize(deep)
3533
3687
  new_kids = [self.target, self.gen_token(Tok.LPAREN, "(")]
3534
- if self.params:
3535
- new_kids.append(self.params)
3688
+ for i, prm in enumerate(self.params):
3689
+ new_kids.append(prm)
3690
+ if i < len(self.params) - 1:
3691
+ new_kids.append(self.gen_token(Tok.COMMA))
3536
3692
  if self.genai_call:
3537
3693
  new_kids.append(self.gen_token(Tok.KW_BY))
3538
3694
  new_kids.append(self.genai_call)
@@ -3780,11 +3936,11 @@ class FilterCompr(AtomExpr):
3780
3936
  def __init__(
3781
3937
  self,
3782
3938
  f_type: Optional[Expr],
3783
- compares: Optional[SubNodeList[CompareExpr]],
3939
+ compares: Sequence[CompareExpr],
3784
3940
  kid: Sequence[UniNode],
3785
3941
  ) -> None:
3786
3942
  self.f_type = f_type
3787
- self.compares = compares
3943
+ self.compares = list(compares)
3788
3944
  UniNode.__init__(self, kid=kid)
3789
3945
  Expr.__init__(self)
3790
3946
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
@@ -3793,7 +3949,8 @@ class FilterCompr(AtomExpr):
3793
3949
  res = True
3794
3950
  if deep:
3795
3951
  res = self.f_type.normalize(deep) if self.f_type else res
3796
- res = res and self.compares.normalize(deep) if self.compares else res
3952
+ for comp in self.compares:
3953
+ res = res and comp.normalize(deep)
3797
3954
  new_kid: list[UniNode] = []
3798
3955
  if not isinstance(self.parent, EdgeOpRef):
3799
3956
  new_kid.append(self.gen_token(Tok.LPAREN))
@@ -3805,7 +3962,10 @@ class FilterCompr(AtomExpr):
3805
3962
  if self.compares:
3806
3963
  if self.f_type:
3807
3964
  new_kid.append(self.gen_token(Tok.COLON))
3808
- new_kid.append(self.compares)
3965
+ for i, comp in enumerate(self.compares):
3966
+ new_kid.append(comp)
3967
+ if i < len(self.compares) - 1:
3968
+ new_kid.append(self.gen_token(Tok.COMMA))
3809
3969
  if not isinstance(self.parent, EdgeOpRef):
3810
3970
  new_kid.append(self.gen_token(Tok.RPAREN))
3811
3971
  self.set_kids(nodes=new_kid)
@@ -3817,10 +3977,10 @@ class AssignCompr(AtomExpr):
3817
3977
 
3818
3978
  def __init__(
3819
3979
  self,
3820
- assigns: SubNodeList[KWPair],
3980
+ assigns: Sequence[KWPair],
3821
3981
  kid: Sequence[UniNode],
3822
3982
  ) -> None:
3823
- self.assigns = assigns
3983
+ self.assigns = list(assigns)
3824
3984
  UniNode.__init__(self, kid=kid)
3825
3985
  Expr.__init__(self)
3826
3986
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
@@ -3828,14 +3988,21 @@ class AssignCompr(AtomExpr):
3828
3988
  def normalize(self, deep: bool = False) -> bool:
3829
3989
  res = True
3830
3990
  if deep:
3831
- res = self.assigns.normalize(deep)
3991
+ for assign in self.assigns:
3992
+ res = res and assign.normalize(deep)
3832
3993
  new_kid: list[UniNode] = []
3833
3994
  if isinstance(self.parent, ConnectOp):
3834
- new_kid.append(self.assigns)
3995
+ for i, assign in enumerate(self.assigns):
3996
+ new_kid.append(assign)
3997
+ if i < len(self.assigns) - 1:
3998
+ new_kid.append(self.gen_token(Tok.COMMA))
3835
3999
  else:
3836
4000
  new_kid.append(self.gen_token(Tok.LPAREN))
3837
4001
  new_kid.append(self.gen_token(Tok.EQ))
3838
- new_kid.append(self.assigns)
4002
+ for i, assign in enumerate(self.assigns):
4003
+ new_kid.append(assign)
4004
+ if i < len(self.assigns) - 1:
4005
+ new_kid.append(self.gen_token(Tok.COMMA))
3839
4006
  new_kid.append(self.gen_token(Tok.RPAREN))
3840
4007
  self.set_kids(nodes=new_kid)
3841
4008
  return res
@@ -4133,30 +4300,37 @@ class MatchArch(MatchPattern):
4133
4300
  def __init__(
4134
4301
  self,
4135
4302
  name: AtomTrailer | NameAtom,
4136
- arg_patterns: Optional[SubNodeList[MatchPattern]],
4137
- kw_patterns: Optional[SubNodeList[MatchKVPair]],
4303
+ arg_patterns: Sequence[MatchPattern] | None,
4304
+ kw_patterns: Sequence[MatchKVPair] | None,
4138
4305
  kid: Sequence[UniNode],
4139
4306
  ) -> None:
4140
4307
  self.name = name
4141
- self.arg_patterns = arg_patterns
4142
- self.kw_patterns = kw_patterns
4308
+ self.arg_patterns = list(arg_patterns) if arg_patterns else None
4309
+ self.kw_patterns = list(kw_patterns) if kw_patterns else None
4143
4310
  UniNode.__init__(self, kid=kid)
4144
4311
 
4145
4312
  def normalize(self, deep: bool = False) -> bool:
4146
4313
  res = True
4147
4314
  if deep:
4148
4315
  res = self.name.normalize(deep)
4149
- res = res and (not self.arg_patterns or self.arg_patterns.normalize(deep))
4150
- res = res and (not self.kw_patterns or self.kw_patterns.normalize(deep))
4316
+ for arg in self.arg_patterns or []:
4317
+ res = res and arg.normalize(deep)
4318
+ for kw in self.kw_patterns or []:
4319
+ res = res and kw.normalize(deep)
4151
4320
  new_kid: list[UniNode] = [self.name]
4152
4321
  new_kid.append(self.gen_token(Tok.LPAREN))
4153
4322
  if self.arg_patterns:
4154
- new_kid.append(self.arg_patterns)
4155
- new_kid.append(self.gen_token(Tok.COMMA))
4323
+ for idx, arg in enumerate(self.arg_patterns):
4324
+ new_kid.append(arg)
4325
+ if idx < len(self.arg_patterns) - 1:
4326
+ new_kid.append(self.gen_token(Tok.COMMA))
4327
+ if self.kw_patterns:
4328
+ new_kid.append(self.gen_token(Tok.COMMA))
4156
4329
  if self.kw_patterns:
4157
- new_kid.append(self.kw_patterns)
4158
- else:
4159
- new_kid.pop()
4330
+ for idx, kw in enumerate(self.kw_patterns):
4331
+ new_kid.append(kw)
4332
+ if idx < len(self.kw_patterns) - 1:
4333
+ new_kid.append(self.gen_token(Tok.COMMA))
4160
4334
  new_kid.append(self.gen_token(Tok.RPAREN))
4161
4335
  self.set_kids(nodes=new_kid)
4162
4336
  return res
@@ -4214,10 +4388,9 @@ class Name(Token, NameAtom):
4214
4388
  col_end: int,
4215
4389
  pos_start: int,
4216
4390
  pos_end: int,
4217
- is_enum_singleton: bool = False,
4391
+ is_enum_stmt: bool = False,
4218
4392
  is_kwesc: bool = False,
4219
4393
  ) -> None:
4220
- self.is_enum_singleton = is_enum_singleton
4221
4394
  self.is_kwesc = is_kwesc
4222
4395
  Token.__init__(
4223
4396
  self,
@@ -4231,7 +4404,7 @@ class Name(Token, NameAtom):
4231
4404
  pos_start=pos_start,
4232
4405
  pos_end=pos_end,
4233
4406
  )
4234
- NameAtom.__init__(self)
4407
+ NameAtom.__init__(self, is_enum_stmt=is_enum_stmt)
4235
4408
  AstSymbolNode.__init__(
4236
4409
  self,
4237
4410
  sym_name=value,
@@ -4242,7 +4415,7 @@ class Name(Token, NameAtom):
4242
4415
  def unparse(self) -> str:
4243
4416
  super().unparse()
4244
4417
  return (f"<>{self.value}" if self.is_kwesc else self.value) + (
4245
- ",\n" if self.is_enum_singleton else ""
4418
+ ",\n" if self.is_enum_stmt else ""
4246
4419
  )
4247
4420
 
4248
4421
  @staticmethod
@@ -4272,6 +4445,7 @@ class SpecialVarRef(Name):
4272
4445
  def __init__(
4273
4446
  self,
4274
4447
  var: Name,
4448
+ is_enum_stmt: bool = False,
4275
4449
  ) -> None:
4276
4450
  self.orig = var
4277
4451
  Name.__init__(
@@ -4286,7 +4460,7 @@ class SpecialVarRef(Name):
4286
4460
  pos_start=var.pos_start,
4287
4461
  pos_end=var.pos_end,
4288
4462
  )
4289
- NameAtom.__init__(self)
4463
+ NameAtom.__init__(self, is_enum_stmt=is_enum_stmt)
4290
4464
  AstSymbolNode.__init__(
4291
4465
  self,
4292
4466
  sym_name=self.py_resolve_name(),
@@ -4416,22 +4590,21 @@ class String(Literal):
4416
4590
  return eval(self.value)
4417
4591
 
4418
4592
  elif self.value.startswith(("'", '"')):
4419
- repr_str = self.value.encode().decode("unicode_escape")
4420
- if (
4421
- (self.value.startswith('"""') and self.value.endswith('"""'))
4422
- or (self.value.startswith("'''") and self.value.endswith("'''"))
4423
- ) and not self.find_parent_of_type(FString):
4424
- return repr_str[3:-3]
4425
4593
  if (not self.find_parent_of_type(FString)) or (
4426
- not (
4427
- self.parent
4428
- and isinstance(self.parent, SubNodeList)
4429
- and self.parent.parent
4430
- and isinstance(self.parent.parent, FString)
4431
- )
4594
+ not (self.parent and isinstance(self.parent, FString))
4432
4595
  ):
4433
- return repr_str[1:-1]
4434
- return repr_str
4596
+ try:
4597
+ return ast3.literal_eval(self.value)
4598
+ except (ValueError, SyntaxError):
4599
+ if (
4600
+ self.value.startswith('"""') and self.value.endswith('"""')
4601
+ ) or (self.value.startswith("'''") and self.value.endswith("'''")):
4602
+ return self.value[3:-3]
4603
+ return self.value[1:-1]
4604
+ try:
4605
+ return ast3.literal_eval(self.value)
4606
+ except (ValueError, SyntaxError):
4607
+ return self.value
4435
4608
  else:
4436
4609
  return self.value
4437
4610
 
@@ -4599,9 +4772,4 @@ class PythonModuleAst(EmptyToken):
4599
4772
  super().__init__()
4600
4773
  self.ast = ast
4601
4774
  self.orig_src = orig_src
4602
-
4603
- # This bellow attribute is un-necessary since it already exists in the orig_src
4604
- # however I'm keeping it here not to break existing code trying to access file_path.
4605
- # We can remove this in the future once we safley remove all references to it and
4606
- # use orig_src.
4607
4775
  self.file_path = orig_src.file_path