jaclang 0.7.29__py3-none-any.whl → 0.7.31__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 (40) hide show
  1. jaclang/__init__.py +419 -3
  2. jaclang/compiler/__init__.py +1 -1
  3. jaclang/compiler/absyntree.py +15 -5
  4. jaclang/compiler/compile.py +1 -1
  5. jaclang/compiler/constant.py +4 -5
  6. jaclang/compiler/jac.lark +227 -180
  7. jaclang/compiler/parser.py +1335 -1826
  8. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +2 -2
  9. jaclang/compiler/passes/main/import_pass.py +3 -2
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +570 -747
  11. jaclang/compiler/passes/main/tests/test_import_pass.py +4 -1
  12. jaclang/compiler/passes/main/tests/test_type_check_pass.py +6 -3
  13. jaclang/compiler/passes/tool/jac_formatter_pass.py +0 -1
  14. jaclang/compiler/tests/test_importer.py +45 -1
  15. jaclang/compiler/tests/test_parser.py +13 -5
  16. jaclang/plugin/builtin.py +11 -0
  17. jaclang/plugin/default.py +55 -20
  18. jaclang/plugin/feature.py +14 -5
  19. jaclang/plugin/spec.py +16 -6
  20. jaclang/plugin/tests/fixtures/graph_purger.jac +2 -0
  21. jaclang/plugin/tests/fixtures/other_root_access.jac +1 -0
  22. jaclang/plugin/tests/fixtures/savable_object.jac +2 -0
  23. jaclang/plugin/tests/test_jaseci.py +1 -1
  24. jaclang/runtimelib/architype.py +11 -21
  25. jaclang/runtimelib/context.py +25 -9
  26. jaclang/runtimelib/importer.py +26 -3
  27. jaclang/runtimelib/machine.py +2 -2
  28. jaclang/settings.py +2 -0
  29. jaclang/tests/fixtures/create_dynamic_architype.jac +1 -1
  30. jaclang/tests/fixtures/nested_impls.jac +55 -0
  31. jaclang/tests/test_cli.py +1 -1
  32. jaclang/tests/test_language.py +27 -13
  33. jaclang/tests/test_reference.py +2 -2
  34. jaclang/utils/helpers.py +4 -3
  35. jaclang/utils/test.py +2 -2
  36. jaclang/utils/tests/test_lang_tools.py +4 -2
  37. {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/METADATA +2 -2
  38. {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/RECORD +40 -39
  39. {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/WHEEL +1 -1
  40. {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/entry_points.txt +0 -0
@@ -7,11 +7,12 @@ in each node. Module nodes contain the entire module code.
7
7
  import ast as ast3
8
8
  import textwrap
9
9
  from dataclasses import dataclass
10
- from typing import Optional, Sequence, TypeVar
10
+ from typing import Optional, Sequence, TypeVar, cast
11
11
 
12
12
  import jaclang.compiler.absyntree as ast
13
13
  from jaclang.compiler.constant import Constants as Con, EdgeDir, Tokens as Tok
14
14
  from jaclang.compiler.passes import Pass
15
+ from jaclang.settings import settings
15
16
 
16
17
  T = TypeVar("T", bound=ast3.AST)
17
18
 
@@ -52,8 +53,47 @@ class PyastGenPass(Pass):
52
53
  ),
53
54
  jac_node=self.ir,
54
55
  ),
56
+ (
57
+ self.sync(
58
+ ast3.ImportFrom(
59
+ module="jaclang",
60
+ names=[self.sync(ast3.alias(name="*", asname=None))],
61
+ level=0,
62
+ ),
63
+ jac_node=self.ir,
64
+ )
65
+ if settings.pyout_jaclib_import_all
66
+ else self.sync(
67
+ ast3.Import(
68
+ names=[
69
+ self.sync(
70
+ ast3.alias(
71
+ name="jaclang", asname=settings.pyout_jaclib_alias
72
+ )
73
+ )
74
+ ]
75
+ ),
76
+ jac_node=self.ir,
77
+ )
78
+ ),
55
79
  ]
56
80
 
81
+ from jaclang.plugin.builtin import __all__ as jac_builtin_funcs
82
+
83
+ if not settings.pyout_jaclib_import_all:
84
+ self.preamble += [
85
+ self.sync(
86
+ ast3.ImportFrom(
87
+ module="jaclang",
88
+ names=[
89
+ self.sync(ast3.alias(name=func_name))
90
+ for func_name in jac_builtin_funcs
91
+ ],
92
+ level=0,
93
+ )
94
+ )
95
+ ]
96
+
57
97
  def enter_node(self, node: ast.AstNode) -> None:
58
98
  """Enter node."""
59
99
  if node.gen.py_ast:
@@ -71,25 +111,19 @@ class PyastGenPass(Pass):
71
111
  # if isinstance(i, ast3.AST):
72
112
  # i.jac_link = node
73
113
 
74
- def needs_jac_import(self) -> None:
75
- """Check if import is needed."""
76
- if self.needs_jac_import.__name__ in self.already_added:
77
- return
78
- self.preamble.append(
79
- self.sync(
80
- ast3.ImportFrom(
81
- module="jaclang",
82
- names=[
83
- self.sync(
84
- ast3.alias(name="jac_import", asname="__jac_import__")
85
- )
86
- ],
87
- level=0,
114
+ def jaclib_obj(self, obj_name: str) -> ast3.Name | ast3.Attribute:
115
+ """Return the object from jaclib as ast node based on the import config."""
116
+ if settings.pyout_jaclib_import_all:
117
+ return self.sync(ast3.Name(id=obj_name, ctx=ast3.Load()))
118
+ return self.sync(
119
+ ast3.Attribute(
120
+ value=self.sync(
121
+ ast3.Name(id=settings.pyout_jaclib_alias, ctx=ast3.Load())
88
122
  ),
89
- jac_node=self.ir,
123
+ attr=obj_name,
124
+ ctx=ast3.Load(),
90
125
  )
91
126
  )
92
- self.already_added.append(self.needs_jac_import.__name__)
93
127
 
94
128
  def needs_typing(self) -> None:
95
129
  """Check if enum is needed."""
@@ -100,7 +134,7 @@ class PyastGenPass(Pass):
100
134
  ast3.Import(
101
135
  names=[
102
136
  self.sync(
103
- ast3.alias(name="typing", asname="_jac_typ"),
137
+ ast3.alias(name="typing"),
104
138
  jac_node=self.ir,
105
139
  ),
106
140
  ]
@@ -110,25 +144,6 @@ class PyastGenPass(Pass):
110
144
  )
111
145
  self.already_added.append(self.needs_typing.__name__)
112
146
 
113
- def needs_abc(self) -> None:
114
- """Check if enum is needed."""
115
- if self.needs_abc.__name__ in self.already_added:
116
- return
117
- self.preamble.append(
118
- self.sync(
119
- ast3.Import(
120
- names=[
121
- self.sync(
122
- ast3.alias(name="abc", asname="_jac_abc"),
123
- jac_node=self.ir,
124
- ),
125
- ]
126
- ),
127
- jac_node=self.ir,
128
- )
129
- )
130
- self.already_added.append(self.needs_abc.__name__)
131
-
132
147
  def needs_enum(self) -> None:
133
148
  """Check if enum is needed."""
134
149
  if self.needs_enum.__name__ in self.already_added:
@@ -138,8 +153,8 @@ class PyastGenPass(Pass):
138
153
  ast3.ImportFrom(
139
154
  module="enum",
140
155
  names=[
141
- self.sync(ast3.alias(name="Enum", asname="__jac_Enum__")),
142
- self.sync(ast3.alias(name="auto", asname="__jac_auto__")),
156
+ self.sync(ast3.alias(name="Enum", asname=None)),
157
+ self.sync(ast3.alias(name="auto", asname=None)),
143
158
  ],
144
159
  level=0,
145
160
  ),
@@ -148,74 +163,6 @@ class PyastGenPass(Pass):
148
163
  )
149
164
  self.already_added.append(self.needs_enum.__name__)
150
165
 
151
- def needs_jac_feature(self) -> None:
152
- """Check if enum is needed."""
153
- if self.needs_jac_feature.__name__ in self.already_added:
154
- return
155
- self.preamble.append(
156
- self.sync(
157
- ast3.ImportFrom(
158
- module="jaclang.plugin.feature",
159
- names=[
160
- self.sync(
161
- ast3.alias(name="JacFeature", asname=Con.JAC_FEATURE.value)
162
- ),
163
- ],
164
- level=0,
165
- ),
166
- jac_node=self.ir,
167
- )
168
- )
169
- self.preamble.append(
170
- self.sync(
171
- ast3.ImportFrom(
172
- module="jaclang.plugin.builtin",
173
- names=[self.sync(ast3.alias(name="*", asname=None))],
174
- level=0,
175
- ),
176
- jac_node=self.ir,
177
- )
178
- )
179
- self.already_added.append(self.needs_jac_feature.__name__)
180
-
181
- def needs_dataclass(self) -> None:
182
- """Check if enum is needed."""
183
- if self.needs_dataclass.__name__ in self.already_added:
184
- return
185
- self.preamble.append(
186
- self.sync(
187
- ast3.ImportFrom(
188
- module="dataclasses",
189
- names=[
190
- self.sync(
191
- ast3.alias(name="dataclass", asname="__jac_dataclass__")
192
- ),
193
- ],
194
- level=0,
195
- ),
196
- jac_node=self.ir,
197
- )
198
- )
199
- self.already_added.append(self.needs_dataclass.__name__)
200
-
201
- def needs_dataclass_field(self) -> None:
202
- """Check if enum is needed."""
203
- if self.needs_dataclass_field.__name__ in self.already_added:
204
- return
205
- self.preamble.append(
206
- self.sync(
207
- ast3.ImportFrom(
208
- module="dataclasses",
209
- names=[
210
- self.sync(ast3.alias(name="field", asname="__jac_field__")),
211
- ],
212
- level=0,
213
- ),
214
- jac_node=self.ir,
215
- )
216
- )
217
- self.already_added.append(self.needs_dataclass_field.__name__)
218
-
219
166
  def flatten(self, body: list[T | list[T] | None]) -> list[T]:
220
167
  """Flatten ast list."""
221
168
  new_body = []
@@ -404,7 +351,6 @@ class PyastGenPass(Pass):
404
351
  body: SubNodeList[CodeBlockStmt],
405
352
  doc: Optional[String],
406
353
  """
407
- self.needs_jac_feature()
408
354
  test_name = node.name.sym_name
409
355
  func = self.sync(
410
356
  ast3.FunctionDef(
@@ -412,7 +358,11 @@ class PyastGenPass(Pass):
412
358
  args=self.sync(
413
359
  ast3.arguments(
414
360
  posonlyargs=[],
415
- args=[self.sync(ast3.arg(arg="_jac_check", annotation=None))],
361
+ args=[
362
+ self.sync(
363
+ ast3.arg(arg=Con.JAC_CHECK.value, annotation=None)
364
+ )
365
+ ],
416
366
  kwonlyargs=[],
417
367
  vararg=None,
418
368
  kwargs=None,
@@ -421,17 +371,7 @@ class PyastGenPass(Pass):
421
371
  )
422
372
  ),
423
373
  body=self.resolve_stmt_block(node.body, doc=node.doc),
424
- decorator_list=[
425
- self.sync(
426
- ast3.Attribute(
427
- value=self.sync(
428
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
429
- ),
430
- attr="create_test",
431
- ctx=ast3.Load(),
432
- )
433
- )
434
- ],
374
+ decorator_list=[self.jaclib_obj("jac_test")],
435
375
  returns=self.sync(ast3.Constant(value=None)),
436
376
  type_comment=None,
437
377
  type_params=[],
@@ -443,9 +383,7 @@ class PyastGenPass(Pass):
443
383
  ast3.Call(
444
384
  func=self.sync(
445
385
  ast3.Attribute(
446
- value=self.sync(
447
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
448
- ),
386
+ value=self.jaclib_obj("Jac"),
449
387
  attr="impl_patch_filename",
450
388
  ctx=ast3.Load(),
451
389
  )
@@ -548,7 +486,6 @@ class PyastGenPass(Pass):
548
486
  for k, v in imp_from.items():
549
487
  item_keys.append(self.sync(ast3.Constant(value=k)))
550
488
  item_values.append(self.sync(ast3.Constant(value=v)))
551
- self.needs_jac_import()
552
489
  path_named_value: str
553
490
  py_nodes: list[ast3.AST] = []
554
491
  typecheck_nodes: list[ast3.AST] = []
@@ -607,68 +544,65 @@ class PyastGenPass(Pass):
607
544
  ),
608
545
  value=self.sync(
609
546
  ast3.Call(
610
- func=self.sync(
611
- ast3.Name(id="__jac_import__", ctx=ast3.Load())
612
- ),
613
- args=[],
614
- keywords=[
615
- self.sync(
616
- ast3.keyword(
617
- arg="target",
618
- value=self.sync(
619
- ast3.Constant(value=path),
620
- ),
621
- )
622
- ),
623
- self.sync(
624
- ast3.keyword(
625
- arg="base_path",
626
- value=self.sync(
627
- ast3.Name(
628
- id="__file__",
629
- ctx=ast3.Load(),
630
- )
631
- ),
547
+ func=self.jaclib_obj("jac_import"),
548
+ args=[
549
+ self.sync(ast3.Constant(value=path)),
550
+ ]
551
+ + (
552
+ [
553
+ self.sync(
554
+ ast3.Constant(value="py"),
555
+ node.hint,
632
556
  )
633
- ),
634
- self.sync(
635
- ast3.keyword(
636
- arg="lng",
637
- value=self.sync(
638
- ast3.Constant(
639
- value="py" if node.is_py else "jac"
557
+ ]
558
+ if node.is_py
559
+ else []
560
+ ),
561
+ keywords=(
562
+ [
563
+ self.sync(
564
+ ast3.keyword(
565
+ arg="absorb",
566
+ value=self.sync(
567
+ ast3.Constant(value=node.is_absorb),
640
568
  ),
641
- node.hint,
642
- ),
643
- )
644
- ),
645
- self.sync(
646
- ast3.keyword(
647
- arg="absorb",
648
- value=self.sync(
649
- ast3.Constant(value=node.is_absorb),
650
- ),
651
- )
652
- ),
653
- self.sync(
654
- ast3.keyword(
655
- arg="mdl_alias",
656
- value=self.sync(
657
- ast3.Constant(value=alias),
658
- ),
659
- )
660
- ),
661
- self.sync(
662
- ast3.keyword(
663
- arg="items",
664
- value=self.sync(
665
- ast3.Dict(
666
- keys=item_keys, values=item_values
569
+ )
570
+ ),
571
+ ]
572
+ if node.is_absorb
573
+ else []
574
+ )
575
+ + (
576
+ [
577
+ self.sync(
578
+ ast3.keyword(
579
+ arg="alias",
580
+ value=self.sync(
581
+ ast3.Constant(value=alias),
667
582
  ),
668
- ),
669
- )
670
- ),
671
- ],
583
+ )
584
+ ),
585
+ ]
586
+ if alias
587
+ else []
588
+ )
589
+ + (
590
+ [
591
+ self.sync(
592
+ ast3.keyword(
593
+ arg="items",
594
+ value=self.sync(
595
+ ast3.Dict(
596
+ keys=item_keys,
597
+ values=item_values,
598
+ ),
599
+ ),
600
+ )
601
+ ),
602
+ ]
603
+ if len(item_keys)
604
+ else []
605
+ ),
672
606
  )
673
607
  ),
674
608
  ),
@@ -857,7 +791,7 @@ class PyastGenPass(Pass):
857
791
  ast3.If(
858
792
  test=self.sync(
859
793
  ast3.Attribute(
860
- value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
794
+ value=self.sync(ast3.Name(id="typing", ctx=ast3.Load())),
861
795
  attr="TYPE_CHECKING",
862
796
  ctx=ast3.Load(),
863
797
  )
@@ -935,88 +869,9 @@ class PyastGenPass(Pass):
935
869
  else []
936
870
  )
937
871
 
938
- ds_on_entry, ds_on_exit = self.collect_events(node)
939
- if node.arch_type.name != Tok.KW_CLASS:
940
- self.needs_jac_feature()
941
- self.needs_dataclass()
942
- decorators.append(
943
- self.sync(
944
- ast3.Call(
945
- func=self.sync(
946
- ast3.Attribute(
947
- value=self.sync(
948
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
949
- ),
950
- attr=f"make_{node.arch_type.value}",
951
- ctx=ast3.Load(),
952
- )
953
- ),
954
- args=[],
955
- keywords=[
956
- self.sync(
957
- ast3.keyword(
958
- arg="on_entry",
959
- value=self.sync(
960
- ast3.List(elts=ds_on_entry, ctx=ast3.Load())
961
- ),
962
- )
963
- ),
964
- self.sync(
965
- ast3.keyword(
966
- arg="on_exit",
967
- value=self.sync(
968
- ast3.List(elts=ds_on_exit, ctx=ast3.Load())
969
- ),
970
- )
971
- ),
972
- ],
973
- )
974
- )
975
- )
976
- decorators.append(
977
- self.sync(
978
- ast3.Call(
979
- func=self.sync(
980
- ast3.Name(id="__jac_dataclass__", ctx=ast3.Load())
981
- ),
982
- args=[],
983
- keywords=[
984
- self.sync(
985
- ast3.keyword(
986
- arg="eq",
987
- value=self.sync(
988
- ast3.Constant(value=False),
989
- ),
990
- )
991
- )
992
- ],
993
- )
994
- )
995
- )
996
872
  base_classes = node.base_classes.gen.py_ast if node.base_classes else []
997
873
  if node.arch_type.name != Tok.KW_CLASS:
998
- base_classes.append(
999
- self.sync(
1000
- ast3.Attribute(
1001
- value=self.sync(
1002
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1003
- ),
1004
- attr=node.arch_type.value.capitalize(),
1005
- ctx=ast3.Load(),
1006
- )
1007
- )
1008
- )
1009
- if node.is_abstract:
1010
- self.needs_abc()
1011
- base_classes.append(
1012
- self.sync(
1013
- ast3.Attribute(
1014
- value=self.sync(ast3.Name(id="_jac_abc", ctx=ast3.Load())),
1015
- attr="ABC",
1016
- ctx=ast3.Load(),
1017
- )
1018
- )
1019
- )
874
+ base_classes.append(self.jaclib_obj(node.arch_type.value.capitalize()))
1020
875
  node.gen.py_ast = [
1021
876
  self.sync(
1022
877
  ast3.ClassDef(
@@ -1030,42 +885,6 @@ class PyastGenPass(Pass):
1030
885
  )
1031
886
  ]
1032
887
 
1033
- def collect_events(
1034
- self, node: ast.Architype
1035
- ) -> tuple[list[ast3.AST], list[ast3.AST]]:
1036
- """Collect events."""
1037
- ds_on_entry: list[ast3.AST] = []
1038
- ds_on_exit: list[ast3.AST] = []
1039
- for i in (
1040
- node.body.body.items
1041
- if isinstance(node.body, ast.ArchDef)
1042
- else node.body.items if node.body else []
1043
- ):
1044
- if isinstance(i, ast.Ability) and isinstance(
1045
- i.signature, ast.EventSignature
1046
- ):
1047
- func_spec = self.sync(
1048
- ast3.Call(
1049
- func=self.sync(
1050
- ast3.Attribute(
1051
- value=self.sync(
1052
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1053
- ),
1054
- attr="DSFunc",
1055
- ctx=ast3.Load(),
1056
- )
1057
- ),
1058
- args=[self.sync(ast3.Constant(value=i.sym_name))],
1059
- keywords=[],
1060
- )
1061
- )
1062
- (
1063
- ds_on_entry.append(func_spec)
1064
- if i.signature.event.name == Tok.KW_ENTRY
1065
- else ds_on_exit.append(func_spec)
1066
- )
1067
- return ds_on_entry, ds_on_exit
1068
-
1069
888
  def exit_arch_def(self, node: ast.ArchDef) -> None:
1070
889
  """Sub objects.
1071
890
 
@@ -1110,9 +929,7 @@ class PyastGenPass(Pass):
1110
929
  )
1111
930
  base_classes = node.base_classes.gen.py_ast if node.base_classes else []
1112
931
  if isinstance(base_classes, list):
1113
- base_classes.append(
1114
- self.sync(ast3.Name(id="__jac_Enum__", ctx=ast3.Load()))
1115
- )
932
+ base_classes.append(self.sync(ast3.Name(id="Enum", ctx=ast3.Load())))
1116
933
  else:
1117
934
  raise self.ice()
1118
935
  node.gen.py_ast = [
@@ -1207,56 +1024,35 @@ class PyastGenPass(Pass):
1207
1024
  node,
1208
1025
  )
1209
1026
  decorator_list = node.decorators.gen.py_ast if node.decorators else []
1027
+ if isinstance(node.signature, ast.EventSignature):
1028
+ decorator_list.append(
1029
+ self.jaclib_obj(
1030
+ "with_entry"
1031
+ if node.signature.event.name == Tok.KW_ENTRY
1032
+ else "with_exit"
1033
+ )
1034
+ )
1035
+
1210
1036
  if isinstance(node.body, ast.AstImplOnlyNode):
1211
- self.needs_jac_feature()
1212
1037
  decorator_list.append(
1213
1038
  self.sync(
1214
1039
  ast3.Call(
1215
1040
  func=self.sync(
1216
1041
  ast3.Attribute(
1217
- value=self.sync(
1218
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1219
- ),
1042
+ self.jaclib_obj("Jac"),
1220
1043
  attr="impl_patch_filename",
1221
1044
  ctx=ast3.Load(),
1222
- )
1223
- ),
1224
- args=[],
1225
- keywords=[
1226
- self.sync(
1227
- ast3.keyword(
1228
- arg="file_loc",
1229
- value=self.sync(
1230
- ast3.Constant(value=node.body.loc.mod_path)
1231
- ),
1232
- )
1233
1045
  ),
1234
- ],
1046
+ ),
1047
+ args=[self.sync(ast3.Constant(value=node.body.loc.mod_path))],
1048
+ keywords=[],
1235
1049
  )
1236
1050
  )
1237
1051
  )
1238
1052
  if node.is_abstract:
1239
- self.needs_abc()
1240
- decorator_list.append(
1241
- self.sync(
1242
- ast3.Attribute(
1243
- value=self.sync(ast3.Name(id="_jac_abc", ctx=ast3.Load())),
1244
- attr="abstractmethod",
1245
- ctx=ast3.Load(),
1246
- )
1247
- )
1248
- )
1053
+ decorator_list.append(self.jaclib_obj("abstract"))
1249
1054
  if node.is_override:
1250
- self.needs_typing()
1251
- decorator_list.append(
1252
- self.sync(
1253
- ast3.Attribute(
1254
- value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
1255
- attr="override",
1256
- ctx=ast3.Load(),
1257
- )
1258
- )
1259
- )
1055
+ decorator_list.append(self.jaclib_obj("override"))
1260
1056
  if node.is_static:
1261
1057
  decorator_list.insert(
1262
1058
  0, self.sync(ast3.Name(id="staticmethod", ctx=ast3.Load()))
@@ -1381,23 +1177,13 @@ class PyastGenPass(Pass):
1381
1177
  isinstance(node.arch_name, ast.SpecialVarRef)
1382
1178
  and node.arch_name.orig.name == Tok.KW_ROOT
1383
1179
  ):
1384
- node.gen.py_ast = [
1385
- self.sync(
1386
- ast3.Attribute(
1387
- value=self.sync(
1388
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1389
- ),
1390
- attr="RootType",
1391
- ctx=ast3.Load(),
1392
- )
1393
- )
1394
- ]
1180
+ node.gen.py_ast = [self.jaclib_obj("Root")]
1395
1181
  else:
1396
1182
  self.needs_typing()
1397
1183
  node.gen.py_ast = [
1398
1184
  self.sync(
1399
1185
  ast3.Attribute(
1400
- value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
1186
+ value=self.sync(ast3.Name(id="typing", ctx=ast3.Load())),
1401
1187
  attr=node.arch_name.sym_name,
1402
1188
  ctx=ast3.Load(),
1403
1189
  )
@@ -1498,25 +1284,15 @@ class PyastGenPass(Pass):
1498
1284
  )
1499
1285
  )
1500
1286
  if is_static_var:
1501
- self.needs_typing()
1502
1287
  annotation = self.sync(
1503
1288
  ast3.Subscript(
1504
- value=self.sync(
1505
- ast3.Attribute(
1506
- value=self.sync(ast3.Name(id="_jac_typ", ctx=ast3.Load())),
1507
- attr="ClassVar",
1508
- ctx=ast3.Load(),
1509
- )
1510
- ),
1289
+ value=self.jaclib_obj("static"),
1511
1290
  slice=annotation,
1512
1291
  ctx=ast3.Load(),
1513
1292
  )
1514
1293
  )
1515
- (
1516
- self.needs_dataclass_field()
1517
- if node.defer and not (is_static_var or is_in_class)
1518
- else None
1519
- )
1294
+
1295
+ default_field_fn_name = "field"
1520
1296
  node.gen.py_ast = [
1521
1297
  (
1522
1298
  self.sync(
@@ -1526,42 +1302,45 @@ class PyastGenPass(Pass):
1526
1302
  value=(
1527
1303
  self.sync(
1528
1304
  ast3.Call(
1529
- func=self.sync(
1530
- ast3.Attribute(
1531
- value=self.sync(
1532
- ast3.Name(
1533
- id=Con.JAC_FEATURE.value,
1534
- ctx=ast3.Load(),
1535
- )
1536
- ),
1537
- attr="has_instance_default",
1538
- ctx=ast3.Load(),
1305
+ func=self.jaclib_obj(default_field_fn_name),
1306
+ args=(
1307
+ [node.value.gen.py_ast[0]]
1308
+ if isinstance(
1309
+ node.value.gen.py_ast[0], ast3.Constant
1539
1310
  )
1311
+ else []
1540
1312
  ),
1541
- args=[],
1542
- keywords=[
1543
- self.sync(
1544
- ast3.keyword(
1545
- arg="gen_func",
1546
- value=self.sync(
1547
- ast3.Lambda(
1548
- args=self.sync(
1549
- ast3.arguments(
1550
- posonlyargs=[],
1551
- args=[],
1552
- kwonlyargs=[],
1553
- vararg=None,
1554
- kwargs=None,
1555
- kw_defaults=[],
1556
- defaults=[],
1557
- )
1558
- ),
1559
- body=node.value.gen.py_ast[0],
1560
- )
1561
- ),
1313
+ keywords=(
1314
+ [
1315
+ self.sync(
1316
+ ast3.keyword(
1317
+ arg="gen",
1318
+ value=self.sync(
1319
+ ast3.Lambda(
1320
+ args=self.sync(
1321
+ ast3.arguments(
1322
+ posonlyargs=[],
1323
+ args=[],
1324
+ kwonlyargs=[],
1325
+ vararg=None,
1326
+ kwargs=None,
1327
+ kw_defaults=[],
1328
+ defaults=[],
1329
+ )
1330
+ ),
1331
+ body=node.value.gen.py_ast[
1332
+ 0
1333
+ ],
1334
+ )
1335
+ ),
1336
+ )
1562
1337
  )
1338
+ ]
1339
+ if not isinstance(
1340
+ node.value.gen.py_ast[0], ast3.Constant
1563
1341
  )
1564
- ],
1342
+ else []
1343
+ ),
1565
1344
  )
1566
1345
  )
1567
1346
  if node.value
@@ -1569,19 +1348,14 @@ class PyastGenPass(Pass):
1569
1348
  else (
1570
1349
  self.sync(
1571
1350
  ast3.Call(
1572
- func=self.sync(
1573
- ast3.Name(
1574
- id="__jac_field__",
1575
- ctx=ast3.Load(),
1576
- )
1577
- ),
1351
+ func=self.jaclib_obj(default_field_fn_name),
1578
1352
  args=[],
1579
1353
  keywords=[
1580
1354
  self.sync(
1581
1355
  ast3.keyword(
1582
- arg="init",
1356
+ arg="postinit",
1583
1357
  value=self.sync(
1584
- ast3.Constant(value=False)
1358
+ ast3.Constant(value=True)
1585
1359
  ),
1586
1360
  )
1587
1361
  )
@@ -1983,16 +1757,16 @@ class PyastGenPass(Pass):
1983
1757
  for param in node.target.params.items:
1984
1758
  assert_args_list.append(param.gen.py_ast[0])
1985
1759
 
1986
- # assert_func_expr = "_jac_check.assertXXX"
1760
+ # assert_func_expr = "Con.JAC_CHECK.value.assertXXX"
1987
1761
  assert_func_expr: ast3.Attribute = self.sync(
1988
1762
  ast3.Attribute(
1989
- value=self.sync(ast3.Name(id="_jac_check", ctx=ast3.Load())),
1763
+ value=self.sync(ast3.Name(id=Con.JAC_CHECK.value, ctx=ast3.Load())),
1990
1764
  attr=assert_func_name,
1991
1765
  ctx=ast3.Load(),
1992
1766
  )
1993
1767
  )
1994
1768
 
1995
- # assert_call_expr = "(_jac_check.assertXXX)(args)"
1769
+ # assert_call_expr = "(Con.JAC_CHECK.value.assertXXX)(args)"
1996
1770
  assert_call_expr: ast3.Call = self.sync(
1997
1771
  ast3.Call(func=assert_func_expr, args=assert_args_list, keywords=[])
1998
1772
  )
@@ -2041,12 +1815,7 @@ class PyastGenPass(Pass):
2041
1815
  ast3.Call(
2042
1816
  func=self.sync(
2043
1817
  ast3.Attribute(
2044
- value=self.sync(
2045
- ast3.Name(
2046
- id=Con.JAC_FEATURE.value,
2047
- ctx=ast3.Load(),
2048
- )
2049
- ),
1818
+ value=self.jaclib_obj(Con.JAC_FEATURE.value),
2050
1819
  attr="report",
2051
1820
  ctx=ast3.Load(),
2052
1821
  )
@@ -2092,11 +1861,12 @@ class PyastGenPass(Pass):
2092
1861
 
2093
1862
  target: ExprType,
2094
1863
  """
2095
- loc = self.sync(
1864
+ walker = self.sync(
2096
1865
  ast3.Name(id="self", ctx=ast3.Load())
2097
1866
  if node.from_walker
2098
1867
  else ast3.Name(id=Con.HERE.value, ctx=ast3.Load())
2099
1868
  )
1869
+
2100
1870
  node.gen.py_ast = [
2101
1871
  self.sync(
2102
1872
  ast3.Expr(
@@ -2104,16 +1874,12 @@ class PyastGenPass(Pass):
2104
1874
  ast3.Call(
2105
1875
  func=self.sync(
2106
1876
  ast3.Attribute(
2107
- value=self.sync(
2108
- ast3.Name(
2109
- id=Con.JAC_FEATURE.value, ctx=ast3.Load()
2110
- )
2111
- ),
1877
+ value=walker,
2112
1878
  attr="ignore",
2113
1879
  ctx=ast3.Load(),
2114
1880
  )
2115
1881
  ),
2116
- args=[loc, node.target.gen.py_ast[0]],
1882
+ args=[node.target.gen.py_ast[0]],
2117
1883
  keywords=[],
2118
1884
  )
2119
1885
  )
@@ -2133,29 +1899,37 @@ class PyastGenPass(Pass):
2133
1899
  if node.from_walker
2134
1900
  else ast3.Name(id=Con.HERE.value, ctx=ast3.Load())
2135
1901
  )
1902
+
1903
+ visit_call = self.sync(
1904
+ ast3.Call(
1905
+ func=self.sync(
1906
+ ast3.Attribute(
1907
+ value=loc,
1908
+ attr="visit",
1909
+ ctx=ast3.Load(),
1910
+ )
1911
+ ),
1912
+ args=[node.target.gen.py_ast[0]],
1913
+ keywords=[],
1914
+ )
1915
+ )
1916
+
2136
1917
  node.gen.py_ast = [
2137
- self.sync(
2138
- ast3.If(
2139
- test=self.sync(
2140
- ast3.Call(
2141
- func=self.sync(
2142
- ast3.Attribute(
2143
- value=self.sync(
2144
- ast3.Name(
2145
- id=Con.JAC_FEATURE.value, ctx=ast3.Load()
2146
- )
2147
- ),
2148
- attr="visit_node",
2149
- ctx=ast3.Load(),
2150
- )
2151
- ),
2152
- args=[loc, node.target.gen.py_ast[0]],
2153
- keywords=[],
2154
- )
2155
- ),
2156
- body=[self.sync(ast3.Pass())],
2157
- orelse=node.else_body.gen.py_ast if node.else_body else [],
1918
+ (
1919
+ self.sync(
1920
+ ast3.If(
1921
+ test=self.sync(
1922
+ ast3.UnaryOp(
1923
+ op=self.sync(ast3.Not()),
1924
+ operand=visit_call,
1925
+ )
1926
+ ),
1927
+ body=node.else_body.gen.py_ast,
1928
+ orelse=[],
1929
+ )
2158
1930
  )
1931
+ if node.else_body
1932
+ else self.sync(ast3.Expr(value=visit_call))
2159
1933
  )
2160
1934
  ]
2161
1935
 
@@ -2179,30 +1953,24 @@ class PyastGenPass(Pass):
2179
1953
  )
2180
1954
  node.gen.py_ast = [
2181
1955
  self.sync(
2182
- ast3.Expr(
2183
- value=self.sync(
1956
+ ast3.Return(
1957
+ self.sync(
2184
1958
  self.sync(
2185
1959
  ast3.Call(
2186
1960
  func=self.sync(
2187
1961
  ast3.Attribute(
2188
- value=self.sync(
2189
- ast3.Name(
2190
- id=Con.JAC_FEATURE.value,
2191
- ctx=ast3.Load(),
2192
- )
2193
- ),
1962
+ value=loc,
2194
1963
  attr="disengage",
2195
1964
  ctx=ast3.Load(),
2196
1965
  )
2197
1966
  ),
2198
- args=[loc],
1967
+ args=[],
2199
1968
  keywords=[],
2200
1969
  )
2201
1970
  )
2202
1971
  )
2203
1972
  )
2204
1973
  ),
2205
- self.sync(ast3.Return()),
2206
1974
  ]
2207
1975
 
2208
1976
  def exit_await_expr(self, node: ast.AwaitExpr) -> None:
@@ -2256,7 +2024,7 @@ class PyastGenPass(Pass):
2256
2024
  else (
2257
2025
  self.sync(
2258
2026
  ast3.Call(
2259
- func=self.sync(ast3.Name(id="__jac_auto__", ctx=ast3.Load())),
2027
+ func=self.sync(ast3.Name(id="auto", ctx=ast3.Load())),
2260
2028
  args=[],
2261
2029
  keywords=[],
2262
2030
  )
@@ -2299,91 +2067,120 @@ class PyastGenPass(Pass):
2299
2067
  op: Token | DisconnectOp | ConnectOp,
2300
2068
  """
2301
2069
  if isinstance(node.op, ast.ConnectOp):
2070
+
2071
+ left = (
2072
+ node.right.gen.py_ast[0]
2073
+ if node.op.edge_dir == EdgeDir.IN
2074
+ else node.left.gen.py_ast[0]
2075
+ )
2076
+ right = (
2077
+ node.left.gen.py_ast[0]
2078
+ if node.op.edge_dir == EdgeDir.IN
2079
+ else node.right.gen.py_ast[0]
2080
+ )
2081
+ conn_type = (
2082
+ node.op.conn_type.gen.py_ast[0]
2083
+ if node.op.conn_type
2084
+ else self.sync(ast3.Constant(value=None))
2085
+ )
2086
+ undir = self.sync(ast3.Constant(value=node.op.edge_dir == EdgeDir.ANY))
2087
+ conn_assign = (
2088
+ node.op.conn_assign.gen.py_ast[0]
2089
+ if node.op.conn_assign
2090
+ else self.sync(ast3.Constant(value=None))
2091
+ )
2092
+
2093
+ keywords = []
2094
+ if not isinstance(conn_type, ast3.Constant) or conn_type.value is not None:
2095
+ keywords.append(
2096
+ self.sync(
2097
+ ast3.keyword(
2098
+ arg="edge",
2099
+ value=conn_type,
2100
+ )
2101
+ )
2102
+ )
2103
+ if undir.value: # default is Fault.
2104
+ keywords.append(
2105
+ self.sync(
2106
+ ast3.keyword(
2107
+ arg="undir",
2108
+ value=undir,
2109
+ )
2110
+ )
2111
+ )
2112
+ if (
2113
+ not isinstance(conn_assign, ast3.Constant)
2114
+ or conn_assign.value is not None
2115
+ ):
2116
+ keywords.append(
2117
+ self.sync(
2118
+ ast3.keyword(
2119
+ arg="conn_assign",
2120
+ value=conn_assign,
2121
+ )
2122
+ )
2123
+ )
2124
+
2302
2125
  node.gen.py_ast = [
2303
2126
  self.sync(
2304
2127
  ast3.Call(
2305
2128
  func=self.sync(
2306
2129
  ast3.Attribute(
2307
- value=self.sync(
2308
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2309
- ),
2130
+ value=left,
2310
2131
  attr="connect",
2311
2132
  ctx=ast3.Load(),
2312
- )
2313
- ),
2314
- args=[],
2315
- keywords=[
2316
- self.sync(
2317
- ast3.keyword(
2318
- arg="left",
2319
- value=(
2320
- node.right.gen.py_ast[0]
2321
- if node.op.edge_dir == EdgeDir.IN
2322
- else node.left.gen.py_ast[0]
2323
- ),
2324
- )
2325
- ),
2326
- self.sync(
2327
- ast3.keyword(
2328
- arg="right",
2329
- value=(
2330
- node.left.gen.py_ast[0]
2331
- if node.op.edge_dir == EdgeDir.IN
2332
- else node.right.gen.py_ast[0]
2333
- ),
2334
- )
2335
2133
  ),
2336
- self.sync(
2337
- ast3.keyword(
2338
- arg="edge_spec",
2339
- value=node.op.gen.py_ast[0],
2340
- )
2341
- ),
2342
- ],
2134
+ ),
2135
+ args=[right],
2136
+ keywords=keywords,
2343
2137
  )
2344
2138
  )
2345
2139
  ]
2140
+
2346
2141
  elif isinstance(node.op, ast.DisconnectOp):
2347
- node.gen.py_ast = [
2348
- self.sync(
2349
- ast3.Call(
2350
- func=self.sync(
2351
- ast3.Attribute(
2352
- value=self.sync(
2353
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2354
- ),
2355
- attr="disconnect",
2356
- ctx=ast3.Load(),
2357
- )
2358
- ),
2359
- args=[
2360
- node.left.gen.py_ast[0],
2361
- node.right.gen.py_ast[0],
2362
- self.sync(
2142
+ keywords = []
2143
+
2144
+ if node.op.edge_spec.filter_cond and node.op.edge_spec.filter_cond.f_type:
2145
+ keywords.append(
2146
+ self.sync(
2147
+ ast3.keyword(
2148
+ arg="edge",
2149
+ value=self.sync(
2150
+ node.op.edge_spec.filter_cond.f_type.gen.py_ast[0]
2151
+ ),
2152
+ )
2153
+ )
2154
+ )
2155
+
2156
+ if node.op.edge_spec.edge_dir != EdgeDir.OUT:
2157
+ keywords.append(
2158
+ self.sync(
2159
+ ast3.keyword(
2160
+ arg="dir",
2161
+ value=self.sync(
2363
2162
  ast3.Attribute(
2364
- value=self.sync(
2365
- ast3.Attribute(
2366
- value=self.sync(
2367
- ast3.Name(
2368
- id=Con.JAC_FEATURE.value,
2369
- ctx=ast3.Load(),
2370
- )
2371
- ),
2372
- attr="EdgeDir",
2373
- ctx=ast3.Load(),
2374
- )
2375
- ),
2163
+ value=self.jaclib_obj("EdgeDir"),
2376
2164
  attr=node.op.edge_spec.edge_dir.name,
2377
2165
  ctx=ast3.Load(),
2378
2166
  )
2379
2167
  ),
2380
- (
2381
- node.op.edge_spec.filter_cond.gen.py_ast[0]
2382
- if node.op.edge_spec.filter_cond is not None
2383
- else self.sync(ast3.Constant(value=None))
2384
- ),
2385
- ],
2386
- keywords=[],
2168
+ )
2169
+ )
2170
+ )
2171
+
2172
+ node.gen.py_ast = [
2173
+ self.sync(
2174
+ ast3.Call(
2175
+ func=self.sync(
2176
+ ast3.Attribute(
2177
+ value=node.left.gen.py_ast[0],
2178
+ attr="disconnect",
2179
+ ctx=ast3.Load(),
2180
+ )
2181
+ ),
2182
+ args=[node.right.gen.py_ast[0]],
2183
+ keywords=keywords,
2387
2184
  )
2388
2185
  )
2389
2186
  ]
@@ -2444,20 +2241,17 @@ class PyastGenPass(Pass):
2444
2241
  self.exit_func_call(func_node)
2445
2242
  return func_node.gen.py_ast
2446
2243
  elif node.op.name in [Tok.KW_SPAWN]:
2447
- self.needs_jac_feature()
2448
2244
  return [
2449
2245
  self.sync(
2450
2246
  ast3.Call(
2451
2247
  func=self.sync(
2452
2248
  ast3.Attribute(
2453
- value=self.sync(
2454
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2455
- ),
2456
- attr="spawn_call",
2249
+ value=node.left.gen.py_ast[0],
2250
+ attr="spawn",
2457
2251
  ctx=ast3.Load(),
2458
2252
  )
2459
2253
  ),
2460
- args=[node.left.gen.py_ast[0], node.right.gen.py_ast[0]],
2254
+ args=[node.right.gen.py_ast[0]],
2461
2255
  keywords=[],
2462
2256
  )
2463
2257
  )
@@ -2482,25 +2276,6 @@ class PyastGenPass(Pass):
2482
2276
  return func_node.gen.py_ast
2483
2277
  elif node.op.name == Tok.PIPE_FWD and isinstance(node.right, ast.TupleVal):
2484
2278
  self.error("Invalid pipe target.")
2485
- elif node.op.name == Tok.ELVIS_OP:
2486
- self.needs_jac_feature()
2487
- return [
2488
- self.sync(
2489
- ast3.Call(
2490
- func=self.sync(
2491
- ast3.Attribute(
2492
- value=self.sync(
2493
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2494
- ),
2495
- attr="elvis",
2496
- ctx=ast3.Load(),
2497
- )
2498
- ),
2499
- args=[node.left.gen.py_ast[0], node.right.gen.py_ast[0]],
2500
- keywords=[],
2501
- )
2502
- )
2503
- ]
2504
2279
  else:
2505
2280
  self.error(
2506
2281
  f"Binary operator {node.op.value} not supported in bootstrap Jac"
@@ -2638,15 +2413,7 @@ class PyastGenPass(Pass):
2638
2413
  node.gen.py_ast = [
2639
2414
  self.sync(
2640
2415
  ast3.Call(
2641
- func=self.sync(
2642
- ast3.Attribute(
2643
- value=self.sync(
2644
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2645
- ),
2646
- attr="get_object",
2647
- ctx=ast3.Load(),
2648
- )
2649
- ),
2416
+ func=self.jaclib_obj("jobj"),
2650
2417
  args=[],
2651
2418
  keywords=[
2652
2419
  self.sync(
@@ -2746,14 +2513,32 @@ class PyastGenPass(Pass):
2746
2513
 
2747
2514
  values: Optional[SubNodeList[ExprType]],
2748
2515
  """
2749
- node.gen.py_ast = [
2750
- self.sync(
2751
- ast3.List(
2752
- elts=node.values.gen.py_ast if node.values else [],
2753
- ctx=node.py_ctx_func(),
2516
+ if isinstance(node.py_ctx_func(), ast3.Load):
2517
+ node.gen.py_ast = [
2518
+ self.sync(
2519
+ ast3.Call(
2520
+ func=self.jaclib_obj("JacList"),
2521
+ args=[
2522
+ self.sync(
2523
+ ast3.List(
2524
+ elts=node.values.gen.py_ast if node.values else [],
2525
+ ctx=ast3.Load(),
2526
+ )
2527
+ )
2528
+ ],
2529
+ keywords=[],
2530
+ )
2754
2531
  )
2755
- )
2756
- ]
2532
+ ]
2533
+ else:
2534
+ node.gen.py_ast = [
2535
+ self.sync(
2536
+ ast3.List(
2537
+ elts=node.values.gen.py_ast if node.values else [],
2538
+ ctx=node.py_ctx_func(),
2539
+ )
2540
+ )
2541
+ ]
2757
2542
 
2758
2543
  def exit_set_val(self, node: ast.SetVal) -> None:
2759
2544
  """Sub objects.
@@ -2853,9 +2638,17 @@ class PyastGenPass(Pass):
2853
2638
  """
2854
2639
  node.gen.py_ast = [
2855
2640
  self.sync(
2856
- ast3.ListComp(
2857
- elt=node.out_expr.gen.py_ast[0],
2858
- generators=[i.gen.py_ast[0] for i in node.compr],
2641
+ ast3.Call(
2642
+ func=self.jaclib_obj("JacList"),
2643
+ args=[
2644
+ self.sync(
2645
+ ast3.ListComp(
2646
+ elt=node.out_expr.gen.py_ast[0],
2647
+ generators=[i.gen.py_ast[0] for i in node.compr],
2648
+ )
2649
+ )
2650
+ ],
2651
+ keywords=[],
2859
2652
  )
2860
2653
  )
2861
2654
  ]
@@ -2936,8 +2729,14 @@ class PyastGenPass(Pass):
2936
2729
  node.gen.py_ast = [
2937
2730
  self.sync(
2938
2731
  ast3.Call(
2939
- func=node.right.gen.py_ast[0],
2940
- args=[node.target.gen.py_ast[0]],
2732
+ func=self.sync(
2733
+ ast3.Attribute(
2734
+ value=node.target.gen.py_ast[0],
2735
+ attr="filter",
2736
+ ctx=ast3.Load(),
2737
+ )
2738
+ ),
2739
+ args=cast(ast3.Tuple, node.right.gen.py_ast[0]).elts,
2941
2740
  keywords=[],
2942
2741
  )
2943
2742
  )
@@ -2948,14 +2747,12 @@ class PyastGenPass(Pass):
2948
2747
  ast3.Call(
2949
2748
  func=self.sync(
2950
2749
  ast3.Attribute(
2951
- value=self.sync(
2952
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
2953
- ),
2954
- attr="assign_compr",
2750
+ value=node.target.gen.py_ast[0],
2751
+ attr="assign",
2955
2752
  ctx=ast3.Load(),
2956
2753
  )
2957
2754
  ),
2958
- args=[node.target.gen.py_ast[0], node.right.gen.py_ast[0]],
2755
+ args=cast(ast3.Tuple, node.right.gen.py_ast[0]).elts,
2959
2756
  keywords=[],
2960
2757
  )
2961
2758
  )
@@ -3063,7 +2860,6 @@ class PyastGenPass(Pass):
3063
2860
  else:
3064
2861
  self.ice("Invalid Parameter")
3065
2862
  if node.genai_call:
3066
- self.needs_jac_feature()
3067
2863
  by_llm_call_args = self.get_by_llm_call_args(node)
3068
2864
  node.gen.py_ast = [self.sync(self.by_llm_call(**by_llm_call_args))]
3069
2865
  else:
@@ -3141,26 +2937,7 @@ class PyastGenPass(Pass):
3141
2937
  )
3142
2938
  ]
3143
2939
  elif node.name == Tok.KW_ROOT:
3144
- node.gen.py_ast = [
3145
- self.sync(
3146
- ast3.Call(
3147
- func=self.sync(
3148
- ast3.Attribute(
3149
- value=self.sync(
3150
- ast3.Name(
3151
- id=Con.JAC_FEATURE.value,
3152
- ctx=ast3.Load(),
3153
- )
3154
- ),
3155
- attr="get_root",
3156
- ctx=ast3.Load(),
3157
- )
3158
- ),
3159
- args=[],
3160
- keywords=[],
3161
- )
3162
- )
3163
- ]
2940
+ node.gen.py_ast = [self.jaclib_obj("root")]
3164
2941
 
3165
2942
  else:
3166
2943
  node.gen.py_ast = [
@@ -3202,8 +2979,14 @@ class PyastGenPass(Pass):
3202
2979
  if next_i and isinstance(next_i, ast.FilterCompr):
3203
2980
  pynode = self.sync(
3204
2981
  ast3.Call(
3205
- func=next_i.gen.py_ast[0],
3206
- args=[pynode],
2982
+ func=self.sync(
2983
+ ast3.Attribute(
2984
+ value=pynode,
2985
+ attr="filter",
2986
+ ctx=ast3.Load(),
2987
+ )
2988
+ ),
2989
+ args=cast(ast3.Tuple, next_i.gen.py_ast[0]).elts,
3207
2990
  keywords=[],
3208
2991
  )
3209
2992
  )
@@ -3238,71 +3021,145 @@ class PyastGenPass(Pass):
3238
3021
  self,
3239
3022
  loc: ast3.AST,
3240
3023
  node: ast.EdgeOpRef,
3241
- targ: Optional[ast3.AST],
3024
+ targ: ast3.AST | None,
3242
3025
  edges_only: bool,
3243
3026
  ) -> ast3.AST:
3244
3027
  """Generate ast for edge op ref call."""
3245
- return self.sync(
3246
- ast3.Call(
3247
- func=self.sync(
3248
- ast3.Attribute(
3249
- value=self.sync(
3250
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
3251
- ),
3252
- attr="edge_ref",
3253
- ctx=ast3.Load(),
3254
- )
3255
- ),
3256
- args=[loc],
3257
- keywords=[
3258
- self.sync(
3259
- ast3.keyword(
3260
- arg="target_obj",
3261
- value=(
3262
- targ if targ else self.sync(ast3.Constant(value=None))
3263
- ),
3264
- )
3265
- ),
3266
- self.sync(
3267
- ast3.keyword(
3268
- arg="dir",
3269
- value=self.sync(
3028
+ args = []
3029
+ keywords = []
3030
+
3031
+ if node.filter_cond and node.filter_cond.f_type:
3032
+ args.append(self.sync(node.filter_cond.f_type.gen.py_ast[0]))
3033
+
3034
+ edge_iter_name = "edge"
3035
+ if node.filter_cond.compares:
3036
+
3037
+ expr: ast3.expr | None = None
3038
+ comp = node.filter_cond.compares.items[0]
3039
+ if (
3040
+ len(node.filter_cond.compares.items) == 1
3041
+ and isinstance(comp.gen.py_ast[0], ast3.Compare)
3042
+ and isinstance(comp.gen.py_ast[0].left, ast3.Name)
3043
+ ):
3044
+ expr = self.sync(
3045
+ ast3.Compare(
3046
+ left=self.sync(
3270
3047
  ast3.Attribute(
3271
3048
  value=self.sync(
3272
- ast3.Attribute(
3273
- value=self.sync(
3274
- ast3.Name(
3275
- id=Con.JAC_FEATURE.value,
3276
- ctx=ast3.Load(),
3277
- )
3278
- ),
3279
- attr="EdgeDir",
3049
+ ast3.Name(
3050
+ id=edge_iter_name,
3280
3051
  ctx=ast3.Load(),
3281
- )
3052
+ ),
3053
+ jac_node=comp,
3282
3054
  ),
3283
- attr=node.edge_dir.name,
3055
+ attr=comp.gen.py_ast[0].left.id,
3284
3056
  ctx=ast3.Load(),
3285
- )
3057
+ ),
3058
+ jac_node=comp,
3286
3059
  ),
3287
- )
3288
- ),
3060
+ ops=comp.gen.py_ast[0].ops,
3061
+ comparators=comp.gen.py_ast[0].comparators,
3062
+ ),
3063
+ jac_node=comp,
3064
+ )
3065
+ else:
3066
+ expr = self.sync(
3067
+ ast3.BoolOp(
3068
+ op=self.sync(ast3.And()),
3069
+ values=[
3070
+ self.sync(
3071
+ ast3.Compare(
3072
+ left=self.sync(
3073
+ ast3.Attribute(
3074
+ value=self.sync(
3075
+ ast3.Name(
3076
+ id=edge_iter_name,
3077
+ ctx=ast3.Load(),
3078
+ ),
3079
+ jac_node=comp,
3080
+ ),
3081
+ attr=comp.gen.py_ast[0].left.id,
3082
+ ctx=ast3.Load(),
3083
+ ),
3084
+ jac_node=comp,
3085
+ ),
3086
+ ops=comp.gen.py_ast[0].ops,
3087
+ comparators=comp.gen.py_ast[0].comparators,
3088
+ ),
3089
+ jac_node=comp,
3090
+ )
3091
+ for comp in node.filter_cond.compares.items
3092
+ if isinstance(comp.gen.py_ast[0], ast3.Compare)
3093
+ and isinstance(comp.gen.py_ast[0].left, ast3.Name)
3094
+ ],
3095
+ ),
3096
+ )
3097
+ assert expr is not None
3098
+
3099
+ args.append(
3289
3100
  self.sync(
3290
- ast3.keyword(
3291
- arg="filter_func",
3292
- value=self.sync(
3293
- node.filter_cond.gen.py_ast[0]
3294
- if node.filter_cond
3295
- else self.sync(ast3.Constant(value=None))
3101
+ ast3.Lambda(
3102
+ args=self.sync(
3103
+ ast3.arguments(
3104
+ posonlyargs=[],
3105
+ args=[self.sync(ast3.arg(arg=edge_iter_name))],
3106
+ kwonlyargs=[],
3107
+ kw_defaults=[],
3108
+ defaults=[],
3109
+ )
3296
3110
  ),
3111
+ body=expr,
3297
3112
  )
3298
- ),
3299
- self.sync(
3300
- ast3.keyword(
3301
- arg="edges_only",
3302
- value=self.sync(ast3.Constant(value=edges_only)),
3303
- )
3304
- ),
3305
- ],
3113
+ )
3114
+ )
3115
+
3116
+ if targ is not None:
3117
+ keywords.append(
3118
+ self.sync(
3119
+ ast3.keyword(
3120
+ arg="target",
3121
+ value=self.sync(ast3.Constant(value=None)),
3122
+ )
3123
+ )
3124
+ )
3125
+
3126
+ if node.edge_dir != EdgeDir.OUT:
3127
+ keywords.append(
3128
+ self.sync(
3129
+ ast3.keyword(
3130
+ arg="dir",
3131
+ value=self.sync(
3132
+ ast3.Attribute(
3133
+ value=self.jaclib_obj("EdgeDir"),
3134
+ attr=node.edge_dir.name,
3135
+ ctx=ast3.Load(),
3136
+ )
3137
+ ),
3138
+ )
3139
+ )
3140
+ )
3141
+
3142
+ if edges_only:
3143
+ keywords.append(
3144
+ self.sync(
3145
+ ast3.keyword(
3146
+ arg="edges_only",
3147
+ value=self.sync(ast3.Constant(value=edges_only)),
3148
+ )
3149
+ )
3150
+ )
3151
+
3152
+ return self.sync(
3153
+ ast3.Call(
3154
+ func=self.sync(
3155
+ ast3.Attribute(
3156
+ value=loc,
3157
+ attr="refs",
3158
+ ctx=ast3.Load(),
3159
+ )
3160
+ ),
3161
+ args=args,
3162
+ keywords=keywords,
3306
3163
  )
3307
3164
  )
3308
3165
 
@@ -3325,9 +3182,7 @@ class PyastGenPass(Pass):
3325
3182
  ast3.Call(
3326
3183
  func=self.sync(
3327
3184
  ast3.Attribute(
3328
- value=self.sync(
3329
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
3330
- ),
3185
+ value=self.jaclib_obj(Con.JAC_FEATURE.value),
3331
3186
  attr="build_edge",
3332
3187
  ctx=ast3.Load(),
3333
3188
  )
@@ -3372,106 +3227,74 @@ class PyastGenPass(Pass):
3372
3227
 
3373
3228
  compares: SubNodeList[BinaryExpr],
3374
3229
  """
3375
- node.gen.py_ast = [
3230
+ iter_name = "item"
3231
+ comprs = [
3376
3232
  self.sync(
3377
- ast3.Lambda(
3378
- args=self.sync(
3379
- ast3.arguments(
3380
- posonlyargs=[],
3381
- args=[self.sync(ast3.arg(arg="x"))],
3382
- kwonlyargs=[],
3383
- kw_defaults=[],
3384
- defaults=[],
3385
- )
3233
+ ast3.Compare(
3234
+ left=self.sync(
3235
+ ast3.Attribute(
3236
+ value=self.sync(
3237
+ ast3.Name(
3238
+ id=iter_name,
3239
+ ctx=ast3.Load(),
3240
+ ),
3241
+ jac_node=x,
3242
+ ),
3243
+ attr=x.gen.py_ast[0].left.id,
3244
+ ctx=ast3.Load(),
3245
+ ),
3246
+ jac_node=x,
3386
3247
  ),
3387
- body=self.sync(
3388
- ast3.ListComp(
3389
- elt=self.sync(ast3.Name(id="i", ctx=ast3.Load())),
3390
- generators=[
3391
- self.sync(
3392
- ast3.comprehension(
3393
- target=self.sync(
3394
- ast3.Name(id="i", ctx=ast3.Store())
3395
- ),
3396
- iter=self.sync(
3397
- ast3.Name(id="x", ctx=ast3.Load())
3398
- ),
3399
- ifs=(
3400
- (
3401
- [
3402
- self.sync(
3403
- ast3.Call(
3404
- func=self.sync(
3405
- ast3.Name(
3406
- id="isinstance",
3407
- ctx=ast3.Load(),
3408
- )
3409
- ),
3410
- args=[
3411
- self.sync(
3412
- ast3.Name(
3413
- id="i",
3414
- ctx=ast3.Load(),
3415
- )
3416
- ),
3417
- self.sync(
3418
- node.f_type.gen.py_ast[
3419
- 0
3420
- ]
3421
- ),
3422
- ],
3423
- keywords=[],
3424
- )
3425
- )
3426
- ]
3427
- if node.f_type
3428
- else []
3429
- )
3430
- + [
3431
- self.sync(
3432
- ast3.Compare(
3433
- left=self.sync(
3434
- ast3.Attribute(
3435
- value=self.sync(
3436
- ast3.Name(
3437
- id="i",
3438
- ctx=ast3.Load(),
3439
- ),
3440
- jac_node=x,
3441
- ),
3442
- attr=x.gen.py_ast[
3443
- 0
3444
- ].left.id,
3445
- ctx=ast3.Load(),
3446
- ),
3447
- jac_node=x,
3448
- ),
3449
- ops=x.gen.py_ast[0].ops,
3450
- comparators=x.gen.py_ast[
3451
- 0
3452
- ].comparators,
3453
- ),
3454
- jac_node=x,
3455
- )
3456
- for x in (
3457
- node.compares.items
3458
- if node.compares
3459
- else []
3460
- )
3461
- if isinstance(
3462
- x.gen.py_ast[0], ast3.Compare
3463
- )
3464
- and isinstance(
3465
- x.gen.py_ast[0].left, ast3.Name
3466
- )
3467
- ]
3468
- ),
3469
- is_async=0,
3470
- )
3248
+ ops=x.gen.py_ast[0].ops,
3249
+ comparators=x.gen.py_ast[0].comparators,
3250
+ ),
3251
+ jac_node=x,
3252
+ )
3253
+ for x in (node.compares.items if node.compares else [])
3254
+ if isinstance(x.gen.py_ast[0], ast3.Compare)
3255
+ and isinstance(x.gen.py_ast[0].left, ast3.Name)
3256
+ ]
3257
+
3258
+ body = (
3259
+ self.sync(
3260
+ ast3.BoolOp(
3261
+ op=self.sync(ast3.And()),
3262
+ values=comprs,
3263
+ )
3264
+ )
3265
+ if len(comprs) > 1
3266
+ else (comprs[0] if comprs else None)
3267
+ )
3268
+
3269
+ node.gen.py_ast = [
3270
+ self.sync(
3271
+ ast3.Tuple(
3272
+ elts=[
3273
+ (
3274
+ self.sync(node.f_type.gen.py_ast[0])
3275
+ if node.f_type
3276
+ else self.sync(ast3.Constant(value=None))
3277
+ ),
3278
+ (
3279
+ self.sync(
3280
+ ast3.Lambda(
3281
+ args=self.sync(
3282
+ ast3.arguments(
3283
+ posonlyargs=[],
3284
+ args=[self.sync(ast3.arg(arg=iter_name))],
3285
+ kwonlyargs=[],
3286
+ kw_defaults=[],
3287
+ defaults=[],
3288
+ )
3289
+ ),
3290
+ body=body,
3471
3291
  )
3472
- ],
3473
- )
3474
- ),
3292
+ )
3293
+ if body
3294
+ else self.sync(ast3.Constant(value=None))
3295
+ ),
3296
+ ],
3297
+ ctx=ast3.Load(),
3475
3298
  )
3476
3299
  )
3477
3300
  ]