jaclang 0.8.7__py3-none-any.whl → 0.8.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 (99) hide show
  1. jaclang/cli/cli.py +77 -29
  2. jaclang/cli/cmdreg.py +44 -0
  3. jaclang/compiler/constant.py +6 -2
  4. jaclang/compiler/jac.lark +37 -47
  5. jaclang/compiler/larkparse/jac_parser.py +2 -2
  6. jaclang/compiler/parser.py +356 -61
  7. jaclang/compiler/passes/main/__init__.py +2 -4
  8. jaclang/compiler/passes/main/def_use_pass.py +1 -4
  9. jaclang/compiler/passes/main/predynamo_pass.py +221 -0
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +221 -135
  11. jaclang/compiler/passes/main/pyast_load_pass.py +54 -20
  12. jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
  13. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
  14. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
  15. jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
  16. jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
  17. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
  18. jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
  19. jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
  20. jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
  21. jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
  22. jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
  23. jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
  24. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
  25. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
  26. jaclang/compiler/passes/main/tests/test_checker_pass.py +190 -0
  27. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +56 -0
  28. jaclang/compiler/passes/main/type_checker_pass.py +29 -73
  29. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +302 -58
  30. jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
  31. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
  32. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
  33. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
  34. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +276 -10
  35. jaclang/compiler/passes/transform.py +12 -8
  36. jaclang/compiler/program.py +19 -7
  37. jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
  38. jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
  39. jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
  40. jaclang/compiler/tests/fixtures/python_module.py +1 -0
  41. jaclang/compiler/tests/test_importer.py +39 -0
  42. jaclang/compiler/tests/test_parser.py +49 -0
  43. jaclang/compiler/type_system/type_evaluator.jac +959 -0
  44. jaclang/compiler/type_system/type_utils.py +246 -0
  45. jaclang/compiler/type_system/types.py +58 -2
  46. jaclang/compiler/unitree.py +102 -107
  47. jaclang/langserve/engine.jac +138 -159
  48. jaclang/langserve/server.jac +25 -1
  49. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  50. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  51. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  52. jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
  53. jaclang/langserve/tests/server_test/circle_template.jac +80 -0
  54. jaclang/langserve/tests/server_test/glob_template.jac +4 -0
  55. jaclang/langserve/tests/server_test/test_lang_serve.py +154 -309
  56. jaclang/langserve/tests/server_test/utils.py +153 -116
  57. jaclang/langserve/tests/test_server.py +21 -84
  58. jaclang/langserve/utils.jac +12 -15
  59. jaclang/lib.py +17 -0
  60. jaclang/runtimelib/archetype.py +25 -25
  61. jaclang/runtimelib/constructs.py +2 -2
  62. jaclang/runtimelib/machine.py +63 -46
  63. jaclang/runtimelib/meta_importer.py +27 -1
  64. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  65. jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
  66. jaclang/settings.py +19 -16
  67. jaclang/tests/fixtures/abc_check.jac +3 -3
  68. jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
  69. jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
  70. jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
  71. jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
  72. jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
  73. jaclang/tests/fixtures/funccall_genexpr.py +5 -0
  74. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  75. jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
  76. jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
  77. jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
  78. jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
  79. jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
  80. jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
  81. jaclang/tests/fixtures/py2jac_params.py +8 -0
  82. jaclang/tests/fixtures/run_test.jac +4 -4
  83. jaclang/tests/test_cli.py +159 -7
  84. jaclang/tests/test_language.py +213 -38
  85. jaclang/tests/test_reference.py +3 -1
  86. jaclang/utils/helpers.py +67 -6
  87. jaclang/utils/module_resolver.py +10 -0
  88. jaclang/utils/test.py +8 -0
  89. jaclang/utils/tests/test_lang_tools.py +4 -15
  90. jaclang/utils/treeprinter.py +0 -18
  91. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -2
  92. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/RECORD +95 -65
  93. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/WHEEL +1 -1
  94. jaclang/compiler/passes/main/inheritance_pass.py +0 -131
  95. jaclang/compiler/type_system/type_evaluator.py +0 -560
  96. jaclang/langserve/dev_engine.jac +0 -645
  97. jaclang/langserve/dev_server.jac +0 -201
  98. /jaclang/{langserve/tests/server_test/code_test.py → tests/fixtures/py2jac_empty.py} +0 -0
  99. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
@@ -64,7 +64,6 @@ TOKEN_AST_MAP: dict[Tok, type[ast3.AST]] = {
64
64
  Tok.MINUS: ast3.Sub,
65
65
  Tok.SUB_EQ: ast3.Sub,
66
66
  Tok.BW_NOT: ast3.Invert,
67
- Tok.BW_NOT_EQ: ast3.Invert,
68
67
  Tok.NOT: ast3.Not,
69
68
  Tok.EQ: ast3.NotEq,
70
69
  Tok.EE: ast3.Eq,
@@ -92,11 +91,34 @@ UNARY_OP_MAP: dict[Tok, type[ast3.unaryop]] = {
92
91
  class PyastGenPass(UniPass):
93
92
  """Jac blue transpilation to python pass."""
94
93
 
94
+ # Builtins that should be imported from jaclang.runtimelib.builtin
95
+ KNOWN_BUILTINS = {
96
+ "abstractmethod",
97
+ "ClassVar",
98
+ "override",
99
+ "printgraph",
100
+ "jid",
101
+ "jobj",
102
+ "grant",
103
+ "revoke",
104
+ "allroots",
105
+ "save",
106
+ "commit",
107
+ "NoPerm",
108
+ "ReadPerm",
109
+ "ConnectPerm",
110
+ "WritePerm",
111
+ }
112
+
95
113
  def before_pass(self) -> None:
114
+ self.child_passes: list[PyastGenPass] = []
96
115
  for i in self.ir_in.impl_mod + self.ir_in.test_mod:
97
- PyastGenPass(ir_in=i, prog=self.prog)
116
+ child_pass = PyastGenPass(ir_in=i, prog=self.prog)
117
+ self.child_passes.append(child_pass)
98
118
  self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
99
119
  self.already_added: list[str] = []
120
+ self.jaclib_imports: set[str] = set() # Track individual jaclib imports
121
+ self.builtin_imports: set[str] = set() # Track individual builtin imports
100
122
  self.preamble: list[ast3.AST] = [
101
123
  self.sync(
102
124
  ast3.ImportFrom(
@@ -106,40 +128,6 @@ class PyastGenPass(UniPass):
106
128
  ),
107
129
  jac_node=self.ir_out,
108
130
  ),
109
- (
110
- self.sync(
111
- ast3.ImportFrom(
112
- module="jaclang.runtimelib.builtin",
113
- names=[
114
- self.sync(
115
- ast3.alias(
116
- name="*",
117
- asname=None,
118
- )
119
- )
120
- ],
121
- level=0,
122
- ),
123
- jac_node=self.ir_out,
124
- )
125
- ),
126
- (
127
- self.sync(
128
- ast3.ImportFrom(
129
- module="jaclang",
130
- names=[
131
- self.sync(
132
- ast3.alias(
133
- name="JacMachineInterface",
134
- asname=settings.pyout_jaclib_alias,
135
- )
136
- ),
137
- ],
138
- level=0,
139
- ),
140
- jac_node=self.ir_out,
141
- )
142
- ),
143
131
  ]
144
132
 
145
133
  def enter_node(self, node: uni.UniNode) -> None:
@@ -161,15 +149,31 @@ class PyastGenPass(UniPass):
161
149
 
162
150
  def jaclib_obj(self, obj_name: str) -> ast3.Name | ast3.Attribute:
163
151
  """Return the object from jaclib as ast node based on the import config."""
164
- return self.sync(
165
- ast3.Attribute(
166
- value=self.sync(
167
- ast3.Name(id=settings.pyout_jaclib_alias, ctx=ast3.Load())
168
- ),
169
- attr=obj_name,
170
- ctx=ast3.Load(),
152
+ if settings.library_mode:
153
+ self.jaclib_imports.add(obj_name)
154
+ return self.sync(ast3.Name(id=obj_name, ctx=ast3.Load()))
155
+ else:
156
+ self.needs_jaclib()
157
+ return self.sync(
158
+ ast3.Attribute(
159
+ value=self.sync(
160
+ ast3.Name(id=settings.pyout_jaclib_alias, ctx=ast3.Load())
161
+ ),
162
+ attr=obj_name,
163
+ ctx=ast3.Load(),
164
+ )
171
165
  )
172
- )
166
+
167
+ def builtin_name(self, name: str) -> ast3.Name:
168
+ """Return a builtin name and track it for importing.
169
+
170
+ Note: Some names like 'Enum' are provided by other imports (e.g., needs_enum)
171
+ and should not be added to builtin_imports.
172
+ """
173
+ # Enum is imported via needs_enum, not from builtins
174
+ if name not in ["Enum"]:
175
+ self.builtin_imports.add(name)
176
+ return self.sync(ast3.Name(id=name, ctx=ast3.Load()))
173
177
 
174
178
  def _add_preamble_once(self, key: str, node: ast3.AST) -> None:
175
179
  """Append an import statement to the preamble once."""
@@ -187,15 +191,6 @@ class PyastGenPass(UniPass):
187
191
  ),
188
192
  )
189
193
 
190
- def needs_mtllm(self) -> None:
191
- """Ensure byLLM is imported only once."""
192
- self._add_preamble_once(
193
- self.needs_mtllm.__name__,
194
- ast3.Import(
195
- names=[self.sync(ast3.alias(name="byllm"), jac_node=self.ir_out)]
196
- ),
197
- )
198
-
199
194
  def needs_enum(self) -> None:
200
195
  """Ensure Enum utilities are imported only once."""
201
196
  self._add_preamble_once(
@@ -221,6 +216,24 @@ class PyastGenPass(UniPass):
221
216
  ),
222
217
  )
223
218
 
219
+ def needs_jaclib(self) -> None:
220
+ """Ensure JacMachineInterface is imported only once."""
221
+ self._add_preamble_once(
222
+ self.needs_jaclib.__name__,
223
+ ast3.ImportFrom(
224
+ module="jaclang",
225
+ names=[
226
+ self.sync(
227
+ ast3.alias(
228
+ name="JacMachineInterface",
229
+ asname=settings.pyout_jaclib_alias,
230
+ )
231
+ )
232
+ ],
233
+ level=0,
234
+ ),
235
+ )
236
+
224
237
  def _get_sem_decorator(self, node: uni.UniNode) -> ast3.Call | None:
225
238
  """Create a semstring decorator for the given semantic strings.
226
239
 
@@ -283,7 +296,10 @@ class PyastGenPass(UniPass):
283
296
  else {}
284
297
  )
285
298
 
286
- if not semstr and not inner_semstr:
299
+ # Only add sem decorator if there's actual semantic content
300
+ if not semstr and (
301
+ not inner_semstr or all(not v for v in inner_semstr.values())
302
+ ):
287
303
  return None
288
304
 
289
305
  return self.sync(
@@ -417,6 +433,48 @@ class PyastGenPass(UniPass):
417
433
  node.gen.py_ast = node.tag.gen.py_ast
418
434
 
419
435
  def exit_module(self, node: uni.Module) -> None:
436
+ # Check if any child passes (impl_mod or test_mod) needed jaclib
437
+ for child_pass in self.child_passes:
438
+ if "needs_jaclib" in child_pass.already_added:
439
+ self.needs_jaclib()
440
+ break
441
+ # Merge jaclib and builtin imports from child passes
442
+ if settings.library_mode:
443
+ self.jaclib_imports.update(child_pass.jaclib_imports)
444
+ self.builtin_imports.update(child_pass.builtin_imports)
445
+
446
+ # Add builtin imports if any were used
447
+ if self.builtin_imports:
448
+ self.preamble.append(
449
+ self.sync(
450
+ ast3.ImportFrom(
451
+ module="jaclang.runtimelib.builtin",
452
+ names=[
453
+ self.sync(ast3.alias(name=name, asname=None))
454
+ for name in sorted(self.builtin_imports)
455
+ ],
456
+ level=0,
457
+ ),
458
+ jac_node=self.ir_out,
459
+ )
460
+ )
461
+
462
+ # Add library mode imports at the end of preamble
463
+ if settings.library_mode and self.jaclib_imports:
464
+ self.preamble.append(
465
+ self.sync(
466
+ ast3.ImportFrom(
467
+ module="jaclang.lib",
468
+ names=[
469
+ self.sync(ast3.alias(name=name, asname=None))
470
+ for name in sorted(self.jaclib_imports)
471
+ ],
472
+ level=0,
473
+ ),
474
+ jac_node=self.ir_out,
475
+ )
476
+ )
477
+
420
478
  clean_body = [i for i in node.body if not isinstance(i, uni.ImplDef)]
421
479
  pre_body: list[uni.UniNode] = []
422
480
  for pbody in node.impl_mod:
@@ -722,7 +780,7 @@ class PyastGenPass(UniPass):
722
780
  decorators.append(sem_decorator)
723
781
 
724
782
  base_classes = [cast(ast3.expr, i.gen.py_ast[0]) for i in node.base_classes]
725
- base_classes.append(self.sync(ast3.Name(id="Enum", ctx=ast3.Load())))
783
+ base_classes.append(self.builtin_name("Enum"))
726
784
  node.gen.py_ast = [
727
785
  self.sync(
728
786
  ast3.ClassDef(
@@ -744,23 +802,9 @@ class PyastGenPass(UniPass):
744
802
  self, model: ast3.expr, caller: ast3.expr, args: ast3.Dict
745
803
  ) -> ast3.Call:
746
804
  """Reusable method to codegen call_llm(model, caller, args)."""
747
- self.needs_mtllm()
748
- mtir_cls_ast = self.sync(
749
- ast3.Attribute(
750
- value=self.sync(ast3.Name(id="byllm", ctx=ast3.Load())),
751
- attr="MTIR",
752
- ctx=ast3.Load(),
753
- )
754
- )
755
805
  mtir_ast = self.sync(
756
806
  ast3.Call(
757
- func=self.sync(
758
- ast3.Attribute(
759
- value=mtir_cls_ast,
760
- attr="factory",
761
- ctx=ast3.Load(),
762
- )
763
- ),
807
+ func=self.jaclib_obj("get_mtir"),
764
808
  args=[],
765
809
  keywords=[
766
810
  self.sync(
@@ -928,7 +972,9 @@ class PyastGenPass(UniPass):
928
972
  if isinstance(node.signature, uni.EventSignature):
929
973
  decorator_list.append(
930
974
  self.jaclib_obj(
931
- "entry" if node.signature.event.name == Tok.KW_ENTRY else "exit"
975
+ "on_entry"
976
+ if node.signature.event.name == Tok.KW_ENTRY
977
+ else "on_exit"
932
978
  )
933
979
  )
934
980
 
@@ -943,11 +989,9 @@ class PyastGenPass(UniPass):
943
989
  )
944
990
  )
945
991
  if node.is_abstract:
946
- decorator_list.append(
947
- self.sync(ast3.Name(id="abstractmethod", ctx=ast3.Load()))
948
- )
992
+ decorator_list.append(self.builtin_name("abstractmethod"))
949
993
  if node.is_override:
950
- decorator_list.append(self.sync(ast3.Name(id="override", ctx=ast3.Load())))
994
+ decorator_list.append(self.builtin_name("override"))
951
995
  if node.is_static:
952
996
  decorator_list.insert(
953
997
  0, self.sync(ast3.Name(id="staticmethod", ctx=ast3.Load()))
@@ -1000,6 +1044,9 @@ class PyastGenPass(UniPass):
1000
1044
  pass
1001
1045
 
1002
1046
  def exit_func_signature(self, node: uni.FuncSignature) -> None:
1047
+ posonlyargs = [i.gen.py_ast[0] for i in node.posonly_params]
1048
+ vararg = node.varargs.gen.py_ast[0] if node.varargs else None
1049
+ kwarg = node.kwargs.gen.py_ast[0] if node.kwargs else None
1003
1050
  params = (
1004
1051
  [self.sync(ast3.arg(arg="self", annotation=None))]
1005
1052
  if (abl := node.parent)
@@ -1009,29 +1056,33 @@ class PyastGenPass(UniPass):
1009
1056
  and not node.is_in_py_class
1010
1057
  else []
1011
1058
  )
1012
- vararg = None
1013
- kwarg = None
1014
- for i in node.params:
1015
- if i.unpack and i.unpack.value == "*":
1016
- vararg = i.gen.py_ast[0]
1017
- elif i.unpack and i.unpack.value == "**":
1018
- kwarg = i.gen.py_ast[0]
1059
+ if posonlyargs:
1060
+ posonlyargs = params + posonlyargs
1061
+ params = [i.gen.py_ast[0] for i in node.params]
1062
+ else:
1063
+ params = params + [i.gen.py_ast[0] for i in node.params]
1064
+ defaults = []
1065
+ for i in [*node.posonly_params, *node.params]:
1066
+ if i.value:
1067
+ defaults.append(cast(ast3.expr, i.value.gen.py_ast[0]))
1068
+ kwonly_args = [i.gen.py_ast[0] for i in node.kwonlyargs]
1069
+ # kw_defaults must be the same length as kwonlyargs
1070
+ # it will have None for args that don't have defaults
1071
+ kw_defaults: list[ast3.expr | None] = []
1072
+ for i in node.kwonlyargs:
1073
+ if i.value:
1074
+ kw_defaults.append(cast(ast3.expr, i.value.gen.py_ast[0]))
1019
1075
  else:
1020
- (
1021
- params.append(i.gen.py_ast[0])
1022
- if isinstance(i.gen.py_ast[0], ast3.arg)
1023
- else self.ice("This list should only be Args")
1024
- )
1025
- defaults = [x.value.gen.py_ast[0] for x in node.params if x.value]
1076
+ kw_defaults.append(None)
1026
1077
  node.gen.py_ast = [
1027
1078
  self.sync(
1028
1079
  ast3.arguments(
1029
- posonlyargs=[],
1080
+ posonlyargs=[cast(ast3.arg, param) for param in posonlyargs],
1030
1081
  args=[cast(ast3.arg, param) for param in params],
1031
- kwonlyargs=[],
1082
+ kwonlyargs=kwonly_args,
1032
1083
  vararg=cast(ast3.arg, vararg) if vararg else None,
1033
1084
  kwarg=cast(ast3.arg, kwarg) if kwarg else None,
1034
- kw_defaults=[],
1085
+ kw_defaults=kw_defaults,
1035
1086
  defaults=[cast(ast3.expr, default) for default in defaults],
1036
1087
  )
1037
1088
  )
@@ -1138,7 +1189,7 @@ class PyastGenPass(UniPass):
1138
1189
  elif is_static_var:
1139
1190
  annotation = self.sync(
1140
1191
  ast3.Subscript(
1141
- value=self.sync(ast3.Name(id="ClassVar", ctx=ast3.Load())),
1192
+ value=self.builtin_name("ClassVar"),
1142
1193
  slice=cast(ast3.expr, annotation),
1143
1194
  ctx=ast3.Load(),
1144
1195
  )
@@ -1215,8 +1266,29 @@ class PyastGenPass(UniPass):
1215
1266
  ]
1216
1267
 
1217
1268
  def exit_typed_ctx_block(self, node: uni.TypedCtxBlock) -> None:
1218
- # TODO: Come back
1219
- pass
1269
+ loc = self.sync(
1270
+ ast3.Name(id=Con.HERE.value, ctx=ast3.Load())
1271
+ if node.from_walker
1272
+ else ast3.Name(id=Con.VISITOR.value, ctx=ast3.Load())
1273
+ )
1274
+ node.gen.py_ast = [
1275
+ self.sync(
1276
+ ast3.If(
1277
+ test=self.sync(
1278
+ ast3.Call(
1279
+ func=self.sync(ast3.Name(id="isinstance", ctx=ast3.Load())),
1280
+ args=[
1281
+ loc,
1282
+ cast(ast3.expr, node.type_ctx.gen.py_ast[0]),
1283
+ ],
1284
+ keywords=[],
1285
+ )
1286
+ ),
1287
+ body=cast(list[ast3.stmt], self.resolve_stmt_block(node.body)),
1288
+ orelse=[],
1289
+ )
1290
+ )
1291
+ ]
1220
1292
 
1221
1293
  def exit_if_stmt(self, node: uni.IfStmt) -> None:
1222
1294
  node.gen.py_ast = [
@@ -1467,20 +1539,23 @@ class PyastGenPass(UniPass):
1467
1539
  ]
1468
1540
 
1469
1541
  def exit_assert_stmt(self, node: uni.AssertStmt) -> None:
1470
- node.gen.py_ast = [
1471
- self.sync(
1472
- ast3.Assert(
1473
- test=cast(ast3.expr, node.condition.gen.py_ast[0]),
1474
- msg=(
1475
- cast(ast3.expr, node.error_msg.gen.py_ast[0])
1476
- if node.error_msg
1477
- else None
1478
- ),
1542
+ if isinstance(node.parent, uni.Test):
1543
+ self.assert_helper(node)
1544
+ else:
1545
+ node.gen.py_ast = [
1546
+ self.sync(
1547
+ ast3.Assert(
1548
+ test=cast(ast3.expr, node.condition.gen.py_ast[0]),
1549
+ msg=(
1550
+ cast(ast3.expr, node.error_msg.gen.py_ast[0])
1551
+ if node.error_msg
1552
+ else None
1553
+ ),
1554
+ )
1479
1555
  )
1480
- )
1481
- ]
1556
+ ]
1482
1557
 
1483
- def exit_check_stmt(self, node: uni.CheckStmt) -> None:
1558
+ def assert_helper(self, node: uni.AssertStmt) -> None:
1484
1559
  """Sub objects.
1485
1560
 
1486
1561
  target: ExprType,
@@ -1536,16 +1611,16 @@ class PyastGenPass(UniPass):
1536
1611
 
1537
1612
  # By default the check expression will become assertTrue(<expr>), unless any pattern detected.
1538
1613
  assert_func_name = "assertTrue"
1539
- assert_args_list = node.target.gen.py_ast
1614
+ assert_args_list = node.condition.gen.py_ast
1540
1615
 
1541
1616
  # Compare operations. Note that We're only considering the compare
1542
1617
  # operation with a single operation ie. a < b < c is ignored here.
1543
1618
  if (
1544
- isinstance(node.target, uni.CompareExpr)
1545
- and isinstance(node.target.gen.py_ast[0], ast3.Compare)
1546
- and len(node.target.ops) == 1
1619
+ isinstance(node.condition, uni.CompareExpr)
1620
+ and isinstance(node.condition.gen.py_ast[0], ast3.Compare)
1621
+ and len(node.condition.ops) == 1
1547
1622
  ):
1548
- expr: uni.CompareExpr = node.target
1623
+ expr: uni.CompareExpr = node.condition
1549
1624
  opty: uni.Token = expr.ops[0]
1550
1625
 
1551
1626
  optype2fn = {
@@ -1579,10 +1654,10 @@ class PyastGenPass(UniPass):
1579
1654
  assert_args_list.pop()
1580
1655
 
1581
1656
  # Check if 'isinstance' is called.
1582
- elif isinstance(node.target, uni.FuncCall) and isinstance(
1583
- node.target.gen.py_ast[0], ast3.Call
1657
+ elif isinstance(node.condition, uni.FuncCall) and isinstance(
1658
+ node.condition.gen.py_ast[0], ast3.Call
1584
1659
  ):
1585
- res = check_node_isinstance_call(node.target)
1660
+ res = check_node_isinstance_call(node.condition)
1586
1661
  if res.isit:
1587
1662
  # These assertions will make mypy happy.
1588
1663
  assert isinstance(res.inst, ast3.AST)
@@ -1592,12 +1667,12 @@ class PyastGenPass(UniPass):
1592
1667
 
1593
1668
  # Check if 'not isinstance(<expr>, <expr>)' is called.
1594
1669
  elif (
1595
- isinstance(node.target, uni.UnaryExpr)
1596
- and isinstance(node.target, uni.UnaryExpr)
1597
- and isinstance(node.target.operand, uni.FuncCall)
1598
- and isinstance(node.target.operand, uni.UnaryExpr)
1670
+ isinstance(node.condition, uni.UnaryExpr)
1671
+ and isinstance(node.condition, uni.UnaryExpr)
1672
+ and isinstance(node.condition.operand, uni.FuncCall)
1673
+ and isinstance(node.condition.operand, uni.UnaryExpr)
1599
1674
  ):
1600
- res = check_node_isinstance_call(node.target.operand)
1675
+ res = check_node_isinstance_call(node.condition.operand)
1601
1676
  if res.isit:
1602
1677
  # These assertions will make mypy happy.
1603
1678
  assert isinstance(res.inst, ast3.AST)
@@ -1610,14 +1685,14 @@ class PyastGenPass(UniPass):
1610
1685
  # the almost equal functionality (snice there is no almost equal operator in jac and never needed ig.).
1611
1686
 
1612
1687
  # Check if 'almostEqual' is called.
1613
- if isinstance(node.target, uni.FuncCall) and isinstance(
1614
- node.target.gen.py_ast[0], ast3.Call
1688
+ if isinstance(node.condition, uni.FuncCall) and isinstance(
1689
+ node.condition.gen.py_ast[0], ast3.Call
1615
1690
  ):
1616
- func = node.target.target
1691
+ func = node.condition.target
1617
1692
  if isinstance(func, uni.Name) and func.value == "almostEqual":
1618
1693
  assert_func_name = "assertAlmostEqual"
1619
1694
  assert_args_list = []
1620
- for param in node.target.params:
1695
+ for param in node.condition.params:
1621
1696
  assert_args_list.append(param.gen.py_ast[0])
1622
1697
 
1623
1698
  # assert_func_expr = "Con.JAC_CHECK.value.assertXXX"
@@ -1989,7 +2064,7 @@ class PyastGenPass(UniPass):
1989
2064
  keywords.append(
1990
2065
  self.sync(
1991
2066
  ast3.keyword(
1992
- arg="filter",
2067
+ arg="filter_on",
1993
2068
  value=cast(
1994
2069
  ast3.expr,
1995
2070
  node.op.edge_spec.filter_cond.gen.py_ast[0],
@@ -2196,7 +2271,7 @@ class PyastGenPass(UniPass):
2196
2271
  node.gen.py_ast = [
2197
2272
  self.sync(
2198
2273
  ast3.Call(
2199
- func=self.sync(ast3.Name(id="jobj", ctx=ast3.Load())),
2274
+ func=self.builtin_name("jobj"),
2200
2275
  args=[],
2201
2276
  keywords=[
2202
2277
  self.sync(
@@ -2421,7 +2496,7 @@ class PyastGenPass(UniPass):
2421
2496
  node.gen.py_ast = [
2422
2497
  self.sync(
2423
2498
  ast3.Call(
2424
- func=self.jaclib_obj("filter"),
2499
+ func=self.jaclib_obj("filter_on"),
2425
2500
  args=[],
2426
2501
  keywords=[
2427
2502
  self.sync(
@@ -2444,7 +2519,7 @@ class PyastGenPass(UniPass):
2444
2519
  node.gen.py_ast = [
2445
2520
  self.sync(
2446
2521
  ast3.Call(
2447
- func=self.jaclib_obj("assign"),
2522
+ func=self.jaclib_obj("assign_all"),
2448
2523
  args=cast(
2449
2524
  list[ast3.expr],
2450
2525
  [node.target.gen.py_ast[0], node.right.gen.py_ast[0]],
@@ -2675,7 +2750,7 @@ class PyastGenPass(UniPass):
2675
2750
  func=self.sync(
2676
2751
  ast3.Attribute(
2677
2752
  value=pynode,
2678
- attr=f"_{cur.edge_dir.name.lower()}",
2753
+ attr=f"edge_{cur.edge_dir.name.lower()}",
2679
2754
  ctx=ast3.Load(),
2680
2755
  )
2681
2756
  ),
@@ -2718,14 +2793,22 @@ class PyastGenPass(UniPass):
2718
2793
  keywords=[],
2719
2794
  )
2720
2795
  )
2721
-
2722
- pynode = self.sync(
2723
- ast3.Call(
2724
- func=self.jaclib_obj("refs"),
2725
- args=[pynode],
2726
- keywords=[],
2796
+ if node.is_async:
2797
+ pynode = self.sync(
2798
+ ast3.Call(
2799
+ func=self.jaclib_obj("arefs"),
2800
+ args=[pynode],
2801
+ keywords=[],
2802
+ )
2803
+ )
2804
+ else:
2805
+ pynode = self.sync(
2806
+ ast3.Call(
2807
+ func=self.jaclib_obj("refs"),
2808
+ args=[pynode],
2809
+ keywords=[],
2810
+ )
2727
2811
  )
2728
- )
2729
2812
 
2730
2813
  node.gen.py_ast = [pynode]
2731
2814
 
@@ -3008,6 +3091,9 @@ class PyastGenPass(UniPass):
3008
3091
 
3009
3092
  def exit_name(self, node: uni.Name) -> None:
3010
3093
  name = node.sym_name
3094
+ # Track if this name is a known builtin
3095
+ if name in self.KNOWN_BUILTINS:
3096
+ self.builtin_imports.add(name)
3011
3097
  node.gen.py_ast = [self.sync(ast3.Name(id=name, ctx=node.py_ctx_func()))]
3012
3098
 
3013
3099
  def exit_float(self, node: uni.Float) -> None: