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
@@ -11,6 +11,7 @@ from typing import Optional, Sequence, TypeVar
11
11
  import jaclang.compiler.absyntree as ast
12
12
  from jaclang.compiler.constant import Constants as Con, EdgeDir, Tokens as Tok
13
13
  from jaclang.compiler.passes import Pass
14
+ from jaclang.core.utils import get_sem_scope
14
15
 
15
16
  T = TypeVar("T", bound=ast3.AST)
16
17
 
@@ -208,11 +209,28 @@ class PyastGenPass(Pass):
208
209
  if isinstance(i, ast3.AST):
209
210
  i.lineno = jac_node.loc.first_line
210
211
  i.col_offset = jac_node.loc.col_start
211
- i.end_lineno = jac_node.loc.last_line
212
- i.end_col_offset = jac_node.loc.col_end
213
- i.jac_link = jac_node # type: ignore
212
+ i.end_lineno = (
213
+ jac_node.loc.last_line
214
+ if jac_node.loc.last_line
215
+ else jac_node.loc.first_line
216
+ )
217
+ i.end_col_offset = (
218
+ jac_node.loc.col_end
219
+ if jac_node.loc.col_end
220
+ else jac_node.loc.col_start
221
+ )
222
+ i.jac_link: list[ast3.AST] = [jac_node] # type: ignore
214
223
  return py_node
215
224
 
225
+ def link_jac_py_nodes(
226
+ self, jac_node: ast.AstNode, py_nodes: list[ast3.AST]
227
+ ) -> None:
228
+ """Link jac name ast to py ast nodes."""
229
+ jac_node.gen.py_ast = py_nodes
230
+ for i in py_nodes:
231
+ if isinstance(i.jac_link, list): # type: ignore
232
+ i.jac_link.append(jac_node) # type: ignore
233
+
216
234
  def pyinline_sync(
217
235
  self,
218
236
  py_nodes: list[ast3.AST],
@@ -225,7 +243,7 @@ class PyastGenPass(Pass):
225
243
  i.lineno += self.cur_node.loc.first_line
226
244
  if hasattr(i, "end_lineno") and i.end_lineno is not None:
227
245
  i.end_lineno += self.cur_node.loc.first_line
228
- i.jac_link = self.cur_node # type: ignore
246
+ i.jac_link: ast3.AST = [self.cur_node] # type: ignore
229
247
  return py_nodes
230
248
 
231
249
  def resolve_stmt_block(
@@ -239,15 +257,18 @@ class PyastGenPass(Pass):
239
257
  doc: Optional[ast.String] = None,
240
258
  ) -> list[ast3.AST]:
241
259
  """Unwind codeblock."""
260
+ valid_stmts = (
261
+ [i for i in node.items if not isinstance(i, ast.Semi)] if node else []
262
+ )
242
263
  ret: list[ast3.AST] = (
243
264
  [self.sync(ast3.Pass(), node)]
244
- if isinstance(node, ast.SubNodeList) and not node.items
265
+ if isinstance(node, ast.SubNodeList) and not valid_stmts
245
266
  else (
246
267
  self.flatten(
247
268
  [
248
269
  x.gen.py_ast
249
- for x in node.items
250
- # if not isinstance(x, ast.AstImplOnlyNode)
270
+ for x in valid_stmts
271
+ if not isinstance(x, ast.AstImplOnlyNode)
251
272
  ]
252
273
  )
253
274
  if node and isinstance(node.gen.py_ast, list)
@@ -305,7 +326,8 @@ class PyastGenPass(Pass):
305
326
  body: Sequence[ElementStmt],
306
327
  is_imported: bool,
307
328
  """
308
- pre_body = [*node.impl_mod.body, *node.body] if node.impl_mod else node.body
329
+ clean_body = [i for i in node.body if not isinstance(i, ast.AstImplOnlyNode)]
330
+ pre_body = [*node.impl_mod.body, *clean_body] if node.impl_mod else clean_body
309
331
  pre_body = [*pre_body, *node.test_mod.body] if node.test_mod else pre_body
310
332
  body = (
311
333
  [
@@ -567,6 +589,8 @@ class PyastGenPass(Pass):
567
589
  )
568
590
  )
569
591
  ]
592
+ if node.alias:
593
+ self.link_jac_py_nodes(jac_node=node.alias, py_nodes=node.gen.py_ast)
570
594
 
571
595
  def exit_module_item(self, node: ast.ModuleItem) -> None:
572
596
  """Sub objects.
@@ -691,6 +715,9 @@ class PyastGenPass(Pass):
691
715
  )
692
716
  )
693
717
  ]
718
+ self.link_jac_py_nodes(jac_node=node.name, py_nodes=node.gen.py_ast)
719
+ if isinstance(node.body, ast.ArchDef):
720
+ self.link_jac_py_nodes(jac_node=node.body, py_nodes=node.gen.py_ast)
694
721
 
695
722
  def collect_events(
696
723
  self, node: ast.Architype
@@ -743,6 +770,12 @@ class PyastGenPass(Pass):
743
770
  doc: Optional[String],
744
771
  decorators: Optional[SubNodeList[ExprType]],
745
772
  """
773
+ for i in node.target.archs:
774
+ if i.sym_link:
775
+ self.link_jac_py_nodes(jac_node=i, py_nodes=i.sym_link.decl.gen.py_ast)
776
+ self.link_jac_py_nodes(
777
+ jac_node=i.name_ref, py_nodes=i.sym_link.decl.gen.py_ast
778
+ )
746
779
 
747
780
  def exit_enum(self, node: ast.Enum) -> None:
748
781
  """Sub objects.
@@ -783,6 +816,8 @@ class PyastGenPass(Pass):
783
816
  )
784
817
  )
785
818
  ]
819
+ if isinstance(node.body, ast.EnumDef):
820
+ self.link_jac_py_nodes(jac_node=node.body, py_nodes=node.gen.py_ast)
786
821
 
787
822
  def exit_enum_def(self, node: ast.EnumDef) -> None:
788
823
  """Sub objects.
@@ -792,6 +827,12 @@ class PyastGenPass(Pass):
792
827
  doc: Optional[String],
793
828
  decorators: Optional[SubNodeList[ExprType]],
794
829
  """
830
+ for i in node.target.archs:
831
+ if i.sym_link:
832
+ self.link_jac_py_nodes(jac_node=i, py_nodes=i.sym_link.decl.gen.py_ast)
833
+ self.link_jac_py_nodes(
834
+ jac_node=i.name_ref, py_nodes=i.sym_link.decl.gen.py_ast
835
+ )
795
836
 
796
837
  def exit_ability(self, node: ast.Ability) -> None:
797
838
  """Sub objects.
@@ -815,12 +856,12 @@ class PyastGenPass(Pass):
815
856
  [
816
857
  self.sync(
817
858
  ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc
818
- ), # type: ignore
819
- self.sync(ast3.Pass(), node.body), # type: ignore
859
+ ),
860
+ self.sync(ast3.Pass(), node.body),
820
861
  ]
821
862
  if node.doc and node.is_abstract
822
863
  else (
823
- [self.sync(ast3.Pass(), node.body)] # type: ignore
864
+ [self.sync(ast3.Pass(), node.body)]
824
865
  if node.is_abstract
825
866
  else self.resolve_stmt_block(
826
867
  (
@@ -875,6 +916,7 @@ class PyastGenPass(Pass):
875
916
  )
876
917
  if not body and not isinstance(node.body, ast.FuncCall):
877
918
  self.error("Ability has no body. Perhaps an impl must be imported.", node)
919
+ body = [self.sync(ast3.Pass(), node)]
878
920
 
879
921
  node.gen.py_ast = [
880
922
  self.sync(
@@ -892,22 +934,92 @@ class PyastGenPass(Pass):
892
934
  )
893
935
  )
894
936
  ]
937
+ self.link_jac_py_nodes(jac_node=node.name_ref, py_nodes=node.gen.py_ast)
938
+ if isinstance(node.body, ast.AbilityDef):
939
+ self.link_jac_py_nodes(jac_node=node.body, py_nodes=node.gen.py_ast)
940
+
941
+ def bfs_collect_type(self, node: ast.AstNode) -> list[str]:
942
+ """Collect type information in assignment using bfs."""
943
+ extracted_type = []
944
+ if isinstance(node, (ast.BuiltinType, ast.Token)):
945
+ extracted_type.append(node.value)
946
+ for child in node.kid:
947
+ extracted_type.extend(self.bfs_collect_type(child))
948
+ return extracted_type
895
949
 
896
950
  def gen_llm_body(self, node: ast.Ability) -> list[ast3.AST]:
897
951
  """Generate llm body."""
898
952
  if isinstance(node.body, ast.FuncCall):
899
- model_params = (
900
- {
901
- param.key: param.value
902
- for param in node.body.params.items
903
- if isinstance(param, ast.KWPair)
904
- }
905
- if node.body.params
906
- else {}
953
+ model_params = {}
954
+ include_info = []
955
+ exclude_info = []
956
+ if node.body.params:
957
+ for param in node.body.params.items:
958
+ if isinstance(param, ast.KWPair) and isinstance(
959
+ param.key, ast.Name
960
+ ):
961
+ key = param.key.value
962
+ value = param.value
963
+ if key not in ["incl_info", "excl_info"]:
964
+ model_params[key] = value
965
+ elif key == "incl_info":
966
+ if isinstance(value, ast.AtomUnit):
967
+ var_name = (
968
+ value.value.right.value
969
+ if isinstance(value.value, ast.AtomTrailer)
970
+ and isinstance(value.value.right, ast.Name)
971
+ else (
972
+ value.value.value
973
+ if isinstance(value.value, ast.Name)
974
+ else ""
975
+ )
976
+ )
977
+ include_info.append((var_name, value.gen.py_ast[0]))
978
+ elif isinstance(value, ast.TupleVal) and value.values:
979
+ for i in value.values.items:
980
+ var_name = (
981
+ i.right.value
982
+ if isinstance(i, ast.AtomTrailer)
983
+ and isinstance(i.right, ast.Name)
984
+ else (
985
+ i.value if isinstance(i, ast.Name) else ""
986
+ )
987
+ )
988
+ include_info.append((var_name, i.gen.py_ast[0]))
989
+ elif key == "excl_info":
990
+ if isinstance(value, ast.AtomUnit):
991
+ var_name = (
992
+ value.value.right.value
993
+ if isinstance(value.value, ast.AtomTrailer)
994
+ and isinstance(value.value.right, ast.Name)
995
+ else (
996
+ value.value.value
997
+ if isinstance(value.value, ast.Name)
998
+ else ""
999
+ )
1000
+ )
1001
+ exclude_info.append((var_name, value.gen.py_ast[0]))
1002
+ elif isinstance(value, ast.TupleVal) and value.values:
1003
+ for i in value.values.items:
1004
+ var_name = (
1005
+ i.right.value
1006
+ if isinstance(i, ast.AtomTrailer)
1007
+ and isinstance(i.right, ast.Name)
1008
+ else (
1009
+ i.value if isinstance(i, ast.Name) else ""
1010
+ )
1011
+ )
1012
+ exclude_info.append((var_name, i.gen.py_ast[0]))
1013
+ extracted = (
1014
+ "".join(self.bfs_collect_type(node.signature.return_type))
1015
+ if isinstance(node.signature, ast.FuncSignature)
1016
+ and node.signature.return_type
1017
+ else None
907
1018
  )
908
1019
  return [
909
1020
  self.sync(
910
- ast3.Return(
1021
+ ast3.Assign(
1022
+ targets=[self.sync(ast3.Name(id="output", ctx=ast3.Store()))],
911
1023
  value=self.sync(
912
1024
  ast3.Call(
913
1025
  func=self.sync(
@@ -924,6 +1036,16 @@ class PyastGenPass(Pass):
924
1036
  ),
925
1037
  args=[],
926
1038
  keywords=[
1039
+ self.sync(
1040
+ ast3.keyword(
1041
+ arg="file_loc",
1042
+ value=self.sync(
1043
+ ast3.Name(
1044
+ id="__file__", ctx=ast3.Load()
1045
+ )
1046
+ ),
1047
+ )
1048
+ ),
927
1049
  self.sync(
928
1050
  ast3.keyword(
929
1051
  arg="model",
@@ -936,7 +1058,9 @@ class PyastGenPass(Pass):
936
1058
  value=self.sync(
937
1059
  ast3.Dict(
938
1060
  keys=[
939
- self.sync(ast3.Constant(value=key.value)) # type: ignore
1061
+ self.sync(
1062
+ ast3.Constant(value=key)
1063
+ )
940
1064
  for key in model_params.keys()
941
1065
  ],
942
1066
  values=[
@@ -947,21 +1071,69 @@ class PyastGenPass(Pass):
947
1071
  ),
948
1072
  )
949
1073
  ),
1074
+ self.sync(
1075
+ ast3.keyword(
1076
+ arg="scope",
1077
+ value=(
1078
+ self.sync(
1079
+ ast3.Constant(
1080
+ value=str(get_sem_scope(node))
1081
+ )
1082
+ )
1083
+ ),
1084
+ )
1085
+ ),
950
1086
  self.sync(
951
1087
  ast3.keyword(
952
1088
  arg="incl_info",
953
1089
  value=self.sync(
954
- ast3.Constant(value=None)
955
- ), # TODO: Add incl_info
1090
+ ast3.List(
1091
+ elts=[
1092
+ self.sync(
1093
+ ast3.Tuple(
1094
+ elts=[
1095
+ self.sync(
1096
+ ast3.Constant(
1097
+ value=key
1098
+ )
1099
+ ),
1100
+ value,
1101
+ ],
1102
+ ctx=ast3.Load(),
1103
+ )
1104
+ )
1105
+ for key, value in include_info
1106
+ ],
1107
+ ctx=ast3.Load(),
1108
+ )
1109
+ ),
956
1110
  )
957
1111
  ),
958
1112
  self.sync(
959
1113
  ast3.keyword(
960
1114
  arg="excl_info",
961
1115
  value=self.sync(
962
- ast3.Constant(value=None)
963
- ), # TODO: Add excl_info
964
- )
1116
+ ast3.List(
1117
+ elts=[
1118
+ self.sync(
1119
+ ast3.Tuple(
1120
+ elts=[
1121
+ self.sync(
1122
+ ast3.Constant(
1123
+ value=key
1124
+ )
1125
+ ),
1126
+ value,
1127
+ ],
1128
+ ctx=ast3.Load(),
1129
+ )
1130
+ )
1131
+ for key, value in exclude_info
1132
+ ],
1133
+ ctx=ast3.Load(),
1134
+ )
1135
+ ),
1136
+ ),
965
1137
  ),
966
1138
  self.sync(
967
1139
  ast3.keyword(
@@ -974,11 +1146,15 @@ class PyastGenPass(Pass):
974
1146
  ast3.Tuple(
975
1147
  elts=[
976
1148
  (
977
- param.semstr.gen.py_ast[
978
- 0
979
- ]
980
- if param.semstr
981
- else None
1149
+ self.sync(
1150
+ ast3.Constant(
1151
+ value=(
1152
+ param.semstr.lit_value
1153
+ if param.semstr
1154
+ else None
1155
+ )
1156
+ )
1157
+ )
982
1158
  ),
983
1159
  (
984
1160
  param.type_tag.tag.gen.py_ast[
@@ -1024,11 +1200,15 @@ class PyastGenPass(Pass):
1024
1200
  elts=(
1025
1201
  [
1026
1202
  (
1027
- node.signature.semstr.gen.py_ast[
1028
- 0
1029
- ]
1030
- if node.signature.semstr
1031
- else None
1203
+ self.sync(
1204
+ ast3.Constant(
1205
+ value=(
1206
+ node.signature.semstr.lit_value
1207
+ if node.signature.semstr
1208
+ else None
1209
+ )
1210
+ )
1211
+ )
1032
1212
  ),
1033
1213
  (
1034
1214
  node.signature.return_type.gen.py_ast[
@@ -1037,6 +1217,15 @@ class PyastGenPass(Pass):
1037
1217
  if node.signature.return_type
1038
1218
  else None
1039
1219
  ),
1220
+ (
1221
+ self.sync(
1222
+ ast3.Constant(
1223
+ value=(
1224
+ extracted
1225
+ )
1226
+ )
1227
+ )
1228
+ ),
1040
1229
  ]
1041
1230
  if isinstance(
1042
1231
  node.signature,
@@ -1048,7 +1237,7 @@ class PyastGenPass(Pass):
1048
1237
  )
1049
1238
  ),
1050
1239
  )
1051
- ), # TODO: Add Meaning Types of Outputs
1240
+ ),
1052
1241
  self.sync(
1053
1242
  ast3.keyword(
1054
1243
  arg="action",
@@ -1061,9 +1250,55 @@ class PyastGenPass(Pass):
1061
1250
  ),
1062
1251
  ],
1063
1252
  )
1064
- )
1253
+ ),
1065
1254
  )
1066
- )
1255
+ ),
1256
+ self.sync(
1257
+ ast3.Try(
1258
+ body=[
1259
+ self.sync(
1260
+ ast3.Return(
1261
+ value=self.sync(
1262
+ ast3.Call(
1263
+ func=self.sync(
1264
+ ast3.Name(id="eval", ctx=ast3.Load())
1265
+ ),
1266
+ args=[
1267
+ self.sync(
1268
+ ast3.Name(
1269
+ id="output", ctx=ast3.Load()
1270
+ )
1271
+ )
1272
+ ],
1273
+ keywords=[],
1274
+ )
1275
+ )
1276
+ )
1277
+ )
1278
+ ],
1279
+ handlers=[
1280
+ self.sync(
1281
+ ast3.ExceptHandler(
1282
+ type=None,
1283
+ name=None,
1284
+ body=[
1285
+ self.sync(
1286
+ ast3.Return(
1287
+ value=self.sync(
1288
+ ast3.Name(
1289
+ id="output", ctx=ast3.Load()
1290
+ )
1291
+ )
1292
+ )
1293
+ )
1294
+ ],
1295
+ )
1296
+ )
1297
+ ],
1298
+ orelse=[],
1299
+ finalbody=[],
1300
+ )
1301
+ ),
1067
1302
  ]
1068
1303
  else:
1069
1304
  return []
@@ -1077,6 +1312,15 @@ class PyastGenPass(Pass):
1077
1312
  doc: Optional[String],
1078
1313
  decorators: Optional[SubNodeList[ExprType]],
1079
1314
  """
1315
+ for i in node.target.archs:
1316
+ if i.sym_link:
1317
+ self.link_jac_py_nodes(jac_node=i, py_nodes=i.sym_link.decl.gen.py_ast)
1318
+ self.link_jac_py_nodes(
1319
+ jac_node=i.name_ref, py_nodes=i.sym_link.decl.gen.py_ast
1320
+ )
1321
+ if isinstance(node.parent, ast.Ability) and node.parent.signature:
1322
+ # TODO: Here we need to do a link for each subnode to the original parent signature
1323
+ pass
1080
1324
 
1081
1325
  def exit_func_signature(self, node: ast.FuncSignature) -> None:
1082
1326
  """Sub objects.
@@ -1233,6 +1477,7 @@ class PyastGenPass(Pass):
1233
1477
  )
1234
1478
  )
1235
1479
  ]
1480
+ self.link_jac_py_nodes(jac_node=node.name, py_nodes=node.gen.py_ast)
1236
1481
 
1237
1482
  def exit_arch_has(self, node: ast.ArchHas) -> None:
1238
1483
  """Sub objects.
@@ -1488,6 +1733,8 @@ class PyastGenPass(Pass):
1488
1733
  )
1489
1734
  )
1490
1735
  ]
1736
+ if node.name:
1737
+ self.link_jac_py_nodes(jac_node=node.name, py_nodes=node.gen.py_ast)
1491
1738
 
1492
1739
  def exit_finally_stmt(self, node: ast.FinallyStmt) -> None:
1493
1740
  """Sub objects.
@@ -1595,6 +1842,9 @@ class PyastGenPass(Pass):
1595
1842
  )
1596
1843
  )
1597
1844
  ]
1845
+ self.link_jac_py_nodes(jac_node=node.expr, py_nodes=node.gen.py_ast)
1846
+ if node.alias:
1847
+ self.link_jac_py_nodes(jac_node=node.alias, py_nodes=node.gen.py_ast)
1598
1848
 
1599
1849
  def exit_raise_stmt(self, node: ast.RaiseStmt) -> None:
1600
1850
  """Sub objects.
@@ -1852,6 +2102,7 @@ class PyastGenPass(Pass):
1852
2102
  jac_node=x,
1853
2103
  )
1854
2104
  )
2105
+ self.link_jac_py_nodes(jac_node=x, py_nodes=[py_nodes[-1]])
1855
2106
  node.gen.py_ast = [*py_nodes]
1856
2107
 
1857
2108
  def exit_non_local_stmt(self, node: ast.NonLocalStmt) -> None:
@@ -1867,6 +2118,7 @@ class PyastGenPass(Pass):
1867
2118
  jac_node=x,
1868
2119
  )
1869
2120
  )
2121
+ self.link_jac_py_nodes(jac_node=x, py_nodes=[py_nodes[-1]])
1870
2122
  node.gen.py_ast = [*py_nodes]
1871
2123
 
1872
2124
  def exit_assignment(self, node: ast.Assignment) -> None:
@@ -1877,6 +2129,21 @@ class PyastGenPass(Pass):
1877
2129
  type_tag: Optional[SubTag[ExprType]],
1878
2130
  mutable: bool =True,
1879
2131
  """
2132
+ value = (
2133
+ node.value.gen.py_ast[0]
2134
+ if node.value
2135
+ else (
2136
+ self.sync(
2137
+ ast3.Call(
2138
+ func=self.sync(ast3.Name(id="__jac_auto__", ctx=ast3.Load())),
2139
+ args=[],
2140
+ keywords=[],
2141
+ )
2142
+ )
2143
+ if node.is_enum_stmt
2144
+ else None if node.type_tag else self.ice()
2145
+ )
2146
+ )
1880
2147
  if node.type_tag:
1881
2148
  node.gen.py_ast = [
1882
2149
  self.sync(
@@ -1888,25 +2155,19 @@ class PyastGenPass(Pass):
1888
2155
  )
1889
2156
  )
1890
2157
  ]
1891
- elif not node.value:
1892
- self.ice()
1893
2158
  elif node.aug_op:
1894
2159
  node.gen.py_ast = [
1895
2160
  self.sync(
1896
2161
  ast3.AugAssign(
1897
2162
  target=node.target.items[0].gen.py_ast[0],
1898
2163
  op=node.aug_op.gen.py_ast[0],
1899
- value=node.value.gen.py_ast[0],
2164
+ value=value,
1900
2165
  )
1901
2166
  )
1902
2167
  ]
1903
2168
  else:
1904
2169
  node.gen.py_ast = [
1905
- self.sync(
1906
- ast3.Assign(
1907
- targets=node.target.gen.py_ast, value=node.value.gen.py_ast[0]
1908
- )
1909
- )
2170
+ self.sync(ast3.Assign(targets=node.target.gen.py_ast, value=value))
1910
2171
  ]
1911
2172
 
1912
2173
  def exit_binary_expr(self, node: ast.BinaryExpr) -> None:
@@ -2037,7 +2298,9 @@ class PyastGenPass(Pass):
2037
2298
  params=(
2038
2299
  node.left.values
2039
2300
  if isinstance(node.left, ast.TupleVal)
2040
- else ast.SubNodeList(items=[node.left], kid=[node.left])
2301
+ else ast.SubNodeList(
2302
+ items=[node.left], delim=Tok.COMMA, kid=[node.left]
2303
+ )
2041
2304
  ),
2042
2305
  kid=node.kid,
2043
2306
  )
@@ -2071,7 +2334,9 @@ class PyastGenPass(Pass):
2071
2334
  params=(
2072
2335
  node.right.values
2073
2336
  if isinstance(node.right, ast.TupleVal)
2074
- else ast.SubNodeList(items=[node.right], kid=[node.right])
2337
+ else ast.SubNodeList(
2338
+ items=[node.right], delim=Tok.COMMA, kid=[node.right]
2339
+ )
2075
2340
  ),
2076
2341
  kid=node.kid,
2077
2342
  )
@@ -2206,7 +2471,10 @@ class PyastGenPass(Pass):
2206
2471
  elif node.op.name in [Tok.STAR_MUL]:
2207
2472
  node.gen.py_ast = [
2208
2473
  self.sync(
2209
- ast3.Starred(value=node.operand.gen.py_ast[0], ctx=ast3.Load())
2474
+ ast3.Starred(
2475
+ value=node.operand.gen.py_ast[0],
2476
+ ctx=ast3.Load(),
2477
+ )
2210
2478
  )
2211
2479
  ]
2212
2480
  elif node.op.name in [Tok.STAR_POW]:
@@ -2293,13 +2561,6 @@ class PyastGenPass(Pass):
2293
2561
  else [self.sync(ast3.Constant(value=""))]
2294
2562
  )
2295
2563
 
2296
- def exit_expr_list(self, node: ast.ExprList) -> None:
2297
- """Sub objects.
2298
-
2299
- values: Optional[SubNodeList[ExprType]],
2300
- """
2301
- node.gen.py_ast = node.values.gen.py_ast if node.values else []
2302
-
2303
2564
  def exit_list_val(self, node: ast.ListVal) -> None:
2304
2565
  """Sub objects.
2305
2566
 
@@ -2380,6 +2641,8 @@ class PyastGenPass(Pass):
2380
2641
  )
2381
2642
  )
2382
2643
  ]
2644
+ if node.key:
2645
+ self.link_jac_py_nodes(jac_node=node.key, py_nodes=node.gen.py_ast)
2383
2646
 
2384
2647
  def exit_inner_compr(self, node: ast.InnerCompr) -> None:
2385
2648
  """Sub objects.
@@ -2394,7 +2657,11 @@ class PyastGenPass(Pass):
2394
2657
  ast3.comprehension(
2395
2658
  target=node.target.gen.py_ast[0],
2396
2659
  iter=node.collection.gen.py_ast[0],
2397
- ifs=node.conditional.gen.py_ast if node.conditional else [],
2660
+ ifs=(
2661
+ [x.gen.py_ast[0] for x in node.conditional]
2662
+ if node.conditional
2663
+ else []
2664
+ ),
2398
2665
  is_async=0,
2399
2666
  )
2400
2667
  )
@@ -2404,7 +2671,7 @@ class PyastGenPass(Pass):
2404
2671
  """Sub objects.
2405
2672
 
2406
2673
  out_expr: ExprType,
2407
- compr: InnerCompr,
2674
+ compr: list[InnerCompr]
2408
2675
  """
2409
2676
  node.gen.py_ast = [
2410
2677
  self.sync(
@@ -2419,7 +2686,7 @@ class PyastGenPass(Pass):
2419
2686
  """Sub objects.
2420
2687
 
2421
2688
  out_expr: ExprType,
2422
- compr: InnerCompr,
2689
+ compr: list[InnerCompr]
2423
2690
  """
2424
2691
  node.gen.py_ast = [
2425
2692
  self.sync(
@@ -2434,7 +2701,7 @@ class PyastGenPass(Pass):
2434
2701
  """Sub objects.
2435
2702
 
2436
2703
  out_expr: ExprType,
2437
- compr: InnerCompr,
2704
+ compr: list[InnerCompr]
2438
2705
  """
2439
2706
  node.gen.py_ast = [
2440
2707
  self.sync(
@@ -2468,27 +2735,25 @@ class PyastGenPass(Pass):
2468
2735
 
2469
2736
  target: Expr,
2470
2737
  right: AtomExpr | Expr,
2471
- is_attr: Optional[Token],
2738
+ is_attr: bool,
2472
2739
  is_null_ok: bool,
2473
2740
  """
2474
2741
  if node.is_attr:
2475
- node.gen.py_ast = [
2476
- self.sync(
2477
- ast3.Attribute(
2478
- value=node.target.gen.py_ast[0],
2479
- attr=(
2480
- node.right.sym_name
2481
- if isinstance(node.right, ast.AstSymbolNode)
2482
- else ""
2483
- ),
2484
- ctx=(
2485
- node.right.py_ctx_func()
2486
- if isinstance(node.right, ast.AstSymbolNode)
2487
- else ast3.Load()
2488
- ),
2742
+ if isinstance(node.right, ast.AstSymbolNode):
2743
+ node.gen.py_ast = [
2744
+ self.sync(
2745
+ ast3.Attribute(
2746
+ value=node.target.gen.py_ast[0],
2747
+ attr=(node.right.sym_name),
2748
+ ctx=(node.right.py_ctx_func()),
2749
+ )
2489
2750
  )
2751
+ ]
2752
+ self.link_jac_py_nodes(
2753
+ jac_node=node.right.sym_name_node, py_nodes=node.gen.py_ast
2490
2754
  )
2491
- ]
2755
+ else:
2756
+ self.error("Invalid attribute access")
2492
2757
  elif isinstance(node.right, ast.FilterCompr):
2493
2758
  node.gen.py_ast = [
2494
2759
  self.sync(
@@ -2568,19 +2833,11 @@ class PyastGenPass(Pass):
2568
2833
  target: Expr,
2569
2834
  params: Optional[SubNodeList[Expr | KWPair]],
2570
2835
  """
2571
- node.gen.py_ast = [self.sync(self.gen_func_call(node.target, node.params))]
2572
-
2573
- def gen_func_call(
2574
- self,
2575
- target: ast.Expr,
2576
- params: Optional[ast.SubNodeList[ast.Expr | ast.KWPair]],
2577
- ) -> ast3.Call:
2578
- """Generate a function call."""
2579
- func = target.gen.py_ast[0]
2836
+ func = node.target.gen.py_ast[0]
2580
2837
  args = []
2581
2838
  keywords = []
2582
- if params and len(params.items) > 0:
2583
- for x in params.items:
2839
+ if node.params and len(node.params.items) > 0:
2840
+ for x in node.params.items:
2584
2841
  if isinstance(x, ast.UnaryExpr) and x.op.name == Tok.STAR_POW:
2585
2842
  keywords.append(
2586
2843
  self.sync(ast3.keyword(value=x.operand.gen.py_ast[0]), x)
@@ -2593,7 +2850,9 @@ class PyastGenPass(Pass):
2593
2850
  keywords.append(x.gen.py_ast[0])
2594
2851
  else:
2595
2852
  self.ice("Invalid Parameter")
2596
- return ast3.Call(func=func, args=args, keywords=keywords)
2853
+ node.gen.py_ast = [
2854
+ self.sync(ast3.Call(func=func, args=args, keywords=keywords))
2855
+ ]
2597
2856
 
2598
2857
  def exit_index_slice(self, node: ast.IndexSlice) -> None:
2599
2858
  """Sub objects.
@@ -2976,14 +3235,14 @@ class PyastGenPass(Pass):
2976
3235
 
2977
3236
  pattern: MatchPattern,
2978
3237
  guard: Optional[ExprType],
2979
- body: SubNodeList[CodeBlockStmt],
3238
+ body: list[CodeBlockStmt],
2980
3239
  """
2981
3240
  node.gen.py_ast = [
2982
3241
  self.sync(
2983
3242
  ast3.match_case(
2984
3243
  pattern=node.pattern.gen.py_ast[0],
2985
3244
  guard=node.guard.gen.py_ast[0] if node.guard else None,
2986
- body=self.resolve_stmt_block(node.body),
3245
+ body=[x.gen.py_ast[0] for x in node.body],
2987
3246
  )
2988
3247
  )
2989
3248
  ]
@@ -3204,24 +3463,6 @@ class PyastGenPass(Pass):
3204
3463
  node.gen.py_ast = [
3205
3464
  self.sync(ast3.Name(id=node.sym_name, ctx=node.py_ctx_func()))
3206
3465
  ]
3207
- if node.is_enum_singleton and isinstance(node.gen.py_ast[0], ast3.Name):
3208
- node.gen.py_ast[0].ctx = ast3.Store()
3209
- node.gen.py_ast = [
3210
- self.sync(
3211
- ast3.Assign(
3212
- targets=node.gen.py_ast,
3213
- value=self.sync(
3214
- ast3.Call(
3215
- func=self.sync(
3216
- ast3.Name(id="__jac_auto__", ctx=ast3.Load())
3217
- ),
3218
- args=[],
3219
- keywords=[],
3220
- )
3221
- ),
3222
- )
3223
- )
3224
- ]
3225
3466
 
3226
3467
  def exit_float(self, node: ast.Float) -> None:
3227
3468
  """Sub objects.