jaclang 0.6.5__py3-none-any.whl → 0.7.0__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/compiler/absyntree.py +2 -0
- jaclang/compiler/parser.py +13 -4
- jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
- jaclang/compiler/passes/transform.py +13 -4
- jaclang/compiler/tests/fixtures/mod_doc_test.jac +3 -1
- jaclang/langserve/engine.py +287 -0
- jaclang/langserve/server.py +105 -74
- jaclang/langserve/utils.py +17 -15
- jaclang/plugin/default.py +1 -1
- {jaclang-0.6.5.dist-info → jaclang-0.7.0.dist-info}/METADATA +8 -16
- {jaclang-0.6.5.dist-info → jaclang-0.7.0.dist-info}/RECORD +13 -14
- jaclang/compiler/tests/test_workspace.py +0 -93
- jaclang/compiler/workspace.py +0 -234
- {jaclang-0.6.5.dist-info → jaclang-0.7.0.dist-info}/WHEEL +0 -0
- {jaclang-0.6.5.dist-info → jaclang-0.7.0.dist-info}/entry_points.txt +0 -0
jaclang/compiler/absyntree.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import ast as ast3
|
|
6
|
+
from hashlib import md5
|
|
6
7
|
from types import EllipsisType
|
|
7
8
|
from typing import Any, Callable, Generic, Optional, Sequence, Type, TypeVar
|
|
8
9
|
|
|
@@ -4081,6 +4082,7 @@ class JacSource(EmptyToken):
|
|
|
4081
4082
|
"""Initialize source string."""
|
|
4082
4083
|
super().__init__()
|
|
4083
4084
|
self.value = source
|
|
4085
|
+
self.hash = md5(source.encode()).hexdigest()
|
|
4084
4086
|
self.file_path = mod_path
|
|
4085
4087
|
self.comments: list[CommentToken] = []
|
|
4086
4088
|
|
jaclang/compiler/parser.py
CHANGED
|
@@ -28,7 +28,7 @@ class JacParser(Pass):
|
|
|
28
28
|
JacParser.make_dev()
|
|
29
29
|
Pass.__init__(self, input_ir=input_ir, prior=None)
|
|
30
30
|
|
|
31
|
-
def transform(self, ir: ast.AstNode) -> ast.
|
|
31
|
+
def transform(self, ir: ast.AstNode) -> ast.Module:
|
|
32
32
|
"""Transform input IR."""
|
|
33
33
|
try:
|
|
34
34
|
tree, comments = JacParser.parse(
|
|
@@ -36,6 +36,10 @@ class JacParser(Pass):
|
|
|
36
36
|
)
|
|
37
37
|
mod = JacParser.TreeToAST(parser=self).transform(tree)
|
|
38
38
|
self.source.comments = [self.proc_comment(i, mod) for i in comments]
|
|
39
|
+
if isinstance(mod, ast.Module):
|
|
40
|
+
return mod
|
|
41
|
+
else:
|
|
42
|
+
raise self.ice()
|
|
39
43
|
except jl.UnexpectedInput as e:
|
|
40
44
|
catch_error = ast.EmptyToken()
|
|
41
45
|
catch_error.file_path = self.mod_path
|
|
@@ -43,11 +47,16 @@ class JacParser(Pass):
|
|
|
43
47
|
catch_error.c_start = e.column
|
|
44
48
|
catch_error.c_end = e.column
|
|
45
49
|
self.error(f"Syntax Error: {e}", node_override=catch_error)
|
|
46
|
-
mod = self.source
|
|
47
50
|
except Exception as e:
|
|
48
|
-
mod = self.source
|
|
49
51
|
self.error(f"Internal Error: {e}")
|
|
50
|
-
return
|
|
52
|
+
return ast.Module(
|
|
53
|
+
name="",
|
|
54
|
+
source=self.source,
|
|
55
|
+
doc=None,
|
|
56
|
+
body=[],
|
|
57
|
+
is_imported=False,
|
|
58
|
+
kid=[ast.EmptyToken()],
|
|
59
|
+
)
|
|
51
60
|
|
|
52
61
|
@staticmethod
|
|
53
62
|
def proc_comment(token: jl.Token, mod: ast.AstNode) -> ast.CommentToken:
|
|
@@ -1161,7 +1161,7 @@ class JacFormatPass(Pass):
|
|
|
1161
1161
|
if (
|
|
1162
1162
|
node.parent
|
|
1163
1163
|
and node.parent.parent
|
|
1164
|
-
and isinstance(node.parent.parent, (ast.Ability))
|
|
1164
|
+
and not isinstance(node.parent.parent, (ast.Ability, ast.ModuleCode))
|
|
1165
1165
|
and node.parent.kid[1].gen.jac != "self.jaseci_sdk = {};\n"
|
|
1166
1166
|
):
|
|
1167
1167
|
self.emit_ln(node, "")
|
|
@@ -1229,7 +1229,7 @@ class JacFormatPass(Pass):
|
|
|
1229
1229
|
|
|
1230
1230
|
body: CodeBlock,
|
|
1231
1231
|
"""
|
|
1232
|
-
self.emit(node, "finally")
|
|
1232
|
+
self.emit(node, " finally")
|
|
1233
1233
|
|
|
1234
1234
|
self.emit(node, node.body.gen.jac)
|
|
1235
1235
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
|
-
from typing import Generic, Optional
|
|
6
|
+
from typing import Generic, Optional, Type
|
|
7
7
|
|
|
8
8
|
from jaclang.compiler.absyntree import AstNode, T
|
|
9
9
|
from jaclang.compiler.codeloc import CodeLocInfo
|
|
@@ -13,10 +13,11 @@ from jaclang.utils.log import logging
|
|
|
13
13
|
class Alert:
|
|
14
14
|
"""Alert interface."""
|
|
15
15
|
|
|
16
|
-
def __init__(self, msg: str, loc: CodeLocInfo) -> None:
|
|
16
|
+
def __init__(self, msg: str, loc: CodeLocInfo, from_pass: Type[Transform]) -> None:
|
|
17
17
|
"""Initialize alert."""
|
|
18
18
|
self.msg = msg
|
|
19
19
|
self.loc: CodeLocInfo = loc
|
|
20
|
+
self.from_pass: Type[Transform] = from_pass
|
|
20
21
|
|
|
21
22
|
def __str__(self) -> str:
|
|
22
23
|
"""Return string representation of alert."""
|
|
@@ -52,14 +53,22 @@ class Transform(ABC, Generic[T]):
|
|
|
52
53
|
|
|
53
54
|
def log_error(self, msg: str, node_override: Optional[AstNode] = None) -> None:
|
|
54
55
|
"""Pass Error."""
|
|
55
|
-
alrt = Alert(
|
|
56
|
+
alrt = Alert(
|
|
57
|
+
msg,
|
|
58
|
+
self.cur_node.loc if not node_override else node_override.loc,
|
|
59
|
+
self.__class__,
|
|
60
|
+
)
|
|
56
61
|
self.errors_had.append(alrt)
|
|
57
62
|
# print("Error:", str(alrt))
|
|
58
63
|
self.logger.error(str(alrt))
|
|
59
64
|
|
|
60
65
|
def log_warning(self, msg: str, node_override: Optional[AstNode] = None) -> None:
|
|
61
66
|
"""Pass Error."""
|
|
62
|
-
alrt = Alert(
|
|
67
|
+
alrt = Alert(
|
|
68
|
+
msg,
|
|
69
|
+
self.cur_node.loc if not node_override else node_override.loc,
|
|
70
|
+
self.__class__,
|
|
71
|
+
)
|
|
63
72
|
self.warnings_had.append(alrt)
|
|
64
73
|
# print("Warning:", str(alrt))
|
|
65
74
|
self.logger.warning(str(alrt))
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"""Living Workspace of Jac project."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from hashlib import md5
|
|
6
|
+
from typing import Sequence, Type
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import jaclang.compiler.absyntree as ast
|
|
10
|
+
from jaclang.compiler.compile import jac_pass_to_pass, jac_str_to_pass
|
|
11
|
+
from jaclang.compiler.parser import JacParser
|
|
12
|
+
from jaclang.compiler.passes import Pass
|
|
13
|
+
from jaclang.compiler.passes.main.schedules import (
|
|
14
|
+
AccessCheckPass,
|
|
15
|
+
PyBytecodeGenPass,
|
|
16
|
+
py_code_gen_typed,
|
|
17
|
+
)
|
|
18
|
+
from jaclang.compiler.passes.tool import FuseCommentsPass, JacFormatPass
|
|
19
|
+
from jaclang.compiler.passes.transform import Alert
|
|
20
|
+
from jaclang.compiler.symtable import Symbol
|
|
21
|
+
from jaclang.langserve.utils import sym_tab_list
|
|
22
|
+
from jaclang.vendor.pygls.server import LanguageServer
|
|
23
|
+
from jaclang.vendor.pygls.workspace.text_document import TextDocument
|
|
24
|
+
|
|
25
|
+
import lsprotocol.types as lspt
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ModuleInfo:
|
|
29
|
+
"""Module IR and Stats."""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
ir: ast.Module,
|
|
34
|
+
to_pass: Pass,
|
|
35
|
+
errors: Sequence[Alert],
|
|
36
|
+
warnings: Sequence[Alert],
|
|
37
|
+
) -> None:
|
|
38
|
+
"""Initialize module info."""
|
|
39
|
+
self.ir = ir
|
|
40
|
+
self.at_pass = to_pass
|
|
41
|
+
self.errors = errors
|
|
42
|
+
self.warnings = warnings
|
|
43
|
+
self.diagnostics = self.gen_diagnostics()
|
|
44
|
+
|
|
45
|
+
def gen_diagnostics(self) -> list[lspt.Diagnostic]:
|
|
46
|
+
"""Return diagnostics."""
|
|
47
|
+
return [
|
|
48
|
+
lspt.Diagnostic(
|
|
49
|
+
range=lspt.Range(
|
|
50
|
+
start=lspt.Position(
|
|
51
|
+
line=error.loc.first_line, character=error.loc.col_start
|
|
52
|
+
),
|
|
53
|
+
end=lspt.Position(
|
|
54
|
+
line=error.loc.last_line,
|
|
55
|
+
character=error.loc.col_end,
|
|
56
|
+
),
|
|
57
|
+
),
|
|
58
|
+
message=error.msg,
|
|
59
|
+
severity=lspt.DiagnosticSeverity.Error,
|
|
60
|
+
)
|
|
61
|
+
for error in self.errors
|
|
62
|
+
] + [
|
|
63
|
+
lspt.Diagnostic(
|
|
64
|
+
range=lspt.Range(
|
|
65
|
+
start=lspt.Position(
|
|
66
|
+
line=warning.loc.first_line, character=warning.loc.col_start
|
|
67
|
+
),
|
|
68
|
+
end=lspt.Position(
|
|
69
|
+
line=warning.loc.last_line,
|
|
70
|
+
character=warning.loc.col_end,
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
message=warning.msg,
|
|
74
|
+
severity=lspt.DiagnosticSeverity.Warning,
|
|
75
|
+
)
|
|
76
|
+
for warning in self.warnings
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class JacLangServer(LanguageServer):
|
|
81
|
+
"""Class for managing workspace."""
|
|
82
|
+
|
|
83
|
+
def __init__(self) -> None:
|
|
84
|
+
"""Initialize workspace."""
|
|
85
|
+
super().__init__("jac-lsp", "v0.1")
|
|
86
|
+
self.modules: dict[str, ModuleInfo] = {}
|
|
87
|
+
|
|
88
|
+
def module_not_diff(self, doc: TextDocument) -> bool:
|
|
89
|
+
"""Check if module was changed."""
|
|
90
|
+
return (
|
|
91
|
+
doc.uri in self.modules
|
|
92
|
+
and self.modules[doc.uri].ir.source.hash
|
|
93
|
+
== md5(doc.source.encode()).hexdigest()
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def module_reached_pass(self, doc: TextDocument, target: Type[Pass]) -> bool:
|
|
97
|
+
"""Check if module reached a pass."""
|
|
98
|
+
return doc.uri in self.modules and isinstance(
|
|
99
|
+
self.modules[doc.uri].at_pass, target
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def push_diagnostics(self, file_path: str) -> None:
|
|
103
|
+
"""Push diagnostics for a file."""
|
|
104
|
+
if file_path in self.modules:
|
|
105
|
+
self.publish_diagnostics(
|
|
106
|
+
file_path,
|
|
107
|
+
self.modules[file_path].diagnostics,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def quick_check(self, file_path: str) -> None:
|
|
111
|
+
"""Rebuild a file."""
|
|
112
|
+
document = self.workspace.get_document(file_path)
|
|
113
|
+
if self.module_not_diff(document):
|
|
114
|
+
return
|
|
115
|
+
try:
|
|
116
|
+
build = jac_str_to_pass(
|
|
117
|
+
jac_str=document.source, file_path=document.path, schedule=[]
|
|
118
|
+
)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
self.log_error(f"Error during syntax check: {e}")
|
|
121
|
+
if isinstance(build.ir, ast.Module):
|
|
122
|
+
self.modules[file_path] = ModuleInfo(
|
|
123
|
+
ir=build.ir,
|
|
124
|
+
to_pass=build,
|
|
125
|
+
errors=build.errors_had,
|
|
126
|
+
warnings=build.warnings_had,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def deep_check(self, file_path: str) -> None:
|
|
130
|
+
"""Rebuild a file and its dependencies."""
|
|
131
|
+
document = self.workspace.get_document(file_path)
|
|
132
|
+
if self.module_not_diff(document) and self.module_reached_pass(
|
|
133
|
+
document, PyBytecodeGenPass
|
|
134
|
+
):
|
|
135
|
+
return
|
|
136
|
+
try:
|
|
137
|
+
build = jac_pass_to_pass(in_pass=self.modules[file_path].at_pass)
|
|
138
|
+
except Exception as e:
|
|
139
|
+
self.log_error(f"Error during syntax check: {e}")
|
|
140
|
+
if isinstance(build.ir, ast.Module):
|
|
141
|
+
self.modules[file_path] = ModuleInfo(
|
|
142
|
+
ir=build.ir,
|
|
143
|
+
to_pass=build,
|
|
144
|
+
errors=build.errors_had,
|
|
145
|
+
warnings=build.warnings_had,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
def type_check(self, file_path: str) -> None:
|
|
149
|
+
"""Rebuild a file and its dependencies."""
|
|
150
|
+
document = self.workspace.get_document(file_path)
|
|
151
|
+
if self.module_not_diff(document) and self.module_reached_pass(
|
|
152
|
+
document, AccessCheckPass
|
|
153
|
+
):
|
|
154
|
+
return
|
|
155
|
+
try:
|
|
156
|
+
build = jac_pass_to_pass(
|
|
157
|
+
in_pass=self.modules[file_path].at_pass,
|
|
158
|
+
target=AccessCheckPass,
|
|
159
|
+
schedule=py_code_gen_typed,
|
|
160
|
+
)
|
|
161
|
+
except Exception as e:
|
|
162
|
+
self.log_error(f"Error during type check: {e}")
|
|
163
|
+
if isinstance(build.ir, ast.Module):
|
|
164
|
+
self.modules[file_path] = ModuleInfo(
|
|
165
|
+
ir=build.ir,
|
|
166
|
+
to_pass=build,
|
|
167
|
+
errors=build.errors_had,
|
|
168
|
+
warnings=build.warnings_had,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def get_completion(
|
|
172
|
+
self, file_path: str, position: lspt.Position
|
|
173
|
+
) -> lspt.CompletionList:
|
|
174
|
+
"""Return completion for a file."""
|
|
175
|
+
items = []
|
|
176
|
+
document = self.workspace.get_document(file_path)
|
|
177
|
+
current_line = document.lines[position.line].strip()
|
|
178
|
+
if current_line.endswith("hello."):
|
|
179
|
+
|
|
180
|
+
items = [
|
|
181
|
+
lspt.CompletionItem(label="world"),
|
|
182
|
+
lspt.CompletionItem(label="friend"),
|
|
183
|
+
]
|
|
184
|
+
return lspt.CompletionList(is_incomplete=False, items=items)
|
|
185
|
+
|
|
186
|
+
def rename_module(self, old_path: str, new_path: str) -> None:
|
|
187
|
+
"""Rename module."""
|
|
188
|
+
if old_path in self.modules and new_path != old_path:
|
|
189
|
+
self.modules[new_path] = self.modules[old_path]
|
|
190
|
+
del self.modules[old_path]
|
|
191
|
+
|
|
192
|
+
def delete_module(self, uri: str) -> None:
|
|
193
|
+
"""Delete module."""
|
|
194
|
+
if uri in self.modules:
|
|
195
|
+
del self.modules[uri]
|
|
196
|
+
|
|
197
|
+
def formatted_jac(self, file_path: str) -> list[lspt.TextEdit]:
|
|
198
|
+
"""Return formatted jac."""
|
|
199
|
+
try:
|
|
200
|
+
document = self.workspace.get_document(file_path)
|
|
201
|
+
format = jac_str_to_pass(
|
|
202
|
+
jac_str=document.source,
|
|
203
|
+
file_path=document.path,
|
|
204
|
+
target=JacFormatPass,
|
|
205
|
+
schedule=[FuseCommentsPass, JacFormatPass],
|
|
206
|
+
)
|
|
207
|
+
formatted_text = (
|
|
208
|
+
format.ir.gen.jac
|
|
209
|
+
if JacParser not in [e.from_pass for e in format.errors_had]
|
|
210
|
+
else document.source
|
|
211
|
+
)
|
|
212
|
+
except Exception as e:
|
|
213
|
+
self.log_error(f"Error during formatting: {e}")
|
|
214
|
+
formatted_text = document.source
|
|
215
|
+
return [
|
|
216
|
+
lspt.TextEdit(
|
|
217
|
+
range=lspt.Range(
|
|
218
|
+
start=lspt.Position(line=0, character=0),
|
|
219
|
+
end=lspt.Position(
|
|
220
|
+
line=len(document.source.splitlines()) + 1, character=0
|
|
221
|
+
),
|
|
222
|
+
),
|
|
223
|
+
new_text=(formatted_text),
|
|
224
|
+
)
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
def get_dependencies(
|
|
228
|
+
self, file_path: str, deep: bool = False
|
|
229
|
+
) -> list[ast.ModulePath]:
|
|
230
|
+
"""Return a list of dependencies for a file."""
|
|
231
|
+
mod_ir = self.modules[file_path].ir
|
|
232
|
+
if deep:
|
|
233
|
+
return (
|
|
234
|
+
[
|
|
235
|
+
i
|
|
236
|
+
for i in mod_ir.get_all_sub_nodes(ast.ModulePath)
|
|
237
|
+
if i.parent_of_type(ast.Import).hint.tag.value == "jac"
|
|
238
|
+
]
|
|
239
|
+
if mod_ir
|
|
240
|
+
else []
|
|
241
|
+
)
|
|
242
|
+
else:
|
|
243
|
+
return (
|
|
244
|
+
[
|
|
245
|
+
i
|
|
246
|
+
for i in mod_ir.get_all_sub_nodes(ast.ModulePath)
|
|
247
|
+
if i.loc.mod_path == file_path
|
|
248
|
+
and i.parent_of_type(ast.Import).hint.tag.value == "jac"
|
|
249
|
+
]
|
|
250
|
+
if mod_ir
|
|
251
|
+
else []
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def get_symbols(self, file_path: str) -> list[Symbol]:
|
|
255
|
+
"""Return a list of symbols for a file."""
|
|
256
|
+
symbols = []
|
|
257
|
+
mod_ir = self.modules[file_path].ir
|
|
258
|
+
if file_path in self.modules:
|
|
259
|
+
root_table = mod_ir.sym_tab if mod_ir else None
|
|
260
|
+
if file_path in self.modules and root_table:
|
|
261
|
+
for i in sym_tab_list(sym_tab=root_table, file_path=file_path):
|
|
262
|
+
symbols += list(i.tab.values())
|
|
263
|
+
return symbols
|
|
264
|
+
|
|
265
|
+
def get_definitions(
|
|
266
|
+
self, file_path: str
|
|
267
|
+
) -> Sequence[ast.AstSymbolNode]: # need test
|
|
268
|
+
"""Return a list of definitions for a file."""
|
|
269
|
+
defs = []
|
|
270
|
+
for i in self.get_symbols(file_path):
|
|
271
|
+
defs += i.defn
|
|
272
|
+
return defs
|
|
273
|
+
|
|
274
|
+
def log_error(self, message: str) -> None:
|
|
275
|
+
"""Log an error message."""
|
|
276
|
+
self.show_message_log(message, lspt.MessageType.Error)
|
|
277
|
+
self.show_message(message, lspt.MessageType.Error)
|
|
278
|
+
|
|
279
|
+
def log_warning(self, message: str) -> None:
|
|
280
|
+
"""Log a warning message."""
|
|
281
|
+
self.show_message_log(message, lspt.MessageType.Warning)
|
|
282
|
+
self.show_message(message, lspt.MessageType.Warning)
|
|
283
|
+
|
|
284
|
+
def log_info(self, message: str) -> None:
|
|
285
|
+
"""Log an info message."""
|
|
286
|
+
self.show_message_log(message, lspt.MessageType.Info)
|
|
287
|
+
self.show_message(message, lspt.MessageType.Info)
|
jaclang/langserve/server.py
CHANGED
|
@@ -2,101 +2,132 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
from jaclang.
|
|
5
|
+
import threading
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from jaclang.langserve.engine import JacLangServer
|
|
9
|
+
from jaclang.langserve.utils import debounce
|
|
9
10
|
|
|
10
11
|
import lsprotocol.types as lspt
|
|
11
12
|
|
|
12
|
-
server =
|
|
13
|
+
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) -> 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
|
+
ls.deep_check(uri)
|
|
26
|
+
ls.push_diagnostics(uri)
|
|
27
|
+
ls.type_check(uri)
|
|
28
|
+
ls.push_diagnostics(uri)
|
|
29
|
+
|
|
30
|
+
analysis_thread = threading.Thread(target=run_analysis)
|
|
31
|
+
analysis_thread.start()
|
|
32
|
+
ls.log_info("Analysis restarted")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def stop_analysis() -> None:
|
|
36
|
+
"""Stop analysis."""
|
|
37
|
+
global analysis_thread, analysis_stop_event
|
|
38
|
+
if analysis_thread is not None:
|
|
39
|
+
analysis_stop_event.set()
|
|
40
|
+
analysis_thread.join()
|
|
41
|
+
analysis_stop_event.clear()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@server.feature(lspt.TEXT_DOCUMENT_DID_OPEN)
|
|
45
|
+
async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
|
|
46
|
+
"""Check syntax on change."""
|
|
47
|
+
stop_analysis()
|
|
48
|
+
analyze_and_publish(ls, params.text_document.uri)
|
|
13
49
|
|
|
14
50
|
|
|
15
51
|
@server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
|
|
16
|
-
@debounce(0.
|
|
52
|
+
@debounce(0.1)
|
|
17
53
|
async def did_change(
|
|
18
|
-
ls:
|
|
54
|
+
ls: JacLangServer, params: lspt.DidChangeTextDocumentParams
|
|
19
55
|
) -> None:
|
|
20
56
|
"""Check syntax on change."""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
stop_analysis()
|
|
58
|
+
analyze_and_publish(ls, params.text_document.uri)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
|
|
62
|
+
async def did_save(ls: JacLangServer, params: lspt.DidSaveTextDocumentParams) -> None:
|
|
63
|
+
"""Check syntax on save."""
|
|
64
|
+
stop_analysis()
|
|
65
|
+
analyze_and_publish(ls, params.text_document.uri)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@server.feature(
|
|
69
|
+
lspt.WORKSPACE_DID_CREATE_FILES,
|
|
70
|
+
lspt.FileOperationRegistrationOptions(
|
|
71
|
+
filters=[
|
|
72
|
+
lspt.FileOperationFilter(pattern=lspt.FileOperationPattern("**/*.jac"))
|
|
73
|
+
]
|
|
74
|
+
),
|
|
75
|
+
)
|
|
76
|
+
async def did_create_files(ls: JacLangServer, params: lspt.CreateFilesParams) -> None:
|
|
77
|
+
"""Check syntax on file creation."""
|
|
78
|
+
for file in params.files:
|
|
79
|
+
ls.quick_check(file.uri)
|
|
80
|
+
ls.push_diagnostics(file.uri)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@server.feature(
|
|
84
|
+
lspt.WORKSPACE_DID_RENAME_FILES,
|
|
85
|
+
lspt.FileOperationRegistrationOptions(
|
|
86
|
+
filters=[
|
|
87
|
+
lspt.FileOperationFilter(pattern=lspt.FileOperationPattern("**/*.jac"))
|
|
88
|
+
]
|
|
89
|
+
),
|
|
90
|
+
)
|
|
91
|
+
async def did_rename_files(ls: JacLangServer, params: lspt.RenameFilesParams) -> None:
|
|
92
|
+
"""Check syntax on file rename."""
|
|
93
|
+
new_uris = [file.new_uri for file in params.files]
|
|
94
|
+
old_uris = [file.old_uri for file in params.files]
|
|
95
|
+
for i in range(len(new_uris)):
|
|
96
|
+
ls.rename_module(old_uris[i], new_uris[i])
|
|
97
|
+
ls.quick_check(new_uris[i])
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@server.feature(
|
|
101
|
+
lspt.WORKSPACE_DID_DELETE_FILES,
|
|
102
|
+
lspt.FileOperationRegistrationOptions(
|
|
103
|
+
filters=[
|
|
104
|
+
lspt.FileOperationFilter(pattern=lspt.FileOperationPattern("**/*.jac"))
|
|
105
|
+
]
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
async def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None:
|
|
109
|
+
"""Check syntax on file delete."""
|
|
110
|
+
for file in params.files:
|
|
111
|
+
ls.delete_module(file.uri)
|
|
53
112
|
|
|
54
113
|
|
|
55
114
|
@server.feature(
|
|
56
115
|
lspt.TEXT_DOCUMENT_COMPLETION,
|
|
57
116
|
lspt.CompletionOptions(trigger_characters=[".", ":", ""]),
|
|
58
117
|
)
|
|
59
|
-
def
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if current_line.endswith("hello."):
|
|
65
|
-
|
|
66
|
-
items = [
|
|
67
|
-
lspt.CompletionItem(label="world"),
|
|
68
|
-
lspt.CompletionItem(label="friend"),
|
|
69
|
-
]
|
|
70
|
-
return lspt.CompletionList(is_incomplete=False, items=items)
|
|
118
|
+
async def completion(
|
|
119
|
+
ls: JacLangServer, params: lspt.CompletionParams
|
|
120
|
+
) -> lspt.CompletionList:
|
|
121
|
+
"""Provide completion."""
|
|
122
|
+
return ls.get_completion(params.text_document.uri, params.position)
|
|
71
123
|
|
|
72
124
|
|
|
73
125
|
@server.feature(lspt.TEXT_DOCUMENT_FORMATTING)
|
|
74
126
|
def formatting(
|
|
75
|
-
ls:
|
|
127
|
+
ls: JacLangServer, params: lspt.DocumentFormattingParams
|
|
76
128
|
) -> list[lspt.TextEdit]:
|
|
77
129
|
"""Format the given document."""
|
|
78
|
-
|
|
79
|
-
document = ls.workspace.get_document(params.text_document.uri)
|
|
80
|
-
formatted_text = jac_str_to_pass(
|
|
81
|
-
jac_str=document.source,
|
|
82
|
-
file_path=document.path,
|
|
83
|
-
target=JacFormatPass,
|
|
84
|
-
schedule=[FuseCommentsPass, JacFormatPass],
|
|
85
|
-
).ir.gen.jac
|
|
86
|
-
except Exception as e:
|
|
87
|
-
log_error(ls, f"Error during formatting: {e}")
|
|
88
|
-
formatted_text = document.source
|
|
89
|
-
return [
|
|
90
|
-
lspt.TextEdit(
|
|
91
|
-
range=lspt.Range(
|
|
92
|
-
start=lspt.Position(line=0, character=0),
|
|
93
|
-
end=lspt.Position(
|
|
94
|
-
line=len(formatted_text.splitlines()) + 1, character=0
|
|
95
|
-
),
|
|
96
|
-
),
|
|
97
|
-
new_text=formatted_text,
|
|
98
|
-
)
|
|
99
|
-
]
|
|
130
|
+
return ls.formatted_jac(params.text_document.uri)
|
|
100
131
|
|
|
101
132
|
|
|
102
133
|
def run_lang_server() -> None:
|
jaclang/langserve/utils.py
CHANGED
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
"""Utility functions for the language server."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
import logging
|
|
5
4
|
from functools import wraps
|
|
6
5
|
from typing import Any, Awaitable, Callable, Coroutine, ParamSpec, TypeVar
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import lsprotocol.types as lspt
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def log_error(ls: LanguageServer, message: str) -> None:
|
|
14
|
-
"""Log an error message."""
|
|
15
|
-
ls.show_message_log(message, lspt.MessageType.Error)
|
|
16
|
-
ls.show_message(message, lspt.MessageType.Error)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def log(info: str) -> None:
|
|
20
|
-
"""Log an info message."""
|
|
21
|
-
logging.warning(info)
|
|
7
|
+
import jaclang.compiler.absyntree as ast
|
|
8
|
+
from jaclang.compiler.symtable import SymbolTable
|
|
22
9
|
|
|
23
10
|
|
|
24
11
|
T = TypeVar("T", bound=Callable[..., Coroutine[Any, Any, Any]])
|
|
@@ -51,3 +38,18 @@ def debounce(wait: float) -> Callable[[T], Callable[..., Awaitable[None]]]:
|
|
|
51
38
|
return debounced
|
|
52
39
|
|
|
53
40
|
return decorator
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def sym_tab_list(sym_tab: SymbolTable, file_path: str) -> list[SymbolTable]:
|
|
44
|
+
"""Iterate through symbol table."""
|
|
45
|
+
sym_tabs = (
|
|
46
|
+
[sym_tab]
|
|
47
|
+
if not (
|
|
48
|
+
isinstance(sym_tab.owner, ast.Module)
|
|
49
|
+
and sym_tab.owner.loc.mod_path != file_path
|
|
50
|
+
)
|
|
51
|
+
else []
|
|
52
|
+
)
|
|
53
|
+
for i in sym_tab.kid:
|
|
54
|
+
sym_tabs += sym_tab_list(i, file_path=file_path)
|
|
55
|
+
return sym_tabs
|
jaclang/plugin/default.py
CHANGED
|
@@ -189,8 +189,8 @@ class JacFeatureDefaults:
|
|
|
189
189
|
|
|
190
190
|
@wraps(inner_init)
|
|
191
191
|
def new_init(self: Architype, *args: object, **kwargs: object) -> None:
|
|
192
|
-
inner_init(self, *args, **kwargs)
|
|
193
192
|
arch_base.__init__(self)
|
|
193
|
+
inner_init(self, *args, **kwargs)
|
|
194
194
|
|
|
195
195
|
cls.__init__ = new_init # type: ignore
|
|
196
196
|
return cls
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jaclang
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Jac is a unique and powerful programming language that runs on top of Python, offering an unprecedented level of intelligence and intuitive understanding.
|
|
5
5
|
Home-page: https://jaseci.org
|
|
6
6
|
License: MIT
|
|
@@ -25,7 +25,7 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
width="20%">
|
|
26
26
|
</picture>
|
|
27
27
|
|
|
28
|
-
[Website]
|
|
28
|
+
[Jac Website] | [Getting started] | [Learn] | [Documentation] | [Contributing]
|
|
29
29
|
|
|
30
30
|
[](https://pypi.org/project/jaclang/) [](https://github.com/chandralegend/jaclang/actions/workflows/run_pytest.yml) [](https://codecov.io/github/chandralegend/jaclang)
|
|
31
31
|
</div>
|
|
@@ -33,30 +33,22 @@ Description-Content-Type: text/markdown
|
|
|
33
33
|
This is the main source code repository for the [Jac] programming language. It contains the compiler, language server, and documentation.
|
|
34
34
|
|
|
35
35
|
[Jac]: https://www.jac-lang.org/
|
|
36
|
+
[Jac Website]: https://www.jac-lang.org/
|
|
36
37
|
[Getting Started]: https://www.jac-lang.org//start/
|
|
37
38
|
[Learn]: https://www.jac-lang.org//learn
|
|
38
39
|
[Documentation]: https://www.jac-lang.org//learn/guide/
|
|
39
40
|
[Contributing]: .github/CONTRIBUTING.md
|
|
40
41
|
|
|
41
|
-
## Why Jac?
|
|
42
|
+
## What and Why Jac?
|
|
42
43
|
|
|
43
|
-
- **
|
|
44
|
+
- **Native Superset of Python** - Jac is a native superset of python, meaning the entire python ecosystem is directly interoperable with Jac without any trickery (no interop interface needed). Like Typescript is to Javascript, or C++ is to C, Jac is to Python. (every Jac program can be ejected to pure python, and every python program can be transpiled to a Jac program)
|
|
44
45
|
|
|
45
|
-
- **
|
|
46
|
+
- **AI as a Programming Language Constructs** - Jac includes a novel (neurosymbolic) language construct that allows replacing code with generative AI models themselves. Jac's philosophy abstracts away prompt engineering. (Imagine taking a function body and swapping it out with a model.)
|
|
46
47
|
|
|
47
|
-
- **
|
|
48
|
+
- **New Modern Abstractions** - Jac introduces a paradigm that reasons about persistence and the notion of users as a language level construct. This enables writing simple programs for which no code changes are needed whether they run in a simple command terminal, or distributed across a large cloud. Jac's philosophy abstracts away dev ops and container/cloud configuration.
|
|
48
49
|
|
|
49
|
-
- **
|
|
50
|
+
- **Jac Improves on Python** - Jac makes multiple thoughtful quality-of-life improvements/additions to Python. These include new modern operators, new types of comprehensions, new ways of organizing modules (i.e., separating implementations from declarations), etc.
|
|
50
51
|
|
|
51
|
-
- **Support:** Jac compiles to Python, which is widely used and has a large ecosystem. Making it easy to integrate with existing code.
|
|
52
|
-
|
|
53
|
-
- **Dev Friendly:** Highly Refactorable, Jac is designed to be easy to refactor and maintain. VSCode Editor support. Builtin language server protocol support.
|
|
54
|
-
|
|
55
|
-
- **Cloud-native:** Jac is designed to be cloud-native, making it easy to deploy and scale.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
[jac-analyzer]: https://github.com/Jaseci-Labs/jac-analyzer
|
|
60
52
|
|
|
61
53
|
## Quick Start
|
|
62
54
|
|
|
@@ -6,12 +6,12 @@ jaclang/cli/cli.py,sha256=d352zfA5_Da5InyQkv4V-qaxIcdIaVYJVeYt8npSB3I,13553
|
|
|
6
6
|
jaclang/cli/cmdreg.py,sha256=u0jAd6A8czt7tBgPBBKBhYAG4By1FrjEGaTU2XFKeYs,8372
|
|
7
7
|
jaclang/compiler/.gitignore,sha256=n1k2_xXTorp9PY8hhYM4psHircn-NMaFx95bSgDKopo,10
|
|
8
8
|
jaclang/compiler/__init__.py,sha256=JA3L1ran0PlZI5Pcj2CIrFgrZGRNFHHC5kRh1QYgYlY,3146
|
|
9
|
-
jaclang/compiler/absyntree.py,sha256=
|
|
9
|
+
jaclang/compiler/absyntree.py,sha256=yHKyIqPTajrZa8KE2gneilkLk9xFBU0EPaknVelmAZ4,126981
|
|
10
10
|
jaclang/compiler/codeloc.py,sha256=KMwf5OMQu3_uDjIdH7ta2piacUtXNPgUV1t8OuLjpzE,2828
|
|
11
11
|
jaclang/compiler/compile.py,sha256=IOjTLv42IULW6HbCpFINNrRhwjHDebKO1vdon0EX85k,2772
|
|
12
12
|
jaclang/compiler/constant.py,sha256=C8nOgWLAg-fRg8Qax_jRcYp6jGyWSSA1gwzk9Zdy7HE,6534
|
|
13
13
|
jaclang/compiler/jac.lark,sha256=TI8ctvs_cASPp-EDPrMiCeL80Ngvj_7WxGMUFtGN7vs,17040
|
|
14
|
-
jaclang/compiler/parser.py,sha256=
|
|
14
|
+
jaclang/compiler/parser.py,sha256=Fy6qsTdh82YvXSgXoevIT5dIGjAn3hqbN45muJ5jFNY,138789
|
|
15
15
|
jaclang/compiler/passes/__init__.py,sha256=0Tw0d130ZjzA05jVcny9cf5NfLjlaM70PKqFnY4zqn4,69
|
|
16
16
|
jaclang/compiler/passes/ir_pass.py,sha256=gh1Zd8ouu79FoxerW1sMxktmfeC9gHyp4H_MoAviYP8,5504
|
|
17
17
|
jaclang/compiler/passes/main/__init__.py,sha256=m8vZ0F6EiwOm0e0DWKRYgc8JcgiT2ayBrY6GojZkTfY,945
|
|
@@ -64,7 +64,7 @@ jaclang/compiler/passes/main/tests/test_typeinfo_pass.py,sha256=ehC0_giLg7NwB7fR
|
|
|
64
64
|
jaclang/compiler/passes/main/type_check_pass.py,sha256=-f41Ukr3B1w4rkQdZ2xJy6nozymgnVKjJ8E1fn7qJmI,3339
|
|
65
65
|
jaclang/compiler/passes/tool/__init__.py,sha256=xekCOXysHIcthWm8NRmQoA1Ah1XV8vFbkfeHphJtUdc,223
|
|
66
66
|
jaclang/compiler/passes/tool/fuse_comments_pass.py,sha256=N9a84qArNuTXX1iaXsBzqcufx6A3zYq2p-1ieH6FmHc,3133
|
|
67
|
-
jaclang/compiler/passes/tool/jac_formatter_pass.py,sha256=
|
|
67
|
+
jaclang/compiler/passes/tool/jac_formatter_pass.py,sha256=xpM10gIhILS37Ne2NVFMruJwmG1GfDcY0y8fbgqWrdM,86134
|
|
68
68
|
jaclang/compiler/passes/tool/schedules.py,sha256=kmbsCazAMizGAdQuZpFky5BPlYlMXqNw7wOUzdi_wBo,432
|
|
69
69
|
jaclang/compiler/passes/tool/tests/__init__.py,sha256=AeOaZjA1rf6VAr0JqIit6jlcmOzW7pxGr4U1fOwgK_Y,24
|
|
70
70
|
jaclang/compiler/passes/tool/tests/fixtures/corelib.jac,sha256=GA5_CDQQo9awG6H8wed8tp06KoWtQ8nR70LVbBwCFIY,12416
|
|
@@ -99,7 +99,7 @@ jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac,sha256=6jwYKXxJ1
|
|
|
99
99
|
jaclang/compiler/passes/tool/tests/test_fuse_comments_pass.py,sha256=ZeWHsm7VIyyS8KKpoB2SdlHM4jF22fMfSrfTfxt2MQw,398
|
|
100
100
|
jaclang/compiler/passes/tool/tests/test_jac_format_pass.py,sha256=P4vBRbwVAkb8svFSAOf4VKioZS8BkoaVfYdn-LCrRqA,6144
|
|
101
101
|
jaclang/compiler/passes/tool/tests/test_unparse_validate.py,sha256=Tg9k7BOSkWngAZLvSHmPt95ILJzdIvdHxKBT__mgpS0,2910
|
|
102
|
-
jaclang/compiler/passes/transform.py,sha256=
|
|
102
|
+
jaclang/compiler/passes/transform.py,sha256=jh2pMGFs6J9ZbQ2E-3r21khDm53yKXbNq5GstLMkBpg,2374
|
|
103
103
|
jaclang/compiler/passes/utils/__init__.py,sha256=UsI5rUopTUiStAzup4kbPwIwrnC5ofCrqWBCBbM2-k4,35
|
|
104
104
|
jaclang/compiler/passes/utils/mypy_ast_build.py,sha256=DbTYKwQ2K-3JXS_RybLyvqDz_381Li8JfFKNeEQhbRY,26324
|
|
105
105
|
jaclang/compiler/symtable.py,sha256=f-9c3eQJTDhEG22kYC3Vd4i5gRWf77_CsqFm7t8Wsng,6031
|
|
@@ -109,13 +109,11 @@ jaclang/compiler/tests/fixtures/activity.py,sha256=fSvxYDKufsPeQIrbuh031zHw_hdbR
|
|
|
109
109
|
jaclang/compiler/tests/fixtures/fam.jac,sha256=DGR9vJI8H73plbyvwdTHbsvSRd_0hT-Kq9IIIrQ1GLU,1544
|
|
110
110
|
jaclang/compiler/tests/fixtures/hello_world.jac,sha256=uT67nGzdYY7YT6Xj5-OHFAZPEHfIl4zGlfyNs7-zRBI,78
|
|
111
111
|
jaclang/compiler/tests/fixtures/kwesc.jac,sha256=OXxVL_fwiFuvYO1YX1RHa2hpETSpb0QD1-gMYnMY6DA,103
|
|
112
|
-
jaclang/compiler/tests/fixtures/mod_doc_test.jac,sha256=
|
|
112
|
+
jaclang/compiler/tests/fixtures/mod_doc_test.jac,sha256=aFZpjn7V5lvCHp0lPoGXtdkcY3CK8_-SKeZGruutv4Y,35
|
|
113
113
|
jaclang/compiler/tests/fixtures/staticcheck.jac,sha256=t849--dTkSSjCJX1OiMV-lgao_hIDSKwKVs-aS6IwK8,342
|
|
114
114
|
jaclang/compiler/tests/fixtures/stuff.jac,sha256=qOq6WOwhlprMmJpiqQudgqnr4qTd9uhulQSDGQ3o6sY,82
|
|
115
115
|
jaclang/compiler/tests/test_importer.py,sha256=JNmte5FsHhnng9jzw7N5BenflAFCasuhezN1sytDVyg,1739
|
|
116
116
|
jaclang/compiler/tests/test_parser.py,sha256=C81mUo8EGwypPTTLRVS9BglP0Dyye9xaPSQtw7cwnnI,4814
|
|
117
|
-
jaclang/compiler/tests/test_workspace.py,sha256=SEBcvz_daTbonrLHK9FbjiH86TUbOtVGH-iZ3xkJSMk,3184
|
|
118
|
-
jaclang/compiler/workspace.py,sha256=I1MF2jaSylDOcQQV4Ez3svi4FdOyfmbNupuZT7q9aFQ,7797
|
|
119
117
|
jaclang/core/__init__.py,sha256=jDDYBCV82qPhmcDVk3NIvHbhng0ebSrXD3xrojg0-eo,34
|
|
120
118
|
jaclang/core/aott.py,sha256=MMFmel9cf1KrREjLUY9vV0b38pdb_4N3pxe5jMedBYA,7582
|
|
121
119
|
jaclang/core/construct.py,sha256=ZwgOO-P2OTv8d7mnxBkRg-AitrzYxsbFNqJZjRE9YqM,18649
|
|
@@ -134,7 +132,8 @@ jaclang/core/registry.py,sha256=4uuXahPN4SMVEWwJ6Gjm5LM14rePMGoyjQtSbDQmQZs,4178
|
|
|
134
132
|
jaclang/core/shelve_storage.py,sha256=UsZRHM8KPGUlZTX_bfcxzabInNrTaQVNMatQifycMYg,1692
|
|
135
133
|
jaclang/core/utils.py,sha256=5e4DyjtSweFxKeIuEyeYGV2MsuTtfnncfIwRdoyFdys,7736
|
|
136
134
|
jaclang/langserve/__init__.py,sha256=3qbnivBBcLZCfmDYRMIeKkG08Lx7XQsJJg-qG8TU8yc,51
|
|
137
|
-
jaclang/langserve/
|
|
135
|
+
jaclang/langserve/engine.py,sha256=3XIOhM8S5mlnfS42po8DKPlg4ptGfDMmYmlF8grnsGs,10079
|
|
136
|
+
jaclang/langserve/server.py,sha256=17u6mgK4JgLcnnlpixHmOXKj5-OJiwUurMXJ9Qt7s4Q,3992
|
|
138
137
|
jaclang/langserve/tests/__init__.py,sha256=iDM47k6c3vahaWhwxpbkdEOshbmX-Zl5x669VONjS2I,23
|
|
139
138
|
jaclang/langserve/tests/defaults.py,sha256=8UWHuCHY-WatPcWFhyX9-4KLuJgODTlLNj0wNnKomIM,7608
|
|
140
139
|
jaclang/langserve/tests/fixtures/hello.jac,sha256=iRMKtYVCw1zLvjOQbj3q__3Manj1Di1YeDTNMEvYtBc,36
|
|
@@ -145,10 +144,10 @@ jaclang/langserve/tests/pylsp_jsonrpc/exceptions.py,sha256=NGHeFQawZcjoLUcgDmY3b
|
|
|
145
144
|
jaclang/langserve/tests/pylsp_jsonrpc/streams.py,sha256=R80_FvICIkrbdGmNtlemWYaxrr7-XldPgLaASnyv0W8,3332
|
|
146
145
|
jaclang/langserve/tests/session.py,sha256=3pIRoQjZnsnUWIYnO2SpK7c1PAiHMCFrrStNK2tawRM,9572
|
|
147
146
|
jaclang/langserve/tests/test_server.py,sha256=Zqo4bnlUg9TH1xHSpT4VBpTefT6tLCWjOZbFI9hEzUs,1411
|
|
148
|
-
jaclang/langserve/utils.py,sha256=
|
|
147
|
+
jaclang/langserve/utils.py,sha256=p0ohiZwvasbBWY-jtHj5lULL3ZYPXuc9B80eFzhk5TQ,1602
|
|
149
148
|
jaclang/plugin/__init__.py,sha256=5t2krHKt_44PrCTGojzxEimxpNHYVQcn89jAiCSXE_k,165
|
|
150
149
|
jaclang/plugin/builtin.py,sha256=PP2Vs4p_oDbGYEx0iBFDYH49I4uSRnNVWgx2aOzorVA,1187
|
|
151
|
-
jaclang/plugin/default.py,sha256=
|
|
150
|
+
jaclang/plugin/default.py,sha256=bi8qyiKkXAwr-TjT_VSI0_KSW4l5fqHCGp7dV0egfI0,27142
|
|
152
151
|
jaclang/plugin/feature.py,sha256=Qi30JWJvt51s9nx3eJ0_BSTYIeTYLHe-e26y0IjJLz8,9444
|
|
153
152
|
jaclang/plugin/spec.py,sha256=mJRUMGaIhlHbZIvO2J-A1q3eNhnIWJ0iBCPmxhHiHx4,9043
|
|
154
153
|
jaclang/plugin/tests/__init__.py,sha256=rn_tNG8jCHWwBc_rx4yFkGc4N1GISb7aPuTFVRTvrTk,38
|
|
@@ -1470,7 +1469,7 @@ jaclang/vendor/typing_extensions-4.12.2.dist-info/METADATA,sha256=BeUQIa8cnYbrjW
|
|
|
1470
1469
|
jaclang/vendor/typing_extensions-4.12.2.dist-info/RECORD,sha256=XS4fBVrPI7kaNZ56Ggl2RGa76jySWLqTzcrUpZIQTVM,418
|
|
1471
1470
|
jaclang/vendor/typing_extensions-4.12.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
1472
1471
|
jaclang/vendor/typing_extensions.py,sha256=gwekpyG9DVG3lxWKX4ni8u7nk3We5slG98mA9F3DJQw,134451
|
|
1473
|
-
jaclang-0.
|
|
1474
|
-
jaclang-0.
|
|
1475
|
-
jaclang-0.
|
|
1476
|
-
jaclang-0.
|
|
1472
|
+
jaclang-0.7.0.dist-info/METADATA,sha256=t3CGvduif1vz_lYjQFxjon55vqB3fO2adkxvMxHHxXw,4756
|
|
1473
|
+
jaclang-0.7.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
1474
|
+
jaclang-0.7.0.dist-info/entry_points.txt,sha256=8sMi4Tvi9f8tQDN2QAXsSA2icO27zQ4GgEdph6bNEZM,49
|
|
1475
|
+
jaclang-0.7.0.dist-info/RECORD,,
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
"""Tests for Jac Workspace."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
from jaclang.compiler.workspace import Workspace
|
|
6
|
-
from jaclang.utils.test import TestCase
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class TestWorkspace(TestCase):
|
|
10
|
-
"""Test Jac Workspace."""
|
|
11
|
-
|
|
12
|
-
def test_workspace_basic(self) -> None:
|
|
13
|
-
"""Basic test of functionarlity."""
|
|
14
|
-
ws = Workspace(path=os.path.join(os.path.dirname(__file__)))
|
|
15
|
-
self.assertGreater(len(ws.modules.keys()), 4)
|
|
16
|
-
|
|
17
|
-
def test_dependecies_basic(self) -> None:
|
|
18
|
-
"""Basic test of functionarlity."""
|
|
19
|
-
ws = Workspace(path=os.path.join(os.path.dirname(__file__)))
|
|
20
|
-
key = [i for i in ws.modules.keys() if "fam.jac" in i][0]
|
|
21
|
-
self.assertGreater(len(ws.get_dependencies(key)), 0)
|
|
22
|
-
|
|
23
|
-
def test_symbols_basic(self) -> None:
|
|
24
|
-
"""Basic test of functionarlity."""
|
|
25
|
-
ws = Workspace(path=os.path.join(os.path.dirname(__file__)))
|
|
26
|
-
key = [i for i in ws.modules.keys() if "fam.jac" in i][0]
|
|
27
|
-
self.assertGreater(len(ws.get_symbols(key)), 5)
|
|
28
|
-
|
|
29
|
-
def test_get_defs_basic(self) -> None:
|
|
30
|
-
"""Basic test of functionarlity."""
|
|
31
|
-
ws = Workspace(path=os.path.join(os.path.dirname(__file__)))
|
|
32
|
-
key = [i for i in ws.modules.keys() if "fam.jac" in i][0]
|
|
33
|
-
self.assertGreater(len(ws.get_definitions(key)), 5)
|
|
34
|
-
|
|
35
|
-
def test_get_uses_basic(self) -> None:
|
|
36
|
-
"""Basic test of functionarlity."""
|
|
37
|
-
ws = Workspace(path=os.path.join(os.path.dirname(__file__)))
|
|
38
|
-
key = [i for i in ws.modules.keys() if "fam.jac" in i][0]
|
|
39
|
-
self.assertGreater(len(ws.get_uses(key)), 5)
|
|
40
|
-
|
|
41
|
-
def test_man_code_dir(self) -> None:
|
|
42
|
-
"""Test of circle workspace."""
|
|
43
|
-
loc = os.path.join(os.path.dirname(__file__))
|
|
44
|
-
ws = Workspace(path=loc + "/../../../examples/manual_code")
|
|
45
|
-
key = [i for i in ws.modules.keys() if "circle.jac" in i][0]
|
|
46
|
-
# print(ws.modules[key].ir.sym_tab.pp())
|
|
47
|
-
# for i in ws.get_symbols(key):
|
|
48
|
-
# print(i.decl.pp(depth=2))
|
|
49
|
-
out = ""
|
|
50
|
-
for i in ws.get_uses(key):
|
|
51
|
-
# print(i.pp(depth=2).strip())
|
|
52
|
-
out += i.pp(depth=2)
|
|
53
|
-
for i in [
|
|
54
|
-
"math",
|
|
55
|
-
"calculate_area",
|
|
56
|
-
"RAD",
|
|
57
|
-
"expected_area",
|
|
58
|
-
"Circle",
|
|
59
|
-
"c",
|
|
60
|
-
"ShapeType",
|
|
61
|
-
"float",
|
|
62
|
-
"radius",
|
|
63
|
-
"CIRCLE",
|
|
64
|
-
"Shape",
|
|
65
|
-
"__init__",
|
|
66
|
-
"print",
|
|
67
|
-
]:
|
|
68
|
-
self.assertIn(i, out)
|
|
69
|
-
|
|
70
|
-
# def test_decl_impl(self) -> None:
|
|
71
|
-
# """Test of circle workspace."""
|
|
72
|
-
# loc = os.path.join(os.path.dirname(__file__))
|
|
73
|
-
# ws = Workspace(path=loc + "/../../../examples/manual_code")
|
|
74
|
-
# key = [i for i in ws.modules.keys() if "circle_clean.jac" in i][0]
|
|
75
|
-
# out = ""
|
|
76
|
-
# for i in ws.get_uses(key):
|
|
77
|
-
# out += i.pp(depth=2)
|
|
78
|
-
# for i in [
|
|
79
|
-
# "math",
|
|
80
|
-
# "calculate_area",
|
|
81
|
-
# "RAD",
|
|
82
|
-
# "expected_area",
|
|
83
|
-
# "Circle",
|
|
84
|
-
# "c",
|
|
85
|
-
# "ShapeType",
|
|
86
|
-
# "float",
|
|
87
|
-
# "radius",
|
|
88
|
-
# "CIRCLE",
|
|
89
|
-
# "Shape",
|
|
90
|
-
# "__init__",
|
|
91
|
-
# "print",
|
|
92
|
-
# ]:
|
|
93
|
-
# self.assertIn(i, out)
|
jaclang/compiler/workspace.py
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
"""Living Workspace of Jac project."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
from typing import Optional, Sequence
|
|
7
|
-
|
|
8
|
-
import jaclang.compiler.absyntree as ast
|
|
9
|
-
from jaclang.compiler.compile import jac_str_to_pass
|
|
10
|
-
from jaclang.compiler.passes.main import DefUsePass, schedules
|
|
11
|
-
from jaclang.compiler.passes.transform import Alert
|
|
12
|
-
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def sym_tab_list(sym_tab: SymbolTable, file_path: str) -> Sequence[SymbolTable]:
|
|
16
|
-
"""Iterate through symbol table."""
|
|
17
|
-
sym_tabs = (
|
|
18
|
-
[sym_tab]
|
|
19
|
-
if not (
|
|
20
|
-
isinstance(sym_tab.owner, ast.Module)
|
|
21
|
-
and sym_tab.owner.loc.mod_path != file_path
|
|
22
|
-
)
|
|
23
|
-
else []
|
|
24
|
-
)
|
|
25
|
-
for i in sym_tab.kid:
|
|
26
|
-
sym_tabs += sym_tab_list(i, file_path=file_path)
|
|
27
|
-
return sym_tabs
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class ModuleInfo:
|
|
31
|
-
"""Module IR and Stats."""
|
|
32
|
-
|
|
33
|
-
def __init__(
|
|
34
|
-
self,
|
|
35
|
-
ir: Optional[ast.Module],
|
|
36
|
-
errors: Sequence[Alert],
|
|
37
|
-
warnings: Sequence[Alert],
|
|
38
|
-
) -> None:
|
|
39
|
-
"""Initialize module info."""
|
|
40
|
-
self.ir = ir
|
|
41
|
-
self.errors = errors
|
|
42
|
-
self.warnings = warnings
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class Workspace:
|
|
46
|
-
"""Class for managing workspace."""
|
|
47
|
-
|
|
48
|
-
def __init__(
|
|
49
|
-
self, path: str, lazy_parse: bool = False, type_check: bool = False
|
|
50
|
-
) -> None:
|
|
51
|
-
"""Initialize workspace."""
|
|
52
|
-
self.path = path
|
|
53
|
-
self.modules: dict[str, ModuleInfo] = {}
|
|
54
|
-
self.lazy_parse = lazy_parse
|
|
55
|
-
self.type_check = type_check
|
|
56
|
-
self.rebuild_workspace()
|
|
57
|
-
|
|
58
|
-
def rebuild_workspace(self) -> None:
|
|
59
|
-
"""Rebuild workspace."""
|
|
60
|
-
self.modules = {}
|
|
61
|
-
for file in [
|
|
62
|
-
os.path.normpath(os.path.join(root, name))
|
|
63
|
-
for root, _, files in os.walk(self.path)
|
|
64
|
-
for name in files
|
|
65
|
-
if name.endswith(".jac")
|
|
66
|
-
]:
|
|
67
|
-
if file in self.modules:
|
|
68
|
-
continue
|
|
69
|
-
if self.lazy_parse:
|
|
70
|
-
# If lazy_parse is True, add the file to modules with empty IR
|
|
71
|
-
self.modules[file] = ModuleInfo(
|
|
72
|
-
ir=None,
|
|
73
|
-
errors=[],
|
|
74
|
-
warnings=[],
|
|
75
|
-
)
|
|
76
|
-
continue
|
|
77
|
-
|
|
78
|
-
with open(file, "r") as f:
|
|
79
|
-
source = f.read()
|
|
80
|
-
build = jac_str_to_pass(
|
|
81
|
-
jac_str=source,
|
|
82
|
-
file_path=file,
|
|
83
|
-
schedule=(
|
|
84
|
-
schedules.py_code_gen_typed
|
|
85
|
-
if self.type_check
|
|
86
|
-
else schedules.py_code_gen
|
|
87
|
-
),
|
|
88
|
-
target=DefUsePass if not self.type_check else None,
|
|
89
|
-
)
|
|
90
|
-
if not isinstance(build.ir, ast.Module):
|
|
91
|
-
src = ast.JacSource(source, mod_path=file)
|
|
92
|
-
self.modules[file] = ModuleInfo(
|
|
93
|
-
ir=ast.Module(
|
|
94
|
-
name="",
|
|
95
|
-
doc=None,
|
|
96
|
-
body=[],
|
|
97
|
-
source=src,
|
|
98
|
-
is_imported=False,
|
|
99
|
-
kid=[src],
|
|
100
|
-
),
|
|
101
|
-
errors=build.errors_had,
|
|
102
|
-
warnings=build.warnings_had,
|
|
103
|
-
)
|
|
104
|
-
continue
|
|
105
|
-
self.modules[file] = ModuleInfo(
|
|
106
|
-
ir=build.ir,
|
|
107
|
-
errors=build.errors_had,
|
|
108
|
-
warnings=build.warnings_had,
|
|
109
|
-
)
|
|
110
|
-
if build.ir:
|
|
111
|
-
for sub in build.ir.mod_deps:
|
|
112
|
-
self.modules[sub] = ModuleInfo(
|
|
113
|
-
ir=build.ir.mod_deps[sub],
|
|
114
|
-
errors=build.errors_had,
|
|
115
|
-
warnings=build.warnings_had,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
def rebuild_file(
|
|
119
|
-
self, file_path: str, deep: bool = False, source: str = ""
|
|
120
|
-
) -> bool:
|
|
121
|
-
"""Rebuild a file."""
|
|
122
|
-
if source == "":
|
|
123
|
-
with open(file_path, "r") as f:
|
|
124
|
-
source = f.read()
|
|
125
|
-
build = jac_str_to_pass(
|
|
126
|
-
jac_str=source,
|
|
127
|
-
file_path=file_path,
|
|
128
|
-
schedule=(
|
|
129
|
-
schedules.py_code_gen_typed
|
|
130
|
-
if self.type_check
|
|
131
|
-
else schedules.py_code_gen
|
|
132
|
-
),
|
|
133
|
-
target=DefUsePass if not self.type_check else None,
|
|
134
|
-
)
|
|
135
|
-
if not isinstance(build.ir, ast.Module):
|
|
136
|
-
src = ast.JacSource(source, mod_path=file_path)
|
|
137
|
-
self.modules[file_path] = ModuleInfo(
|
|
138
|
-
ir=ast.Module(
|
|
139
|
-
name="",
|
|
140
|
-
doc=None,
|
|
141
|
-
body=[],
|
|
142
|
-
source=src,
|
|
143
|
-
is_imported=False,
|
|
144
|
-
kid=[src],
|
|
145
|
-
),
|
|
146
|
-
errors=build.errors_had,
|
|
147
|
-
warnings=build.warnings_had,
|
|
148
|
-
)
|
|
149
|
-
return False
|
|
150
|
-
self.modules[file_path] = ModuleInfo(
|
|
151
|
-
ir=build.ir,
|
|
152
|
-
errors=build.errors_had,
|
|
153
|
-
warnings=build.warnings_had,
|
|
154
|
-
)
|
|
155
|
-
if deep:
|
|
156
|
-
for sub in build.ir.mod_deps:
|
|
157
|
-
self.modules[sub] = ModuleInfo(
|
|
158
|
-
ir=build.ir.mod_deps[sub],
|
|
159
|
-
errors=build.errors_had,
|
|
160
|
-
warnings=build.warnings_had,
|
|
161
|
-
)
|
|
162
|
-
return True
|
|
163
|
-
|
|
164
|
-
def add_file(self, file_path: str) -> None:
|
|
165
|
-
"""Add a file to the workspace."""
|
|
166
|
-
self.rebuild_file(file_path)
|
|
167
|
-
|
|
168
|
-
def del_file(self, file_path: str) -> None:
|
|
169
|
-
"""Delete a file from the workspace."""
|
|
170
|
-
del self.modules[file_path]
|
|
171
|
-
|
|
172
|
-
def file_list(self) -> Sequence[str]:
|
|
173
|
-
"""Return a list of files in the workspace."""
|
|
174
|
-
return list(self.modules.keys())
|
|
175
|
-
|
|
176
|
-
def get_dependencies(
|
|
177
|
-
self, file_path: str, deep: bool = False
|
|
178
|
-
) -> list[ast.ModulePath]:
|
|
179
|
-
"""Return a list of dependencies for a file."""
|
|
180
|
-
mod_ir = self.modules[file_path].ir
|
|
181
|
-
if deep:
|
|
182
|
-
return (
|
|
183
|
-
[
|
|
184
|
-
i
|
|
185
|
-
for i in mod_ir.get_all_sub_nodes(ast.ModulePath)
|
|
186
|
-
if i.parent_of_type(ast.Import).hint.tag.value == "jac"
|
|
187
|
-
]
|
|
188
|
-
if mod_ir
|
|
189
|
-
else []
|
|
190
|
-
)
|
|
191
|
-
else:
|
|
192
|
-
return (
|
|
193
|
-
[
|
|
194
|
-
i
|
|
195
|
-
for i in mod_ir.get_all_sub_nodes(ast.ModulePath)
|
|
196
|
-
if i.loc.mod_path == file_path
|
|
197
|
-
and i.parent_of_type(ast.Import).hint.tag.value == "jac"
|
|
198
|
-
]
|
|
199
|
-
if mod_ir
|
|
200
|
-
else []
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
def get_symbols(self, file_path: str) -> Sequence[Symbol]:
|
|
204
|
-
"""Return a list of symbols for a file."""
|
|
205
|
-
symbols = []
|
|
206
|
-
mod_ir = self.modules[file_path].ir
|
|
207
|
-
if file_path in self.modules:
|
|
208
|
-
root_table = mod_ir.sym_tab if mod_ir else None
|
|
209
|
-
if file_path in self.modules and root_table:
|
|
210
|
-
for i in sym_tab_list(sym_tab=root_table, file_path=file_path):
|
|
211
|
-
symbols += list(i.tab.values())
|
|
212
|
-
return symbols
|
|
213
|
-
|
|
214
|
-
def get_definitions(
|
|
215
|
-
self, file_path: str
|
|
216
|
-
) -> Sequence[ast.AstSymbolNode]: # need test
|
|
217
|
-
"""Return a list of definitions for a file."""
|
|
218
|
-
defs = []
|
|
219
|
-
for i in self.get_symbols(file_path):
|
|
220
|
-
defs += i.defn
|
|
221
|
-
return defs
|
|
222
|
-
|
|
223
|
-
def get_uses(self, file_path: str) -> Sequence[ast.AstSymbolNode]: # need test
|
|
224
|
-
"""Return a list of definitions for a file."""
|
|
225
|
-
mod_ir = self.modules[file_path].ir
|
|
226
|
-
uses: list[ast.AstSymbolNode] = []
|
|
227
|
-
if self.lazy_parse:
|
|
228
|
-
return uses
|
|
229
|
-
if file_path in self.modules:
|
|
230
|
-
root_table = mod_ir.sym_tab if mod_ir else None
|
|
231
|
-
if file_path in self.modules and root_table:
|
|
232
|
-
for i in sym_tab_list(sym_tab=root_table, file_path=file_path):
|
|
233
|
-
uses += i.uses
|
|
234
|
-
return uses
|
|
File without changes
|
|
File without changes
|