jaclang 0.7.14__py3-none-any.whl → 0.7.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/cli/cli.py +11 -8
- jaclang/cli/cmdreg.py +9 -12
- jaclang/compiler/__init__.py +0 -2
- jaclang/compiler/absyntree.py +3 -8
- jaclang/compiler/passes/ir_pass.py +3 -12
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +4 -5
- jaclang/compiler/passes/main/import_pass.py +4 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +32 -31
- jaclang/compiler/passes/main/registry_pass.py +1 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +3 -20
- jaclang/compiler/passes/transform.py +4 -0
- jaclang/compiler/semtable.py +5 -3
- jaclang/compiler/tests/test_importer.py +3 -0
- jaclang/langserve/engine.py +210 -69
- jaclang/langserve/server.py +6 -10
- jaclang/langserve/tests/fixtures/base_module_structure.jac +1 -1
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/test_sem_tokens.py +277 -0
- jaclang/langserve/tests/test_server.py +4 -4
- jaclang/langserve/utils.py +128 -95
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +23 -16
- jaclang/plugin/feature.py +4 -5
- jaclang/plugin/spec.py +2 -2
- jaclang/{core → runtimelib}/architype.py +1 -1
- jaclang/{core → runtimelib}/context.py +4 -1
- jaclang/runtimelib/importer.py +414 -0
- jaclang/runtimelib/machine.py +19 -0
- jaclang/{core → runtimelib}/utils.py +1 -1
- jaclang/tests/fixtures/deep/one_lev.jac +3 -3
- jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +7 -0
- jaclang/utils/treeprinter.py +0 -4
- {jaclang-0.7.14.dist-info → jaclang-0.7.15.dist-info}/METADATA +1 -1
- {jaclang-0.7.14.dist-info → jaclang-0.7.15.dist-info}/RECORD +42 -40
- jaclang/core/importer.py +0 -344
- /jaclang/{core → runtimelib}/__init__.py +0 -0
- /jaclang/{core → runtimelib}/constructs.py +0 -0
- /jaclang/{core → runtimelib}/memory.py +0 -0
- /jaclang/{core → runtimelib}/test.py +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.15.dist-info}/WHEEL +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.15.dist-info}/entry_points.txt +0 -0
jaclang/plugin/spec.py
CHANGED
|
@@ -8,7 +8,7 @@ from typing import Any, Callable, Optional, TYPE_CHECKING, Type, TypeVar, Union
|
|
|
8
8
|
from jaclang.compiler.absyntree import Module
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
-
from jaclang.
|
|
11
|
+
from jaclang.runtimelib.constructs import EdgeArchitype, NodeArchitype
|
|
12
12
|
from jaclang.plugin.default import (
|
|
13
13
|
Architype,
|
|
14
14
|
EdgeDir,
|
|
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|
|
17
17
|
Root,
|
|
18
18
|
DSFunc,
|
|
19
19
|
)
|
|
20
|
-
from jaclang.
|
|
20
|
+
from jaclang.runtimelib.memory import Memory
|
|
21
21
|
|
|
22
22
|
import pluggy
|
|
23
23
|
|
|
@@ -8,7 +8,7 @@ from typing import Any, Callable, Optional
|
|
|
8
8
|
from uuid import UUID, uuid4
|
|
9
9
|
|
|
10
10
|
from jaclang.compiler.constant import EdgeDir
|
|
11
|
-
from jaclang.
|
|
11
|
+
from jaclang.runtimelib.utils import collect_node_connections
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
@dataclass(eq=False)
|
|
@@ -8,6 +8,7 @@ from typing import Callable, Optional
|
|
|
8
8
|
from uuid import UUID
|
|
9
9
|
|
|
10
10
|
from .architype import Architype, Root
|
|
11
|
+
from .machine import JacMachine
|
|
11
12
|
from .memory import Memory, ShelveStorage
|
|
12
13
|
|
|
13
14
|
|
|
@@ -22,13 +23,15 @@ class ExecutionContext:
|
|
|
22
23
|
super().__init__()
|
|
23
24
|
self.mem = ShelveStorage()
|
|
24
25
|
self.root = None
|
|
26
|
+
self.jac_machine = JacMachine()
|
|
25
27
|
|
|
26
|
-
def init_memory(self, session: str = "") -> None:
|
|
28
|
+
def init_memory(self, base_path: str = "", session: str = "") -> None:
|
|
27
29
|
"""Initialize memory."""
|
|
28
30
|
if session:
|
|
29
31
|
self.mem = ShelveStorage(session)
|
|
30
32
|
else:
|
|
31
33
|
self.mem = Memory()
|
|
34
|
+
self.jac_machine = JacMachine(base_path)
|
|
32
35
|
|
|
33
36
|
def get_root(self) -> Root:
|
|
34
37
|
"""Get the root object."""
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
"""Special Imports for Jac Code."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib
|
|
6
|
+
import marshal
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import types
|
|
10
|
+
from os import getcwd, path
|
|
11
|
+
from typing import Optional, Union
|
|
12
|
+
|
|
13
|
+
from jaclang.compiler.absyntree import Module
|
|
14
|
+
from jaclang.compiler.compile import compile_jac
|
|
15
|
+
from jaclang.compiler.constant import Constants as Con
|
|
16
|
+
from jaclang.runtimelib.machine import JacMachine
|
|
17
|
+
from jaclang.runtimelib.utils import sys_path_context
|
|
18
|
+
from jaclang.utils.log import logging
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ImportPathSpec:
|
|
24
|
+
"""Import Specification."""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
target: str,
|
|
29
|
+
base_path: str,
|
|
30
|
+
absorb: bool,
|
|
31
|
+
cachable: bool,
|
|
32
|
+
mdl_alias: Optional[str],
|
|
33
|
+
override_name: Optional[str],
|
|
34
|
+
mod_bundle: Optional[Module | str],
|
|
35
|
+
lng: Optional[str],
|
|
36
|
+
items: Optional[dict[str, Union[str, Optional[str]]]],
|
|
37
|
+
) -> None:
|
|
38
|
+
"""Initialize the ImportPathSpec object."""
|
|
39
|
+
self.target = target
|
|
40
|
+
self.base_path = base_path
|
|
41
|
+
self.absorb = absorb
|
|
42
|
+
self.cachable = cachable
|
|
43
|
+
self.mdl_alias = mdl_alias
|
|
44
|
+
self.override_name = override_name
|
|
45
|
+
self.mod_bundle = mod_bundle
|
|
46
|
+
self.language = lng
|
|
47
|
+
self.items = items
|
|
48
|
+
self.dir_path, self.file_name = path.split(path.join(*(target.split("."))))
|
|
49
|
+
self.module_name = path.splitext(self.file_name)[0]
|
|
50
|
+
self.package_path = self.dir_path.replace(path.sep, ".")
|
|
51
|
+
self.caller_dir = self.get_caller_dir()
|
|
52
|
+
self.full_target = path.abspath(path.join(self.caller_dir, self.file_name))
|
|
53
|
+
|
|
54
|
+
def get_caller_dir(self) -> str:
|
|
55
|
+
"""Get the directory of the caller."""
|
|
56
|
+
caller_dir = (
|
|
57
|
+
self.base_path
|
|
58
|
+
if path.isdir(self.base_path)
|
|
59
|
+
else path.dirname(self.base_path)
|
|
60
|
+
)
|
|
61
|
+
caller_dir = caller_dir if caller_dir else getcwd()
|
|
62
|
+
chomp_target = self.target
|
|
63
|
+
if chomp_target.startswith("."):
|
|
64
|
+
chomp_target = chomp_target[1:]
|
|
65
|
+
while chomp_target.startswith("."):
|
|
66
|
+
caller_dir = path.dirname(caller_dir)
|
|
67
|
+
chomp_target = chomp_target[1:]
|
|
68
|
+
return path.join(caller_dir, self.dir_path)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ImportReturn:
|
|
72
|
+
"""Import Return Object."""
|
|
73
|
+
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
ret_mod: types.ModuleType,
|
|
77
|
+
ret_items: list[types.ModuleType],
|
|
78
|
+
importer: Importer,
|
|
79
|
+
) -> None:
|
|
80
|
+
"""Initialize the ImportReturn object."""
|
|
81
|
+
self.ret_mod = ret_mod
|
|
82
|
+
self.ret_items = ret_items
|
|
83
|
+
self.importer = importer
|
|
84
|
+
|
|
85
|
+
def process_items(
|
|
86
|
+
self,
|
|
87
|
+
module: types.ModuleType,
|
|
88
|
+
items: dict[str, Union[str, Optional[str]]],
|
|
89
|
+
caller_dir: str,
|
|
90
|
+
lang: Optional[str],
|
|
91
|
+
mod_bundle: Optional[Module] = None,
|
|
92
|
+
cachable: bool = True,
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Process items within a module by handling renaming and potentially loading missing attributes."""
|
|
95
|
+
|
|
96
|
+
def handle_item_loading(
|
|
97
|
+
item: types.ModuleType, alias: Union[str, Optional[str]]
|
|
98
|
+
) -> None:
|
|
99
|
+
if item:
|
|
100
|
+
self.ret_items.append(item)
|
|
101
|
+
setattr(module, name, item)
|
|
102
|
+
if alias and alias != name and not isinstance(alias, bool):
|
|
103
|
+
setattr(module, alias, item)
|
|
104
|
+
|
|
105
|
+
for name, alias in items.items():
|
|
106
|
+
try:
|
|
107
|
+
item = getattr(module, name)
|
|
108
|
+
handle_item_loading(item, alias)
|
|
109
|
+
except AttributeError:
|
|
110
|
+
if lang == "jac":
|
|
111
|
+
jac_file_path = (
|
|
112
|
+
os.path.join(module.__path__[0], f"{name}.jac")
|
|
113
|
+
if hasattr(module, "__path__")
|
|
114
|
+
else module.__file__
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
if jac_file_path and os.path.isfile(jac_file_path):
|
|
118
|
+
item = self.load_jac_file(
|
|
119
|
+
module=module,
|
|
120
|
+
name=name,
|
|
121
|
+
jac_file_path=jac_file_path,
|
|
122
|
+
mod_bundle=mod_bundle,
|
|
123
|
+
cachable=cachable,
|
|
124
|
+
caller_dir=caller_dir,
|
|
125
|
+
)
|
|
126
|
+
handle_item_loading(item, alias)
|
|
127
|
+
else:
|
|
128
|
+
if hasattr(module, "__path__"):
|
|
129
|
+
full_module_name = f"{module.__name__}.{name}"
|
|
130
|
+
item = importlib.import_module(full_module_name)
|
|
131
|
+
handle_item_loading(item, alias)
|
|
132
|
+
|
|
133
|
+
def load_jac_file(
|
|
134
|
+
self,
|
|
135
|
+
module: types.ModuleType,
|
|
136
|
+
name: str,
|
|
137
|
+
jac_file_path: str,
|
|
138
|
+
mod_bundle: Optional[Module],
|
|
139
|
+
cachable: bool,
|
|
140
|
+
caller_dir: str,
|
|
141
|
+
) -> Optional[types.ModuleType]:
|
|
142
|
+
"""Load a single .jac file into the specified module component."""
|
|
143
|
+
try:
|
|
144
|
+
package_name = (
|
|
145
|
+
f"{module.__name__}.{name}"
|
|
146
|
+
if hasattr(module, "__path__")
|
|
147
|
+
else module.__name__
|
|
148
|
+
)
|
|
149
|
+
if isinstance(self.importer, JacImporter):
|
|
150
|
+
new_module = sys.modules.get(
|
|
151
|
+
package_name,
|
|
152
|
+
self.importer.create_jac_py_module(
|
|
153
|
+
mod_bundle, name, module.__name__, jac_file_path
|
|
154
|
+
),
|
|
155
|
+
)
|
|
156
|
+
codeobj = self.importer.get_codeobj(
|
|
157
|
+
full_target=jac_file_path,
|
|
158
|
+
module_name=name,
|
|
159
|
+
mod_bundle=mod_bundle,
|
|
160
|
+
cachable=cachable,
|
|
161
|
+
caller_dir=caller_dir,
|
|
162
|
+
)
|
|
163
|
+
if not codeobj:
|
|
164
|
+
raise ImportError(f"No bytecode found for {jac_file_path}")
|
|
165
|
+
|
|
166
|
+
exec(codeobj, new_module.__dict__)
|
|
167
|
+
return getattr(new_module, name, new_module)
|
|
168
|
+
except ImportError as e:
|
|
169
|
+
logger.error(
|
|
170
|
+
f"Failed to load {name} from {jac_file_path} in {module.__name__}: {str(e)}"
|
|
171
|
+
)
|
|
172
|
+
return None
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class Importer:
|
|
176
|
+
"""Abstract base class for all importers."""
|
|
177
|
+
|
|
178
|
+
def __init__(self, jac_machine: JacMachine) -> None:
|
|
179
|
+
"""Initialize the Importer object."""
|
|
180
|
+
self.jac_machine = jac_machine
|
|
181
|
+
self.result: Optional[ImportReturn] = None
|
|
182
|
+
|
|
183
|
+
def run_import(self, spec: ImportPathSpec) -> ImportReturn:
|
|
184
|
+
"""Run the import process."""
|
|
185
|
+
raise NotImplementedError
|
|
186
|
+
|
|
187
|
+
def update_sys(self, module: types.ModuleType, spec: ImportPathSpec) -> None:
|
|
188
|
+
"""Update sys.modules with the newly imported module."""
|
|
189
|
+
if spec.module_name not in sys.modules:
|
|
190
|
+
sys.modules[spec.module_name] = module
|
|
191
|
+
|
|
192
|
+
def get_codeobj(
|
|
193
|
+
self,
|
|
194
|
+
full_target: str,
|
|
195
|
+
module_name: str,
|
|
196
|
+
mod_bundle: Optional[Module],
|
|
197
|
+
cachable: bool,
|
|
198
|
+
caller_dir: str,
|
|
199
|
+
) -> Optional[types.CodeType]:
|
|
200
|
+
"""Get the code object for a given module."""
|
|
201
|
+
if mod_bundle:
|
|
202
|
+
codeobj = mod_bundle.mod_deps[full_target].gen.py_bytecode
|
|
203
|
+
return marshal.loads(codeobj) if isinstance(codeobj, bytes) else None
|
|
204
|
+
gen_dir = os.path.join(caller_dir, Con.JAC_GEN_DIR)
|
|
205
|
+
pyc_file_path = os.path.join(gen_dir, module_name + ".jbc")
|
|
206
|
+
if cachable and os.path.exists(pyc_file_path):
|
|
207
|
+
with open(pyc_file_path, "rb") as f:
|
|
208
|
+
return marshal.load(f)
|
|
209
|
+
|
|
210
|
+
result = compile_jac(full_target, cache_result=cachable)
|
|
211
|
+
if result.errors_had or not result.ir.gen.py_bytecode:
|
|
212
|
+
logger.error(
|
|
213
|
+
f"While importing {len(result.errors_had)} errors"
|
|
214
|
+
f" found in {full_target}"
|
|
215
|
+
)
|
|
216
|
+
return None
|
|
217
|
+
if result.ir.gen.py_bytecode is not None:
|
|
218
|
+
return marshal.loads(result.ir.gen.py_bytecode)
|
|
219
|
+
else:
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class PythonImporter(Importer):
|
|
224
|
+
"""Importer for Python modules."""
|
|
225
|
+
|
|
226
|
+
def __init__(self, jac_machine: JacMachine) -> None:
|
|
227
|
+
"""Initialize the PythonImporter object."""
|
|
228
|
+
self.jac_machine = jac_machine
|
|
229
|
+
|
|
230
|
+
def run_import(self, spec: ImportPathSpec) -> ImportReturn:
|
|
231
|
+
"""Run the import process for Python modules."""
|
|
232
|
+
try:
|
|
233
|
+
loaded_items: list = []
|
|
234
|
+
if spec.target.startswith("."):
|
|
235
|
+
spec.target = spec.target.lstrip(".")
|
|
236
|
+
full_target = path.normpath(path.join(spec.caller_dir, spec.target))
|
|
237
|
+
imp_spec = importlib.util.spec_from_file_location(
|
|
238
|
+
spec.target, full_target + ".py"
|
|
239
|
+
)
|
|
240
|
+
if imp_spec and imp_spec.loader:
|
|
241
|
+
imported_module = importlib.util.module_from_spec(imp_spec)
|
|
242
|
+
sys.modules[imp_spec.name] = imported_module
|
|
243
|
+
imp_spec.loader.exec_module(imported_module)
|
|
244
|
+
else:
|
|
245
|
+
raise ImportError(
|
|
246
|
+
f"Cannot find module {spec.target} at {full_target}"
|
|
247
|
+
)
|
|
248
|
+
else:
|
|
249
|
+
imported_module = importlib.import_module(name=spec.target)
|
|
250
|
+
|
|
251
|
+
main_module = __import__("__main__")
|
|
252
|
+
if spec.absorb:
|
|
253
|
+
for name in dir(imported_module):
|
|
254
|
+
if not name.startswith("_"):
|
|
255
|
+
setattr(main_module, name, getattr(imported_module, name))
|
|
256
|
+
|
|
257
|
+
elif spec.items:
|
|
258
|
+
for name, alias in spec.items.items():
|
|
259
|
+
if isinstance(alias, bool):
|
|
260
|
+
alias = name
|
|
261
|
+
try:
|
|
262
|
+
item = getattr(imported_module, name)
|
|
263
|
+
if item not in loaded_items:
|
|
264
|
+
setattr(
|
|
265
|
+
main_module,
|
|
266
|
+
alias if isinstance(alias, str) else name,
|
|
267
|
+
item,
|
|
268
|
+
)
|
|
269
|
+
loaded_items.append(item)
|
|
270
|
+
except AttributeError as e:
|
|
271
|
+
if hasattr(imported_module, "__path__"):
|
|
272
|
+
item = importlib.import_module(f"{spec.target}.{name}")
|
|
273
|
+
if item not in loaded_items:
|
|
274
|
+
setattr(
|
|
275
|
+
main_module,
|
|
276
|
+
alias if isinstance(alias, str) else name,
|
|
277
|
+
item,
|
|
278
|
+
)
|
|
279
|
+
loaded_items.append(item)
|
|
280
|
+
else:
|
|
281
|
+
raise e
|
|
282
|
+
|
|
283
|
+
else:
|
|
284
|
+
setattr(
|
|
285
|
+
__import__("__main__"),
|
|
286
|
+
spec.mdl_alias if isinstance(spec.mdl_alias, str) else spec.target,
|
|
287
|
+
imported_module,
|
|
288
|
+
)
|
|
289
|
+
self.result = ImportReturn(imported_module, loaded_items, self)
|
|
290
|
+
return self.result
|
|
291
|
+
|
|
292
|
+
except ImportError as e:
|
|
293
|
+
raise e
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class JacImporter(Importer):
|
|
297
|
+
"""Importer for Jac modules."""
|
|
298
|
+
|
|
299
|
+
def __init__(self, jac_machine: JacMachine) -> None:
|
|
300
|
+
"""Initialize the JacImporter object."""
|
|
301
|
+
self.jac_machine = jac_machine
|
|
302
|
+
|
|
303
|
+
def get_sys_mod_name(self, full_target: str) -> str:
|
|
304
|
+
"""Generate the system module name based on full target path and package path."""
|
|
305
|
+
if full_target == self.jac_machine.base_path_dir:
|
|
306
|
+
return path.basename(self.jac_machine.base_path_dir)
|
|
307
|
+
relative_path = path.relpath(full_target, start=self.jac_machine.base_path_dir)
|
|
308
|
+
base_name = path.splitext(relative_path)[0]
|
|
309
|
+
sys_mod_name = base_name.replace(os.sep, ".").strip(".")
|
|
310
|
+
return sys_mod_name
|
|
311
|
+
|
|
312
|
+
def handle_directory(
|
|
313
|
+
self, module_name: str, full_mod_path: str, mod_bundle: Optional[Module | str]
|
|
314
|
+
) -> types.ModuleType:
|
|
315
|
+
"""Import from a directory that potentially contains multiple Jac modules."""
|
|
316
|
+
module_name = self.get_sys_mod_name(full_mod_path)
|
|
317
|
+
module = types.ModuleType(module_name)
|
|
318
|
+
module.__name__ = module_name
|
|
319
|
+
module.__path__ = [full_mod_path]
|
|
320
|
+
module.__file__ = None
|
|
321
|
+
module.__dict__["__jac_mod_bundle__"] = mod_bundle
|
|
322
|
+
|
|
323
|
+
if module_name not in sys.modules:
|
|
324
|
+
sys.modules[module_name] = module
|
|
325
|
+
return module
|
|
326
|
+
|
|
327
|
+
def create_jac_py_module(
|
|
328
|
+
self,
|
|
329
|
+
mod_bundle: Optional[Module | str],
|
|
330
|
+
module_name: str,
|
|
331
|
+
package_path: str,
|
|
332
|
+
full_target: str,
|
|
333
|
+
) -> types.ModuleType:
|
|
334
|
+
"""Create a module."""
|
|
335
|
+
module = types.ModuleType(module_name)
|
|
336
|
+
module.__file__ = full_target
|
|
337
|
+
module.__name__ = module_name
|
|
338
|
+
module.__dict__["__jac_mod_bundle__"] = mod_bundle
|
|
339
|
+
sys.modules[module_name] = module
|
|
340
|
+
if package_path:
|
|
341
|
+
base_path = full_target.split(package_path.replace(".", path.sep))[0]
|
|
342
|
+
parts = package_path.split(".")
|
|
343
|
+
for i in range(len(parts)):
|
|
344
|
+
package_name = ".".join(parts[: i + 1])
|
|
345
|
+
if package_name not in sys.modules:
|
|
346
|
+
full_mod_path = path.join(
|
|
347
|
+
base_path, package_name.replace(".", path.sep)
|
|
348
|
+
)
|
|
349
|
+
self.handle_directory(
|
|
350
|
+
module_name=package_name,
|
|
351
|
+
full_mod_path=full_mod_path,
|
|
352
|
+
mod_bundle=mod_bundle,
|
|
353
|
+
)
|
|
354
|
+
setattr(sys.modules[package_path], module_name, module)
|
|
355
|
+
sys.modules[f"{package_path}.{module_name}"] = module
|
|
356
|
+
|
|
357
|
+
return module
|
|
358
|
+
|
|
359
|
+
def run_import(self, spec: ImportPathSpec) -> ImportReturn:
|
|
360
|
+
"""Run the import process for Jac modules."""
|
|
361
|
+
unique_loaded_items: list[types.ModuleType] = []
|
|
362
|
+
module = None
|
|
363
|
+
valid_mod_bundle = (
|
|
364
|
+
sys.modules[spec.mod_bundle].__jac_mod_bundle__
|
|
365
|
+
if isinstance(spec.mod_bundle, str)
|
|
366
|
+
and spec.mod_bundle in sys.modules
|
|
367
|
+
and "__jac_mod_bundle__" in sys.modules[spec.mod_bundle].__dict__
|
|
368
|
+
else None
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
if not module:
|
|
372
|
+
if os.path.isdir(spec.full_target):
|
|
373
|
+
module = self.handle_directory(
|
|
374
|
+
spec.module_name, spec.full_target, valid_mod_bundle
|
|
375
|
+
)
|
|
376
|
+
else:
|
|
377
|
+
spec.full_target += ".jac" if spec.language == "jac" else ".py"
|
|
378
|
+
module_name = self.get_sys_mod_name(spec.full_target)
|
|
379
|
+
module_name = (
|
|
380
|
+
spec.override_name if spec.override_name else spec.module_name
|
|
381
|
+
)
|
|
382
|
+
module = self.create_jac_py_module(
|
|
383
|
+
valid_mod_bundle,
|
|
384
|
+
module_name,
|
|
385
|
+
spec.package_path,
|
|
386
|
+
spec.full_target,
|
|
387
|
+
)
|
|
388
|
+
codeobj = self.get_codeobj(
|
|
389
|
+
spec.full_target,
|
|
390
|
+
module_name,
|
|
391
|
+
valid_mod_bundle,
|
|
392
|
+
spec.cachable,
|
|
393
|
+
caller_dir=spec.caller_dir,
|
|
394
|
+
)
|
|
395
|
+
try:
|
|
396
|
+
if not codeobj:
|
|
397
|
+
raise ImportError(f"No bytecode found for {spec.full_target}")
|
|
398
|
+
with sys_path_context(spec.caller_dir):
|
|
399
|
+
exec(codeobj, module.__dict__)
|
|
400
|
+
except Exception as e:
|
|
401
|
+
raise ImportError(f"Error importing {spec.full_target}: {str(e)}")
|
|
402
|
+
|
|
403
|
+
import_return = ImportReturn(module, unique_loaded_items, self)
|
|
404
|
+
if spec.items:
|
|
405
|
+
import_return.process_items(
|
|
406
|
+
module=module,
|
|
407
|
+
items=spec.items,
|
|
408
|
+
caller_dir=spec.caller_dir,
|
|
409
|
+
mod_bundle=valid_mod_bundle,
|
|
410
|
+
cachable=spec.cachable,
|
|
411
|
+
lang=spec.language,
|
|
412
|
+
)
|
|
413
|
+
self.result = import_return
|
|
414
|
+
return self.result
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Jac Machine module."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class JacMachine:
|
|
7
|
+
"""JacMachine to handle the VM-related functionalities and loaded programs."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, base_path: str = "") -> None:
|
|
10
|
+
"""Initialize the JacMachine object."""
|
|
11
|
+
# self.loaded_modules: Dict[str, types.ModuleType] = {}
|
|
12
|
+
if not len(base_path):
|
|
13
|
+
base_path = os.getcwd()
|
|
14
|
+
self.base_path = base_path
|
|
15
|
+
self.base_path_dir = (
|
|
16
|
+
os.path.dirname(base_path)
|
|
17
|
+
if not os.path.isdir(base_path)
|
|
18
|
+
else os.path.abspath(base_path)
|
|
19
|
+
)
|
|
@@ -11,7 +11,7 @@ import jaclang.compiler.absyntree as ast
|
|
|
11
11
|
from jaclang.compiler.semtable import SemScope
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from jaclang.
|
|
14
|
+
from jaclang.runtimelib.constructs import NodeAnchor, NodeArchitype
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@contextmanager
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import:jac from .deeper, snd_lev as snd_lev;
|
|
2
|
-
import:jac from ..deep, deeper;
|
|
3
|
-
import:jac from ., deeper as mydeeper;
|
|
2
|
+
# import:jac from ..deep, deeper;
|
|
3
|
+
# import:jac from ., deeper as mydeeper;
|
|
4
4
|
|
|
5
5
|
can olprint -> str {
|
|
6
6
|
# deeper.snd_lev.slprint(); FIXME:
|
|
7
7
|
return "one level deeper" + snd_lev.slprint();
|
|
8
|
-
}
|
|
8
|
+
}
|
jaclang/tests/test_cli.py
CHANGED
|
@@ -46,7 +46,7 @@ class JacCliTests(TestCase):
|
|
|
46
46
|
sys.stderr = sys.__stderr__
|
|
47
47
|
stdout_value = captured_output.getvalue()
|
|
48
48
|
# print(stdout_value)
|
|
49
|
-
self.assertIn("
|
|
49
|
+
self.assertIn("Error", stdout_value)
|
|
50
50
|
|
|
51
51
|
def test_jac_ast_tool_pass_template(self) -> None:
|
|
52
52
|
"""Basic test for pass."""
|
jaclang/tests/test_language.py
CHANGED
|
@@ -60,6 +60,7 @@ class JacLanguageTests(TestCase):
|
|
|
60
60
|
|
|
61
61
|
def test_simple_jac_red(self) -> None:
|
|
62
62
|
"""Parse micro jac file."""
|
|
63
|
+
Jac.context().init_memory(base_path=self.examples_abs_path(""))
|
|
63
64
|
captured_output = io.StringIO()
|
|
64
65
|
sys.stdout = captured_output
|
|
65
66
|
jac_import("micro.simple_walk", base_path=self.examples_abs_path(""))
|
|
@@ -151,6 +152,7 @@ class JacLanguageTests(TestCase):
|
|
|
151
152
|
|
|
152
153
|
def test_filter_compr(self) -> None:
|
|
153
154
|
"""Testing filter comprehension."""
|
|
155
|
+
Jac.context().init_memory(base_path=self.examples_abs_path("./"))
|
|
154
156
|
captured_output = io.StringIO()
|
|
155
157
|
sys.stdout = captured_output
|
|
156
158
|
jac_import(
|
|
@@ -207,8 +209,10 @@ class JacLanguageTests(TestCase):
|
|
|
207
209
|
def test_deep_imports(self) -> None:
|
|
208
210
|
"""Parse micro jac file."""
|
|
209
211
|
Jac.get_root()._jac_.edges.clear()
|
|
212
|
+
Jac.context().init_memory(base_path=self.fixture_abs_path("./"))
|
|
210
213
|
captured_output = io.StringIO()
|
|
211
214
|
sys.stdout = captured_output
|
|
215
|
+
|
|
212
216
|
jac_import("deep_import", base_path=self.fixture_abs_path("./"))
|
|
213
217
|
sys.stdout = sys.__stdout__
|
|
214
218
|
stdout_value = captured_output.getvalue()
|
|
@@ -217,6 +221,7 @@ class JacLanguageTests(TestCase):
|
|
|
217
221
|
def test_deep_outer_imports_one(self) -> None:
|
|
218
222
|
"""Parse micro jac file."""
|
|
219
223
|
Jac.get_root()._jac_.edges.clear()
|
|
224
|
+
Jac.context().init_memory(base_path=self.fixture_abs_path("./"))
|
|
220
225
|
captured_output = io.StringIO()
|
|
221
226
|
sys.stdout = captured_output
|
|
222
227
|
jac_import(
|
|
@@ -230,6 +235,7 @@ class JacLanguageTests(TestCase):
|
|
|
230
235
|
def test_deep_outer_imports_from_loc(self) -> None:
|
|
231
236
|
"""Parse micro jac file."""
|
|
232
237
|
Jac.get_root()._jac_.edges.clear()
|
|
238
|
+
Jac.context().init_memory(base_path=self.fixture_abs_path("./deep/deeper/"))
|
|
233
239
|
captured_output = io.StringIO()
|
|
234
240
|
sys.stdout = captured_output
|
|
235
241
|
os.chdir(self.fixture_abs_path("./deep/deeper/"))
|
|
@@ -383,6 +389,7 @@ class JacLanguageTests(TestCase):
|
|
|
383
389
|
|
|
384
390
|
def test_typed_filter_compr(self) -> None:
|
|
385
391
|
"""Parse micro jac file."""
|
|
392
|
+
Jac.context().init_memory(base_path=self.examples_abs_path(""))
|
|
386
393
|
captured_output = io.StringIO()
|
|
387
394
|
sys.stdout = captured_output
|
|
388
395
|
jac_import(
|
jaclang/utils/treeprinter.py
CHANGED
|
@@ -248,10 +248,6 @@ def _build_symbol_tree_common(
|
|
|
248
248
|
symbol_node = SymbolTree(node_name=f"{sym.sym_name}", parent=symbols)
|
|
249
249
|
SymbolTree(node_name=f"{sym.access} {sym.sym_type}", parent=symbol_node)
|
|
250
250
|
|
|
251
|
-
# if isinstance(node.owner, ast.AstSymbolNode) and node.owner.sym_info:
|
|
252
|
-
# print("From tree printer", id(node.owner))
|
|
253
|
-
# SymbolTree(node_name=f"Datatype: {node.owner.sym_info.typ}", parent=symbol_node)
|
|
254
|
-
|
|
255
251
|
if sym.decl and sym.decl.loc.first_line > 0:
|
|
256
252
|
SymbolTree(
|
|
257
253
|
node_name=f"decl: line {sym.decl.loc.first_line}, col {sym.decl.loc.col_start}",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jaclang
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.15
|
|
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
|