jaclang 0.7.14__py3-none-any.whl → 0.7.17__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 +147 -77
- jaclang/cli/cmdreg.py +9 -12
- jaclang/compiler/__init__.py +19 -53
- jaclang/compiler/absyntree.py +94 -16
- jaclang/compiler/constant.py +8 -8
- jaclang/compiler/jac.lark +4 -3
- jaclang/compiler/parser.py +41 -25
- jaclang/compiler/passes/ir_pass.py +4 -13
- jaclang/compiler/passes/main/__init__.py +1 -1
- jaclang/compiler/passes/main/access_modifier_pass.py +96 -147
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +155 -54
- jaclang/compiler/passes/main/import_pass.py +99 -75
- jaclang/compiler/passes/main/py_collect_dep_pass.py +70 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +328 -565
- jaclang/compiler/passes/main/pyast_load_pass.py +33 -6
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -0
- jaclang/compiler/passes/main/registry_pass.py +37 -3
- jaclang/compiler/passes/main/schedules.py +9 -2
- jaclang/compiler/passes/main/sym_tab_build_pass.py +10 -6
- jaclang/compiler/passes/main/tests/__init__.py +1 -1
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.empty.impl.jac +0 -0
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.jac +1 -1
- jaclang/compiler/passes/main/tests/fixtures/py_imp_test.jac +29 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/color.py +3 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/constants.py +5 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/display.py +2 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +72 -13
- jaclang/compiler/passes/main/type_check_pass.py +22 -5
- jaclang/compiler/passes/tool/jac_formatter_pass.py +135 -89
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +37 -41
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +37 -42
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/access_mod_check.jac +27 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
- jaclang/compiler/passes/transform.py +4 -0
- jaclang/compiler/passes/utils/mypy_ast_build.py +45 -0
- jaclang/compiler/semtable.py +31 -7
- jaclang/compiler/symtable.py +16 -11
- jaclang/compiler/tests/test_importer.py +25 -10
- jaclang/langserve/engine.py +104 -118
- jaclang/langserve/sem_manager.py +379 -0
- jaclang/langserve/server.py +24 -11
- jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
- jaclang/langserve/tests/fixtures/circle.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/fixtures/rename.jac +30 -0
- jaclang/langserve/tests/test_sem_tokens.py +277 -0
- jaclang/langserve/tests/test_server.py +287 -17
- jaclang/langserve/utils.py +184 -98
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +288 -92
- jaclang/plugin/feature.py +65 -27
- jaclang/plugin/spec.py +62 -23
- jaclang/plugin/tests/fixtures/other_root_access.jac +82 -0
- jaclang/plugin/tests/test_jaseci.py +414 -42
- jaclang/runtimelib/architype.py +650 -0
- jaclang/{core → runtimelib}/constructs.py +5 -8
- jaclang/{core → runtimelib}/context.py +86 -59
- jaclang/runtimelib/importer.py +361 -0
- jaclang/runtimelib/machine.py +158 -0
- jaclang/runtimelib/memory.py +158 -0
- jaclang/{core → runtimelib}/utils.py +30 -15
- jaclang/settings.py +5 -4
- jaclang/tests/fixtures/abc.jac +3 -3
- jaclang/tests/fixtures/access_checker.jac +12 -17
- jaclang/tests/fixtures/access_modifier.jac +88 -33
- jaclang/tests/fixtures/baddy.jac +3 -0
- jaclang/tests/fixtures/baddy.test.jac +3 -0
- jaclang/tests/fixtures/bar.jac +34 -0
- jaclang/tests/fixtures/byllmissue.jac +1 -5
- jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
- jaclang/tests/fixtures/cls_method.jac +41 -0
- jaclang/tests/fixtures/dblhello.jac +6 -0
- jaclang/tests/fixtures/deep/one_lev.jac +3 -3
- jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
- jaclang/tests/fixtures/deep_import_mods.jac +13 -0
- jaclang/tests/fixtures/edge_node_walk.jac +1 -1
- jaclang/tests/fixtures/edge_ops.jac +1 -1
- jaclang/tests/fixtures/edges_walk.jac +1 -1
- jaclang/tests/fixtures/err.impl.jac +3 -0
- jaclang/tests/fixtures/err.jac +4 -2
- jaclang/tests/fixtures/err_runtime.jac +15 -0
- jaclang/tests/fixtures/foo.jac +43 -0
- jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
- jaclang/tests/fixtures/hello.jac +4 -0
- jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
- jaclang/tests/fixtures/impl_grab.jac +4 -1
- jaclang/tests/fixtures/import.jac +9 -0
- jaclang/tests/fixtures/index_slice.jac +30 -0
- jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/needs_import.jac +2 -2
- jaclang/tests/fixtures/pyfunc_1.py +1 -1
- jaclang/tests/fixtures/pyfunc_2.py +5 -2
- jaclang/tests/fixtures/pygame_mock/__init__.py +3 -0
- jaclang/tests/fixtures/pygame_mock/color.py +3 -0
- jaclang/tests/fixtures/pygame_mock/constants.py +5 -0
- jaclang/tests/fixtures/pygame_mock/display.py +2 -0
- jaclang/tests/fixtures/pygame_mock/inner/__init__.py +0 -0
- jaclang/tests/fixtures/pygame_mock/inner/iner_mod.py +2 -0
- jaclang/tests/fixtures/registry.jac +9 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/fixtures/semstr.jac +1 -4
- jaclang/tests/fixtures/simple_archs.jac +1 -1
- jaclang/tests/test_cli.py +109 -3
- jaclang/tests/test_language.py +170 -68
- jaclang/tests/test_reference.py +2 -3
- jaclang/utils/helpers.py +45 -21
- jaclang/utils/test.py +9 -0
- jaclang/utils/treeprinter.py +30 -7
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/METADATA +3 -2
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/RECORD +126 -90
- jaclang/core/architype.py +0 -502
- jaclang/core/importer.py +0 -344
- jaclang/core/memory.py +0 -99
- jaclang/tests/fixtures/aott_raise.jac +0 -25
- jaclang/tests/fixtures/package_import.jac +0 -6
- /jaclang/{core → runtimelib}/__init__.py +0 -0
- /jaclang/{core → runtimelib}/test.py +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/WHEEL +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import ast as ast3
|
|
4
4
|
import importlib
|
|
5
|
-
import inspect
|
|
6
5
|
import marshal
|
|
7
6
|
import os
|
|
8
7
|
import pickle
|
|
@@ -19,10 +18,12 @@ from jaclang.compiler.constant import Constants
|
|
|
19
18
|
from jaclang.compiler.passes.main.pyast_load_pass import PyastBuildPass
|
|
20
19
|
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
21
20
|
from jaclang.compiler.passes.tool.schedules import format_pass
|
|
22
|
-
from jaclang.core.constructs import Architype
|
|
23
21
|
from jaclang.plugin.builtin import dotgen
|
|
24
22
|
from jaclang.plugin.feature import JacCmd as Cmd
|
|
25
23
|
from jaclang.plugin.feature import JacFeature as Jac
|
|
24
|
+
from jaclang.runtimelib.constructs import WalkerArchitype
|
|
25
|
+
from jaclang.runtimelib.context import ExecutionContext
|
|
26
|
+
from jaclang.runtimelib.machine import JacMachine, JacProgram
|
|
26
27
|
from jaclang.utils.helpers import debugger as db
|
|
27
28
|
from jaclang.utils.lang_tools import AstTool
|
|
28
29
|
|
|
@@ -67,12 +68,7 @@ def format(path: str, outfile: str = "", debug: bool = False) -> None:
|
|
|
67
68
|
|
|
68
69
|
@cmd_registry.register
|
|
69
70
|
def run(
|
|
70
|
-
filename: str,
|
|
71
|
-
session: str = "",
|
|
72
|
-
main: bool = True,
|
|
73
|
-
cache: bool = True,
|
|
74
|
-
walker: str = "",
|
|
75
|
-
node: str = "",
|
|
71
|
+
filename: str, session: str = "", main: bool = True, cache: bool = True
|
|
76
72
|
) -> None:
|
|
77
73
|
"""Run the specified .jac file."""
|
|
78
74
|
# if no session specified, check if it was defined when starting the command shell
|
|
@@ -86,81 +82,93 @@ def run(
|
|
|
86
82
|
else ""
|
|
87
83
|
)
|
|
88
84
|
|
|
89
|
-
Jac.context().init_memory(session)
|
|
90
|
-
|
|
91
85
|
base, mod = os.path.split(filename)
|
|
92
86
|
base = base if base else "./"
|
|
93
87
|
mod = mod[:-4]
|
|
88
|
+
|
|
89
|
+
jctx = ExecutionContext.create(session=session)
|
|
90
|
+
|
|
94
91
|
if filename.endswith(".jac"):
|
|
95
|
-
|
|
92
|
+
jac_import(
|
|
96
93
|
target=mod,
|
|
97
94
|
base_path=base,
|
|
98
95
|
cachable=cache,
|
|
99
96
|
override_name="__main__" if main else None,
|
|
100
97
|
)
|
|
101
|
-
if ret_module is None:
|
|
102
|
-
loaded_mod = None
|
|
103
|
-
else:
|
|
104
|
-
(loaded_mod,) = ret_module
|
|
105
98
|
elif filename.endswith(".jir"):
|
|
106
99
|
with open(filename, "rb") as f:
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
JacMachine(base).attach_program(
|
|
101
|
+
JacProgram(mod_bundle=pickle.load(f), bytecode=None)
|
|
102
|
+
)
|
|
103
|
+
jac_import(
|
|
109
104
|
target=mod,
|
|
110
105
|
base_path=base,
|
|
111
106
|
cachable=cache,
|
|
112
107
|
override_name="__main__" if main else None,
|
|
113
|
-
mod_bundle=ir,
|
|
114
108
|
)
|
|
115
|
-
if ret_module is None:
|
|
116
|
-
loaded_mod = None
|
|
117
|
-
else:
|
|
118
|
-
(loaded_mod,) = ret_module
|
|
119
109
|
else:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if not node or node == "root":
|
|
124
|
-
entrypoint: Architype = Jac.get_root()
|
|
125
|
-
else:
|
|
126
|
-
obj = Jac.context().get_obj(UUID(node))
|
|
127
|
-
if obj is None:
|
|
128
|
-
print(f"Entrypoint {node} not found.")
|
|
129
|
-
return
|
|
130
|
-
entrypoint = obj
|
|
131
|
-
|
|
132
|
-
# TODO: handle no override name
|
|
133
|
-
if walker:
|
|
134
|
-
walker_module = dict(inspect.getmembers(loaded_mod)).get(walker)
|
|
135
|
-
if walker_module:
|
|
136
|
-
Jac.spawn_call(entrypoint, walker_module())
|
|
137
|
-
else:
|
|
138
|
-
print(f"Walker {walker} not found.")
|
|
110
|
+
jctx.close()
|
|
111
|
+
JacMachine.detach()
|
|
112
|
+
raise ValueError("Not a valid file!\nOnly supports `.jac` and `.jir`")
|
|
139
113
|
|
|
140
|
-
|
|
114
|
+
jctx.close()
|
|
115
|
+
JacMachine.detach()
|
|
141
116
|
|
|
142
117
|
|
|
143
118
|
@cmd_registry.register
|
|
144
|
-
def get_object(
|
|
119
|
+
def get_object(
|
|
120
|
+
filename: str, id: str, session: str = "", main: bool = True, cache: bool = True
|
|
121
|
+
) -> dict:
|
|
145
122
|
"""Get the object with the specified id."""
|
|
146
123
|
if session == "":
|
|
147
|
-
session =
|
|
124
|
+
session = (
|
|
125
|
+
cmd_registry.args.session
|
|
126
|
+
if hasattr(cmd_registry, "args")
|
|
127
|
+
and hasattr(cmd_registry.args, "session")
|
|
128
|
+
and cmd_registry.args.session
|
|
129
|
+
else ""
|
|
130
|
+
)
|
|
148
131
|
|
|
149
|
-
|
|
132
|
+
base, mod = os.path.split(filename)
|
|
133
|
+
base = base if base else "./"
|
|
134
|
+
mod = mod[:-4]
|
|
150
135
|
|
|
151
|
-
|
|
152
|
-
|
|
136
|
+
jctx = ExecutionContext.create(session=session)
|
|
137
|
+
|
|
138
|
+
if filename.endswith(".jac"):
|
|
139
|
+
jac_import(
|
|
140
|
+
target=mod,
|
|
141
|
+
base_path=base,
|
|
142
|
+
cachable=cache,
|
|
143
|
+
override_name="__main__" if main else None,
|
|
144
|
+
)
|
|
145
|
+
elif filename.endswith(".jir"):
|
|
146
|
+
with open(filename, "rb") as f:
|
|
147
|
+
JacMachine(base).attach_program(
|
|
148
|
+
JacProgram(mod_bundle=pickle.load(f), bytecode=None)
|
|
149
|
+
)
|
|
150
|
+
jac_import(
|
|
151
|
+
target=mod,
|
|
152
|
+
base_path=base,
|
|
153
|
+
cachable=cache,
|
|
154
|
+
override_name="__main__" if main else None,
|
|
155
|
+
)
|
|
153
156
|
else:
|
|
154
|
-
|
|
157
|
+
jctx.close()
|
|
158
|
+
JacMachine.detach()
|
|
159
|
+
raise ValueError("Not a valid file!\nOnly supports `.jac` and `.jir`")
|
|
155
160
|
|
|
156
|
-
|
|
157
|
-
if
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
data = {}
|
|
162
|
+
if id == "root":
|
|
163
|
+
data = jctx.root.__getstate__()
|
|
164
|
+
elif obj := jctx.mem.find_by_id(UUID(id)):
|
|
165
|
+
data = obj.__getstate__()
|
|
161
166
|
else:
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
print(f"Object with id {id} not found.")
|
|
168
|
+
|
|
169
|
+
jctx.close()
|
|
170
|
+
JacMachine.detach()
|
|
171
|
+
return data
|
|
164
172
|
|
|
165
173
|
|
|
166
174
|
@cmd_registry.register
|
|
@@ -210,25 +218,78 @@ def lsp() -> None:
|
|
|
210
218
|
|
|
211
219
|
|
|
212
220
|
@cmd_registry.register
|
|
213
|
-
def enter(
|
|
214
|
-
|
|
221
|
+
def enter(
|
|
222
|
+
filename: str,
|
|
223
|
+
entrypoint: str,
|
|
224
|
+
args: list,
|
|
225
|
+
session: str = "",
|
|
226
|
+
main: bool = True,
|
|
227
|
+
cache: bool = True,
|
|
228
|
+
root: str = "",
|
|
229
|
+
node: str = "",
|
|
230
|
+
) -> None:
|
|
231
|
+
"""
|
|
232
|
+
Run the specified entrypoint function in the given .jac file.
|
|
215
233
|
|
|
216
234
|
:param filename: The path to the .jac file.
|
|
217
235
|
:param entrypoint: The name of the entrypoint function.
|
|
218
236
|
:param args: Arguments to pass to the entrypoint function.
|
|
237
|
+
:param session: shelve.Shelf file path.
|
|
238
|
+
:param root: root executor.
|
|
239
|
+
:param node: starting node.
|
|
219
240
|
"""
|
|
241
|
+
if session == "":
|
|
242
|
+
session = (
|
|
243
|
+
cmd_registry.args.session
|
|
244
|
+
if hasattr(cmd_registry, "args")
|
|
245
|
+
and hasattr(cmd_registry.args, "session")
|
|
246
|
+
and cmd_registry.args.session
|
|
247
|
+
else ""
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
base, mod = os.path.split(filename)
|
|
251
|
+
base = base if base else "./"
|
|
252
|
+
mod = mod[:-4]
|
|
253
|
+
|
|
254
|
+
jctx = ExecutionContext.create(session=session, root=root)
|
|
255
|
+
|
|
220
256
|
if filename.endswith(".jac"):
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
257
|
+
ret_module = jac_import(
|
|
258
|
+
target=mod,
|
|
259
|
+
base_path=base,
|
|
260
|
+
cachable=cache,
|
|
261
|
+
override_name="__main__" if main else None,
|
|
262
|
+
)
|
|
263
|
+
elif filename.endswith(".jir"):
|
|
264
|
+
with open(filename, "rb") as f:
|
|
265
|
+
JacMachine(base).attach_program(
|
|
266
|
+
JacProgram(mod_bundle=pickle.load(f), bytecode=None)
|
|
267
|
+
)
|
|
268
|
+
ret_module = jac_import(
|
|
269
|
+
target=mod,
|
|
270
|
+
base_path=base,
|
|
271
|
+
cachable=cache,
|
|
272
|
+
override_name="__main__" if main else None,
|
|
273
|
+
)
|
|
274
|
+
else:
|
|
275
|
+
jctx.close()
|
|
276
|
+
JacMachine.detach()
|
|
277
|
+
raise ValueError("Not a valid file!\nOnly supports `.jac` and `.jir`")
|
|
278
|
+
|
|
279
|
+
if ret_module:
|
|
280
|
+
(loaded_mod,) = ret_module
|
|
281
|
+
if not loaded_mod:
|
|
226
282
|
print("Errors occurred while importing the module.")
|
|
227
|
-
return
|
|
228
283
|
else:
|
|
229
|
-
getattr(
|
|
230
|
-
|
|
231
|
-
|
|
284
|
+
architype = getattr(loaded_mod, entrypoint)(*args)
|
|
285
|
+
|
|
286
|
+
jctx.set_entry_node(node)
|
|
287
|
+
|
|
288
|
+
if isinstance(architype, WalkerArchitype) and jctx.validate_access():
|
|
289
|
+
Jac.spawn_call(jctx.entry_node.architype, architype)
|
|
290
|
+
|
|
291
|
+
jctx.close()
|
|
292
|
+
JacMachine.detach()
|
|
232
293
|
|
|
233
294
|
|
|
234
295
|
@cmd_registry.register
|
|
@@ -251,6 +312,8 @@ def test(
|
|
|
251
312
|
|
|
252
313
|
jac test => jac test -d .
|
|
253
314
|
"""
|
|
315
|
+
jctx = ExecutionContext.create()
|
|
316
|
+
|
|
254
317
|
failcount = Jac.run_test(
|
|
255
318
|
filepath=filepath,
|
|
256
319
|
filter=filter,
|
|
@@ -259,6 +322,9 @@ def test(
|
|
|
259
322
|
directory=directory,
|
|
260
323
|
verbose=verbose,
|
|
261
324
|
)
|
|
325
|
+
|
|
326
|
+
jctx.close()
|
|
327
|
+
|
|
262
328
|
if failcount:
|
|
263
329
|
raise SystemExit(f"Tests failed: {failcount}")
|
|
264
330
|
|
|
@@ -357,17 +423,16 @@ def dot(
|
|
|
357
423
|
else ""
|
|
358
424
|
)
|
|
359
425
|
|
|
360
|
-
Jac.context().init_memory(session)
|
|
361
|
-
|
|
362
426
|
base, mod = os.path.split(filename)
|
|
363
427
|
base = base if base else "./"
|
|
364
428
|
mod = mod[:-4]
|
|
429
|
+
|
|
430
|
+
jctx = ExecutionContext.create(session=session)
|
|
431
|
+
|
|
365
432
|
if filename.endswith(".jac"):
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
)
|
|
370
|
-
module = importlib.import_module(mod)
|
|
433
|
+
jac_machine = JacMachine(base)
|
|
434
|
+
jac_import(target=mod, base_path=base)
|
|
435
|
+
module = jac_machine.loaded_modules.get(mod)
|
|
371
436
|
globals().update(vars(module))
|
|
372
437
|
try:
|
|
373
438
|
node = globals().get(initial, eval(initial)) if initial else None
|
|
@@ -385,7 +450,7 @@ def dot(
|
|
|
385
450
|
import traceback
|
|
386
451
|
|
|
387
452
|
traceback.print_exc()
|
|
388
|
-
|
|
453
|
+
jctx.close()
|
|
389
454
|
return
|
|
390
455
|
file_name = saveto if saveto else f"{mod}.dot"
|
|
391
456
|
with open(file_name, "w") as file:
|
|
@@ -394,7 +459,7 @@ def dot(
|
|
|
394
459
|
else:
|
|
395
460
|
print("Not a .jac file.")
|
|
396
461
|
|
|
397
|
-
|
|
462
|
+
jctx.close()
|
|
398
463
|
|
|
399
464
|
|
|
400
465
|
@cmd_registry.register
|
|
@@ -437,12 +502,17 @@ def start_cli() -> None:
|
|
|
437
502
|
parser = cmd_registry.parser
|
|
438
503
|
args = parser.parse_args()
|
|
439
504
|
cmd_registry.args = args
|
|
505
|
+
|
|
506
|
+
if args.version:
|
|
507
|
+
version = importlib.metadata.version("jaclang")
|
|
508
|
+
print(f"Jac version {version}")
|
|
509
|
+
return
|
|
510
|
+
|
|
440
511
|
command = cmd_registry.get(args.command)
|
|
441
512
|
if command:
|
|
442
513
|
args_dict = vars(args)
|
|
443
514
|
args_dict.pop("command")
|
|
444
|
-
|
|
445
|
-
args_dict.pop("session")
|
|
515
|
+
args_dict.pop("version", None)
|
|
446
516
|
ret = command.call(**args_dict)
|
|
447
517
|
if ret:
|
|
448
518
|
print(ret)
|
jaclang/cli/cmdreg.py
CHANGED
|
@@ -38,7 +38,7 @@ class CommandRegistry:
|
|
|
38
38
|
self.registry = {}
|
|
39
39
|
self.parser = argparse.ArgumentParser(prog="jac")
|
|
40
40
|
self.parser.add_argument(
|
|
41
|
-
"
|
|
41
|
+
"-V", "--version", action="store_true", help="Show the Jac version"
|
|
42
42
|
)
|
|
43
43
|
self.sub_parsers = self.parser.add_subparsers(title="commands", dest="command")
|
|
44
44
|
self.args = argparse.Namespace()
|
|
@@ -172,17 +172,14 @@ class CommandShell(cmd.Cmd):
|
|
|
172
172
|
|
|
173
173
|
def default(self, line: str) -> None:
|
|
174
174
|
"""Process the command line input."""
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
self.stdout.write(f"{ret_str}\n")
|
|
184
|
-
except Exception as e:
|
|
185
|
-
print(e)
|
|
175
|
+
args = vars(self.cmd_reg.parser.parse_args(line.split()))
|
|
176
|
+
command = self.cmd_reg.get(args["command"])
|
|
177
|
+
if command:
|
|
178
|
+
args.pop("command")
|
|
179
|
+
ret = command.call(**args)
|
|
180
|
+
if ret:
|
|
181
|
+
ret_str = pprint.pformat(ret, indent=2)
|
|
182
|
+
self.stdout.write(f"{ret_str}\n")
|
|
186
183
|
|
|
187
184
|
def do_help(self, arg: str) -> None:
|
|
188
185
|
"""Jac CLI 'help' implementaion."""
|
jaclang/compiler/__init__.py
CHANGED
|
@@ -35,7 +35,6 @@ def generate_static_parser(force: bool = False) -> None:
|
|
|
35
35
|
logging.error(f"Error generating reference files: {e}")
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
generate_static_parser()
|
|
39
38
|
try:
|
|
40
39
|
from jaclang.compiler.generated import jac_parser as jac_lark
|
|
41
40
|
except ModuleNotFoundError:
|
|
@@ -50,62 +49,29 @@ TOKEN_MAP = {
|
|
|
50
49
|
for x in jac_lark.Lark_StandAlone().parser.lexer_conf.terminals
|
|
51
50
|
}
|
|
52
51
|
|
|
52
|
+
# fmt: off
|
|
53
53
|
TOKEN_MAP.update(
|
|
54
54
|
{
|
|
55
|
-
"CARROW_L": "<++",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"ARROW_L_P1": "<-:",
|
|
73
|
-
"ARROW_R_P2": ":->",
|
|
74
|
-
"ARROW_L_P2": ":-",
|
|
75
|
-
"ARROW_R_P1": "-:",
|
|
76
|
-
"CARROW_BI": "<++>",
|
|
77
|
-
"CARROW_L": "<++",
|
|
78
|
-
"CARROW_R": "++>",
|
|
79
|
-
"CARROW_L_P1": "<+:",
|
|
80
|
-
"CARROW_R_P2": ":+>",
|
|
81
|
-
"CARROW_L_P2": ":+",
|
|
82
|
-
"CARROW_R_P1": "+:",
|
|
83
|
-
"PIPE_FWD": "|>",
|
|
84
|
-
"PIPE_BKWD": "<|",
|
|
85
|
-
"A_PIPE_FWD": ":>",
|
|
86
|
-
"A_PIPE_BKWD": "<:",
|
|
87
|
-
"DOT_FWD": ".>",
|
|
88
|
-
"STAR_POW": "**",
|
|
89
|
-
"STAR_MUL": "*",
|
|
90
|
-
"FLOOR_DIV": "//",
|
|
91
|
-
"DIV": "/",
|
|
92
|
-
"PYNLINE": "::py::",
|
|
93
|
-
"ADD_EQ": "+=",
|
|
94
|
-
"SUB_EQ": "-=",
|
|
95
|
-
"STAR_POW_EQ": "**=",
|
|
96
|
-
"MUL_EQ": "*=",
|
|
97
|
-
"FLOOR_DIV_EQ": "//=",
|
|
98
|
-
"DIV_EQ": "/=",
|
|
99
|
-
"MOD_EQ": "%=",
|
|
100
|
-
"BW_AND_EQ": "&=",
|
|
101
|
-
"BW_OR_EQ": "|=",
|
|
102
|
-
"BW_XOR_EQ": "^=",
|
|
103
|
-
"BW_NOT_EQ": "~=",
|
|
104
|
-
"LSHIFT_EQ": "<<=",
|
|
105
|
-
"RSHIFT_EQ": ">>=",
|
|
106
|
-
"ELLIPSIS": "...",
|
|
55
|
+
"CARROW_L": "<++", "CARROW_R": "++>", "GLOBAL_OP": ":global:",
|
|
56
|
+
"NONLOCAL_OP": ":nonlocal:", "WALKER_OP": ":walker:", "NODE_OP": ":node:",
|
|
57
|
+
"EDGE_OP": ":edge:", "CLASS_OP": ":class:", "OBJECT_OP": ":obj:",
|
|
58
|
+
"TYPE_OP": "`", "ABILITY_OP": ":can:", "ELVIS_OP": "?:", "NULL_OK": "?",
|
|
59
|
+
"KW_OR": "|", "ARROW_BI": "<-->", "ARROW_L": "<--",
|
|
60
|
+
"ARROW_R": "-->", "ARROW_L_P1": "<-:", "ARROW_R_P2": ":->",
|
|
61
|
+
"ARROW_L_P2": ":-", "ARROW_R_P1": "-:", "CARROW_BI": "<++>",
|
|
62
|
+
"CARROW_L": "<++", "CARROW_R": "++>", "CARROW_L_P1": "<+:",
|
|
63
|
+
"CARROW_R_P2": ":+>", "CARROW_L_P2": ":+", "CARROW_R_P1": "+:",
|
|
64
|
+
"PIPE_FWD": "|>", "PIPE_BKWD": "<|", "A_PIPE_FWD": ":>",
|
|
65
|
+
"A_PIPE_BKWD": "<:", "DOT_FWD": ".>", "STAR_POW": "**",
|
|
66
|
+
"STAR_MUL": "*", "FLOOR_DIV": "//", "DIV": "/",
|
|
67
|
+
"PYNLINE": "::py::", "ADD_EQ": "+=", "SUB_EQ": "-=",
|
|
68
|
+
"STAR_POW_EQ": "**=", "MUL_EQ": "*=", "FLOOR_DIV_EQ": "//=",
|
|
69
|
+
"DIV_EQ": "/=", "MOD_EQ": "%=", "BW_AND_EQ": "&=",
|
|
70
|
+
"BW_OR_EQ": "|=", "BW_XOR_EQ": "^=", "BW_NOT_EQ": "~=",
|
|
71
|
+
"LSHIFT_EQ": "<<=", "RSHIFT_EQ": ">>=", "ELLIPSIS": "...",
|
|
107
72
|
}
|
|
108
73
|
)
|
|
74
|
+
# fmt: on
|
|
109
75
|
|
|
110
76
|
|
|
111
77
|
__all__ = ["jac_lark", "TOKEN_MAP"]
|
jaclang/compiler/absyntree.py
CHANGED
|
@@ -55,15 +55,10 @@ class AstNode:
|
|
|
55
55
|
"""Get symbol table."""
|
|
56
56
|
# sym_tab should never be accessed without being set in codebase
|
|
57
57
|
if not self._sym_tab:
|
|
58
|
-
import traceback
|
|
59
|
-
|
|
60
|
-
if self.parent:
|
|
61
|
-
print(f"Parent: {self.parent.pp()}")
|
|
62
|
-
print("Node: ", self.pp())
|
|
63
|
-
stack_trace = traceback.format_stack()
|
|
64
|
-
print("".join(stack_trace))
|
|
65
58
|
raise ValueError(
|
|
66
|
-
f"Symbol table not set for {type(self).__name__}. Impossible
|
|
59
|
+
f"Symbol table not set for {type(self).__name__}. Impossible.\n"
|
|
60
|
+
f"Node: {self.pp()}\n"
|
|
61
|
+
f"Parent: {self.parent.pp() if self.parent else None}\n"
|
|
67
62
|
)
|
|
68
63
|
return self._sym_tab
|
|
69
64
|
|
|
@@ -163,7 +158,7 @@ class AstNode:
|
|
|
163
158
|
"""Get parent of type."""
|
|
164
159
|
from jaclang.compiler.passes import Pass
|
|
165
160
|
|
|
166
|
-
return Pass.
|
|
161
|
+
return Pass.find_parent_of_type(node=self, typ=typ)
|
|
167
162
|
|
|
168
163
|
def parent_of_type(self, typ: Type[T]) -> T:
|
|
169
164
|
"""Get parent of type."""
|
|
@@ -635,8 +630,11 @@ class Module(AstDocNode):
|
|
|
635
630
|
self.impl_mod: list[Module] = []
|
|
636
631
|
self.test_mod: list[Module] = []
|
|
637
632
|
self.mod_deps: dict[str, Module] = {}
|
|
633
|
+
self.py_mod_dep_map: dict[str, str] = {}
|
|
634
|
+
self.py_raise_map: dict[str, str] = {}
|
|
638
635
|
self.registry = registry
|
|
639
636
|
self.terminals: list[Token] = terminals
|
|
637
|
+
self.is_raised_from_py: bool = False
|
|
640
638
|
AstNode.__init__(self, kid=kid)
|
|
641
639
|
AstDocNode.__init__(self, doc=doc)
|
|
642
640
|
|
|
@@ -863,7 +861,7 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
863
861
|
|
|
864
862
|
def __init__(
|
|
865
863
|
self,
|
|
866
|
-
hint: SubTag[Name],
|
|
864
|
+
hint: Optional[SubTag[Name]],
|
|
867
865
|
from_loc: Optional[ModulePath],
|
|
868
866
|
items: SubNodeList[ModuleItem] | SubNodeList[ModulePath],
|
|
869
867
|
is_absorb: bool, # For includes
|
|
@@ -878,11 +876,52 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
878
876
|
AstNode.__init__(self, kid=kid)
|
|
879
877
|
AstDocNode.__init__(self, doc=doc)
|
|
880
878
|
|
|
879
|
+
@property
|
|
880
|
+
def is_py(self) -> bool:
|
|
881
|
+
"""Check if import is python."""
|
|
882
|
+
if self.hint and self.hint.tag.value == "py":
|
|
883
|
+
return True
|
|
884
|
+
if not self.hint:
|
|
885
|
+
return not self.__jac_detected
|
|
886
|
+
return False
|
|
887
|
+
|
|
888
|
+
@property
|
|
889
|
+
def is_jac(self) -> bool:
|
|
890
|
+
"""Check if import is jac."""
|
|
891
|
+
if self.hint and self.hint.tag.value == "jac":
|
|
892
|
+
return True
|
|
893
|
+
if not self.hint:
|
|
894
|
+
return self.__jac_detected
|
|
895
|
+
return False
|
|
896
|
+
|
|
897
|
+
@property
|
|
898
|
+
def __jac_detected(self) -> bool:
|
|
899
|
+
"""Check if import is jac."""
|
|
900
|
+
if self.from_loc:
|
|
901
|
+
if self.from_loc.resolve_relative_path().endswith(".jac"):
|
|
902
|
+
return True
|
|
903
|
+
if os.path.isdir(self.from_loc.resolve_relative_path()):
|
|
904
|
+
if os.path.exists(
|
|
905
|
+
os.path.join(self.from_loc.resolve_relative_path(), "__init__.jac")
|
|
906
|
+
):
|
|
907
|
+
return True
|
|
908
|
+
for i in self.items.items:
|
|
909
|
+
if isinstance(
|
|
910
|
+
i, ModuleItem
|
|
911
|
+
) and self.from_loc.resolve_relative_path(i.name.value).endswith(
|
|
912
|
+
".jac"
|
|
913
|
+
):
|
|
914
|
+
return True
|
|
915
|
+
return any(
|
|
916
|
+
isinstance(i, ModulePath) and i.resolve_relative_path().endswith(".jac")
|
|
917
|
+
for i in self.items.items
|
|
918
|
+
)
|
|
919
|
+
|
|
881
920
|
def normalize(self, deep: bool = False) -> bool:
|
|
882
921
|
"""Normalize import node."""
|
|
883
922
|
res = True
|
|
884
923
|
if deep:
|
|
885
|
-
res = self.hint.normalize(deep)
|
|
924
|
+
res = self.hint.normalize(deep) if self.hint else res
|
|
886
925
|
res = res and self.from_loc.normalize(deep) if self.from_loc else res
|
|
887
926
|
res = res and self.items.normalize(deep)
|
|
888
927
|
res = res and self.doc.normalize(deep) if self.doc else res
|
|
@@ -893,7 +932,8 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
893
932
|
new_kid.append(self.gen_token(Tok.KW_INCLUDE))
|
|
894
933
|
else:
|
|
895
934
|
new_kid.append(self.gen_token(Tok.KW_IMPORT))
|
|
896
|
-
|
|
935
|
+
if self.hint:
|
|
936
|
+
new_kid.append(self.hint)
|
|
897
937
|
if self.from_loc:
|
|
898
938
|
new_kid.append(self.gen_token(Tok.KW_FROM))
|
|
899
939
|
new_kid.append(self.from_loc)
|
|
@@ -919,6 +959,7 @@ class ModulePath(AstSymbolNode):
|
|
|
919
959
|
self.level = level
|
|
920
960
|
self.alias = alias
|
|
921
961
|
self.sub_module: Optional[Module] = None
|
|
962
|
+
self.abs_path: Optional[str] = None
|
|
922
963
|
|
|
923
964
|
name_spec = alias if alias else path[0] if path else None
|
|
924
965
|
|
|
@@ -940,12 +981,32 @@ class ModulePath(AstSymbolNode):
|
|
|
940
981
|
)
|
|
941
982
|
|
|
942
983
|
@property
|
|
943
|
-
def
|
|
984
|
+
def dot_path_str(self) -> str:
|
|
944
985
|
"""Get path string."""
|
|
945
986
|
return ("." * self.level) + ".".join(
|
|
946
987
|
[p.value for p in self.path] if self.path else [self.name_spec.sym_name]
|
|
947
988
|
)
|
|
948
989
|
|
|
990
|
+
def resolve_relative_path(self, target_item: Optional[str] = None) -> str:
|
|
991
|
+
"""Convert an import target string into a relative file path."""
|
|
992
|
+
target = self.dot_path_str
|
|
993
|
+
if target_item:
|
|
994
|
+
target += f".{target_item}"
|
|
995
|
+
base_path = os.path.dirname(self.loc.mod_path)
|
|
996
|
+
base_path = base_path if base_path else os.getcwd()
|
|
997
|
+
parts = target.split(".")
|
|
998
|
+
traversal_levels = self.level - 1 if self.level > 0 else 0
|
|
999
|
+
actual_parts = parts[traversal_levels:]
|
|
1000
|
+
for _ in range(traversal_levels):
|
|
1001
|
+
base_path = os.path.dirname(base_path)
|
|
1002
|
+
relative_path = os.path.join(base_path, *actual_parts)
|
|
1003
|
+
relative_path = (
|
|
1004
|
+
relative_path + ".jac"
|
|
1005
|
+
if os.path.exists(relative_path + ".jac")
|
|
1006
|
+
else relative_path
|
|
1007
|
+
)
|
|
1008
|
+
return relative_path
|
|
1009
|
+
|
|
949
1010
|
def normalize(self, deep: bool = False) -> bool:
|
|
950
1011
|
"""Normalize module path node."""
|
|
951
1012
|
res = True
|
|
@@ -991,6 +1052,7 @@ class ModuleItem(AstSymbolNode):
|
|
|
991
1052
|
name_spec=alias if alias else name,
|
|
992
1053
|
sym_category=SymbolType.MOD_VAR,
|
|
993
1054
|
)
|
|
1055
|
+
self.abs_path: Optional[str] = None
|
|
994
1056
|
|
|
995
1057
|
@property
|
|
996
1058
|
def from_parent(self) -> Import:
|
|
@@ -1132,7 +1194,6 @@ class ArchDef(AstImplOnlyNode):
|
|
|
1132
1194
|
body: SubNodeList[ArchBlockStmt],
|
|
1133
1195
|
kid: Sequence[AstNode],
|
|
1134
1196
|
doc: Optional[String] = None,
|
|
1135
|
-
decorators: Optional[SubNodeList[Expr]] = None,
|
|
1136
1197
|
decl_link: Optional[Architype] = None,
|
|
1137
1198
|
) -> None:
|
|
1138
1199
|
"""Initialize arch def node."""
|
|
@@ -1473,6 +1534,23 @@ class FuncSignature(AstSemStrNode):
|
|
|
1473
1534
|
and self.parent.decl_link.is_static
|
|
1474
1535
|
)
|
|
1475
1536
|
|
|
1537
|
+
@property
|
|
1538
|
+
def is_in_py_class(self) -> bool:
|
|
1539
|
+
"""Check if the ability belongs to a class."""
|
|
1540
|
+
is_archi = self.find_parent_of_type(Architype)
|
|
1541
|
+
is_class = is_archi is not None and is_archi.arch_type.name == Tok.KW_CLASS
|
|
1542
|
+
|
|
1543
|
+
return (
|
|
1544
|
+
isinstance(self.parent, Ability)
|
|
1545
|
+
and self.parent.is_method is not None
|
|
1546
|
+
and is_class
|
|
1547
|
+
) or (
|
|
1548
|
+
isinstance(self.parent, AbilityDef)
|
|
1549
|
+
and isinstance(self.parent.decl_link, Ability)
|
|
1550
|
+
and self.parent.decl_link.is_method
|
|
1551
|
+
and is_class
|
|
1552
|
+
)
|
|
1553
|
+
|
|
1476
1554
|
|
|
1477
1555
|
class EventSignature(AstSemStrNode):
|
|
1478
1556
|
"""EventSignature node type for Jac Ast."""
|
|
@@ -4240,11 +4318,11 @@ class Ellipsis(Literal):
|
|
|
4240
4318
|
class EmptyToken(Token):
|
|
4241
4319
|
"""EmptyToken node type for Jac Ast."""
|
|
4242
4320
|
|
|
4243
|
-
def __init__(self) -> None:
|
|
4321
|
+
def __init__(self, file_path: str = "") -> None:
|
|
4244
4322
|
"""Initialize empty token."""
|
|
4245
4323
|
super().__init__(
|
|
4246
4324
|
name="EmptyToken",
|
|
4247
|
-
file_path=
|
|
4325
|
+
file_path=file_path,
|
|
4248
4326
|
value="",
|
|
4249
4327
|
line=0,
|
|
4250
4328
|
end_line=0,
|