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.

@@ -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
 
@@ -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.AstNode:
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 mod
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(msg, self.cur_node.loc if not node_override else node_override.loc)
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(msg, self.cur_node.loc if not node_override else node_override.loc)
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))
@@ -1 +1,3 @@
1
- with entry { print("hello"); }
1
+ with entry {
2
+ print("hello");
3
+ }
@@ -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)
@@ -2,101 +2,132 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from jaclang.compiler.compile import jac_str_to_pass
6
- from jaclang.compiler.passes.tool import FuseCommentsPass, JacFormatPass
7
- from jaclang.langserve.utils import debounce, log, log_error
8
- from jaclang.vendor.pygls.server import LanguageServer
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 = LanguageServer("jac-lsp", "v0.1")
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.3)
52
+ @debounce(0.1)
17
53
  async def did_change(
18
- ls: LanguageServer, params: lspt.DidChangeTextDocumentParams
54
+ ls: JacLangServer, params: lspt.DidChangeTextDocumentParams
19
55
  ) -> None:
20
56
  """Check syntax on change."""
21
- document = ls.workspace.get_document(params.text_document.uri)
22
- try:
23
- result = jac_str_to_pass(
24
- jac_str=document.source,
25
- file_path=document.path,
26
- schedule=[],
27
- )
28
- if not result.errors_had and not result.warnings_had:
29
- ls.publish_diagnostics(document.uri, [])
30
- else:
31
- ls.publish_diagnostics(
32
- document.uri,
33
- [
34
- lspt.Diagnostic(
35
- range=lspt.Range(
36
- start=lspt.Position(
37
- line=error.loc.first_line, character=error.loc.col_start
38
- ),
39
- end=lspt.Position(
40
- line=error.loc.last_line,
41
- character=error.loc.col_end,
42
- ),
43
- ),
44
- message=error.msg,
45
- severity=lspt.DiagnosticSeverity.Error,
46
- )
47
- for error in result.errors_had
48
- ],
49
- )
50
- except Exception as e:
51
- log_error(ls, f"Error during syntax check: {e}")
52
- log(f"Error during syntax check: {e}")
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 completions(params: lspt.CompletionParams) -> lspt.CompletionList:
60
- """Provide completions for the given completion request."""
61
- items = []
62
- document = server.workspace.get_text_document(params.text_document.uri)
63
- current_line = document.lines[params.position.line].strip()
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: LanguageServer, params: lspt.DocumentFormattingParams
127
+ ls: JacLangServer, params: lspt.DocumentFormattingParams
76
128
  ) -> list[lspt.TextEdit]:
77
129
  """Format the given document."""
78
- try:
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:
@@ -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
- from jaclang.vendor.pygls.server import LanguageServer
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.6.5
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][Jaclang] | [Getting started] | [Learn] | [Documentation] | [Contributing]
28
+ [Jac Website] | [Getting started] | [Learn] | [Documentation] | [Contributing]
29
29
 
30
30
  [![PyPI version](https://img.shields.io/pypi/v/jaclang.svg)](https://pypi.org/project/jaclang/) [![Tests](https://github.com/chandralegend/jaclang/actions/workflows/run_pytest.yml/badge.svg?branch=main)](https://github.com/chandralegend/jaclang/actions/workflows/run_pytest.yml) [![codecov](https://codecov.io/github/chandralegend/jaclang/graph/badge.svg?token=OAX26B0FE4)](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
- - **Easy:** Jac is designed to be easy to learn and use, while also being powerful.
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
- - **Reliability:** Our rich type system and runtime checks ensure your code is correct.
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
- - **AI Ready:** Jac provide easy to use Abstractions specially designed for LLMs.
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
- - **Data Spatial Programming:** Jac provides easy to use Abstractions for Data Spatial Programming.
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=PXHefWmwDO2ZD9iShs_Mt3-m_JP0f0HVCsE4UfPZjQg,126904
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=Cp_3p5lR7QekGqYYGYm6Blye5tmQAux7EuP6CBDRNpY,138547
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=oYXDWWlxYj0FGXxXUOPnmwnkFPmayd2fRoWngvDgXwc,86113
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=Z3TuHMJ7TyyBHt0XmRWEjMk8-t6logKs7XG_OTDJIvo,2162
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=p3n-JMJAerocPBA0p_MGf_F7KY-OosIqjHEqcjVrB30,31
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/server.py,sha256=6SSsYDU6OBNHbgO0p6O38yrLZrjqFfpiRMwVnA79XJs,3553
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=VsSdZQNVW5lS8ko8z-h4CnbCugs4UK44NLAqYqTGjwA,1490
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=EegsveW7I41Pvkh261LVr3smC08rcbUXLBkrhLTh9mY,27142
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.6.5.dist-info/METADATA,sha256=6vtnoi2-XOXoeB-n3ZgVJv5X7qAQ4C8p-LQglGBl-nc,4213
1474
- jaclang-0.6.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1475
- jaclang-0.6.5.dist-info/entry_points.txt,sha256=8sMi4Tvi9f8tQDN2QAXsSA2icO27zQ4GgEdph6bNEZM,49
1476
- jaclang-0.6.5.dist-info/RECORD,,
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)
@@ -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