jaclang 0.7.27__py3-none-any.whl → 0.7.28__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 +3 -0
- jaclang/compiler/absyntree.py +18 -3
- jaclang/compiler/passes/main/__init__.py +1 -1
- jaclang/compiler/passes/main/access_modifier_pass.py +1 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +62 -33
- jaclang/compiler/passes/main/import_pass.py +284 -63
- jaclang/compiler/passes/main/inheritance_pass.py +103 -0
- jaclang/compiler/passes/main/py_collect_dep_pass.py +5 -5
- jaclang/compiler/passes/main/pyast_load_pass.py +1 -1
- jaclang/compiler/passes/main/schedules.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +17 -0
- jaclang/compiler/passes/main/tests/fixtures/data_spatial_types.jac +130 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -3
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.pyi +3 -3
- jaclang/compiler/passes/main/tests/test_import_pass.py +13 -17
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +24 -0
- jaclang/compiler/passes/main/type_check_pass.py +3 -2
- jaclang/compiler/py_info.py +22 -0
- jaclang/compiler/symtable.py +9 -2
- jaclang/langserve/tests/test_server.py +2 -2
- jaclang/plugin/default.py +11 -3
- jaclang/plugin/feature.py +2 -0
- jaclang/plugin/spec.py +1 -0
- jaclang/runtimelib/test.py +59 -4
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/base_class1.jac +11 -0
- jaclang/tests/fixtures/base_class2.jac +11 -0
- jaclang/tests/fixtures/import_all.jac +7 -0
- jaclang/tests/fixtures/import_all_py.py +8 -0
- jaclang/tests/fixtures/jactest_imported.jac +6 -0
- jaclang/tests/fixtures/jactest_main.jac +22 -0
- jaclang/tests/fixtures/multi_dim_array_split.jac +2 -6
- jaclang/tests/fixtures/test_py.py +12 -0
- jaclang/tests/test_cli.py +82 -0
- jaclang/tests/test_language.py +7 -7
- jaclang/utils/helpers.py +9 -1
- jaclang/utils/treeprinter.py +6 -3
- {jaclang-0.7.27.dist-info → jaclang-0.7.28.dist-info}/METADATA +2 -2
- {jaclang-0.7.27.dist-info → jaclang-0.7.28.dist-info}/RECORD +41 -31
- {jaclang-0.7.27.dist-info → jaclang-0.7.28.dist-info}/WHEEL +1 -1
- {jaclang-0.7.27.dist-info → jaclang-0.7.28.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Pass used to add the inherited symbols for architypes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
import jaclang.compiler.absyntree as ast
|
|
8
|
+
from jaclang.compiler.passes import Pass
|
|
9
|
+
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
10
|
+
from jaclang.settings import settings
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InheritancePass(Pass):
|
|
14
|
+
"""Add inherited abilities in the target symbol tables."""
|
|
15
|
+
|
|
16
|
+
def __debug_print(self, msg: str) -> None:
|
|
17
|
+
if settings.inherit_pass_debug:
|
|
18
|
+
self.log_info("[PyImportPass] " + msg)
|
|
19
|
+
|
|
20
|
+
def __lookup(self, name: str, sym_table: SymbolTable) -> Optional[Symbol]:
|
|
21
|
+
symbol = sym_table.lookup(name)
|
|
22
|
+
if symbol is None:
|
|
23
|
+
# Check if the needed symbol in builtins
|
|
24
|
+
builtins_symtable = self.ir.sym_tab.find_scope("builtins")
|
|
25
|
+
assert builtins_symtable is not None
|
|
26
|
+
symbol = builtins_symtable.lookup(name)
|
|
27
|
+
return symbol
|
|
28
|
+
|
|
29
|
+
def enter_architype(self, node: ast.Architype) -> None:
|
|
30
|
+
"""Fill architype symbol tables with abilities from parent architypes."""
|
|
31
|
+
if node.base_classes is None:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
for item in node.base_classes.items:
|
|
35
|
+
# The assumption is that the base class can only be a name node
|
|
36
|
+
# or an atom trailer only.
|
|
37
|
+
assert isinstance(item, (ast.Name, ast.AtomTrailer))
|
|
38
|
+
|
|
39
|
+
# In case of name node, then get the symbol table that contains
|
|
40
|
+
# the current class and lookup for that name after that use the
|
|
41
|
+
# symbol to get the symbol table of the base class
|
|
42
|
+
if isinstance(item, ast.Name):
|
|
43
|
+
assert node.sym_tab.parent is not None
|
|
44
|
+
base_class_symbol = self.__lookup(item.sym_name, node.sym_tab.parent)
|
|
45
|
+
if base_class_symbol is None:
|
|
46
|
+
msg = "Missing symbol for base class "
|
|
47
|
+
msg += f"{ast.Module.get_href_path(item)}.{item.sym_name}"
|
|
48
|
+
msg += f" needed for {ast.Module.get_href_path(node)}"
|
|
49
|
+
self.__debug_print(msg)
|
|
50
|
+
continue
|
|
51
|
+
base_class_symbol_table = base_class_symbol.fetch_sym_tab
|
|
52
|
+
if (
|
|
53
|
+
base_class_symbol_table is None
|
|
54
|
+
and base_class_symbol.defn[0]
|
|
55
|
+
.parent_of_type(ast.Module)
|
|
56
|
+
.py_info.is_raised_from_py
|
|
57
|
+
):
|
|
58
|
+
msg = "Missing symbol table for python base class "
|
|
59
|
+
msg += f"{ast.Module.get_href_path(item)}.{item.sym_name}"
|
|
60
|
+
msg += f" needed for {ast.Module.get_href_path(node)}"
|
|
61
|
+
self.__debug_print(msg)
|
|
62
|
+
continue
|
|
63
|
+
assert base_class_symbol_table is not None
|
|
64
|
+
node.sym_tab.inherit_sym_tab(base_class_symbol_table)
|
|
65
|
+
|
|
66
|
+
# In case of atom trailer, unwind it and use each name node to
|
|
67
|
+
# as the code above to lookup for the base class
|
|
68
|
+
elif isinstance(item, ast.AtomTrailer):
|
|
69
|
+
current_sym_table = node.sym_tab.parent
|
|
70
|
+
not_found: bool = False
|
|
71
|
+
assert current_sym_table is not None
|
|
72
|
+
for name in item.as_attr_list:
|
|
73
|
+
sym = self.__lookup(name.sym_name, current_sym_table)
|
|
74
|
+
if sym is None:
|
|
75
|
+
msg = "Missing symbol for base class "
|
|
76
|
+
msg += f"{ast.Module.get_href_path(name)}.{name.sym_name}"
|
|
77
|
+
msg += f" needed for {ast.Module.get_href_path(node)}"
|
|
78
|
+
self.__debug_print(msg)
|
|
79
|
+
not_found = True
|
|
80
|
+
break
|
|
81
|
+
current_sym_table = sym.fetch_sym_tab
|
|
82
|
+
|
|
83
|
+
# In case of python nodes, the base class may not be
|
|
84
|
+
# raised so ignore these classes for now
|
|
85
|
+
# TODO Do we need to import these classes?
|
|
86
|
+
if (
|
|
87
|
+
sym.defn[0].parent_of_type(ast.Module).py_info.is_raised_from_py
|
|
88
|
+
and current_sym_table is None
|
|
89
|
+
):
|
|
90
|
+
msg = "Missing symbol table for python base class "
|
|
91
|
+
msg += f"{ast.Module.get_href_path(name)}.{name.sym_name}"
|
|
92
|
+
msg += f" needed for {ast.Module.get_href_path(node)}"
|
|
93
|
+
self.__debug_print(msg)
|
|
94
|
+
not_found = True
|
|
95
|
+
break
|
|
96
|
+
|
|
97
|
+
assert current_sym_table is not None
|
|
98
|
+
|
|
99
|
+
if not_found:
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
assert current_sym_table is not None
|
|
103
|
+
node.sym_tab.inherit_sym_tab(current_sym_table)
|
|
@@ -35,7 +35,7 @@ class PyCollectDepsPass(Pass):
|
|
|
35
35
|
if isinstance(node, ast.ModulePath):
|
|
36
36
|
if node.path:
|
|
37
37
|
path = ".".join([i.value for i in node.path])
|
|
38
|
-
node.abs_path = self.ir.py_mod_dep_map.get(path)
|
|
38
|
+
node.abs_path = self.ir.py_info.py_mod_dep_map.get(path)
|
|
39
39
|
if node.abs_path and os.path.isfile(node.abs_path.replace(".pyi", ".py")):
|
|
40
40
|
node.abs_path = node.abs_path.replace(".pyi", ".py")
|
|
41
41
|
|
|
@@ -45,7 +45,7 @@ class PyCollectDepsPass(Pass):
|
|
|
45
45
|
if mod_path_node.path:
|
|
46
46
|
path = ".".join([i.value for i in mod_path_node.path])
|
|
47
47
|
path += f".{node.name.value}"
|
|
48
|
-
node.abs_path = self.ir.py_mod_dep_map.get(path)
|
|
48
|
+
node.abs_path = self.ir.py_info.py_mod_dep_map.get(path)
|
|
49
49
|
if node.abs_path and os.path.isfile(node.abs_path.replace(".pyi", ".py")):
|
|
50
50
|
node.abs_path = node.abs_path.replace(".pyi", ".py")
|
|
51
51
|
|
|
@@ -61,17 +61,17 @@ class PyCollectDepsPass(Pass):
|
|
|
61
61
|
else:
|
|
62
62
|
mod_name = node_full_name
|
|
63
63
|
|
|
64
|
-
if mod_name not in self.ir.py_mod_dep_map:
|
|
64
|
+
if mod_name not in self.ir.py_info.py_mod_dep_map:
|
|
65
65
|
self.__debug_print(
|
|
66
66
|
f"Can't find a python file associated with {type(node)}::{node.loc}"
|
|
67
67
|
)
|
|
68
68
|
return
|
|
69
69
|
|
|
70
|
-
mode_path = self.ir.py_mod_dep_map[mod_name]
|
|
70
|
+
mode_path = self.ir.py_info.py_mod_dep_map[mod_name]
|
|
71
71
|
if mode_path.endswith(".jac"):
|
|
72
72
|
return
|
|
73
73
|
|
|
74
|
-
self.ir.py_raise_map[mod_name] = mode_path
|
|
74
|
+
self.ir.py_info.py_raise_map[mod_name] = mode_path
|
|
75
75
|
else:
|
|
76
76
|
self.__debug_print(
|
|
77
77
|
f"Collect python dependencies is not supported in {type(node)}::{node.loc}"
|
|
@@ -20,6 +20,7 @@ from .fuse_typeinfo_pass import FuseTypeInfoPass # noqa: I100
|
|
|
20
20
|
from .registry_pass import RegistryPass # noqa: I100
|
|
21
21
|
from .access_modifier_pass import AccessCheckPass # noqa: I100
|
|
22
22
|
from .py_collect_dep_pass import PyCollectDepsPass # noqa: I100
|
|
23
|
+
from .inheritance_pass import InheritancePass # noqa: I100
|
|
23
24
|
|
|
24
25
|
py_code_gen = [
|
|
25
26
|
SubNodeTabPass,
|
|
@@ -38,6 +39,7 @@ type_checker_sched = [
|
|
|
38
39
|
PyCollectDepsPass,
|
|
39
40
|
PyImportPass,
|
|
40
41
|
DefUsePass,
|
|
42
|
+
InheritancePass,
|
|
41
43
|
FuseTypeInfoPass,
|
|
42
44
|
AccessCheckPass,
|
|
43
45
|
]
|
|
@@ -4,6 +4,8 @@ This pass builds the symbol table tree for the Jaseci Ast. It also adds symbols
|
|
|
4
4
|
for globals, imports, architypes, and abilities declarations and definitions.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from typing import TypeVar
|
|
8
|
+
|
|
7
9
|
import jaclang.compiler.absyntree as ast
|
|
8
10
|
from jaclang.compiler.passes import Pass
|
|
9
11
|
from jaclang.compiler.symtable import SymbolTable
|
|
@@ -19,6 +21,7 @@ class SymTabBuildPass(Pass):
|
|
|
19
21
|
def push_scope(self, name: str, key_node: ast.AstNode) -> None:
|
|
20
22
|
"""Push scope."""
|
|
21
23
|
inherit = key_node.parent
|
|
24
|
+
|
|
22
25
|
if not len(self.cur_sym_tab) and not inherit:
|
|
23
26
|
self.cur_sym_tab.append(SymbolTable(name, key_node))
|
|
24
27
|
elif not len(self.cur_sym_tab) and inherit:
|
|
@@ -1284,3 +1287,17 @@ class SymTabBuildPass(Pass):
|
|
|
1284
1287
|
def enter_comment_token(self, node: ast.CommentToken) -> None:
|
|
1285
1288
|
"""Sub objects."""
|
|
1286
1289
|
self.sync_node_to_scope(node)
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
T = TypeVar("T", bound=ast.AstNode)
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
class PyInspectSymTabBuildPass(SymTabBuildPass):
|
|
1296
|
+
"""Jac Symbol table build pass."""
|
|
1297
|
+
|
|
1298
|
+
def push_scope(self, name: str, key_node: ast.AstNode) -> None:
|
|
1299
|
+
"""Push scope."""
|
|
1300
|
+
if not len(self.cur_sym_tab):
|
|
1301
|
+
self.cur_sym_tab.append(SymbolTable(name, key_node))
|
|
1302
|
+
else:
|
|
1303
|
+
self.cur_sym_tab.append(self.cur_scope.push_kid_scope(name, key_node))
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
node NodeA {
|
|
2
|
+
has value: int = 10;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
node NodeC {
|
|
6
|
+
has value: int = 10;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
edge EdgeB {
|
|
10
|
+
has value: int = 20;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
with entry {
|
|
14
|
+
node_1 = a(value=5);
|
|
15
|
+
node_2 = a();
|
|
16
|
+
node_3 = a(value=15);
|
|
17
|
+
node_4 = a(value=20);
|
|
18
|
+
node_5 = c(value=25);
|
|
19
|
+
print(type(root ++> node_1));
|
|
20
|
+
node_1 +:edge_1 := b(value=5):+> node_2;
|
|
21
|
+
node_1 +:edge_2 := b(value=10):+> node_3;
|
|
22
|
+
node_1 +:edge_3 := b(value=15):+> node_4;
|
|
23
|
+
node_1 +:edge_4 := b():+> node_5;
|
|
24
|
+
node_1 del--> node_2;
|
|
25
|
+
del node_3;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
node A {
|
|
30
|
+
has val: int = 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
edge a {}
|
|
34
|
+
|
|
35
|
+
walker W {
|
|
36
|
+
can create with `root entry;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:walker:W:can:create {
|
|
40
|
+
Start = A(5);
|
|
41
|
+
here +:a:+> Start;
|
|
42
|
+
Start +:a:+> A(10) +:a:+> A(15);
|
|
43
|
+
Start +:a:+> A(20) +:a:+> A(25);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
with entry {
|
|
47
|
+
root spawn W();
|
|
48
|
+
print([root-->-->(`?A)]);
|
|
49
|
+
print([root-->-->-->(`?A)]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
"""Bubble sort using DS Features of Jac (somparision and swapping happens in inner nodes)."""
|
|
53
|
+
glob list1 = [80, 79, 60, 59, 40, 35, 19, 1];
|
|
54
|
+
|
|
55
|
+
node main_node {
|
|
56
|
+
has no: int = 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
node inner_node {
|
|
60
|
+
has main: int = 0,
|
|
61
|
+
sub: int = 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
walker walker1 {
|
|
65
|
+
can create_main_node with `root entry;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:walker:walker1:can:create_main_node {
|
|
69
|
+
end = here;
|
|
70
|
+
for i=0 to i<len(list1)+1 by i+=1 {
|
|
71
|
+
end ++> (end := main_node(no=i + 1));
|
|
72
|
+
visit [-->];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
walker walker2 {
|
|
77
|
+
can skip_root with `root entry {
|
|
78
|
+
visit [-->];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
can process with main_node entry;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
:walker:walker2:can:process {
|
|
85
|
+
:g: list1 ;
|
|
86
|
+
|
|
87
|
+
for j in range(0, len(list1) - (here.no)) {
|
|
88
|
+
here ++> inner_node(main=here.no, sub=j + 1);
|
|
89
|
+
}
|
|
90
|
+
visit [-->];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
walker walker3 {
|
|
94
|
+
can skiproot with `root entry {
|
|
95
|
+
visit [-->];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
can adjust with main_node entry;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
:walker:walker3:can:adjust {
|
|
102
|
+
here spawn walker4();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
walker walker4 {
|
|
106
|
+
can skipmain with main_node entry {
|
|
107
|
+
visit [-->];# print(f"iteration {here.no} started {list1}");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
can skipin with inner_node entry {
|
|
111
|
+
:g: list1 ;
|
|
112
|
+
|
|
113
|
+
j = here.sub - 1;
|
|
114
|
+
if list1[j] > list1[j + 1] {
|
|
115
|
+
x = list1[j];
|
|
116
|
+
list1[j] = list1[j + 1];
|
|
117
|
+
list1[j + 1] = x;
|
|
118
|
+
}
|
|
119
|
+
#uncomment below to see the swap in each inner nodes
|
|
120
|
+
# print(list1);
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
with entry {
|
|
126
|
+
root spawn walker1();
|
|
127
|
+
root spawn walker2();
|
|
128
|
+
root spawn walker3();
|
|
129
|
+
print(Jac.node_dot(root));
|
|
130
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .display import
|
|
2
|
-
from .color import
|
|
3
|
-
from .constants import
|
|
1
|
+
from .display import set_mode
|
|
2
|
+
from .color import Color
|
|
3
|
+
from .constants import CONST_VALUE, CL
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .display import
|
|
2
|
-
from .color import
|
|
3
|
-
from .constants import
|
|
1
|
+
from .display import set_mode
|
|
2
|
+
from .color import Color
|
|
3
|
+
from .constants import CONST_VALUE, CL
|
|
@@ -81,39 +81,35 @@ class ImportPassPassTests(TestCase):
|
|
|
81
81
|
"genericpath": r"jaclang/vendor/mypy/typeshed/stdlib/genericpath.pyi$",
|
|
82
82
|
}
|
|
83
83
|
for i in p:
|
|
84
|
-
self.assertIn(i, build.ir.py_raise_map)
|
|
85
|
-
self.assertRegex(
|
|
84
|
+
self.assertIn(i, build.ir.py_info.py_raise_map)
|
|
85
|
+
self.assertRegex(
|
|
86
|
+
re.sub(r".*fixtures/", "", build.ir.py_info.py_raise_map[i]), p[i]
|
|
87
|
+
)
|
|
86
88
|
|
|
87
89
|
def test_py_raised_mods(self) -> None:
|
|
88
90
|
"""Basic test for pass."""
|
|
89
91
|
state = jac_file_to_pass(
|
|
90
92
|
self.fixture_abs_path("py_imp_test.jac"), schedule=py_code_gen_typed
|
|
91
93
|
)
|
|
94
|
+
for i in list(
|
|
95
|
+
filter(
|
|
96
|
+
lambda x: x.py_info.is_raised_from_py,
|
|
97
|
+
state.ir.get_all_sub_nodes(ast.Module),
|
|
98
|
+
)
|
|
99
|
+
):
|
|
100
|
+
print(ast.Module.get_href_path(i))
|
|
92
101
|
self.assertEqual(
|
|
93
102
|
len(
|
|
94
103
|
list(
|
|
95
104
|
filter(
|
|
96
|
-
lambda x: x.is_raised_from_py,
|
|
105
|
+
lambda x: x.py_info.is_raised_from_py,
|
|
97
106
|
state.ir.get_all_sub_nodes(ast.Module),
|
|
98
107
|
)
|
|
99
108
|
)
|
|
100
109
|
),
|
|
101
|
-
|
|
110
|
+
11, # TODO: Need to only link the modules one time
|
|
102
111
|
)
|
|
103
112
|
|
|
104
|
-
# def test_py_resolve_list(self) -> None:
|
|
105
|
-
# """Basic test for pass."""
|
|
106
|
-
# state: JacImportPass = jac_file_to_pass(
|
|
107
|
-
# self.examples_abs_path("rpg_game/jac_impl/jac_impl_5/main.jac"),
|
|
108
|
-
# JacImportPass,
|
|
109
|
-
# )
|
|
110
|
-
# self.assertGreater(len(state.py_resolve_list), 20)
|
|
111
|
-
# self.assertIn("pygame.sprite.Sprite.__init__", state.py_resolve_list)
|
|
112
|
-
# self.assertIn("pygame.mouse.get_pressed", state.py_resolve_list)
|
|
113
|
-
# self.assertIn("pygame.K_SPACE", state.py_resolve_list)
|
|
114
|
-
# self.assertIn("random.randint", state.py_resolve_list)
|
|
115
|
-
# self.assertIn("pygame.font.Font", state.py_resolve_list)
|
|
116
|
-
|
|
117
113
|
def test_double_empty_anx(self) -> None:
|
|
118
114
|
"""Test importing python."""
|
|
119
115
|
captured_output = io.StringIO()
|
|
@@ -62,3 +62,27 @@ class MypyTypeCheckPassTests(TestCase):
|
|
|
62
62
|
self.assertEqual(out.count("Type: builtins.str"), 35)
|
|
63
63
|
for i in lis:
|
|
64
64
|
self.assertNotIn(i, out)
|
|
65
|
+
|
|
66
|
+
def test_data_spatial_type_info(self) -> None:
|
|
67
|
+
"""Testing for type info for dataspatial constructs."""
|
|
68
|
+
out = AstTool().ir(
|
|
69
|
+
["ast", f"{self.fixture_abs_path('data_spatial_types.jac')}"]
|
|
70
|
+
)
|
|
71
|
+
self.assertRegex(
|
|
72
|
+
out,
|
|
73
|
+
r"129:24 - 129:28.*SpecialVarRef - _Jac.get_root\(\) \- Type\: jaclang.runtimelib.architype.Root",
|
|
74
|
+
)
|
|
75
|
+
self.assertRegex(out, r"129:11 - 129:29.*FuncCall \- Type\: builtins\.str")
|
|
76
|
+
self.assertRegex(
|
|
77
|
+
out,
|
|
78
|
+
r"129:15 - 129:23.*Name \- node_dot \- Type\: builtins.str, SymbolTable\: str",
|
|
79
|
+
)
|
|
80
|
+
self.assertRegex(
|
|
81
|
+
out,
|
|
82
|
+
r"128:5 - 128:25.*BinaryExpr \- Type\: jaclang.runtimelib.architype.WalkerArchitype",
|
|
83
|
+
)
|
|
84
|
+
self.assertRegex(
|
|
85
|
+
out,
|
|
86
|
+
r"48:11 - 48:28.*EdgeRefTrailer \- Type\: builtins.list\[data_spatial_types.A\]",
|
|
87
|
+
)
|
|
88
|
+
self.assertRegex(out, r"24:5 - 24:25.*BinaryExpr \- Type\: builtins.bool", out)
|
|
@@ -115,13 +115,14 @@ class JacTypeCheckPass(Pass):
|
|
|
115
115
|
for k, v in mypy_graph.items()
|
|
116
116
|
if (
|
|
117
117
|
k.startswith("jaclang.plugin")
|
|
118
|
+
or k.startswith("jaclang.runtimelib")
|
|
118
119
|
or not (k.startswith("jaclang.") or k.startswith("mypy."))
|
|
119
120
|
)
|
|
120
121
|
}
|
|
121
122
|
for i in mypy_graph:
|
|
122
|
-
self.ir.py_mod_dep_map[i] = mypy_graph[i].xpath
|
|
123
|
+
self.ir.py_info.py_mod_dep_map[i] = mypy_graph[i].xpath
|
|
123
124
|
for j in mypy_graph[i].dependencies:
|
|
124
|
-
self.ir.py_mod_dep_map[j] = str(
|
|
125
|
+
self.ir.py_info.py_mod_dep_map[j] = str(
|
|
125
126
|
myab.find_module_with_reason(j, manager)
|
|
126
127
|
)
|
|
127
128
|
myab.process_graph(mypy_graph, manager)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Code location info for AST nodes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PyInfo:
|
|
7
|
+
"""Python info related to python imports."""
|
|
8
|
+
|
|
9
|
+
def __init__(self) -> None:
|
|
10
|
+
"""Object Initialization."""
|
|
11
|
+
# Module dependacy map used to store all module dependacies detected
|
|
12
|
+
# by mypy. The dependacies are computed using the mypy graph in
|
|
13
|
+
# TypeCheck pass
|
|
14
|
+
self.py_mod_dep_map: dict[str, str] = {}
|
|
15
|
+
|
|
16
|
+
# Get all the modules that we really need to raise inorder to make
|
|
17
|
+
# all Jac types correct (FuseTypeInfo works). This is computed using
|
|
18
|
+
# PyCollectDepsPass.
|
|
19
|
+
self.py_raise_map: dict[str, str] = {}
|
|
20
|
+
|
|
21
|
+
# Flag for python modules raised into jac
|
|
22
|
+
self.is_raised_from_py: bool = False
|
jaclang/compiler/symtable.py
CHANGED
|
@@ -115,6 +115,7 @@ class SymbolTable:
|
|
|
115
115
|
node: ast.AstSymbolNode,
|
|
116
116
|
access_spec: Optional[ast.AstAccessNode] | SymbolAccess = None,
|
|
117
117
|
single: bool = False,
|
|
118
|
+
force_overwrite: bool = False,
|
|
118
119
|
) -> Optional[ast.AstNode]:
|
|
119
120
|
"""Set a variable in the symbol table.
|
|
120
121
|
|
|
@@ -126,7 +127,7 @@ class SymbolTable:
|
|
|
126
127
|
if single and node.sym_name in self.tab
|
|
127
128
|
else None
|
|
128
129
|
)
|
|
129
|
-
if node.sym_name not in self.tab:
|
|
130
|
+
if force_overwrite or node.sym_name not in self.tab:
|
|
130
131
|
self.tab[node.sym_name] = Symbol(
|
|
131
132
|
defn=node.name_spec,
|
|
132
133
|
access=(
|
|
@@ -163,11 +164,17 @@ class SymbolTable:
|
|
|
163
164
|
node: ast.AstSymbolNode,
|
|
164
165
|
access_spec: Optional[ast.AstAccessNode] | SymbolAccess = None,
|
|
165
166
|
single_decl: Optional[str] = None,
|
|
167
|
+
force_overwrite: bool = False,
|
|
166
168
|
) -> Optional[Symbol]:
|
|
167
169
|
"""Insert into symbol table."""
|
|
168
170
|
if node.sym and self == node.sym.parent_tab:
|
|
169
171
|
return node.sym
|
|
170
|
-
self.insert(
|
|
172
|
+
self.insert(
|
|
173
|
+
node=node,
|
|
174
|
+
single=single_decl is not None,
|
|
175
|
+
access_spec=access_spec,
|
|
176
|
+
force_overwrite=force_overwrite,
|
|
177
|
+
)
|
|
171
178
|
self.update_py_ctx_for_def(node)
|
|
172
179
|
return node.sym
|
|
173
180
|
|
|
@@ -330,7 +330,7 @@ class TestJacLangServer(TestCase):
|
|
|
330
330
|
"doubleinner",
|
|
331
331
|
"apply_red",
|
|
332
332
|
],
|
|
333
|
-
|
|
333
|
+
11,
|
|
334
334
|
),
|
|
335
335
|
(
|
|
336
336
|
lspt.Position(65, 23),
|
|
@@ -359,7 +359,7 @@ class TestJacLangServer(TestCase):
|
|
|
359
359
|
"doubleinner",
|
|
360
360
|
"apply_red",
|
|
361
361
|
],
|
|
362
|
-
|
|
362
|
+
11,
|
|
363
363
|
),
|
|
364
364
|
(
|
|
365
365
|
lspt.Position(73, 22),
|
jaclang/plugin/default.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import ast as ast3
|
|
6
6
|
import fnmatch
|
|
7
7
|
import html
|
|
8
|
+
import inspect
|
|
8
9
|
import os
|
|
9
10
|
import types
|
|
10
11
|
from collections import OrderedDict
|
|
@@ -818,12 +819,14 @@ class JacFeatureImpl(
|
|
|
818
819
|
@hookimpl
|
|
819
820
|
def create_test(test_fun: Callable) -> Callable:
|
|
820
821
|
"""Create a new test."""
|
|
822
|
+
file_path = inspect.getfile(test_fun)
|
|
823
|
+
func_name = test_fun.__name__
|
|
821
824
|
|
|
822
825
|
def test_deco() -> None:
|
|
823
826
|
test_fun(JacTestCheck())
|
|
824
827
|
|
|
825
828
|
test_deco.__name__ = test_fun.__name__
|
|
826
|
-
JacTestCheck.add_test(test_deco)
|
|
829
|
+
JacTestCheck.add_test(file_path, func_name, test_deco)
|
|
827
830
|
|
|
828
831
|
return test_deco
|
|
829
832
|
|
|
@@ -831,6 +834,7 @@ class JacFeatureImpl(
|
|
|
831
834
|
@hookimpl
|
|
832
835
|
def run_test(
|
|
833
836
|
filepath: str,
|
|
837
|
+
func_name: Optional[str],
|
|
834
838
|
filter: Optional[str],
|
|
835
839
|
xit: bool,
|
|
836
840
|
maxfail: Optional[int],
|
|
@@ -849,7 +853,9 @@ class JacFeatureImpl(
|
|
|
849
853
|
mod_name = mod_name[:-5]
|
|
850
854
|
JacTestCheck.reset()
|
|
851
855
|
Jac.jac_import(target=mod_name, base_path=base, cachable=False)
|
|
852
|
-
JacTestCheck.run_test(
|
|
856
|
+
JacTestCheck.run_test(
|
|
857
|
+
xit, maxfail, verbose, os.path.abspath(filepath), func_name
|
|
858
|
+
)
|
|
853
859
|
ret_count = JacTestCheck.failcount
|
|
854
860
|
else:
|
|
855
861
|
print("Not a .jac file.")
|
|
@@ -875,7 +881,9 @@ class JacFeatureImpl(
|
|
|
875
881
|
print(f"\n\n\t\t* Inside {root_dir}" + "/" + f"{file} *")
|
|
876
882
|
JacTestCheck.reset()
|
|
877
883
|
Jac.jac_import(target=file[:-4], base_path=root_dir)
|
|
878
|
-
JacTestCheck.run_test(
|
|
884
|
+
JacTestCheck.run_test(
|
|
885
|
+
xit, maxfail, verbose, os.path.abspath(file), func_name
|
|
886
|
+
)
|
|
879
887
|
|
|
880
888
|
if JacTestCheck.breaker and (xit or maxfail):
|
|
881
889
|
break
|
jaclang/plugin/feature.py
CHANGED
|
@@ -359,6 +359,7 @@ class JacFeature(
|
|
|
359
359
|
@staticmethod
|
|
360
360
|
def run_test(
|
|
361
361
|
filepath: str,
|
|
362
|
+
func_name: Optional[str] = None,
|
|
362
363
|
filter: Optional[str] = None,
|
|
363
364
|
xit: bool = False,
|
|
364
365
|
maxfail: Optional[int] = None,
|
|
@@ -368,6 +369,7 @@ class JacFeature(
|
|
|
368
369
|
"""Run the test suite in the specified .jac file."""
|
|
369
370
|
return plugin_manager.hook.run_test(
|
|
370
371
|
filepath=filepath,
|
|
372
|
+
func_name=func_name,
|
|
371
373
|
filter=filter,
|
|
372
374
|
xit=xit,
|
|
373
375
|
maxfail=maxfail,
|