jaclang 0.7.2__py3-none-any.whl → 0.7.7__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 (92) hide show
  1. jaclang/cli/cli.py +2 -2
  2. jaclang/compiler/absyntree.py +499 -294
  3. jaclang/compiler/codeloc.py +2 -2
  4. jaclang/compiler/constant.py +100 -2
  5. jaclang/compiler/jac.lark +27 -19
  6. jaclang/compiler/parser.py +119 -92
  7. jaclang/compiler/passes/main/access_modifier_pass.py +20 -12
  8. jaclang/compiler/passes/main/def_impl_match_pass.py +28 -14
  9. jaclang/compiler/passes/main/def_use_pass.py +59 -40
  10. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +65 -43
  11. jaclang/compiler/passes/main/import_pass.py +8 -6
  12. jaclang/compiler/passes/main/pyast_gen_pass.py +97 -42
  13. jaclang/compiler/passes/main/pyast_load_pass.py +47 -12
  14. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +19 -10
  15. jaclang/compiler/passes/main/registry_pass.py +6 -6
  16. jaclang/compiler/passes/main/sub_node_tab_pass.py +0 -5
  17. jaclang/compiler/passes/main/sym_tab_build_pass.py +43 -235
  18. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +21 -4
  19. jaclang/compiler/passes/main/tests/test_def_use_pass.py +5 -10
  20. jaclang/compiler/passes/main/type_check_pass.py +2 -1
  21. jaclang/compiler/passes/tool/jac_formatter_pass.py +30 -9
  22. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
  23. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
  24. jaclang/compiler/passes/tool/tests/fixtures/genai/essay_review.jac +1 -1
  25. jaclang/compiler/passes/tool/tests/fixtures/genai/expert_answer.jac +1 -1
  26. jaclang/compiler/passes/tool/tests/fixtures/genai/joke_gen.jac +1 -1
  27. jaclang/compiler/passes/tool/tests/fixtures/genai/odd_word_out.jac +1 -1
  28. jaclang/compiler/passes/tool/tests/fixtures/genai/personality_finder.jac +1 -1
  29. jaclang/compiler/passes/tool/tests/fixtures/genai/text_to_type.jac +1 -1
  30. jaclang/compiler/passes/tool/tests/fixtures/genai/translator.jac +1 -1
  31. jaclang/compiler/passes/tool/tests/fixtures/genai/wikipedia.jac +1 -1
  32. jaclang/compiler/passes/transform.py +2 -4
  33. jaclang/{core/registry.py → compiler/semtable.py} +1 -3
  34. jaclang/compiler/symtable.py +142 -101
  35. jaclang/compiler/tests/test_parser.py +2 -2
  36. jaclang/core/aott.py +15 -11
  37. jaclang/core/{construct.py → architype.py} +25 -240
  38. jaclang/core/constructs.py +44 -0
  39. jaclang/core/context.py +157 -0
  40. jaclang/core/importer.py +18 -9
  41. jaclang/core/memory.py +99 -0
  42. jaclang/core/test.py +90 -0
  43. jaclang/core/utils.py +2 -2
  44. jaclang/langserve/engine.py +127 -50
  45. jaclang/langserve/server.py +34 -61
  46. jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -0
  47. jaclang/langserve/tests/fixtures/circle.jac +16 -12
  48. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  49. jaclang/langserve/tests/fixtures/circle_pure.test.jac +15 -0
  50. jaclang/langserve/tests/fixtures/import_include_statements.jac +6 -0
  51. jaclang/langserve/tests/fixtures/py_import.py +26 -0
  52. jaclang/langserve/tests/test_server.py +93 -18
  53. jaclang/langserve/utils.py +124 -10
  54. jaclang/plugin/builtin.py +1 -1
  55. jaclang/plugin/default.py +23 -9
  56. jaclang/plugin/feature.py +25 -7
  57. jaclang/plugin/spec.py +18 -20
  58. jaclang/settings.py +3 -0
  59. jaclang/tests/fixtures/abc.jac +16 -12
  60. jaclang/tests/fixtures/aott_raise.jac +1 -1
  61. jaclang/tests/fixtures/byllmissue.jac +9 -0
  62. jaclang/tests/fixtures/edgetypeissue.jac +10 -0
  63. jaclang/tests/fixtures/hello.jac +1 -1
  64. jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
  65. jaclang/tests/fixtures/impl_match_confused.jac +5 -0
  66. jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
  67. jaclang/tests/fixtures/run_test.jac +17 -5
  68. jaclang/tests/fixtures/with_llm_function.jac +1 -1
  69. jaclang/tests/fixtures/with_llm_lower.jac +1 -1
  70. jaclang/tests/fixtures/with_llm_method.jac +1 -1
  71. jaclang/tests/fixtures/with_llm_type.jac +1 -1
  72. jaclang/tests/fixtures/with_llm_vision.jac +1 -1
  73. jaclang/tests/test_bugs.py +19 -0
  74. jaclang/tests/test_cli.py +1 -1
  75. jaclang/tests/test_language.py +161 -96
  76. jaclang/tests/test_reference.py +1 -1
  77. jaclang/utils/lang_tools.py +5 -4
  78. jaclang/utils/test.py +2 -1
  79. jaclang/utils/treeprinter.py +22 -8
  80. {jaclang-0.7.2.dist-info → jaclang-0.7.7.dist-info}/METADATA +1 -1
  81. {jaclang-0.7.2.dist-info → jaclang-0.7.7.dist-info}/RECORD +83 -80
  82. jaclang/core/llms/__init__.py +0 -20
  83. jaclang/core/llms/anthropic.py +0 -90
  84. jaclang/core/llms/base.py +0 -206
  85. jaclang/core/llms/groq.py +0 -70
  86. jaclang/core/llms/huggingface.py +0 -76
  87. jaclang/core/llms/ollama.py +0 -81
  88. jaclang/core/llms/openai.py +0 -65
  89. jaclang/core/llms/togetherai.py +0 -63
  90. jaclang/core/llms/utils.py +0 -9
  91. {jaclang-0.7.2.dist-info → jaclang-0.7.7.dist-info}/WHEEL +0 -0
  92. {jaclang-0.7.2.dist-info → jaclang-0.7.7.dist-info}/entry_points.txt +0 -0
@@ -42,7 +42,6 @@ class PyastGenPass(Pass):
42
42
  """Initialize pass."""
43
43
  self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
44
44
  self.already_added: list[str] = []
45
- self.method_sigs: list[ast.FuncSignature | ast.EventSignature] = []
46
45
  self.preamble: list[ast3.AST] = [
47
46
  self.sync(
48
47
  ast3.ImportFrom(
@@ -393,7 +392,7 @@ class PyastGenPass(Pass):
393
392
  args=self.sync(
394
393
  ast3.arguments(
395
394
  posonlyargs=[],
396
- args=[self.sync(ast3.arg(arg="check", annotation=None))],
395
+ args=[self.sync(ast3.arg(arg="_jac_check", annotation=None))],
397
396
  kwonlyargs=[],
398
397
  vararg=None,
399
398
  kwargs=None,
@@ -552,7 +551,7 @@ class PyastGenPass(Pass):
552
551
  arg="mod_bundle",
553
552
  value=self.sync(
554
553
  ast3.Name(
555
- id="__jac_mod_bundle__",
554
+ id="__name__",
556
555
  ctx=ast3.Load(),
557
556
  )
558
557
  ),
@@ -678,14 +677,6 @@ class PyastGenPass(Pass):
678
677
  doc: Optional[String],
679
678
  decorators: Optional[SubNodeList[ExprType]],
680
679
  """
681
- # Record all signatures that are part of methods
682
- for i in (
683
- node.body.body.items
684
- if isinstance(node.body, ast.ArchDef)
685
- else node.body.items if node.body else []
686
- ):
687
- if isinstance(i, ast.Ability):
688
- self.method_sigs.append(i.signature)
689
680
  if isinstance(node.body, ast.AstImplOnlyNode):
690
681
  self.traverse(node.body)
691
682
 
@@ -768,6 +759,18 @@ class PyastGenPass(Pass):
768
759
  )
769
760
  )
770
761
  base_classes = node.base_classes.gen.py_ast if node.base_classes else []
762
+ if node.arch_type.name != Tok.KW_CLASS:
763
+ base_classes.append(
764
+ self.sync(
765
+ ast3.Attribute(
766
+ value=self.sync(
767
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
768
+ ),
769
+ attr=node.arch_type.value.capitalize(),
770
+ ctx=ast3.Load(),
771
+ )
772
+ )
773
+ )
771
774
  if node.is_abstract:
772
775
  self.needs_jac_feature()
773
776
  base_classes.append(
@@ -1091,7 +1094,7 @@ class PyastGenPass(Pass):
1091
1094
  value=(
1092
1095
  node.signature.semstr.lit_value
1093
1096
  if node.signature.semstr
1094
- else None
1097
+ else ""
1095
1098
  )
1096
1099
  )
1097
1100
  )
@@ -1333,7 +1336,7 @@ class PyastGenPass(Pass):
1333
1336
  """
1334
1337
  params = (
1335
1338
  [self.sync(ast3.arg(arg="self", annotation=None))]
1336
- if node in self.method_sigs and not node.is_static
1339
+ if node.is_method and not node.is_static
1337
1340
  else []
1338
1341
  )
1339
1342
  vararg = None
@@ -1391,7 +1394,7 @@ class PyastGenPass(Pass):
1391
1394
  posonlyargs=[],
1392
1395
  args=(
1393
1396
  [self.sync(ast3.arg(arg="self", annotation=None)), here]
1394
- if node in self.method_sigs
1397
+ if node.is_method
1395
1398
  else [here]
1396
1399
  ),
1397
1400
  kwonlyargs=[],
@@ -1409,27 +1412,19 @@ class PyastGenPass(Pass):
1409
1412
  name_ref: NameType,
1410
1413
  arch: Token,
1411
1414
  """
1412
- if node.arch.name == Tok.TYPE_OP:
1415
+ if node.arch_type.name == Tok.TYPE_OP:
1413
1416
  if (
1414
- isinstance(node.name_ref, ast.SpecialVarRef)
1415
- and node.name_ref.var.name == Tok.KW_ROOT
1417
+ isinstance(node.arch_name, ast.SpecialVarRef)
1418
+ and node.arch_name.orig.name == Tok.KW_ROOT
1416
1419
  ):
1417
1420
  node.gen.py_ast = [
1418
1421
  self.sync(
1419
- ast3.Call(
1420
- func=self.sync(
1421
- ast3.Attribute(
1422
- value=self.sync(
1423
- ast3.Name(
1424
- id=Con.JAC_FEATURE.value, ctx=ast3.Load()
1425
- )
1426
- ),
1427
- attr="get_root_type",
1428
- ctx=ast3.Load(),
1429
- )
1422
+ ast3.Attribute(
1423
+ value=self.sync(
1424
+ ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1430
1425
  ),
1431
- args=[],
1432
- keywords=[],
1426
+ attr="RootType",
1427
+ ctx=ast3.Load(),
1433
1428
  )
1434
1429
  )
1435
1430
  ]
@@ -1439,13 +1434,13 @@ class PyastGenPass(Pass):
1439
1434
  self.sync(
1440
1435
  ast3.Attribute(
1441
1436
  value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
1442
- attr=node.name_ref.sym_name,
1437
+ attr=node.arch_name.sym_name,
1443
1438
  ctx=ast3.Load(),
1444
1439
  )
1445
1440
  )
1446
1441
  ]
1447
1442
  else:
1448
- node.gen.py_ast = node.name_ref.gen.py_ast
1443
+ node.gen.py_ast = node.arch_name.gen.py_ast
1449
1444
 
1450
1445
  def exit_arch_ref_chain(self, node: ast.ArchRefChain) -> None:
1451
1446
  """Sub objects.
@@ -1463,7 +1458,7 @@ class PyastGenPass(Pass):
1463
1458
  attr = self.sync(
1464
1459
  ast3.Attribute(
1465
1460
  value=make_attr_chain(arch[:-1]),
1466
- attr=cur.name_ref.sym_name,
1461
+ attr=cur.arch_name.sym_name,
1467
1462
  ctx=ast3.Load(),
1468
1463
  ),
1469
1464
  jac_node=cur,
@@ -1881,6 +1876,38 @@ class PyastGenPass(Pass):
1881
1876
  )
1882
1877
  ]
1883
1878
 
1879
+ def exit_check_stmt(self, node: ast.CheckStmt) -> None:
1880
+ """Sub objects.
1881
+
1882
+ target: ExprType,
1883
+ """
1884
+ if isinstance(node.target, ast.FuncCall) and isinstance(
1885
+ node.target.gen.py_ast[0], ast3.Call
1886
+ ):
1887
+ func = node.target.target.gen.py_ast[0]
1888
+ if isinstance(func, ast3.Name):
1889
+ new_func: ast3.expr = self.sync(
1890
+ ast3.Attribute(
1891
+ value=self.sync(ast3.Name(id="_jac_check", ctx=ast3.Load())),
1892
+ attr=func.id,
1893
+ ctx=ast3.Load(),
1894
+ )
1895
+ )
1896
+ node.target.gen.py_ast[0].func = new_func
1897
+ node.gen.py_ast = [
1898
+ self.sync(
1899
+ ast3.Expr(
1900
+ value=node.target.gen.py_ast[0],
1901
+ )
1902
+ )
1903
+ ]
1904
+ return
1905
+ self.error(
1906
+ "For now, check statements must be function calls "
1907
+ "in the style of assertTrue(), assertEqual(), etc.",
1908
+ node,
1909
+ )
1910
+
1884
1911
  def exit_ctrl_stmt(self, node: ast.CtrlStmt) -> None:
1885
1912
  """Sub objects.
1886
1913
 
@@ -3090,14 +3117,42 @@ class PyastGenPass(Pass):
3090
3117
 
3091
3118
  var: Token,
3092
3119
  """
3093
- try:
3094
- var_ast_expr = ast3.parse(node.sym_name).body[0]
3095
- if not isinstance(var_ast_expr, ast3.Expr):
3096
- raise self.ice("Invalid special var ref for pyast generation")
3097
- var_ast = var_ast_expr.value
3098
- except Exception:
3099
- raise self.ice("Invalid special var ref for pyast generation")
3100
- node.gen.py_ast = [self.sync(var_ast, deep=True)]
3120
+ if node.name == Tok.KW_SUPER:
3121
+ node.gen.py_ast = [
3122
+ self.sync(
3123
+ ast3.Call(
3124
+ func=self.sync(ast3.Name(id="super", ctx=node.py_ctx_func())),
3125
+ args=[],
3126
+ keywords=[],
3127
+ )
3128
+ )
3129
+ ]
3130
+ elif node.name == Tok.KW_ROOT:
3131
+ node.gen.py_ast = [
3132
+ self.sync(
3133
+ ast3.Call(
3134
+ func=self.sync(
3135
+ ast3.Attribute(
3136
+ value=self.sync(
3137
+ ast3.Name(
3138
+ id=Con.JAC_FEATURE.value,
3139
+ ctx=ast3.Load(),
3140
+ )
3141
+ ),
3142
+ attr="get_root",
3143
+ ctx=ast3.Load(),
3144
+ )
3145
+ ),
3146
+ args=[],
3147
+ keywords=[],
3148
+ )
3149
+ )
3150
+ ]
3151
+
3152
+ else:
3153
+ node.gen.py_ast = [
3154
+ self.sync(ast3.Name(id=node.sym_name, ctx=node.py_ctx_func()))
3155
+ ]
3101
3156
 
3102
3157
  def exit_edge_ref_trailer(self, node: ast.EdgeRefTrailer) -> None:
3103
3158
  """Sub objects.
@@ -3577,7 +3632,7 @@ class PyastGenPass(Pass):
3577
3632
  [
3578
3633
  x.key.sym_name
3579
3634
  for x in node.kw_patterns.items
3580
- if isinstance(x.key, ast.NameSpec)
3635
+ if isinstance(x.key, ast.NameAtom)
3581
3636
  ]
3582
3637
  if node.kw_patterns
3583
3638
  else []
@@ -150,6 +150,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
150
150
  node.name if node.name != "root" else "root_"
151
151
  ), # root is a reserved keyword
152
152
  line=node.lineno,
153
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
153
154
  col_start=node.col_offset,
154
155
  col_end=node.col_offset + len(node.name),
155
156
  pos_start=0,
@@ -262,6 +263,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
262
263
  name=Tok.NAME,
263
264
  value=node.name,
264
265
  line=node.lineno,
266
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
265
267
  col_start=node.col_offset,
266
268
  col_end=node.col_offset + len(node.name),
267
269
  pos_start=0,
@@ -272,6 +274,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
272
274
  name=Tok.KW_CLASS,
273
275
  value="class",
274
276
  line=node.lineno,
277
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
275
278
  col_start=0,
276
279
  col_end=0,
277
280
  pos_start=0,
@@ -284,17 +287,18 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
284
287
  and isinstance(body_stmt.name_ref, ast.Name)
285
288
  and body_stmt.name_ref.value == "__init__"
286
289
  ):
287
- tok = ast.Token(
290
+ tok = ast.Name(
288
291
  file_path=self.mod_path,
289
292
  name=Tok.KW_INIT,
290
293
  value="init",
291
294
  line=node.lineno,
295
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
292
296
  col_start=node.col_offset,
293
297
  col_end=node.col_offset + len("init"),
294
298
  pos_start=0,
295
299
  pos_end=0,
296
300
  )
297
- body_stmt.name_ref = ast.SpecialVarRef(var=tok, kid=[tok])
301
+ body_stmt.name_ref = ast.SpecialVarRef(var=tok)
298
302
  if (
299
303
  isinstance(body_stmt, ast.Ability)
300
304
  and body_stmt.signature
@@ -373,17 +377,18 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
373
377
  converted_stmt.expr, ast.String
374
378
  ):
375
379
  continue
376
- tok = ast.Token(
380
+ pintok = ast.Token(
377
381
  file_path=self.mod_path,
378
382
  name=Tok.PYNLINE,
379
383
  value=py_ast.unparse(class_body_stmt),
380
384
  line=node.lineno,
385
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
381
386
  col_start=node.col_offset,
382
387
  col_end=node.col_offset + len(py_ast.unparse(class_body_stmt)),
383
388
  pos_start=0,
384
389
  pos_end=0,
385
390
  )
386
- valid_enum_body.append(ast.PyInlineCode(code=tok, kid=[tok]))
391
+ valid_enum_body.append(ast.PyInlineCode(code=pintok, kid=[pintok]))
387
392
 
388
393
  valid_enum_body2: list[ast.EnumBlockStmt] = [
389
394
  i for i in valid_enum_body if isinstance(i, ast.EnumBlockStmt)
@@ -903,17 +908,18 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
903
908
  and isinstance(value.target, ast.Name)
904
909
  and value.target.value == "super"
905
910
  ):
906
- tok = ast.Token(
911
+ tok = ast.Name(
907
912
  file_path=self.mod_path,
908
913
  name=Tok.KW_SUPER,
909
914
  value="super",
910
915
  line=node.lineno,
916
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
911
917
  col_start=node.col_offset,
912
918
  col_end=node.col_offset + len("super"),
913
919
  pos_start=0,
914
920
  pos_end=0,
915
921
  )
916
- value = ast.SpecialVarRef(var=tok, kid=[tok])
922
+ value = ast.SpecialVarRef(var=tok)
917
923
  # exit()
918
924
  attribute = ast.Name(
919
925
  file_path=self.mod_path,
@@ -924,6 +930,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
924
930
  else "init" if node.attr == "__init__" else node.attr
925
931
  ),
926
932
  line=node.lineno,
933
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
927
934
  col_start=node.col_offset,
928
935
  col_end=node.col_offset + len(node.attr),
929
936
  pos_start=0,
@@ -1030,6 +1037,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1030
1037
  name=Tok.KW_BREAK,
1031
1038
  value="break",
1032
1039
  line=0,
1040
+ end_line=0,
1033
1041
  col_start=0,
1034
1042
  col_end=0,
1035
1043
  pos_start=0,
@@ -1144,6 +1152,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1144
1152
  else str(node.value)
1145
1153
  ),
1146
1154
  line=node.lineno,
1155
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1147
1156
  col_start=node.col_offset,
1148
1157
  col_end=node.col_offset + len(str(node.value)),
1149
1158
  pos_start=0,
@@ -1155,6 +1164,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1155
1164
  name=Tok.ELLIPSIS,
1156
1165
  value="...",
1157
1166
  line=node.lineno,
1167
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1158
1168
  col_start=node.col_offset,
1159
1169
  col_end=node.col_offset + 3,
1160
1170
  pos_start=0,
@@ -1170,6 +1180,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1170
1180
  name=Tok.KW_CONTINUE,
1171
1181
  value="continue",
1172
1182
  line=0,
1183
+ end_line=0,
1173
1184
  col_start=0,
1174
1185
  col_end=0,
1175
1186
  pos_start=0,
@@ -1246,6 +1257,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1246
1257
  name=Tok.NAME,
1247
1258
  value="Exception",
1248
1259
  line=node.lineno,
1260
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1249
1261
  col_start=node.col_offset,
1250
1262
  col_end=node.col_offset + 9,
1251
1263
  pos_start=0,
@@ -1256,6 +1268,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1256
1268
  name=Tok.NAME,
1257
1269
  value="e",
1258
1270
  line=node.lineno,
1271
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1259
1272
  col_start=node.col_offset,
1260
1273
  col_end=node.col_offset + 1,
1261
1274
  pos_start=0,
@@ -1267,6 +1280,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1267
1280
  # name=Tok.NAME,
1268
1281
  # value=no,
1269
1282
  # line=node.lineno,
1283
+ # end_line = (node.end_lineno if node.end_lineno else node.lineno,)
1270
1284
  # col_start=node.col_offset,
1271
1285
  # col_end=node.col_offset + 9,
1272
1286
  # pos_start=0,
@@ -1278,6 +1292,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1278
1292
  name=Tok.NAME,
1279
1293
  value=node.name,
1280
1294
  line=node.lineno,
1295
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1281
1296
  col_start=node.col_offset,
1282
1297
  col_end=node.col_offset + len(node.name),
1283
1298
  pos_start=0,
@@ -1369,7 +1384,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1369
1384
  class Global(stmt):
1370
1385
  names: list[_Identifier]
1371
1386
  """
1372
- names: list[ast.NameSpec] = []
1387
+ names: list[ast.NameAtom] = []
1373
1388
  for id in node.names:
1374
1389
  names.append(
1375
1390
  ast.Name(
@@ -1377,13 +1392,14 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1377
1392
  name=Tok.NAME,
1378
1393
  value=id,
1379
1394
  line=node.lineno,
1395
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1380
1396
  col_start=node.col_offset,
1381
1397
  col_end=node.col_offset + len(id),
1382
1398
  pos_start=0,
1383
1399
  pos_end=0,
1384
1400
  )
1385
1401
  )
1386
- target = ast.SubNodeList[ast.NameSpec](items=names, delim=Tok.COMMA, kid=names)
1402
+ target = ast.SubNodeList[ast.NameAtom](items=names, delim=Tok.COMMA, kid=names)
1387
1403
  return ast.GlobalStmt(target=target, kid=[target])
1388
1404
 
1389
1405
  def proc_if_exp(self, node: py_ast.IfExp) -> ast.IfElseExpr:
@@ -1439,6 +1455,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1439
1455
  name=Tok.NAME,
1440
1456
  value="py",
1441
1457
  line=node.lineno,
1458
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1442
1459
  col_start=node.col_offset,
1443
1460
  col_end=0,
1444
1461
  pos_start=0,
@@ -1468,6 +1485,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1468
1485
  name=Tok.NAME,
1469
1486
  value="py",
1470
1487
  line=node.lineno,
1488
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1471
1489
  col_start=node.col_offset,
1472
1490
  col_end=0,
1473
1491
  pos_start=0,
@@ -1482,6 +1500,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1482
1500
  name=Tok.NAME,
1483
1501
  value=i,
1484
1502
  line=node.lineno,
1503
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1485
1504
  col_start=0,
1486
1505
  col_end=0,
1487
1506
  pos_start=0,
@@ -1643,6 +1662,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1643
1662
  name=Tok.NAME,
1644
1663
  value=node.name if node.name else "_",
1645
1664
  line=node.lineno,
1665
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1646
1666
  col_start=node.col_offset,
1647
1667
  col_end=(
1648
1668
  (node.col_offset + len(node.name))
@@ -1696,6 +1716,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1696
1716
  name=Tok.NAME,
1697
1717
  value=kwd_attrs,
1698
1718
  line=node.lineno,
1719
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1699
1720
  col_start=node.col_offset,
1700
1721
  col_end=node.col_offset + len(kwd_attrs),
1701
1722
  pos_start=0,
@@ -1720,7 +1741,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1720
1741
  kid.append(kw_patterns)
1721
1742
  else:
1722
1743
  kw_patterns = None
1723
- if isinstance(cls, (ast.NameSpec, ast.AtomTrailer)):
1744
+ if isinstance(cls, (ast.NameAtom, ast.AtomTrailer)):
1724
1745
  return ast.MatchArch(
1725
1746
  name=cls, arg_patterns=patterns_sub, kw_patterns=kw_patterns, kid=kid
1726
1747
  )
@@ -1738,7 +1759,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1738
1759
  values: list[ast.MatchKVPair | ast.MatchStar] = []
1739
1760
  keys = [self.convert(i) for i in node.keys]
1740
1761
  valid_keys = [
1741
- i for i in keys if isinstance(i, (ast.MatchPattern, ast.NameSpec))
1762
+ i for i in keys if isinstance(i, (ast.MatchPattern, ast.NameAtom))
1742
1763
  ]
1743
1764
  patterns = [self.convert(i) for i in node.patterns]
1744
1765
  valid_patterns = [i for i in patterns if isinstance(i, ast.MatchPattern)]
@@ -1755,6 +1776,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1755
1776
  name=Tok.NAME,
1756
1777
  value=node.rest,
1757
1778
  line=node.lineno,
1779
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1758
1780
  col_start=node.col_offset,
1759
1781
  col_end=node.col_offset + len(node.rest),
1760
1782
  pos_start=0,
@@ -1799,6 +1821,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1799
1821
  name=type,
1800
1822
  value=str(node.value),
1801
1823
  line=node.lineno,
1824
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1802
1825
  col_start=node.col_offset,
1803
1826
  col_end=node.col_offset + len(str(node.value)),
1804
1827
  pos_start=0,
@@ -1820,6 +1843,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1820
1843
  name=Tok.NAME,
1821
1844
  value=node.name if node.name else "_",
1822
1845
  line=node.lineno,
1846
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1823
1847
  col_start=node.col_offset,
1824
1848
  col_end=node.col_offset + len(node.name if node.name else "_"),
1825
1849
  pos_start=0,
@@ -1853,6 +1877,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1853
1877
  name=Tok.NAME,
1854
1878
  value=node.id if node.id != "root" else "root_", # reserved word
1855
1879
  line=node.lineno,
1880
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1856
1881
  col_start=node.col_offset,
1857
1882
  col_end=node.col_offset + len(node.id),
1858
1883
  pos_start=0,
@@ -1885,7 +1910,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1885
1910
  class Nonlocal(stmt):
1886
1911
  names: list[_Identifier]
1887
1912
  """
1888
- names: list[ast.NameSpec] = []
1913
+ names: list[ast.NameAtom] = []
1889
1914
  for name in node.names:
1890
1915
  names.append(
1891
1916
  ast.Name(
@@ -1893,13 +1918,14 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1893
1918
  name=Tok.NAME,
1894
1919
  value=name if name != "root" else "root_",
1895
1920
  line=node.lineno,
1921
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
1896
1922
  col_start=node.col_offset,
1897
1923
  col_end=node.col_offset + len(name),
1898
1924
  pos_start=0,
1899
1925
  pos_end=0,
1900
1926
  )
1901
1927
  )
1902
- target = ast.SubNodeList[ast.NameSpec](items=names, delim=Tok.COMMA, kid=names)
1928
+ target = ast.SubNodeList[ast.NameAtom](items=names, delim=Tok.COMMA, kid=names)
1903
1929
  return ast.NonLocalStmt(target=target, kid=names)
1904
1930
 
1905
1931
  def proc_pass(self, node: py_ast.Pass) -> ast.Semi:
@@ -1909,6 +1935,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1909
1935
  name=Tok.SEMI,
1910
1936
  value=";",
1911
1937
  line=0,
1938
+ end_line=0,
1912
1939
  col_start=0,
1913
1940
  col_end=0,
1914
1941
  pos_start=0,
@@ -2176,6 +2203,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2176
2203
  name=Tok.NAME,
2177
2204
  value=node.name,
2178
2205
  line=node.lineno,
2206
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
2179
2207
  col_start=node.col_offset,
2180
2208
  col_end=node.col_offset + len(node.name),
2181
2209
  pos_start=0,
@@ -2187,6 +2215,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2187
2215
  name=Tok.NAME,
2188
2216
  value=node.asname,
2189
2217
  line=node.lineno,
2218
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
2190
2219
  col_start=node.col_offset,
2191
2220
  col_end=node.col_offset + len(node.asname),
2192
2221
  pos_start=0,
@@ -2211,6 +2240,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2211
2240
  name=Tok.NAME,
2212
2241
  value=node.arg if node.arg != "root" else "root_", # reserved word
2213
2242
  line=node.lineno,
2243
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
2214
2244
  col_start=node.col_offset,
2215
2245
  col_end=node.col_offset + len(node.arg),
2216
2246
  pos_start=0,
@@ -2224,6 +2254,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2224
2254
  name=Tok.NAME,
2225
2255
  value="Any",
2226
2256
  line=node.lineno,
2257
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
2227
2258
  col_start=node.col_offset,
2228
2259
  col_end=node.col_offset + 3,
2229
2260
  pos_start=0,
@@ -2257,6 +2288,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2257
2288
  name=Tok.STAR_MUL,
2258
2289
  value="*",
2259
2290
  line=vararg.loc.first_line,
2291
+ end_line=vararg.loc.last_line,
2260
2292
  col_start=vararg.loc.col_start,
2261
2293
  col_end=vararg.loc.col_end,
2262
2294
  pos_start=0,
@@ -2282,6 +2314,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2282
2314
  name=Tok.STAR_POW,
2283
2315
  value="**",
2284
2316
  line=kwarg.loc.first_line,
2317
+ end_line=kwarg.loc.last_line,
2285
2318
  col_start=kwarg.loc.col_start,
2286
2319
  col_end=kwarg.loc.col_end,
2287
2320
  pos_start=0,
@@ -2327,6 +2360,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2327
2360
  name=tok,
2328
2361
  value=value,
2329
2362
  line=0,
2363
+ end_line=0,
2330
2364
  col_start=0,
2331
2365
  col_end=0,
2332
2366
  pos_start=0,
@@ -2491,6 +2525,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2491
2525
  name=Tok.NAME,
2492
2526
  value=node.arg if node.arg else "_",
2493
2527
  line=node.lineno,
2528
+ end_line=node.end_lineno if node.end_lineno else node.lineno,
2494
2529
  col_start=node.col_offset,
2495
2530
  col_end=node.col_offset + len(node.arg if node.arg else "_"),
2496
2531
  pos_start=0,
@@ -57,10 +57,13 @@ class PyJacAstLinkPass(Pass):
57
57
  decorators: Optional[SubNodeList[ExprType]],
58
58
  """
59
59
  for i in node.target.archs:
60
- if i.sym_link:
61
- self.link_jac_py_nodes(jac_node=i, py_nodes=i.sym_link.decl.gen.py_ast)
60
+ if i.name_spec.name_of.sym:
62
61
  self.link_jac_py_nodes(
63
- jac_node=i.name_ref, py_nodes=i.sym_link.decl.gen.py_ast
62
+ jac_node=i, py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast
63
+ )
64
+ self.link_jac_py_nodes(
65
+ jac_node=i.name_spec,
66
+ py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast,
64
67
  )
65
68
 
66
69
  def exit_enum(self, node: ast.Enum) -> None:
@@ -85,10 +88,13 @@ class PyJacAstLinkPass(Pass):
85
88
  decorators: Optional[SubNodeList[ExprType]],
86
89
  """
87
90
  for i in node.target.archs:
88
- if i.sym_link:
89
- self.link_jac_py_nodes(jac_node=i, py_nodes=i.sym_link.decl.gen.py_ast)
91
+ if i.name_spec.name_of.sym:
92
+ self.link_jac_py_nodes(
93
+ jac_node=i, py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast
94
+ )
90
95
  self.link_jac_py_nodes(
91
- jac_node=i.name_ref, py_nodes=i.sym_link.decl.gen.py_ast
96
+ jac_node=i.name_spec,
97
+ py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast,
92
98
  )
93
99
 
94
100
  def exit_ability(self, node: ast.Ability) -> None:
@@ -119,10 +125,13 @@ class PyJacAstLinkPass(Pass):
119
125
  decorators: Optional[SubNodeList[ExprType]],
120
126
  """
121
127
  for i in node.target.archs:
122
- if i.sym_link:
123
- self.link_jac_py_nodes(jac_node=i, py_nodes=i.sym_link.decl.gen.py_ast)
128
+ if i.name_spec.name_of.sym:
129
+ self.link_jac_py_nodes(
130
+ jac_node=i, py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast
131
+ )
124
132
  self.link_jac_py_nodes(
125
- jac_node=i.name_ref, py_nodes=i.sym_link.decl.gen.py_ast
133
+ jac_node=i.name_spec,
134
+ py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast,
126
135
  )
127
136
 
128
137
  if isinstance(node.parent, ast.Ability) and node.parent.signature:
@@ -219,5 +228,5 @@ class PyJacAstLinkPass(Pass):
219
228
  """
220
229
  if node.is_attr and isinstance(node.right, ast.AstSymbolNode):
221
230
  self.link_jac_py_nodes(
222
- jac_node=node.right.sym_name_node, py_nodes=node.gen.py_ast
231
+ jac_node=node.right.name_spec, py_nodes=node.gen.py_ast
223
232
  )