jaclang 0.7.5__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.

Files changed (55) hide show
  1. jaclang/compiler/absyntree.py +167 -26
  2. jaclang/compiler/constant.py +98 -2
  3. jaclang/compiler/jac.lark +2 -0
  4. jaclang/compiler/parser.py +4 -0
  5. jaclang/compiler/passes/main/access_modifier_pass.py +5 -3
  6. jaclang/compiler/passes/main/def_impl_match_pass.py +3 -1
  7. jaclang/compiler/passes/main/def_use_pass.py +27 -39
  8. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +34 -12
  9. jaclang/compiler/passes/main/sub_node_tab_pass.py +0 -5
  10. jaclang/compiler/passes/main/sym_tab_build_pass.py +31 -181
  11. jaclang/compiler/passes/tool/tests/fixtures/genai/essay_review.jac +1 -1
  12. jaclang/compiler/passes/tool/tests/fixtures/genai/expert_answer.jac +1 -1
  13. jaclang/compiler/passes/tool/tests/fixtures/genai/joke_gen.jac +1 -1
  14. jaclang/compiler/passes/tool/tests/fixtures/genai/odd_word_out.jac +1 -1
  15. jaclang/compiler/passes/tool/tests/fixtures/genai/personality_finder.jac +1 -1
  16. jaclang/compiler/passes/tool/tests/fixtures/genai/text_to_type.jac +1 -1
  17. jaclang/compiler/passes/tool/tests/fixtures/genai/translator.jac +1 -1
  18. jaclang/compiler/passes/tool/tests/fixtures/genai/wikipedia.jac +1 -1
  19. jaclang/compiler/symtable.py +118 -65
  20. jaclang/core/aott.py +7 -3
  21. jaclang/core/importer.py +1 -1
  22. jaclang/langserve/engine.py +100 -36
  23. jaclang/langserve/server.py +34 -61
  24. jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -0
  25. jaclang/langserve/tests/fixtures/circle_pure.test.jac +15 -0
  26. jaclang/langserve/tests/fixtures/import_include_statements.jac +6 -0
  27. jaclang/langserve/tests/fixtures/py_import.py +26 -0
  28. jaclang/langserve/tests/test_server.py +90 -6
  29. jaclang/langserve/utils.py +114 -4
  30. jaclang/plugin/default.py +2 -2
  31. jaclang/plugin/feature.py +1 -1
  32. jaclang/plugin/spec.py +1 -1
  33. jaclang/tests/fixtures/aott_raise.jac +1 -1
  34. jaclang/tests/fixtures/edgetypeissue.jac +10 -0
  35. jaclang/tests/fixtures/hello.jac +1 -1
  36. jaclang/tests/fixtures/with_llm_function.jac +1 -1
  37. jaclang/tests/fixtures/with_llm_lower.jac +1 -1
  38. jaclang/tests/fixtures/with_llm_method.jac +1 -1
  39. jaclang/tests/fixtures/with_llm_type.jac +1 -1
  40. jaclang/tests/fixtures/with_llm_vision.jac +1 -1
  41. jaclang/tests/test_language.py +106 -96
  42. {jaclang-0.7.5.dist-info → jaclang-0.7.6.dist-info}/METADATA +1 -1
  43. {jaclang-0.7.5.dist-info → jaclang-0.7.6.dist-info}/RECORD +45 -50
  44. jaclang/core/llms/__init__.py +0 -20
  45. jaclang/core/llms/anthropic.py +0 -90
  46. jaclang/core/llms/base.py +0 -206
  47. jaclang/core/llms/groq.py +0 -70
  48. jaclang/core/llms/huggingface.py +0 -76
  49. jaclang/core/llms/ollama.py +0 -81
  50. jaclang/core/llms/openai.py +0 -65
  51. jaclang/core/llms/togetherai.py +0 -63
  52. jaclang/core/llms/utils.py +0 -9
  53. jaclang/tests/fixtures/edgetypetest.jac +0 -16
  54. {jaclang-0.7.5.dist-info → jaclang-0.7.6.dist-info}/WHEEL +0 -0
  55. {jaclang-0.7.5.dist-info → jaclang-0.7.6.dist-info}/entry_points.txt +0 -0
@@ -2,68 +2,37 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import threading
6
5
  from typing import Optional
7
6
 
7
+ from jaclang.compiler.constant import (
8
+ JacSemTokenModifier as SemTokMod,
9
+ JacSemTokenType as SemTokType,
10
+ )
8
11
  from jaclang.langserve.engine import JacLangServer
9
12
  from jaclang.langserve.utils import debounce
10
13
 
11
14
  import lsprotocol.types as lspt
12
15
 
13
16
  server = JacLangServer()
14
- analysis_thread: Optional[threading.Thread] = None
15
- analysis_stop_event = threading.Event()
16
-
17
-
18
- def analyze_and_publish(ls: JacLangServer, uri: str, level: int = 2) -> None:
19
- """Analyze and publish diagnostics."""
20
- global analysis_thread, analysis_stop_event
21
-
22
- def run_analysis() -> None:
23
- ls.quick_check(uri)
24
- ls.push_diagnostics(uri)
25
- if not analysis_stop_event.is_set() and level > 0:
26
- ls.deep_check(uri)
27
- ls.push_diagnostics(uri)
28
- if not analysis_stop_event.is_set() and level > 1:
29
- ls.type_check(uri)
30
- ls.push_diagnostics(uri)
31
-
32
- analysis_thread = threading.Thread(target=run_analysis)
33
- analysis_thread.start()
34
-
35
-
36
- def stop_analysis() -> None:
37
- """Stop analysis."""
38
- global analysis_thread, analysis_stop_event
39
- if analysis_thread is not None:
40
- analysis_stop_event.set()
41
- analysis_thread.join()
42
- analysis_stop_event.clear()
43
17
 
44
18
 
45
19
  @server.feature(lspt.TEXT_DOCUMENT_DID_OPEN)
46
- async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
20
+ @server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
21
+ def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
47
22
  """Check syntax on change."""
48
- stop_analysis()
49
- analyze_and_publish(ls, params.text_document.uri)
23
+ ls.analyze_and_publish(params.text_document.uri)
24
+ # token_params = lspt.SemanticTokensParams(
25
+ # text_document=lspt.TextDocumentIdentifier(uri=params.text_document.uri)
26
+ # )
27
+ # tokens = semantic_tokens_full(ls, token_params)
28
+ # ls.send_notification("textDocument/publishSemanticTokens", tokens)
50
29
 
51
30
 
52
31
  @server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
53
32
  @debounce(0.1)
54
- async def did_change(
55
- ls: JacLangServer, params: lspt.DidChangeTextDocumentParams
56
- ) -> None:
33
+ async def did_change(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
57
34
  """Check syntax on change."""
58
- stop_analysis()
59
- analyze_and_publish(ls, params.text_document.uri)
60
-
61
-
62
- @server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
63
- async def did_save(ls: JacLangServer, params: lspt.DidSaveTextDocumentParams) -> None:
64
- """Check syntax on save."""
65
- stop_analysis()
66
- analyze_and_publish(ls, params.text_document.uri)
35
+ ls.analyze_and_publish(params.text_document.uri, level=0)
67
36
 
68
37
 
69
38
  @server.feature(
@@ -74,11 +43,8 @@ async def did_save(ls: JacLangServer, params: lspt.DidSaveTextDocumentParams) ->
74
43
  ]
75
44
  ),
76
45
  )
77
- async def did_create_files(ls: JacLangServer, params: lspt.CreateFilesParams) -> None:
46
+ def did_create_files(ls: JacLangServer, params: lspt.CreateFilesParams) -> None:
78
47
  """Check syntax on file creation."""
79
- for file in params.files:
80
- ls.quick_check(file.uri)
81
- ls.push_diagnostics(file.uri)
82
48
 
83
49
 
84
50
  @server.feature(
@@ -89,13 +55,12 @@ async def did_create_files(ls: JacLangServer, params: lspt.CreateFilesParams) ->
89
55
  ]
90
56
  ),
91
57
  )
92
- async def did_rename_files(ls: JacLangServer, params: lspt.RenameFilesParams) -> None:
58
+ def did_rename_files(ls: JacLangServer, params: lspt.RenameFilesParams) -> None:
93
59
  """Check syntax on file rename."""
94
60
  new_uris = [file.new_uri for file in params.files]
95
61
  old_uris = [file.old_uri for file in params.files]
96
62
  for i in range(len(new_uris)):
97
63
  ls.rename_module(old_uris[i], new_uris[i])
98
- ls.quick_check(new_uris[i])
99
64
 
100
65
 
101
66
  @server.feature(
@@ -106,7 +71,7 @@ async def did_rename_files(ls: JacLangServer, params: lspt.RenameFilesParams) ->
106
71
  ]
107
72
  ),
108
73
  )
109
- async def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None:
74
+ def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None:
110
75
  """Check syntax on file delete."""
111
76
  for file in params.files:
112
77
  ls.delete_module(file.uri)
@@ -116,9 +81,7 @@ async def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) ->
116
81
  lspt.TEXT_DOCUMENT_COMPLETION,
117
82
  lspt.CompletionOptions(trigger_characters=[".", ":", ""]),
118
83
  )
119
- async def completion(
120
- ls: JacLangServer, params: lspt.CompletionParams
121
- ) -> lspt.CompletionList:
84
+ def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.CompletionList:
122
85
  """Provide completion."""
123
86
  return ls.get_completion(params.text_document.uri, params.position)
124
87
 
@@ -140,25 +103,35 @@ def hover(
140
103
 
141
104
 
142
105
  @server.feature(lspt.TEXT_DOCUMENT_DOCUMENT_SYMBOL)
143
- async def document_symbol(
106
+ def document_symbol(
144
107
  ls: JacLangServer, params: lspt.DocumentSymbolParams
145
108
  ) -> list[lspt.DocumentSymbol]:
146
109
  """Provide document symbols."""
147
- stop_analysis()
148
- analyze_and_publish(ls, params.text_document.uri)
149
110
  return ls.get_document_symbols(params.text_document.uri)
150
111
 
151
112
 
152
113
  @server.feature(lspt.TEXT_DOCUMENT_DEFINITION)
153
- async def definition(
114
+ def definition(
154
115
  ls: JacLangServer, params: lspt.TextDocumentPositionParams
155
116
  ) -> Optional[lspt.Location]:
156
117
  """Provide definition."""
157
- stop_analysis()
158
- analyze_and_publish(ls, params.text_document.uri, level=1)
159
118
  return ls.get_definition(params.text_document.uri, params.position)
160
119
 
161
120
 
121
+ @server.feature(
122
+ lspt.TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
123
+ lspt.SemanticTokensLegend(
124
+ token_types=SemTokType.as_str_list(),
125
+ token_modifiers=SemTokMod.as_str_list(),
126
+ ),
127
+ )
128
+ def semantic_tokens_full(
129
+ ls: JacLangServer, params: lspt.SemanticTokensParams
130
+ ) -> lspt.SemanticTokens:
131
+ """Provide semantic tokens."""
132
+ return ls.get_semantic_tokens(params.text_document.uri)
133
+
134
+
162
135
  def run_lang_server() -> None:
163
136
  """Run the language server."""
164
137
  server.start_io()
@@ -0,0 +1,28 @@
1
+ """A Docstring can be added the head of any module.
2
+
3
+ Any element in the module can also have a docstring.
4
+ If there is only one docstring before the first element,
5
+ it is assumed to be a module docstring.
6
+ """
7
+
8
+ """A docstring for add function"""
9
+ can add(a: int, b: int) -> int {
10
+ return a + b;
11
+ }
12
+ # No docstring for subtract function
13
+
14
+ can subtract(a: int, b: int) -> int {
15
+ return a - b;
16
+ }
17
+
18
+ with entry:__main__ {
19
+ print(add(1, subtract(3, 1)));
20
+ }
21
+
22
+ glob x: int = 10;
23
+
24
+ enum Color {
25
+ RED,
26
+ GREEN,
27
+ BLUE
28
+ }
@@ -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, force=True)
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, force=True)
109
- lsp.deep_check(circle_impl_file, force=True)
110
- lsp.type_check(circle_impl_file, force=True)
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",
@@ -180,3 +180,87 @@ class TestJacLangServer(TestCase):
180
180
  "guess_game4.jac:27:8-27:21",
181
181
  str(lsp.get_definition(guess_game_file, lspt.Position(46, 45))),
182
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)
@@ -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:
@@ -150,7 +154,7 @@ def collect_symbols(node: SymbolTable) -> list[lspt.DocumentSymbol]:
150
154
 
151
155
  def owner_sym(table: SymbolTable) -> Optional[Symbol]:
152
156
  """Get owner sym."""
153
- if table.has_parent() and isinstance(table.owner, ast.AstSymbolNode):
157
+ if table.parent and isinstance(table.owner, ast.AstSymbolNode):
154
158
  return table.parent.lookup(table.owner.sym_name)
155
159
  return None
156
160
 
@@ -158,8 +162,14 @@ def owner_sym(table: SymbolTable) -> Optional[Symbol]:
158
162
  def create_range(loc: CodeLocInfo) -> lspt.Range:
159
163
  """Create an lspt.Range from a location object."""
160
164
  return lspt.Range(
161
- start=lspt.Position(line=loc.first_line - 1, character=loc.col_start - 1),
162
- end=lspt.Position(line=loc.last_line - 1, character=loc.col_end - 1),
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
+ ),
163
173
  )
164
174
 
165
175
 
@@ -182,3 +192,103 @@ def kind_map(sub_tab: ast.AstNode) -> lspt.SymbolKind:
182
192
  )
183
193
  )
184
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/default.py CHANGED
@@ -495,14 +495,14 @@ class JacFeatureDefaults:
495
495
  @hookimpl
496
496
  def build_edge(
497
497
  is_undirected: bool,
498
- conn_type: Optional[Type[EdgeArchitype]],
498
+ conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
499
499
  conn_assign: Optional[tuple[tuple, tuple]],
500
500
  ) -> Callable[[], EdgeArchitype]:
501
501
  """Jac's root getter."""
502
502
  conn_type = conn_type if conn_type else GenericEdge
503
503
 
504
504
  def builder() -> EdgeArchitype:
505
- edge = conn_type()
505
+ edge = conn_type() if isinstance(conn_type, type) else conn_type
506
506
  edge._jac_.is_undirected = is_undirected
507
507
  if conn_assign:
508
508
  for fld, val in zip(conn_assign[0], conn_assign[1]):
jaclang/plugin/feature.py CHANGED
@@ -263,7 +263,7 @@ class JacFeature:
263
263
  @staticmethod
264
264
  def build_edge(
265
265
  is_undirected: bool,
266
- conn_type: Optional[Type[EdgeArchitype]],
266
+ conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
267
267
  conn_assign: Optional[tuple[tuple, tuple]],
268
268
  ) -> Callable[[], EdgeArchitype]:
269
269
  """Jac's root getter."""
jaclang/plugin/spec.py CHANGED
@@ -246,7 +246,7 @@ class JacFeatureSpec:
246
246
  @hookspec(firstresult=True)
247
247
  def build_edge(
248
248
  is_undirected: bool,
249
- conn_type: Optional[Type[EdgeArchitype]],
249
+ conn_type: Optional[Type[EdgeArchitype] | EdgeArchitype],
250
250
  conn_assign: Optional[tuple[tuple, tuple]],
251
251
  ) -> Callable[[], EdgeArchitype]:
252
252
  """Jac's root getter."""
@@ -1,4 +1,4 @@
1
- import:py from jaclang.core.llms, BaseLLM;
1
+ import:py from mtllm.llms.base, BaseLLM;
2
2
 
3
3
  obj model:BaseLLM: {
4
4
  can __infer__(meaning_in: str, **kwargs: dict) {
@@ -0,0 +1,10 @@
1
+ node x {}
2
+
3
+ edge e {
4
+ has name: str;
5
+ }
6
+
7
+ with entry {
8
+ nodes = root +:e(name="hello"):+> x();
9
+ print(nodes);
10
+ }
@@ -2,4 +2,4 @@
2
2
 
3
3
  with entry {
4
4
  "Hello World!" |> print;
5
- }
5
+ }
@@ -1,4 +1,4 @@
1
- import:py from jaclang.core.llms, BaseLLM;
1
+ import:py from mtllm.llms, BaseLLM;
2
2
 
3
3
  obj model:BaseLLM: {
4
4
  can init {
@@ -1,4 +1,4 @@
1
- import:py from jaclang.core.llms, BaseLLM;
1
+ import:py from mtllm.llms, BaseLLM;
2
2
 
3
3
  obj model:BaseLLM: {
4
4
  can init {
@@ -1,4 +1,4 @@
1
- import:py from jaclang.core.llms, BaseLLM;
1
+ import:py from mtllm.llms, BaseLLM;
2
2
 
3
3
  obj model:BaseLLM: {
4
4
  can init {
@@ -1,4 +1,4 @@
1
- import:py from jaclang.core.llms, BaseLLM;
1
+ import:py from mtllm.llms, BaseLLM;
2
2
 
3
3
  obj model:BaseLLM: {
4
4
  can init(output_str: str) {
@@ -1,4 +1,4 @@
1
- import:py from jaclang.core.llms, BaseLLM;
1
+ import:py from mtllm.llms, BaseLLM;
2
2
  import:py from PIL, Image;
3
3
  import:py os;
4
4