jaclang 0.5.7__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 (41) hide show
  1. jaclang/cli/cli.py +55 -7
  2. jaclang/cli/cmdreg.py +12 -0
  3. jaclang/compiler/__init__.py +6 -3
  4. jaclang/compiler/__jac_gen__/jac_parser.py +2 -2
  5. jaclang/compiler/absyntree.py +1725 -55
  6. jaclang/compiler/codeloc.py +7 -0
  7. jaclang/compiler/compile.py +1 -1
  8. jaclang/compiler/constant.py +17 -0
  9. jaclang/compiler/parser.py +131 -112
  10. jaclang/compiler/passes/main/def_impl_match_pass.py +19 -3
  11. jaclang/compiler/passes/main/def_use_pass.py +1 -1
  12. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +357 -0
  13. jaclang/compiler/passes/main/import_pass.py +7 -3
  14. jaclang/compiler/passes/main/pyast_gen_pass.py +112 -76
  15. jaclang/compiler/passes/main/pyast_load_pass.py +1779 -206
  16. jaclang/compiler/passes/main/schedules.py +2 -1
  17. jaclang/compiler/passes/main/sym_tab_build_pass.py +20 -28
  18. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +14 -5
  19. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +8 -8
  20. jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +7 -0
  21. jaclang/compiler/passes/main/type_check_pass.py +0 -1
  22. jaclang/compiler/passes/tool/jac_formatter_pass.py +8 -17
  23. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +43 -0
  24. jaclang/compiler/passes/utils/mypy_ast_build.py +28 -14
  25. jaclang/compiler/symtable.py +23 -2
  26. jaclang/compiler/tests/test_parser.py +53 -0
  27. jaclang/compiler/workspace.py +52 -26
  28. jaclang/core/construct.py +54 -2
  29. jaclang/plugin/default.py +51 -13
  30. jaclang/plugin/feature.py +16 -2
  31. jaclang/plugin/spec.py +9 -5
  32. jaclang/utils/helpers.py +25 -0
  33. jaclang/utils/lang_tools.py +4 -1
  34. jaclang/utils/test.py +1 -0
  35. jaclang/utils/tests/test_lang_tools.py +11 -14
  36. jaclang/utils/treeprinter.py +10 -2
  37. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/METADATA +1 -1
  38. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/RECORD +41 -38
  39. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/WHEEL +1 -1
  40. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/entry_points.txt +0 -0
  41. {jaclang-0.5.7.dist-info → jaclang-0.5.8.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,66 @@ 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
+ 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
1775
1804
  valid_assignees = [i for i in assignees if isinstance(i, (ast.Expr))]
1776
1805
  new_targ = ast.SubNodeList[ast.Expr](
1777
1806
  items=valid_assignees,
1807
+ delim=Tok.EQ,
1778
1808
  kid=assignees,
1779
1809
  )
1780
1810
  kid = [x for x in kid if x not in assignees]
1781
1811
  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
1812
  if is_aug:
1800
1813
  return self.nu(
1801
1814
  ast.Assignment(
1802
1815
  target=new_targ,
1803
- type_tag=type_tag,
1816
+ type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1804
1817
  value=value,
1805
1818
  mutable=is_frozen,
1806
1819
  aug_op=is_aug,
@@ -1810,7 +1823,7 @@ class JacParser(Pass):
1810
1823
  return self.nu(
1811
1824
  ast.Assignment(
1812
1825
  target=new_targ,
1813
- type_tag=type_tag,
1826
+ type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1814
1827
  value=value,
1815
1828
  mutable=is_frozen,
1816
1829
  kid=kid,
@@ -2280,7 +2293,7 @@ class JacParser(Pass):
2280
2293
  target=target,
2281
2294
  right=chomp[0],
2282
2295
  is_null_ok=is_null_ok,
2283
- is_attr=None,
2296
+ is_attr=False,
2284
2297
  kid=kid,
2285
2298
  )
2286
2299
  )
@@ -2295,7 +2308,7 @@ class JacParser(Pass):
2295
2308
  target=(target if chomp[0].name != Tok.DOT_BKWD else chomp[1]),
2296
2309
  right=(chomp[1] if chomp[0].name != Tok.DOT_BKWD else target),
2297
2310
  is_null_ok=is_null_ok,
2298
- is_attr=chomp[0],
2311
+ is_attr=True,
2299
2312
  kid=kid,
2300
2313
  )
2301
2314
  )
@@ -2333,7 +2346,7 @@ class JacParser(Pass):
2333
2346
  expr = index.values.items[0] if index.values else None
2334
2347
  else:
2335
2348
  sublist = ast.SubNodeList[ast.Expr | ast.KWPair](
2336
- items=[*index.values.items], kid=index.kid
2349
+ items=[*index.values.items], delim=Tok.COMMA, kid=index.kid
2337
2350
  )
2338
2351
  expr = ast.TupleVal(values=sublist, kid=[sublist])
2339
2352
  kid = [expr]
@@ -2392,7 +2405,7 @@ class JacParser(Pass):
2392
2405
  and isinstance(kid[1], (ast.Expr, ast.YieldExpr))
2393
2406
  and isinstance(kid[2], ast.Token)
2394
2407
  ):
2395
- ret = ast.AtomUnit(value=kid[1], is_paren=True, kid=kid)
2408
+ ret = ast.AtomUnit(value=kid[1], kid=kid)
2396
2409
  return self.nu(ret)
2397
2410
  else:
2398
2411
  raise self.ice()
@@ -2509,6 +2522,7 @@ class JacParser(Pass):
2509
2522
  return self.nu(
2510
2523
  ast.SubNodeList[ast.String | ast.ExprStmt](
2511
2524
  items=valid_parts,
2525
+ delim=None,
2512
2526
  kid=valid_parts,
2513
2527
  )
2514
2528
  )
@@ -2532,6 +2546,7 @@ class JacParser(Pass):
2532
2546
  return self.nu(
2533
2547
  ast.SubNodeList[ast.String | ast.ExprStmt](
2534
2548
  items=valid_parts,
2549
+ delim=None,
2535
2550
  kid=valid_parts,
2536
2551
  )
2537
2552
  )
@@ -2622,6 +2637,7 @@ class JacParser(Pass):
2622
2637
  return self.nu(
2623
2638
  ast.SubNodeList[ast.Expr](
2624
2639
  items=valid_kid,
2640
+ delim=Tok.COMMA,
2625
2641
  kid=new_kid,
2626
2642
  )
2627
2643
  )
@@ -2646,6 +2662,7 @@ class JacParser(Pass):
2646
2662
  return self.nu(
2647
2663
  ast.SubNodeList[ast.KWPair](
2648
2664
  items=valid_kid,
2665
+ delim=Tok.COMMA,
2649
2666
  kid=new_kid,
2650
2667
  )
2651
2668
  )
@@ -2698,6 +2715,7 @@ class JacParser(Pass):
2698
2715
  return self.nu(
2699
2716
  ast.SubNodeList[ast.Name](
2700
2717
  items=valid_kid,
2718
+ delim=Tok.COMMA,
2701
2719
  kid=new_kid,
2702
2720
  )
2703
2721
  )
@@ -2732,6 +2750,7 @@ class JacParser(Pass):
2732
2750
  return self.nu(
2733
2751
  ast.SubNodeList[ast.Expr | ast.KWPair](
2734
2752
  items=valid_kid,
2753
+ delim=Tok.COMMA,
2735
2754
  kid=kid,
2736
2755
  )
2737
2756
  )
@@ -2847,7 +2866,7 @@ class JacParser(Pass):
2847
2866
  def inner_compr(self, kid: list[ast.AstNode]) -> ast.InnerCompr:
2848
2867
  """Grammar rule.
2849
2868
 
2850
- 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)*
2851
2870
  """
2852
2871
  chomp = [*kid]
2853
2872
  is_async = bool(
@@ -2862,7 +2881,7 @@ class JacParser(Pass):
2862
2881
  target=chomp[0],
2863
2882
  collection=chomp[2],
2864
2883
  conditional=(
2865
- chomp[4]
2884
+ [i for i in chomp[4:] if isinstance(i, ast.Expr)]
2866
2885
  if len(chomp) > 4 and isinstance(chomp[4], ast.Expr)
2867
2886
  else None
2868
2887
  ),
@@ -2898,6 +2917,7 @@ class JacParser(Pass):
2898
2917
  return self.nu(
2899
2918
  ast.SubNodeList[ast.Expr | ast.KWPair](
2900
2919
  items=valid_kid,
2920
+ delim=Tok.COMMA,
2901
2921
  kid=kid,
2902
2922
  )
2903
2923
  )
@@ -2927,6 +2947,7 @@ class JacParser(Pass):
2927
2947
  return self.nu(
2928
2948
  ast.SubNodeList[ast.Assignment](
2929
2949
  items=valid_kid,
2950
+ delim=Tok.COMMA,
2930
2951
  kid=new_kid,
2931
2952
  )
2932
2953
  )
@@ -3181,8 +3202,7 @@ class JacParser(Pass):
3181
3202
  def edge_ref_chain(self, kid: list[ast.AstNode]) -> ast.EdgeRefTrailer:
3182
3203
  """Grammar rule.
3183
3204
 
3184
- edge_ref_chain: (EDGE_OP|NODE_OP)? LSQUARE expression?
3185
- (edge_op_ref (NODE_OP? expression)?)+ RSQUARE
3205
+ (EDGE_OP|NODE_OP)? LSQUARE expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
3186
3206
  """
3187
3207
  valid_chain = [i for i in kid if isinstance(i, (ast.Expr, ast.FilterCompr))]
3188
3208
  return self.nu(
@@ -3249,7 +3269,7 @@ class JacParser(Pass):
3249
3269
  def connect_op(self, kid: list[ast.AstNode]) -> ast.ConnectOp:
3250
3270
  """Grammar rule.
3251
3271
 
3252
- connect_op: EDGE_OP? (connect_from | connect_to)
3272
+ connect_op: connect_from | connect_to | connect_any
3253
3273
  """
3254
3274
  if len(kid) < 2 and isinstance(kid[0], ast.ConnectOp):
3255
3275
  return self.nu(kid[0])
@@ -3394,6 +3414,7 @@ class JacParser(Pass):
3394
3414
  return self.nu(
3395
3415
  ast.SubNodeList[ast.CompareExpr](
3396
3416
  items=valid_kid,
3417
+ delim=Tok.COMMA,
3397
3418
  kid=new_kid,
3398
3419
  )
3399
3420
  )
@@ -3434,7 +3455,7 @@ class JacParser(Pass):
3434
3455
  def assign_compr(self, kid: list[ast.AstNode]) -> ast.AssignCompr:
3435
3456
  """Grammar rule.
3436
3457
 
3437
- filter_compr: LPAREN STAR_MUL kw_expr_list RPAREN
3458
+ filter_compr: LPAREN EQ kw_expr_list RPAREN
3438
3459
  """
3439
3460
  if isinstance(kid[2], ast.SubNodeList):
3440
3461
  return self.nu(
@@ -3470,11 +3491,9 @@ class JacParser(Pass):
3470
3491
  """
3471
3492
  pattern = kid[1]
3472
3493
  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)
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))
3478
3497
  ):
3479
3498
  return self.nu(
3480
3499
  ast.MatchCase(
@@ -3737,6 +3756,7 @@ class JacParser(Pass):
3737
3756
  valid_kid = [i for i in new_kid if isinstance(i, ast.MatchPattern)]
3738
3757
  return ast.SubNodeList[ast.MatchPattern](
3739
3758
  items=valid_kid,
3759
+ delim=Tok.COMMA,
3740
3760
  kid=kid,
3741
3761
  )
3742
3762
 
@@ -3782,6 +3802,7 @@ class JacParser(Pass):
3782
3802
  valid_kid = [i for i in new_kid if isinstance(i, ast.MatchKVPair)]
3783
3803
  return ast.SubNodeList[ast.MatchKVPair](
3784
3804
  items=valid_kid,
3805
+ delim=Tok.COMMA,
3785
3806
  kid=new_kid,
3786
3807
  )
3787
3808
  else:
@@ -3802,7 +3823,6 @@ class JacParser(Pass):
3802
3823
  pos_start=token.start_pos if token.start_pos is not None else 0,
3803
3824
  pos_end=token.end_pos if token.end_pos is not None else 0,
3804
3825
  is_kwesc=True,
3805
- kid=[],
3806
3826
  )
3807
3827
  )
3808
3828
  elif token.type == Tok.NAME:
@@ -3841,6 +3861,5 @@ class JacParser(Pass):
3841
3861
  col_end=token.end_column if token.end_column is not None else 0,
3842
3862
  pos_start=token.start_pos if token.start_pos is not None else 0,
3843
3863
  pos_end=token.end_pos if token.end_pos is not None else 0,
3844
- kid=[],
3845
3864
  )
3846
3865
  )
@@ -9,7 +9,7 @@ body field.
9
9
  import jaclang.compiler.absyntree as ast
10
10
  from jaclang.compiler.passes import Pass
11
11
  from jaclang.compiler.passes.main import SubNodeTabPass
12
- from jaclang.compiler.symtable import SymbolTable, SymbolType
12
+ from jaclang.compiler.symtable import Symbol, SymbolTable, SymbolType
13
13
 
14
14
 
15
15
  class DeclDefMatchPass(Pass):
@@ -28,6 +28,14 @@ class DeclDefMatchPass(Pass):
28
28
  """Rebuild sub node table."""
29
29
  self.ir = SubNodeTabPass(input_ir=self.ir, prior=self).ir
30
30
 
31
+ def defn_lookup(self, lookup: Symbol) -> ast.AstImplNeedingNode | None:
32
+ """Lookup a definition in a symbol table."""
33
+ for defn in range(len(lookup.defn)):
34
+ candidate = lookup.defn[len(lookup.defn) - (defn + 1)]
35
+ if isinstance(candidate, ast.AstImplNeedingNode) and candidate.needs_impl:
36
+ return candidate
37
+ return None
38
+
31
39
  def connect_def_impl(self, sym_tab: SymbolTable) -> None:
32
40
  """Connect Decls and Defs."""
33
41
  for sym in sym_tab.tab.values():
@@ -35,7 +43,11 @@ class DeclDefMatchPass(Pass):
35
43
  # currently strips the type info from impls
36
44
  arch_refs = [x[3:] for x in sym.sym_name.split(".")]
37
45
  lookup = sym_tab.lookup(arch_refs[0])
38
- decl_node = lookup.decl if lookup else None
46
+ decl_node = (
47
+ self.defn_lookup(lookup)
48
+ if len(arch_refs) == 1 and lookup
49
+ else lookup.defn[-1] if lookup else None
50
+ )
39
51
  for name in arch_refs[1:]:
40
52
  if decl_node:
41
53
  lookup = (
@@ -43,7 +55,11 @@ class DeclDefMatchPass(Pass):
43
55
  if decl_node.sym_tab
44
56
  else None
45
57
  )
46
- decl_node = lookup.decl if lookup else None
58
+ decl_node = (
59
+ self.defn_lookup(lookup)
60
+ if len(arch_refs) == 1 and lookup
61
+ else lookup.defn[-1] if lookup else None
62
+ )
47
63
  else:
48
64
  break
49
65
  if not decl_node: