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/core/architype.py DELETED
@@ -1,502 +0,0 @@
1
- """Core constructs for Jac Language."""
2
-
3
- from __future__ import annotations
4
-
5
- import types
6
- from dataclasses import dataclass, field
7
- from typing import Any, Callable, Optional
8
- from uuid import UUID, uuid4
9
-
10
- from jaclang.compiler.constant import EdgeDir
11
- from jaclang.core.utils import collect_node_connections
12
-
13
-
14
- @dataclass(eq=False)
15
- class ElementAnchor:
16
- """Element Anchor."""
17
-
18
- obj: Architype
19
- id: UUID = field(default_factory=uuid4)
20
-
21
-
22
- @dataclass(eq=False)
23
- class ObjectAnchor(ElementAnchor):
24
- """Object Anchor."""
25
-
26
- def spawn_call(self, walk: WalkerArchitype) -> WalkerArchitype:
27
- """Invoke data spatial call."""
28
- return walk._jac_.spawn_call(self.obj)
29
-
30
-
31
- @dataclass(eq=False)
32
- class NodeAnchor(ObjectAnchor):
33
- """Node Anchor."""
34
-
35
- obj: NodeArchitype
36
- edges: list[EdgeArchitype] = field(default_factory=lambda: [])
37
- edge_ids: list[UUID] = field(default_factory=lambda: [])
38
- persistent: bool = False
39
-
40
- def __getstate__(self) -> dict:
41
- """Override getstate for pickle and shelve."""
42
- state = self.__dict__.copy()
43
- state.pop("obj")
44
- if self.edges and "edges" in state:
45
- edges = state.pop("edges")
46
- state["edge_ids"] = [e._jac_.id for e in edges]
47
-
48
- return state
49
-
50
- def __setstate__(self, state: dict) -> None:
51
- """Override setstate for pickle and shelve."""
52
- self.__dict__.update(state)
53
- if "edge_ids" in state:
54
- self.edge_ids = state.pop("edge_ids")
55
-
56
- def populate_edges(self) -> None:
57
- """Populate edges from edge ids."""
58
- from jaclang.plugin.feature import JacFeature as Jac
59
-
60
- if len(self.edges) == 0 and len(self.edge_ids) > 0:
61
- for e_id in self.edge_ids:
62
- edge = Jac.context().get_obj(e_id)
63
- if edge is None:
64
- raise ValueError(f"Edge with id {e_id} not found.")
65
- elif not isinstance(edge, EdgeArchitype):
66
- raise ValueError(f"Object with id {e_id} is not an edge.")
67
- else:
68
- self.edges.append(edge)
69
- self.edge_ids.clear()
70
-
71
- def connect_node(self, nd: NodeArchitype, edg: EdgeArchitype) -> NodeArchitype:
72
- """Connect a node with given edge."""
73
- edg._jac_.attach(self.obj, nd)
74
- return self.obj
75
-
76
- def get_edges(
77
- self,
78
- dir: EdgeDir,
79
- filter_func: Optional[Callable[[list[EdgeArchitype]], list[EdgeArchitype]]],
80
- target_obj: Optional[list[NodeArchitype]],
81
- ) -> list[EdgeArchitype]:
82
- """Get edges connected to this node."""
83
- self.populate_edges()
84
-
85
- edge_list: list[EdgeArchitype] = [*self.edges]
86
- ret_edges: list[EdgeArchitype] = []
87
- edge_list = filter_func(edge_list) if filter_func else edge_list
88
- for e in edge_list:
89
- if (
90
- e._jac_.target
91
- and e._jac_.source
92
- and (
93
- dir in [EdgeDir.OUT, EdgeDir.ANY]
94
- and self.obj == e._jac_.source
95
- and (not target_obj or e._jac_.target in target_obj)
96
- )
97
- or (
98
- dir in [EdgeDir.IN, EdgeDir.ANY]
99
- and self.obj == e._jac_.target
100
- and (not target_obj or e._jac_.source in target_obj)
101
- )
102
- ):
103
- ret_edges.append(e)
104
- return ret_edges
105
-
106
- def edges_to_nodes(
107
- self,
108
- dir: EdgeDir,
109
- filter_func: Optional[Callable[[list[EdgeArchitype]], list[EdgeArchitype]]],
110
- target_obj: Optional[list[NodeArchitype]],
111
- ) -> list[NodeArchitype]:
112
- """Get set of nodes connected to this node."""
113
- self.populate_edges()
114
- for edge in self.edges:
115
- edge.populate_nodes()
116
- edge_list: list[EdgeArchitype] = [*self.edges]
117
- node_list: list[NodeArchitype] = []
118
- edge_list = filter_func(edge_list) if filter_func else edge_list
119
- for e in edge_list:
120
- if e._jac_.target and e._jac_.source:
121
- if (
122
- dir in [EdgeDir.OUT, EdgeDir.ANY]
123
- and self.obj == e._jac_.source
124
- and (not target_obj or e._jac_.target in target_obj)
125
- ):
126
- node_list.append(e._jac_.target)
127
- if (
128
- dir in [EdgeDir.IN, EdgeDir.ANY]
129
- and self.obj == e._jac_.target
130
- and (not target_obj or e._jac_.source in target_obj)
131
- ):
132
- node_list.append(e._jac_.source)
133
- return node_list
134
-
135
- def gen_dot(self, dot_file: Optional[str] = None) -> str:
136
- """Generate Dot file for visualizing nodes and edges."""
137
- visited_nodes: set[NodeAnchor] = set()
138
- connections: set[tuple[NodeArchitype, NodeArchitype, str]] = set()
139
- unique_node_id_dict = {}
140
-
141
- collect_node_connections(self, visited_nodes, connections)
142
- dot_content = 'digraph {\nnode [style="filled", shape="ellipse", fillcolor="invis", fontcolor="black"];\n'
143
- for idx, i in enumerate([nodes_.obj for nodes_ in visited_nodes]):
144
- unique_node_id_dict[i] = (i.__class__.__name__, str(idx))
145
- dot_content += f'{idx} [label="{i}"];\n'
146
- dot_content += 'edge [color="gray", style="solid"];\n'
147
-
148
- for pair in list(set(connections)):
149
- dot_content += (
150
- f"{unique_node_id_dict[pair[0]][1]} -> {unique_node_id_dict[pair[1]][1]}"
151
- f' [label="{pair[2]}"];\n'
152
- )
153
- if dot_file:
154
- with open(dot_file, "w") as f:
155
- f.write(dot_content + "}")
156
- return dot_content + "}"
157
-
158
-
159
- @dataclass(eq=False)
160
- class EdgeAnchor(ObjectAnchor):
161
- """Edge Anchor."""
162
-
163
- obj: EdgeArchitype
164
- source: Optional[NodeArchitype] = None
165
- target: Optional[NodeArchitype] = None
166
- source_id: Optional[UUID] = None
167
- target_id: Optional[UUID] = None
168
- is_undirected: bool = False
169
- persistent: bool = False
170
-
171
- def __getstate__(self) -> dict:
172
- """Override getstate for pickle and shelve."""
173
- state = self.__dict__.copy()
174
- state.pop("obj")
175
-
176
- if self.source:
177
- state["source_id"] = self.source._jac_.id
178
- state.pop("source")
179
-
180
- if self.target:
181
- state["target_id"] = self.target._jac_.id
182
- state.pop("target")
183
-
184
- return state
185
-
186
- def __setstate__(self, state: dict) -> None:
187
- """Override setstate for pickle and shelve."""
188
- self.__dict__.update(state)
189
-
190
- def attach(
191
- self, src: NodeArchitype, trg: NodeArchitype, is_undirected: bool = False
192
- ) -> EdgeAnchor:
193
- """Attach edge to nodes."""
194
- self.source = src
195
- self.target = trg
196
- self.is_undirected = is_undirected
197
- src._jac_.edges.append(self.obj)
198
- trg._jac_.edges.append(self.obj)
199
- return self
200
-
201
- def detach(
202
- self, src: NodeArchitype, trg: NodeArchitype, is_undirected: bool = False
203
- ) -> None:
204
- """Detach edge from nodes."""
205
- self.is_undirected = is_undirected
206
- src._jac_.edges.remove(self.obj)
207
- trg._jac_.edges.remove(self.obj)
208
- self.source = None
209
- self.target = None
210
- del self
211
-
212
- def spawn_call(self, walk: WalkerArchitype) -> WalkerArchitype:
213
- """Invoke data spatial call."""
214
- if self.target:
215
- return walk._jac_.spawn_call(self.target)
216
- else:
217
- raise ValueError("Edge has no target.")
218
-
219
-
220
- @dataclass(eq=False)
221
- class WalkerAnchor(ObjectAnchor):
222
- """Walker Anchor."""
223
-
224
- obj: WalkerArchitype
225
- path: list[Architype] = field(default_factory=lambda: [])
226
- next: list[Architype] = field(default_factory=lambda: [])
227
- ignores: list[Architype] = field(default_factory=lambda: [])
228
- disengaged: bool = False
229
-
230
- def visit_node(
231
- self,
232
- nds: (
233
- list[NodeArchitype | EdgeArchitype]
234
- | list[NodeArchitype]
235
- | list[EdgeArchitype]
236
- | NodeArchitype
237
- | EdgeArchitype
238
- ),
239
- ) -> bool:
240
- """Walker visits node."""
241
- nd_list: list[NodeArchitype | EdgeArchitype]
242
- if not isinstance(nds, list):
243
- nd_list = [nds]
244
- else:
245
- nd_list = list(nds)
246
- before_len = len(self.next)
247
- for i in nd_list:
248
- if i not in self.ignores:
249
- if isinstance(i, NodeArchitype):
250
- self.next.append(i)
251
- elif isinstance(i, EdgeArchitype):
252
- if i._jac_.target:
253
- self.next.append(i._jac_.target)
254
- else:
255
- raise ValueError("Edge has no target.")
256
- return len(self.next) > before_len
257
-
258
- def ignore_node(
259
- self,
260
- nds: (
261
- list[NodeArchitype | EdgeArchitype]
262
- | list[NodeArchitype]
263
- | list[EdgeArchitype]
264
- | NodeArchitype
265
- | EdgeArchitype
266
- ),
267
- ) -> bool:
268
- """Walker ignores node."""
269
- nd_list: list[NodeArchitype | EdgeArchitype]
270
- if not isinstance(nds, list):
271
- nd_list = [nds]
272
- else:
273
- nd_list = list(nds)
274
- before_len = len(self.ignores)
275
- for i in nd_list:
276
- if i not in self.ignores:
277
- if isinstance(i, NodeArchitype):
278
- self.ignores.append(i)
279
- elif isinstance(i, EdgeArchitype):
280
- if i._jac_.target:
281
- self.ignores.append(i._jac_.target)
282
- else:
283
- raise ValueError("Edge has no target.")
284
- return len(self.ignores) > before_len
285
-
286
- def disengage_now(self) -> None:
287
- """Disengage walker from traversal."""
288
- self.disengaged = True
289
-
290
- def spawn_call(self, nd: Architype) -> WalkerArchitype:
291
- """Invoke data spatial call."""
292
- self.path = []
293
- self.next = [nd]
294
- while len(self.next):
295
- nd = self.next.pop(0)
296
- for i in nd._jac_entry_funcs_:
297
- if not i.trigger or isinstance(self.obj, i.trigger):
298
- if i.func:
299
- i.func(nd, self.obj)
300
- else:
301
- raise ValueError(f"No function {i.name} to call.")
302
- if self.disengaged:
303
- return self.obj
304
- for i in self.obj._jac_entry_funcs_:
305
- if not i.trigger or isinstance(nd, i.trigger):
306
- if i.func:
307
- i.func(self.obj, nd)
308
- else:
309
- raise ValueError(f"No function {i.name} to call.")
310
- if self.disengaged:
311
- return self.obj
312
- for i in self.obj._jac_exit_funcs_:
313
- if not i.trigger or isinstance(nd, i.trigger):
314
- if i.func:
315
- i.func(self.obj, nd)
316
- else:
317
- raise ValueError(f"No function {i.name} to call.")
318
- if self.disengaged:
319
- return self.obj
320
- for i in nd._jac_exit_funcs_:
321
- if not i.trigger or isinstance(self.obj, i.trigger):
322
- if i.func:
323
- i.func(nd, self.obj)
324
- else:
325
- raise ValueError(f"No function {i.name} to call.")
326
- if self.disengaged:
327
- return self.obj
328
- self.ignores = []
329
- return self.obj
330
-
331
-
332
- class Architype:
333
- """Architype Protocol."""
334
-
335
- _jac_entry_funcs_: list[DSFunc]
336
- _jac_exit_funcs_: list[DSFunc]
337
-
338
- def __init__(self) -> None:
339
- """Create default architype."""
340
- self._jac_: ObjectAnchor = ObjectAnchor(obj=self)
341
-
342
- def __hash__(self) -> int:
343
- """Override hash for architype."""
344
- return hash(self._jac_.id)
345
-
346
- def __eq__(self, other: object) -> bool:
347
- """Override equality for architype."""
348
- if not isinstance(other, Architype):
349
- return False
350
- else:
351
- return self._jac_.id == other._jac_.id
352
-
353
- def __repr__(self) -> str:
354
- """Override repr for architype."""
355
- return f"{self.__class__.__name__}"
356
-
357
- def __getstate__(self) -> dict:
358
- """Override getstate for pickle and shelve."""
359
- raise NotImplementedError
360
-
361
-
362
- class NodeArchitype(Architype):
363
- """Node Architype Protocol."""
364
-
365
- _jac_: NodeAnchor
366
-
367
- def __init__(self) -> None:
368
- """Create node architype."""
369
- from jaclang.plugin.feature import JacFeature as Jac
370
-
371
- self._jac_: NodeAnchor = NodeAnchor(obj=self)
372
- Jac.context().save_obj(self, persistent=self._jac_.persistent)
373
-
374
- def save(self) -> None:
375
- """Save the node to the memory/storage hierarchy."""
376
- from jaclang.plugin.feature import JacFeature as Jac
377
-
378
- self._jac_.persistent = True
379
- Jac.context().save_obj(self, persistent=True)
380
-
381
- def __getstate__(self) -> dict:
382
- """Override getstate for pickle and shelve."""
383
- state = self.__dict__.copy()
384
- state["_jac_"] = self._jac_.__getstate__()
385
- return state
386
-
387
- def __setstate__(self, state: dict) -> None:
388
- """Override setstate for pickle and shelve."""
389
- self.__dict__.update(state)
390
- self._jac_ = NodeAnchor(obj=self)
391
- self._jac_.__setstate__(state["_jac_"])
392
-
393
-
394
- class EdgeArchitype(Architype):
395
- """Edge Architype Protocol."""
396
-
397
- _jac_: EdgeAnchor
398
- persistent: bool = False
399
-
400
- def __init__(self) -> None:
401
- """Create edge architype."""
402
- from jaclang.plugin.feature import JacFeature as Jac
403
-
404
- self._jac_: EdgeAnchor = EdgeAnchor(obj=self)
405
- Jac.context().save_obj(self, persistent=self.persistent)
406
-
407
- def save(self) -> None:
408
- """Save the edge to the memory/storage hierarchy."""
409
- from jaclang.plugin.feature import JacFeature as Jac
410
-
411
- self.persistent = True
412
- Jac.context().save_obj(self, persistent=True)
413
-
414
- def __getstate__(self) -> dict:
415
- """Override getstate for pickle and shelve."""
416
- state = self.__dict__.copy()
417
- state["_jac_"] = self._jac_.__getstate__()
418
- return state
419
-
420
- def __setstate__(self, state: dict) -> None:
421
- """Override setstate for pickle and shelve."""
422
- self.__dict__.update(state)
423
- self._jac_ = EdgeAnchor(obj=self)
424
- self._jac_.__setstate__(state["_jac_"])
425
-
426
- def populate_nodes(self) -> None:
427
- """Populate nodes for the edges from node ids."""
428
- from jaclang.plugin.feature import JacFeature as Jac
429
-
430
- if self._jac_.source_id:
431
- obj = Jac.context().get_obj(self._jac_.source_id)
432
- if obj is None:
433
- raise ValueError(f"Node with id {self._jac_.source_id} not found.")
434
- elif not isinstance(obj, NodeArchitype):
435
- raise ValueError(
436
- f"Object with id {self._jac_.source_id} is not a node."
437
- )
438
- else:
439
- self._jac_.source = obj
440
- self._jac_.source_id = None
441
- if self._jac_.target_id:
442
- obj = Jac.context().get_obj(self._jac_.target_id)
443
- if obj is None:
444
- raise ValueError(f"Node with id {self._jac_.target_id} not found.")
445
- elif not isinstance(obj, NodeArchitype):
446
- raise ValueError(
447
- f"Object with id {self._jac_.target_id} is not a node."
448
- )
449
- else:
450
- self._jac_.target = obj
451
- self._jac_.target_id = None
452
-
453
-
454
- class WalkerArchitype(Architype):
455
- """Walker Architype Protocol."""
456
-
457
- _jac_: WalkerAnchor
458
-
459
- def __init__(self) -> None:
460
- """Create walker architype."""
461
- self._jac_: WalkerAnchor = WalkerAnchor(obj=self)
462
-
463
-
464
- class GenericEdge(EdgeArchitype):
465
- """Generic Root Node."""
466
-
467
- _jac_entry_funcs_ = []
468
- _jac_exit_funcs_ = []
469
-
470
-
471
- class Root(NodeArchitype):
472
- """Generic Root Node."""
473
-
474
- _jac_entry_funcs_ = []
475
- _jac_exit_funcs_ = []
476
- reachable_nodes: list[NodeArchitype] = []
477
- connections: set[tuple[NodeArchitype, NodeArchitype, EdgeArchitype]] = set()
478
-
479
- def __init__(self) -> None:
480
- """Create root node."""
481
- super().__init__()
482
- self._jac_.id = UUID(int=0)
483
- self._jac_.persistent = True
484
-
485
- def reset(self) -> None:
486
- """Reset the root."""
487
- self.reachable_nodes = []
488
- self.connections = set()
489
- self._jac_.edges = []
490
-
491
-
492
- @dataclass(eq=False)
493
- class DSFunc:
494
- """Data Spatial Function."""
495
-
496
- name: str
497
- trigger: type | types.UnionType | tuple[type | types.UnionType, ...] | None
498
- func: Callable[[Any, Any], Any] | None = None
499
-
500
- def resolve(self, cls: type) -> None:
501
- """Resolve the function."""
502
- self.func = getattr(cls, self.name)