jaclang 0.5.7__py3-none-any.whl → 0.5.9__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 (49) hide show
  1. jaclang/cli/cli.py +113 -7
  2. jaclang/cli/cmdreg.py +12 -0
  3. jaclang/compiler/__init__.py +58 -2
  4. jaclang/compiler/absyntree.py +1775 -61
  5. jaclang/compiler/codeloc.py +7 -0
  6. jaclang/compiler/compile.py +1 -1
  7. jaclang/compiler/constant.py +17 -0
  8. jaclang/compiler/parser.py +134 -112
  9. jaclang/compiler/passes/ir_pass.py +18 -0
  10. jaclang/compiler/passes/main/__init__.py +2 -0
  11. jaclang/compiler/passes/main/def_impl_match_pass.py +19 -3
  12. jaclang/compiler/passes/main/def_use_pass.py +1 -1
  13. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +357 -0
  14. jaclang/compiler/passes/main/import_pass.py +7 -3
  15. jaclang/compiler/passes/main/pyast_gen_pass.py +350 -109
  16. jaclang/compiler/passes/main/pyast_load_pass.py +1779 -206
  17. jaclang/compiler/passes/main/registry_pass.py +126 -0
  18. jaclang/compiler/passes/main/schedules.py +4 -1
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +20 -28
  20. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +14 -5
  21. jaclang/compiler/passes/main/tests/test_registry_pass.py +39 -0
  22. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +8 -8
  23. jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +7 -0
  24. jaclang/compiler/passes/main/type_check_pass.py +0 -1
  25. jaclang/compiler/passes/tool/jac_formatter_pass.py +8 -17
  26. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +65 -0
  27. jaclang/compiler/passes/utils/mypy_ast_build.py +28 -14
  28. jaclang/compiler/symtable.py +23 -2
  29. jaclang/compiler/tests/test_parser.py +53 -0
  30. jaclang/compiler/workspace.py +52 -26
  31. jaclang/core/aott.py +193 -28
  32. jaclang/core/construct.py +59 -2
  33. jaclang/core/registry.py +115 -0
  34. jaclang/core/utils.py +25 -0
  35. jaclang/plugin/default.py +108 -26
  36. jaclang/plugin/feature.py +22 -4
  37. jaclang/plugin/spec.py +13 -7
  38. jaclang/utils/helpers.py +66 -3
  39. jaclang/utils/lang_tools.py +6 -38
  40. jaclang/utils/test.py +1 -0
  41. jaclang/utils/tests/test_lang_tools.py +11 -14
  42. jaclang/utils/treeprinter.py +10 -2
  43. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/METADATA +1 -1
  44. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/RECORD +47 -43
  45. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/WHEEL +1 -1
  46. jaclang/compiler/__jac_gen__/__init__.py +0 -0
  47. jaclang/compiler/__jac_gen__/jac_parser.py +0 -4069
  48. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/entry_points.txt +0 -0
  49. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/top_level.txt +0 -0
@@ -22,6 +22,13 @@ class CodeGenTarget:
22
22
  mypy_ast: list[MypyNode] = field(default_factory=lambda: [])
23
23
  py_bytecode: Optional[bytes] = None
24
24
 
25
+ def clean(self) -> None:
26
+ """Clean code generation target."""
27
+ self.py = ""
28
+ self.jac = ""
29
+ self.py_ast = []
30
+ self.mypy_ast = []
31
+
25
32
 
26
33
  class CodeLocInfo:
27
34
  """Code location info."""
@@ -16,7 +16,7 @@ def compile_jac(file_path: str, cache_result: bool = False) -> Pass:
16
16
  file_path=file_path,
17
17
  schedule=pass_schedule,
18
18
  )
19
- if cache_result and isinstance(code.ir, ast.Module) and not code.errors_had:
19
+ if cache_result and isinstance(code.ir, ast.Module):
20
20
  print_pass = PyOutPass(input_ir=code.ir, prior=code)
21
21
  return print_pass
22
22
  else:
@@ -236,6 +236,23 @@ class Tokens(str, Enum):
236
236
  return self.value
237
237
 
238
238
 
239
+ DELIM_MAP = {
240
+ Tokens.COMMA: ",",
241
+ Tokens.EQ: "=",
242
+ Tokens.DECOR_OP: "@",
243
+ Tokens.WS: "\n",
244
+ Tokens.SEMI: ";",
245
+ Tokens.COLON: ":",
246
+ Tokens.LBRACE: "{",
247
+ Tokens.RBRACE: "}",
248
+ Tokens.LSQUARE: "[",
249
+ Tokens.RSQUARE: "]",
250
+ Tokens.LPAREN: "(",
251
+ Tokens.RPAREN: ")",
252
+ Tokens.RETURN_HINT: "->",
253
+ Tokens.DOT: ".",
254
+ }
255
+
239
256
  colors = [
240
257
  "#FFE9E9",
241
258
  "#F0FFF0",
@@ -390,6 +390,7 @@ class JacParser(Pass):
390
390
  """
391
391
  ret = ast.SubNodeList[ast.ModuleItem](
392
392
  items=[i for i in kid if isinstance(i, ast.ModuleItem)],
393
+ delim=Tok.COMMA,
393
394
  kid=kid,
394
395
  )
395
396
  return self.nu(ret)
@@ -509,6 +510,7 @@ class JacParser(Pass):
509
510
  return self.nu(
510
511
  ast.SubNodeList[ast.Expr](
511
512
  items=valid_decors,
513
+ delim=Tok.DECOR_OP,
512
514
  kid=kid,
513
515
  )
514
516
  )
@@ -525,6 +527,7 @@ class JacParser(Pass):
525
527
  return self.nu(
526
528
  ast.SubNodeList[ast.Expr](
527
529
  items=valid_inh,
530
+ delim=Tok.COMMA,
528
531
  kid=kid,
529
532
  )
530
533
  )
@@ -596,6 +599,7 @@ class JacParser(Pass):
596
599
  if isinstance(kid[0], (ast.Enum, ast.EnumDef)):
597
600
  return self.nu(kid[0])
598
601
  else:
602
+
599
603
  raise self.ice()
600
604
 
601
605
  def enum_decl(self, kid: list[ast.AstNode]) -> ast.Enum:
@@ -655,37 +659,65 @@ class JacParser(Pass):
655
659
 
656
660
  enum_block: LBRACE ((enum_stmt COMMA)* enum_stmt)? RBRACE
657
661
  """
658
- ret = ast.SubNodeList[ast.EnumBlockStmt](
659
- items=[],
660
- kid=kid,
661
- )
662
+ ret = ast.SubNodeList[ast.EnumBlockStmt](items=[], delim=Tok.COMMA, kid=kid)
662
663
  ret.items = [i for i in kid if isinstance(i, ast.EnumBlockStmt)]
663
664
  return self.nu(ret)
664
665
 
665
666
  def enum_stmt(self, kid: list[ast.AstNode]) -> ast.EnumBlockStmt:
666
667
  """Grammar rule.
667
668
 
668
- enum_stmt: NAME EQ expression
669
- | NAME
669
+ enum_stmt: NAME (COLON STRING)? EQ expression
670
+ | NAME (COLON STRING)?
670
671
  | py_code_block
671
672
  """
672
673
  if isinstance(kid[0], ast.PyInlineCode):
673
674
  return self.nu(kid[0])
674
675
  if isinstance(kid[0], (ast.Name)):
675
- if len(kid) == 1:
676
- kid[0].is_enum_singleton = True
677
- return self.nu(kid[0])
678
- elif isinstance(kid[2], ast.Expr):
679
- targ = ast.SubNodeList[ast.Expr](items=[kid[0]], kid=[kid[0]])
676
+ if (
677
+ len(kid) >= 3
678
+ and isinstance(kid[-1], ast.Expr)
679
+ and not isinstance(kid[-1], ast.String)
680
+ ):
681
+ semstr = (
682
+ kid[2]
683
+ if len(kid) > 3 and isinstance(kid[2], ast.String)
684
+ else None
685
+ )
686
+ targ = ast.SubNodeList[ast.Expr](
687
+ items=[kid[0]], delim=Tok.COMMA, kid=[kid[0]]
688
+ )
689
+ kid[0] = targ
690
+ return self.nu(
691
+ ast.Assignment(
692
+ target=targ,
693
+ value=kid[-1],
694
+ type_tag=None,
695
+ kid=kid,
696
+ semstr=semstr,
697
+ is_enum_stmt=True,
698
+ )
699
+ )
700
+ else:
701
+ semstr = (
702
+ kid[2]
703
+ if len(kid) == 3 and isinstance(kid[2], ast.String)
704
+ else None
705
+ )
706
+ targ = ast.SubNodeList[ast.Expr](
707
+ items=[kid[0]], delim=Tok.COMMA, kid=[kid[0]]
708
+ )
680
709
  kid[0] = targ
681
710
  return self.nu(
682
711
  ast.Assignment(
683
712
  target=targ,
684
- value=kid[2],
713
+ value=None,
685
714
  type_tag=None,
686
715
  kid=kid,
716
+ semstr=semstr,
717
+ is_enum_stmt=True,
687
718
  )
688
719
  )
720
+
689
721
  raise self.ice()
690
722
 
691
723
  def ability(
@@ -748,7 +780,6 @@ class JacParser(Pass):
748
780
  chomp = chomp[1:] if semstr else chomp
749
781
  name = chomp[0]
750
782
  chomp = chomp[1:]
751
- is_func = isinstance(chomp[0], ast.FuncSignature)
752
783
  signature = chomp[0]
753
784
  chomp = chomp[1:]
754
785
  body = chomp[0] if isinstance(chomp[0], ast.SubNodeList) else None
@@ -758,7 +789,6 @@ class JacParser(Pass):
758
789
  return self.nu(
759
790
  ast.Ability(
760
791
  name_ref=name,
761
- is_func=is_func,
762
792
  is_async=False,
763
793
  is_override=is_override,
764
794
  is_static=is_static,
@@ -818,7 +848,6 @@ class JacParser(Pass):
818
848
  chomp = chomp[1:] if semstr else chomp
819
849
  name = chomp[0]
820
850
  chomp = chomp[1:]
821
- is_func = isinstance(chomp[0], ast.FuncSignature)
822
851
  signature = chomp[0]
823
852
  chomp = chomp[1:]
824
853
  if isinstance(name, ast.NameSpec) and isinstance(
@@ -827,7 +856,6 @@ class JacParser(Pass):
827
856
  return self.nu(
828
857
  ast.Ability(
829
858
  name_ref=name,
830
- is_func=is_func,
831
859
  is_async=False,
832
860
  is_override=is_override,
833
861
  is_static=is_static,
@@ -846,7 +874,7 @@ class JacParser(Pass):
846
874
  """Grammar rule.
847
875
 
848
876
  genai_ability: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? STRING?
849
- any_ref (func_decl) KW_WITH atomic_call SEMI
877
+ any_ref (func_decl) KW_BY atomic_call SEMI
850
878
  """
851
879
  chomp = [*kid]
852
880
  is_override = (
@@ -864,22 +892,19 @@ class JacParser(Pass):
864
892
  chomp = chomp[1:] if semstr else chomp
865
893
  name = chomp[0]
866
894
  chomp = chomp[1:]
867
- is_func = isinstance(chomp[0], ast.FuncSignature)
868
895
  signature = chomp[0]
869
896
  chomp = chomp[1:]
870
- has_with = isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_WITH
871
- chomp = chomp[1:] if has_with else chomp
872
- is_funccall = isinstance(chomp[0], ast.FuncCall)
897
+ has_by = isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_BY
898
+ chomp = chomp[1:] if has_by else chomp
873
899
  if (
874
900
  isinstance(name, ast.NameSpec)
875
901
  and isinstance(signature, (ast.FuncSignature, ast.EventSignature))
876
- and is_funccall
877
- and has_with
902
+ and isinstance(chomp[0], ast.FuncCall)
903
+ and has_by
878
904
  ):
879
905
  return self.nu(
880
906
  ast.Ability(
881
907
  name_ref=name,
882
- is_func=is_func,
883
908
  is_async=False,
884
909
  is_override=is_override,
885
910
  is_static=is_static,
@@ -887,7 +912,7 @@ class JacParser(Pass):
887
912
  access=access,
888
913
  semstr=semstr,
889
914
  signature=signature,
890
- body=chomp[0], # type: ignore
915
+ body=chomp[0],
891
916
  kid=kid,
892
917
  )
893
918
  )
@@ -959,6 +984,7 @@ class JacParser(Pass):
959
984
  """
960
985
  ret = ast.SubNodeList[ast.ParamVar](
961
986
  items=[i for i in kid if isinstance(i, ast.ParamVar)],
987
+ delim=Tok.COMMA,
962
988
  kid=kid,
963
989
  )
964
990
  return self.nu(ret)
@@ -1014,9 +1040,12 @@ class JacParser(Pass):
1014
1040
  """
1015
1041
  ret = ast.SubNodeList[ast.ArchBlockStmt](
1016
1042
  items=[],
1043
+ delim=Tok.WS,
1017
1044
  kid=kid,
1018
1045
  )
1019
1046
  ret.items = [i for i in kid if isinstance(i, ast.ArchBlockStmt)]
1047
+ ret.left_enc = kid[0] if isinstance(kid[0], ast.Token) else None
1048
+ ret.right_enc = kid[-1] if isinstance(kid[-1], ast.Token) else None
1020
1049
  return self.nu(ret)
1021
1050
 
1022
1051
  def member_stmt(self, kid: list[ast.AstNode]) -> ast.ArchBlockStmt:
@@ -1092,6 +1121,7 @@ class JacParser(Pass):
1092
1121
  return self.nu(
1093
1122
  ast.SubNodeList[ast.HasVar](
1094
1123
  items=valid_kid,
1124
+ delim=Tok.COMMA,
1095
1125
  kid=new_kid,
1096
1126
  )
1097
1127
  )
@@ -1161,7 +1191,6 @@ class JacParser(Pass):
1161
1191
  col_end=kid[0].loc.col_end,
1162
1192
  pos_start=kid[0].pos_start,
1163
1193
  pos_end=kid[0].pos_end,
1164
- kid=kid[0].kid,
1165
1194
  )
1166
1195
  )
1167
1196
  else:
@@ -1172,32 +1201,18 @@ class JacParser(Pass):
1172
1201
  ) -> ast.SubNodeList[ast.CodeBlockStmt]:
1173
1202
  """Grammar rule.
1174
1203
 
1175
- code_block: LBRACE statement_list* RBRACE
1176
- """
1177
- if isinstance(kid[1], ast.SubNodeList):
1178
- kid[1].add_kids_left([kid[0]])
1179
- kid[1].add_kids_right([kid[2]])
1180
- return self.nu(kid[1])
1181
- else:
1182
- return self.nu(
1183
- ast.SubNodeList[ast.CodeBlockStmt](
1184
- items=[],
1185
- kid=kid,
1186
- )
1187
- )
1188
-
1189
- def statement_list(
1190
- self, kid: list[ast.AstNode]
1191
- ) -> ast.SubNodeList[ast.CodeBlockStmt]:
1192
- """Grammar rule.
1193
-
1194
- statement_list: statement+
1204
+ code_block: LBRACE statement* RBRACE
1195
1205
  """
1206
+ left_enc = kid[0] if isinstance(kid[0], ast.Token) else None
1207
+ right_enc = kid[-1] if isinstance(kid[-1], ast.Token) else None
1196
1208
  valid_stmt = [i for i in kid if isinstance(i, ast.CodeBlockStmt)]
1197
- if len(valid_stmt) == len(kid):
1209
+ if len(valid_stmt) == len(kid) - 2:
1198
1210
  return self.nu(
1199
1211
  ast.SubNodeList[ast.CodeBlockStmt](
1200
1212
  items=valid_stmt,
1213
+ delim=Tok.WS,
1214
+ left_enc=left_enc,
1215
+ right_enc=right_enc,
1201
1216
  kid=kid,
1202
1217
  )
1203
1218
  )
@@ -1367,6 +1382,7 @@ class JacParser(Pass):
1367
1382
  return self.nu(
1368
1383
  ast.SubNodeList[ast.Except](
1369
1384
  items=valid_kid,
1385
+ delim=Tok.WS,
1370
1386
  kid=kid,
1371
1387
  )
1372
1388
  )
@@ -1515,6 +1531,7 @@ class JacParser(Pass):
1515
1531
  """
1516
1532
  ret = ast.SubNodeList[ast.ExprAsItem](
1517
1533
  items=[i for i in kid if isinstance(i, ast.ExprAsItem)],
1534
+ delim=Tok.COMMA,
1518
1535
  kid=kid,
1519
1536
  )
1520
1537
  return self.nu(ret)
@@ -1737,70 +1754,68 @@ class JacParser(Pass):
1737
1754
  def assignment(self, kid: list[ast.AstNode]) -> ast.Assignment:
1738
1755
  """Grammar rule.
1739
1756
 
1740
- assignment: KW_LET? (atomic_chain EQ)+ (yield_stmt | expression)
1741
- | atomic_chain type_tag (EQ (yield_stmt | expression))?
1742
- | atomic_chain aug_op (yield_stmt | expression)
1757
+ assignment: KW_LET? (atomic_chain EQ)+ (yield_expr | expression)
1758
+ | atomic_chain (COLON STRING)? type_tag (EQ (yield_expr | expression))?
1759
+ | atomic_chain aug_op (yield_expr | expression)
1743
1760
  """
1744
1761
  chomp = [*kid]
1745
1762
  is_frozen = isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_LET
1746
1763
  is_aug = None
1747
1764
  assignees = []
1748
1765
  chomp = chomp[1:] if is_frozen else chomp
1749
- if (
1750
- len(chomp) > 1
1751
- and isinstance(chomp[1], ast.Token)
1752
- and chomp[1].name != Tok.EQ
1753
- ):
1754
- assignees += [chomp[0]]
1755
- is_aug = chomp[1]
1756
- chomp = chomp[2:]
1757
- elif (
1758
- len(chomp) > 1
1759
- and isinstance(chomp[1], ast.Token)
1760
- and chomp[1].name == Tok.EQ
1761
- ):
1762
- while (
1763
- isinstance(chomp[0], ast.Expr)
1764
- and len(chomp) > 1
1765
- and isinstance(chomp[1], ast.Token)
1766
- and chomp[1].name == Tok.EQ
1767
- ):
1768
- assignees += [chomp[0], chomp[1]]
1769
- chomp = chomp[2:]
1770
- elif isinstance(chomp[0], ast.Expr):
1771
- assignees += [chomp[0]]
1772
- chomp = chomp[1:]
1773
- else:
1774
- raise self.ice()
1766
+ value = chomp[-1] if isinstance(chomp[-1], ast.Expr) else None
1767
+ chomp = (
1768
+ chomp[:-2]
1769
+ if value and isinstance(chomp[-3], ast.SubTag)
1770
+ else chomp[:-1] if value else chomp
1771
+ )
1772
+ type_tag = chomp[-1] if isinstance(chomp[-1], ast.SubTag) else None
1773
+ if not value:
1774
+ semstr = chomp[2] if len(chomp) > 2 else None
1775
+ chomp = chomp[:-2] if semstr else chomp
1776
+ else:
1777
+ if type_tag:
1778
+ chomp = chomp[:-1]
1779
+ semstr = (
1780
+ chomp[-1]
1781
+ if len(chomp) > 1 and isinstance(chomp[-1], ast.String)
1782
+ else None
1783
+ )
1784
+ chomp = chomp[:-2] if semstr else chomp
1785
+ else:
1786
+ semstr = None
1787
+ if (
1788
+ isinstance(chomp[1], ast.Token)
1789
+ and chomp[1].name != Tok.EQ
1790
+ and chomp[1].name != Tok.COLON
1791
+ ):
1792
+ assignees += [chomp[0]]
1793
+ is_aug = chomp[1]
1794
+ chomp = chomp[2:]
1795
+ else:
1796
+ while (
1797
+ len(chomp) > 1
1798
+ and isinstance(chomp[0], ast.Expr)
1799
+ and isinstance(chomp[1], ast.Token)
1800
+ and chomp[1].name == Tok.EQ
1801
+ ):
1802
+ assignees += [chomp[0], chomp[1]]
1803
+ chomp = chomp[2:]
1804
+
1805
+ assignees += chomp
1775
1806
  valid_assignees = [i for i in assignees if isinstance(i, (ast.Expr))]
1776
1807
  new_targ = ast.SubNodeList[ast.Expr](
1777
1808
  items=valid_assignees,
1809
+ delim=Tok.EQ,
1778
1810
  kid=assignees,
1779
1811
  )
1780
1812
  kid = [x for x in kid if x not in assignees]
1781
1813
  kid.insert(1, new_targ) if is_frozen else kid.insert(0, new_targ)
1782
- type_tag = (
1783
- chomp[0]
1784
- if len(chomp) > 0 and isinstance(chomp[0], ast.SubTag)
1785
- else None
1786
- )
1787
- chomp = chomp[1:] if type_tag else chomp
1788
- if (
1789
- len(chomp) > 0
1790
- and isinstance(chomp[0], ast.Token)
1791
- and chomp[0].name == Tok.EQ
1792
- ):
1793
- chomp = chomp[1:]
1794
- value = (
1795
- chomp[0]
1796
- if len(chomp) > 0 and isinstance(chomp[0], (ast.YieldExpr, ast.Expr))
1797
- else None
1798
- )
1799
1814
  if is_aug:
1800
1815
  return self.nu(
1801
1816
  ast.Assignment(
1802
1817
  target=new_targ,
1803
- type_tag=type_tag,
1818
+ type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1804
1819
  value=value,
1805
1820
  mutable=is_frozen,
1806
1821
  aug_op=is_aug,
@@ -1810,10 +1825,11 @@ class JacParser(Pass):
1810
1825
  return self.nu(
1811
1826
  ast.Assignment(
1812
1827
  target=new_targ,
1813
- type_tag=type_tag,
1828
+ type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1814
1829
  value=value,
1815
1830
  mutable=is_frozen,
1816
1831
  kid=kid,
1832
+ semstr=semstr if isinstance(semstr, ast.String) else None,
1817
1833
  )
1818
1834
  )
1819
1835
 
@@ -2280,7 +2296,7 @@ class JacParser(Pass):
2280
2296
  target=target,
2281
2297
  right=chomp[0],
2282
2298
  is_null_ok=is_null_ok,
2283
- is_attr=None,
2299
+ is_attr=False,
2284
2300
  kid=kid,
2285
2301
  )
2286
2302
  )
@@ -2295,7 +2311,7 @@ class JacParser(Pass):
2295
2311
  target=(target if chomp[0].name != Tok.DOT_BKWD else chomp[1]),
2296
2312
  right=(chomp[1] if chomp[0].name != Tok.DOT_BKWD else target),
2297
2313
  is_null_ok=is_null_ok,
2298
- is_attr=chomp[0],
2314
+ is_attr=True,
2299
2315
  kid=kid,
2300
2316
  )
2301
2317
  )
@@ -2333,7 +2349,7 @@ class JacParser(Pass):
2333
2349
  expr = index.values.items[0] if index.values else None
2334
2350
  else:
2335
2351
  sublist = ast.SubNodeList[ast.Expr | ast.KWPair](
2336
- items=[*index.values.items], kid=index.kid
2352
+ items=[*index.values.items], delim=Tok.COMMA, kid=index.kid
2337
2353
  )
2338
2354
  expr = ast.TupleVal(values=sublist, kid=[sublist])
2339
2355
  kid = [expr]
@@ -2392,7 +2408,7 @@ class JacParser(Pass):
2392
2408
  and isinstance(kid[1], (ast.Expr, ast.YieldExpr))
2393
2409
  and isinstance(kid[2], ast.Token)
2394
2410
  ):
2395
- ret = ast.AtomUnit(value=kid[1], is_paren=True, kid=kid)
2411
+ ret = ast.AtomUnit(value=kid[1], kid=kid)
2396
2412
  return self.nu(ret)
2397
2413
  else:
2398
2414
  raise self.ice()
@@ -2509,6 +2525,7 @@ class JacParser(Pass):
2509
2525
  return self.nu(
2510
2526
  ast.SubNodeList[ast.String | ast.ExprStmt](
2511
2527
  items=valid_parts,
2528
+ delim=None,
2512
2529
  kid=valid_parts,
2513
2530
  )
2514
2531
  )
@@ -2532,6 +2549,7 @@ class JacParser(Pass):
2532
2549
  return self.nu(
2533
2550
  ast.SubNodeList[ast.String | ast.ExprStmt](
2534
2551
  items=valid_parts,
2552
+ delim=None,
2535
2553
  kid=valid_parts,
2536
2554
  )
2537
2555
  )
@@ -2622,6 +2640,7 @@ class JacParser(Pass):
2622
2640
  return self.nu(
2623
2641
  ast.SubNodeList[ast.Expr](
2624
2642
  items=valid_kid,
2643
+ delim=Tok.COMMA,
2625
2644
  kid=new_kid,
2626
2645
  )
2627
2646
  )
@@ -2646,6 +2665,7 @@ class JacParser(Pass):
2646
2665
  return self.nu(
2647
2666
  ast.SubNodeList[ast.KWPair](
2648
2667
  items=valid_kid,
2668
+ delim=Tok.COMMA,
2649
2669
  kid=new_kid,
2650
2670
  )
2651
2671
  )
@@ -2698,6 +2718,7 @@ class JacParser(Pass):
2698
2718
  return self.nu(
2699
2719
  ast.SubNodeList[ast.Name](
2700
2720
  items=valid_kid,
2721
+ delim=Tok.COMMA,
2701
2722
  kid=new_kid,
2702
2723
  )
2703
2724
  )
@@ -2732,6 +2753,7 @@ class JacParser(Pass):
2732
2753
  return self.nu(
2733
2754
  ast.SubNodeList[ast.Expr | ast.KWPair](
2734
2755
  items=valid_kid,
2756
+ delim=Tok.COMMA,
2735
2757
  kid=kid,
2736
2758
  )
2737
2759
  )
@@ -2847,7 +2869,7 @@ class JacParser(Pass):
2847
2869
  def inner_compr(self, kid: list[ast.AstNode]) -> ast.InnerCompr:
2848
2870
  """Grammar rule.
2849
2871
 
2850
- inner_compr: KW_ASYNC? KW_FOR atomic_chain KW_IN walrus_assign (KW_IF expression)?
2872
+ inner_compr: KW_ASYNC? KW_FOR atomic_chain KW_IN pipe_call (KW_IF walrus_assign)*
2851
2873
  """
2852
2874
  chomp = [*kid]
2853
2875
  is_async = bool(
@@ -2862,7 +2884,7 @@ class JacParser(Pass):
2862
2884
  target=chomp[0],
2863
2885
  collection=chomp[2],
2864
2886
  conditional=(
2865
- chomp[4]
2887
+ [i for i in chomp[4:] if isinstance(i, ast.Expr)]
2866
2888
  if len(chomp) > 4 and isinstance(chomp[4], ast.Expr)
2867
2889
  else None
2868
2890
  ),
@@ -2898,6 +2920,7 @@ class JacParser(Pass):
2898
2920
  return self.nu(
2899
2921
  ast.SubNodeList[ast.Expr | ast.KWPair](
2900
2922
  items=valid_kid,
2923
+ delim=Tok.COMMA,
2901
2924
  kid=kid,
2902
2925
  )
2903
2926
  )
@@ -2927,6 +2950,7 @@ class JacParser(Pass):
2927
2950
  return self.nu(
2928
2951
  ast.SubNodeList[ast.Assignment](
2929
2952
  items=valid_kid,
2953
+ delim=Tok.COMMA,
2930
2954
  kid=new_kid,
2931
2955
  )
2932
2956
  )
@@ -3181,8 +3205,7 @@ class JacParser(Pass):
3181
3205
  def edge_ref_chain(self, kid: list[ast.AstNode]) -> ast.EdgeRefTrailer:
3182
3206
  """Grammar rule.
3183
3207
 
3184
- edge_ref_chain: (EDGE_OP|NODE_OP)? LSQUARE expression?
3185
- (edge_op_ref (NODE_OP? expression)?)+ RSQUARE
3208
+ (EDGE_OP|NODE_OP)? LSQUARE expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
3186
3209
  """
3187
3210
  valid_chain = [i for i in kid if isinstance(i, (ast.Expr, ast.FilterCompr))]
3188
3211
  return self.nu(
@@ -3249,7 +3272,7 @@ class JacParser(Pass):
3249
3272
  def connect_op(self, kid: list[ast.AstNode]) -> ast.ConnectOp:
3250
3273
  """Grammar rule.
3251
3274
 
3252
- connect_op: EDGE_OP? (connect_from | connect_to)
3275
+ connect_op: connect_from | connect_to | connect_any
3253
3276
  """
3254
3277
  if len(kid) < 2 and isinstance(kid[0], ast.ConnectOp):
3255
3278
  return self.nu(kid[0])
@@ -3394,6 +3417,7 @@ class JacParser(Pass):
3394
3417
  return self.nu(
3395
3418
  ast.SubNodeList[ast.CompareExpr](
3396
3419
  items=valid_kid,
3420
+ delim=Tok.COMMA,
3397
3421
  kid=new_kid,
3398
3422
  )
3399
3423
  )
@@ -3434,7 +3458,7 @@ class JacParser(Pass):
3434
3458
  def assign_compr(self, kid: list[ast.AstNode]) -> ast.AssignCompr:
3435
3459
  """Grammar rule.
3436
3460
 
3437
- filter_compr: LPAREN STAR_MUL kw_expr_list RPAREN
3461
+ filter_compr: LPAREN EQ kw_expr_list RPAREN
3438
3462
  """
3439
3463
  if isinstance(kid[2], ast.SubNodeList):
3440
3464
  return self.nu(
@@ -3470,11 +3494,9 @@ class JacParser(Pass):
3470
3494
  """
3471
3495
  pattern = kid[1]
3472
3496
  guard = kid[3] if len(kid) > 4 else None
3473
- stmts = kid[-1]
3474
- if (
3475
- isinstance(pattern, ast.MatchPattern)
3476
- and isinstance(guard, (ast.Expr, type(None)))
3477
- and isinstance(stmts, ast.SubNodeList)
3497
+ stmts = [i for i in kid if isinstance(i, ast.CodeBlockStmt)]
3498
+ if isinstance(pattern, ast.MatchPattern) and isinstance(
3499
+ guard, (ast.Expr, type(None))
3478
3500
  ):
3479
3501
  return self.nu(
3480
3502
  ast.MatchCase(
@@ -3737,6 +3759,7 @@ class JacParser(Pass):
3737
3759
  valid_kid = [i for i in new_kid if isinstance(i, ast.MatchPattern)]
3738
3760
  return ast.SubNodeList[ast.MatchPattern](
3739
3761
  items=valid_kid,
3762
+ delim=Tok.COMMA,
3740
3763
  kid=kid,
3741
3764
  )
3742
3765
 
@@ -3782,6 +3805,7 @@ class JacParser(Pass):
3782
3805
  valid_kid = [i for i in new_kid if isinstance(i, ast.MatchKVPair)]
3783
3806
  return ast.SubNodeList[ast.MatchKVPair](
3784
3807
  items=valid_kid,
3808
+ delim=Tok.COMMA,
3785
3809
  kid=new_kid,
3786
3810
  )
3787
3811
  else:
@@ -3802,7 +3826,6 @@ class JacParser(Pass):
3802
3826
  pos_start=token.start_pos if token.start_pos is not None else 0,
3803
3827
  pos_end=token.end_pos if token.end_pos is not None else 0,
3804
3828
  is_kwesc=True,
3805
- kid=[],
3806
3829
  )
3807
3830
  )
3808
3831
  elif token.type == Tok.NAME:
@@ -3841,6 +3864,5 @@ class JacParser(Pass):
3841
3864
  col_end=token.end_column if token.end_column is not None else 0,
3842
3865
  pos_start=token.start_pos if token.start_pos is not None else 0,
3843
3866
  pos_end=token.end_pos if token.end_pos is not None else 0,
3844
- kid=[],
3845
3867
  )
3846
3868
  )
@@ -68,6 +68,24 @@ class Pass(Transform[ast.T]):
68
68
  result.extend(Pass.get_all_sub_nodes(i, typ, brute_force))
69
69
  return result
70
70
 
71
+ @staticmethod
72
+ def has_parent_of_type(node: ast.AstNode, typ: Type[ast.T]) -> Optional[ast.T]:
73
+ """Check if node has parent of type."""
74
+ while node.parent:
75
+ if isinstance(node.parent, typ):
76
+ return node.parent
77
+ node = node.parent
78
+ return None
79
+
80
+ @staticmethod
81
+ def has_parent_of_node(node: ast.AstNode, parent: ast.AstNode) -> bool:
82
+ """Check if node has parent of type."""
83
+ while node.parent:
84
+ if node.parent == parent:
85
+ return True
86
+ node = node.parent
87
+ return False
88
+
71
89
  def recalculate_parents(self, node: ast.AstNode) -> None:
72
90
  """Recalculate parents."""
73
91
  if not node:
@@ -10,6 +10,7 @@ from .pyast_load_pass import PyastBuildPass # type: ignore # noqa: I100
10
10
  from .pyast_gen_pass import PyastGenPass # noqa: I100
11
11
  from .schedules import py_code_gen # noqa: I100
12
12
  from .type_check_pass import JacTypeCheckPass # noqa: I100
13
+ from .registry_pass import RegistryPass # noqa: I100
13
14
 
14
15
 
15
16
  pass_schedule = py_code_gen
@@ -24,4 +25,5 @@ __all__ = [
24
25
  "PyastBuildPass",
25
26
  "PyastGenPass",
26
27
  "JacTypeCheckPass",
28
+ "RegistryPass",
27
29
  ]