jaclang 0.7.2__py3-none-any.whl → 0.7.6__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 +499 -294
- 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 +28 -14
- jaclang/compiler/passes/main/def_use_pass.py +59 -40
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +65 -43
- jaclang/compiler/passes/main/import_pass.py +8 -6
- jaclang/compiler/passes/main/pyast_gen_pass.py +97 -42
- jaclang/compiler/passes/main/pyast_load_pass.py +47 -12
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +19 -10
- 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/type_check_pass.py +2 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +30 -9
- 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/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/transform.py +2 -4
- jaclang/{core/registry.py → compiler/semtable.py} +1 -3
- jaclang/compiler/symtable.py +142 -101
- jaclang/compiler/tests/test_parser.py +2 -2
- jaclang/core/aott.py +15 -11
- jaclang/core/{construct.py → architype.py} +25 -240
- jaclang/core/constructs.py +44 -0
- jaclang/core/context.py +157 -0
- jaclang/core/importer.py +18 -9
- jaclang/core/memory.py +99 -0
- jaclang/core/test.py +90 -0
- jaclang/core/utils.py +2 -2
- jaclang/langserve/engine.py +127 -50
- jaclang/langserve/server.py +34 -61
- 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.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 +93 -18
- jaclang/langserve/utils.py +124 -10
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +23 -9
- jaclang/plugin/feature.py +25 -7
- jaclang/plugin/spec.py +18 -20
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/abc.jac +16 -12
- jaclang/tests/fixtures/aott_raise.jac +1 -1
- jaclang/tests/fixtures/byllmissue.jac +9 -0
- jaclang/tests/fixtures/edgetypeissue.jac +10 -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/maxfail_run_test.jac +17 -5
- jaclang/tests/fixtures/run_test.jac +17 -5
- 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 +1 -1
- jaclang/tests/test_bugs.py +19 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +161 -96
- jaclang/tests/test_reference.py +1 -1
- jaclang/utils/lang_tools.py +5 -4
- jaclang/utils/test.py +2 -1
- jaclang/utils/treeprinter.py +22 -8
- {jaclang-0.7.2.dist-info → jaclang-0.7.6.dist-info}/METADATA +1 -1
- {jaclang-0.7.2.dist-info → jaclang-0.7.6.dist-info}/RECORD +83 -80
- jaclang/core/llms/__init__.py +0 -20
- jaclang/core/llms/anthropic.py +0 -90
- jaclang/core/llms/base.py +0 -206
- jaclang/core/llms/groq.py +0 -70
- jaclang/core/llms/huggingface.py +0 -76
- jaclang/core/llms/ollama.py +0 -81
- jaclang/core/llms/openai.py +0 -65
- jaclang/core/llms/togetherai.py +0 -63
- jaclang/core/llms/utils.py +0 -9
- {jaclang-0.7.2.dist-info → jaclang-0.7.6.dist-info}/WHEEL +0 -0
- {jaclang-0.7.2.dist-info → jaclang-0.7.6.dist-info}/entry_points.txt +0 -0
|
@@ -59,15 +59,15 @@ print(f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}
|
|
|
59
59
|
glob expected_area = 78.53981633974483;
|
|
60
60
|
|
|
61
61
|
test calc_area {
|
|
62
|
-
check
|
|
62
|
+
check assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
test circle_area {
|
|
66
66
|
c = Circle(RAD);
|
|
67
|
-
check
|
|
67
|
+
check assertAlmostEqual(c.area(), expected_area);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
test circle_type {
|
|
71
71
|
c = Circle(RAD);
|
|
72
|
-
check
|
|
72
|
+
check assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
73
73
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
glob expected_area = 78.53981633974483;
|
|
2
|
+
|
|
3
|
+
test a1 {
|
|
4
|
+
check assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
test a2 {
|
|
8
|
+
c = Circle(RAD);
|
|
9
|
+
check assertAlmostEqual(c.area(), expected_area);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
test a3 {
|
|
13
|
+
c = Circle(RAD);
|
|
14
|
+
check assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
15
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import:py os;
|
|
2
|
+
import:py from math, sqrt as square_root;
|
|
3
|
+
import:py datetime as dt;
|
|
4
|
+
import:jac from base_module_structure, add as adsd, subtract,x,Color as clr;
|
|
5
|
+
import:jac base_module_structure as base_module_structure;
|
|
6
|
+
import:py from py_import,add1 as ss, sub1 as subtract1,apple,Orange1;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""This is a helper file."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def add1():
|
|
5
|
+
return 1 + 1
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def sub1():
|
|
9
|
+
return 1 - 1
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# classes
|
|
13
|
+
class Orange1:
|
|
14
|
+
def __init__(self):
|
|
15
|
+
self.orange = 1
|
|
16
|
+
|
|
17
|
+
def get_orange(self):
|
|
18
|
+
return self.orange
|
|
19
|
+
|
|
20
|
+
def set_orange(self, orange):
|
|
21
|
+
self.orange = orange
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# variables
|
|
25
|
+
orange2 = 1
|
|
26
|
+
apple = 1
|
|
@@ -63,10 +63,10 @@ class TestJacLangServer(TestCase):
|
|
|
63
63
|
self.assertEqual(len(lsp.modules), 1)
|
|
64
64
|
self.assertEqual(lsp.modules[circle_file].diagnostics[0].range.start.line, 22)
|
|
65
65
|
lsp.deep_check(circle_file)
|
|
66
|
-
self.assertEqual(len(lsp.modules), 1)
|
|
66
|
+
# self.assertEqual(len(lsp.modules), 1)
|
|
67
67
|
self.assertEqual(lsp.modules[circle_file].diagnostics[0].range.start.line, 22)
|
|
68
68
|
lsp.type_check(circle_file)
|
|
69
|
-
self.assertEqual(len(lsp.modules), 1)
|
|
69
|
+
# self.assertEqual(len(lsp.modules), 1)
|
|
70
70
|
self.assertEqual(lsp.modules[circle_file].diagnostics[0].range.start.line, 22)
|
|
71
71
|
|
|
72
72
|
def test_impl_stay_connected(self) -> None:
|
|
@@ -88,7 +88,7 @@ class TestJacLangServer(TestCase):
|
|
|
88
88
|
"Circle class inherits from Shape.",
|
|
89
89
|
lsp.get_hover_info(circle_file, pos).contents.value,
|
|
90
90
|
)
|
|
91
|
-
lsp.type_check(circle_impl_file
|
|
91
|
+
lsp.type_check(circle_impl_file)
|
|
92
92
|
pos = lspt.Position(8, 11)
|
|
93
93
|
self.assertIn(
|
|
94
94
|
"ability) calculate_area: float",
|
|
@@ -105,9 +105,9 @@ class TestJacLangServer(TestCase):
|
|
|
105
105
|
circle_impl_file = uris.from_fs_path(
|
|
106
106
|
self.fixture_abs_path("circle_pure.impl.jac")
|
|
107
107
|
)
|
|
108
|
-
lsp.quick_check(circle_impl_file
|
|
109
|
-
lsp.deep_check(circle_impl_file
|
|
110
|
-
lsp.type_check(circle_impl_file
|
|
108
|
+
lsp.quick_check(circle_impl_file)
|
|
109
|
+
lsp.deep_check(circle_impl_file)
|
|
110
|
+
lsp.type_check(circle_impl_file)
|
|
111
111
|
pos = lspt.Position(8, 11)
|
|
112
112
|
self.assertIn(
|
|
113
113
|
"ability) calculate_area: float",
|
|
@@ -143,16 +143,7 @@ class TestJacLangServer(TestCase):
|
|
|
143
143
|
lsp.quick_check(circle_file)
|
|
144
144
|
lsp.deep_check(circle_file)
|
|
145
145
|
lsp.type_check(circle_file)
|
|
146
|
-
|
|
147
|
-
"DocumentSymbol(name='calculate_area', kind=<SymbolKind.Function: 12>, range=9:0-9:43, "
|
|
148
|
-
"selection_range=9:0-9:43, detail=None, tags=None, deprecated=None, children=["
|
|
149
|
-
"DocumentSymbol(name='radius', kind=<SymbolKind.Variable: 13>, range=9:1-9:14, "
|
|
150
|
-
"selection_range=9:1-9:14, detail=None, tags=None, deprecated=None, children=[])])"
|
|
151
|
-
)
|
|
152
|
-
self.assertEqual(
|
|
153
|
-
expected_string, str((lsp.get_document_symbols(circle_file))[6])
|
|
154
|
-
)
|
|
155
|
-
self.assertEqual(10, len(lsp.get_document_symbols(circle_file)))
|
|
146
|
+
self.assertEqual(8, len(lsp.get_document_symbols(circle_file)))
|
|
156
147
|
|
|
157
148
|
def test_go_to_definition(self) -> None:
|
|
158
149
|
"""Test that the go to definition is correct."""
|
|
@@ -169,7 +160,7 @@ class TestJacLangServer(TestCase):
|
|
|
169
160
|
str(lsp.get_definition(circle_file, lspt.Position(9, 16))),
|
|
170
161
|
)
|
|
171
162
|
self.assertIn(
|
|
172
|
-
"fixtures/circle_pure.jac:
|
|
163
|
+
"fixtures/circle_pure.jac:13:11-13:16",
|
|
173
164
|
str(lsp.get_definition(circle_file, lspt.Position(20, 17))),
|
|
174
165
|
)
|
|
175
166
|
|
|
@@ -186,6 +177,90 @@ class TestJacLangServer(TestCase):
|
|
|
186
177
|
lsp.deep_check(guess_game_file)
|
|
187
178
|
lsp.type_check(guess_game_file)
|
|
188
179
|
self.assertIn(
|
|
189
|
-
"guess_game4.jac:27:
|
|
180
|
+
"guess_game4.jac:27:8-27:21",
|
|
190
181
|
str(lsp.get_definition(guess_game_file, lspt.Position(46, 45))),
|
|
191
182
|
)
|
|
183
|
+
|
|
184
|
+
def test_test_annex(self) -> None:
|
|
185
|
+
"""Test that the server doesn't run if there is a syntax error."""
|
|
186
|
+
lsp = JacLangServer()
|
|
187
|
+
# Set up the workspace path to "fixtures/"
|
|
188
|
+
workspace_path = self.fixture_abs_path("")
|
|
189
|
+
workspace = Workspace(workspace_path, lsp)
|
|
190
|
+
lsp.lsp._workspace = workspace
|
|
191
|
+
circle_file = uris.from_fs_path(self.fixture_abs_path("circle_pure.test.jac"))
|
|
192
|
+
lsp.quick_check(circle_file)
|
|
193
|
+
lsp.deep_check(circle_file)
|
|
194
|
+
lsp.type_check(circle_file)
|
|
195
|
+
pos = lspt.Position(13, 29)
|
|
196
|
+
self.assertIn(
|
|
197
|
+
"shape_type: circle_pure.ShapeType",
|
|
198
|
+
lsp.get_hover_info(circle_file, pos).contents.value,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def test_go_to_defintion_import(self) -> None:
|
|
202
|
+
"""Test that the go to definition is correct."""
|
|
203
|
+
lsp = JacLangServer()
|
|
204
|
+
workspace_path = self.fixture_abs_path("")
|
|
205
|
+
workspace = Workspace(workspace_path, lsp)
|
|
206
|
+
lsp.lsp._workspace = workspace
|
|
207
|
+
import_file = uris.from_fs_path(
|
|
208
|
+
self.fixture_abs_path("import_include_statements.jac")
|
|
209
|
+
)
|
|
210
|
+
lsp.quick_check(import_file)
|
|
211
|
+
lsp.deep_check(import_file)
|
|
212
|
+
lsp.type_check(import_file)
|
|
213
|
+
positions = [
|
|
214
|
+
(2, 16, "datetime.py:0:0-0:0"),
|
|
215
|
+
(3, 17, "base_module_structure.jac:0:0-0:0"),
|
|
216
|
+
(3, 74, "base_module_structure.jac:23:0-23:5"),
|
|
217
|
+
(5, 65, "py_import.py:12:0-20:5"),
|
|
218
|
+
(5, 35, "py_import.py:3:0-4:5"),
|
|
219
|
+
]
|
|
220
|
+
|
|
221
|
+
for line, char, expected in positions:
|
|
222
|
+
with self.subTest(line=line, char=char):
|
|
223
|
+
self.assertIn(
|
|
224
|
+
expected,
|
|
225
|
+
str(lsp.get_definition(import_file, lspt.Position(line, char))),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
def test_sem_tokens(self) -> None:
|
|
229
|
+
"""Test that the Semantic Tokens are generated correctly."""
|
|
230
|
+
lsp = JacLangServer()
|
|
231
|
+
workspace_path = self.fixture_abs_path("")
|
|
232
|
+
workspace = Workspace(workspace_path, lsp)
|
|
233
|
+
lsp.lsp._workspace = workspace
|
|
234
|
+
circle_file = uris.from_fs_path(self.fixture_abs_path("circle.jac"))
|
|
235
|
+
lsp.quick_check(circle_file)
|
|
236
|
+
lsp.deep_check(circle_file)
|
|
237
|
+
lsp.type_check(circle_file)
|
|
238
|
+
sem_list = lsp.get_semantic_tokens(circle_file).data
|
|
239
|
+
expected_counts = [
|
|
240
|
+
("<JacSemTokenType.VARIABLE: 8>, <JacSemTokenModifier.READONLY: 4>", 206),
|
|
241
|
+
(
|
|
242
|
+
"<JacSemTokenType.PROPERTY: 9>, <JacSemTokenModifier.DEFINITION: 2>,",
|
|
243
|
+
112,
|
|
244
|
+
),
|
|
245
|
+
(
|
|
246
|
+
"<JacSemTokenType.PARAMETER: 7>, <JacSemTokenModifier.DECLARATION: 1>,",
|
|
247
|
+
56,
|
|
248
|
+
),
|
|
249
|
+
(
|
|
250
|
+
"<JacSemTokenType.FUNCTION: 12>, <JacSemTokenModifier.DECLARATION: 1>,",
|
|
251
|
+
25,
|
|
252
|
+
),
|
|
253
|
+
("<JacSemTokenType.METHOD: 13>, <JacSemTokenModifier.DECLARATION: 1>", 12),
|
|
254
|
+
("<JacSemTokenType.ENUM: 3>, <JacSemTokenModifier.DECLARATION: 1>,", 37),
|
|
255
|
+
("<JacSemTokenType.CLASS: 2>, <JacSemTokenModifier.DECLARATION: ", 162),
|
|
256
|
+
(
|
|
257
|
+
"<JacSemTokenType.NAMESPACE: 0>, <JacSemTokenModifier.DEFINITION: 2>,",
|
|
258
|
+
10,
|
|
259
|
+
),
|
|
260
|
+
("0, 0, 4,", 22),
|
|
261
|
+
("0, 0, 3,", 192),
|
|
262
|
+
("0, 0, 6, ", 65),
|
|
263
|
+
(" 0, 7, 3,", 3),
|
|
264
|
+
]
|
|
265
|
+
for token_type, expected_count in expected_counts:
|
|
266
|
+
self.assertEqual(str(sem_list).count(token_type), expected_count)
|
jaclang/langserve/utils.py
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import builtins
|
|
5
|
+
import importlib.util
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
5
8
|
from functools import wraps
|
|
6
9
|
from typing import Any, Awaitable, Callable, Coroutine, Optional, ParamSpec, TypeVar
|
|
7
10
|
|
|
8
11
|
import jaclang.compiler.absyntree as ast
|
|
9
12
|
from jaclang.compiler.codeloc import CodeLocInfo
|
|
10
13
|
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
14
|
+
from jaclang.utils.helpers import import_target_to_relative_path
|
|
11
15
|
|
|
12
16
|
import lsprotocol.types as lspt
|
|
13
17
|
|
|
@@ -68,7 +72,7 @@ def find_deepest_symbol_node_at_pos(
|
|
|
68
72
|
if isinstance(node, ast.AstSymbolNode):
|
|
69
73
|
last_symbol_node = node
|
|
70
74
|
|
|
71
|
-
for child in node.kid:
|
|
75
|
+
for child in [i for i in node.kid if i.loc.mod_path == node.loc.mod_path]:
|
|
72
76
|
if position_within_node(child, line, character):
|
|
73
77
|
deeper_node = find_deepest_symbol_node_at_pos(child, line, character)
|
|
74
78
|
if deeper_node is not None:
|
|
@@ -106,23 +110,27 @@ def collect_symbols(node: SymbolTable) -> list[lspt.DocumentSymbol]:
|
|
|
106
110
|
return symbols
|
|
107
111
|
|
|
108
112
|
for key, item in node.tab.items():
|
|
109
|
-
if
|
|
110
|
-
|
|
111
|
-
|
|
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
|
+
):
|
|
112
118
|
continue
|
|
113
119
|
else:
|
|
114
120
|
|
|
115
|
-
pos = create_range(item.
|
|
121
|
+
pos = create_range(item.decl.loc)
|
|
116
122
|
symbol = lspt.DocumentSymbol(
|
|
117
123
|
name=key,
|
|
118
|
-
kind=kind_map(item.
|
|
124
|
+
kind=kind_map(item.decl),
|
|
119
125
|
range=pos,
|
|
120
126
|
selection_range=pos,
|
|
121
127
|
children=[],
|
|
122
128
|
)
|
|
123
129
|
symbols.append(symbol)
|
|
124
130
|
|
|
125
|
-
for sub_tab in
|
|
131
|
+
for sub_tab in [
|
|
132
|
+
i for i in node.kid if i.owner.loc.mod_path == node.owner.loc.mod_path
|
|
133
|
+
]:
|
|
126
134
|
sub_symbols = collect_symbols(sub_tab)
|
|
127
135
|
|
|
128
136
|
if isinstance(
|
|
@@ -146,7 +154,7 @@ def collect_symbols(node: SymbolTable) -> list[lspt.DocumentSymbol]:
|
|
|
146
154
|
|
|
147
155
|
def owner_sym(table: SymbolTable) -> Optional[Symbol]:
|
|
148
156
|
"""Get owner sym."""
|
|
149
|
-
if table.
|
|
157
|
+
if table.parent and isinstance(table.owner, ast.AstSymbolNode):
|
|
150
158
|
return table.parent.lookup(table.owner.sym_name)
|
|
151
159
|
return None
|
|
152
160
|
|
|
@@ -154,8 +162,14 @@ def owner_sym(table: SymbolTable) -> Optional[Symbol]:
|
|
|
154
162
|
def create_range(loc: CodeLocInfo) -> lspt.Range:
|
|
155
163
|
"""Create an lspt.Range from a location object."""
|
|
156
164
|
return lspt.Range(
|
|
157
|
-
start=lspt.Position(
|
|
158
|
-
|
|
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
|
+
),
|
|
159
173
|
)
|
|
160
174
|
|
|
161
175
|
|
|
@@ -178,3 +192,103 @@ def kind_map(sub_tab: ast.AstNode) -> lspt.SymbolKind:
|
|
|
178
192
|
)
|
|
179
193
|
)
|
|
180
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
|
@@ -14,6 +14,7 @@ from typing import Any, Callable, Optional, Type, Union
|
|
|
14
14
|
|
|
15
15
|
from jaclang.compiler.absyntree import Module
|
|
16
16
|
from jaclang.compiler.constant import EdgeDir, colors
|
|
17
|
+
from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
|
|
17
18
|
from jaclang.core.aott import (
|
|
18
19
|
aott_raise,
|
|
19
20
|
extract_non_primary_type,
|
|
@@ -21,7 +22,7 @@ from jaclang.core.aott import (
|
|
|
21
22
|
get_info_types,
|
|
22
23
|
get_input_information,
|
|
23
24
|
)
|
|
24
|
-
from jaclang.core.
|
|
25
|
+
from jaclang.core.constructs import (
|
|
25
26
|
Architype,
|
|
26
27
|
DSFunc,
|
|
27
28
|
EdgeAnchor,
|
|
@@ -39,7 +40,6 @@ from jaclang.core.construct import (
|
|
|
39
40
|
exec_context,
|
|
40
41
|
)
|
|
41
42
|
from jaclang.core.importer import jac_importer
|
|
42
|
-
from jaclang.core.registry import SemInfo, SemRegistry, SemScope
|
|
43
43
|
from jaclang.core.utils import traverse_graph
|
|
44
44
|
from jaclang.plugin.feature import JacFeature as Jac
|
|
45
45
|
from jaclang.plugin.spec import T
|
|
@@ -110,7 +110,9 @@ class JacFeatureDefaults:
|
|
|
110
110
|
"""Create a new architype."""
|
|
111
111
|
for i in on_entry + on_exit:
|
|
112
112
|
i.resolve(cls)
|
|
113
|
-
if not
|
|
113
|
+
if not hasattr(cls, "_jac_entry_funcs_") or not hasattr(
|
|
114
|
+
cls, "_jac_exit_funcs_"
|
|
115
|
+
):
|
|
114
116
|
# Saving the module path and reassign it after creating cls
|
|
115
117
|
# So the jac modules are part of the correct module
|
|
116
118
|
cur_module = cls.__module__
|
|
@@ -216,7 +218,7 @@ class JacFeatureDefaults:
|
|
|
216
218
|
cachable: bool,
|
|
217
219
|
mdl_alias: Optional[str],
|
|
218
220
|
override_name: Optional[str],
|
|
219
|
-
mod_bundle: Optional[Module],
|
|
221
|
+
mod_bundle: Optional[Module | str],
|
|
220
222
|
lng: Optional[str],
|
|
221
223
|
items: Optional[dict[str, Union[str, bool]]],
|
|
222
224
|
) -> Optional[types.ModuleType]:
|
|
@@ -335,7 +337,13 @@ class JacFeatureDefaults:
|
|
|
335
337
|
@hookimpl
|
|
336
338
|
def ignore(
|
|
337
339
|
walker: WalkerArchitype,
|
|
338
|
-
expr:
|
|
340
|
+
expr: (
|
|
341
|
+
list[NodeArchitype | EdgeArchitype]
|
|
342
|
+
| list[NodeArchitype]
|
|
343
|
+
| list[EdgeArchitype]
|
|
344
|
+
| NodeArchitype
|
|
345
|
+
| EdgeArchitype
|
|
346
|
+
),
|
|
339
347
|
) -> bool:
|
|
340
348
|
"""Jac's ignore stmt feature."""
|
|
341
349
|
return walker._jac_.ignore_node(expr)
|
|
@@ -344,7 +352,13 @@ class JacFeatureDefaults:
|
|
|
344
352
|
@hookimpl
|
|
345
353
|
def visit_node(
|
|
346
354
|
walker: WalkerArchitype,
|
|
347
|
-
expr:
|
|
355
|
+
expr: (
|
|
356
|
+
list[NodeArchitype | EdgeArchitype]
|
|
357
|
+
| list[NodeArchitype]
|
|
358
|
+
| list[EdgeArchitype]
|
|
359
|
+
| NodeArchitype
|
|
360
|
+
| EdgeArchitype
|
|
361
|
+
),
|
|
348
362
|
) -> bool:
|
|
349
363
|
"""Jac's visit stmt feature."""
|
|
350
364
|
if isinstance(walker, WalkerArchitype):
|
|
@@ -481,14 +495,14 @@ class JacFeatureDefaults:
|
|
|
481
495
|
@hookimpl
|
|
482
496
|
def build_edge(
|
|
483
497
|
is_undirected: bool,
|
|
484
|
-
conn_type: Optional[Type[EdgeArchitype]],
|
|
498
|
+
conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
|
|
485
499
|
conn_assign: Optional[tuple[tuple, tuple]],
|
|
486
500
|
) -> Callable[[], EdgeArchitype]:
|
|
487
501
|
"""Jac's root getter."""
|
|
488
502
|
conn_type = conn_type if conn_type else GenericEdge
|
|
489
503
|
|
|
490
504
|
def builder() -> EdgeArchitype:
|
|
491
|
-
edge = conn_type()
|
|
505
|
+
edge = conn_type() if isinstance(conn_type, type) else conn_type
|
|
492
506
|
edge._jac_.is_undirected = is_undirected
|
|
493
507
|
if conn_assign:
|
|
494
508
|
for fld, val in zip(conn_assign[0], conn_assign[1]):
|
|
@@ -649,7 +663,7 @@ class JacFeatureDefaults:
|
|
|
649
663
|
|
|
650
664
|
inputs_information = get_input_information(inputs, type_collector)
|
|
651
665
|
|
|
652
|
-
output_information = f"{outputs[0]} ({outputs[1]})"
|
|
666
|
+
output_information = f"{outputs[0]} ({outputs[1]})".strip()
|
|
653
667
|
type_collector.extend(extract_non_primary_type(outputs[1]))
|
|
654
668
|
output_type_explanations = "\n".join(
|
|
655
669
|
list(
|
jaclang/plugin/feature.py
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
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, TypeAlias, Union
|
|
7
7
|
|
|
8
8
|
from jaclang.compiler.absyntree import Module
|
|
9
|
-
from jaclang.core.
|
|
9
|
+
from jaclang.core.constructs import (
|
|
10
10
|
Architype,
|
|
11
11
|
EdgeArchitype,
|
|
12
12
|
Memory,
|
|
@@ -31,7 +31,13 @@ class JacFeature:
|
|
|
31
31
|
|
|
32
32
|
import abc
|
|
33
33
|
from jaclang.compiler.constant import EdgeDir
|
|
34
|
-
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
|
|
35
41
|
|
|
36
42
|
@staticmethod
|
|
37
43
|
def context(session: str = "") -> ExecutionContext:
|
|
@@ -96,7 +102,7 @@ class JacFeature:
|
|
|
96
102
|
cachable: bool = True,
|
|
97
103
|
mdl_alias: Optional[str] = None,
|
|
98
104
|
override_name: Optional[str] = None,
|
|
99
|
-
mod_bundle: Optional[Module] = None,
|
|
105
|
+
mod_bundle: Optional[Module | str] = None,
|
|
100
106
|
lng: Optional[str] = "jac",
|
|
101
107
|
items: Optional[dict[str, Union[str, bool]]] = None,
|
|
102
108
|
) -> Optional[types.ModuleType]:
|
|
@@ -160,7 +166,13 @@ class JacFeature:
|
|
|
160
166
|
@staticmethod
|
|
161
167
|
def ignore(
|
|
162
168
|
walker: WalkerArchitype,
|
|
163
|
-
expr:
|
|
169
|
+
expr: (
|
|
170
|
+
list[NodeArchitype | EdgeArchitype]
|
|
171
|
+
| list[NodeArchitype]
|
|
172
|
+
| list[EdgeArchitype]
|
|
173
|
+
| NodeArchitype
|
|
174
|
+
| EdgeArchitype
|
|
175
|
+
),
|
|
164
176
|
) -> bool: # noqa: ANN401
|
|
165
177
|
"""Jac's ignore stmt feature."""
|
|
166
178
|
return pm.hook.ignore(walker=walker, expr=expr)
|
|
@@ -168,7 +180,13 @@ class JacFeature:
|
|
|
168
180
|
@staticmethod
|
|
169
181
|
def visit_node(
|
|
170
182
|
walker: WalkerArchitype,
|
|
171
|
-
expr:
|
|
183
|
+
expr: (
|
|
184
|
+
list[NodeArchitype | EdgeArchitype]
|
|
185
|
+
| list[NodeArchitype]
|
|
186
|
+
| list[EdgeArchitype]
|
|
187
|
+
| NodeArchitype
|
|
188
|
+
| EdgeArchitype
|
|
189
|
+
),
|
|
172
190
|
) -> bool: # noqa: ANN401
|
|
173
191
|
"""Jac's visit stmt feature."""
|
|
174
192
|
return pm.hook.visit_node(walker=walker, expr=expr)
|
|
@@ -245,7 +263,7 @@ class JacFeature:
|
|
|
245
263
|
@staticmethod
|
|
246
264
|
def build_edge(
|
|
247
265
|
is_undirected: bool,
|
|
248
|
-
conn_type: Optional[Type[EdgeArchitype]],
|
|
266
|
+
conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
|
|
249
267
|
conn_assign: Optional[tuple[tuple, tuple]],
|
|
250
268
|
) -> Callable[[], EdgeArchitype]:
|
|
251
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."""
|