jaclang 0.6.0__py3-none-any.whl → 0.6.1__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.
- jaclang/cli/cli.py +90 -3
- jaclang/cli/cmdreg.py +18 -6
- jaclang/compiler/absyntree.py +1 -2
- jaclang/compiler/generated/jac_parser.py +1 -1
- jaclang/compiler/parser.py +1 -1
- jaclang/compiler/passes/main/def_impl_match_pass.py +4 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +10 -7
- jaclang/compiler/passes/main/import_pass.py +39 -22
- jaclang/compiler/passes/main/pyast_gen_pass.py +6 -57
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +218 -0
- jaclang/compiler/passes/main/schedules.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +9 -3
- jaclang/compiler/passes/main/tests/test_import_pass.py +11 -0
- jaclang/core/aott.py +10 -1
- jaclang/core/construct.py +157 -21
- jaclang/core/importer.py +6 -2
- jaclang/core/memory.py +48 -0
- jaclang/core/shelve_storage.py +55 -0
- jaclang/plugin/__init__.py +1 -2
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +97 -4
- jaclang/plugin/feature.py +28 -9
- jaclang/plugin/spec.py +45 -10
- jaclang/plugin/tests/test_jaseci.py +219 -0
- jaclang/utils/treeprinter.py +7 -2
- {jaclang-0.6.0.dist-info → jaclang-0.6.1.dist-info}/METADATA +1 -1
- {jaclang-0.6.0.dist-info → jaclang-0.6.1.dist-info}/RECORD +30 -26
- {jaclang-0.6.0.dist-info → jaclang-0.6.1.dist-info}/WHEEL +0 -0
- {jaclang-0.6.0.dist-info → jaclang-0.6.1.dist-info}/entry_points.txt +0 -0
- {jaclang-0.6.0.dist-info → jaclang-0.6.1.dist-info}/top_level.txt +0 -0
jaclang/core/construct.py
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
# import shelve
|
|
6
|
-
import types
|
|
7
5
|
import unittest
|
|
8
6
|
from dataclasses import dataclass, field
|
|
9
|
-
from typing import
|
|
10
|
-
|
|
7
|
+
from typing import Callable, Optional
|
|
8
|
+
from uuid import UUID, uuid4
|
|
11
9
|
|
|
12
10
|
from jaclang.compiler.constant import EdgeDir
|
|
13
11
|
from jaclang.core.utils import collect_node_connections
|
|
12
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
13
|
+
from jaclang.plugin.spec import DSFunc
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@dataclass(eq=False)
|
|
@@ -18,6 +18,7 @@ class ElementAnchor:
|
|
|
18
18
|
"""Element Anchor."""
|
|
19
19
|
|
|
20
20
|
obj: Architype
|
|
21
|
+
id: UUID = field(default_factory=uuid4)
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
@dataclass(eq=False)
|
|
@@ -35,6 +36,37 @@ class NodeAnchor(ObjectAnchor):
|
|
|
35
36
|
|
|
36
37
|
obj: NodeArchitype
|
|
37
38
|
edges: list[EdgeArchitype] = field(default_factory=lambda: [])
|
|
39
|
+
edge_ids: list[UUID] = field(default_factory=lambda: [])
|
|
40
|
+
persistent: bool = False
|
|
41
|
+
|
|
42
|
+
def __getstate__(self) -> dict:
|
|
43
|
+
"""Override getstate for pickle and shelve."""
|
|
44
|
+
state = self.__dict__.copy()
|
|
45
|
+
state.pop("obj")
|
|
46
|
+
if self.edges and "edges" in state:
|
|
47
|
+
edges = state.pop("edges")
|
|
48
|
+
state["edge_ids"] = [e._jac_.id for e in edges]
|
|
49
|
+
|
|
50
|
+
return state
|
|
51
|
+
|
|
52
|
+
def __setstate__(self, state: dict) -> None:
|
|
53
|
+
"""Override setstate for pickle and shelve."""
|
|
54
|
+
self.__dict__.update(state)
|
|
55
|
+
if "edge_ids" in state:
|
|
56
|
+
self.edge_ids = state.pop("edge_ids")
|
|
57
|
+
|
|
58
|
+
def populate_edges(self) -> None:
|
|
59
|
+
"""Populate edges from edge ids."""
|
|
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()
|
|
38
70
|
|
|
39
71
|
def connect_node(self, nd: NodeArchitype, edg: EdgeArchitype) -> NodeArchitype:
|
|
40
72
|
"""Connect a node with given edge."""
|
|
@@ -48,6 +80,8 @@ class NodeAnchor(ObjectAnchor):
|
|
|
48
80
|
target_obj: Optional[list[NodeArchitype]],
|
|
49
81
|
) -> list[EdgeArchitype]:
|
|
50
82
|
"""Get edges connected to this node."""
|
|
83
|
+
self.populate_edges()
|
|
84
|
+
|
|
51
85
|
edge_list: list[EdgeArchitype] = [*self.edges]
|
|
52
86
|
ret_edges: list[EdgeArchitype] = []
|
|
53
87
|
edge_list = filter_func(edge_list) if filter_func else edge_list
|
|
@@ -76,6 +110,9 @@ class NodeAnchor(ObjectAnchor):
|
|
|
76
110
|
target_obj: Optional[list[NodeArchitype]],
|
|
77
111
|
) -> list[NodeArchitype]:
|
|
78
112
|
"""Get set of nodes connected to this node."""
|
|
113
|
+
self.populate_edges()
|
|
114
|
+
for edge in self.edges:
|
|
115
|
+
edge.populate_nodes()
|
|
79
116
|
edge_list: list[EdgeArchitype] = [*self.edges]
|
|
80
117
|
node_list: list[NodeArchitype] = []
|
|
81
118
|
edge_list = filter_func(edge_list) if filter_func else edge_list
|
|
@@ -126,7 +163,29 @@ class EdgeAnchor(ObjectAnchor):
|
|
|
126
163
|
obj: EdgeArchitype
|
|
127
164
|
source: Optional[NodeArchitype] = None
|
|
128
165
|
target: Optional[NodeArchitype] = None
|
|
166
|
+
source_id: Optional[UUID] = None
|
|
167
|
+
target_id: Optional[UUID] = None
|
|
129
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)
|
|
130
189
|
|
|
131
190
|
def attach(
|
|
132
191
|
self, src: NodeArchitype, trg: NodeArchitype, is_undirected: bool = False
|
|
@@ -268,26 +327,113 @@ class Architype:
|
|
|
268
327
|
"""Create default architype."""
|
|
269
328
|
self._jac_: ObjectAnchor = ObjectAnchor(obj=self)
|
|
270
329
|
|
|
330
|
+
def __hash__(self) -> int:
|
|
331
|
+
"""Override hash for architype."""
|
|
332
|
+
return hash(self._jac_.id)
|
|
333
|
+
|
|
334
|
+
def __eq__(self, other: object) -> bool:
|
|
335
|
+
"""Override equality for architype."""
|
|
336
|
+
if not isinstance(other, Architype):
|
|
337
|
+
return False
|
|
338
|
+
else:
|
|
339
|
+
return self._jac_.id == other._jac_.id
|
|
340
|
+
|
|
341
|
+
def __repr__(self) -> str:
|
|
342
|
+
"""Override repr for architype."""
|
|
343
|
+
return f"{self.__class__.__name__}"
|
|
344
|
+
|
|
345
|
+
def __getstate__(self) -> dict:
|
|
346
|
+
"""Override getstate for pickle and shelve."""
|
|
347
|
+
raise NotImplementedError
|
|
348
|
+
|
|
271
349
|
|
|
272
350
|
class NodeArchitype(Architype):
|
|
273
351
|
"""Node Architype Protocol."""
|
|
274
352
|
|
|
353
|
+
_jac_: NodeAnchor
|
|
354
|
+
|
|
275
355
|
def __init__(self) -> None:
|
|
276
356
|
"""Create node architype."""
|
|
277
357
|
self._jac_: NodeAnchor = NodeAnchor(obj=self)
|
|
358
|
+
Jac.context().save_obj(self, persistent=self._jac_.persistent)
|
|
359
|
+
|
|
360
|
+
def save(self) -> None:
|
|
361
|
+
"""Save the node to the memory/storage hierarchy."""
|
|
362
|
+
self._jac_.persistent = True
|
|
363
|
+
Jac.context().save_obj(self, persistent=True)
|
|
364
|
+
|
|
365
|
+
def __getstate__(self) -> dict:
|
|
366
|
+
"""Override getstate for pickle and shelve."""
|
|
367
|
+
state = self.__dict__.copy()
|
|
368
|
+
state["_jac_"] = self._jac_.__getstate__()
|
|
369
|
+
return state
|
|
370
|
+
|
|
371
|
+
def __setstate__(self, state: dict) -> None:
|
|
372
|
+
"""Override setstate for pickle and shelve."""
|
|
373
|
+
self.__dict__.update(state)
|
|
374
|
+
self._jac_ = NodeAnchor(obj=self)
|
|
375
|
+
self._jac_.__setstate__(state["_jac_"])
|
|
278
376
|
|
|
279
377
|
|
|
280
378
|
class EdgeArchitype(Architype):
|
|
281
379
|
"""Edge Architype Protocol."""
|
|
282
380
|
|
|
381
|
+
_jac_: EdgeAnchor
|
|
382
|
+
persistent: bool = False
|
|
383
|
+
|
|
283
384
|
def __init__(self) -> None:
|
|
284
385
|
"""Create edge architype."""
|
|
285
386
|
self._jac_: EdgeAnchor = EdgeAnchor(obj=self)
|
|
387
|
+
Jac.context().save_obj(self, persistent=self.persistent)
|
|
388
|
+
|
|
389
|
+
def save(self) -> None:
|
|
390
|
+
"""Save the edge to the memory/storage hierarchy."""
|
|
391
|
+
self.persistent = True
|
|
392
|
+
Jac.context().save_obj(self, persistent=True)
|
|
393
|
+
|
|
394
|
+
def __getstate__(self) -> dict:
|
|
395
|
+
"""Override getstate for pickle and shelve."""
|
|
396
|
+
state = self.__dict__.copy()
|
|
397
|
+
state["_jac_"] = self._jac_.__getstate__()
|
|
398
|
+
return state
|
|
399
|
+
|
|
400
|
+
def __setstate__(self, state: dict) -> None:
|
|
401
|
+
"""Override setstate for pickle and shelve."""
|
|
402
|
+
self.__dict__.update(state)
|
|
403
|
+
self._jac_ = EdgeAnchor(obj=self)
|
|
404
|
+
self._jac_.__setstate__(state["_jac_"])
|
|
405
|
+
|
|
406
|
+
def populate_nodes(self) -> None:
|
|
407
|
+
"""Populate nodes for the edges from node ids."""
|
|
408
|
+
if self._jac_.source_id:
|
|
409
|
+
obj = Jac.context().get_obj(self._jac_.source_id)
|
|
410
|
+
if obj is None:
|
|
411
|
+
raise ValueError(f"Node with id {self._jac_.source_id} not found.")
|
|
412
|
+
elif not isinstance(obj, NodeArchitype):
|
|
413
|
+
raise ValueError(
|
|
414
|
+
f"Object with id {self._jac_.source_id} is not a node."
|
|
415
|
+
)
|
|
416
|
+
else:
|
|
417
|
+
self._jac_.source = obj
|
|
418
|
+
self._jac_.source_id = None
|
|
419
|
+
if self._jac_.target_id:
|
|
420
|
+
obj = Jac.context().get_obj(self._jac_.target_id)
|
|
421
|
+
if obj is None:
|
|
422
|
+
raise ValueError(f"Node with id {self._jac_.target_id} not found.")
|
|
423
|
+
elif not isinstance(obj, NodeArchitype):
|
|
424
|
+
raise ValueError(
|
|
425
|
+
f"Object with id {self._jac_.target_id} is not a node."
|
|
426
|
+
)
|
|
427
|
+
else:
|
|
428
|
+
self._jac_.target = obj
|
|
429
|
+
self._jac_.target_id = None
|
|
286
430
|
|
|
287
431
|
|
|
288
432
|
class WalkerArchitype(Architype):
|
|
289
433
|
"""Walker Architype Protocol."""
|
|
290
434
|
|
|
435
|
+
_jac_: WalkerAnchor
|
|
436
|
+
|
|
291
437
|
def __init__(self) -> None:
|
|
292
438
|
"""Create walker architype."""
|
|
293
439
|
self._jac_: WalkerAnchor = WalkerAnchor(obj=self)
|
|
@@ -301,6 +447,12 @@ class Root(NodeArchitype):
|
|
|
301
447
|
reachable_nodes: list[NodeArchitype] = []
|
|
302
448
|
connections: set[tuple[NodeArchitype, NodeArchitype, EdgeArchitype]] = set()
|
|
303
449
|
|
|
450
|
+
def __init__(self) -> None:
|
|
451
|
+
"""Create root node."""
|
|
452
|
+
super().__init__()
|
|
453
|
+
self._jac_.id = UUID(int=0)
|
|
454
|
+
self._jac_.persistent = True
|
|
455
|
+
|
|
304
456
|
def reset(self) -> None:
|
|
305
457
|
"""Reset the root."""
|
|
306
458
|
self.reachable_nodes = []
|
|
@@ -315,19 +467,6 @@ class GenericEdge(EdgeArchitype):
|
|
|
315
467
|
_jac_exit_funcs_ = []
|
|
316
468
|
|
|
317
469
|
|
|
318
|
-
@dataclass(eq=False)
|
|
319
|
-
class DSFunc:
|
|
320
|
-
"""Data Spatial Function."""
|
|
321
|
-
|
|
322
|
-
name: str
|
|
323
|
-
trigger: type | types.UnionType | tuple[type | types.UnionType, ...] | None
|
|
324
|
-
func: Callable[[Any, Any], Any] | None = None
|
|
325
|
-
|
|
326
|
-
def resolve(self, cls: type) -> None:
|
|
327
|
-
"""Resolve the function."""
|
|
328
|
-
self.func = getattr(cls, self.name)
|
|
329
|
-
|
|
330
|
-
|
|
331
470
|
class JacTestResult(unittest.TextTestResult):
|
|
332
471
|
"""Jac test result class."""
|
|
333
472
|
|
|
@@ -407,9 +546,6 @@ class JacTestCheck:
|
|
|
407
546
|
"""Create a new test."""
|
|
408
547
|
JacTestCheck.test_suite.addTest(unittest.FunctionTestCase(test_fun))
|
|
409
548
|
|
|
410
|
-
def __getattr__(self, name: str) ->
|
|
549
|
+
def __getattr__(self, name: str) -> object:
|
|
411
550
|
"""Make convenient check.Equal(...) etc."""
|
|
412
551
|
return getattr(JacTestCheck.test_case, name)
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
root = Root()
|
jaclang/core/importer.py
CHANGED
|
@@ -32,9 +32,13 @@ def jac_importer(
|
|
|
32
32
|
module_name = path.splitext(file_name)[0]
|
|
33
33
|
package_path = dir_path.replace(path.sep, ".")
|
|
34
34
|
|
|
35
|
-
if
|
|
35
|
+
if (
|
|
36
|
+
not override_name
|
|
37
|
+
and package_path
|
|
38
|
+
and f"{package_path}.{module_name}" in sys.modules
|
|
39
|
+
):
|
|
36
40
|
return sys.modules[f"{package_path}.{module_name}"]
|
|
37
|
-
elif not package_path and module_name in sys.modules:
|
|
41
|
+
elif not override_name and not package_path and module_name in sys.modules:
|
|
38
42
|
return sys.modules[module_name]
|
|
39
43
|
|
|
40
44
|
caller_dir = get_caller_dir(target, base_path, dir_path)
|
jaclang/core/memory.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Memory abstraction for jaseci plugin."""
|
|
2
|
+
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
from jaclang.core.construct import Architype
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Memory:
|
|
9
|
+
"""Memory module interface."""
|
|
10
|
+
|
|
11
|
+
mem: dict[UUID, Architype] = {}
|
|
12
|
+
save_obj_list: dict[UUID, Architype] = {}
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
"""init."""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
def get_obj(self, obj_id: UUID) -> Architype | None:
|
|
19
|
+
"""Get object from memory."""
|
|
20
|
+
return self.get_obj_from_store(obj_id)
|
|
21
|
+
|
|
22
|
+
def get_obj_from_store(self, obj_id: UUID) -> Architype | None:
|
|
23
|
+
"""Get object from the underlying store."""
|
|
24
|
+
ret = self.mem.get(obj_id)
|
|
25
|
+
return ret
|
|
26
|
+
|
|
27
|
+
def has_obj(self, obj_id: UUID) -> bool:
|
|
28
|
+
"""Check if the object exists."""
|
|
29
|
+
return self.has_obj_in_store(obj_id)
|
|
30
|
+
|
|
31
|
+
def has_obj_in_store(self, obj_id: UUID) -> bool:
|
|
32
|
+
"""Check if the object exists in the underlying store."""
|
|
33
|
+
return obj_id in self.mem
|
|
34
|
+
|
|
35
|
+
def save_obj(self, item: Architype, persistent: bool) -> None:
|
|
36
|
+
"""Save object."""
|
|
37
|
+
self.mem[item._jac_.id] = item
|
|
38
|
+
if persistent:
|
|
39
|
+
# TODO: check if it needs to be saved, i.e. dirty or not
|
|
40
|
+
self.save_obj_list[item._jac_.id] = item
|
|
41
|
+
|
|
42
|
+
def commit(self) -> None:
|
|
43
|
+
"""Commit changes to persistent storage, if applicable."""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
def close(self) -> None:
|
|
47
|
+
"""Close any connection, if applicable."""
|
|
48
|
+
self.mem.clear()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Shelve storage for persistence storage of jaclang runtime object."""
|
|
2
|
+
|
|
3
|
+
import shelve
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from jaclang.core.construct import Architype
|
|
7
|
+
from jaclang.core.memory import Memory
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ShelveStorage(Memory):
|
|
11
|
+
"""Shelve storage for jaclang runtime object."""
|
|
12
|
+
|
|
13
|
+
storage: shelve.Shelf | None = None
|
|
14
|
+
|
|
15
|
+
def __init__(self, session: str = "") -> None:
|
|
16
|
+
"""Init shelve storage."""
|
|
17
|
+
super().__init__()
|
|
18
|
+
if session:
|
|
19
|
+
self.connect(session)
|
|
20
|
+
|
|
21
|
+
def get_obj_from_store(self, obj_id: UUID) -> Architype | None:
|
|
22
|
+
"""Get object from the underlying store."""
|
|
23
|
+
obj = super().get_obj_from_store(obj_id)
|
|
24
|
+
if obj is None and self.storage:
|
|
25
|
+
obj = self.storage.get(str(obj_id))
|
|
26
|
+
if obj is not None:
|
|
27
|
+
self.mem[obj_id] = obj
|
|
28
|
+
|
|
29
|
+
return obj
|
|
30
|
+
|
|
31
|
+
def has_obj_in_store(self, obj_id: UUID | str) -> bool:
|
|
32
|
+
"""Check if the object exists in the underlying store."""
|
|
33
|
+
return obj_id in self.mem or (
|
|
34
|
+
str(obj_id) in self.storage if self.storage else False
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def commit(self) -> None:
|
|
38
|
+
"""Commit changes to persistent storage."""
|
|
39
|
+
if self.storage is not None:
|
|
40
|
+
for obj_id, obj in self.save_obj_list.items():
|
|
41
|
+
self.storage[str(obj_id)] = obj
|
|
42
|
+
self.save_obj_list.clear()
|
|
43
|
+
|
|
44
|
+
def connect(self, session: str) -> None:
|
|
45
|
+
"""Connect to storage."""
|
|
46
|
+
self.session = session
|
|
47
|
+
self.storage = shelve.open(session)
|
|
48
|
+
|
|
49
|
+
def close(self) -> None:
|
|
50
|
+
"""Close the storage."""
|
|
51
|
+
super().close()
|
|
52
|
+
self.commit()
|
|
53
|
+
if self.storage:
|
|
54
|
+
self.storage.close()
|
|
55
|
+
self.storage = None
|
jaclang/plugin/__init__.py
CHANGED
jaclang/plugin/builtin.py
CHANGED
|
@@ -20,9 +20,9 @@ def dotgen(
|
|
|
20
20
|
dot_file: Optional[str] = None,
|
|
21
21
|
) -> str:
|
|
22
22
|
"""Print the dot graph."""
|
|
23
|
-
from jaclang.core.construct import root
|
|
24
23
|
from jaclang.plugin.feature import pm
|
|
25
24
|
|
|
25
|
+
root = pm.hook.get_root()
|
|
26
26
|
node = node if node is not None else root
|
|
27
27
|
depth = depth if depth is not None else -1
|
|
28
28
|
traverse = traverse if traverse is not None else False
|
jaclang/plugin/default.py
CHANGED
|
@@ -7,9 +7,11 @@ import html
|
|
|
7
7
|
import os
|
|
8
8
|
import pickle
|
|
9
9
|
import types
|
|
10
|
+
from contextvars import ContextVar
|
|
10
11
|
from dataclasses import field
|
|
11
12
|
from functools import wraps
|
|
12
13
|
from typing import Any, Callable, Optional, Type, Union
|
|
14
|
+
from uuid import UUID
|
|
13
15
|
|
|
14
16
|
from jaclang.compiler.absyntree import Module
|
|
15
17
|
from jaclang.compiler.constant import EdgeDir, colors
|
|
@@ -34,10 +36,11 @@ from jaclang.core.construct import (
|
|
|
34
36
|
Root,
|
|
35
37
|
WalkerAnchor,
|
|
36
38
|
WalkerArchitype,
|
|
37
|
-
root,
|
|
38
39
|
)
|
|
39
40
|
from jaclang.core.importer import jac_importer
|
|
41
|
+
from jaclang.core.memory import Memory
|
|
40
42
|
from jaclang.core.registry import SemInfo, SemRegistry, SemScope
|
|
43
|
+
from jaclang.core.shelve_storage import ShelveStorage
|
|
41
44
|
from jaclang.core.utils import traverse_graph
|
|
42
45
|
from jaclang.plugin.feature import JacFeature as Jac
|
|
43
46
|
from jaclang.plugin.spec import T
|
|
@@ -55,11 +58,10 @@ __all__ = [
|
|
|
55
58
|
"WalkerAnchor",
|
|
56
59
|
"NodeArchitype",
|
|
57
60
|
"EdgeArchitype",
|
|
61
|
+
"Root",
|
|
58
62
|
"WalkerArchitype",
|
|
59
63
|
"Architype",
|
|
60
64
|
"DSFunc",
|
|
61
|
-
"root",
|
|
62
|
-
"Root",
|
|
63
65
|
"jac_importer",
|
|
64
66
|
"T",
|
|
65
67
|
]
|
|
@@ -68,11 +70,95 @@ __all__ = [
|
|
|
68
70
|
hookimpl = pluggy.HookimplMarker("jac")
|
|
69
71
|
|
|
70
72
|
|
|
73
|
+
class ExecutionContext:
|
|
74
|
+
"""Default Execution Context implementation."""
|
|
75
|
+
|
|
76
|
+
mem: Optional[Memory]
|
|
77
|
+
root: Optional[Root]
|
|
78
|
+
|
|
79
|
+
def __init__(self) -> None:
|
|
80
|
+
super().__init__()
|
|
81
|
+
self.mem = ShelveStorage()
|
|
82
|
+
self.root = None
|
|
83
|
+
|
|
84
|
+
def init_memory(self, session: str = "") -> None:
|
|
85
|
+
if session:
|
|
86
|
+
self.mem = ShelveStorage(session)
|
|
87
|
+
else:
|
|
88
|
+
self.mem = Memory()
|
|
89
|
+
|
|
90
|
+
def get_root(self) -> Root:
|
|
91
|
+
if self.mem is None:
|
|
92
|
+
raise ValueError("Memory not initialized")
|
|
93
|
+
|
|
94
|
+
if not self.root:
|
|
95
|
+
root = self.mem.get_obj(UUID(int=0))
|
|
96
|
+
if root is None:
|
|
97
|
+
self.root = Root()
|
|
98
|
+
self.mem.save_obj(self.root, persistent=self.root._jac_.persistent)
|
|
99
|
+
elif not isinstance(root, Root):
|
|
100
|
+
raise ValueError(f"Invalid root object: {root}")
|
|
101
|
+
else:
|
|
102
|
+
self.root = root
|
|
103
|
+
return self.root
|
|
104
|
+
|
|
105
|
+
def get_obj(self, obj_id: UUID) -> Architype | None:
|
|
106
|
+
"""Get object from memory."""
|
|
107
|
+
if self.mem is None:
|
|
108
|
+
raise ValueError("Memory not initialized")
|
|
109
|
+
|
|
110
|
+
return self.mem.get_obj(obj_id)
|
|
111
|
+
|
|
112
|
+
def save_obj(self, item: Architype, persistent: bool) -> None:
|
|
113
|
+
"""Save object to memory."""
|
|
114
|
+
if self.mem is None:
|
|
115
|
+
raise ValueError("Memory not initialized")
|
|
116
|
+
|
|
117
|
+
self.mem.save_obj(item, persistent)
|
|
118
|
+
|
|
119
|
+
def reset(self) -> None:
|
|
120
|
+
"""Reset the execution context."""
|
|
121
|
+
if self.mem:
|
|
122
|
+
self.mem.close()
|
|
123
|
+
self.mem = None
|
|
124
|
+
self.root = None
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
ExecContext: ContextVar[ExecutionContext | None] = ContextVar(
|
|
128
|
+
"ExecutionContext", default=None
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
71
132
|
class JacFeatureDefaults:
|
|
72
133
|
"""Jac Feature."""
|
|
73
134
|
|
|
74
135
|
pm = pluggy.PluginManager("jac")
|
|
75
136
|
|
|
137
|
+
@staticmethod
|
|
138
|
+
@hookimpl
|
|
139
|
+
def context(session: str = "") -> ExecutionContext:
|
|
140
|
+
"""Get the execution context."""
|
|
141
|
+
ctx = ExecContext.get()
|
|
142
|
+
if ctx is None:
|
|
143
|
+
ctx = ExecutionContext()
|
|
144
|
+
ExecContext.set(ctx)
|
|
145
|
+
return ctx
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
@hookimpl
|
|
149
|
+
def reset_context() -> None:
|
|
150
|
+
"""Reset the execution context."""
|
|
151
|
+
ctx = ExecContext.get()
|
|
152
|
+
if ctx:
|
|
153
|
+
ctx.reset()
|
|
154
|
+
ExecContext.set(None)
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
@hookimpl
|
|
158
|
+
def memory_hook() -> Memory | None:
|
|
159
|
+
"""Return the memory hook."""
|
|
160
|
+
return Jac.context().mem
|
|
161
|
+
|
|
76
162
|
@staticmethod
|
|
77
163
|
@hookimpl
|
|
78
164
|
def make_architype(
|
|
@@ -377,6 +463,12 @@ class JacFeatureDefaults:
|
|
|
377
463
|
conn_edge = edge_spec()
|
|
378
464
|
edges.append(conn_edge)
|
|
379
465
|
i._jac_.connect_node(j, conn_edge)
|
|
466
|
+
|
|
467
|
+
if i._jac_.persistent or j._jac_.persistent:
|
|
468
|
+
conn_edge.save()
|
|
469
|
+
j.save()
|
|
470
|
+
i.save()
|
|
471
|
+
|
|
380
472
|
return right if not edges_only else edges
|
|
381
473
|
|
|
382
474
|
@staticmethod
|
|
@@ -429,7 +521,7 @@ class JacFeatureDefaults:
|
|
|
429
521
|
@hookimpl
|
|
430
522
|
def get_root() -> Root:
|
|
431
523
|
"""Jac's assign comprehension feature."""
|
|
432
|
-
return
|
|
524
|
+
return Jac.context().get_root()
|
|
433
525
|
|
|
434
526
|
@staticmethod
|
|
435
527
|
@hookimpl
|
|
@@ -603,6 +695,7 @@ class JacFeatureDefaults:
|
|
|
603
695
|
)
|
|
604
696
|
|
|
605
697
|
type_collector: list = []
|
|
698
|
+
incl_info = [x for x in incl_info if not isinstance(x[1], type)]
|
|
606
699
|
information, collected_types = get_info_types(_scope, mod_registry, incl_info)
|
|
607
700
|
type_collector.extend(collected_types)
|
|
608
701
|
inputs_information_list = []
|
jaclang/plugin/feature.py
CHANGED
|
@@ -3,18 +3,22 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import types
|
|
6
|
-
from typing import Any, Callable, Optional, Type, Union
|
|
6
|
+
from typing import Any, Callable, Optional, TYPE_CHECKING, Type, Union
|
|
7
7
|
|
|
8
8
|
from jaclang.compiler.absyntree import Module
|
|
9
|
-
from jaclang.core.construct import (
|
|
10
|
-
Architype,
|
|
11
|
-
EdgeArchitype,
|
|
12
|
-
NodeArchitype,
|
|
13
|
-
Root,
|
|
14
|
-
WalkerArchitype,
|
|
15
|
-
)
|
|
16
9
|
from jaclang.plugin.spec import JacBuiltin, JacCmdSpec, JacFeatureSpec, T
|
|
17
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from jaclang.core.construct import (
|
|
13
|
+
Architype,
|
|
14
|
+
EdgeArchitype,
|
|
15
|
+
NodeArchitype,
|
|
16
|
+
WalkerArchitype,
|
|
17
|
+
Root,
|
|
18
|
+
)
|
|
19
|
+
from jaclang.plugin.default import ExecutionContext
|
|
20
|
+
from jaclang.core.memory import Memory
|
|
21
|
+
|
|
18
22
|
|
|
19
23
|
import pluggy
|
|
20
24
|
|
|
@@ -28,8 +32,23 @@ class JacFeature:
|
|
|
28
32
|
"""Jac Feature."""
|
|
29
33
|
|
|
30
34
|
import abc
|
|
31
|
-
from jaclang.plugin.spec import DSFunc
|
|
32
35
|
from jaclang.compiler.constant import EdgeDir
|
|
36
|
+
from jaclang.plugin.spec import DSFunc
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def context(session: str = "") -> ExecutionContext:
|
|
40
|
+
"""Create execution context."""
|
|
41
|
+
return pm.hook.context(session=session)
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def reset_context() -> None:
|
|
45
|
+
"""Reset execution context."""
|
|
46
|
+
return pm.hook.reset_context()
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def memory_hook() -> Memory | None:
|
|
50
|
+
"""Create memory abstraction."""
|
|
51
|
+
return pm.hook.memory_hook()
|
|
33
52
|
|
|
34
53
|
@staticmethod
|
|
35
54
|
def make_architype(
|