jaclang 0.8.1__py3-none-any.whl → 0.8.3__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/__init__.py +6 -0
- jaclang/cli/cli.py +21 -50
- jaclang/compiler/codeinfo.py +0 -1
- jaclang/compiler/constant.py +2 -0
- jaclang/compiler/jac.lark +17 -10
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +34 -10
- jaclang/compiler/passes/main/__init__.py +2 -14
- jaclang/compiler/passes/main/annex_pass.py +2 -8
- jaclang/compiler/passes/main/cfg_build_pass.py +38 -12
- jaclang/compiler/passes/main/import_pass.py +3 -11
- jaclang/compiler/passes/main/pyast_gen_pass.py +246 -592
- jaclang/compiler/passes/main/sem_def_match_pass.py +67 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +8 -0
- jaclang/compiler/passes/main/sym_tab_link_pass.py +2 -5
- jaclang/compiler/passes/main/tests/fixtures/sem_def_match.impl.jac +12 -0
- jaclang/compiler/passes/main/tests/fixtures/sem_def_match.jac +31 -0
- jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +2 -8
- jaclang/compiler/passes/main/tests/test_decl_impl_match_pass.py +7 -8
- jaclang/compiler/passes/main/tests/test_import_pass.py +5 -18
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -6
- jaclang/compiler/passes/main/tests/test_sem_def_match_pass.py +38 -0
- jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -3
- jaclang/compiler/passes/main/tests/test_sym_tab_link_pass.py +20 -17
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +259 -106
- jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -0
- jaclang/compiler/passes/tool/tests/fixtures/archetype_frmt.jac +14 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +5 -4
- jaclang/compiler/passes/tool/tests/fixtures/has_frmt.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +6 -0
- jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +3 -3
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +9 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +25 -3
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +2 -2
- jaclang/compiler/program.py +23 -60
- jaclang/compiler/tests/fixtures/pkg_import_lib_py/__init__.py +2 -8
- jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/__init__.py +1 -5
- jaclang/compiler/tests/test_importer.py +10 -13
- jaclang/compiler/unitree.py +88 -16
- jaclang/langserve/__init__.jac +1 -1
- jaclang/langserve/engine.jac +113 -108
- jaclang/langserve/server.jac +17 -2
- jaclang/langserve/tests/server_test/test_lang_serve.py +138 -46
- jaclang/langserve/tests/server_test/utils.py +35 -9
- jaclang/langserve/tests/test_sem_tokens.py +1 -1
- jaclang/langserve/tests/test_server.py +3 -7
- jaclang/runtimelib/archetype.py +127 -5
- jaclang/runtimelib/importer.py +51 -94
- jaclang/runtimelib/machine.py +391 -268
- jaclang/runtimelib/meta_importer.py +86 -0
- jaclang/runtimelib/tests/fixtures/graph_purger.jac +24 -26
- jaclang/runtimelib/tests/fixtures/other_root_access.jac +25 -16
- jaclang/runtimelib/tests/test_jaseci.py +3 -1
- jaclang/tests/fixtures/arch_rel_import_creation.jac +23 -23
- jaclang/tests/fixtures/async_ability.jac +43 -10
- jaclang/tests/fixtures/async_function.jac +18 -0
- jaclang/tests/fixtures/async_walker.jac +17 -12
- jaclang/tests/fixtures/create_dynamic_archetype.jac +25 -28
- jaclang/tests/fixtures/deep/deeper/deep_outer_import.jac +7 -4
- jaclang/tests/fixtures/deep/deeper/snd_lev.jac +2 -2
- jaclang/tests/fixtures/deep/deeper/snd_lev_dup.jac +6 -0
- jaclang/tests/fixtures/deep/one_lev.jac +2 -2
- jaclang/tests/fixtures/deep/one_lev_dup.jac +4 -3
- jaclang/tests/fixtures/dynamic_archetype.jac +19 -12
- jaclang/tests/fixtures/foo.jac +14 -22
- jaclang/tests/fixtures/jac_from_py.py +1 -1
- jaclang/tests/fixtures/jp_importer.jac +6 -6
- jaclang/tests/fixtures/jp_importer_auto.jac +5 -3
- jaclang/tests/fixtures/unicode_strings.jac +24 -0
- jaclang/tests/fixtures/walker_update.jac +5 -7
- jaclang/tests/test_language.py +138 -140
- jaclang/tests/test_reference.py +9 -4
- jaclang/tests/test_typecheck.py +13 -26
- jaclang/utils/lang_tools.py +7 -5
- jaclang/utils/module_resolver.py +23 -0
- {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/METADATA +1 -1
- {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/RECORD +79 -72
- jaclang/compiler/passes/main/tests/fixtures/main_err.jac +0 -6
- jaclang/compiler/passes/main/tests/fixtures/second_err.jac +0 -4
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +0 -644
- jaclang/compiler/passes/tool/tests/test_doc_ir_gen_pass.py +0 -29
- jaclang/tests/fixtures/deep/deeper/__init__.jac +0 -1
- {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/WHEEL +0 -0
- {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/entry_points.txt +0 -0
jaclang/runtimelib/machine.py
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import ast as ast3
|
|
6
|
-
import asyncio
|
|
7
6
|
import fnmatch
|
|
8
7
|
import html
|
|
9
8
|
import inspect
|
|
@@ -14,12 +13,13 @@ import types
|
|
|
14
13
|
from collections import OrderedDict
|
|
15
14
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
16
15
|
from dataclasses import MISSING, dataclass, field
|
|
17
|
-
from functools import
|
|
16
|
+
from functools import wraps
|
|
18
17
|
from inspect import getfile
|
|
19
18
|
from logging import getLogger
|
|
20
19
|
from typing import (
|
|
21
20
|
Any,
|
|
22
21
|
Callable,
|
|
22
|
+
Coroutine,
|
|
23
23
|
Mapping,
|
|
24
24
|
Optional,
|
|
25
25
|
ParamSpec,
|
|
@@ -39,7 +39,9 @@ from jaclang.compiler.constant import Constants as Con, EdgeDir, colors
|
|
|
39
39
|
from jaclang.compiler.passes.main.pyast_gen_pass import PyastGenPass
|
|
40
40
|
from jaclang.compiler.program import JacProgram
|
|
41
41
|
from jaclang.runtimelib.archetype import (
|
|
42
|
+
DataSpatialDestination,
|
|
42
43
|
DataSpatialFunction,
|
|
44
|
+
DataSpatialPath,
|
|
43
45
|
GenericEdge as _GenericEdge,
|
|
44
46
|
Root as _Root,
|
|
45
47
|
)
|
|
@@ -77,6 +79,64 @@ T = TypeVar("T")
|
|
|
77
79
|
P = ParamSpec("P")
|
|
78
80
|
|
|
79
81
|
|
|
82
|
+
class ExecutionContext:
|
|
83
|
+
"""Execution Context."""
|
|
84
|
+
|
|
85
|
+
def __init__(
|
|
86
|
+
self,
|
|
87
|
+
session: Optional[str] = None,
|
|
88
|
+
root: Optional[str] = None,
|
|
89
|
+
) -> None:
|
|
90
|
+
"""Initialize JacMachine."""
|
|
91
|
+
self.mem: Memory = ShelfStorage(session)
|
|
92
|
+
self.reports: list[Any] = []
|
|
93
|
+
sr_arch = Root()
|
|
94
|
+
sr_anch = sr_arch.__jac__
|
|
95
|
+
sr_anch.id = UUID(Con.SUPER_ROOT_UUID)
|
|
96
|
+
sr_anch.persistent = False
|
|
97
|
+
self.system_root = sr_anch
|
|
98
|
+
self.custom: Any = MISSING
|
|
99
|
+
if not isinstance(
|
|
100
|
+
system_root := self.mem.find_by_id(UUID(Con.SUPER_ROOT_UUID)), NodeAnchor
|
|
101
|
+
):
|
|
102
|
+
system_root = cast(NodeAnchor, Root().__jac__) # type: ignore[attr-defined]
|
|
103
|
+
system_root.id = UUID(Con.SUPER_ROOT_UUID)
|
|
104
|
+
self.mem.set(system_root.id, system_root)
|
|
105
|
+
|
|
106
|
+
self.system_root = system_root
|
|
107
|
+
|
|
108
|
+
self.entry_node = self.root_state = self.init_anchor(root, self.system_root)
|
|
109
|
+
|
|
110
|
+
def init_anchor(
|
|
111
|
+
self,
|
|
112
|
+
anchor_id: str | None,
|
|
113
|
+
default: NodeAnchor,
|
|
114
|
+
) -> NodeAnchor:
|
|
115
|
+
"""Load initial anchors."""
|
|
116
|
+
if anchor_id:
|
|
117
|
+
if isinstance(anchor := self.mem.find_by_id(UUID(anchor_id)), NodeAnchor):
|
|
118
|
+
return anchor
|
|
119
|
+
raise ValueError(f"Invalid anchor id {anchor_id} !")
|
|
120
|
+
return default
|
|
121
|
+
|
|
122
|
+
def set_entry_node(self, entry_node: str | None) -> None:
|
|
123
|
+
"""Override entry."""
|
|
124
|
+
self.entry_node = self.init_anchor(entry_node, self.root_state)
|
|
125
|
+
|
|
126
|
+
def close(self) -> None:
|
|
127
|
+
"""Close current ExecutionContext."""
|
|
128
|
+
self.mem.close()
|
|
129
|
+
JacMachine.reset_machine()
|
|
130
|
+
|
|
131
|
+
def get_root(self) -> Root:
|
|
132
|
+
"""Get current root."""
|
|
133
|
+
return cast(Root, self.root_state.archetype)
|
|
134
|
+
|
|
135
|
+
def global_system_root(self) -> NodeAnchor:
|
|
136
|
+
"""Get global system root."""
|
|
137
|
+
return self.system_root
|
|
138
|
+
|
|
139
|
+
|
|
80
140
|
class JacAccessValidation:
|
|
81
141
|
"""Jac Access Validation Specs."""
|
|
82
142
|
|
|
@@ -233,69 +293,105 @@ class JacNode:
|
|
|
233
293
|
|
|
234
294
|
@staticmethod
|
|
235
295
|
def get_edges(
|
|
236
|
-
|
|
237
|
-
dir: EdgeDir,
|
|
238
|
-
filter: Callable[[EdgeArchetype], bool] | None,
|
|
239
|
-
target_obj: list[NodeArchetype] | None,
|
|
296
|
+
origin: list[NodeArchetype], destination: DataSpatialDestination
|
|
240
297
|
) -> list[EdgeArchetype]:
|
|
241
298
|
"""Get edges connected to this node."""
|
|
242
|
-
|
|
243
|
-
for
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
and (target := anchor.target)
|
|
247
|
-
and (not filter or filter(anchor.archetype))
|
|
248
|
-
and source.archetype
|
|
249
|
-
and target.archetype
|
|
250
|
-
):
|
|
299
|
+
edges: OrderedDict[EdgeAnchor, EdgeArchetype] = OrderedDict()
|
|
300
|
+
for node in origin:
|
|
301
|
+
nanch = node.__jac__
|
|
302
|
+
for anchor in nanch.edges:
|
|
251
303
|
if (
|
|
252
|
-
|
|
253
|
-
and
|
|
254
|
-
and (
|
|
255
|
-
and
|
|
304
|
+
(source := anchor.source)
|
|
305
|
+
and (target := anchor.target)
|
|
306
|
+
and destination.edge_filter(anchor.archetype)
|
|
307
|
+
and source.archetype
|
|
308
|
+
and target.archetype
|
|
256
309
|
):
|
|
257
|
-
|
|
310
|
+
if (
|
|
311
|
+
destination.direction in [EdgeDir.OUT, EdgeDir.ANY]
|
|
312
|
+
and nanch == source
|
|
313
|
+
and destination.node_filter(target.archetype)
|
|
314
|
+
and JacMachineInterface.check_read_access(target)
|
|
315
|
+
):
|
|
316
|
+
edges[anchor] = anchor.archetype
|
|
317
|
+
if (
|
|
318
|
+
destination.direction in [EdgeDir.IN, EdgeDir.ANY]
|
|
319
|
+
and nanch == target
|
|
320
|
+
and destination.node_filter(source.archetype)
|
|
321
|
+
and JacMachineInterface.check_read_access(source)
|
|
322
|
+
):
|
|
323
|
+
edges[anchor] = anchor.archetype
|
|
324
|
+
return list(edges.values())
|
|
325
|
+
|
|
326
|
+
@staticmethod
|
|
327
|
+
def get_edges_with_node(
|
|
328
|
+
origin: list[NodeArchetype],
|
|
329
|
+
destination: DataSpatialDestination,
|
|
330
|
+
from_visit: bool = False,
|
|
331
|
+
) -> list[EdgeArchetype | NodeArchetype]:
|
|
332
|
+
"""Get edges connected to this node and the node."""
|
|
333
|
+
loc: OrderedDict[
|
|
334
|
+
Union[NodeAnchor, EdgeAnchor], Union[NodeArchetype, EdgeArchetype]
|
|
335
|
+
] = OrderedDict()
|
|
336
|
+
for node in origin:
|
|
337
|
+
nanch = node.__jac__
|
|
338
|
+
for anchor in nanch.edges:
|
|
258
339
|
if (
|
|
259
|
-
|
|
260
|
-
and
|
|
261
|
-
and (
|
|
262
|
-
and
|
|
340
|
+
(source := anchor.source)
|
|
341
|
+
and (target := anchor.target)
|
|
342
|
+
and destination.edge_filter(anchor.archetype)
|
|
343
|
+
and source.archetype
|
|
344
|
+
and target.archetype
|
|
263
345
|
):
|
|
264
|
-
|
|
265
|
-
|
|
346
|
+
if (
|
|
347
|
+
destination.direction in [EdgeDir.OUT, EdgeDir.ANY]
|
|
348
|
+
and nanch == source
|
|
349
|
+
and destination.node_filter(target.archetype)
|
|
350
|
+
and JacMachineInterface.check_read_access(target)
|
|
351
|
+
):
|
|
352
|
+
loc[anchor] = anchor.archetype
|
|
353
|
+
loc[target] = target.archetype
|
|
354
|
+
if (
|
|
355
|
+
destination.direction in [EdgeDir.IN, EdgeDir.ANY]
|
|
356
|
+
and nanch == target
|
|
357
|
+
and destination.node_filter(source.archetype)
|
|
358
|
+
and JacMachineInterface.check_read_access(source)
|
|
359
|
+
):
|
|
360
|
+
loc[anchor] = anchor.archetype
|
|
361
|
+
loc[source] = source.archetype
|
|
362
|
+
return list(loc.values())
|
|
266
363
|
|
|
267
364
|
@staticmethod
|
|
268
365
|
def edges_to_nodes(
|
|
269
|
-
|
|
270
|
-
dir: EdgeDir,
|
|
271
|
-
filter: Callable[[EdgeArchetype], bool] | None,
|
|
272
|
-
target_obj: list[NodeArchetype] | None,
|
|
366
|
+
origin: list[NodeArchetype], destination: DataSpatialDestination
|
|
273
367
|
) -> list[NodeArchetype]:
|
|
274
368
|
"""Get set of nodes connected to this node."""
|
|
275
|
-
|
|
276
|
-
for
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
and (target := anchor.target)
|
|
280
|
-
and (not filter or filter(anchor.archetype))
|
|
281
|
-
and source.archetype
|
|
282
|
-
and target.archetype
|
|
283
|
-
):
|
|
369
|
+
nodes: OrderedDict[NodeAnchor, NodeArchetype] = OrderedDict()
|
|
370
|
+
for node in origin:
|
|
371
|
+
nanch = node.__jac__
|
|
372
|
+
for anchor in nanch.edges:
|
|
284
373
|
if (
|
|
285
|
-
|
|
286
|
-
and
|
|
287
|
-
and (
|
|
288
|
-
and
|
|
289
|
-
|
|
290
|
-
ret_edges.append(target.archetype)
|
|
291
|
-
if (
|
|
292
|
-
dir in [EdgeDir.IN, EdgeDir.ANY]
|
|
293
|
-
and node == target
|
|
294
|
-
and (not target_obj or source.archetype in target_obj)
|
|
295
|
-
and JacMachineInterface.check_read_access(source)
|
|
374
|
+
(source := anchor.source)
|
|
375
|
+
and (target := anchor.target)
|
|
376
|
+
and destination.edge_filter(anchor.archetype)
|
|
377
|
+
and source.archetype
|
|
378
|
+
and target.archetype
|
|
296
379
|
):
|
|
297
|
-
|
|
298
|
-
|
|
380
|
+
if (
|
|
381
|
+
destination.direction in [EdgeDir.OUT, EdgeDir.ANY]
|
|
382
|
+
and nanch == source
|
|
383
|
+
and destination.node_filter(target.archetype)
|
|
384
|
+
and JacMachineInterface.check_read_access(target)
|
|
385
|
+
):
|
|
386
|
+
nodes[target] = target.archetype
|
|
387
|
+
if (
|
|
388
|
+
destination.direction in [EdgeDir.IN, EdgeDir.ANY]
|
|
389
|
+
and nanch == target
|
|
390
|
+
and destination.node_filter(source.archetype)
|
|
391
|
+
and JacMachineInterface.check_read_access(source)
|
|
392
|
+
):
|
|
393
|
+
nodes[source] = source.archetype
|
|
394
|
+
return list(nodes.values())
|
|
299
395
|
|
|
300
396
|
@staticmethod
|
|
301
397
|
def remove_edge(node: NodeAnchor, edge: EdgeAnchor) -> None:
|
|
@@ -477,7 +573,115 @@ class JacWalker:
|
|
|
477
573
|
return warch
|
|
478
574
|
|
|
479
575
|
@staticmethod
|
|
480
|
-
def
|
|
576
|
+
async def async_spawn_call(
|
|
577
|
+
walker: WalkerAnchor,
|
|
578
|
+
node: NodeAnchor | EdgeAnchor,
|
|
579
|
+
) -> WalkerArchetype:
|
|
580
|
+
"""Jac's spawn operator feature."""
|
|
581
|
+
warch = walker.archetype
|
|
582
|
+
walker.path = []
|
|
583
|
+
current_loc = node.archetype
|
|
584
|
+
|
|
585
|
+
# walker ability on any entry
|
|
586
|
+
for i in warch._jac_entry_funcs_:
|
|
587
|
+
if not i.trigger:
|
|
588
|
+
result = i.func(warch, current_loc)
|
|
589
|
+
if isinstance(result, Coroutine):
|
|
590
|
+
await result
|
|
591
|
+
if walker.disengaged:
|
|
592
|
+
return warch
|
|
593
|
+
|
|
594
|
+
while len(walker.next):
|
|
595
|
+
if current_loc := walker.next.pop(0).archetype:
|
|
596
|
+
# walker ability with loc entry
|
|
597
|
+
for i in warch._jac_entry_funcs_:
|
|
598
|
+
if (
|
|
599
|
+
i.trigger
|
|
600
|
+
and (
|
|
601
|
+
all_issubclass(i.trigger, NodeArchetype)
|
|
602
|
+
or all_issubclass(i.trigger, EdgeArchetype)
|
|
603
|
+
)
|
|
604
|
+
and isinstance(current_loc, i.trigger)
|
|
605
|
+
):
|
|
606
|
+
result = i.func(warch, current_loc)
|
|
607
|
+
if isinstance(result, Coroutine):
|
|
608
|
+
await result
|
|
609
|
+
if walker.disengaged:
|
|
610
|
+
return warch
|
|
611
|
+
|
|
612
|
+
# loc ability with any entry
|
|
613
|
+
for i in current_loc._jac_entry_funcs_:
|
|
614
|
+
if not i.trigger:
|
|
615
|
+
result = i.func(current_loc, warch)
|
|
616
|
+
if isinstance(result, Coroutine):
|
|
617
|
+
await result
|
|
618
|
+
if walker.disengaged:
|
|
619
|
+
return warch
|
|
620
|
+
|
|
621
|
+
# loc ability with walker entry
|
|
622
|
+
for i in current_loc._jac_entry_funcs_:
|
|
623
|
+
if (
|
|
624
|
+
i.trigger
|
|
625
|
+
and all_issubclass(i.trigger, WalkerArchetype)
|
|
626
|
+
and isinstance(warch, i.trigger)
|
|
627
|
+
):
|
|
628
|
+
result = i.func(current_loc, warch)
|
|
629
|
+
if isinstance(result, Coroutine):
|
|
630
|
+
await result
|
|
631
|
+
if walker.disengaged:
|
|
632
|
+
return warch
|
|
633
|
+
|
|
634
|
+
# loc ability with walker exit
|
|
635
|
+
for i in current_loc._jac_exit_funcs_:
|
|
636
|
+
if (
|
|
637
|
+
i.trigger
|
|
638
|
+
and all_issubclass(i.trigger, WalkerArchetype)
|
|
639
|
+
and isinstance(warch, i.trigger)
|
|
640
|
+
):
|
|
641
|
+
result = i.func(current_loc, warch)
|
|
642
|
+
if isinstance(result, Coroutine):
|
|
643
|
+
await result
|
|
644
|
+
if walker.disengaged:
|
|
645
|
+
return warch
|
|
646
|
+
|
|
647
|
+
# loc ability with any exit
|
|
648
|
+
for i in current_loc._jac_exit_funcs_:
|
|
649
|
+
if not i.trigger:
|
|
650
|
+
result = i.func(current_loc, warch)
|
|
651
|
+
if isinstance(result, Coroutine):
|
|
652
|
+
await result
|
|
653
|
+
if walker.disengaged:
|
|
654
|
+
return warch
|
|
655
|
+
|
|
656
|
+
# walker ability with loc exit
|
|
657
|
+
for i in warch._jac_exit_funcs_:
|
|
658
|
+
if (
|
|
659
|
+
i.trigger
|
|
660
|
+
and (
|
|
661
|
+
all_issubclass(i.trigger, NodeArchetype)
|
|
662
|
+
or all_issubclass(i.trigger, EdgeArchetype)
|
|
663
|
+
)
|
|
664
|
+
and isinstance(current_loc, i.trigger)
|
|
665
|
+
):
|
|
666
|
+
result = i.func(warch, current_loc)
|
|
667
|
+
if isinstance(result, Coroutine):
|
|
668
|
+
await result
|
|
669
|
+
if walker.disengaged:
|
|
670
|
+
return warch
|
|
671
|
+
# walker ability with any exit
|
|
672
|
+
for i in warch._jac_exit_funcs_:
|
|
673
|
+
if not i.trigger:
|
|
674
|
+
result = i.func(warch, current_loc)
|
|
675
|
+
if isinstance(result, Coroutine):
|
|
676
|
+
await result
|
|
677
|
+
if walker.disengaged:
|
|
678
|
+
return warch
|
|
679
|
+
|
|
680
|
+
walker.ignores = []
|
|
681
|
+
return warch
|
|
682
|
+
|
|
683
|
+
@staticmethod
|
|
684
|
+
def spawn(op1: Archetype, op2: Archetype) -> WalkerArchetype | Coroutine:
|
|
481
685
|
"""Jac's spawn operator feature."""
|
|
482
686
|
edge: EdgeAnchor | None = None
|
|
483
687
|
if isinstance(op1, WalkerArchetype):
|
|
@@ -511,12 +715,7 @@ class JacWalker:
|
|
|
511
715
|
walker.next = [node]
|
|
512
716
|
|
|
513
717
|
if warch.__jac_async__:
|
|
514
|
-
|
|
515
|
-
_event_loop = machine._event_loop
|
|
516
|
-
func = partial(JacMachineInterface.spawn_call, *(walker, loc))
|
|
517
|
-
return asyncio.ensure_future(
|
|
518
|
-
_event_loop.run_in_executor(None, func), loop=_event_loop
|
|
519
|
-
)
|
|
718
|
+
return JacMachineInterface.async_spawn_call(walker=walker, node=loc)
|
|
520
719
|
else:
|
|
521
720
|
return JacMachineInterface.spawn_call(walker=walker, node=loc)
|
|
522
721
|
|
|
@@ -542,6 +741,8 @@ class JacClassReferences:
|
|
|
542
741
|
Root: TypeAlias = _Root
|
|
543
742
|
GenericEdge: TypeAlias = _GenericEdge
|
|
544
743
|
|
|
744
|
+
Path: TypeAlias = DataSpatialPath
|
|
745
|
+
|
|
545
746
|
|
|
546
747
|
class JacBuiltin:
|
|
547
748
|
"""Jac Builtins."""
|
|
@@ -656,9 +857,9 @@ class JacBasics:
|
|
|
656
857
|
"""Set Class References."""
|
|
657
858
|
|
|
658
859
|
@staticmethod
|
|
659
|
-
def get_context() ->
|
|
860
|
+
def get_context() -> ExecutionContext:
|
|
660
861
|
"""Get current execution context."""
|
|
661
|
-
return
|
|
862
|
+
return JacMachine.exec_ctx
|
|
662
863
|
|
|
663
864
|
@staticmethod
|
|
664
865
|
def reset_graph(root: Optional[Root] = None) -> int:
|
|
@@ -759,54 +960,8 @@ class JacBasics:
|
|
|
759
960
|
|
|
760
961
|
return decorator
|
|
761
962
|
|
|
762
|
-
@staticmethod
|
|
763
|
-
def py_get_jac_machine() -> JacMachine:
|
|
764
|
-
"""Get jac machine from python context."""
|
|
765
|
-
machine = JacBasics.py_find_jac_machine()
|
|
766
|
-
if not machine:
|
|
767
|
-
raise RuntimeError("Jac machine not found in python context. ")
|
|
768
|
-
return machine
|
|
769
|
-
|
|
770
|
-
@staticmethod
|
|
771
|
-
def py_find_jac_machine() -> Optional[JacMachine]:
|
|
772
|
-
"""Get jac machine from python context."""
|
|
773
|
-
machine = None
|
|
774
|
-
for i in inspect.stack():
|
|
775
|
-
machine = i.frame.f_globals.get("__jac_mach__") or i.frame.f_locals.get(
|
|
776
|
-
"__jac_mach__"
|
|
777
|
-
)
|
|
778
|
-
if machine:
|
|
779
|
-
break
|
|
780
|
-
return machine
|
|
781
|
-
|
|
782
|
-
@staticmethod
|
|
783
|
-
def py_jac_import(
|
|
784
|
-
target: str,
|
|
785
|
-
base_path: str,
|
|
786
|
-
absorb: bool = False,
|
|
787
|
-
mdl_alias: Optional[str] = None,
|
|
788
|
-
override_name: Optional[str] = None,
|
|
789
|
-
items: Optional[dict[str, Union[str, Optional[str]]]] = None,
|
|
790
|
-
reload_module: Optional[bool] = False,
|
|
791
|
-
) -> tuple[types.ModuleType, ...]:
|
|
792
|
-
"""Core Import Process."""
|
|
793
|
-
machine = JacBasics.py_find_jac_machine()
|
|
794
|
-
if not machine:
|
|
795
|
-
machine = JacMachine(base_path=base_path)
|
|
796
|
-
return JacMachineInterface.jac_import(
|
|
797
|
-
mach=machine,
|
|
798
|
-
target=target,
|
|
799
|
-
base_path=base_path,
|
|
800
|
-
absorb=absorb,
|
|
801
|
-
mdl_alias=mdl_alias,
|
|
802
|
-
override_name=override_name,
|
|
803
|
-
items=items,
|
|
804
|
-
reload_module=reload_module,
|
|
805
|
-
)
|
|
806
|
-
|
|
807
963
|
@staticmethod
|
|
808
964
|
def jac_import(
|
|
809
|
-
mach: JacMachine,
|
|
810
965
|
target: str,
|
|
811
966
|
base_path: str,
|
|
812
967
|
absorb: bool = False,
|
|
@@ -834,13 +989,13 @@ class JacBasics:
|
|
|
834
989
|
items,
|
|
835
990
|
)
|
|
836
991
|
|
|
837
|
-
if not
|
|
838
|
-
JacMachineInterface.attach_program(
|
|
992
|
+
if not JacMachine.program:
|
|
993
|
+
JacMachineInterface.attach_program(JacProgram())
|
|
839
994
|
|
|
840
995
|
if lng == "py":
|
|
841
|
-
import_result = PythonImporter(
|
|
996
|
+
import_result = PythonImporter().run_import(spec)
|
|
842
997
|
else:
|
|
843
|
-
import_result = JacImporter(
|
|
998
|
+
import_result = JacImporter().run_import(spec, reload_module)
|
|
844
999
|
|
|
845
1000
|
return (
|
|
846
1001
|
(import_result.ret_mod,)
|
|
@@ -864,7 +1019,6 @@ class JacBasics:
|
|
|
864
1019
|
|
|
865
1020
|
@staticmethod
|
|
866
1021
|
def run_test(
|
|
867
|
-
mach: JacMachine,
|
|
868
1022
|
filepath: str,
|
|
869
1023
|
func_name: Optional[str] = None,
|
|
870
1024
|
filter: Optional[str] = None,
|
|
@@ -884,9 +1038,7 @@ class JacBasics:
|
|
|
884
1038
|
if mod_name.endswith(".test"):
|
|
885
1039
|
mod_name = mod_name[:-5]
|
|
886
1040
|
JacTestCheck.reset()
|
|
887
|
-
JacMachineInterface.jac_import(
|
|
888
|
-
mach=mach, target=mod_name, base_path=base
|
|
889
|
-
)
|
|
1041
|
+
JacMachineInterface.jac_import(target=mod_name, base_path=base)
|
|
890
1042
|
JacTestCheck.run_test(
|
|
891
1043
|
xit, maxfail, verbose, os.path.abspath(filepath), func_name
|
|
892
1044
|
)
|
|
@@ -915,7 +1067,7 @@ class JacBasics:
|
|
|
915
1067
|
print(f"\n\n\t\t* Inside {root_dir}" + "/" + f"{file} *")
|
|
916
1068
|
JacTestCheck.reset()
|
|
917
1069
|
JacMachineInterface.jac_import(
|
|
918
|
-
|
|
1070
|
+
target=file[:-4], base_path=root_dir
|
|
919
1071
|
)
|
|
920
1072
|
JacTestCheck.run_test(
|
|
921
1073
|
xit, maxfail, verbose, os.path.abspath(file), func_name
|
|
@@ -950,52 +1102,31 @@ class JacBasics:
|
|
|
950
1102
|
|
|
951
1103
|
@staticmethod
|
|
952
1104
|
def refs(
|
|
953
|
-
|
|
954
|
-
targets: NodeArchetype | list[NodeArchetype] | None = None,
|
|
955
|
-
dir: EdgeDir = EdgeDir.OUT,
|
|
956
|
-
filter: Callable[[EdgeArchetype], bool] | None = None,
|
|
957
|
-
edges_only: bool = False,
|
|
958
|
-
from_visit: bool = False,
|
|
1105
|
+
path: DataSpatialPath | NodeArchetype | list[NodeArchetype],
|
|
959
1106
|
) -> (
|
|
960
1107
|
list[NodeArchetype] | list[EdgeArchetype] | list[NodeArchetype | EdgeArchetype]
|
|
961
1108
|
):
|
|
962
1109
|
"""Jac's apply_dir stmt feature."""
|
|
963
|
-
if isinstance(
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
if edges_only:
|
|
971
|
-
connected_edges: list[EdgeArchetype | NodeArchetype] = []
|
|
972
|
-
for node in sources:
|
|
973
|
-
edges = JacMachineInterface.get_edges(
|
|
974
|
-
node.__jac__, dir, filter, target_obj=targ_obj_set
|
|
975
|
-
)
|
|
976
|
-
for edge in edges:
|
|
977
|
-
assert isinstance(edge, EdgeArchetype)
|
|
978
|
-
if edge in connected_edges:
|
|
979
|
-
continue
|
|
980
|
-
if from_visit:
|
|
981
|
-
connected_edges.append(edge)
|
|
982
|
-
if dir == EdgeDir.IN:
|
|
983
|
-
connected_edges.append(edge.__jac__.source.archetype)
|
|
984
|
-
else:
|
|
985
|
-
connected_edges.append(edge.__jac__.target.archetype)
|
|
986
|
-
else:
|
|
987
|
-
connected_edges.append(edge)
|
|
988
|
-
return connected_edges
|
|
1110
|
+
if not isinstance(path, DataSpatialPath):
|
|
1111
|
+
path = DataSpatialPath(path, [DataSpatialDestination(EdgeDir.OUT)])
|
|
1112
|
+
|
|
1113
|
+
origin = path.origin
|
|
1114
|
+
|
|
1115
|
+
if path.edge_only:
|
|
1116
|
+
destinations = path.destinations[:-1]
|
|
989
1117
|
else:
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1118
|
+
destinations = path.destinations
|
|
1119
|
+
while destinations:
|
|
1120
|
+
dest = path.destinations.pop(0)
|
|
1121
|
+
origin = JacMachineInterface.edges_to_nodes(origin, dest)
|
|
1122
|
+
|
|
1123
|
+
if path.edge_only:
|
|
1124
|
+
if path.from_visit:
|
|
1125
|
+
return JacMachineInterface.get_edges_with_node(
|
|
1126
|
+
origin, path.destinations[-1]
|
|
994
1127
|
)
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
)
|
|
998
|
-
return connected_nodes
|
|
1128
|
+
return JacMachineInterface.get_edges(origin, path.destinations[-1])
|
|
1129
|
+
return origin
|
|
999
1130
|
|
|
1000
1131
|
@staticmethod
|
|
1001
1132
|
def filter(
|
|
@@ -1095,7 +1226,7 @@ class JacBasics:
|
|
|
1095
1226
|
@staticmethod
|
|
1096
1227
|
def root() -> Root:
|
|
1097
1228
|
"""Jac's root getter."""
|
|
1098
|
-
return
|
|
1229
|
+
return JacMachine.get_context().get_root()
|
|
1099
1230
|
|
|
1100
1231
|
@staticmethod
|
|
1101
1232
|
def build_edge(
|
|
@@ -1209,6 +1340,40 @@ class JacBasics:
|
|
|
1209
1340
|
"mtllm is not installed. Please install it with `pip install mtllm` and run `jac clean`."
|
|
1210
1341
|
)
|
|
1211
1342
|
|
|
1343
|
+
@staticmethod
|
|
1344
|
+
def gen_llm_call_override(
|
|
1345
|
+
_pass: PyastGenPass, node: ast.FuncCall
|
|
1346
|
+
) -> list[ast3.AST]:
|
|
1347
|
+
"""Generate python ast nodes for llm function body override syntax.
|
|
1348
|
+
|
|
1349
|
+
example:
|
|
1350
|
+
foo() by llm();
|
|
1351
|
+
"""
|
|
1352
|
+
_pass.log_warning(
|
|
1353
|
+
"MT-LLM is not installed. Please install it with `pip install mtllm`."
|
|
1354
|
+
)
|
|
1355
|
+
return [
|
|
1356
|
+
_pass.sync(
|
|
1357
|
+
ast3.Raise(
|
|
1358
|
+
_pass.sync(
|
|
1359
|
+
ast3.Call(
|
|
1360
|
+
func=_pass.sync(
|
|
1361
|
+
ast3.Name(id="ImportError", ctx=ast3.Load())
|
|
1362
|
+
),
|
|
1363
|
+
args=[
|
|
1364
|
+
_pass.sync(
|
|
1365
|
+
ast3.Constant(
|
|
1366
|
+
value="mtllm is not installed. Please install it with `pip install mtllm` and run `jac clean`." # noqa: E501
|
|
1367
|
+
)
|
|
1368
|
+
)
|
|
1369
|
+
],
|
|
1370
|
+
keywords=[],
|
|
1371
|
+
)
|
|
1372
|
+
)
|
|
1373
|
+
)
|
|
1374
|
+
)
|
|
1375
|
+
]
|
|
1376
|
+
|
|
1212
1377
|
@staticmethod
|
|
1213
1378
|
def gen_llm_body(_pass: PyastGenPass, node: ast.Ability) -> list[ast3.AST]:
|
|
1214
1379
|
"""Generate the by LLM body."""
|
|
@@ -1346,32 +1511,49 @@ class JacBasics:
|
|
|
1346
1511
|
"exclude_info": [],
|
|
1347
1512
|
}
|
|
1348
1513
|
|
|
1514
|
+
@staticmethod
|
|
1515
|
+
def get_semstr_type(
|
|
1516
|
+
file_loc: str, scope: str, attr: str, return_semstr: bool
|
|
1517
|
+
) -> Optional[str]:
|
|
1518
|
+
"""Jac's get_semstr_type feature."""
|
|
1519
|
+
|
|
1520
|
+
@staticmethod
|
|
1521
|
+
def obj_scope(file_loc: str, attr: str) -> str:
|
|
1522
|
+
"""Jac's gather_scope feature."""
|
|
1523
|
+
return ""
|
|
1524
|
+
|
|
1525
|
+
@staticmethod
|
|
1526
|
+
def get_sem_type(file_loc: str, attr: str) -> tuple[str | None, str | None]:
|
|
1527
|
+
"""Jac's get_semstr_type implementation."""
|
|
1528
|
+
return None, None
|
|
1529
|
+
|
|
1349
1530
|
|
|
1350
1531
|
class JacUtils:
|
|
1351
1532
|
"""Jac Machine Utilities."""
|
|
1352
1533
|
|
|
1353
1534
|
@staticmethod
|
|
1354
|
-
def attach_program(
|
|
1535
|
+
def attach_program(jac_program: JacProgram) -> None:
|
|
1355
1536
|
"""Attach a JacProgram to the machine."""
|
|
1356
|
-
|
|
1537
|
+
JacMachine.program = jac_program
|
|
1357
1538
|
|
|
1358
1539
|
@staticmethod
|
|
1359
1540
|
def load_module(
|
|
1360
|
-
|
|
1541
|
+
module_name: str, module: types.ModuleType, force: bool = False
|
|
1361
1542
|
) -> None:
|
|
1362
1543
|
"""Load a module into the machine."""
|
|
1363
|
-
|
|
1364
|
-
|
|
1544
|
+
if module_name not in JacMachine.loaded_modules or force:
|
|
1545
|
+
JacMachine.loaded_modules[module_name] = module
|
|
1546
|
+
sys.modules[module_name] = module # TODO: May want to nuke this one day
|
|
1365
1547
|
|
|
1366
1548
|
@staticmethod
|
|
1367
|
-
def list_modules(
|
|
1549
|
+
def list_modules() -> list[str]:
|
|
1368
1550
|
"""List all loaded modules."""
|
|
1369
|
-
return list(
|
|
1551
|
+
return list(JacMachine.loaded_modules.keys())
|
|
1370
1552
|
|
|
1371
1553
|
@staticmethod
|
|
1372
|
-
def list_walkers(
|
|
1554
|
+
def list_walkers(module_name: str) -> list[str]:
|
|
1373
1555
|
"""List all walkers in a specific module."""
|
|
1374
|
-
module =
|
|
1556
|
+
module = JacMachine.loaded_modules.get(module_name)
|
|
1375
1557
|
if module:
|
|
1376
1558
|
walkers = []
|
|
1377
1559
|
for name, obj in inspect.getmembers(module):
|
|
@@ -1381,9 +1563,9 @@ class JacUtils:
|
|
|
1381
1563
|
return []
|
|
1382
1564
|
|
|
1383
1565
|
@staticmethod
|
|
1384
|
-
def list_nodes(
|
|
1566
|
+
def list_nodes(module_name: str) -> list[str]:
|
|
1385
1567
|
"""List all nodes in a specific module."""
|
|
1386
|
-
module =
|
|
1568
|
+
module = JacMachine.loaded_modules.get(module_name)
|
|
1387
1569
|
if module:
|
|
1388
1570
|
nodes = []
|
|
1389
1571
|
for name, obj in inspect.getmembers(module):
|
|
@@ -1393,9 +1575,9 @@ class JacUtils:
|
|
|
1393
1575
|
return []
|
|
1394
1576
|
|
|
1395
1577
|
@staticmethod
|
|
1396
|
-
def list_edges(
|
|
1578
|
+
def list_edges(module_name: str) -> list[str]:
|
|
1397
1579
|
"""List all edges in a specific module."""
|
|
1398
|
-
module =
|
|
1580
|
+
module = JacMachine.loaded_modules.get(module_name)
|
|
1399
1581
|
if module:
|
|
1400
1582
|
nodes = []
|
|
1401
1583
|
for name, obj in inspect.getmembers(module):
|
|
@@ -1406,7 +1588,6 @@ class JacUtils:
|
|
|
1406
1588
|
|
|
1407
1589
|
@staticmethod
|
|
1408
1590
|
def create_archetype_from_source(
|
|
1409
|
-
mach: JacMachine,
|
|
1410
1591
|
source_code: str,
|
|
1411
1592
|
module_name: Optional[str] = None,
|
|
1412
1593
|
base_path: Optional[str] = None,
|
|
@@ -1417,12 +1598,12 @@ class JacUtils:
|
|
|
1417
1598
|
from jaclang.runtimelib.importer import JacImporter, ImportPathSpec
|
|
1418
1599
|
|
|
1419
1600
|
if not base_path:
|
|
1420
|
-
base_path =
|
|
1601
|
+
base_path = JacMachine.base_path_dir or os.getcwd()
|
|
1421
1602
|
|
|
1422
1603
|
if base_path and not os.path.exists(base_path):
|
|
1423
1604
|
os.makedirs(base_path)
|
|
1424
1605
|
if not module_name:
|
|
1425
|
-
module_name = f"_dynamic_module_{len(
|
|
1606
|
+
module_name = f"_dynamic_module_{len(JacMachine.loaded_modules)}"
|
|
1426
1607
|
with tempfile.NamedTemporaryFile(
|
|
1427
1608
|
mode="w",
|
|
1428
1609
|
suffix=".jac",
|
|
@@ -1434,7 +1615,7 @@ class JacUtils:
|
|
|
1434
1615
|
tmp_file.write(source_code)
|
|
1435
1616
|
|
|
1436
1617
|
try:
|
|
1437
|
-
importer = JacImporter(
|
|
1618
|
+
importer = JacImporter()
|
|
1438
1619
|
tmp_file_basename = os.path.basename(tmp_file_path)
|
|
1439
1620
|
tmp_module_name, _ = os.path.splitext(tmp_file_basename)
|
|
1440
1621
|
|
|
@@ -1451,7 +1632,7 @@ class JacUtils:
|
|
|
1451
1632
|
import_result = importer.run_import(spec, reload=False)
|
|
1452
1633
|
module = import_result.ret_mod
|
|
1453
1634
|
|
|
1454
|
-
|
|
1635
|
+
JacMachine.loaded_modules[module_name] = module
|
|
1455
1636
|
return module
|
|
1456
1637
|
except Exception as e:
|
|
1457
1638
|
logger.error(f"Error importing dynamic module '{module_name}': {e}")
|
|
@@ -1462,20 +1643,19 @@ class JacUtils:
|
|
|
1462
1643
|
|
|
1463
1644
|
@staticmethod
|
|
1464
1645
|
def update_walker(
|
|
1465
|
-
mach: JacMachine,
|
|
1466
1646
|
module_name: str,
|
|
1467
1647
|
items: Optional[dict[str, Union[str, Optional[str]]]],
|
|
1468
1648
|
) -> tuple[types.ModuleType, ...]:
|
|
1469
1649
|
"""Reimport the module."""
|
|
1470
1650
|
from .importer import JacImporter, ImportPathSpec
|
|
1471
1651
|
|
|
1472
|
-
if module_name in
|
|
1652
|
+
if module_name in JacMachine.loaded_modules:
|
|
1473
1653
|
try:
|
|
1474
|
-
old_module =
|
|
1475
|
-
importer = JacImporter(
|
|
1654
|
+
old_module = JacMachine.loaded_modules[module_name]
|
|
1655
|
+
importer = JacImporter()
|
|
1476
1656
|
spec = ImportPathSpec(
|
|
1477
1657
|
target=module_name,
|
|
1478
|
-
base_path=
|
|
1658
|
+
base_path=JacMachine.base_path_dir,
|
|
1479
1659
|
absorb=False,
|
|
1480
1660
|
mdl_alias=None,
|
|
1481
1661
|
override_name=None,
|
|
@@ -1504,13 +1684,12 @@ class JacUtils:
|
|
|
1504
1684
|
|
|
1505
1685
|
@staticmethod
|
|
1506
1686
|
def spawn_node(
|
|
1507
|
-
mach: JacMachine,
|
|
1508
1687
|
node_name: str,
|
|
1509
1688
|
attributes: Optional[dict] = None,
|
|
1510
1689
|
module_name: str = "__main__",
|
|
1511
1690
|
) -> NodeArchetype:
|
|
1512
1691
|
"""Spawn a node instance of the given node_name with attributes."""
|
|
1513
|
-
node_class = JacMachineInterface.get_archetype(
|
|
1692
|
+
node_class = JacMachineInterface.get_archetype(module_name, node_name)
|
|
1514
1693
|
if isinstance(node_class, type) and issubclass(node_class, NodeArchetype):
|
|
1515
1694
|
if attributes is None:
|
|
1516
1695
|
attributes = {}
|
|
@@ -1521,13 +1700,12 @@ class JacUtils:
|
|
|
1521
1700
|
|
|
1522
1701
|
@staticmethod
|
|
1523
1702
|
def spawn_walker(
|
|
1524
|
-
mach: JacMachine,
|
|
1525
1703
|
walker_name: str,
|
|
1526
1704
|
attributes: Optional[dict] = None,
|
|
1527
1705
|
module_name: str = "__main__",
|
|
1528
1706
|
) -> WalkerArchetype:
|
|
1529
1707
|
"""Spawn a walker instance of the given walker_name."""
|
|
1530
|
-
walker_class = JacMachineInterface.get_archetype(
|
|
1708
|
+
walker_class = JacMachineInterface.get_archetype(module_name, walker_name)
|
|
1531
1709
|
if isinstance(walker_class, type) and issubclass(walker_class, WalkerArchetype):
|
|
1532
1710
|
if attributes is None:
|
|
1533
1711
|
attributes = {}
|
|
@@ -1537,27 +1715,17 @@ class JacUtils:
|
|
|
1537
1715
|
raise ValueError(f"Walker {walker_name} not found.")
|
|
1538
1716
|
|
|
1539
1717
|
@staticmethod
|
|
1540
|
-
def get_archetype(
|
|
1541
|
-
mach: JacMachine, module_name: str, archetype_name: str
|
|
1542
|
-
) -> Optional[Archetype]:
|
|
1718
|
+
def get_archetype(module_name: str, archetype_name: str) -> Optional[Archetype]:
|
|
1543
1719
|
"""Retrieve an archetype class from a module."""
|
|
1544
|
-
module =
|
|
1720
|
+
module = JacMachine.loaded_modules.get(module_name)
|
|
1545
1721
|
if module:
|
|
1546
1722
|
return getattr(module, archetype_name, None)
|
|
1547
1723
|
return None
|
|
1548
1724
|
|
|
1549
|
-
@staticmethod
|
|
1550
|
-
def await_obj(obj: Any) -> Any: # noqa: ANN401
|
|
1551
|
-
"""Await an object if it is a coroutine or async or future function."""
|
|
1552
|
-
machine = JacMachineInterface.py_get_jac_machine()
|
|
1553
|
-
_event_loop = machine._event_loop
|
|
1554
|
-
return _event_loop.run_until_complete(obj)
|
|
1555
|
-
|
|
1556
1725
|
@staticmethod
|
|
1557
1726
|
def thread_run(func: Callable, *args: object) -> Future: # noqa: ANN401
|
|
1558
1727
|
"""Run a function in a thread."""
|
|
1559
|
-
|
|
1560
|
-
_executor = machine.pool
|
|
1728
|
+
_executor = JacMachine.pool
|
|
1561
1729
|
return _executor.submit(func, *args)
|
|
1562
1730
|
|
|
1563
1731
|
@staticmethod
|
|
@@ -1583,80 +1751,35 @@ class JacMachineInterface(
|
|
|
1583
1751
|
class JacMachine(JacMachineInterface):
|
|
1584
1752
|
"""Jac Machine State."""
|
|
1585
1753
|
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
) -> None:
|
|
1592
|
-
"""Initialize JacMachine."""
|
|
1593
|
-
self.loaded_modules: dict[str, types.ModuleType] = {}
|
|
1594
|
-
if not base_path:
|
|
1595
|
-
base_path = os.getcwd()
|
|
1596
|
-
# Ensure the base_path is a list rather than a string
|
|
1597
|
-
self.base_path = base_path
|
|
1598
|
-
self.base_path_dir = (
|
|
1599
|
-
os.path.dirname(base_path)
|
|
1600
|
-
if not os.path.isdir(base_path)
|
|
1601
|
-
else os.path.abspath(base_path)
|
|
1602
|
-
)
|
|
1603
|
-
self.program: JacProgram = JacProgram()
|
|
1604
|
-
self.pool = ThreadPoolExecutor()
|
|
1605
|
-
self._event_loop = asyncio.new_event_loop()
|
|
1606
|
-
self.mem: Memory = ShelfStorage(session)
|
|
1607
|
-
self.reports: list[Any] = []
|
|
1608
|
-
sr_arch = Root()
|
|
1609
|
-
sr_anch = sr_arch.__jac__
|
|
1610
|
-
sr_anch.id = UUID(Con.SUPER_ROOT_UUID)
|
|
1611
|
-
sr_anch.persistent = False
|
|
1612
|
-
self.system_root = sr_anch
|
|
1613
|
-
self.custom: Any = MISSING
|
|
1614
|
-
if not isinstance(
|
|
1615
|
-
system_root := self.mem.find_by_id(UUID(Con.SUPER_ROOT_UUID)), NodeAnchor
|
|
1616
|
-
):
|
|
1617
|
-
system_root = cast(NodeAnchor, Root().__jac__) # type: ignore[attr-defined]
|
|
1618
|
-
system_root.id = UUID(Con.SUPER_ROOT_UUID)
|
|
1619
|
-
self.mem.set(system_root.id, system_root)
|
|
1620
|
-
|
|
1621
|
-
self.system_root = system_root
|
|
1622
|
-
|
|
1623
|
-
self.entry_node = self.root_state = self.init_anchor(root, self.system_root)
|
|
1624
|
-
|
|
1625
|
-
def init_anchor(
|
|
1626
|
-
self,
|
|
1627
|
-
anchor_id: str | None,
|
|
1628
|
-
default: NodeAnchor,
|
|
1629
|
-
) -> NodeAnchor:
|
|
1630
|
-
"""Load initial anchors."""
|
|
1631
|
-
if anchor_id:
|
|
1632
|
-
if isinstance(anchor := self.mem.find_by_id(UUID(anchor_id)), NodeAnchor):
|
|
1633
|
-
return anchor
|
|
1634
|
-
raise ValueError(f"Invalid anchor id {anchor_id} !")
|
|
1635
|
-
return default
|
|
1636
|
-
|
|
1637
|
-
def set_entry_node(self, entry_node: str | None) -> None:
|
|
1638
|
-
"""Override entry."""
|
|
1639
|
-
self.entry_node = self.init_anchor(entry_node, self.root_state)
|
|
1640
|
-
|
|
1641
|
-
def close(self) -> None:
|
|
1642
|
-
"""Close current ExecutionContext."""
|
|
1643
|
-
call_jac_func_with_machine(mach=self, func=self.mem.close)
|
|
1644
|
-
|
|
1645
|
-
def get_root(self) -> Root:
|
|
1646
|
-
"""Get current root."""
|
|
1647
|
-
return cast(Root, self.root_state.archetype)
|
|
1754
|
+
loaded_modules: dict[str, types.ModuleType] = {}
|
|
1755
|
+
base_path_dir: str = os.getcwd()
|
|
1756
|
+
program: JacProgram = JacProgram()
|
|
1757
|
+
pool: ThreadPoolExecutor = ThreadPoolExecutor()
|
|
1758
|
+
exec_ctx: ExecutionContext = ExecutionContext()
|
|
1648
1759
|
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1760
|
+
@staticmethod
|
|
1761
|
+
def set_base_path(base_path: str) -> None:
|
|
1762
|
+
"""Set the base path for the machine."""
|
|
1763
|
+
JacMachine.reset_machine()
|
|
1764
|
+
JacMachine.base_path_dir = (
|
|
1765
|
+
base_path if os.path.isdir(base_path) else os.path.dirname(base_path)
|
|
1766
|
+
)
|
|
1652
1767
|
|
|
1768
|
+
@staticmethod
|
|
1769
|
+
def set_context(context: ExecutionContext) -> None:
|
|
1770
|
+
"""Set the context for the machine."""
|
|
1771
|
+
JacMachine.exec_ctx = context
|
|
1653
1772
|
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1773
|
+
@staticmethod
|
|
1774
|
+
def reset_machine() -> None:
|
|
1775
|
+
"""Reset the machine."""
|
|
1776
|
+
# for i in JacMachine.loaded_modules.values():
|
|
1777
|
+
# sys.modules.pop(i.__name__, None)
|
|
1778
|
+
JacMachine.loaded_modules.clear()
|
|
1779
|
+
JacMachine.base_path_dir = os.getcwd()
|
|
1780
|
+
JacMachine.program = JacProgram()
|
|
1781
|
+
JacMachine.pool = ThreadPoolExecutor()
|
|
1782
|
+
JacMachine.exec_ctx = ExecutionContext()
|
|
1660
1783
|
|
|
1661
1784
|
|
|
1662
1785
|
def generate_plugin_helpers(
|