jaclang 0.7.1__py3-none-any.whl → 0.7.5__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 +2 -2
- jaclang/compiler/absyntree.py +378 -277
- jaclang/compiler/codeloc.py +2 -2
- jaclang/compiler/constant.py +2 -0
- jaclang/compiler/jac.lark +25 -19
- jaclang/compiler/parser.py +115 -92
- jaclang/compiler/passes/main/access_modifier_pass.py +15 -9
- jaclang/compiler/passes/main/def_impl_match_pass.py +29 -11
- jaclang/compiler/passes/main/def_use_pass.py +48 -17
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +49 -30
- jaclang/compiler/passes/main/import_pass.py +12 -7
- jaclang/compiler/passes/main/pyast_gen_pass.py +110 -47
- jaclang/compiler/passes/main/pyast_load_pass.py +49 -13
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +25 -11
- jaclang/compiler/passes/main/pyout_pass.py +3 -1
- jaclang/compiler/passes/main/registry_pass.py +6 -6
- jaclang/compiler/passes/main/sym_tab_build_pass.py +30 -72
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +21 -4
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +5 -10
- jaclang/compiler/passes/main/tests/test_import_pass.py +8 -0
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/main/type_check_pass.py +2 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +44 -11
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
- jaclang/compiler/passes/transform.py +2 -4
- jaclang/{core/registry.py → compiler/semtable.py} +1 -3
- jaclang/compiler/symtable.py +39 -31
- jaclang/compiler/tests/test_parser.py +2 -2
- jaclang/core/aott.py +112 -16
- jaclang/core/{construct.py → architype.py} +44 -93
- jaclang/core/constructs.py +44 -0
- jaclang/core/context.py +157 -0
- jaclang/core/importer.py +18 -9
- jaclang/core/llms/anthropic.py +31 -2
- jaclang/core/llms/base.py +3 -3
- jaclang/core/llms/groq.py +4 -1
- jaclang/core/llms/huggingface.py +4 -1
- jaclang/core/llms/ollama.py +4 -1
- jaclang/core/llms/openai.py +6 -2
- jaclang/core/llms/togetherai.py +4 -1
- jaclang/core/memory.py +53 -2
- jaclang/core/test.py +90 -0
- jaclang/core/utils.py +2 -2
- jaclang/langserve/engine.py +119 -122
- jaclang/langserve/server.py +27 -5
- jaclang/langserve/tests/fixtures/circle.jac +16 -12
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.impl.jac +8 -4
- jaclang/langserve/tests/fixtures/circle_pure.jac +2 -2
- jaclang/langserve/tests/test_server.py +114 -0
- jaclang/langserve/utils.py +104 -10
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +46 -90
- jaclang/plugin/feature.py +32 -16
- jaclang/plugin/spec.py +17 -19
- jaclang/plugin/tests/test_features.py +0 -33
- jaclang/settings.py +4 -0
- jaclang/tests/fixtures/abc.jac +16 -12
- jaclang/tests/fixtures/byllmissue.jac +12 -0
- jaclang/tests/fixtures/edgetypetest.jac +16 -0
- jaclang/tests/fixtures/hash_init_check.jac +17 -0
- jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
- jaclang/tests/fixtures/impl_match_confused.jac +5 -0
- jaclang/tests/fixtures/math_question.jpg +0 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
- jaclang/tests/fixtures/nosigself.jac +19 -0
- jaclang/tests/fixtures/run_test.jac +17 -5
- jaclang/tests/fixtures/walker_override.jac +21 -0
- jaclang/tests/fixtures/with_llm_vision.jac +25 -0
- jaclang/tests/test_bugs.py +19 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +116 -11
- jaclang/tests/test_reference.py +1 -1
- jaclang/utils/lang_tools.py +5 -4
- jaclang/utils/test.py +2 -1
- jaclang/utils/treeprinter.py +35 -4
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/METADATA +3 -2
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/RECORD +84 -71
- jaclang/core/shelve_storage.py +0 -55
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/WHEEL +0 -0
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
"""Jac to python ast link pass.
|
|
1
|
+
"""Jac to python ast link pass.
|
|
2
|
+
|
|
3
|
+
This pass is needed so cases where there are multiple Jac nodes relevant to a
|
|
4
|
+
single python node can be linked. For example FuncDef doesn't have a Name node
|
|
5
|
+
however Ability does.
|
|
6
|
+
"""
|
|
2
7
|
|
|
3
8
|
import ast as ast3
|
|
4
9
|
|
|
@@ -52,10 +57,13 @@ class PyJacAstLinkPass(Pass):
|
|
|
52
57
|
decorators: Optional[SubNodeList[ExprType]],
|
|
53
58
|
"""
|
|
54
59
|
for i in node.target.archs:
|
|
55
|
-
if i.
|
|
56
|
-
self.link_jac_py_nodes(
|
|
60
|
+
if i.name_spec.name_of.sym:
|
|
61
|
+
self.link_jac_py_nodes(
|
|
62
|
+
jac_node=i, py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast
|
|
63
|
+
)
|
|
57
64
|
self.link_jac_py_nodes(
|
|
58
|
-
jac_node=i.
|
|
65
|
+
jac_node=i.name_spec,
|
|
66
|
+
py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast,
|
|
59
67
|
)
|
|
60
68
|
|
|
61
69
|
def exit_enum(self, node: ast.Enum) -> None:
|
|
@@ -80,10 +88,13 @@ class PyJacAstLinkPass(Pass):
|
|
|
80
88
|
decorators: Optional[SubNodeList[ExprType]],
|
|
81
89
|
"""
|
|
82
90
|
for i in node.target.archs:
|
|
83
|
-
if i.
|
|
84
|
-
self.link_jac_py_nodes(jac_node=i, py_nodes=i.sym_link.decl.gen.py_ast)
|
|
91
|
+
if i.name_spec.name_of.sym:
|
|
85
92
|
self.link_jac_py_nodes(
|
|
86
|
-
jac_node=i
|
|
93
|
+
jac_node=i, py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast
|
|
94
|
+
)
|
|
95
|
+
self.link_jac_py_nodes(
|
|
96
|
+
jac_node=i.name_spec,
|
|
97
|
+
py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast,
|
|
87
98
|
)
|
|
88
99
|
|
|
89
100
|
def exit_ability(self, node: ast.Ability) -> None:
|
|
@@ -114,10 +125,13 @@ class PyJacAstLinkPass(Pass):
|
|
|
114
125
|
decorators: Optional[SubNodeList[ExprType]],
|
|
115
126
|
"""
|
|
116
127
|
for i in node.target.archs:
|
|
117
|
-
if i.
|
|
118
|
-
self.link_jac_py_nodes(
|
|
128
|
+
if i.name_spec.name_of.sym:
|
|
129
|
+
self.link_jac_py_nodes(
|
|
130
|
+
jac_node=i, py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast
|
|
131
|
+
)
|
|
119
132
|
self.link_jac_py_nodes(
|
|
120
|
-
jac_node=i.
|
|
133
|
+
jac_node=i.name_spec,
|
|
134
|
+
py_nodes=i.name_spec.name_of.sym.decl.gen.py_ast,
|
|
121
135
|
)
|
|
122
136
|
|
|
123
137
|
if isinstance(node.parent, ast.Ability) and node.parent.signature:
|
|
@@ -214,5 +228,5 @@ class PyJacAstLinkPass(Pass):
|
|
|
214
228
|
"""
|
|
215
229
|
if node.is_attr and isinstance(node.right, ast.AstSymbolNode):
|
|
216
230
|
self.link_jac_py_nodes(
|
|
217
|
-
jac_node=node.right.
|
|
231
|
+
jac_node=node.right.name_spec, py_nodes=node.gen.py_ast
|
|
218
232
|
)
|
|
@@ -35,7 +35,9 @@ class PyOutPass(Pass):
|
|
|
35
35
|
f"Unable to find module {node.loc.mod_path} or no code present.", node
|
|
36
36
|
)
|
|
37
37
|
return
|
|
38
|
-
mods = [node] +
|
|
38
|
+
mods = [node] + [
|
|
39
|
+
i for i in self.get_all_sub_nodes(node, ast.Module) if not i.stub_only
|
|
40
|
+
]
|
|
39
41
|
for mod in mods:
|
|
40
42
|
mod_path, out_path_py, out_path_pyc = self.get_output_targets(mod)
|
|
41
43
|
if os.path.exists(out_path_pyc) and os.path.getmtime(
|
|
@@ -12,7 +12,7 @@ import pickle
|
|
|
12
12
|
import jaclang.compiler.absyntree as ast
|
|
13
13
|
from jaclang.compiler.constant import Constants as Con
|
|
14
14
|
from jaclang.compiler.passes import Pass
|
|
15
|
-
from jaclang.
|
|
15
|
+
from jaclang.compiler.semtable import SemInfo, SemRegistry
|
|
16
16
|
from jaclang.core.utils import get_sem_scope
|
|
17
17
|
|
|
18
18
|
|
|
@@ -48,7 +48,7 @@ class RegistryPass(Pass):
|
|
|
48
48
|
seminfo = SemInfo(
|
|
49
49
|
node.name.value,
|
|
50
50
|
node.arch_type.value,
|
|
51
|
-
node.semstr.lit_value if node.semstr else
|
|
51
|
+
node.semstr.lit_value if node.semstr else "",
|
|
52
52
|
)
|
|
53
53
|
if (
|
|
54
54
|
len(self.modules_visited)
|
|
@@ -61,7 +61,7 @@ class RegistryPass(Pass):
|
|
|
61
61
|
"""Save enum information."""
|
|
62
62
|
scope = get_sem_scope(node)
|
|
63
63
|
seminfo = SemInfo(
|
|
64
|
-
node.name.value, "Enum", node.semstr.lit_value if node.semstr else
|
|
64
|
+
node.name.value, "Enum", node.semstr.lit_value if node.semstr else ""
|
|
65
65
|
)
|
|
66
66
|
if (
|
|
67
67
|
len(self.modules_visited)
|
|
@@ -79,7 +79,7 @@ class RegistryPass(Pass):
|
|
|
79
79
|
seminfo = SemInfo(
|
|
80
80
|
node.name.value,
|
|
81
81
|
extracted_type,
|
|
82
|
-
node.semstr.lit_value if node.semstr else
|
|
82
|
+
node.semstr.lit_value if node.semstr else "",
|
|
83
83
|
)
|
|
84
84
|
if len(self.modules_visited) and self.modules_visited[-1].registry:
|
|
85
85
|
self.modules_visited[-1].registry.add(scope, seminfo)
|
|
@@ -100,7 +100,7 @@ class RegistryPass(Pass):
|
|
|
100
100
|
else ""
|
|
101
101
|
),
|
|
102
102
|
extracted_type,
|
|
103
|
-
node.semstr.lit_value if node.semstr else
|
|
103
|
+
node.semstr.lit_value if node.semstr else "",
|
|
104
104
|
)
|
|
105
105
|
if len(self.modules_visited) and self.modules_visited[-1].registry:
|
|
106
106
|
self.modules_visited[-1].registry.add(scope, seminfo)
|
|
@@ -113,7 +113,7 @@ class RegistryPass(Pass):
|
|
|
113
113
|
and node.parent.parent.__class__.__name__ == "Enum"
|
|
114
114
|
):
|
|
115
115
|
scope = get_sem_scope(node)
|
|
116
|
-
seminfo = SemInfo(node.value, None,
|
|
116
|
+
seminfo = SemInfo(node.value, None, "")
|
|
117
117
|
if len(self.modules_visited) and self.modules_visited[-1].registry:
|
|
118
118
|
self.modules_visited[-1].registry.add(scope, seminfo)
|
|
119
119
|
|
|
@@ -17,19 +17,6 @@ from jaclang.compiler.symtable import Symbol, SymbolAccess, SymbolTable
|
|
|
17
17
|
class SymTabPass(Pass):
|
|
18
18
|
"""Jac Ast build pass."""
|
|
19
19
|
|
|
20
|
-
def before_pass(self) -> None:
|
|
21
|
-
"""Before pass."""
|
|
22
|
-
self.unlinked: set[ast.AstSymbolNode] = set() # Failed use lookups
|
|
23
|
-
self.linked: set[ast.AstSymbolNode] = set() # Successful use lookups
|
|
24
|
-
|
|
25
|
-
def seen(self, node: ast.AstSymbolNode) -> bool:
|
|
26
|
-
"""Check if seen."""
|
|
27
|
-
result = node in self.linked or node in self.unlinked
|
|
28
|
-
if node.sym_link and not result:
|
|
29
|
-
self.linked.add(node)
|
|
30
|
-
return True
|
|
31
|
-
return result
|
|
32
|
-
|
|
33
20
|
def inherit_sym_tab(self, scope: SymbolTable, sym_tab: SymbolTable) -> None:
|
|
34
21
|
"""Inherit symbol table."""
|
|
35
22
|
for i in sym_tab.tab.values():
|
|
@@ -44,21 +31,20 @@ class SymTabPass(Pass):
|
|
|
44
31
|
) -> Optional[Symbol]:
|
|
45
32
|
"""Insert into symbol table."""
|
|
46
33
|
table = table_override if table_override else node.sym_tab
|
|
47
|
-
if
|
|
48
|
-
return node.
|
|
34
|
+
if node.sym and table == node.sym.parent_tab:
|
|
35
|
+
return node.sym
|
|
49
36
|
if table:
|
|
50
37
|
table.insert(
|
|
51
38
|
node=node, single=single_decl is not None, access_spec=access_spec
|
|
52
39
|
)
|
|
53
40
|
self.update_py_ctx_for_def(node)
|
|
54
|
-
|
|
55
|
-
return node.sym_link
|
|
41
|
+
return node.sym
|
|
56
42
|
|
|
57
43
|
def update_py_ctx_for_def(self, node: ast.AstSymbolNode) -> None:
|
|
58
44
|
"""Update python context for definition."""
|
|
59
|
-
node.py_ctx_func = ast3.Store
|
|
60
|
-
if isinstance(node.
|
|
61
|
-
node.
|
|
45
|
+
node.name_spec.py_ctx_func = ast3.Store
|
|
46
|
+
if isinstance(node.name_spec, ast.AstSymbolNode):
|
|
47
|
+
node.name_spec.py_ctx_func = ast3.Store
|
|
62
48
|
if isinstance(node, (ast.TupleVal, ast.ListVal)) and node.values:
|
|
63
49
|
# Handling of UnaryExpr case for item is only necessary for
|
|
64
50
|
# the generation of Starred nodes in the AST for examples
|
|
@@ -66,11 +52,11 @@ class SymTabPass(Pass):
|
|
|
66
52
|
def fix(item: ast.TupleVal | ast.ListVal | ast.UnaryExpr) -> None:
|
|
67
53
|
if isinstance(item, ast.UnaryExpr):
|
|
68
54
|
if isinstance(item.operand, ast.AstSymbolNode):
|
|
69
|
-
item.operand.py_ctx_func = ast3.Store
|
|
55
|
+
item.operand.name_spec.py_ctx_func = ast3.Store
|
|
70
56
|
elif isinstance(item, (ast.TupleVal, ast.ListVal)):
|
|
71
57
|
for i in item.values.items if item.values else []:
|
|
72
58
|
if isinstance(i, ast.AstSymbolNode):
|
|
73
|
-
i.py_ctx_func = ast3.Store
|
|
59
|
+
i.name_spec.py_ctx_func = ast3.Store
|
|
74
60
|
elif isinstance(i, ast.AtomTrailer):
|
|
75
61
|
self.chain_def_insert(self.unwind_atom_trailer(i))
|
|
76
62
|
if isinstance(i, (ast.TupleVal, ast.ListVal, ast.UnaryExpr)):
|
|
@@ -84,28 +70,23 @@ class SymTabPass(Pass):
|
|
|
84
70
|
sym_table: Optional[SymbolTable] = None,
|
|
85
71
|
) -> Optional[Symbol]:
|
|
86
72
|
"""Link to symbol."""
|
|
87
|
-
if
|
|
88
|
-
return node.
|
|
73
|
+
if node.sym:
|
|
74
|
+
return node.sym
|
|
89
75
|
if not sym_table:
|
|
90
76
|
sym_table = node.sym_tab
|
|
91
77
|
if sym_table:
|
|
92
|
-
node.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# If successful lookup mark linked, add to table uses, and link others
|
|
96
|
-
if node.sym_link:
|
|
97
|
-
sym_table.uses.append(node)
|
|
98
|
-
self.handle_hit_outcome(node)
|
|
99
|
-
return node.sym_link
|
|
78
|
+
lookup = sym_table.lookup(name=node.sym_name, deep=True)
|
|
79
|
+
lookup.add_use(node.name_spec) if lookup else None
|
|
80
|
+
return node.sym
|
|
100
81
|
|
|
101
82
|
def chain_def_insert(self, node_list: Sequence[ast.AstSymbolNode]) -> None:
|
|
102
83
|
"""Link chain of containing names to symbol."""
|
|
103
84
|
if not node_list:
|
|
104
85
|
return
|
|
105
86
|
cur_sym_tab = node_list[0].sym_tab
|
|
106
|
-
node_list[-1].py_ctx_func = ast3.Store
|
|
107
|
-
if isinstance(node_list[-1].
|
|
108
|
-
node_list[-1].
|
|
87
|
+
node_list[-1].name_spec.py_ctx_func = ast3.Store
|
|
88
|
+
if isinstance(node_list[-1].name_spec, ast.AstSymbolNode):
|
|
89
|
+
node_list[-1].name_spec.py_ctx_func = ast3.Store
|
|
109
90
|
|
|
110
91
|
node_list = node_list[:-1] # Just performs lookup mappings of pre assign chain
|
|
111
92
|
for i in node_list:
|
|
@@ -165,25 +146,6 @@ class SymTabPass(Pass):
|
|
|
165
146
|
trag_list.insert(0, left)
|
|
166
147
|
return trag_list
|
|
167
148
|
|
|
168
|
-
def handle_hit_outcome(
|
|
169
|
-
self,
|
|
170
|
-
node: ast.AstSymbolNode,
|
|
171
|
-
) -> None:
|
|
172
|
-
"""Handle outcome of lookup or insert."""
|
|
173
|
-
# If successful lookup mark linked, add to table uses, and link others
|
|
174
|
-
if node.sym_link:
|
|
175
|
-
self.linked.add(node)
|
|
176
|
-
if isinstance(node.sym_name_node, ast.AstSymbolNode):
|
|
177
|
-
node.sym_name_node.sym_link = node.sym_link
|
|
178
|
-
if not node.sym_link:
|
|
179
|
-
# Mark nodes that were not successfully linked
|
|
180
|
-
self.unlinked.add(node)
|
|
181
|
-
if (
|
|
182
|
-
isinstance(node.sym_name_node, ast.AstSymbolNode)
|
|
183
|
-
and not node.sym_name_node.sym_link
|
|
184
|
-
):
|
|
185
|
-
self.unlinked.add(node.sym_name_node)
|
|
186
|
-
|
|
187
149
|
def already_declared_err(
|
|
188
150
|
self,
|
|
189
151
|
name: str,
|
|
@@ -238,7 +200,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
238
200
|
mod_path: str,
|
|
239
201
|
is_imported: bool,
|
|
240
202
|
"""
|
|
241
|
-
self.push_scope(node.name, node, fresh=
|
|
203
|
+
self.push_scope(node.name, node, fresh=(node == self.ir))
|
|
242
204
|
self.sync_node_to_scope(node)
|
|
243
205
|
for obj in dir(builtins):
|
|
244
206
|
builtin = ast.Name(
|
|
@@ -246,6 +208,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
246
208
|
name=Tok.NAME,
|
|
247
209
|
value=str(obj),
|
|
248
210
|
line=0,
|
|
211
|
+
end_line=0,
|
|
249
212
|
col_start=0,
|
|
250
213
|
col_end=0,
|
|
251
214
|
pos_start=0,
|
|
@@ -253,6 +216,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
253
216
|
)
|
|
254
217
|
self.sync_node_to_scope(builtin)
|
|
255
218
|
self.def_insert(builtin)
|
|
219
|
+
# self.def_insert(ast.Name.gen_stub_from_node(node.name, "root"))
|
|
256
220
|
|
|
257
221
|
def exit_module(self, node: ast.Module) -> None:
|
|
258
222
|
"""Sub objects.
|
|
@@ -263,23 +227,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
263
227
|
mod_path: str,
|
|
264
228
|
is_imported: bool,
|
|
265
229
|
"""
|
|
266
|
-
|
|
267
|
-
# If not the main module add all the other modules symbol table
|
|
268
|
-
# as a child to the current symbol table
|
|
269
|
-
if node != self.ir:
|
|
270
|
-
self.cur_scope().kid.append(s)
|
|
271
|
-
s.parent = self.cur_scope()
|
|
272
|
-
|
|
273
|
-
if (
|
|
274
|
-
isinstance(node.parent, ast.Module)
|
|
275
|
-
and node
|
|
276
|
-
in [
|
|
277
|
-
node.parent.impl_mod,
|
|
278
|
-
node.parent.test_mod,
|
|
279
|
-
]
|
|
280
|
-
and node.sym_tab
|
|
281
|
-
):
|
|
282
|
-
self.inherit_sym_tab(scope=self.cur_scope(), sym_tab=node.sym_tab)
|
|
230
|
+
self.pop_scope()
|
|
283
231
|
|
|
284
232
|
def enter_global_vars(self, node: ast.GlobalVars) -> None:
|
|
285
233
|
"""Sub objects.
|
|
@@ -510,6 +458,9 @@ class SymTabBuildPass(SymTabPass):
|
|
|
510
458
|
self.def_insert(node, access_spec=node, single_decl="ability")
|
|
511
459
|
self.push_scope(node.sym_name, node)
|
|
512
460
|
self.sync_node_to_scope(node)
|
|
461
|
+
if node.is_method:
|
|
462
|
+
self.def_insert(ast.Name.gen_stub_from_node(node, "self"))
|
|
463
|
+
self.def_insert(ast.Name.gen_stub_from_node(node, "super"))
|
|
513
464
|
|
|
514
465
|
def exit_ability(self, node: ast.Ability) -> None:
|
|
515
466
|
"""Sub objects.
|
|
@@ -896,6 +847,13 @@ class SymTabBuildPass(SymTabPass):
|
|
|
896
847
|
"""
|
|
897
848
|
self.sync_node_to_scope(node)
|
|
898
849
|
|
|
850
|
+
def enter_check_stmt(self, node: ast.CheckStmt) -> None:
|
|
851
|
+
"""Sub objects.
|
|
852
|
+
|
|
853
|
+
target: Expr,
|
|
854
|
+
"""
|
|
855
|
+
self.sync_node_to_scope(node)
|
|
856
|
+
|
|
899
857
|
def enter_ctrl_stmt(self, node: ast.CtrlStmt) -> None:
|
|
900
858
|
"""Sub objects.
|
|
901
859
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Test pass module."""
|
|
2
2
|
|
|
3
|
+
import jaclang.compiler.absyntree as ast
|
|
3
4
|
from jaclang.compiler.compile import jac_file_to_pass
|
|
4
5
|
from jaclang.compiler.passes.main import DeclImplMatchPass
|
|
5
6
|
from jaclang.utils.test import TestCase
|
|
@@ -17,15 +18,31 @@ class DeclImplMatchPassTests(TestCase):
|
|
|
17
18
|
state = jac_file_to_pass(self.fixture_abs_path("base.jac"), DeclImplMatchPass)
|
|
18
19
|
self.assertFalse(state.errors_had)
|
|
19
20
|
self.assertIn("(o)Test.(c)say_hi", state.ir.sym_tab.tab)
|
|
20
|
-
self.assertIsNotNone(
|
|
21
|
+
self.assertIsNotNone(
|
|
22
|
+
state.ir.sym_tab.tab["(o)Test.(c)say_hi"].decl.name_of.body
|
|
23
|
+
)
|
|
21
24
|
self.assertIn("(o)Test.(c)__init__", state.ir.sym_tab.tab)
|
|
22
|
-
self.assertIsNotNone(
|
|
25
|
+
self.assertIsNotNone(
|
|
26
|
+
state.ir.sym_tab.tab["(o)Test.(c)__init__"].decl.name_of.body
|
|
27
|
+
)
|
|
23
28
|
|
|
24
29
|
def test_ability_connected_to_decl_post(self) -> None:
|
|
25
30
|
"""Basic test for pass."""
|
|
26
31
|
state = jac_file_to_pass(self.fixture_abs_path("base2.jac"), DeclImplMatchPass)
|
|
27
32
|
self.assertFalse(state.errors_had)
|
|
28
33
|
self.assertIn("(o)Test.(c)say_hi", state.ir.sym_tab.tab)
|
|
29
|
-
self.assertIsNotNone(
|
|
34
|
+
self.assertIsNotNone(
|
|
35
|
+
state.ir.sym_tab.tab["(o)Test.(c)say_hi"].decl.name_of.body
|
|
36
|
+
)
|
|
30
37
|
self.assertIn("(o)Test.(c)__init__", state.ir.sym_tab.tab)
|
|
31
|
-
self.assertIsNotNone(
|
|
38
|
+
self.assertIsNotNone(
|
|
39
|
+
state.ir.sym_tab.tab["(o)Test.(c)__init__"].decl.name_of.body
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def test_arch_ref_has_sym(self) -> None:
|
|
43
|
+
"""Basic test for pass."""
|
|
44
|
+
state = jac_file_to_pass(
|
|
45
|
+
self.fixture_abs_path("defs_and_uses.jac"), DeclImplMatchPass
|
|
46
|
+
)
|
|
47
|
+
for i in state.ir.get_all_sub_nodes(ast.ArchRef):
|
|
48
|
+
self.assertIsNotNone(i.sym)
|
|
@@ -18,13 +18,8 @@ class DefUsePassTests(TestCase):
|
|
|
18
18
|
file_path=self.fixture_abs_path("defs_and_uses.jac"),
|
|
19
19
|
target=DefUsePass,
|
|
20
20
|
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# f", {i.sym_link.decl.loc if i.sym_link else None}"
|
|
27
|
-
# )
|
|
28
|
-
self.assertGreater(len(state.linked), 5)
|
|
29
|
-
self.assertLess(len(state.warnings_had), 50)
|
|
30
|
-
self.assertEqual(len(state.errors_had), 0)
|
|
21
|
+
uses = [i.uses for i in state.ir.sym_tab.kid[0].tab.values()]
|
|
22
|
+
self.assertEqual(len(uses[1]), 1)
|
|
23
|
+
self.assertEqual(len(uses[2]), 1)
|
|
24
|
+
self.assertIn("output", [uses[1][0].sym_name, uses[2][0].sym_name])
|
|
25
|
+
self.assertIn("message", [uses[1][0].sym_name, uses[2][0].sym_name])
|
|
@@ -41,3 +41,11 @@ class ImportPassPassTests(TestCase):
|
|
|
41
41
|
self.assertIn("autoimpl", mod_names)
|
|
42
42
|
self.assertIn("autoimpl.impl", mod_names)
|
|
43
43
|
self.assertIn("autoimpl.something.else.impl", mod_names)
|
|
44
|
+
|
|
45
|
+
def test_annexalbe_by_discovery(self) -> None:
|
|
46
|
+
"""Basic test for pass."""
|
|
47
|
+
state = jac_file_to_pass(
|
|
48
|
+
self.fixture_abs_path("incautoimpl.jac"), JacImportPass
|
|
49
|
+
)
|
|
50
|
+
for i in state.ir.get_all_sub_nodes(ast.Module):
|
|
51
|
+
self.assertEqual(i.annexable_by, self.fixture_abs_path("autoimpl.jac"))
|
|
@@ -59,6 +59,6 @@ class MypyTypeCheckPassTests(TestCase):
|
|
|
59
59
|
self.assertIn("HasVar - species - Type: builtins.str", out)
|
|
60
60
|
self.assertIn("myDog - Type: type_info.Dog", out)
|
|
61
61
|
self.assertIn("Body - Type: type_info.Dog.Body", out)
|
|
62
|
-
self.assertEqual(out.count("Type: builtins.str"),
|
|
62
|
+
self.assertEqual(out.count("Type: builtins.str"), 28)
|
|
63
63
|
for i in lis:
|
|
64
64
|
self.assertNotIn(i, out)
|
|
@@ -8,9 +8,9 @@ import os
|
|
|
8
8
|
import pathlib
|
|
9
9
|
import sys
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
import jaclang.compiler.absyntree as ast
|
|
13
12
|
import jaclang.compiler.passes.utils.mypy_ast_build as myab
|
|
13
|
+
from jaclang.compiler.constant import Constants as Con
|
|
14
14
|
from jaclang.compiler.passes import Pass
|
|
15
15
|
|
|
16
16
|
|
|
@@ -48,6 +48,7 @@ class JacTypeCheckPass(Pass):
|
|
|
48
48
|
"""Call mypy APIs to implement type checking in Jac."""
|
|
49
49
|
# Creating mypy api objects
|
|
50
50
|
options = myab.myb.Options()
|
|
51
|
+
options.cache_dir = Con.JAC_MYPY_CACHE
|
|
51
52
|
errors = myab.Errors(self, options)
|
|
52
53
|
fs_cache = myab.FileSystemCache()
|
|
53
54
|
search_paths = myab.compute_search_paths([], options, str(self.__path))
|
|
@@ -421,7 +421,10 @@ class JacFormatPass(Pass):
|
|
|
421
421
|
self.emit_ln(node, "")
|
|
422
422
|
self.emit_ln(node, i.gen.jac)
|
|
423
423
|
if isinstance(i, ast.Token) and i.name == Tok.KW_BY:
|
|
424
|
-
|
|
424
|
+
if not node.params:
|
|
425
|
+
self.emit(node, f"{i.gen.jac} ")
|
|
426
|
+
else:
|
|
427
|
+
self.emit(node, f" {i.gen.jac} ")
|
|
425
428
|
else:
|
|
426
429
|
if (
|
|
427
430
|
line_break_needed
|
|
@@ -481,7 +484,7 @@ class JacFormatPass(Pass):
|
|
|
481
484
|
|
|
482
485
|
var: Token,
|
|
483
486
|
"""
|
|
484
|
-
self.emit(node, node.
|
|
487
|
+
self.emit(node, node.orig.value)
|
|
485
488
|
|
|
486
489
|
def exit_ability_def(self, node: ast.AbilityDef) -> None:
|
|
487
490
|
"""Sub objects.
|
|
@@ -1868,6 +1871,32 @@ class JacFormatPass(Pass):
|
|
|
1868
1871
|
if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):
|
|
1869
1872
|
self.emit_ln(node, "")
|
|
1870
1873
|
|
|
1874
|
+
def exit_check_stmt(self, node: ast.CheckStmt) -> None:
|
|
1875
|
+
"""Sub objects.
|
|
1876
|
+
|
|
1877
|
+
target: ExprType,
|
|
1878
|
+
"""
|
|
1879
|
+
start = True
|
|
1880
|
+
for i in node.kid:
|
|
1881
|
+
if isinstance(i, ast.CommentToken):
|
|
1882
|
+
if i.is_inline:
|
|
1883
|
+
self.emit(node, f" {i.gen.jac}")
|
|
1884
|
+
else:
|
|
1885
|
+
if not node.gen.jac.endswith("\n"):
|
|
1886
|
+
self.emit_ln(node, "")
|
|
1887
|
+
self.emit_ln(node, "")
|
|
1888
|
+
self.emit(node, i.gen.jac)
|
|
1889
|
+
elif isinstance(i, ast.Semi):
|
|
1890
|
+
self.emit(node, i.gen.jac)
|
|
1891
|
+
else:
|
|
1892
|
+
if start:
|
|
1893
|
+
self.emit(node, i.gen.jac)
|
|
1894
|
+
start = False
|
|
1895
|
+
else:
|
|
1896
|
+
self.emit(node, f" {i.gen.jac}")
|
|
1897
|
+
if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):
|
|
1898
|
+
self.emit_ln(node, "")
|
|
1899
|
+
|
|
1871
1900
|
def exit_ctrl_stmt(self, node: ast.CtrlStmt) -> None:
|
|
1872
1901
|
"""Sub objects.
|
|
1873
1902
|
|
|
@@ -1999,7 +2028,6 @@ class JacFormatPass(Pass):
|
|
|
1999
2028
|
doc: Optional[Token],
|
|
2000
2029
|
body: CodeBlock,
|
|
2001
2030
|
"""
|
|
2002
|
-
start = True
|
|
2003
2031
|
for i in node.kid:
|
|
2004
2032
|
if isinstance(i, ast.CommentToken):
|
|
2005
2033
|
if i.is_inline:
|
|
@@ -2010,14 +2038,10 @@ class JacFormatPass(Pass):
|
|
|
2010
2038
|
elif isinstance(i, ast.Semi):
|
|
2011
2039
|
self.emit(node, i.gen.jac)
|
|
2012
2040
|
elif isinstance(i, ast.Name):
|
|
2013
|
-
if not i.value.startswith("
|
|
2014
|
-
self.emit(node, f" {i.value}
|
|
2041
|
+
if not i.value.startswith("_jac_gen_"):
|
|
2042
|
+
self.emit(node, f" {i.value}")
|
|
2015
2043
|
else:
|
|
2016
|
-
|
|
2017
|
-
self.emit(node, i.gen.jac)
|
|
2018
|
-
start = False
|
|
2019
|
-
else:
|
|
2020
|
-
self.emit(node, f" {i.gen.jac}")
|
|
2044
|
+
self.emit(node, i.gen.jac)
|
|
2021
2045
|
if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):
|
|
2022
2046
|
self.emit_ln(node, "")
|
|
2023
2047
|
|
|
@@ -2402,7 +2426,16 @@ class JacFormatPass(Pass):
|
|
|
2402
2426
|
and isinstance(node.parent.parent, ast.FString)
|
|
2403
2427
|
):
|
|
2404
2428
|
self.emit(node, node.value)
|
|
2405
|
-
|
|
2429
|
+
if "\n" in node.value:
|
|
2430
|
+
string_type = node.value[0:3]
|
|
2431
|
+
pure_string = node.value[3:-3]
|
|
2432
|
+
lines = pure_string.split("\n")
|
|
2433
|
+
self.emit(node, string_type)
|
|
2434
|
+
for line in lines[:-1]:
|
|
2435
|
+
self.emit_ln(node, line)
|
|
2436
|
+
self.emit_ln(node, f"{lines[-1]}{string_type}")
|
|
2437
|
+
else:
|
|
2438
|
+
self.emit(node, node.value)
|
|
2406
2439
|
|
|
2407
2440
|
def enter_bool(self, node: ast.Bool) -> None:
|
|
2408
2441
|
"""Sub objects.
|
|
@@ -478,3 +478,19 @@ obj JacPlugin {
|
|
|
478
478
|
(walker_obj: Any, expr: Any) -> bool {
|
|
479
479
|
return walker_obj._jac_.visit_node(expr);
|
|
480
480
|
}
|
|
481
|
+
|
|
482
|
+
glob expected_area = 78.53981633974483;
|
|
483
|
+
|
|
484
|
+
test a1 {
|
|
485
|
+
check assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
test a2 {
|
|
489
|
+
c = Circle(RAD);
|
|
490
|
+
check assertAlmostEqual(c.area(), expected_area);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
test a3 {
|
|
494
|
+
c = Circle(RAD);
|
|
495
|
+
check assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
496
|
+
}
|
|
@@ -478,3 +478,19 @@ obj JacPlugin {
|
|
|
478
478
|
(walker_obj: Any, expr: Any) -> bool {
|
|
479
479
|
return walker_obj._jac_.visit_node(expr);
|
|
480
480
|
}
|
|
481
|
+
|
|
482
|
+
glob expected_area = 78.53981633974483;
|
|
483
|
+
|
|
484
|
+
test a1 {
|
|
485
|
+
check assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
test a2 {
|
|
489
|
+
c = Circle(RAD);
|
|
490
|
+
check assertAlmostEqual(c.area(), expected_area);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
test a3 {
|
|
494
|
+
c = Circle(RAD);
|
|
495
|
+
check assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
496
|
+
}
|
|
@@ -44,8 +44,8 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
44
44
|
|
|
45
45
|
if diff:
|
|
46
46
|
print(f"Differences found in comparison:\n{diff}")
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
raise AssertionError("Files differ after formatting.")
|
|
48
|
+
|
|
49
49
|
except FileNotFoundError:
|
|
50
50
|
print(f"File not found: {original_file} or {formatted_file}")
|
|
51
51
|
raise
|
|
@@ -76,6 +76,9 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
76
76
|
self.compare_files(
|
|
77
77
|
os.path.join(self.fixture_abs_path(""), "corelib_fmt.jac"),
|
|
78
78
|
)
|
|
79
|
+
self.compare_files(
|
|
80
|
+
os.path.join(self.fixture_abs_path(""), "doc_string.jac"),
|
|
81
|
+
)
|
|
79
82
|
|
|
80
83
|
def test_compare_myca_fixtures(self) -> None:
|
|
81
84
|
"""Tests if files in the myca fixtures directory do not change after being formatted."""
|
|
@@ -135,14 +138,13 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
135
138
|
diff = "\n".join(unified_diff(before.splitlines(), after.splitlines()))
|
|
136
139
|
self.assertFalse(diff, "AST structures differ after formatting.")
|
|
137
140
|
|
|
138
|
-
except Exception:
|
|
141
|
+
except Exception as e:
|
|
139
142
|
print(add_line_numbers(code_gen_pure.ir.source.code))
|
|
140
143
|
print("\n+++++++++++++++++++++++++++++++++++++++\n")
|
|
141
144
|
print(add_line_numbers(code_gen_format.ir.gen.jac))
|
|
142
145
|
print("\n+++++++++++++++++++++++++++++++++++++++\n")
|
|
143
146
|
print("\n".join(unified_diff(before.splitlines(), after.splitlines())))
|
|
144
|
-
|
|
145
|
-
# raise e
|
|
147
|
+
raise e
|
|
146
148
|
|
|
147
149
|
|
|
148
150
|
JacFormatPassTests.self_attach_micro_tests()
|
|
@@ -30,7 +30,7 @@ class JacUnparseTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
30
30
|
self.assertEqual(x, y)
|
|
31
31
|
except Exception as e:
|
|
32
32
|
print("\n".join(unified_diff(x.splitlines(), y.splitlines())))
|
|
33
|
-
|
|
33
|
+
raise e
|
|
34
34
|
|
|
35
35
|
def micro_suite_test(self, filename: str) -> None:
|
|
36
36
|
"""Parse micro jac file."""
|
|
@@ -75,7 +75,6 @@ class JacUnparseTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
75
75
|
|
|
76
76
|
except Exception as e:
|
|
77
77
|
raise e
|
|
78
|
-
# self.skipTest(f"Test failed, but skipping instead of failing: {e}")
|
|
79
78
|
|
|
80
79
|
|
|
81
80
|
JacUnparseTests.self_attach_micro_tests()
|