jaclang 0.7.1__py3-none-any.whl → 0.7.7__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 +2 -2
- jaclang/compiler/absyntree.py +539 -297
- jaclang/compiler/codeloc.py +2 -2
- jaclang/compiler/constant.py +100 -2
- jaclang/compiler/jac.lark +27 -19
- jaclang/compiler/parser.py +119 -92
- jaclang/compiler/passes/main/access_modifier_pass.py +20 -12
- jaclang/compiler/passes/main/def_impl_match_pass.py +32 -12
- jaclang/compiler/passes/main/def_use_pass.py +59 -40
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +71 -30
- jaclang/compiler/passes/main/import_pass.py +12 -7
- jaclang/compiler/passes/main/pyast_gen_pass.py +110 -47
- jaclang/compiler/passes/main/pyast_load_pass.py +49 -13
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +25 -11
- jaclang/compiler/passes/main/pyout_pass.py +3 -1
- jaclang/compiler/passes/main/registry_pass.py +6 -6
- jaclang/compiler/passes/main/sub_node_tab_pass.py +0 -5
- jaclang/compiler/passes/main/sym_tab_build_pass.py +43 -235
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +21 -4
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +5 -10
- jaclang/compiler/passes/main/tests/test_import_pass.py +8 -0
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/main/type_check_pass.py +2 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +44 -11
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
- jaclang/compiler/passes/tool/tests/fixtures/genai/essay_review.jac +1 -1
- jaclang/compiler/passes/tool/tests/fixtures/genai/expert_answer.jac +1 -1
- jaclang/compiler/passes/tool/tests/fixtures/genai/joke_gen.jac +1 -1
- jaclang/compiler/passes/tool/tests/fixtures/genai/odd_word_out.jac +1 -1
- jaclang/compiler/passes/tool/tests/fixtures/genai/personality_finder.jac +1 -1
- jaclang/compiler/passes/tool/tests/fixtures/genai/text_to_type.jac +1 -1
- jaclang/compiler/passes/tool/tests/fixtures/genai/translator.jac +1 -1
- jaclang/compiler/passes/tool/tests/fixtures/genai/wikipedia.jac +1 -1
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
- jaclang/compiler/passes/transform.py +2 -4
- jaclang/{core/registry.py → compiler/semtable.py} +1 -3
- jaclang/compiler/symtable.py +150 -89
- jaclang/compiler/tests/test_parser.py +2 -2
- jaclang/core/aott.py +118 -18
- jaclang/core/{construct.py → architype.py} +44 -93
- jaclang/core/constructs.py +44 -0
- jaclang/core/context.py +157 -0
- jaclang/core/importer.py +18 -9
- jaclang/core/memory.py +53 -2
- jaclang/core/test.py +90 -0
- jaclang/core/utils.py +2 -2
- jaclang/langserve/engine.py +199 -138
- jaclang/langserve/server.py +48 -53
- jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -0
- jaclang/langserve/tests/fixtures/circle.jac +16 -12
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.impl.jac +8 -4
- jaclang/langserve/tests/fixtures/circle_pure.jac +2 -2
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +15 -0
- jaclang/langserve/tests/fixtures/import_include_statements.jac +6 -0
- jaclang/langserve/tests/fixtures/py_import.py +26 -0
- jaclang/langserve/tests/test_server.py +200 -2
- jaclang/langserve/utils.py +214 -10
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +48 -92
- jaclang/plugin/feature.py +33 -17
- jaclang/plugin/spec.py +18 -20
- jaclang/plugin/tests/test_features.py +0 -33
- jaclang/settings.py +4 -0
- jaclang/tests/fixtures/abc.jac +16 -12
- jaclang/tests/fixtures/aott_raise.jac +1 -1
- jaclang/tests/fixtures/byllmissue.jac +12 -0
- jaclang/tests/fixtures/edgetypeissue.jac +10 -0
- jaclang/tests/fixtures/hash_init_check.jac +17 -0
- jaclang/tests/fixtures/hello.jac +1 -1
- jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
- jaclang/tests/fixtures/impl_match_confused.jac +5 -0
- jaclang/tests/fixtures/math_question.jpg +0 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
- jaclang/tests/fixtures/nosigself.jac +19 -0
- jaclang/tests/fixtures/run_test.jac +17 -5
- jaclang/tests/fixtures/walker_override.jac +21 -0
- jaclang/tests/fixtures/with_llm_function.jac +1 -1
- jaclang/tests/fixtures/with_llm_lower.jac +1 -1
- jaclang/tests/fixtures/with_llm_method.jac +1 -1
- jaclang/tests/fixtures/with_llm_type.jac +1 -1
- jaclang/tests/fixtures/with_llm_vision.jac +25 -0
- jaclang/tests/test_bugs.py +19 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +197 -82
- jaclang/tests/test_reference.py +1 -1
- jaclang/utils/lang_tools.py +5 -4
- jaclang/utils/test.py +2 -1
- jaclang/utils/treeprinter.py +35 -4
- {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/METADATA +3 -2
- {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/RECORD +96 -88
- jaclang/core/llms/__init__.py +0 -20
- jaclang/core/llms/anthropic.py +0 -61
- jaclang/core/llms/base.py +0 -206
- jaclang/core/llms/groq.py +0 -67
- jaclang/core/llms/huggingface.py +0 -73
- jaclang/core/llms/ollama.py +0 -78
- jaclang/core/llms/openai.py +0 -61
- jaclang/core/llms/togetherai.py +0 -60
- jaclang/core/llms/utils.py +0 -9
- jaclang/core/shelve_storage.py +0 -55
- {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/WHEEL +0 -0
- {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/entry_points.txt +0 -0
jaclang/langserve/utils.py
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
"""Utility functions for the language server."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import builtins
|
|
5
|
+
import importlib.util
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
4
8
|
from functools import wraps
|
|
5
9
|
from typing import Any, Awaitable, Callable, Coroutine, Optional, ParamSpec, TypeVar
|
|
6
10
|
|
|
7
11
|
import jaclang.compiler.absyntree as ast
|
|
8
|
-
from jaclang.compiler.
|
|
12
|
+
from jaclang.compiler.codeloc import CodeLocInfo
|
|
13
|
+
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
14
|
+
from jaclang.utils.helpers import import_target_to_relative_path
|
|
9
15
|
|
|
16
|
+
import lsprotocol.types as lspt
|
|
10
17
|
|
|
11
18
|
T = TypeVar("T", bound=Callable[..., Coroutine[Any, Any, Any]])
|
|
12
19
|
P = ParamSpec("P")
|
|
@@ -55,17 +62,23 @@ def sym_tab_list(sym_tab: SymbolTable, file_path: str) -> list[SymbolTable]:
|
|
|
55
62
|
return sym_tabs
|
|
56
63
|
|
|
57
64
|
|
|
58
|
-
def
|
|
65
|
+
def find_deepest_symbol_node_at_pos(
|
|
59
66
|
node: ast.AstNode, line: int, character: int
|
|
60
|
-
) -> Optional[ast.
|
|
61
|
-
"""Return the deepest node that contains the given position."""
|
|
67
|
+
) -> Optional[ast.AstSymbolNode]:
|
|
68
|
+
"""Return the deepest symbol node that contains the given position."""
|
|
69
|
+
last_symbol_node = None
|
|
70
|
+
|
|
62
71
|
if position_within_node(node, line, character):
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
if isinstance(node, ast.AstSymbolNode):
|
|
73
|
+
last_symbol_node = node
|
|
74
|
+
|
|
75
|
+
for child in [i for i in node.kid if i.loc.mod_path == node.loc.mod_path]:
|
|
76
|
+
if position_within_node(child, line, character):
|
|
77
|
+
deeper_node = find_deepest_symbol_node_at_pos(child, line, character)
|
|
78
|
+
if deeper_node is not None:
|
|
79
|
+
last_symbol_node = deeper_node
|
|
80
|
+
|
|
81
|
+
return last_symbol_node
|
|
69
82
|
|
|
70
83
|
|
|
71
84
|
def position_within_node(node: ast.AstNode, line: int, character: int) -> bool:
|
|
@@ -88,3 +101,194 @@ def position_within_node(node: ast.AstNode, line: int, character: int) -> bool:
|
|
|
88
101
|
):
|
|
89
102
|
return True
|
|
90
103
|
return False
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def collect_symbols(node: SymbolTable) -> list[lspt.DocumentSymbol]:
|
|
107
|
+
"""Recursively collect symbols from the AST."""
|
|
108
|
+
symbols = []
|
|
109
|
+
if node is None:
|
|
110
|
+
return symbols
|
|
111
|
+
|
|
112
|
+
for key, item in node.tab.items():
|
|
113
|
+
if (
|
|
114
|
+
key in dir(builtins)
|
|
115
|
+
or item in [owner_sym(tab) for tab in node.kid]
|
|
116
|
+
or item.decl.loc.mod_path != node.owner.loc.mod_path
|
|
117
|
+
):
|
|
118
|
+
continue
|
|
119
|
+
else:
|
|
120
|
+
|
|
121
|
+
pos = create_range(item.decl.loc)
|
|
122
|
+
symbol = lspt.DocumentSymbol(
|
|
123
|
+
name=key,
|
|
124
|
+
kind=kind_map(item.decl),
|
|
125
|
+
range=pos,
|
|
126
|
+
selection_range=pos,
|
|
127
|
+
children=[],
|
|
128
|
+
)
|
|
129
|
+
symbols.append(symbol)
|
|
130
|
+
|
|
131
|
+
for sub_tab in [
|
|
132
|
+
i for i in node.kid if i.owner.loc.mod_path == node.owner.loc.mod_path
|
|
133
|
+
]:
|
|
134
|
+
sub_symbols = collect_symbols(sub_tab)
|
|
135
|
+
|
|
136
|
+
if isinstance(
|
|
137
|
+
sub_tab.owner,
|
|
138
|
+
(ast.IfStmt, ast.ElseStmt, ast.WhileStmt, ast.IterForStmt, ast.InForStmt),
|
|
139
|
+
):
|
|
140
|
+
symbols.extend(sub_symbols)
|
|
141
|
+
else:
|
|
142
|
+
sub_pos = create_range(sub_tab.owner.loc)
|
|
143
|
+
symbol = lspt.DocumentSymbol(
|
|
144
|
+
name=sub_tab.name,
|
|
145
|
+
kind=kind_map(sub_tab.owner),
|
|
146
|
+
range=sub_pos,
|
|
147
|
+
selection_range=sub_pos,
|
|
148
|
+
children=sub_symbols,
|
|
149
|
+
)
|
|
150
|
+
symbols.append(symbol)
|
|
151
|
+
|
|
152
|
+
return symbols
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def owner_sym(table: SymbolTable) -> Optional[Symbol]:
|
|
156
|
+
"""Get owner sym."""
|
|
157
|
+
if table.parent and isinstance(table.owner, ast.AstSymbolNode):
|
|
158
|
+
return table.parent.lookup(table.owner.sym_name)
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def create_range(loc: CodeLocInfo) -> lspt.Range:
|
|
163
|
+
"""Create an lspt.Range from a location object."""
|
|
164
|
+
return lspt.Range(
|
|
165
|
+
start=lspt.Position(
|
|
166
|
+
line=loc.first_line - 1 if loc.first_line > 0 else 0,
|
|
167
|
+
character=loc.col_start - 1 if loc.col_start > 0 else 0,
|
|
168
|
+
),
|
|
169
|
+
end=lspt.Position(
|
|
170
|
+
line=loc.last_line - 1 if loc.last_line > 0 else 0,
|
|
171
|
+
character=loc.col_end - 1 if loc.col_end > 0 else 0,
|
|
172
|
+
),
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def kind_map(sub_tab: ast.AstNode) -> lspt.SymbolKind:
|
|
177
|
+
"""Map the symbol node to an lspt.SymbolKind."""
|
|
178
|
+
return (
|
|
179
|
+
lspt.SymbolKind.Function
|
|
180
|
+
if isinstance(sub_tab, (ast.Ability, ast.AbilityDef))
|
|
181
|
+
else (
|
|
182
|
+
lspt.SymbolKind.Class
|
|
183
|
+
if isinstance(sub_tab, (ast.Architype, ast.ArchDef))
|
|
184
|
+
else (
|
|
185
|
+
lspt.SymbolKind.Module
|
|
186
|
+
if isinstance(sub_tab, ast.Module)
|
|
187
|
+
else (
|
|
188
|
+
lspt.SymbolKind.Enum
|
|
189
|
+
if isinstance(sub_tab, (ast.Enum, ast.EnumDef))
|
|
190
|
+
else lspt.SymbolKind.Variable
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def get_mod_path(mod_path: ast.ModulePath, name_node: ast.Name) -> str | None:
|
|
198
|
+
"""Get path for a module import name."""
|
|
199
|
+
ret_target = None
|
|
200
|
+
module_location_path = mod_path.loc.mod_path
|
|
201
|
+
if mod_path.parent and (
|
|
202
|
+
(
|
|
203
|
+
isinstance(mod_path.parent.parent, ast.Import)
|
|
204
|
+
and mod_path.parent.parent.hint.tag.value == "py"
|
|
205
|
+
)
|
|
206
|
+
or (
|
|
207
|
+
isinstance(mod_path.parent, ast.Import)
|
|
208
|
+
and mod_path.parent.from_loc
|
|
209
|
+
and mod_path.parent.hint.tag.value == "py"
|
|
210
|
+
)
|
|
211
|
+
):
|
|
212
|
+
if mod_path.path and name_node in mod_path.path:
|
|
213
|
+
temporary_path_str = ("." * mod_path.level) + ".".join(
|
|
214
|
+
[p.value for p in mod_path.path[: mod_path.path.index(name_node) + 1]]
|
|
215
|
+
if mod_path.path
|
|
216
|
+
else ""
|
|
217
|
+
)
|
|
218
|
+
else:
|
|
219
|
+
temporary_path_str = mod_path.path_str
|
|
220
|
+
sys.path.append(os.path.dirname(module_location_path))
|
|
221
|
+
spec = importlib.util.find_spec(temporary_path_str)
|
|
222
|
+
sys.path.remove(os.path.dirname(module_location_path))
|
|
223
|
+
if spec and spec.origin and spec.origin.endswith(".py"):
|
|
224
|
+
ret_target = spec.origin
|
|
225
|
+
elif mod_path.parent and (
|
|
226
|
+
(
|
|
227
|
+
isinstance(mod_path.parent.parent, ast.Import)
|
|
228
|
+
and mod_path.parent.parent.hint.tag.value == "jac"
|
|
229
|
+
)
|
|
230
|
+
or (
|
|
231
|
+
isinstance(mod_path.parent, ast.Import)
|
|
232
|
+
and mod_path.parent.from_loc
|
|
233
|
+
and mod_path.parent.hint.tag.value == "jac"
|
|
234
|
+
)
|
|
235
|
+
):
|
|
236
|
+
ret_target = import_target_to_relative_path(
|
|
237
|
+
level=mod_path.level,
|
|
238
|
+
target=mod_path.path_str,
|
|
239
|
+
base_path=os.path.dirname(module_location_path),
|
|
240
|
+
)
|
|
241
|
+
return ret_target
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def get_item_path(mod_item: ast.ModuleItem) -> tuple[str, tuple[int, int]] | None:
|
|
245
|
+
"""Get path."""
|
|
246
|
+
item_name = mod_item.name.value
|
|
247
|
+
if mod_item.from_parent.hint.tag.value == "py" and mod_item.from_parent.from_loc:
|
|
248
|
+
path = get_mod_path(mod_item.from_parent.from_loc, mod_item.name)
|
|
249
|
+
if path:
|
|
250
|
+
return get_definition_range(path, item_name)
|
|
251
|
+
elif mod_item.from_parent.hint.tag.value == "jac":
|
|
252
|
+
mod_node = mod_item.from_mod_path
|
|
253
|
+
if mod_node.sub_module and mod_node.sub_module._sym_tab:
|
|
254
|
+
for symbol_name, symbol in mod_node.sub_module._sym_tab.tab.items():
|
|
255
|
+
if symbol_name == item_name:
|
|
256
|
+
return symbol.decl.loc.mod_path, (
|
|
257
|
+
symbol.decl.loc.first_line - 1,
|
|
258
|
+
symbol.decl.loc.last_line - 1,
|
|
259
|
+
)
|
|
260
|
+
return None
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def get_definition_range(
|
|
264
|
+
filename: str, name: str
|
|
265
|
+
) -> tuple[str, tuple[int, int]] | None:
|
|
266
|
+
"""Get the start and end line of a function or class definition in a file."""
|
|
267
|
+
import ast
|
|
268
|
+
|
|
269
|
+
with open(filename, "r") as file:
|
|
270
|
+
source = file.read()
|
|
271
|
+
|
|
272
|
+
tree = ast.parse(source)
|
|
273
|
+
|
|
274
|
+
for node in ast.walk(tree):
|
|
275
|
+
if isinstance(node, (ast.FunctionDef, ast.ClassDef)) and node.name == name:
|
|
276
|
+
start_line = node.lineno
|
|
277
|
+
end_line = (
|
|
278
|
+
node.body[-1].end_lineno
|
|
279
|
+
if hasattr(node.body[-1], "end_lineno")
|
|
280
|
+
else node.body[-1].lineno
|
|
281
|
+
)
|
|
282
|
+
if start_line and end_line:
|
|
283
|
+
return filename, (start_line - 1, end_line - 1)
|
|
284
|
+
elif isinstance(node, ast.Assign):
|
|
285
|
+
for target in node.targets:
|
|
286
|
+
if isinstance(target, ast.Name) and target.id == name:
|
|
287
|
+
start_line = node.lineno
|
|
288
|
+
end_line = (
|
|
289
|
+
node.end_lineno if hasattr(node, "end_lineno") else node.lineno
|
|
290
|
+
)
|
|
291
|
+
if start_line and end_line:
|
|
292
|
+
return filename, (start_line - 1, end_line - 1)
|
|
293
|
+
|
|
294
|
+
return None
|
jaclang/plugin/builtin.py
CHANGED
jaclang/plugin/default.py
CHANGED
|
@@ -7,40 +7,39 @@ import html
|
|
|
7
7
|
import os
|
|
8
8
|
import pickle
|
|
9
9
|
import types
|
|
10
|
-
from
|
|
10
|
+
from collections import OrderedDict
|
|
11
11
|
from dataclasses import field
|
|
12
12
|
from functools import wraps
|
|
13
13
|
from typing import Any, Callable, Optional, Type, Union
|
|
14
|
-
from uuid import UUID
|
|
15
14
|
|
|
16
15
|
from jaclang.compiler.absyntree import Module
|
|
17
16
|
from jaclang.compiler.constant import EdgeDir, colors
|
|
17
|
+
from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
|
|
18
18
|
from jaclang.core.aott import (
|
|
19
19
|
aott_raise,
|
|
20
20
|
extract_non_primary_type,
|
|
21
21
|
get_all_type_explanations,
|
|
22
22
|
get_info_types,
|
|
23
|
-
|
|
24
|
-
get_type_annotation,
|
|
23
|
+
get_input_information,
|
|
25
24
|
)
|
|
26
|
-
from jaclang.core.
|
|
25
|
+
from jaclang.core.constructs import (
|
|
27
26
|
Architype,
|
|
28
27
|
DSFunc,
|
|
29
28
|
EdgeAnchor,
|
|
30
29
|
EdgeArchitype,
|
|
30
|
+
ExecutionContext,
|
|
31
31
|
GenericEdge,
|
|
32
32
|
JacTestCheck,
|
|
33
|
+
Memory,
|
|
33
34
|
NodeAnchor,
|
|
34
35
|
NodeArchitype,
|
|
35
36
|
ObjectAnchor,
|
|
36
37
|
Root,
|
|
37
38
|
WalkerAnchor,
|
|
38
39
|
WalkerArchitype,
|
|
40
|
+
exec_context,
|
|
39
41
|
)
|
|
40
42
|
from jaclang.core.importer import jac_importer
|
|
41
|
-
from jaclang.core.memory import Memory
|
|
42
|
-
from jaclang.core.registry import SemInfo, SemRegistry, SemScope
|
|
43
|
-
from jaclang.core.shelve_storage import ShelveStorage
|
|
44
43
|
from jaclang.core.utils import traverse_graph
|
|
45
44
|
from jaclang.plugin.feature import JacFeature as Jac
|
|
46
45
|
from jaclang.plugin.spec import T
|
|
@@ -70,65 +69,6 @@ __all__ = [
|
|
|
70
69
|
hookimpl = pluggy.HookimplMarker("jac")
|
|
71
70
|
|
|
72
71
|
|
|
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
|
-
|
|
132
72
|
class JacFeatureDefaults:
|
|
133
73
|
"""Jac Feature."""
|
|
134
74
|
|
|
@@ -138,20 +78,20 @@ class JacFeatureDefaults:
|
|
|
138
78
|
@hookimpl
|
|
139
79
|
def context(session: str = "") -> ExecutionContext:
|
|
140
80
|
"""Get the execution context."""
|
|
141
|
-
ctx =
|
|
81
|
+
ctx = exec_context.get()
|
|
142
82
|
if ctx is None:
|
|
143
83
|
ctx = ExecutionContext()
|
|
144
|
-
|
|
84
|
+
exec_context.set(ctx)
|
|
145
85
|
return ctx
|
|
146
86
|
|
|
147
87
|
@staticmethod
|
|
148
88
|
@hookimpl
|
|
149
89
|
def reset_context() -> None:
|
|
150
90
|
"""Reset the execution context."""
|
|
151
|
-
ctx =
|
|
91
|
+
ctx = exec_context.get()
|
|
152
92
|
if ctx:
|
|
153
93
|
ctx.reset()
|
|
154
|
-
|
|
94
|
+
exec_context.set(None)
|
|
155
95
|
|
|
156
96
|
@staticmethod
|
|
157
97
|
@hookimpl
|
|
@@ -170,7 +110,9 @@ class JacFeatureDefaults:
|
|
|
170
110
|
"""Create a new architype."""
|
|
171
111
|
for i in on_entry + on_exit:
|
|
172
112
|
i.resolve(cls)
|
|
173
|
-
if not
|
|
113
|
+
if not hasattr(cls, "_jac_entry_funcs_") or not hasattr(
|
|
114
|
+
cls, "_jac_exit_funcs_"
|
|
115
|
+
):
|
|
174
116
|
# Saving the module path and reassign it after creating cls
|
|
175
117
|
# So the jac modules are part of the correct module
|
|
176
118
|
cur_module = cls.__module__
|
|
@@ -179,12 +121,20 @@ class JacFeatureDefaults:
|
|
|
179
121
|
cls._jac_entry_funcs_ = on_entry # type: ignore
|
|
180
122
|
cls._jac_exit_funcs_ = on_exit # type: ignore
|
|
181
123
|
else:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
124
|
+
new_entry_funcs = OrderedDict(zip([i.name for i in on_entry], on_entry))
|
|
125
|
+
entry_funcs = OrderedDict(
|
|
126
|
+
zip([i.name for i in cls._jac_entry_funcs_], cls._jac_entry_funcs_)
|
|
127
|
+
)
|
|
128
|
+
entry_funcs.update(new_entry_funcs)
|
|
129
|
+
cls._jac_entry_funcs_ = list(entry_funcs.values())
|
|
130
|
+
|
|
131
|
+
new_exit_funcs = OrderedDict(zip([i.name for i in on_exit], on_exit))
|
|
132
|
+
exit_funcs = OrderedDict(
|
|
133
|
+
zip([i.name for i in cls._jac_exit_funcs_], cls._jac_exit_funcs_)
|
|
134
|
+
)
|
|
135
|
+
exit_funcs.update(new_exit_funcs)
|
|
136
|
+
cls._jac_exit_funcs_ = list(exit_funcs.values())
|
|
137
|
+
|
|
188
138
|
inner_init = cls.__init__ # type: ignore
|
|
189
139
|
|
|
190
140
|
@wraps(inner_init)
|
|
@@ -268,7 +218,7 @@ class JacFeatureDefaults:
|
|
|
268
218
|
cachable: bool,
|
|
269
219
|
mdl_alias: Optional[str],
|
|
270
220
|
override_name: Optional[str],
|
|
271
|
-
mod_bundle: Optional[Module],
|
|
221
|
+
mod_bundle: Optional[Module | str],
|
|
272
222
|
lng: Optional[str],
|
|
273
223
|
items: Optional[dict[str, Union[str, bool]]],
|
|
274
224
|
) -> Optional[types.ModuleType]:
|
|
@@ -387,7 +337,13 @@ class JacFeatureDefaults:
|
|
|
387
337
|
@hookimpl
|
|
388
338
|
def ignore(
|
|
389
339
|
walker: WalkerArchitype,
|
|
390
|
-
expr:
|
|
340
|
+
expr: (
|
|
341
|
+
list[NodeArchitype | EdgeArchitype]
|
|
342
|
+
| list[NodeArchitype]
|
|
343
|
+
| list[EdgeArchitype]
|
|
344
|
+
| NodeArchitype
|
|
345
|
+
| EdgeArchitype
|
|
346
|
+
),
|
|
391
347
|
) -> bool:
|
|
392
348
|
"""Jac's ignore stmt feature."""
|
|
393
349
|
return walker._jac_.ignore_node(expr)
|
|
@@ -396,7 +352,13 @@ class JacFeatureDefaults:
|
|
|
396
352
|
@hookimpl
|
|
397
353
|
def visit_node(
|
|
398
354
|
walker: WalkerArchitype,
|
|
399
|
-
expr:
|
|
355
|
+
expr: (
|
|
356
|
+
list[NodeArchitype | EdgeArchitype]
|
|
357
|
+
| list[NodeArchitype]
|
|
358
|
+
| list[EdgeArchitype]
|
|
359
|
+
| NodeArchitype
|
|
360
|
+
| EdgeArchitype
|
|
361
|
+
),
|
|
400
362
|
) -> bool:
|
|
401
363
|
"""Jac's visit stmt feature."""
|
|
402
364
|
if isinstance(walker, WalkerArchitype):
|
|
@@ -533,14 +495,14 @@ class JacFeatureDefaults:
|
|
|
533
495
|
@hookimpl
|
|
534
496
|
def build_edge(
|
|
535
497
|
is_undirected: bool,
|
|
536
|
-
conn_type: Optional[Type[EdgeArchitype]],
|
|
498
|
+
conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
|
|
537
499
|
conn_assign: Optional[tuple[tuple, tuple]],
|
|
538
500
|
) -> Callable[[], EdgeArchitype]:
|
|
539
501
|
"""Jac's root getter."""
|
|
540
502
|
conn_type = conn_type if conn_type else GenericEdge
|
|
541
503
|
|
|
542
504
|
def builder() -> EdgeArchitype:
|
|
543
|
-
edge = conn_type()
|
|
505
|
+
edge = conn_type() if isinstance(conn_type, type) else conn_type
|
|
544
506
|
edge._jac_.is_undirected = is_undirected
|
|
545
507
|
if conn_assign:
|
|
546
508
|
for fld, val in zip(conn_assign[0], conn_assign[1]):
|
|
@@ -698,16 +660,10 @@ class JacFeatureDefaults:
|
|
|
698
660
|
incl_info = [x for x in incl_info if not isinstance(x[1], type)]
|
|
699
661
|
information, collected_types = get_info_types(_scope, mod_registry, incl_info)
|
|
700
662
|
type_collector.extend(collected_types)
|
|
701
|
-
inputs_information_list = []
|
|
702
|
-
for i in inputs:
|
|
703
|
-
typ_anno = get_type_annotation(i[3])
|
|
704
|
-
type_collector.extend(extract_non_primary_type(typ_anno))
|
|
705
|
-
inputs_information_list.append(
|
|
706
|
-
f"{i[0]} ({i[2]}) ({typ_anno}) = {get_object_string(i[3])}"
|
|
707
|
-
)
|
|
708
|
-
inputs_information = "\n".join(inputs_information_list)
|
|
709
663
|
|
|
710
|
-
|
|
664
|
+
inputs_information = get_input_information(inputs, type_collector)
|
|
665
|
+
|
|
666
|
+
output_information = f"{outputs[0]} ({outputs[1]})".strip()
|
|
711
667
|
type_collector.extend(extract_non_primary_type(outputs[1]))
|
|
712
668
|
output_type_explanations = "\n".join(
|
|
713
669
|
list(
|
jaclang/plugin/feature.py
CHANGED
|
@@ -3,22 +3,20 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import types
|
|
6
|
-
from typing import Any, Callable, Optional,
|
|
6
|
+
from typing import Any, Callable, Optional, Type, TypeAlias, Union
|
|
7
7
|
|
|
8
8
|
from jaclang.compiler.absyntree import Module
|
|
9
|
+
from jaclang.core.constructs import (
|
|
10
|
+
Architype,
|
|
11
|
+
EdgeArchitype,
|
|
12
|
+
Memory,
|
|
13
|
+
NodeArchitype,
|
|
14
|
+
Root,
|
|
15
|
+
WalkerArchitype,
|
|
16
|
+
)
|
|
17
|
+
from jaclang.plugin.default import ExecutionContext
|
|
9
18
|
from jaclang.plugin.spec import JacBuiltin, JacCmdSpec, JacFeatureSpec, T
|
|
10
19
|
|
|
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
|
-
|
|
22
20
|
|
|
23
21
|
import pluggy
|
|
24
22
|
|
|
@@ -33,7 +31,13 @@ class JacFeature:
|
|
|
33
31
|
|
|
34
32
|
import abc
|
|
35
33
|
from jaclang.compiler.constant import EdgeDir
|
|
36
|
-
from jaclang.
|
|
34
|
+
from jaclang.core.constructs import DSFunc
|
|
35
|
+
|
|
36
|
+
RootType: TypeAlias = Root
|
|
37
|
+
Obj: TypeAlias = Architype
|
|
38
|
+
Node: TypeAlias = NodeArchitype
|
|
39
|
+
Edge: TypeAlias = EdgeArchitype
|
|
40
|
+
Walker: TypeAlias = WalkerArchitype
|
|
37
41
|
|
|
38
42
|
@staticmethod
|
|
39
43
|
def context(session: str = "") -> ExecutionContext:
|
|
@@ -98,7 +102,7 @@ class JacFeature:
|
|
|
98
102
|
cachable: bool = True,
|
|
99
103
|
mdl_alias: Optional[str] = None,
|
|
100
104
|
override_name: Optional[str] = None,
|
|
101
|
-
mod_bundle: Optional[Module] = None,
|
|
105
|
+
mod_bundle: Optional[Module | str] = None,
|
|
102
106
|
lng: Optional[str] = "jac",
|
|
103
107
|
items: Optional[dict[str, Union[str, bool]]] = None,
|
|
104
108
|
) -> Optional[types.ModuleType]:
|
|
@@ -162,7 +166,13 @@ class JacFeature:
|
|
|
162
166
|
@staticmethod
|
|
163
167
|
def ignore(
|
|
164
168
|
walker: WalkerArchitype,
|
|
165
|
-
expr:
|
|
169
|
+
expr: (
|
|
170
|
+
list[NodeArchitype | EdgeArchitype]
|
|
171
|
+
| list[NodeArchitype]
|
|
172
|
+
| list[EdgeArchitype]
|
|
173
|
+
| NodeArchitype
|
|
174
|
+
| EdgeArchitype
|
|
175
|
+
),
|
|
166
176
|
) -> bool: # noqa: ANN401
|
|
167
177
|
"""Jac's ignore stmt feature."""
|
|
168
178
|
return pm.hook.ignore(walker=walker, expr=expr)
|
|
@@ -170,7 +180,13 @@ class JacFeature:
|
|
|
170
180
|
@staticmethod
|
|
171
181
|
def visit_node(
|
|
172
182
|
walker: WalkerArchitype,
|
|
173
|
-
expr:
|
|
183
|
+
expr: (
|
|
184
|
+
list[NodeArchitype | EdgeArchitype]
|
|
185
|
+
| list[NodeArchitype]
|
|
186
|
+
| list[EdgeArchitype]
|
|
187
|
+
| NodeArchitype
|
|
188
|
+
| EdgeArchitype
|
|
189
|
+
),
|
|
174
190
|
) -> bool: # noqa: ANN401
|
|
175
191
|
"""Jac's visit stmt feature."""
|
|
176
192
|
return pm.hook.visit_node(walker=walker, expr=expr)
|
|
@@ -247,7 +263,7 @@ class JacFeature:
|
|
|
247
263
|
@staticmethod
|
|
248
264
|
def build_edge(
|
|
249
265
|
is_undirected: bool,
|
|
250
|
-
conn_type: Optional[Type[EdgeArchitype]],
|
|
266
|
+
conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
|
|
251
267
|
conn_assign: Optional[tuple[tuple, tuple]],
|
|
252
268
|
) -> Callable[[], EdgeArchitype]:
|
|
253
269
|
"""Jac's root getter."""
|
jaclang/plugin/spec.py
CHANGED
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import types
|
|
6
|
-
from dataclasses import dataclass
|
|
7
6
|
from typing import Any, Callable, Optional, TYPE_CHECKING, Type, TypeVar, Union
|
|
8
7
|
|
|
9
8
|
from jaclang.compiler.absyntree import Module
|
|
10
9
|
|
|
11
10
|
if TYPE_CHECKING:
|
|
12
|
-
from jaclang.core.
|
|
11
|
+
from jaclang.core.constructs import EdgeArchitype, NodeArchitype
|
|
13
12
|
from jaclang.plugin.default import (
|
|
14
13
|
Architype,
|
|
15
14
|
EdgeDir,
|
|
16
15
|
ExecutionContext,
|
|
17
16
|
WalkerArchitype,
|
|
18
17
|
Root,
|
|
18
|
+
DSFunc,
|
|
19
19
|
)
|
|
20
20
|
from jaclang.core.memory import Memory
|
|
21
21
|
|
|
@@ -26,20 +26,6 @@ hookspec = pluggy.HookspecMarker("jac")
|
|
|
26
26
|
T = TypeVar("T")
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
# TODO: DSFunc should be moved into jaclang/core
|
|
30
|
-
@dataclass(eq=False)
|
|
31
|
-
class DSFunc:
|
|
32
|
-
"""Data Spatial Function."""
|
|
33
|
-
|
|
34
|
-
name: str
|
|
35
|
-
trigger: type | types.UnionType | tuple[type | types.UnionType, ...] | None
|
|
36
|
-
func: Callable[[Any, Any], Any] | None = None
|
|
37
|
-
|
|
38
|
-
def resolve(self, cls: type) -> None:
|
|
39
|
-
"""Resolve the function."""
|
|
40
|
-
self.func = getattr(cls, self.name)
|
|
41
|
-
|
|
42
|
-
|
|
43
29
|
class JacFeatureSpec:
|
|
44
30
|
"""Jac Feature."""
|
|
45
31
|
|
|
@@ -113,7 +99,7 @@ class JacFeatureSpec:
|
|
|
113
99
|
cachable: bool,
|
|
114
100
|
mdl_alias: Optional[str],
|
|
115
101
|
override_name: Optional[str],
|
|
116
|
-
mod_bundle: Optional[Module],
|
|
102
|
+
mod_bundle: Optional[Module | str],
|
|
117
103
|
lng: Optional[str],
|
|
118
104
|
items: Optional[dict[str, Union[str, bool]]],
|
|
119
105
|
) -> Optional[types.ModuleType]:
|
|
@@ -167,7 +153,13 @@ class JacFeatureSpec:
|
|
|
167
153
|
@hookspec(firstresult=True)
|
|
168
154
|
def ignore(
|
|
169
155
|
walker: WalkerArchitype,
|
|
170
|
-
expr:
|
|
156
|
+
expr: (
|
|
157
|
+
list[NodeArchitype | EdgeArchitype]
|
|
158
|
+
| list[NodeArchitype]
|
|
159
|
+
| list[EdgeArchitype]
|
|
160
|
+
| NodeArchitype
|
|
161
|
+
| EdgeArchitype
|
|
162
|
+
),
|
|
171
163
|
) -> bool:
|
|
172
164
|
"""Jac's ignore stmt feature."""
|
|
173
165
|
raise NotImplementedError
|
|
@@ -176,7 +168,13 @@ class JacFeatureSpec:
|
|
|
176
168
|
@hookspec(firstresult=True)
|
|
177
169
|
def visit_node(
|
|
178
170
|
walker: WalkerArchitype,
|
|
179
|
-
expr:
|
|
171
|
+
expr: (
|
|
172
|
+
list[NodeArchitype | EdgeArchitype]
|
|
173
|
+
| list[NodeArchitype]
|
|
174
|
+
| list[EdgeArchitype]
|
|
175
|
+
| NodeArchitype
|
|
176
|
+
| EdgeArchitype
|
|
177
|
+
),
|
|
180
178
|
) -> bool: # noqa: ANN401
|
|
181
179
|
"""Jac's visit stmt feature."""
|
|
182
180
|
raise NotImplementedError
|
|
@@ -248,7 +246,7 @@ class JacFeatureSpec:
|
|
|
248
246
|
@hookspec(firstresult=True)
|
|
249
247
|
def build_edge(
|
|
250
248
|
is_undirected: bool,
|
|
251
|
-
conn_type: Optional[Type[EdgeArchitype]],
|
|
249
|
+
conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
|
|
252
250
|
conn_assign: Optional[tuple[tuple, tuple]],
|
|
253
251
|
) -> Callable[[], EdgeArchitype]:
|
|
254
252
|
"""Jac's root getter."""
|