jaclang 0.5.6__py3-none-any.whl → 0.5.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (51) hide show
  1. jaclang/__init__.py +6 -1
  2. jaclang/cli/cli.py +63 -20
  3. jaclang/cli/cmdreg.py +42 -12
  4. jaclang/compiler/__init__.py +6 -3
  5. jaclang/compiler/__jac_gen__/jac_parser.py +2 -2
  6. jaclang/compiler/absyntree.py +1740 -61
  7. jaclang/compiler/codeloc.py +7 -0
  8. jaclang/compiler/compile.py +4 -5
  9. jaclang/compiler/constant.py +52 -6
  10. jaclang/compiler/parser.py +220 -129
  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 +333 -93
  16. jaclang/compiler/passes/main/pyast_load_pass.py +1779 -206
  17. jaclang/compiler/passes/main/pyout_pass.py +2 -2
  18. jaclang/compiler/passes/main/schedules.py +2 -1
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +20 -28
  20. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +4 -4
  21. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +14 -5
  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 +43 -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 +68 -0
  32. jaclang/core/construct.py +58 -6
  33. jaclang/core/importer.py +9 -10
  34. jaclang/core/utils.py +65 -3
  35. jaclang/plugin/builtin.py +42 -0
  36. jaclang/plugin/default.py +163 -18
  37. jaclang/plugin/feature.py +38 -10
  38. jaclang/plugin/spec.py +33 -6
  39. jaclang/utils/helpers.py +25 -0
  40. jaclang/utils/lang_tools.py +4 -1
  41. jaclang/utils/test.py +1 -0
  42. jaclang/utils/tests/test_lang_tools.py +12 -15
  43. jaclang/utils/treeprinter.py +10 -2
  44. {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/METADATA +1 -1
  45. {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/RECORD +48 -46
  46. {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/WHEEL +1 -1
  47. jaclang/compiler/tests/fixtures/__jac_gen__/__init__.py +0 -0
  48. jaclang/compiler/tests/fixtures/__jac_gen__/hello_world.py +0 -5
  49. jaclang/core/jacbuiltins.py +0 -10
  50. {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/entry_points.txt +0 -0
  51. {jaclang-0.5.6.dist-info → jaclang-0.5.8.dist-info}/top_level.txt +0 -0
@@ -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
  )
@@ -570,11 +573,12 @@ class JacParser(Pass):
570
573
  def special_ref(self, kid: list[ast.AstNode]) -> ast.SpecialVarRef:
571
574
  """Grammar rule.
572
575
 
573
- special_ref: INIT_OP
574
- | ROOT_OP
575
- | SUPER_OP
576
- | SELF_OP
577
- | HERE_OP
576
+ special_ref: KW_INIT
577
+ | KW_POST_INIT
578
+ | KW_ROOT
579
+ | KW_SUPER
580
+ | KW_SELF
581
+ | KW_HERE
578
582
  """
579
583
  if isinstance(kid[0], ast.Token):
580
584
  return self.nu(
@@ -595,6 +599,7 @@ class JacParser(Pass):
595
599
  if isinstance(kid[0], (ast.Enum, ast.EnumDef)):
596
600
  return self.nu(kid[0])
597
601
  else:
602
+
598
603
  raise self.ice()
599
604
 
600
605
  def enum_decl(self, kid: list[ast.AstNode]) -> ast.Enum:
@@ -654,44 +659,75 @@ class JacParser(Pass):
654
659
 
655
660
  enum_block: LBRACE ((enum_stmt COMMA)* enum_stmt)? RBRACE
656
661
  """
657
- ret = ast.SubNodeList[ast.EnumBlockStmt](
658
- items=[],
659
- kid=kid,
660
- )
662
+ ret = ast.SubNodeList[ast.EnumBlockStmt](items=[], delim=Tok.COMMA, kid=kid)
661
663
  ret.items = [i for i in kid if isinstance(i, ast.EnumBlockStmt)]
662
664
  return self.nu(ret)
663
665
 
664
666
  def enum_stmt(self, kid: list[ast.AstNode]) -> ast.EnumBlockStmt:
665
667
  """Grammar rule.
666
668
 
667
- enum_stmt: NAME EQ expression
668
- | NAME
669
+ enum_stmt: NAME (COLON STRING)? EQ expression
670
+ | NAME (COLON STRING)?
669
671
  | py_code_block
670
672
  """
671
673
  if isinstance(kid[0], ast.PyInlineCode):
672
674
  return self.nu(kid[0])
673
675
  if isinstance(kid[0], (ast.Name)):
674
- if len(kid) == 1:
675
- kid[0].is_enum_singleton = True
676
- return self.nu(kid[0])
677
- elif isinstance(kid[2], ast.Expr):
678
- 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
+ )
679
709
  kid[0] = targ
680
710
  return self.nu(
681
711
  ast.Assignment(
682
712
  target=targ,
683
- value=kid[2],
713
+ value=None,
684
714
  type_tag=None,
685
715
  kid=kid,
716
+ semstr=semstr,
717
+ is_enum_stmt=True,
686
718
  )
687
719
  )
720
+
688
721
  raise self.ice()
689
722
 
690
- def ability(self, kid: list[ast.AstNode]) -> ast.Ability | ast.AbilityDef:
691
- """Grammar rule.
723
+ def ability(
724
+ self, kid: list[ast.AstNode]
725
+ ) -> ast.Ability | ast.AbilityDef | ast.FuncCall:
726
+ """Grammer rule.
692
727
 
693
728
  ability: decorators? ability_def
694
729
  | decorators? KW_ASYNC? ability_decl
730
+ | decorators? genai_ability
695
731
  """
696
732
  chomp = [*kid]
697
733
  decorators = chomp[0] if isinstance(chomp[0], ast.SubNodeList) else None
@@ -744,7 +780,6 @@ class JacParser(Pass):
744
780
  chomp = chomp[1:] if semstr else chomp
745
781
  name = chomp[0]
746
782
  chomp = chomp[1:]
747
- is_func = isinstance(chomp[0], ast.FuncSignature)
748
783
  signature = chomp[0]
749
784
  chomp = chomp[1:]
750
785
  body = chomp[0] if isinstance(chomp[0], ast.SubNodeList) else None
@@ -754,7 +789,6 @@ class JacParser(Pass):
754
789
  return self.nu(
755
790
  ast.Ability(
756
791
  name_ref=name,
757
- is_func=is_func,
758
792
  is_async=False,
759
793
  is_override=is_override,
760
794
  is_static=is_static,
@@ -790,6 +824,8 @@ class JacParser(Pass):
790
824
  else:
791
825
  raise self.ice()
792
826
 
827
+ # We need separate production rule for abstract_ability because we don't
828
+ # want to allow regular abilities outside of classed to be abstract.
793
829
  def abstract_ability(self, kid: list[ast.AstNode]) -> ast.Ability:
794
830
  """Grammar rule.
795
831
 
@@ -812,7 +848,6 @@ class JacParser(Pass):
812
848
  chomp = chomp[1:] if semstr else chomp
813
849
  name = chomp[0]
814
850
  chomp = chomp[1:]
815
- is_func = isinstance(chomp[0], ast.FuncSignature)
816
851
  signature = chomp[0]
817
852
  chomp = chomp[1:]
818
853
  if isinstance(name, ast.NameSpec) and isinstance(
@@ -821,7 +856,6 @@ class JacParser(Pass):
821
856
  return self.nu(
822
857
  ast.Ability(
823
858
  name_ref=name,
824
- is_func=is_func,
825
859
  is_async=False,
826
860
  is_override=is_override,
827
861
  is_static=is_static,
@@ -836,6 +870,55 @@ class JacParser(Pass):
836
870
  else:
837
871
  raise self.ice()
838
872
 
873
+ def genai_ability(self, kid: list[ast.AstNode]) -> ast.Ability:
874
+ """Grammar rule.
875
+
876
+ genai_ability: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? STRING?
877
+ any_ref (func_decl) KW_BY atomic_call SEMI
878
+ """
879
+ chomp = [*kid]
880
+ is_override = (
881
+ isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_OVERRIDE
882
+ )
883
+ chomp = chomp[1:] if is_override else chomp
884
+ is_static = (
885
+ isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_STATIC
886
+ )
887
+ chomp = chomp[1:] if is_static else chomp
888
+ chomp = chomp[1:]
889
+ access = chomp[0] if isinstance(chomp[0], ast.SubTag) else None
890
+ chomp = chomp[1:] if access else chomp
891
+ semstr = chomp[0] if isinstance(chomp[0], ast.String) else None
892
+ chomp = chomp[1:] if semstr else chomp
893
+ name = chomp[0]
894
+ chomp = chomp[1:]
895
+ signature = chomp[0]
896
+ chomp = chomp[1:]
897
+ has_by = isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_BY
898
+ chomp = chomp[1:] if has_by else chomp
899
+ if (
900
+ isinstance(name, ast.NameSpec)
901
+ and isinstance(signature, (ast.FuncSignature, ast.EventSignature))
902
+ and isinstance(chomp[0], ast.FuncCall)
903
+ and has_by
904
+ ):
905
+ return self.nu(
906
+ ast.Ability(
907
+ name_ref=name,
908
+ is_async=False,
909
+ is_override=is_override,
910
+ is_static=is_static,
911
+ is_abstract=False,
912
+ access=access,
913
+ semstr=semstr,
914
+ signature=signature,
915
+ body=chomp[0],
916
+ kid=kid,
917
+ )
918
+ )
919
+ else:
920
+ raise self.ice()
921
+
839
922
  def event_clause(self, kid: list[ast.AstNode]) -> ast.EventSignature:
840
923
  """Grammar rule.
841
924
 
@@ -865,7 +948,7 @@ class JacParser(Pass):
865
948
  def func_decl(self, kid: list[ast.AstNode]) -> ast.FuncSignature:
866
949
  """Grammar rule.
867
950
 
868
- func_decl: (LPAREN func_decl_params? RPAREN)? (STRING? RETURN_HINT expression)?
951
+ func_decl: (LPAREN func_decl_params? RPAREN)? (RETURN_HINT (STRING COLON)? expression)?
869
952
  """
870
953
  params = (
871
954
  kid[1] if len(kid) > 1 and isinstance(kid[1], ast.SubNodeList) else None
@@ -875,7 +958,7 @@ class JacParser(Pass):
875
958
  )
876
959
  semstr = (
877
960
  kid[-3]
878
- if return_spec and len(kid) > 2 and isinstance(kid[-3], ast.String)
961
+ if return_spec and len(kid) > 3 and isinstance(kid[-3], ast.String)
879
962
  else None
880
963
  )
881
964
  if (isinstance(params, ast.SubNodeList) or params is None) and (
@@ -901,6 +984,7 @@ class JacParser(Pass):
901
984
  """
902
985
  ret = ast.SubNodeList[ast.ParamVar](
903
986
  items=[i for i in kid if isinstance(i, ast.ParamVar)],
987
+ delim=Tok.COMMA,
904
988
  kid=kid,
905
989
  )
906
990
  return self.nu(ret)
@@ -908,7 +992,7 @@ class JacParser(Pass):
908
992
  def param_var(self, kid: list[ast.AstNode]) -> ast.ParamVar:
909
993
  """Grammar rule.
910
994
 
911
- param_var: (STAR_POW | STAR_MUL)? STRING? NAME type_tag (EQ expression)?
995
+ param_var: (STAR_POW | STAR_MUL)? NAME (COLON STRING)? type_tag (EQ expression)?
912
996
  """
913
997
  star = (
914
998
  kid[0]
@@ -917,18 +1001,22 @@ class JacParser(Pass):
917
1001
  and not isinstance(kid[0], ast.String)
918
1002
  else None
919
1003
  )
1004
+ name = kid[1] if (star) else kid[0]
1005
+ value = kid[-1] if isinstance(kid[-1], ast.Expr) else None
1006
+ type_tag = kid[-3] if value else kid[-1]
920
1007
  semstr = (
921
- kid[1]
922
- if (star and isinstance(kid[1], ast.String))
923
- else kid[0] if isinstance(kid[0], ast.String) else None
924
- )
925
- name = (
926
- kid[2] if (star and semstr) else kid[1] if (star or semstr) else kid[0]
927
- )
928
- type_tag = (
929
- kid[3] if (star and semstr) else kid[2] if (star or semstr) else kid[1]
1008
+ kid[3]
1009
+ if star and len(kid) > 3 and isinstance(kid[3], ast.String)
1010
+ else (
1011
+ kid[2]
1012
+ if len(kid) > 4 and value and isinstance(kid[2], ast.String)
1013
+ else (
1014
+ kid[2]
1015
+ if len(kid) > 2 and isinstance(kid[2], ast.String)
1016
+ else None
1017
+ )
1018
+ )
930
1019
  )
931
- value = kid[-1] if isinstance(kid[-1], ast.Expr) else None
932
1020
  if isinstance(name, ast.Name) and isinstance(type_tag, ast.SubTag):
933
1021
  return self.nu(
934
1022
  ast.ParamVar(
@@ -952,9 +1040,12 @@ class JacParser(Pass):
952
1040
  """
953
1041
  ret = ast.SubNodeList[ast.ArchBlockStmt](
954
1042
  items=[],
1043
+ delim=Tok.WS,
955
1044
  kid=kid,
956
1045
  )
957
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
958
1049
  return self.nu(ret)
959
1050
 
960
1051
  def member_stmt(self, kid: list[ast.AstNode]) -> ast.ArchBlockStmt:
@@ -1030,6 +1121,7 @@ class JacParser(Pass):
1030
1121
  return self.nu(
1031
1122
  ast.SubNodeList[ast.HasVar](
1032
1123
  items=valid_kid,
1124
+ delim=Tok.COMMA,
1033
1125
  kid=new_kid,
1034
1126
  )
1035
1127
  )
@@ -1037,12 +1129,12 @@ class JacParser(Pass):
1037
1129
  def typed_has_clause(self, kid: list[ast.AstNode]) -> ast.HasVar:
1038
1130
  """Grammar rule.
1039
1131
 
1040
- typed_has_clause: STRING? named_ref type_tag (EQ expression | KW_BY POST_INIT_OP)?
1132
+ typed_has_clause: named_ref (COLON STRING)? type_tag (EQ expression | KW_BY KW_POST_INIT)?
1041
1133
  """
1042
- semstr = kid[0] if isinstance(kid[0], ast.String) else None
1043
- name = kid[1] if semstr else kid[0]
1044
- type_tag = kid[2] if semstr else kid[1]
1045
- defer = isinstance(kid[-1], ast.Token) and kid[-1].name == Tok.POST_INIT_OP
1134
+ name = kid[0]
1135
+ semstr = kid[2] if len(kid) > 2 and isinstance(kid[2], ast.String) else None
1136
+ type_tag = kid[3] if semstr else kid[1]
1137
+ defer = isinstance(kid[-1], ast.Token) and kid[-1].name == Tok.KW_POST_INIT
1046
1138
  value = kid[-1] if not defer and isinstance(kid[-1], ast.Expr) else None
1047
1139
  if isinstance(name, ast.Name) and isinstance(type_tag, ast.SubTag):
1048
1140
  return self.nu(
@@ -1099,7 +1191,6 @@ class JacParser(Pass):
1099
1191
  col_end=kid[0].loc.col_end,
1100
1192
  pos_start=kid[0].pos_start,
1101
1193
  pos_end=kid[0].pos_end,
1102
- kid=kid[0].kid,
1103
1194
  )
1104
1195
  )
1105
1196
  else:
@@ -1110,32 +1201,18 @@ class JacParser(Pass):
1110
1201
  ) -> ast.SubNodeList[ast.CodeBlockStmt]:
1111
1202
  """Grammar rule.
1112
1203
 
1113
- code_block: LBRACE statement_list* RBRACE
1114
- """
1115
- if isinstance(kid[1], ast.SubNodeList):
1116
- kid[1].add_kids_left([kid[0]])
1117
- kid[1].add_kids_right([kid[2]])
1118
- return self.nu(kid[1])
1119
- else:
1120
- return self.nu(
1121
- ast.SubNodeList[ast.CodeBlockStmt](
1122
- items=[],
1123
- kid=kid,
1124
- )
1125
- )
1126
-
1127
- def statement_list(
1128
- self, kid: list[ast.AstNode]
1129
- ) -> ast.SubNodeList[ast.CodeBlockStmt]:
1130
- """Grammar rule.
1131
-
1132
- statement_list: statement+
1204
+ code_block: LBRACE statement* RBRACE
1133
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
1134
1208
  valid_stmt = [i for i in kid if isinstance(i, ast.CodeBlockStmt)]
1135
- if len(valid_stmt) == len(kid):
1209
+ if len(valid_stmt) == len(kid) - 2:
1136
1210
  return self.nu(
1137
1211
  ast.SubNodeList[ast.CodeBlockStmt](
1138
1212
  items=valid_stmt,
1213
+ delim=Tok.WS,
1214
+ left_enc=left_enc,
1215
+ right_enc=right_enc,
1139
1216
  kid=kid,
1140
1217
  )
1141
1218
  )
@@ -1305,6 +1382,7 @@ class JacParser(Pass):
1305
1382
  return self.nu(
1306
1383
  ast.SubNodeList[ast.Except](
1307
1384
  items=valid_kid,
1385
+ delim=Tok.WS,
1308
1386
  kid=kid,
1309
1387
  )
1310
1388
  )
@@ -1453,6 +1531,7 @@ class JacParser(Pass):
1453
1531
  """
1454
1532
  ret = ast.SubNodeList[ast.ExprAsItem](
1455
1533
  items=[i for i in kid if isinstance(i, ast.ExprAsItem)],
1534
+ delim=Tok.COMMA,
1456
1535
  kid=kid,
1457
1536
  )
1458
1537
  return self.nu(ret)
@@ -1675,70 +1754,66 @@ class JacParser(Pass):
1675
1754
  def assignment(self, kid: list[ast.AstNode]) -> ast.Assignment:
1676
1755
  """Grammar rule.
1677
1756
 
1678
- assignment: KW_LET? (atomic_chain EQ)+ (yield_stmt | expression)
1679
- | atomic_chain type_tag (EQ (yield_stmt | expression))?
1680
- | 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)
1681
1760
  """
1682
1761
  chomp = [*kid]
1683
1762
  is_frozen = isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_LET
1684
1763
  is_aug = None
1685
1764
  assignees = []
1686
1765
  chomp = chomp[1:] if is_frozen else chomp
1687
- if (
1688
- len(chomp) > 1
1689
- and isinstance(chomp[1], ast.Token)
1690
- and chomp[1].name != Tok.EQ
1691
- ):
1692
- assignees += [chomp[0]]
1693
- is_aug = chomp[1]
1694
- chomp = chomp[2:]
1695
- elif (
1696
- len(chomp) > 1
1697
- and isinstance(chomp[1], ast.Token)
1698
- and chomp[1].name == Tok.EQ
1699
- ):
1700
- while (
1701
- isinstance(chomp[0], ast.Expr)
1702
- and len(chomp) > 1
1703
- and isinstance(chomp[1], ast.Token)
1704
- and chomp[1].name == Tok.EQ
1705
- ):
1706
- assignees += [chomp[0], chomp[1]]
1707
- chomp = chomp[2:]
1708
- elif isinstance(chomp[0], ast.Expr):
1709
- assignees += [chomp[0]]
1710
- chomp = chomp[1:]
1711
- else:
1712
- 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
+ else:
1776
+ if type_tag:
1777
+ chomp = chomp[:-1]
1778
+ semstr = (
1779
+ chomp[-1]
1780
+ if len(chomp) > 1 and isinstance(chomp[-1], ast.String)
1781
+ else None
1782
+ )
1783
+ chomp = chomp[:-2] if semstr else chomp
1784
+ else:
1785
+ if (
1786
+ isinstance(chomp[1], ast.Token)
1787
+ and chomp[1].name != Tok.EQ
1788
+ and chomp[1].name != Tok.COLON
1789
+ ):
1790
+ assignees += [chomp[0]]
1791
+ is_aug = chomp[1]
1792
+ chomp = chomp[2:]
1793
+ else:
1794
+ while (
1795
+ len(chomp) > 1
1796
+ and isinstance(chomp[0], ast.Expr)
1797
+ and isinstance(chomp[1], ast.Token)
1798
+ and chomp[1].name == Tok.EQ
1799
+ ):
1800
+ assignees += [chomp[0], chomp[1]]
1801
+ chomp = chomp[2:]
1802
+
1803
+ assignees += chomp
1713
1804
  valid_assignees = [i for i in assignees if isinstance(i, (ast.Expr))]
1714
1805
  new_targ = ast.SubNodeList[ast.Expr](
1715
1806
  items=valid_assignees,
1807
+ delim=Tok.EQ,
1716
1808
  kid=assignees,
1717
1809
  )
1718
1810
  kid = [x for x in kid if x not in assignees]
1719
1811
  kid.insert(1, new_targ) if is_frozen else kid.insert(0, new_targ)
1720
- type_tag = (
1721
- chomp[0]
1722
- if len(chomp) > 0 and isinstance(chomp[0], ast.SubTag)
1723
- else None
1724
- )
1725
- chomp = chomp[1:] if type_tag else chomp
1726
- if (
1727
- len(chomp) > 0
1728
- and isinstance(chomp[0], ast.Token)
1729
- and chomp[0].name == Tok.EQ
1730
- ):
1731
- chomp = chomp[1:]
1732
- value = (
1733
- chomp[0]
1734
- if len(chomp) > 0 and isinstance(chomp[0], (ast.YieldExpr, ast.Expr))
1735
- else None
1736
- )
1737
1812
  if is_aug:
1738
1813
  return self.nu(
1739
1814
  ast.Assignment(
1740
1815
  target=new_targ,
1741
- type_tag=type_tag,
1816
+ type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1742
1817
  value=value,
1743
1818
  mutable=is_frozen,
1744
1819
  aug_op=is_aug,
@@ -1748,7 +1823,7 @@ class JacParser(Pass):
1748
1823
  return self.nu(
1749
1824
  ast.Assignment(
1750
1825
  target=new_targ,
1751
- type_tag=type_tag,
1826
+ type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1752
1827
  value=value,
1753
1828
  mutable=is_frozen,
1754
1829
  kid=kid,
@@ -2218,7 +2293,7 @@ class JacParser(Pass):
2218
2293
  target=target,
2219
2294
  right=chomp[0],
2220
2295
  is_null_ok=is_null_ok,
2221
- is_attr=None,
2296
+ is_attr=False,
2222
2297
  kid=kid,
2223
2298
  )
2224
2299
  )
@@ -2233,7 +2308,7 @@ class JacParser(Pass):
2233
2308
  target=(target if chomp[0].name != Tok.DOT_BKWD else chomp[1]),
2234
2309
  right=(chomp[1] if chomp[0].name != Tok.DOT_BKWD else target),
2235
2310
  is_null_ok=is_null_ok,
2236
- is_attr=chomp[0],
2311
+ is_attr=True,
2237
2312
  kid=kid,
2238
2313
  )
2239
2314
  )
@@ -2265,14 +2340,23 @@ class JacParser(Pass):
2265
2340
  if len(kid) == 1:
2266
2341
  index = kid[0]
2267
2342
  if isinstance(index, ast.ListVal):
2268
- expr = index.values.items[0] if index.values else None
2343
+ if not index.values:
2344
+ raise self.ice()
2345
+ if len(index.values.items) == 1:
2346
+ expr = index.values.items[0] if index.values else None
2347
+ else:
2348
+ sublist = ast.SubNodeList[ast.Expr | ast.KWPair](
2349
+ items=[*index.values.items], delim=Tok.COMMA, kid=index.kid
2350
+ )
2351
+ expr = ast.TupleVal(values=sublist, kid=[sublist])
2352
+ kid = [expr]
2269
2353
  return self.nu(
2270
2354
  ast.IndexSlice(
2271
2355
  start=expr,
2272
2356
  stop=None,
2273
2357
  step=None,
2274
2358
  is_range=False,
2275
- kid=kid[0].kid,
2359
+ kid=kid,
2276
2360
  )
2277
2361
  )
2278
2362
  else:
@@ -2321,7 +2405,7 @@ class JacParser(Pass):
2321
2405
  and isinstance(kid[1], (ast.Expr, ast.YieldExpr))
2322
2406
  and isinstance(kid[2], ast.Token)
2323
2407
  ):
2324
- ret = ast.AtomUnit(value=kid[1], is_paren=True, kid=kid)
2408
+ ret = ast.AtomUnit(value=kid[1], kid=kid)
2325
2409
  return self.nu(ret)
2326
2410
  else:
2327
2411
  raise self.ice()
@@ -2438,6 +2522,7 @@ class JacParser(Pass):
2438
2522
  return self.nu(
2439
2523
  ast.SubNodeList[ast.String | ast.ExprStmt](
2440
2524
  items=valid_parts,
2525
+ delim=None,
2441
2526
  kid=valid_parts,
2442
2527
  )
2443
2528
  )
@@ -2461,6 +2546,7 @@ class JacParser(Pass):
2461
2546
  return self.nu(
2462
2547
  ast.SubNodeList[ast.String | ast.ExprStmt](
2463
2548
  items=valid_parts,
2549
+ delim=None,
2464
2550
  kid=valid_parts,
2465
2551
  )
2466
2552
  )
@@ -2551,6 +2637,7 @@ class JacParser(Pass):
2551
2637
  return self.nu(
2552
2638
  ast.SubNodeList[ast.Expr](
2553
2639
  items=valid_kid,
2640
+ delim=Tok.COMMA,
2554
2641
  kid=new_kid,
2555
2642
  )
2556
2643
  )
@@ -2575,6 +2662,7 @@ class JacParser(Pass):
2575
2662
  return self.nu(
2576
2663
  ast.SubNodeList[ast.KWPair](
2577
2664
  items=valid_kid,
2665
+ delim=Tok.COMMA,
2578
2666
  kid=new_kid,
2579
2667
  )
2580
2668
  )
@@ -2627,6 +2715,7 @@ class JacParser(Pass):
2627
2715
  return self.nu(
2628
2716
  ast.SubNodeList[ast.Name](
2629
2717
  items=valid_kid,
2718
+ delim=Tok.COMMA,
2630
2719
  kid=new_kid,
2631
2720
  )
2632
2721
  )
@@ -2661,6 +2750,7 @@ class JacParser(Pass):
2661
2750
  return self.nu(
2662
2751
  ast.SubNodeList[ast.Expr | ast.KWPair](
2663
2752
  items=valid_kid,
2753
+ delim=Tok.COMMA,
2664
2754
  kid=kid,
2665
2755
  )
2666
2756
  )
@@ -2776,7 +2866,7 @@ class JacParser(Pass):
2776
2866
  def inner_compr(self, kid: list[ast.AstNode]) -> ast.InnerCompr:
2777
2867
  """Grammar rule.
2778
2868
 
2779
- inner_compr: KW_ASYNC? KW_FOR atomic_chain KW_IN walrus_assign (KW_IF expression)?
2869
+ inner_compr: KW_ASYNC? KW_FOR atomic_chain KW_IN pipe_call (KW_IF walrus_assign)*
2780
2870
  """
2781
2871
  chomp = [*kid]
2782
2872
  is_async = bool(
@@ -2791,7 +2881,7 @@ class JacParser(Pass):
2791
2881
  target=chomp[0],
2792
2882
  collection=chomp[2],
2793
2883
  conditional=(
2794
- chomp[4]
2884
+ [i for i in chomp[4:] if isinstance(i, ast.Expr)]
2795
2885
  if len(chomp) > 4 and isinstance(chomp[4], ast.Expr)
2796
2886
  else None
2797
2887
  ),
@@ -2827,6 +2917,7 @@ class JacParser(Pass):
2827
2917
  return self.nu(
2828
2918
  ast.SubNodeList[ast.Expr | ast.KWPair](
2829
2919
  items=valid_kid,
2920
+ delim=Tok.COMMA,
2830
2921
  kid=kid,
2831
2922
  )
2832
2923
  )
@@ -2856,6 +2947,7 @@ class JacParser(Pass):
2856
2947
  return self.nu(
2857
2948
  ast.SubNodeList[ast.Assignment](
2858
2949
  items=valid_kid,
2950
+ delim=Tok.COMMA,
2859
2951
  kid=new_kid,
2860
2952
  )
2861
2953
  )
@@ -3110,9 +3202,9 @@ class JacParser(Pass):
3110
3202
  def edge_ref_chain(self, kid: list[ast.AstNode]) -> ast.EdgeRefTrailer:
3111
3203
  """Grammar rule.
3112
3204
 
3113
- edge_ref_chain: (EDGE_OP|NODE_OP)? LSQUARE expression? (edge_op_ref expression?)+ RSQUARE
3205
+ (EDGE_OP|NODE_OP)? LSQUARE expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
3114
3206
  """
3115
- valid_chain = [i for i in kid if isinstance(i, (ast.Expr))]
3207
+ valid_chain = [i for i in kid if isinstance(i, (ast.Expr, ast.FilterCompr))]
3116
3208
  return self.nu(
3117
3209
  ast.EdgeRefTrailer(
3118
3210
  chain=valid_chain,
@@ -3177,7 +3269,7 @@ class JacParser(Pass):
3177
3269
  def connect_op(self, kid: list[ast.AstNode]) -> ast.ConnectOp:
3178
3270
  """Grammar rule.
3179
3271
 
3180
- connect_op: EDGE_OP? (connect_from | connect_to)
3272
+ connect_op: connect_from | connect_to | connect_any
3181
3273
  """
3182
3274
  if len(kid) < 2 and isinstance(kid[0], ast.ConnectOp):
3183
3275
  return self.nu(kid[0])
@@ -3322,6 +3414,7 @@ class JacParser(Pass):
3322
3414
  return self.nu(
3323
3415
  ast.SubNodeList[ast.CompareExpr](
3324
3416
  items=valid_kid,
3417
+ delim=Tok.COMMA,
3325
3418
  kid=new_kid,
3326
3419
  )
3327
3420
  )
@@ -3362,7 +3455,7 @@ class JacParser(Pass):
3362
3455
  def assign_compr(self, kid: list[ast.AstNode]) -> ast.AssignCompr:
3363
3456
  """Grammar rule.
3364
3457
 
3365
- filter_compr: LPAREN STAR_MUL kw_expr_list RPAREN
3458
+ filter_compr: LPAREN EQ kw_expr_list RPAREN
3366
3459
  """
3367
3460
  if isinstance(kid[2], ast.SubNodeList):
3368
3461
  return self.nu(
@@ -3398,11 +3491,9 @@ class JacParser(Pass):
3398
3491
  """
3399
3492
  pattern = kid[1]
3400
3493
  guard = kid[3] if len(kid) > 4 else None
3401
- stmts = kid[-1]
3402
- if (
3403
- isinstance(pattern, ast.MatchPattern)
3404
- and isinstance(guard, (ast.Expr, type(None)))
3405
- and isinstance(stmts, ast.SubNodeList)
3494
+ stmts = [i for i in kid if isinstance(i, ast.CodeBlockStmt)]
3495
+ if isinstance(pattern, ast.MatchPattern) and isinstance(
3496
+ guard, (ast.Expr, type(None))
3406
3497
  ):
3407
3498
  return self.nu(
3408
3499
  ast.MatchCase(
@@ -3665,6 +3756,7 @@ class JacParser(Pass):
3665
3756
  valid_kid = [i for i in new_kid if isinstance(i, ast.MatchPattern)]
3666
3757
  return ast.SubNodeList[ast.MatchPattern](
3667
3758
  items=valid_kid,
3759
+ delim=Tok.COMMA,
3668
3760
  kid=kid,
3669
3761
  )
3670
3762
 
@@ -3710,6 +3802,7 @@ class JacParser(Pass):
3710
3802
  valid_kid = [i for i in new_kid if isinstance(i, ast.MatchKVPair)]
3711
3803
  return ast.SubNodeList[ast.MatchKVPair](
3712
3804
  items=valid_kid,
3805
+ delim=Tok.COMMA,
3713
3806
  kid=new_kid,
3714
3807
  )
3715
3808
  else:
@@ -3730,7 +3823,6 @@ class JacParser(Pass):
3730
3823
  pos_start=token.start_pos if token.start_pos is not None else 0,
3731
3824
  pos_end=token.end_pos if token.end_pos is not None else 0,
3732
3825
  is_kwesc=True,
3733
- kid=[],
3734
3826
  )
3735
3827
  )
3736
3828
  elif token.type == Tok.NAME:
@@ -3769,6 +3861,5 @@ class JacParser(Pass):
3769
3861
  col_end=token.end_column if token.end_column is not None else 0,
3770
3862
  pos_start=token.start_pos if token.start_pos is not None else 0,
3771
3863
  pos_end=token.end_pos if token.end_pos is not None else 0,
3772
- kid=[],
3773
3864
  )
3774
3865
  )