jaclang 0.7.14__py3-none-any.whl → 0.7.17__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 (131) hide show
  1. jaclang/cli/cli.py +147 -77
  2. jaclang/cli/cmdreg.py +9 -12
  3. jaclang/compiler/__init__.py +19 -53
  4. jaclang/compiler/absyntree.py +94 -16
  5. jaclang/compiler/constant.py +8 -8
  6. jaclang/compiler/jac.lark +4 -3
  7. jaclang/compiler/parser.py +41 -25
  8. jaclang/compiler/passes/ir_pass.py +4 -13
  9. jaclang/compiler/passes/main/__init__.py +1 -1
  10. jaclang/compiler/passes/main/access_modifier_pass.py +96 -147
  11. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +155 -54
  12. jaclang/compiler/passes/main/import_pass.py +99 -75
  13. jaclang/compiler/passes/main/py_collect_dep_pass.py +70 -0
  14. jaclang/compiler/passes/main/pyast_gen_pass.py +328 -565
  15. jaclang/compiler/passes/main/pyast_load_pass.py +33 -6
  16. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -0
  17. jaclang/compiler/passes/main/registry_pass.py +37 -3
  18. jaclang/compiler/passes/main/schedules.py +9 -2
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +10 -6
  20. jaclang/compiler/passes/main/tests/__init__.py +1 -1
  21. jaclang/compiler/passes/main/tests/fixtures/autoimpl.empty.impl.jac +0 -0
  22. jaclang/compiler/passes/main/tests/fixtures/autoimpl.jac +1 -1
  23. jaclang/compiler/passes/main/tests/fixtures/py_imp_test.jac +29 -0
  24. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -0
  25. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/color.py +3 -0
  26. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/constants.py +5 -0
  27. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/display.py +2 -0
  28. jaclang/compiler/passes/main/tests/test_import_pass.py +72 -13
  29. jaclang/compiler/passes/main/type_check_pass.py +22 -5
  30. jaclang/compiler/passes/tool/jac_formatter_pass.py +135 -89
  31. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +37 -41
  32. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +37 -42
  33. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/access_mod_check.jac +27 -0
  34. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
  35. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
  36. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
  37. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
  38. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
  39. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
  40. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
  41. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
  42. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
  43. jaclang/compiler/passes/transform.py +4 -0
  44. jaclang/compiler/passes/utils/mypy_ast_build.py +45 -0
  45. jaclang/compiler/semtable.py +31 -7
  46. jaclang/compiler/symtable.py +16 -11
  47. jaclang/compiler/tests/test_importer.py +25 -10
  48. jaclang/langserve/engine.py +104 -118
  49. jaclang/langserve/sem_manager.py +379 -0
  50. jaclang/langserve/server.py +24 -11
  51. jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
  52. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  53. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  54. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  55. jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
  56. jaclang/langserve/tests/fixtures/rename.jac +30 -0
  57. jaclang/langserve/tests/test_sem_tokens.py +277 -0
  58. jaclang/langserve/tests/test_server.py +287 -17
  59. jaclang/langserve/utils.py +184 -98
  60. jaclang/plugin/builtin.py +1 -1
  61. jaclang/plugin/default.py +288 -92
  62. jaclang/plugin/feature.py +65 -27
  63. jaclang/plugin/spec.py +62 -23
  64. jaclang/plugin/tests/fixtures/other_root_access.jac +82 -0
  65. jaclang/plugin/tests/test_jaseci.py +414 -42
  66. jaclang/runtimelib/architype.py +650 -0
  67. jaclang/{core → runtimelib}/constructs.py +5 -8
  68. jaclang/{core → runtimelib}/context.py +86 -59
  69. jaclang/runtimelib/importer.py +361 -0
  70. jaclang/runtimelib/machine.py +158 -0
  71. jaclang/runtimelib/memory.py +158 -0
  72. jaclang/{core → runtimelib}/utils.py +30 -15
  73. jaclang/settings.py +5 -4
  74. jaclang/tests/fixtures/abc.jac +3 -3
  75. jaclang/tests/fixtures/access_checker.jac +12 -17
  76. jaclang/tests/fixtures/access_modifier.jac +88 -33
  77. jaclang/tests/fixtures/baddy.jac +3 -0
  78. jaclang/tests/fixtures/baddy.test.jac +3 -0
  79. jaclang/tests/fixtures/bar.jac +34 -0
  80. jaclang/tests/fixtures/byllmissue.jac +1 -5
  81. jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
  82. jaclang/tests/fixtures/cls_method.jac +41 -0
  83. jaclang/tests/fixtures/dblhello.jac +6 -0
  84. jaclang/tests/fixtures/deep/one_lev.jac +3 -3
  85. jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
  86. jaclang/tests/fixtures/deep_import_mods.jac +13 -0
  87. jaclang/tests/fixtures/edge_node_walk.jac +1 -1
  88. jaclang/tests/fixtures/edge_ops.jac +1 -1
  89. jaclang/tests/fixtures/edges_walk.jac +1 -1
  90. jaclang/tests/fixtures/err.impl.jac +3 -0
  91. jaclang/tests/fixtures/err.jac +4 -2
  92. jaclang/tests/fixtures/err_runtime.jac +15 -0
  93. jaclang/tests/fixtures/foo.jac +43 -0
  94. jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
  95. jaclang/tests/fixtures/hello.jac +4 -0
  96. jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
  97. jaclang/tests/fixtures/impl_grab.jac +4 -1
  98. jaclang/tests/fixtures/import.jac +9 -0
  99. jaclang/tests/fixtures/index_slice.jac +30 -0
  100. jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
  101. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  102. jaclang/tests/fixtures/needs_import.jac +2 -2
  103. jaclang/tests/fixtures/pyfunc_1.py +1 -1
  104. jaclang/tests/fixtures/pyfunc_2.py +5 -2
  105. jaclang/tests/fixtures/pygame_mock/__init__.py +3 -0
  106. jaclang/tests/fixtures/pygame_mock/color.py +3 -0
  107. jaclang/tests/fixtures/pygame_mock/constants.py +5 -0
  108. jaclang/tests/fixtures/pygame_mock/display.py +2 -0
  109. jaclang/tests/fixtures/pygame_mock/inner/__init__.py +0 -0
  110. jaclang/tests/fixtures/pygame_mock/inner/iner_mod.py +2 -0
  111. jaclang/tests/fixtures/registry.jac +9 -0
  112. jaclang/tests/fixtures/run_test.jac +4 -4
  113. jaclang/tests/fixtures/semstr.jac +1 -4
  114. jaclang/tests/fixtures/simple_archs.jac +1 -1
  115. jaclang/tests/test_cli.py +109 -3
  116. jaclang/tests/test_language.py +170 -68
  117. jaclang/tests/test_reference.py +2 -3
  118. jaclang/utils/helpers.py +45 -21
  119. jaclang/utils/test.py +9 -0
  120. jaclang/utils/treeprinter.py +30 -7
  121. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/METADATA +3 -2
  122. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/RECORD +126 -90
  123. jaclang/core/architype.py +0 -502
  124. jaclang/core/importer.py +0 -344
  125. jaclang/core/memory.py +0 -99
  126. jaclang/tests/fixtures/aott_raise.jac +0 -25
  127. jaclang/tests/fixtures/package_import.jac +0 -6
  128. /jaclang/{core → runtimelib}/__init__.py +0 -0
  129. /jaclang/{core → runtimelib}/test.py +0 -0
  130. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/WHEEL +0 -0
  131. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/entry_points.txt +0 -0
jaclang/plugin/default.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import ast as ast3
5
6
  import fnmatch
6
7
  import html
7
8
  import os
@@ -10,12 +11,14 @@ import types
10
11
  from collections import OrderedDict
11
12
  from dataclasses import field
12
13
  from functools import wraps
13
- from typing import Any, Callable, Optional, Type, Union
14
+ from typing import Any, Callable, Mapping, Optional, Sequence, Type, Union
14
15
 
15
- from jaclang.compiler.absyntree import Module
16
+ import jaclang.compiler.absyntree as ast
16
17
  from jaclang.compiler.constant import EdgeDir, colors
18
+ from jaclang.compiler.passes.main.pyast_gen_pass import PyastGenPass
17
19
  from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
18
- from jaclang.core.constructs import (
20
+ from jaclang.runtimelib.constructs import (
21
+ Anchor,
19
22
  Architype,
20
23
  DSFunc,
21
24
  EdgeAnchor,
@@ -23,30 +26,30 @@ from jaclang.core.constructs import (
23
26
  ExecutionContext,
24
27
  GenericEdge,
25
28
  JacTestCheck,
26
- Memory,
27
29
  NodeAnchor,
28
30
  NodeArchitype,
29
- ObjectAnchor,
30
31
  Root,
31
32
  WalkerAnchor,
32
33
  WalkerArchitype,
33
- exec_context,
34
34
  )
35
- from jaclang.core.importer import jac_importer
36
- from jaclang.core.utils import traverse_graph
37
- from jaclang.plugin.feature import JacFeature as Jac
38
- from jaclang.plugin.spec import T
35
+ from jaclang.runtimelib.importer import ImportPathSpec, JacImporter, PythonImporter
36
+ from jaclang.runtimelib.machine import JacMachine, JacProgram
37
+ from jaclang.runtimelib.utils import traverse_graph
38
+ from jaclang.plugin.feature import JacFeature as Jac # noqa: I100
39
+ from jaclang.plugin.spec import P, T
39
40
 
40
41
 
41
42
  import pluggy
42
43
 
44
+ hookimpl = pluggy.HookimplMarker("jac")
43
45
 
44
46
  __all__ = [
47
+ "Anchor",
45
48
  "EdgeAnchor",
46
49
  "GenericEdge",
50
+ "hookimpl",
47
51
  "JacTestCheck",
48
52
  "NodeAnchor",
49
- "ObjectAnchor",
50
53
  "WalkerAnchor",
51
54
  "NodeArchitype",
52
55
  "EdgeArchitype",
@@ -54,14 +57,10 @@ __all__ = [
54
57
  "WalkerArchitype",
55
58
  "Architype",
56
59
  "DSFunc",
57
- "jac_importer",
58
60
  "T",
59
61
  ]
60
62
 
61
63
 
62
- hookimpl = pluggy.HookimplMarker("jac")
63
-
64
-
65
64
  class JacFeatureDefaults:
66
65
  """Jac Feature."""
67
66
 
@@ -69,28 +68,9 @@ class JacFeatureDefaults:
69
68
 
70
69
  @staticmethod
71
70
  @hookimpl
72
- def context(session: str = "") -> ExecutionContext:
73
- """Get the execution context."""
74
- ctx = exec_context.get()
75
- if ctx is None:
76
- ctx = ExecutionContext()
77
- exec_context.set(ctx)
78
- return ctx
79
-
80
- @staticmethod
81
- @hookimpl
82
- def reset_context() -> None:
83
- """Reset the execution context."""
84
- ctx = exec_context.get()
85
- if ctx:
86
- ctx.reset()
87
- exec_context.set(None)
88
-
89
- @staticmethod
90
- @hookimpl
91
- def memory_hook() -> Memory | None:
92
- """Return the memory hook."""
93
- return Jac.context().mem
71
+ def get_context() -> ExecutionContext:
72
+ """Get current execution context."""
73
+ return ExecutionContext.get()
94
74
 
95
75
  @staticmethod
96
76
  @hookimpl
@@ -202,6 +182,43 @@ class JacFeatureDefaults:
202
182
 
203
183
  return decorator
204
184
 
185
+ @staticmethod
186
+ @hookimpl
187
+ def impl_patch_filename(
188
+ file_loc: str,
189
+ ) -> Callable[[Callable[P, T]], Callable[P, T]]:
190
+ """Update impl file location."""
191
+
192
+ def decorator(func: Callable[P, T]) -> Callable[P, T]:
193
+ try:
194
+ code = func.__code__
195
+ new_code = types.CodeType(
196
+ code.co_argcount,
197
+ code.co_posonlyargcount,
198
+ code.co_kwonlyargcount,
199
+ code.co_nlocals,
200
+ code.co_stacksize,
201
+ code.co_flags,
202
+ code.co_code,
203
+ code.co_consts,
204
+ code.co_names,
205
+ code.co_varnames,
206
+ file_loc,
207
+ code.co_name,
208
+ code.co_qualname,
209
+ code.co_firstlineno,
210
+ code.co_linetable,
211
+ code.co_exceptiontable,
212
+ code.co_freevars,
213
+ code.co_cellvars,
214
+ )
215
+ func.__code__ = new_code
216
+ except AttributeError:
217
+ pass
218
+ return func
219
+
220
+ return decorator
221
+
205
222
  @staticmethod
206
223
  @hookimpl
207
224
  def jac_import(
@@ -211,23 +228,38 @@ class JacFeatureDefaults:
211
228
  cachable: bool,
212
229
  mdl_alias: Optional[str],
213
230
  override_name: Optional[str],
214
- mod_bundle: Optional[Module | str],
215
231
  lng: Optional[str],
216
232
  items: Optional[dict[str, Union[str, Optional[str]]]],
233
+ reload_module: Optional[bool],
217
234
  ) -> tuple[types.ModuleType, ...]:
218
235
  """Core Import Process."""
219
- result = jac_importer(
220
- target=target,
221
- base_path=base_path,
222
- absorb=absorb,
223
- cachable=cachable,
224
- mdl_alias=mdl_alias,
225
- override_name=override_name,
226
- mod_bundle=mod_bundle,
227
- lng=lng,
228
- items=items,
236
+ spec = ImportPathSpec(
237
+ target,
238
+ base_path,
239
+ absorb,
240
+ cachable,
241
+ mdl_alias,
242
+ override_name,
243
+ lng,
244
+ items,
245
+ )
246
+
247
+ jac_machine = JacMachine.get(base_path)
248
+ if not jac_machine.jac_program:
249
+ jac_machine.attach_program(JacProgram(mod_bundle=None, bytecode=None))
250
+
251
+ if lng == "py":
252
+ import_result = PythonImporter(JacMachine.get()).run_import(spec)
253
+ else:
254
+ import_result = JacImporter(JacMachine.get()).run_import(
255
+ spec, reload_module
256
+ )
257
+
258
+ return (
259
+ (import_result.ret_mod,)
260
+ if absorb or not items
261
+ else tuple(import_result.ret_items)
229
262
  )
230
- return result
231
263
 
232
264
  @staticmethod
233
265
  @hookimpl
@@ -320,9 +352,9 @@ class JacFeatureDefaults:
320
352
  def spawn_call(op1: Architype, op2: Architype) -> WalkerArchitype:
321
353
  """Jac's spawn operator feature."""
322
354
  if isinstance(op1, WalkerArchitype):
323
- return op1._jac_.spawn_call(op2)
355
+ return op1.__jac__.spawn_call(op2.__jac__)
324
356
  elif isinstance(op2, WalkerArchitype):
325
- return op2._jac_.spawn_call(op1)
357
+ return op2.__jac__.spawn_call(op1.__jac__)
326
358
  else:
327
359
  raise TypeError("Invalid walker object")
328
360
 
@@ -344,7 +376,12 @@ class JacFeatureDefaults:
344
376
  ),
345
377
  ) -> bool:
346
378
  """Jac's ignore stmt feature."""
347
- return walker._jac_.ignore_node(expr)
379
+ if isinstance(walker, WalkerArchitype):
380
+ return walker.__jac__.ignore_node(
381
+ (i.__jac__ for i in expr) if isinstance(expr, list) else [expr.__jac__]
382
+ )
383
+ else:
384
+ raise TypeError("Invalid walker object")
348
385
 
349
386
  @staticmethod
350
387
  @hookimpl
@@ -360,7 +397,9 @@ class JacFeatureDefaults:
360
397
  ) -> bool:
361
398
  """Jac's visit stmt feature."""
362
399
  if isinstance(walker, WalkerArchitype):
363
- return walker._jac_.visit_node(expr)
400
+ return walker.__jac__.visit_node(
401
+ (i.__jac__ for i in expr) if isinstance(expr, list) else [expr.__jac__]
402
+ )
364
403
  else:
365
404
  raise TypeError("Invalid walker object")
366
405
 
@@ -368,7 +407,7 @@ class JacFeatureDefaults:
368
407
  @hookimpl
369
408
  def disengage(walker: WalkerArchitype) -> bool: # noqa: ANN401
370
409
  """Jac's disengage stmt feature."""
371
- walker._jac_.disengage_now()
410
+ walker.__jac__.disengage_now()
372
411
  return True
373
412
 
374
413
  @staticmethod
@@ -391,7 +430,7 @@ class JacFeatureDefaults:
391
430
  if edges_only:
392
431
  connected_edges: list[EdgeArchitype] = []
393
432
  for node in node_obj:
394
- connected_edges += node._jac_.get_edges(
433
+ connected_edges += node.__jac__.get_edges(
395
434
  dir, filter_func, target_obj=targ_obj_set
396
435
  )
397
436
  return list(set(connected_edges))
@@ -399,7 +438,9 @@ class JacFeatureDefaults:
399
438
  connected_nodes: list[NodeArchitype] = []
400
439
  for node in node_obj:
401
440
  connected_nodes.extend(
402
- node._jac_.edges_to_nodes(dir, filter_func, target_obj=targ_obj_set)
441
+ node.__jac__.edges_to_nodes(
442
+ dir, filter_func, target_obj=targ_obj_set
443
+ )
403
444
  )
404
445
  return list(set(connected_nodes))
405
446
 
@@ -408,7 +449,7 @@ class JacFeatureDefaults:
408
449
  def connect(
409
450
  left: NodeArchitype | list[NodeArchitype],
410
451
  right: NodeArchitype | list[NodeArchitype],
411
- edge_spec: Callable[[], EdgeArchitype],
452
+ edge_spec: Callable[[NodeAnchor, NodeAnchor], EdgeArchitype],
412
453
  edges_only: bool,
413
454
  ) -> list[NodeArchitype] | list[EdgeArchitype]:
414
455
  """Jac's connect operator feature.
@@ -418,17 +459,16 @@ class JacFeatureDefaults:
418
459
  left = [left] if isinstance(left, NodeArchitype) else left
419
460
  right = [right] if isinstance(right, NodeArchitype) else right
420
461
  edges = []
421
- for i in left:
422
- for j in right:
423
- conn_edge = edge_spec()
424
- edges.append(conn_edge)
425
- i._jac_.connect_node(j, conn_edge)
426
462
 
427
- if i._jac_.persistent or j._jac_.persistent:
428
- conn_edge.save()
429
- j.save()
430
- i.save()
463
+ root = Jac.get_root().__jac__
431
464
 
465
+ for i in left:
466
+ _left = i.__jac__
467
+ if root.has_connect_access(_left):
468
+ for j in right:
469
+ _right = j.__jac__
470
+ if root.has_connect_access(_right):
471
+ edges.append(edge_spec(_left, _right))
432
472
  return right if not edges_only else edges
433
473
 
434
474
  @staticmethod
@@ -443,26 +483,36 @@ class JacFeatureDefaults:
443
483
  disconnect_occurred = False
444
484
  left = [left] if isinstance(left, NodeArchitype) else left
445
485
  right = [right] if isinstance(right, NodeArchitype) else right
486
+
487
+ root = Jac.get_root().__jac__
488
+
446
489
  for i in left:
447
- for j in right:
448
- edge_list: list[EdgeArchitype] = [*i._jac_.edges]
449
- edge_list = filter_func(edge_list) if filter_func else edge_list
450
- for e in edge_list:
451
- if e._jac_.target and e._jac_.source:
452
- if (
453
- dir in ["OUT", "ANY"] # TODO: Not ideal
454
- and i._jac_.obj == e._jac_.source
455
- and e._jac_.target == j._jac_.obj
456
- ):
457
- e._jac_.detach(i._jac_.obj, e._jac_.target)
458
- disconnect_occurred = True
459
- if (
460
- dir in ["IN", "ANY"]
461
- and i._jac_.obj == e._jac_.target
462
- and e._jac_.source == j._jac_.obj
463
- ):
464
- e._jac_.detach(i._jac_.obj, e._jac_.source)
465
- disconnect_occurred = True
490
+ node = i.__jac__
491
+ for anchor in set(node.edges):
492
+ if (
493
+ (source := anchor.source)
494
+ and (target := anchor.target)
495
+ and (not filter_func or filter_func([anchor.architype]))
496
+ and source.architype
497
+ and target.architype
498
+ ):
499
+ if (
500
+ dir in [EdgeDir.OUT, EdgeDir.ANY]
501
+ and node == source
502
+ and target.architype in right
503
+ and root.has_write_access(target)
504
+ ):
505
+ anchor.destroy() if anchor.persistent else anchor.detach()
506
+ disconnect_occurred = True
507
+ if (
508
+ dir in [EdgeDir.IN, EdgeDir.ANY]
509
+ and node == target
510
+ and source.architype in right
511
+ and root.has_write_access(source)
512
+ ):
513
+ anchor.destroy() if anchor.persistent else anchor.detach()
514
+ disconnect_occurred = True
515
+
466
516
  return disconnect_occurred
467
517
 
468
518
  @staticmethod
@@ -481,7 +531,7 @@ class JacFeatureDefaults:
481
531
  @hookimpl
482
532
  def get_root() -> Root:
483
533
  """Jac's assign comprehension feature."""
484
- return Jac.context().get_root()
534
+ return ExecutionContext.get_root()
485
535
 
486
536
  @staticmethod
487
537
  @hookimpl
@@ -495,19 +545,23 @@ class JacFeatureDefaults:
495
545
  is_undirected: bool,
496
546
  conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
497
547
  conn_assign: Optional[tuple[tuple, tuple]],
498
- ) -> Callable[[], EdgeArchitype]:
548
+ ) -> Callable[[NodeAnchor, NodeAnchor], EdgeArchitype]:
499
549
  """Jac's root getter."""
500
550
  conn_type = conn_type if conn_type else GenericEdge
501
551
 
502
- def builder() -> EdgeArchitype:
552
+ def builder(source: NodeAnchor, target: NodeAnchor) -> EdgeArchitype:
503
553
  edge = conn_type() if isinstance(conn_type, type) else conn_type
504
- edge._jac_.is_undirected = is_undirected
554
+ edge.__attach__(source, target, is_undirected)
505
555
  if conn_assign:
506
556
  for fld, val in zip(conn_assign[0], conn_assign[1]):
507
557
  if hasattr(edge, fld):
508
558
  setattr(edge, fld, val)
509
559
  else:
510
560
  raise ValueError(f"Invalid attribute: {fld}")
561
+ if source.persistent or target.persistent:
562
+ edge.__jac__.save()
563
+ target.save()
564
+ source.save()
511
565
  return edge
512
566
 
513
567
  return builder
@@ -628,11 +682,153 @@ class JacFeatureDefaults:
628
682
  inputs: list[tuple[str, str, str, Any]],
629
683
  outputs: tuple,
630
684
  action: str,
685
+ _globals: dict,
686
+ _locals: Mapping,
631
687
  ) -> Any: # noqa: ANN401
632
688
  """Jac's with_llm feature."""
633
689
  raise ImportError(
634
- "mtllm is not installed. Please install it with `pip install mtllm`."
690
+ "mtllm is not installed. Please install it with `pip install mtllm` and run `jac clean`."
691
+ )
692
+
693
+ @staticmethod
694
+ @hookimpl
695
+ def gen_llm_body(_pass: PyastGenPass, node: ast.Ability) -> list[ast3.AST]:
696
+ """Generate the by LLM body."""
697
+ _pass.log_warning(
698
+ "MT-LLM is not installed. Please install it with `pip install mtllm`."
699
+ )
700
+ return [
701
+ _pass.sync(
702
+ ast3.Raise(
703
+ _pass.sync(
704
+ ast3.Call(
705
+ func=_pass.sync(
706
+ ast3.Name(id="ImportError", ctx=ast3.Load())
707
+ ),
708
+ args=[
709
+ _pass.sync(
710
+ ast3.Constant(
711
+ value="mtllm is not installed. Please install it with `pip install mtllm` and run `jac clean`." # noqa: E501
712
+ )
713
+ )
714
+ ],
715
+ keywords=[],
716
+ )
717
+ )
718
+ )
719
+ )
720
+ ]
721
+
722
+ @staticmethod
723
+ @hookimpl
724
+ def by_llm_call(
725
+ _pass: PyastGenPass,
726
+ model: ast3.AST,
727
+ model_params: dict[str, ast.Expr],
728
+ scope: ast3.AST,
729
+ inputs: Sequence[Optional[ast3.AST]],
730
+ outputs: Sequence[Optional[ast3.AST]] | ast3.Call,
731
+ action: Optional[ast3.AST],
732
+ include_info: list[tuple[str, ast3.AST]],
733
+ exclude_info: list[tuple[str, ast3.AST]],
734
+ ) -> ast3.Call:
735
+ """Return the LLM Call, e.g. _Jac.with_llm()."""
736
+ _pass.log_warning(
737
+ "MT-LLM is not installed. Please install it with `pip install mtllm`."
635
738
  )
739
+ return ast3.Call(
740
+ func=_pass.sync(
741
+ ast3.Attribute(
742
+ value=_pass.sync(ast3.Name(id="_Jac", ctx=ast3.Load())),
743
+ attr="with_llm",
744
+ ctx=ast3.Load(),
745
+ )
746
+ ),
747
+ args=[],
748
+ keywords=[
749
+ _pass.sync(
750
+ ast3.keyword(
751
+ arg="file_loc",
752
+ value=_pass.sync(ast3.Constant(value="None")),
753
+ )
754
+ ),
755
+ _pass.sync(
756
+ ast3.keyword(
757
+ arg="model",
758
+ value=_pass.sync(ast3.Constant(value="None")),
759
+ )
760
+ ),
761
+ _pass.sync(
762
+ ast3.keyword(
763
+ arg="model_params",
764
+ value=_pass.sync(ast3.Dict(keys=[], values=[])),
765
+ )
766
+ ),
767
+ _pass.sync(
768
+ ast3.keyword(
769
+ arg="scope",
770
+ value=_pass.sync(ast3.Constant(value="None")),
771
+ )
772
+ ),
773
+ _pass.sync(
774
+ ast3.keyword(
775
+ arg="incl_info",
776
+ value=_pass.sync(ast3.List(elts=[], ctx=ast3.Load())),
777
+ )
778
+ ),
779
+ _pass.sync(
780
+ ast3.keyword(
781
+ arg="excl_info",
782
+ value=_pass.sync(ast3.List(elts=[], ctx=ast3.Load())),
783
+ )
784
+ ),
785
+ _pass.sync(
786
+ ast3.keyword(
787
+ arg="inputs",
788
+ value=_pass.sync(ast3.List(elts=[], ctx=ast3.Load())),
789
+ )
790
+ ),
791
+ _pass.sync(
792
+ ast3.keyword(
793
+ arg="outputs",
794
+ value=_pass.sync(ast3.List(elts=[], ctx=ast3.Load())),
795
+ )
796
+ ),
797
+ _pass.sync(
798
+ ast3.keyword(
799
+ arg="action",
800
+ value=_pass.sync(ast3.Constant(value="None")),
801
+ )
802
+ ),
803
+ _pass.sync(
804
+ ast3.keyword(
805
+ arg="_globals",
806
+ value=_pass.sync(ast3.Constant(value="None")),
807
+ )
808
+ ),
809
+ _pass.sync(
810
+ ast3.keyword(
811
+ arg="_locals",
812
+ value=_pass.sync(ast3.Constant(value="None")),
813
+ )
814
+ ),
815
+ ],
816
+ )
817
+
818
+ @staticmethod
819
+ @hookimpl
820
+ def get_by_llm_call_args(_pass: PyastGenPass, node: ast.FuncCall) -> dict:
821
+ """Get the by LLM call args."""
822
+ return {
823
+ "model": None,
824
+ "model_params": {},
825
+ "scope": None,
826
+ "inputs": [],
827
+ "outputs": [],
828
+ "action": None,
829
+ "include_info": [],
830
+ "exclude_info": [],
831
+ }
636
832
 
637
833
 
638
834
  class JacBuiltin:
@@ -707,14 +903,14 @@ class JacBuiltin:
707
903
  for source, target, edge in connections:
708
904
  dot_content += (
709
905
  f"{visited_nodes.index(source)} -> {visited_nodes.index(target)} "
710
- f' [label="{html.escape(str(edge._jac_.obj.__class__.__name__))} "];\n'
906
+ f' [label="{html.escape(str(edge.__jac__.architype.__class__.__name__))} "];\n'
711
907
  )
712
908
  for node_ in visited_nodes:
713
909
  color = (
714
910
  colors[node_depths[node_]] if node_depths[node_] < 25 else colors[24]
715
911
  )
716
912
  dot_content += (
717
- f'{visited_nodes.index(node_)} [label="{html.escape(str(node_._jac_.obj))}"'
913
+ f'{visited_nodes.index(node_)} [label="{html.escape(str(node_.__jac__.architype))}"'
718
914
  f'fillcolor="{color}"];\n'
719
915
  )
720
916
  if dot_file: