jaclang 0.2.4__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/__init__.py +9 -3
- jaclang/cli/__init__.py +0 -1
- jaclang/cli/__jac_gen__/cli.py +6 -6
- jaclang/cli/__jac_gen__/cli_impl.py +2 -2
- jaclang/cli/__jac_gen__/cmds.py +2 -3
- jaclang/cli/__jac_gen__/cmds_impl.py +2 -3
- jaclang/cli/cmds.jac +1 -1
- jaclang/cli/cmds_impl.jac +2 -3
- 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 +32 -62
- jaclang/jac/constant.py +3 -7
- jaclang/jac/importer.py +1 -1
- jaclang/jac/parser.py +14 -10
- jaclang/jac/passes/main/__init__.py +2 -0
- jaclang/jac/passes/main/def_use_pass.py +4 -7
- jaclang/jac/passes/main/pyast_gen_pass.py +116 -35
- jaclang/jac/passes/main/schedules.py +6 -0
- jaclang/jac/passes/main/sym_tab_build_pass.py +40 -19
- jaclang/jac/passes/main/tests/test_jac_format_pass.py +22 -4
- jaclang/jac/passes/main/tests/test_pyast_gen_pass.py +3 -1
- 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/ast_printer_pass.py +8 -2
- jaclang/jac/passes/tool/fuse_comments_pass.py +57 -39
- jaclang/jac/passes/tool/jac_formatter_pass.py +419 -192
- jaclang/jac/passes/tool/sym_tab_printer_pass.py +10 -93
- jaclang/jac/passes/tool/tests/test_ast_print_pass.py +2 -1
- 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 +16 -7
- jaclang/jac/plugin/spec.py +34 -6
- jaclang/jac/symtable.py +6 -0
- jaclang/jac/tests/test_workspace.py +55 -1
- 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/utils/treeprinter.py +171 -0
- 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.4.dist-info → jaclang-0.3.0.dist-info}/METADATA +1 -1
- {jaclang-0.2.4.dist-info → jaclang-0.3.0.dist-info}/RECORD +77 -71
- {jaclang-0.2.4.dist-info → jaclang-0.3.0.dist-info}/WHEEL +1 -1
- {jaclang-0.2.4.dist-info → jaclang-0.3.0.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.4.dist-info → jaclang-0.3.0.dist-info}/top_level.txt +0 -0
jaclang/jac/plugin/spec.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Jac Language Features."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
from typing import Any, Callable, Optional, Protocol, TypeVar
|
|
4
|
+
from typing import Any, Callable, Optional, Protocol, Type, TypeVar
|
|
5
5
|
|
|
6
6
|
from jaclang.jac.constant import EdgeDir
|
|
7
7
|
|
|
@@ -10,14 +10,26 @@ import pluggy
|
|
|
10
10
|
hookspec = pluggy.HookspecMarker("jac")
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class Architype:
|
|
14
14
|
"""Architype Protocol."""
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
class ArchitypeProtocol(Protocol):
|
|
17
|
+
"""Architype Protocol."""
|
|
18
|
+
|
|
19
|
+
_jac_: ArchitypeProtocol
|
|
20
|
+
|
|
21
|
+
def __call__(self, target: Architype) -> None:
|
|
22
|
+
"""Call the architype's data spatial behavior."""
|
|
23
|
+
if callable(self._jac_):
|
|
24
|
+
return self._jac_(target)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AbsRootHook:
|
|
28
|
+
"""Abstract Root Node."""
|
|
17
29
|
|
|
18
30
|
|
|
19
31
|
T = TypeVar("T")
|
|
20
|
-
AT = TypeVar("AT", bound=
|
|
32
|
+
AT = TypeVar("AT", bound=Architype)
|
|
21
33
|
|
|
22
34
|
|
|
23
35
|
class JacFeatureSpec:
|
|
@@ -25,39 +37,45 @@ class JacFeatureSpec:
|
|
|
25
37
|
|
|
26
38
|
@staticmethod
|
|
27
39
|
@hookspec(firstresult=True)
|
|
28
|
-
def bind_architype(arch: AT) ->
|
|
40
|
+
def bind_architype(arch: Type[AT], arch_type: str) -> bool:
|
|
29
41
|
"""Create a new architype."""
|
|
42
|
+
raise NotImplementedError
|
|
30
43
|
|
|
31
44
|
@staticmethod
|
|
32
45
|
@hookspec(firstresult=True)
|
|
33
46
|
def make_ds_ability(event: str, trigger: Optional[type]) -> Callable[[type], type]:
|
|
34
47
|
"""Create a new architype."""
|
|
48
|
+
raise NotImplementedError
|
|
35
49
|
|
|
36
50
|
@staticmethod
|
|
37
51
|
@hookspec(firstresult=True)
|
|
38
52
|
def elvis(op1: Optional[T], op2: T) -> T: # noqa: ANN401
|
|
39
53
|
"""Jac's elvis operator feature."""
|
|
54
|
+
raise NotImplementedError
|
|
40
55
|
|
|
41
56
|
@staticmethod
|
|
42
57
|
@hookspec(firstresult=True)
|
|
43
58
|
def report(expr: Any) -> Any: # noqa: ANN401
|
|
44
59
|
"""Jac's report stmt feature."""
|
|
60
|
+
raise NotImplementedError
|
|
45
61
|
|
|
46
62
|
@staticmethod
|
|
47
63
|
@hookspec(firstresult=True)
|
|
48
64
|
def ignore(walker_obj: Any, expr: Any) -> bool: # noqa: ANN401
|
|
49
65
|
"""Jac's ignore stmt feature."""
|
|
66
|
+
raise NotImplementedError
|
|
50
67
|
|
|
51
68
|
@staticmethod
|
|
52
69
|
@hookspec(firstresult=True)
|
|
53
70
|
def visit(walker_obj: Any, expr: Any) -> bool: # noqa: ANN401
|
|
54
71
|
"""Jac's visit stmt feature."""
|
|
55
|
-
|
|
72
|
+
raise NotImplementedError
|
|
56
73
|
|
|
57
74
|
@staticmethod
|
|
58
75
|
@hookspec(firstresult=True)
|
|
59
76
|
def disengage(walker_obj: Any) -> bool: # noqa: ANN401
|
|
60
77
|
"""Jac's disengage stmt feature."""
|
|
78
|
+
raise NotImplementedError
|
|
61
79
|
|
|
62
80
|
@staticmethod
|
|
63
81
|
@hookspec(firstresult=True)
|
|
@@ -65,6 +83,7 @@ class JacFeatureSpec:
|
|
|
65
83
|
node_obj: Any, dir: EdgeDir, filter_type: Optional[type] # noqa: ANN401
|
|
66
84
|
) -> list[Any]:
|
|
67
85
|
"""Jac's apply_dir stmt feature."""
|
|
86
|
+
raise NotImplementedError
|
|
68
87
|
|
|
69
88
|
@staticmethod
|
|
70
89
|
@hookspec(firstresult=True)
|
|
@@ -73,11 +92,13 @@ class JacFeatureSpec:
|
|
|
73
92
|
|
|
74
93
|
Note: connect needs to call assign compr with tuple in op
|
|
75
94
|
"""
|
|
95
|
+
raise NotImplementedError
|
|
76
96
|
|
|
77
97
|
@staticmethod
|
|
78
98
|
@hookspec(firstresult=True)
|
|
79
99
|
def disconnect(op1: Optional[T], op2: T, op: Any) -> T: # noqa: ANN401
|
|
80
100
|
"""Jac's connect operator feature."""
|
|
101
|
+
raise NotImplementedError
|
|
81
102
|
|
|
82
103
|
@staticmethod
|
|
83
104
|
@hookspec(firstresult=True)
|
|
@@ -85,3 +106,10 @@ class JacFeatureSpec:
|
|
|
85
106
|
target: list[T], attr_val: tuple[tuple[str], tuple[Any]]
|
|
86
107
|
) -> list[T]:
|
|
87
108
|
"""Jac's assign comprehension feature."""
|
|
109
|
+
raise NotImplementedError
|
|
110
|
+
|
|
111
|
+
@staticmethod
|
|
112
|
+
@hookspec(firstresult=True)
|
|
113
|
+
def get_root() -> Architype:
|
|
114
|
+
"""Jac's root getter."""
|
|
115
|
+
raise NotImplementedError
|
jaclang/jac/symtable.py
CHANGED
|
@@ -4,6 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
from enum import Enum
|
|
5
5
|
from typing import Optional, TYPE_CHECKING
|
|
6
6
|
|
|
7
|
+
from jaclang.utils.treeprinter import print_symtab_tree
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
if TYPE_CHECKING:
|
|
9
11
|
import jaclang.jac.absyntree as ast
|
|
@@ -158,6 +160,10 @@ class SymbolTable:
|
|
|
158
160
|
self.kid.append(SymbolTable(name, key_node, self))
|
|
159
161
|
return self.kid[-1]
|
|
160
162
|
|
|
163
|
+
def pp(self, depth: Optional[int] = None) -> str:
|
|
164
|
+
"""Pretty print."""
|
|
165
|
+
return print_symtab_tree(root=self, depth=depth)
|
|
166
|
+
|
|
161
167
|
def __repr__(self) -> str:
|
|
162
168
|
"""Repr."""
|
|
163
169
|
out = f"{self.name} {super().__repr__()}:\n"
|
|
@@ -5,7 +5,7 @@ from jaclang.jac.workspace import Workspace
|
|
|
5
5
|
from jaclang.utils.test import TestCase
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class
|
|
8
|
+
class TestWorkspace(TestCase):
|
|
9
9
|
"""Test Jac Workspace."""
|
|
10
10
|
|
|
11
11
|
def test_workspace_basic(self) -> None:
|
|
@@ -36,3 +36,57 @@ class TestWrokspace(TestCase):
|
|
|
36
36
|
ws = Workspace(path=os.path.join(os.path.dirname(__file__)))
|
|
37
37
|
key = [i for i in ws.modules.keys() if "fam.jac" in i][0]
|
|
38
38
|
self.assertGreater(len(ws.get_uses(key)), 5)
|
|
39
|
+
|
|
40
|
+
def test_man_code_dir(self) -> None:
|
|
41
|
+
"""Test of circle workspace."""
|
|
42
|
+
loc = os.path.join(os.path.dirname(__file__))
|
|
43
|
+
ws = Workspace(path=loc + "/../../../examples/manual_code")
|
|
44
|
+
key = [i for i in ws.modules.keys() if "circle.jac" in i][0]
|
|
45
|
+
# print(ws.modules[key].ir.sym_tab.pp())
|
|
46
|
+
# for i in ws.get_symbols(key):
|
|
47
|
+
# print(i.decl.pp(depth=2))
|
|
48
|
+
out = ""
|
|
49
|
+
for i in ws.get_uses(key):
|
|
50
|
+
# print(i.pp(depth=2).strip())
|
|
51
|
+
out += i.pp(depth=2)
|
|
52
|
+
for i in [
|
|
53
|
+
"math",
|
|
54
|
+
"calculate_area",
|
|
55
|
+
"RAD",
|
|
56
|
+
"expected_area",
|
|
57
|
+
"Circle",
|
|
58
|
+
"c",
|
|
59
|
+
"ShapeType",
|
|
60
|
+
"float",
|
|
61
|
+
"radius",
|
|
62
|
+
"CIRCLE",
|
|
63
|
+
"Shape",
|
|
64
|
+
"__init__",
|
|
65
|
+
"print",
|
|
66
|
+
]:
|
|
67
|
+
self.assertIn(i, out)
|
|
68
|
+
|
|
69
|
+
# def test_decl_impl(self) -> None:
|
|
70
|
+
# """Test of circle workspace."""
|
|
71
|
+
# loc = os.path.join(os.path.dirname(__file__))
|
|
72
|
+
# ws = Workspace(path=loc + "/../../../examples/manual_code")
|
|
73
|
+
# key = [i for i in ws.modules.keys() if "circle_clean.jac" in i][0]
|
|
74
|
+
# out = ""
|
|
75
|
+
# for i in ws.get_uses(key):
|
|
76
|
+
# out += i.pp(depth=2)
|
|
77
|
+
# for i in [
|
|
78
|
+
# "math",
|
|
79
|
+
# "calculate_area",
|
|
80
|
+
# "RAD",
|
|
81
|
+
# "expected_area",
|
|
82
|
+
# "Circle",
|
|
83
|
+
# "c",
|
|
84
|
+
# "ShapeType",
|
|
85
|
+
# "float",
|
|
86
|
+
# "radius",
|
|
87
|
+
# "CIRCLE",
|
|
88
|
+
# "Shape",
|
|
89
|
+
# "__init__",
|
|
90
|
+
# "print",
|
|
91
|
+
# ]:
|
|
92
|
+
# self.assertIn(i, out)
|
jaclang/jac/transpiler.py
CHANGED
|
@@ -4,11 +4,7 @@ from typing import Optional, Type
|
|
|
4
4
|
import jaclang.jac.absyntree as ast
|
|
5
5
|
from jaclang.jac.parser import JacParser
|
|
6
6
|
from jaclang.jac.passes import Pass
|
|
7
|
-
from jaclang.jac.passes.main import
|
|
8
|
-
PyOutPass,
|
|
9
|
-
PyastGenPass,
|
|
10
|
-
pass_schedule,
|
|
11
|
-
)
|
|
7
|
+
from jaclang.jac.passes.main import PyOutPass, pass_schedule
|
|
12
8
|
from jaclang.jac.passes.tool import JacFormatPass
|
|
13
9
|
from jaclang.jac.passes.tool.schedules import format_pass
|
|
14
10
|
from jaclang.jac.passes.transform import Alert
|
|
@@ -18,7 +14,6 @@ def transpile_jac(file_path: str) -> list[Alert]:
|
|
|
18
14
|
"""Transpiler Jac file and return python code as string."""
|
|
19
15
|
code = jac_file_to_pass(
|
|
20
16
|
file_path=file_path,
|
|
21
|
-
target=PyastGenPass,
|
|
22
17
|
schedule=pass_schedule,
|
|
23
18
|
)
|
|
24
19
|
if isinstance(code.ir, ast.Module) and not code.errors_had:
|
|
@@ -30,7 +25,7 @@ def transpile_jac(file_path: str) -> list[Alert]:
|
|
|
30
25
|
|
|
31
26
|
def jac_file_to_pass(
|
|
32
27
|
file_path: str,
|
|
33
|
-
target: Optional[Type[Pass]] =
|
|
28
|
+
target: Optional[Type[Pass]] = None,
|
|
34
29
|
schedule: list[Type[Pass]] = pass_schedule,
|
|
35
30
|
) -> Pass:
|
|
36
31
|
"""Convert a Jac file to an AST."""
|
|
@@ -46,7 +41,7 @@ def jac_file_to_pass(
|
|
|
46
41
|
def jac_str_to_pass(
|
|
47
42
|
jac_str: str,
|
|
48
43
|
file_path: str,
|
|
49
|
-
target: Optional[Type[Pass]] =
|
|
44
|
+
target: Optional[Type[Pass]] = None,
|
|
50
45
|
schedule: list[Type[Pass]] = pass_schedule,
|
|
51
46
|
) -> Pass:
|
|
52
47
|
"""Convert a Jac file to an AST."""
|
|
@@ -64,7 +59,7 @@ def jac_str_to_pass(
|
|
|
64
59
|
|
|
65
60
|
def jac_pass_to_pass(
|
|
66
61
|
in_pass: Pass,
|
|
67
|
-
target: Optional[Type[Pass]] =
|
|
62
|
+
target: Optional[Type[Pass]] = None,
|
|
68
63
|
schedule: list[Type[Pass]] = pass_schedule,
|
|
69
64
|
) -> Pass:
|
|
70
65
|
"""Convert a Jac file to an AST."""
|
jaclang/utils/helpers.py
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"""Utility functions and classes for Jac compilation toolchain."""
|
|
2
2
|
import re
|
|
3
3
|
import textwrap
|
|
4
|
-
import traceback
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
import jaclang.jac.absyntree as ast
|
|
8
|
-
from jaclang.jac.constant import Constants as Con, Values as Val
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
def pascal_to_snake(pascal_string: str) -> str:
|
|
@@ -44,37 +42,6 @@ def dedent_code_block(code: str) -> str:
|
|
|
44
42
|
return textwrap.dedent(code)
|
|
45
43
|
|
|
46
44
|
|
|
47
|
-
def handle_jac_error(code_string: str, e: Exception, tb: traceback.StackSummary) -> str:
|
|
48
|
-
"""Handle Jac Error."""
|
|
49
|
-
except_line = e.end_lineno if isinstance(e, SyntaxError) else list(tb)[-1].lineno
|
|
50
|
-
if not isinstance(except_line, int) or except_line == 0:
|
|
51
|
-
return ""
|
|
52
|
-
py_error_region = clip_code_section(
|
|
53
|
-
add_line_numbers(code_string), except_line, Val.JAC_ERROR_LINE_RANGE
|
|
54
|
-
)
|
|
55
|
-
try:
|
|
56
|
-
jac_err_line = int(code_string.splitlines()[except_line - 1].split()[-1])
|
|
57
|
-
mod_index = int(code_string.splitlines()[except_line - 1].split()[-2])
|
|
58
|
-
mod_paths = code_string.split(Con.JAC_DEBUG_SPLITTER)[1].strip().splitlines()
|
|
59
|
-
target_mod = mod_paths[mod_index]
|
|
60
|
-
with open(target_mod, "r") as file:
|
|
61
|
-
jac_code_string = file.read()
|
|
62
|
-
jac_error_region = clip_code_section(
|
|
63
|
-
add_line_numbers(jac_code_string), jac_err_line, Val.JAC_ERROR_LINE_RANGE
|
|
64
|
-
)
|
|
65
|
-
target_mod = f"JacCode File: {target_mod}:{jac_err_line}"
|
|
66
|
-
except Exception as e:
|
|
67
|
-
jac_error_region = str(e)
|
|
68
|
-
target_mod = ""
|
|
69
|
-
snippet = (
|
|
70
|
-
f"{Con.JAC_ERROR_PREAMBLE}\n"
|
|
71
|
-
f"{target_mod}\n"
|
|
72
|
-
f"JacCode Snippet:\n{jac_error_region}\n"
|
|
73
|
-
f"PyCode Snippet:\n{py_error_region}\n"
|
|
74
|
-
)
|
|
75
|
-
return snippet
|
|
76
|
-
|
|
77
|
-
|
|
78
45
|
def get_ast_nodes_as_snake_case() -> list[str]:
|
|
79
46
|
"""Get all AST nodes as snake case."""
|
|
80
47
|
import inspect
|
jaclang/utils/lang_tools.py
CHANGED
|
@@ -191,6 +191,9 @@ class AstTool:
|
|
|
191
191
|
arrow = "-.->" if "Optional" in kid.typ else "-->"
|
|
192
192
|
typ = (
|
|
193
193
|
kid.typ.replace("Optional[", "")
|
|
194
|
+
.replace("SubNodeList[", "")
|
|
195
|
+
.replace("SubTag[", "")
|
|
196
|
+
.replace("Sequence[", "")
|
|
194
197
|
.replace("]", "")
|
|
195
198
|
.replace("|", ",")
|
|
196
199
|
.replace("list[", "list - ")
|
jaclang/utils/test.py
CHANGED
|
@@ -65,7 +65,9 @@ class TestCaseMicroSuite(ABC, TestCase):
|
|
|
65
65
|
"""Attach micro tests."""
|
|
66
66
|
for filename in [
|
|
67
67
|
os.path.normpath(os.path.join(root, name))
|
|
68
|
-
for root, _, files in os.walk(
|
|
68
|
+
for root, _, files in os.walk(
|
|
69
|
+
os.path.dirname(os.path.dirname(jaclang.__file__))
|
|
70
|
+
)
|
|
69
71
|
for name in files
|
|
70
72
|
if name.endswith(".jac") and not name.startswith("err")
|
|
71
73
|
]:
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Tree Printing Helpers for Jac."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Optional, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from jaclang.jac.absyntree import AstNode, SymbolTable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def print_ast_tree(
|
|
11
|
+
root: AstNode,
|
|
12
|
+
marker: str = "+-- ",
|
|
13
|
+
level_markers: Optional[list[bool]] = None,
|
|
14
|
+
output_file: Optional[str] = None,
|
|
15
|
+
max_depth: Optional[int] = None,
|
|
16
|
+
) -> str:
|
|
17
|
+
"""Recursively print ast tree."""
|
|
18
|
+
from jaclang.jac.absyntree import AstSymbolNode, Token
|
|
19
|
+
|
|
20
|
+
def __node_repr_in_tree(node: AstNode) -> str:
|
|
21
|
+
if isinstance(node, Token):
|
|
22
|
+
return f"{node.__class__.__name__} - {node.value}"
|
|
23
|
+
elif isinstance(node, AstSymbolNode):
|
|
24
|
+
return f"{node.__class__.__name__} - {node.sym_name}"
|
|
25
|
+
else:
|
|
26
|
+
return f"{node.__class__.__name__}"
|
|
27
|
+
|
|
28
|
+
if root is None or (
|
|
29
|
+
max_depth is not None and len(level_markers or []) >= max_depth
|
|
30
|
+
):
|
|
31
|
+
return ""
|
|
32
|
+
|
|
33
|
+
empty_str = " " * len(marker)
|
|
34
|
+
connection_str = "|" + empty_str[:-1]
|
|
35
|
+
if not level_markers:
|
|
36
|
+
level_markers = []
|
|
37
|
+
level = len(level_markers) # recursion level
|
|
38
|
+
|
|
39
|
+
def mapper(draw: bool) -> str:
|
|
40
|
+
return connection_str if draw else empty_str
|
|
41
|
+
|
|
42
|
+
markers = "".join(map(mapper, level_markers[:-1]))
|
|
43
|
+
markers += marker if level > 0 else ""
|
|
44
|
+
|
|
45
|
+
tree_str = f"{root.loc}\t{markers}{__node_repr_in_tree(root)}\n"
|
|
46
|
+
|
|
47
|
+
for i, child in enumerate(root.kid):
|
|
48
|
+
is_last = i == len(root.kid) - 1
|
|
49
|
+
tree_str += print_ast_tree(
|
|
50
|
+
child, marker, [*level_markers, not is_last], output_file, max_depth
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Write to file only at the top level call
|
|
54
|
+
if output_file and level == 0:
|
|
55
|
+
with open(output_file, "w") as f:
|
|
56
|
+
f.write(tree_str)
|
|
57
|
+
|
|
58
|
+
return tree_str
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class SymbolTree:
|
|
62
|
+
"""Symbol Tree Node."""
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
node_name: str,
|
|
67
|
+
parent: Optional[SymbolTree] = None,
|
|
68
|
+
children: Optional[list[SymbolTree]] = None,
|
|
69
|
+
) -> None:
|
|
70
|
+
"""Initialize Symbol Tree Node."""
|
|
71
|
+
self.parent = parent
|
|
72
|
+
self.kid = children if children is not None else []
|
|
73
|
+
self.name = node_name
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def parent(self) -> Optional[SymbolTree]:
|
|
77
|
+
"""Get parent node."""
|
|
78
|
+
return self.__parent
|
|
79
|
+
|
|
80
|
+
@parent.setter
|
|
81
|
+
def parent(self, parent_node: Optional[SymbolTree]) -> None:
|
|
82
|
+
"""Set parent node."""
|
|
83
|
+
if parent_node:
|
|
84
|
+
self.__parent = parent_node
|
|
85
|
+
parent_node.kid.append(self)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _build_symbol_tree_common(
|
|
89
|
+
node: SymbolTable, parent_node: Optional[SymbolTree] = None
|
|
90
|
+
) -> SymbolTree:
|
|
91
|
+
root = SymbolTree(
|
|
92
|
+
node_name=f"SymTable::{node.owner.__class__.__name__}({node.name})",
|
|
93
|
+
parent=parent_node,
|
|
94
|
+
)
|
|
95
|
+
symbols = SymbolTree(node_name="Symbols", parent=root)
|
|
96
|
+
children = SymbolTree(node_name="Sub Tables", parent=root)
|
|
97
|
+
|
|
98
|
+
for sym in node.tab.values():
|
|
99
|
+
symbol_node = SymbolTree(node_name=f"{sym.sym_name}", parent=symbols)
|
|
100
|
+
SymbolTree(node_name=f"{sym.access} {sym.sym_type}", parent=symbol_node)
|
|
101
|
+
|
|
102
|
+
if sym.decl and sym.decl.loc.first_line > 0:
|
|
103
|
+
SymbolTree(
|
|
104
|
+
node_name=f"decl: line {sym.decl.loc.first_line}, col {sym.decl.loc.col_start}",
|
|
105
|
+
parent=symbol_node,
|
|
106
|
+
)
|
|
107
|
+
defn = SymbolTree(node_name="defn", parent=symbol_node)
|
|
108
|
+
[
|
|
109
|
+
SymbolTree(
|
|
110
|
+
node_name=f"line {n.loc.first_line}, col {n.loc.col_start}",
|
|
111
|
+
parent=defn,
|
|
112
|
+
)
|
|
113
|
+
for n in sym.defn
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
for k in node.kid:
|
|
117
|
+
_build_symbol_tree_common(k, children)
|
|
118
|
+
return root
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def print_symtab_tree(
|
|
122
|
+
root: SymbolTable,
|
|
123
|
+
marker: str = "+-- ",
|
|
124
|
+
level_markers: Optional[list[bool]] = None,
|
|
125
|
+
output_file: Optional[str] = None,
|
|
126
|
+
depth: Optional[int] = None,
|
|
127
|
+
) -> str:
|
|
128
|
+
"""Recursively print symbol table tree."""
|
|
129
|
+
return get_symtab_tree_str(
|
|
130
|
+
_build_symbol_tree_common(root),
|
|
131
|
+
marker,
|
|
132
|
+
level_markers,
|
|
133
|
+
output_file,
|
|
134
|
+
depth,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def get_symtab_tree_str(
|
|
139
|
+
root: SymbolTree,
|
|
140
|
+
marker: str = "+-- ",
|
|
141
|
+
level_markers: Optional[list[bool]] = None,
|
|
142
|
+
output_file: Optional[str] = None,
|
|
143
|
+
depth: Optional[int] = None,
|
|
144
|
+
) -> str:
|
|
145
|
+
"""Recursively print symbol table tree."""
|
|
146
|
+
if root is None or depth == 0:
|
|
147
|
+
return ""
|
|
148
|
+
|
|
149
|
+
level_markers = level_markers or []
|
|
150
|
+
markers = "".join(
|
|
151
|
+
[
|
|
152
|
+
"|" + " " * (len(marker) - 1) if draw else " " * len(marker)
|
|
153
|
+
for draw in level_markers[:-1]
|
|
154
|
+
]
|
|
155
|
+
) + (marker if level_markers else "")
|
|
156
|
+
line = f"{markers}{root.name}\n"
|
|
157
|
+
|
|
158
|
+
if output_file:
|
|
159
|
+
with open(output_file, "a+") as f:
|
|
160
|
+
f.write(line)
|
|
161
|
+
|
|
162
|
+
return line + "".join(
|
|
163
|
+
get_symtab_tree_str(
|
|
164
|
+
child,
|
|
165
|
+
marker,
|
|
166
|
+
level_markers + [i < len(root.kid) - 1],
|
|
167
|
+
output_file,
|
|
168
|
+
None if depth is None else depth - 1,
|
|
169
|
+
)
|
|
170
|
+
for i, child in enumerate(root.kid)
|
|
171
|
+
)
|
|
File without changes
|
jaclang/vendor/mypy/checker.py
CHANGED
|
@@ -6106,24 +6106,31 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
|
|
|
6106
6106
|
if node.arg_kinds[0] != nodes.ARG_POS:
|
|
6107
6107
|
# the first argument might be used as a kwarg
|
|
6108
6108
|
called_type = get_proper_type(self.lookup_type(node.callee))
|
|
6109
|
-
|
|
6109
|
+
|
|
6110
|
+
# TODO: there are some more cases in check_call() to handle.
|
|
6111
|
+
if isinstance(called_type, Instance):
|
|
6112
|
+
call = find_member(
|
|
6113
|
+
"__call__", called_type, called_type, is_operator=True
|
|
6114
|
+
)
|
|
6115
|
+
if call is not None:
|
|
6116
|
+
called_type = get_proper_type(call)
|
|
6110
6117
|
|
|
6111
6118
|
# *assuming* the overloaded function is correct, there's a couple cases:
|
|
6112
6119
|
# 1) The first argument has different names, but is pos-only. We don't
|
|
6113
6120
|
# care about this case, the argument must be passed positionally.
|
|
6114
6121
|
# 2) The first argument allows keyword reference, therefore must be the
|
|
6115
6122
|
# same between overloads.
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6123
|
+
if isinstance(called_type, (CallableType, Overloaded)):
|
|
6124
|
+
name = called_type.items[0].arg_names[0]
|
|
6125
|
+
if name in node.arg_names:
|
|
6126
|
+
idx = node.arg_names.index(name)
|
|
6127
|
+
# we want the idx-th variable to be narrowed
|
|
6128
|
+
expr = collapse_walrus(node.args[idx])
|
|
6129
|
+
else:
|
|
6130
|
+
self.fail(
|
|
6131
|
+
message_registry.TYPE_GUARD_POS_ARG_REQUIRED, node
|
|
6132
|
+
)
|
|
6133
|
+
return {}, {}
|
|
6127
6134
|
if literal(expr) == LITERAL_TYPE:
|
|
6128
6135
|
# Note: we wrap the target type, so that we can special case later.
|
|
6129
6136
|
# Namely, for isinstance() we use a normal meet, while TypeGuard is
|
jaclang/vendor/mypy/checkexpr.py
CHANGED
|
@@ -3870,8 +3870,9 @@ class ExpressionChecker(ExpressionVisitor[Type]):
|
|
|
3870
3870
|
self,
|
|
3871
3871
|
left: Type,
|
|
3872
3872
|
right: Type,
|
|
3873
|
-
original_container: Type | None = None,
|
|
3874
3873
|
*,
|
|
3874
|
+
original_container: Type | None = None,
|
|
3875
|
+
seen_types: set[tuple[Type, Type]] | None = None,
|
|
3875
3876
|
prefer_literal: bool = True,
|
|
3876
3877
|
) -> bool:
|
|
3877
3878
|
"""Check for dangerous non-overlapping comparisons like 42 == 'no'.
|
|
@@ -3892,6 +3893,12 @@ class ExpressionChecker(ExpressionVisitor[Type]):
|
|
|
3892
3893
|
if not self.chk.options.strict_equality:
|
|
3893
3894
|
return False
|
|
3894
3895
|
|
|
3896
|
+
if seen_types is None:
|
|
3897
|
+
seen_types = set()
|
|
3898
|
+
if (left, right) in seen_types:
|
|
3899
|
+
return False
|
|
3900
|
+
seen_types.add((left, right))
|
|
3901
|
+
|
|
3895
3902
|
left, right = get_proper_types((left, right))
|
|
3896
3903
|
|
|
3897
3904
|
# We suppress the error if there is a custom __eq__() method on either
|
|
@@ -3949,7 +3956,9 @@ class ExpressionChecker(ExpressionVisitor[Type]):
|
|
|
3949
3956
|
abstract_set = self.chk.lookup_typeinfo("typing.AbstractSet")
|
|
3950
3957
|
left = map_instance_to_supertype(left, abstract_set)
|
|
3951
3958
|
right = map_instance_to_supertype(right, abstract_set)
|
|
3952
|
-
return self.dangerous_comparison(
|
|
3959
|
+
return self.dangerous_comparison(
|
|
3960
|
+
left.args[0], right.args[0], seen_types=seen_types
|
|
3961
|
+
)
|
|
3953
3962
|
elif left.type.has_base("typing.Mapping") and right.type.has_base(
|
|
3954
3963
|
"typing.Mapping"
|
|
3955
3964
|
):
|
|
@@ -3958,13 +3967,17 @@ class ExpressionChecker(ExpressionVisitor[Type]):
|
|
|
3958
3967
|
left = map_instance_to_supertype(left, abstract_map)
|
|
3959
3968
|
right = map_instance_to_supertype(right, abstract_map)
|
|
3960
3969
|
return self.dangerous_comparison(
|
|
3961
|
-
left.args[0], right.args[0]
|
|
3962
|
-
) or self.dangerous_comparison(
|
|
3970
|
+
left.args[0], right.args[0], seen_types=seen_types
|
|
3971
|
+
) or self.dangerous_comparison(
|
|
3972
|
+
left.args[1], right.args[1], seen_types=seen_types
|
|
3973
|
+
)
|
|
3963
3974
|
elif (
|
|
3964
3975
|
left_name in ("builtins.list", "builtins.tuple")
|
|
3965
3976
|
and right_name == left_name
|
|
3966
3977
|
):
|
|
3967
|
-
return self.dangerous_comparison(
|
|
3978
|
+
return self.dangerous_comparison(
|
|
3979
|
+
left.args[0], right.args[0], seen_types=seen_types
|
|
3980
|
+
)
|
|
3968
3981
|
elif left_name in OVERLAPPING_BYTES_ALLOWLIST and right_name in (
|
|
3969
3982
|
OVERLAPPING_BYTES_ALLOWLIST
|
|
3970
3983
|
):
|
|
@@ -6624,11 +6637,16 @@ class PolyTranslator(TypeTranslator):
|
|
|
6624
6637
|
See docstring for apply_poly() for details.
|
|
6625
6638
|
"""
|
|
6626
6639
|
|
|
6627
|
-
def __init__(
|
|
6640
|
+
def __init__(
|
|
6641
|
+
self,
|
|
6642
|
+
poly_tvars: Iterable[TypeVarLikeType],
|
|
6643
|
+
bound_tvars: frozenset[TypeVarLikeType] = frozenset(),
|
|
6644
|
+
seen_aliases: frozenset[TypeInfo] = frozenset(),
|
|
6645
|
+
) -> None:
|
|
6628
6646
|
self.poly_tvars = set(poly_tvars)
|
|
6629
6647
|
# This is a simplified version of TypeVarScope used during semantic analysis.
|
|
6630
|
-
self.bound_tvars
|
|
6631
|
-
self.seen_aliases
|
|
6648
|
+
self.bound_tvars = bound_tvars
|
|
6649
|
+
self.seen_aliases = seen_aliases
|
|
6632
6650
|
|
|
6633
6651
|
def collect_vars(self, t: CallableType | Parameters) -> list[TypeVarLikeType]:
|
|
6634
6652
|
found_vars = []
|
|
@@ -6706,10 +6724,13 @@ class PolyTranslator(TypeTranslator):
|
|
|
6706
6724
|
if t.args and t.type.is_protocol and t.type.protocol_members == ["__call__"]:
|
|
6707
6725
|
if t.type in self.seen_aliases:
|
|
6708
6726
|
raise PolyTranslationError()
|
|
6709
|
-
self.seen_aliases.add(t.type)
|
|
6710
6727
|
call = find_member("__call__", t, t, is_operator=True)
|
|
6711
6728
|
assert call is not None
|
|
6712
|
-
return call.accept(
|
|
6729
|
+
return call.accept(
|
|
6730
|
+
PolyTranslator(
|
|
6731
|
+
self.poly_tvars, self.bound_tvars, self.seen_aliases | {t.type}
|
|
6732
|
+
)
|
|
6733
|
+
)
|
|
6713
6734
|
return super().visit_instance(t)
|
|
6714
6735
|
|
|
6715
6736
|
|