jaclang 0.2.5__py3-none-any.whl → 0.3.1__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/__init__.py +3 -3
- jaclang/cli/__init__.py +0 -1
- jaclang/cli/__jac_gen__/cli.py +4 -4
- jaclang/cli/__jac_gen__/cmds.py +1 -1
- jaclang/cli/__jac_gen__/cmds_impl.py +1 -1
- jaclang/core/__init__.py +5 -11
- jaclang/core/__jac_gen__/corelib.py +289 -0
- jaclang/core/__jac_gen__/corelib_impl.py +220 -0
- jaclang/core/corelib.jac +21 -34
- jaclang/core/corelib_impl.jac +317 -0
- jaclang/jac/__init__.py +1 -0
- jaclang/jac/__jac_gen__/jac_parser.py +2 -2
- jaclang/jac/absyntree.py +28 -8
- jaclang/jac/constant.py +3 -7
- jaclang/jac/parser.py +13 -9
- jaclang/jac/passes/main/__init__.py +2 -0
- jaclang/jac/passes/main/def_use_pass.py +3 -2
- jaclang/jac/passes/main/pyast_gen_pass.py +99 -34
- jaclang/jac/passes/main/schedules.py +6 -0
- jaclang/jac/passes/main/sym_tab_build_pass.py +3 -5
- jaclang/jac/passes/main/tests/test_jac_format_pass.py +22 -4
- jaclang/jac/passes/main/tests/test_type_check_pass.py +42 -0
- jaclang/jac/passes/main/type_check_pass.py +103 -0
- jaclang/jac/passes/tool/fuse_comments_pass.py +57 -39
- jaclang/jac/passes/tool/jac_formatter_pass.py +419 -192
- jaclang/jac/passes/transform.py +0 -39
- jaclang/jac/passes/utils/__init__.py +1 -0
- jaclang/jac/passes/utils/mypy_ast_build.py +302 -0
- jaclang/jac/plugin/__init__.py +5 -2
- jaclang/jac/plugin/default.py +20 -4
- jaclang/jac/plugin/feature.py +15 -6
- jaclang/jac/plugin/spec.py +34 -6
- jaclang/jac/tests/test_workspace.py +45 -5
- jaclang/jac/transpiler.py +4 -9
- jaclang/utils/helpers.py +0 -33
- jaclang/utils/lang_tools.py +3 -0
- jaclang/utils/test.py +3 -1
- jaclang/vendor/lark/py.typed +0 -0
- jaclang/vendor/mypy/checker.py +19 -12
- jaclang/vendor/mypy/checkexpr.py +31 -10
- jaclang/vendor/mypy/constraints.py +56 -38
- jaclang/vendor/mypy/expandtype.py +1 -0
- jaclang/vendor/mypy/meet.py +10 -1
- jaclang/vendor/mypy/messages.py +16 -4
- jaclang/vendor/mypy/moduleinspect.py +10 -4
- jaclang/vendor/mypy/py.typed +1 -0
- jaclang/vendor/mypy/semanal.py +18 -17
- jaclang/vendor/mypy/semanal_enum.py +7 -4
- jaclang/vendor/mypy/semanal_namedtuple.py +11 -1
- jaclang/vendor/mypy/semanal_typeddict.py +25 -11
- jaclang/vendor/mypy/stubdoc.py +18 -4
- jaclang/vendor/mypy/stubgen.py +80 -1
- jaclang/vendor/mypy/stubgenc.py +47 -5
- jaclang/vendor/mypy/stubtest.py +53 -3
- jaclang/vendor/mypy/stubutil.py +9 -9
- jaclang/vendor/mypy/test/testipc.py +16 -7
- jaclang/vendor/mypy/test/teststubtest.py +20 -2
- jaclang/vendor/mypy/types.py +1 -1
- jaclang/vendor/mypyc/irbuild/prebuildvisitor.py +2 -1
- jaclang/vendor/mypyc/test/test_run.py +2 -4
- jaclang/vendor/pluggy/py.typed +0 -0
- {jaclang-0.2.5.dist-info → jaclang-0.3.1.dist-info}/METADATA +1 -1
- {jaclang-0.2.5.dist-info → jaclang-0.3.1.dist-info}/RECORD +67 -62
- {jaclang-0.2.5.dist-info → jaclang-0.3.1.dist-info}/WHEEL +1 -1
- {jaclang-0.2.5.dist-info → jaclang-0.3.1.dist-info}/entry_points.txt +3 -0
- jaclang/core/arch_impl.jac +0 -131
- jaclang/core/element_impl.jac +0 -109
- jaclang/core/exec_ctx_impl.jac +0 -14
- jaclang/core/memory_impl.jac +0 -57
- jaclang/jac/tests/fixtures/__jac_gen__/hello_world.py +0 -5
- /jaclang/{jac/tests/fixtures → core}/__jac_gen__/__init__.py +0 -0
- {jaclang-0.2.5.dist-info → jaclang-0.3.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Test pass module."""
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from jaclang.jac.passes.main import JacTypeCheckPass
|
|
5
|
+
from jaclang.jac.passes.main.schedules import py_code_gen_typed
|
|
6
|
+
from jaclang.jac.transpiler import jac_file_to_pass
|
|
7
|
+
from jaclang.utils.test import TestCase
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MypyTypeCheckPassTests(TestCase):
|
|
11
|
+
"""Test pass module."""
|
|
12
|
+
|
|
13
|
+
def setUp(self) -> None:
|
|
14
|
+
"""Set up test."""
|
|
15
|
+
self.__messages: List[str] = []
|
|
16
|
+
return super().setUp()
|
|
17
|
+
|
|
18
|
+
def __message_cb(
|
|
19
|
+
self, filename: str | None, new_messages: list[str], is_serious: bool
|
|
20
|
+
) -> None:
|
|
21
|
+
for message in new_messages:
|
|
22
|
+
self.__messages.append(
|
|
23
|
+
message.replace(self.fixture_abs_path("func.jac"), "")
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def test_type_errors(self) -> None:
|
|
27
|
+
"""Basic test for pass."""
|
|
28
|
+
JacTypeCheckPass.message_cb = self.__message_cb
|
|
29
|
+
|
|
30
|
+
jac_file_to_pass(
|
|
31
|
+
file_path=self.fixture_abs_path("func.jac"),
|
|
32
|
+
schedule=py_code_gen_typed,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
errs = "\n".join(self.__messages)
|
|
36
|
+
for i in [
|
|
37
|
+
"File::4",
|
|
38
|
+
"File::12",
|
|
39
|
+
'(got "int", expected "str")',
|
|
40
|
+
'(got "str", expected "int")',
|
|
41
|
+
]:
|
|
42
|
+
self.assertIn(i, errs)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Integrate mypy infrastructure into Jac.
|
|
2
|
+
|
|
3
|
+
This is used to call mypy type checking into Jac files by integrating
|
|
4
|
+
mypy apis into Jac and use jac py ast in it.
|
|
5
|
+
"""
|
|
6
|
+
import os
|
|
7
|
+
import pathlib
|
|
8
|
+
import sys
|
|
9
|
+
from typing import Callable, List, Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import jaclang.jac.absyntree as ast
|
|
13
|
+
import jaclang.jac.passes.utils.mypy_ast_build as myab
|
|
14
|
+
from jaclang.jac.passes import Pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class JacTypeCheckPass(Pass):
|
|
18
|
+
"""Python and bytecode file printing pass."""
|
|
19
|
+
|
|
20
|
+
message_cb: Optional[Callable[[str | None, List[str], bool], None]] = None
|
|
21
|
+
|
|
22
|
+
def before_pass(self) -> None:
|
|
23
|
+
"""Before pass."""
|
|
24
|
+
self.__path = (
|
|
25
|
+
pathlib.Path(os.path.dirname(__file__)).parent.parent.parent
|
|
26
|
+
/ "vendor"
|
|
27
|
+
/ "mypy"
|
|
28
|
+
)
|
|
29
|
+
return super().before_pass()
|
|
30
|
+
|
|
31
|
+
def enter_module(self, node: ast.Module) -> None:
|
|
32
|
+
"""Call mypy checks on module level only."""
|
|
33
|
+
self.api(node, node.loc.mod_path)
|
|
34
|
+
self.terminate()
|
|
35
|
+
|
|
36
|
+
def default_message_cb(
|
|
37
|
+
self, filename: str | None, new_messages: list[str], is_serious: bool
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Mypy errors reporter."""
|
|
40
|
+
for msg in new_messages:
|
|
41
|
+
self.warning(msg)
|
|
42
|
+
|
|
43
|
+
def api(self, node: ast.Module, mod_path: str) -> None:
|
|
44
|
+
"""Call mypy APIs to implement type checking in Jac."""
|
|
45
|
+
# Creating mypy api obbjects
|
|
46
|
+
options = myab.Options()
|
|
47
|
+
errors = myab.Errors(options)
|
|
48
|
+
fs_cache = myab.FileSystemCache()
|
|
49
|
+
search_paths = myab.compute_search_paths([], options, str(self.__path))
|
|
50
|
+
plugin, snapshot = myab.load_plugins(options, errors, sys.stdout, [])
|
|
51
|
+
|
|
52
|
+
if self.message_cb is not None:
|
|
53
|
+
message_cb = self.message_cb
|
|
54
|
+
else:
|
|
55
|
+
message_cb = self.default_message_cb
|
|
56
|
+
|
|
57
|
+
manager = myab.BuildManager(
|
|
58
|
+
data_dir=".",
|
|
59
|
+
search_paths=search_paths,
|
|
60
|
+
ignore_prefix=os.getcwd(),
|
|
61
|
+
source_set=myab.BuildSourceSet([]),
|
|
62
|
+
reports=None,
|
|
63
|
+
options=options,
|
|
64
|
+
version_id="1.8.0+dev",
|
|
65
|
+
plugin=plugin,
|
|
66
|
+
plugins_snapshot=snapshot,
|
|
67
|
+
errors=errors,
|
|
68
|
+
flush_errors=message_cb,
|
|
69
|
+
fscache=fs_cache,
|
|
70
|
+
stdout=sys.stdout,
|
|
71
|
+
stderr=sys.stderr,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
tree = myab.ASTConverter(
|
|
75
|
+
options=options,
|
|
76
|
+
is_stub=False,
|
|
77
|
+
errors=errors,
|
|
78
|
+
ignore_errors=False,
|
|
79
|
+
strip_function_bodies=False,
|
|
80
|
+
).visit(node.gen.py_ast)
|
|
81
|
+
|
|
82
|
+
st = myab.State(
|
|
83
|
+
id="Jac Module",
|
|
84
|
+
path="File:" + mod_path,
|
|
85
|
+
source="",
|
|
86
|
+
manager=manager,
|
|
87
|
+
root_source=False,
|
|
88
|
+
ast_override=tree,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
graph = myab.load_graph(
|
|
92
|
+
[
|
|
93
|
+
myab.BuildSource(
|
|
94
|
+
path=str(self.__path / "typeshed" / "stdlib" / "builtins.pyi"),
|
|
95
|
+
module="builtins",
|
|
96
|
+
)
|
|
97
|
+
],
|
|
98
|
+
manager,
|
|
99
|
+
old_graph={"JacTree": st},
|
|
100
|
+
)
|
|
101
|
+
myab.process_graph(graph, manager)
|
|
102
|
+
|
|
103
|
+
myab.semantic_analysis_for_scc(graph, ["JacTree"], errors)
|
|
@@ -13,7 +13,7 @@ class FuseCommentsPass(Pass):
|
|
|
13
13
|
def before_pass(self) -> None:
|
|
14
14
|
"""Before pass."""
|
|
15
15
|
self.all_tokens: list[ast.Token] = []
|
|
16
|
-
self.comments: list[ast.
|
|
16
|
+
self.comments: list[ast.CommentToken] = (
|
|
17
17
|
self.ir.source.comments if isinstance(self.ir, ast.Module) else []
|
|
18
18
|
)
|
|
19
19
|
return super().before_pass()
|
|
@@ -25,44 +25,62 @@ class FuseCommentsPass(Pass):
|
|
|
25
25
|
|
|
26
26
|
def after_pass(self) -> None:
|
|
27
27
|
"""Insert comment tokens into all_tokens."""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
)
|
|
46
|
-
or (self.all_tokens[i].loc.first_line > chomp[0].loc.first_line)
|
|
28
|
+
comment_stream = iter(self.comments) # Iterator for comments
|
|
29
|
+
code_stream = iter(self.all_tokens) # Iterator for code tokens
|
|
30
|
+
new_stream = [] # New stream to hold ordered tokens
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
next_comment = next(comment_stream) # Get the first comment
|
|
34
|
+
except StopIteration:
|
|
35
|
+
next_comment = None
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
next_code = next(code_stream) # Get the first code token
|
|
39
|
+
except StopIteration:
|
|
40
|
+
next_code = None
|
|
41
|
+
|
|
42
|
+
while next_comment or next_code:
|
|
43
|
+
if next_comment and (
|
|
44
|
+
not next_code or is_comment_next(next_comment, next_code)
|
|
47
45
|
):
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
# Add the comment to the new stream
|
|
47
|
+
new_stream.append(next_comment)
|
|
48
|
+
try:
|
|
49
|
+
next_comment = next(comment_stream)
|
|
50
|
+
except StopIteration:
|
|
51
|
+
next_comment = None
|
|
52
|
+
elif next_code:
|
|
53
|
+
# Add the code token to the new stream
|
|
54
|
+
new_stream.append(next_code)
|
|
55
|
+
try:
|
|
56
|
+
next_code = next(code_stream)
|
|
57
|
+
except StopIteration:
|
|
58
|
+
next_code = None
|
|
59
|
+
|
|
60
|
+
# Insert the tokens back into the AST
|
|
61
|
+
for i, token in enumerate(new_stream):
|
|
62
|
+
if isinstance(token, ast.CommentToken):
|
|
58
63
|
if i == 0:
|
|
59
|
-
self.ir.add_kids_left([
|
|
60
|
-
continue
|
|
61
|
-
new_val = new_tokens[i - 1]
|
|
62
|
-
if new_val.parent is not None:
|
|
63
|
-
new_kids = new_val.parent.kid
|
|
64
|
-
new_kids.insert(new_kids.index(new_val) + 1, new_tokens[i])
|
|
65
|
-
new_val.parent.set_kids(new_kids)
|
|
64
|
+
self.ir.add_kids_left([token])
|
|
66
65
|
else:
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
prev_token = new_stream[i - 1]
|
|
67
|
+
if prev_token.parent is not None:
|
|
68
|
+
parent_kids = prev_token.parent.kid
|
|
69
|
+
insert_index = parent_kids.index(prev_token) + 1
|
|
70
|
+
parent_kids.insert(insert_index, token)
|
|
71
|
+
prev_token.parent.set_kids(parent_kids)
|
|
72
|
+
else:
|
|
73
|
+
prev_token.pp()
|
|
74
|
+
raise self.ice(
|
|
75
|
+
"Token without parent in AST should be impossible"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def is_comment_next(cmt: ast.CommentToken, code: ast.Token) -> bool:
|
|
80
|
+
"""Compare two CodeLocInfo objects."""
|
|
81
|
+
if cmt.loc.first_line < code.loc.first_line:
|
|
82
|
+
return True
|
|
83
|
+
elif cmt.loc.first_line == code.loc.first_line:
|
|
84
|
+
cmt.is_inline = True
|
|
85
|
+
return cmt.loc.col_start < code.loc.col_start
|
|
86
|
+
return False
|