jaclang 0.7.16__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 (77) hide show
  1. jaclang/cli/cli.py +140 -75
  2. jaclang/compiler/absyntree.py +9 -4
  3. jaclang/compiler/constant.py +8 -8
  4. jaclang/compiler/parser.py +10 -2
  5. jaclang/compiler/passes/main/__init__.py +1 -1
  6. jaclang/compiler/passes/main/access_modifier_pass.py +96 -147
  7. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +152 -50
  8. jaclang/compiler/passes/main/import_pass.py +88 -59
  9. jaclang/compiler/passes/main/py_collect_dep_pass.py +70 -0
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +21 -6
  11. jaclang/compiler/passes/main/pyast_load_pass.py +1 -0
  12. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -0
  13. jaclang/compiler/passes/main/schedules.py +9 -2
  14. jaclang/compiler/passes/main/sym_tab_build_pass.py +9 -5
  15. jaclang/compiler/passes/main/tests/fixtures/autoimpl.empty.impl.jac +0 -0
  16. jaclang/compiler/passes/main/tests/fixtures/autoimpl.jac +1 -1
  17. jaclang/compiler/passes/main/tests/fixtures/py_imp_test.jac +29 -0
  18. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -0
  19. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/color.py +3 -0
  20. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/constants.py +5 -0
  21. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/display.py +2 -0
  22. jaclang/compiler/passes/main/tests/test_import_pass.py +72 -13
  23. jaclang/compiler/passes/main/type_check_pass.py +15 -5
  24. jaclang/compiler/passes/tool/jac_formatter_pass.py +11 -3
  25. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +37 -41
  26. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +37 -41
  27. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/access_mod_check.jac +27 -0
  28. jaclang/compiler/passes/utils/mypy_ast_build.py +45 -0
  29. jaclang/compiler/symtable.py +16 -11
  30. jaclang/compiler/tests/test_importer.py +17 -9
  31. jaclang/langserve/engine.py +39 -0
  32. jaclang/langserve/server.py +16 -1
  33. jaclang/langserve/tests/fixtures/rename.jac +30 -0
  34. jaclang/langserve/tests/test_server.py +216 -2
  35. jaclang/langserve/utils.py +21 -2
  36. jaclang/plugin/default.py +78 -70
  37. jaclang/plugin/feature.py +7 -17
  38. jaclang/plugin/spec.py +6 -19
  39. jaclang/plugin/tests/fixtures/other_root_access.jac +82 -0
  40. jaclang/plugin/tests/test_jaseci.py +414 -42
  41. jaclang/runtimelib/architype.py +481 -333
  42. jaclang/runtimelib/constructs.py +5 -8
  43. jaclang/runtimelib/context.py +89 -69
  44. jaclang/runtimelib/importer.py +15 -15
  45. jaclang/runtimelib/machine.py +66 -2
  46. jaclang/runtimelib/memory.py +134 -75
  47. jaclang/runtimelib/utils.py +17 -10
  48. jaclang/settings.py +2 -4
  49. jaclang/tests/fixtures/access_checker.jac +12 -17
  50. jaclang/tests/fixtures/access_modifier.jac +88 -33
  51. jaclang/tests/fixtures/baddy.jac +3 -0
  52. jaclang/tests/fixtures/bar.jac +34 -0
  53. jaclang/tests/fixtures/edge_node_walk.jac +1 -1
  54. jaclang/tests/fixtures/edge_ops.jac +1 -1
  55. jaclang/tests/fixtures/edges_walk.jac +1 -1
  56. jaclang/tests/fixtures/foo.jac +43 -0
  57. jaclang/tests/fixtures/game1.jac +1 -1
  58. jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
  59. jaclang/tests/fixtures/import.jac +9 -0
  60. jaclang/tests/fixtures/index_slice.jac +30 -0
  61. jaclang/tests/fixtures/pyfunc_1.py +1 -1
  62. jaclang/tests/fixtures/pyfunc_2.py +2 -2
  63. jaclang/tests/fixtures/pygame_mock/__init__.py +3 -0
  64. jaclang/tests/fixtures/pygame_mock/color.py +3 -0
  65. jaclang/tests/fixtures/pygame_mock/constants.py +5 -0
  66. jaclang/tests/fixtures/pygame_mock/display.py +2 -0
  67. jaclang/tests/fixtures/pygame_mock/inner/__init__.py +0 -0
  68. jaclang/tests/fixtures/pygame_mock/inner/iner_mod.py +2 -0
  69. jaclang/tests/test_cli.py +49 -6
  70. jaclang/tests/test_language.py +113 -78
  71. jaclang/tests/test_reference.py +2 -9
  72. jaclang/utils/treeprinter.py +30 -3
  73. {jaclang-0.7.16.dist-info → jaclang-0.7.17.dist-info}/METADATA +1 -1
  74. {jaclang-0.7.16.dist-info → jaclang-0.7.17.dist-info}/RECORD +77 -56
  75. /jaclang/tests/fixtures/{err.test.jac → baddy.test.jac} +0 -0
  76. {jaclang-0.7.16.dist-info → jaclang-0.7.17.dist-info}/WHEEL +0 -0
  77. {jaclang-0.7.16.dist-info → jaclang-0.7.17.dist-info}/entry_points.txt +0 -0
jaclang/plugin/default.py CHANGED
@@ -18,6 +18,7 @@ from jaclang.compiler.constant import EdgeDir, colors
18
18
  from jaclang.compiler.passes.main.pyast_gen_pass import PyastGenPass
19
19
  from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
20
20
  from jaclang.runtimelib.constructs import (
21
+ Anchor,
21
22
  Architype,
22
23
  DSFunc,
23
24
  EdgeAnchor,
@@ -25,16 +26,14 @@ from jaclang.runtimelib.constructs import (
25
26
  ExecutionContext,
26
27
  GenericEdge,
27
28
  JacTestCheck,
28
- Memory,
29
29
  NodeAnchor,
30
30
  NodeArchitype,
31
- ObjectAnchor,
32
31
  Root,
33
32
  WalkerAnchor,
34
33
  WalkerArchitype,
35
- exec_context,
36
34
  )
37
35
  from jaclang.runtimelib.importer import ImportPathSpec, JacImporter, PythonImporter
36
+ from jaclang.runtimelib.machine import JacMachine, JacProgram
38
37
  from jaclang.runtimelib.utils import traverse_graph
39
38
  from jaclang.plugin.feature import JacFeature as Jac # noqa: I100
40
39
  from jaclang.plugin.spec import P, T
@@ -45,12 +44,12 @@ import pluggy
45
44
  hookimpl = pluggy.HookimplMarker("jac")
46
45
 
47
46
  __all__ = [
47
+ "Anchor",
48
48
  "EdgeAnchor",
49
49
  "GenericEdge",
50
50
  "hookimpl",
51
51
  "JacTestCheck",
52
52
  "NodeAnchor",
53
- "ObjectAnchor",
54
53
  "WalkerAnchor",
55
54
  "NodeArchitype",
56
55
  "EdgeArchitype",
@@ -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
@@ -263,12 +243,18 @@ class JacFeatureDefaults:
263
243
  lng,
264
244
  items,
265
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
+
266
251
  if lng == "py":
267
- import_result = PythonImporter(Jac.context().jac_machine).run_import(spec)
252
+ import_result = PythonImporter(JacMachine.get()).run_import(spec)
268
253
  else:
269
- import_result = JacImporter(Jac.context().jac_machine).run_import(
254
+ import_result = JacImporter(JacMachine.get()).run_import(
270
255
  spec, reload_module
271
256
  )
257
+
272
258
  return (
273
259
  (import_result.ret_mod,)
274
260
  if absorb or not items
@@ -366,9 +352,9 @@ class JacFeatureDefaults:
366
352
  def spawn_call(op1: Architype, op2: Architype) -> WalkerArchitype:
367
353
  """Jac's spawn operator feature."""
368
354
  if isinstance(op1, WalkerArchitype):
369
- return op1._jac_.spawn_call(op2)
355
+ return op1.__jac__.spawn_call(op2.__jac__)
370
356
  elif isinstance(op2, WalkerArchitype):
371
- return op2._jac_.spawn_call(op1)
357
+ return op2.__jac__.spawn_call(op1.__jac__)
372
358
  else:
373
359
  raise TypeError("Invalid walker object")
374
360
 
@@ -390,7 +376,12 @@ class JacFeatureDefaults:
390
376
  ),
391
377
  ) -> bool:
392
378
  """Jac's ignore stmt feature."""
393
- 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")
394
385
 
395
386
  @staticmethod
396
387
  @hookimpl
@@ -406,7 +397,9 @@ class JacFeatureDefaults:
406
397
  ) -> bool:
407
398
  """Jac's visit stmt feature."""
408
399
  if isinstance(walker, WalkerArchitype):
409
- 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
+ )
410
403
  else:
411
404
  raise TypeError("Invalid walker object")
412
405
 
@@ -414,7 +407,7 @@ class JacFeatureDefaults:
414
407
  @hookimpl
415
408
  def disengage(walker: WalkerArchitype) -> bool: # noqa: ANN401
416
409
  """Jac's disengage stmt feature."""
417
- walker._jac_.disengage_now()
410
+ walker.__jac__.disengage_now()
418
411
  return True
419
412
 
420
413
  @staticmethod
@@ -437,7 +430,7 @@ class JacFeatureDefaults:
437
430
  if edges_only:
438
431
  connected_edges: list[EdgeArchitype] = []
439
432
  for node in node_obj:
440
- connected_edges += node._jac_.get_edges(
433
+ connected_edges += node.__jac__.get_edges(
441
434
  dir, filter_func, target_obj=targ_obj_set
442
435
  )
443
436
  return list(set(connected_edges))
@@ -445,7 +438,9 @@ class JacFeatureDefaults:
445
438
  connected_nodes: list[NodeArchitype] = []
446
439
  for node in node_obj:
447
440
  connected_nodes.extend(
448
- 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
+ )
449
444
  )
450
445
  return list(set(connected_nodes))
451
446
 
@@ -454,7 +449,7 @@ class JacFeatureDefaults:
454
449
  def connect(
455
450
  left: NodeArchitype | list[NodeArchitype],
456
451
  right: NodeArchitype | list[NodeArchitype],
457
- edge_spec: Callable[[], EdgeArchitype],
452
+ edge_spec: Callable[[NodeAnchor, NodeAnchor], EdgeArchitype],
458
453
  edges_only: bool,
459
454
  ) -> list[NodeArchitype] | list[EdgeArchitype]:
460
455
  """Jac's connect operator feature.
@@ -464,17 +459,16 @@ class JacFeatureDefaults:
464
459
  left = [left] if isinstance(left, NodeArchitype) else left
465
460
  right = [right] if isinstance(right, NodeArchitype) else right
466
461
  edges = []
467
- for i in left:
468
- for j in right:
469
- conn_edge = edge_spec()
470
- edges.append(conn_edge)
471
- i._jac_.connect_node(j, conn_edge)
472
462
 
473
- if i._jac_.persistent or j._jac_.persistent:
474
- conn_edge.save()
475
- j.save()
476
- i.save()
463
+ root = Jac.get_root().__jac__
477
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))
478
472
  return right if not edges_only else edges
479
473
 
480
474
  @staticmethod
@@ -489,26 +483,36 @@ class JacFeatureDefaults:
489
483
  disconnect_occurred = False
490
484
  left = [left] if isinstance(left, NodeArchitype) else left
491
485
  right = [right] if isinstance(right, NodeArchitype) else right
486
+
487
+ root = Jac.get_root().__jac__
488
+
492
489
  for i in left:
493
- for j in right:
494
- edge_list: list[EdgeArchitype] = [*i._jac_.edges]
495
- edge_list = filter_func(edge_list) if filter_func else edge_list
496
- for e in edge_list:
497
- if e._jac_.target and e._jac_.source:
498
- if (
499
- dir in ["OUT", "ANY"] # TODO: Not ideal
500
- and i._jac_.obj == e._jac_.source
501
- and e._jac_.target == j._jac_.obj
502
- ):
503
- e._jac_.detach(i._jac_.obj, e._jac_.target)
504
- disconnect_occurred = True
505
- if (
506
- dir in ["IN", "ANY"]
507
- and i._jac_.obj == e._jac_.target
508
- and e._jac_.source == j._jac_.obj
509
- ):
510
- e._jac_.detach(i._jac_.obj, e._jac_.source)
511
- 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
+
512
516
  return disconnect_occurred
513
517
 
514
518
  @staticmethod
@@ -527,7 +531,7 @@ class JacFeatureDefaults:
527
531
  @hookimpl
528
532
  def get_root() -> Root:
529
533
  """Jac's assign comprehension feature."""
530
- return Jac.context().get_root()
534
+ return ExecutionContext.get_root()
531
535
 
532
536
  @staticmethod
533
537
  @hookimpl
@@ -541,19 +545,23 @@ class JacFeatureDefaults:
541
545
  is_undirected: bool,
542
546
  conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
543
547
  conn_assign: Optional[tuple[tuple, tuple]],
544
- ) -> Callable[[], EdgeArchitype]:
548
+ ) -> Callable[[NodeAnchor, NodeAnchor], EdgeArchitype]:
545
549
  """Jac's root getter."""
546
550
  conn_type = conn_type if conn_type else GenericEdge
547
551
 
548
- def builder() -> EdgeArchitype:
552
+ def builder(source: NodeAnchor, target: NodeAnchor) -> EdgeArchitype:
549
553
  edge = conn_type() if isinstance(conn_type, type) else conn_type
550
- edge._jac_.is_undirected = is_undirected
554
+ edge.__attach__(source, target, is_undirected)
551
555
  if conn_assign:
552
556
  for fld, val in zip(conn_assign[0], conn_assign[1]):
553
557
  if hasattr(edge, fld):
554
558
  setattr(edge, fld, val)
555
559
  else:
556
560
  raise ValueError(f"Invalid attribute: {fld}")
561
+ if source.persistent or target.persistent:
562
+ edge.__jac__.save()
563
+ target.save()
564
+ source.save()
557
565
  return edge
558
566
 
559
567
  return builder
@@ -895,14 +903,14 @@ class JacBuiltin:
895
903
  for source, target, edge in connections:
896
904
  dot_content += (
897
905
  f"{visited_nodes.index(source)} -> {visited_nodes.index(target)} "
898
- f' [label="{html.escape(str(edge._jac_.obj.__class__.__name__))} "];\n'
906
+ f' [label="{html.escape(str(edge.__jac__.architype.__class__.__name__))} "];\n'
899
907
  )
900
908
  for node_ in visited_nodes:
901
909
  color = (
902
910
  colors[node_depths[node_]] if node_depths[node_] < 25 else colors[24]
903
911
  )
904
912
  dot_content += (
905
- 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))}"'
906
914
  f'fillcolor="{color}"];\n'
907
915
  )
908
916
  if dot_file:
jaclang/plugin/feature.py CHANGED
@@ -8,16 +8,16 @@ from typing import Any, Callable, Mapping, Optional, Sequence, Type, TypeAlias,
8
8
 
9
9
  import jaclang.compiler.absyntree as ast
10
10
  from jaclang.compiler.passes.main.pyast_gen_pass import PyastGenPass
11
- from jaclang.plugin.default import ExecutionContext
12
11
  from jaclang.plugin.spec import JacBuiltin, JacCmdSpec, JacFeatureSpec, P, T
13
12
  from jaclang.runtimelib.constructs import (
14
13
  Architype,
15
14
  EdgeArchitype,
16
- Memory,
15
+ NodeAnchor,
17
16
  NodeArchitype,
18
17
  Root,
19
18
  WalkerArchitype,
20
19
  )
20
+ from jaclang.runtimelib.context import ExecutionContext
21
21
 
22
22
  import pluggy
23
23
 
@@ -42,19 +42,9 @@ class JacFeature:
42
42
  Walker: TypeAlias = WalkerArchitype
43
43
 
44
44
  @staticmethod
45
- def context(session: str = "") -> ExecutionContext:
46
- """Create execution context."""
47
- return pm.hook.context(session=session)
48
-
49
- @staticmethod
50
- def reset_context() -> None:
51
- """Reset execution context."""
52
- return pm.hook.reset_context()
53
-
54
- @staticmethod
55
- def memory_hook() -> Memory | None:
56
- """Create memory abstraction."""
57
- return pm.hook.memory_hook()
45
+ def get_context() -> ExecutionContext:
46
+ """Get current execution context."""
47
+ return pm.hook.get_context()
58
48
 
59
49
  @staticmethod
60
50
  def make_architype(
@@ -226,7 +216,7 @@ class JacFeature:
226
216
  def connect(
227
217
  left: NodeArchitype | list[NodeArchitype],
228
218
  right: NodeArchitype | list[NodeArchitype],
229
- edge_spec: Callable[[], EdgeArchitype],
219
+ edge_spec: Callable[[NodeAnchor, NodeAnchor], EdgeArchitype],
230
220
  edges_only: bool = False,
231
221
  ) -> list[NodeArchitype] | list[EdgeArchitype]:
232
222
  """Jac's connect operator feature.
@@ -274,7 +264,7 @@ class JacFeature:
274
264
  is_undirected: bool,
275
265
  conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
276
266
  conn_assign: Optional[tuple[tuple, tuple]],
277
- ) -> Callable[[], EdgeArchitype]:
267
+ ) -> Callable[[NodeAnchor, NodeAnchor], EdgeArchitype]:
278
268
  """Jac's root getter."""
279
269
  return pm.hook.build_edge(
280
270
  is_undirected=is_undirected, conn_type=conn_type, conn_assign=conn_assign
jaclang/plugin/spec.py CHANGED
@@ -21,16 +21,15 @@ import jaclang.compiler.absyntree as ast
21
21
  from jaclang.compiler.passes.main.pyast_gen_pass import PyastGenPass
22
22
 
23
23
  if TYPE_CHECKING:
24
- from jaclang.runtimelib.constructs import EdgeArchitype, NodeArchitype
25
24
  from jaclang.plugin.default import (
26
25
  Architype,
27
26
  EdgeDir,
28
- ExecutionContext,
29
27
  WalkerArchitype,
30
28
  Root,
31
29
  DSFunc,
32
30
  )
33
- from jaclang.runtimelib.memory import Memory
31
+ from jaclang.runtimelib.constructs import EdgeArchitype, NodeAnchor, NodeArchitype
32
+ from jaclang.runtimelib.context import ExecutionContext
34
33
 
35
34
  import pluggy
36
35
 
@@ -45,20 +44,8 @@ class JacFeatureSpec:
45
44
 
46
45
  @staticmethod
47
46
  @hookspec(firstresult=True)
48
- def context(session: str = "") -> ExecutionContext:
49
- """Get the execution context."""
50
- raise NotImplementedError
51
-
52
- @staticmethod
53
- @hookspec(firstresult=True)
54
- def reset_context() -> None:
55
- """Reset the execution context."""
56
- raise NotImplementedError
57
-
58
- @staticmethod
59
- @hookspec(firstresult=True)
60
- def memory_hook() -> Memory | None:
61
- """Create memory abstraction."""
47
+ def get_context() -> ExecutionContext:
48
+ """Get current execution context."""
62
49
  raise NotImplementedError
63
50
 
64
51
  @staticmethod
@@ -224,7 +211,7 @@ class JacFeatureSpec:
224
211
  def connect(
225
212
  left: NodeArchitype | list[NodeArchitype],
226
213
  right: NodeArchitype | list[NodeArchitype],
227
- edge_spec: Callable[[], EdgeArchitype],
214
+ edge_spec: Callable[[NodeAnchor, NodeAnchor], EdgeArchitype],
228
215
  edges_only: bool,
229
216
  ) -> list[NodeArchitype] | list[EdgeArchitype]:
230
217
  """Jac's connect operator feature.
@@ -270,7 +257,7 @@ class JacFeatureSpec:
270
257
  is_undirected: bool,
271
258
  conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
272
259
  conn_assign: Optional[tuple[tuple, tuple]],
273
- ) -> Callable[[], EdgeArchitype]:
260
+ ) -> Callable[[NodeAnchor, NodeAnchor], EdgeArchitype]:
274
261
  """Jac's root getter."""
275
262
  raise NotImplementedError
276
263
 
@@ -0,0 +1,82 @@
1
+ import:py from jaclang.runtimelib.architype {Anchor}
2
+ import:py from uuid {UUID}
3
+
4
+ node A {
5
+ has val: int;
6
+ }
7
+
8
+ walker check_node {
9
+ can enter with `root entry {
10
+ visit [-->];
11
+ }
12
+
13
+ can enter2 with A entry {
14
+ print(here);
15
+ }
16
+ }
17
+
18
+ walker update_node {
19
+ has val: int;
20
+
21
+ can enter2 with A entry {
22
+ here.val = self.val;
23
+ }
24
+ }
25
+
26
+ walker create_node {
27
+ has val: int;
28
+
29
+ can enter with `root entry {
30
+ a = A(val=self.val);
31
+ here ++> a;
32
+ print(a.__jac__.id);
33
+ }
34
+ }
35
+
36
+ walker create_other_root {
37
+ can enter with `root entry {
38
+ other_root = `root().__jac__;
39
+ other_root.save();
40
+ print(other_root.id);
41
+ }
42
+ }
43
+
44
+ walker allow_other_root_access {
45
+ has root_id: str, level: int | str = 1, via_all: bool = False;
46
+
47
+ can enter_root with `root entry {
48
+ if self.via_all {
49
+ here.__jac__.unrestrict(self.level);
50
+ } else {
51
+ here.__jac__.allow_root(UUID(self.root_id), self.level);
52
+ }
53
+ }
54
+
55
+ can enter_nested with A entry {
56
+ if self.via_all {
57
+ here.__jac__.unrestrict(self.level);
58
+ } else {
59
+ here.__jac__.allow_root(UUID(self.root_id), self.level);
60
+ }
61
+ }
62
+ }
63
+
64
+ walker disallow_other_root_access {
65
+ has root_id: str, via_all: bool = False;
66
+
67
+ can enter_root with `root entry {
68
+ if self.via_all {
69
+ here.__jac__.restrict();
70
+ } else {
71
+ here.__jac__.disallow_root(UUID(self.root_id));
72
+ }
73
+ }
74
+
75
+ can enter_nested with A entry {
76
+ if self.via_all {
77
+ here.__jac__.restrict();
78
+ } else {
79
+ here.__jac__.disallow_root(UUID(self.root_id));
80
+ }
81
+ }
82
+ }