jaclang 0.5.18__py3-none-any.whl → 0.6.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/cli/cli.py +94 -5
- jaclang/cli/cmdreg.py +18 -6
- jaclang/compiler/__init__.py +12 -5
- jaclang/compiler/absyntree.py +4 -5
- jaclang/compiler/generated/jac_parser.py +2 -2
- jaclang/compiler/jac.lark +2 -2
- jaclang/compiler/parser.py +48 -8
- jaclang/compiler/passes/main/__init__.py +3 -2
- jaclang/compiler/passes/main/access_modifier_pass.py +173 -0
- jaclang/compiler/passes/main/def_impl_match_pass.py +4 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +10 -7
- jaclang/compiler/passes/main/import_pass.py +70 -40
- jaclang/compiler/passes/main/pyast_gen_pass.py +47 -83
- jaclang/compiler/passes/main/pyast_load_pass.py +136 -73
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +218 -0
- jaclang/compiler/passes/main/pyout_pass.py +14 -13
- jaclang/compiler/passes/main/registry_pass.py +8 -3
- jaclang/compiler/passes/main/schedules.py +7 -3
- jaclang/compiler/passes/main/sym_tab_build_pass.py +32 -29
- jaclang/compiler/passes/main/tests/test_import_pass.py +13 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +83 -21
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -4
- jaclang/compiler/passes/transform.py +2 -0
- jaclang/compiler/symtable.py +10 -3
- jaclang/compiler/tests/test_importer.py +9 -0
- jaclang/compiler/workspace.py +17 -5
- jaclang/core/aott.py +43 -63
- jaclang/core/construct.py +157 -21
- jaclang/core/importer.py +77 -65
- jaclang/core/llms/__init__.py +20 -0
- jaclang/core/llms/anthropic.py +61 -0
- jaclang/core/llms/base.py +206 -0
- jaclang/core/llms/groq.py +67 -0
- jaclang/core/llms/huggingface.py +73 -0
- jaclang/core/llms/ollama.py +78 -0
- jaclang/core/llms/openai.py +61 -0
- jaclang/core/llms/togetherai.py +60 -0
- jaclang/core/llms/utils.py +9 -0
- jaclang/core/memory.py +48 -0
- jaclang/core/shelve_storage.py +55 -0
- jaclang/core/utils.py +16 -1
- jaclang/plugin/__init__.py +1 -2
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +134 -18
- jaclang/plugin/feature.py +35 -13
- jaclang/plugin/spec.py +52 -10
- jaclang/plugin/tests/test_jaseci.py +219 -0
- jaclang/settings.py +1 -1
- jaclang/utils/helpers.py +6 -2
- jaclang/utils/treeprinter.py +14 -6
- jaclang-0.6.1.dist-info/METADATA +17 -0
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/RECORD +55 -42
- jaclang/core/llms.py +0 -111
- jaclang-0.5.18.dist-info/METADATA +0 -7
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/WHEEL +0 -0
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/entry_points.txt +0 -0
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/top_level.txt +0 -0
|
@@ -5,7 +5,6 @@ also creates bytecode files from the Python code, and manages the caching of
|
|
|
5
5
|
relevant files.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import ast as ast3
|
|
9
8
|
import os
|
|
10
9
|
|
|
11
10
|
|
|
@@ -43,18 +42,17 @@ class PyOutPass(Pass):
|
|
|
43
42
|
out_path_pyc
|
|
44
43
|
) > os.path.getmtime(mod_path):
|
|
45
44
|
continue
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
try:
|
|
46
|
+
self.gen_python(mod, out_path=out_path_py)
|
|
47
|
+
self.dump_bytecode(mod, mod_path=mod_path, out_path=out_path_pyc)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
self.warning(f"Error in generating Python code: {e}", node)
|
|
48
50
|
self.terminate()
|
|
49
51
|
|
|
50
52
|
def gen_python(self, node: ast.Module, out_path: str) -> None:
|
|
51
53
|
"""Generate Python."""
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
f.write(node.gen.py)
|
|
55
|
-
except Exception as e:
|
|
56
|
-
print(ast3.dump(node.gen.py_ast[0], indent=2))
|
|
57
|
-
raise e
|
|
54
|
+
with open(out_path, "w") as f:
|
|
55
|
+
f.write(node.gen.py)
|
|
58
56
|
|
|
59
57
|
def dump_bytecode(self, node: ast.Module, mod_path: str, out_path: str) -> None:
|
|
60
58
|
"""Generate Python."""
|
|
@@ -70,14 +68,17 @@ class PyOutPass(Pass):
|
|
|
70
68
|
"""Get output targets."""
|
|
71
69
|
base_path, file_name = os.path.split(node.loc.mod_path)
|
|
72
70
|
gen_path = os.path.join(base_path, Con.JAC_GEN_DIR)
|
|
73
|
-
os.makedirs(gen_path, exist_ok=True)
|
|
74
|
-
with open(os.path.join(gen_path, "__init__.py"), "w"):
|
|
75
|
-
pass
|
|
76
71
|
mod_dir, file_name = os.path.split(node.loc.mod_path)
|
|
77
72
|
mod_dir = mod_dir.replace(base_path, "").lstrip(os.sep)
|
|
78
73
|
base_name, _ = os.path.splitext(file_name)
|
|
79
74
|
out_dir = os.path.join(gen_path, mod_dir)
|
|
80
|
-
|
|
75
|
+
try:
|
|
76
|
+
os.makedirs(gen_path, exist_ok=True)
|
|
77
|
+
with open(os.path.join(gen_path, "__init__.py"), "w"):
|
|
78
|
+
pass
|
|
79
|
+
os.makedirs(out_dir, exist_ok=True)
|
|
80
|
+
except Exception as e:
|
|
81
|
+
self.warning(f"Can't create directory {out_dir}: {e}", node)
|
|
81
82
|
out_path_py = os.path.join(out_dir, f"{base_name}.py")
|
|
82
83
|
out_path_pyc = os.path.join(out_dir, f"{base_name}.jbc")
|
|
83
84
|
return node.loc.mod_path, out_path_py, out_path_pyc
|
|
@@ -32,9 +32,14 @@ class RegistryPass(Pass):
|
|
|
32
32
|
module_dir = os.path.join(
|
|
33
33
|
os.path.abspath(os.path.dirname(node.source.file_path)), Con.JAC_GEN_DIR
|
|
34
34
|
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
try:
|
|
36
|
+
os.makedirs(module_dir, exist_ok=True)
|
|
37
|
+
with open(
|
|
38
|
+
os.path.join(module_dir, f"{module_name}.registry.pkl"), "wb"
|
|
39
|
+
) as f:
|
|
40
|
+
pickle.dump(node.registry, f)
|
|
41
|
+
except Exception as e:
|
|
42
|
+
self.warning(f"Can't save registry for {module_name}: {e}")
|
|
38
43
|
self.modules_visited.pop()
|
|
39
44
|
|
|
40
45
|
def exit_architype(self, node: ast.Architype) -> None:
|
|
@@ -7,27 +7,31 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
from .sub_node_tab_pass import SubNodeTabPass # noqa: I100
|
|
10
|
-
from .import_pass import
|
|
10
|
+
from .import_pass import JacImportPass, PyImportPass # noqa: I100
|
|
11
11
|
from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
|
|
12
12
|
from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
|
|
13
13
|
from .def_use_pass import DefUsePass # noqa: I100
|
|
14
14
|
from .pyout_pass import PyOutPass # noqa: I100
|
|
15
15
|
from .pybc_gen_pass import PyBytecodeGenPass # noqa: I100
|
|
16
16
|
from .pyast_gen_pass import PyastGenPass # noqa: I100
|
|
17
|
+
from .pyjac_ast_link_pass import PyJacAstLinkPass # noqa: I100
|
|
17
18
|
from .type_check_pass import JacTypeCheckPass # noqa: I100
|
|
18
19
|
from .fuse_typeinfo_pass import FuseTypeInfoPass # noqa: I100
|
|
19
20
|
from .registry_pass import RegistryPass # noqa: I100
|
|
21
|
+
from .access_modifier_pass import AccessCheckPass # noqa: I100
|
|
20
22
|
|
|
21
23
|
py_code_gen = [
|
|
22
24
|
SubNodeTabPass,
|
|
23
|
-
|
|
25
|
+
JacImportPass,
|
|
26
|
+
PyImportPass,
|
|
24
27
|
SymTabBuildPass,
|
|
25
28
|
DeclDefMatchPass,
|
|
26
29
|
DefUsePass,
|
|
27
30
|
RegistryPass,
|
|
28
31
|
PyastGenPass,
|
|
32
|
+
PyJacAstLinkPass,
|
|
29
33
|
PyBytecodeGenPass,
|
|
30
34
|
]
|
|
31
35
|
|
|
32
|
-
py_code_gen_typed = [*py_code_gen, JacTypeCheckPass, FuseTypeInfoPass]
|
|
36
|
+
py_code_gen_typed = [*py_code_gen, JacTypeCheckPass, FuseTypeInfoPass, AccessCheckPass]
|
|
33
37
|
py_compiler = [*py_code_gen, PyOutPass]
|
|
@@ -11,7 +11,7 @@ from typing import Optional, Sequence
|
|
|
11
11
|
import jaclang.compiler.absyntree as ast
|
|
12
12
|
from jaclang.compiler.constant import Tokens as Tok
|
|
13
13
|
from jaclang.compiler.passes import Pass
|
|
14
|
-
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
14
|
+
from jaclang.compiler.symtable import Symbol, SymbolAccess, SymbolTable
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class SymTabPass(Pass):
|
|
@@ -30,10 +30,15 @@ class SymTabPass(Pass):
|
|
|
30
30
|
return True
|
|
31
31
|
return result
|
|
32
32
|
|
|
33
|
+
def inherit_sym_tab(self, scope: SymbolTable, sym_tab: SymbolTable) -> None:
|
|
34
|
+
"""Inherit symbol table."""
|
|
35
|
+
for i in sym_tab.tab.values():
|
|
36
|
+
self.def_insert(i.decl, access_spec=i.access, table_override=scope)
|
|
37
|
+
|
|
33
38
|
def def_insert(
|
|
34
39
|
self,
|
|
35
40
|
node: ast.AstSymbolNode,
|
|
36
|
-
access_spec: Optional[ast.AstAccessNode] = None,
|
|
41
|
+
access_spec: Optional[ast.AstAccessNode] | SymbolAccess = None,
|
|
37
42
|
single_decl: Optional[str] = None,
|
|
38
43
|
table_override: Optional[SymbolTable] = None,
|
|
39
44
|
) -> Optional[Symbol]:
|
|
@@ -41,26 +46,20 @@ class SymTabPass(Pass):
|
|
|
41
46
|
table = table_override if table_override else node.sym_tab
|
|
42
47
|
if self.seen(node) and node.sym_link and table == node.sym_link.parent_tab:
|
|
43
48
|
return node.sym_link
|
|
44
|
-
if
|
|
45
|
-
table
|
|
46
|
-
|
|
47
|
-
table.insert(
|
|
48
|
-
node=node, single=single_decl is not None, access_spec=access_spec
|
|
49
|
-
)
|
|
49
|
+
if table:
|
|
50
|
+
table.insert(
|
|
51
|
+
node=node, single=single_decl is not None, access_spec=access_spec
|
|
50
52
|
)
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# )
|
|
58
|
-
pass # TODO: Sort this out at some point
|
|
53
|
+
self.update_py_ctx_for_def(node)
|
|
54
|
+
self.handle_hit_outcome(node)
|
|
55
|
+
return node.sym_link
|
|
56
|
+
|
|
57
|
+
def update_py_ctx_for_def(self, node: ast.AstSymbolNode) -> None:
|
|
58
|
+
"""Update python context for definition."""
|
|
59
59
|
node.py_ctx_func = ast3.Store
|
|
60
60
|
if isinstance(node.sym_name_node, ast.AstSymbolNode):
|
|
61
61
|
node.sym_name_node.py_ctx_func = ast3.Store
|
|
62
62
|
if isinstance(node, (ast.TupleVal, ast.ListVal)) and node.values:
|
|
63
|
-
|
|
64
63
|
# Handling of UnaryExpr case for item is only necessary for
|
|
65
64
|
# the generation of Starred nodes in the AST for examples
|
|
66
65
|
# like `(a, *b) = (1, 2, 3, 4)`.
|
|
@@ -78,8 +77,6 @@ class SymTabPass(Pass):
|
|
|
78
77
|
fix(i)
|
|
79
78
|
|
|
80
79
|
fix(node)
|
|
81
|
-
self.handle_hit_outcome(node)
|
|
82
|
-
return node.sym_link
|
|
83
80
|
|
|
84
81
|
def use_lookup(
|
|
85
82
|
self,
|
|
@@ -220,9 +217,9 @@ class SymTabBuildPass(SymTabPass):
|
|
|
220
217
|
else:
|
|
221
218
|
self.cur_sym_tab.append(self.cur_scope().push_scope(name, key_node))
|
|
222
219
|
|
|
223
|
-
def pop_scope(self) ->
|
|
220
|
+
def pop_scope(self) -> SymbolTable:
|
|
224
221
|
"""Pop scope."""
|
|
225
|
-
self.cur_sym_tab.pop()
|
|
222
|
+
return self.cur_sym_tab.pop()
|
|
226
223
|
|
|
227
224
|
def cur_scope(self) -> SymbolTable:
|
|
228
225
|
"""Return current scope."""
|
|
@@ -266,7 +263,13 @@ class SymTabBuildPass(SymTabPass):
|
|
|
266
263
|
mod_path: str,
|
|
267
264
|
is_imported: bool,
|
|
268
265
|
"""
|
|
269
|
-
self.pop_scope()
|
|
266
|
+
s = self.pop_scope()
|
|
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
|
+
|
|
270
273
|
if (
|
|
271
274
|
isinstance(node.parent, ast.Module)
|
|
272
275
|
and node
|
|
@@ -276,8 +279,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
276
279
|
]
|
|
277
280
|
and node.sym_tab
|
|
278
281
|
):
|
|
279
|
-
|
|
280
|
-
self.def_insert(v.decl, table_override=self.cur_scope())
|
|
282
|
+
self.inherit_sym_tab(scope=self.cur_scope(), sym_tab=node.sym_tab)
|
|
281
283
|
|
|
282
284
|
def enter_global_vars(self, node: ast.GlobalVars) -> None:
|
|
283
285
|
"""Sub objects.
|
|
@@ -403,8 +405,9 @@ class SymTabBuildPass(SymTabPass):
|
|
|
403
405
|
f" not found to include *, or ICE occurred!"
|
|
404
406
|
)
|
|
405
407
|
else:
|
|
406
|
-
|
|
407
|
-
self.
|
|
408
|
+
self.inherit_sym_tab(
|
|
409
|
+
scope=self.cur_scope(), sym_tab=source.sub_module.sym_tab
|
|
410
|
+
)
|
|
408
411
|
|
|
409
412
|
def enter_module_path(self, node: ast.ModulePath) -> None:
|
|
410
413
|
"""Sub objects.
|
|
@@ -450,7 +453,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
450
453
|
body: Optional[ArchBlock],
|
|
451
454
|
"""
|
|
452
455
|
self.sync_node_to_scope(node)
|
|
453
|
-
self.def_insert(node, single_decl="architype")
|
|
456
|
+
self.def_insert(node, access_spec=node, single_decl="architype")
|
|
454
457
|
self.push_scope(node.name.value, node)
|
|
455
458
|
self.sync_node_to_scope(node)
|
|
456
459
|
|
|
@@ -504,7 +507,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
504
507
|
body: Optional[CodeBlock],
|
|
505
508
|
"""
|
|
506
509
|
self.sync_node_to_scope(node)
|
|
507
|
-
self.def_insert(node, single_decl="ability")
|
|
510
|
+
self.def_insert(node, access_spec=node, single_decl="ability")
|
|
508
511
|
self.push_scope(node.sym_name, node)
|
|
509
512
|
self.sync_node_to_scope(node)
|
|
510
513
|
|
|
@@ -592,7 +595,7 @@ class SymTabBuildPass(SymTabPass):
|
|
|
592
595
|
body: Optional['EnumBlock'],
|
|
593
596
|
"""
|
|
594
597
|
self.sync_node_to_scope(node)
|
|
595
|
-
self.def_insert(node, single_decl="enum")
|
|
598
|
+
self.def_insert(node, access_spec=node, single_decl="enum")
|
|
596
599
|
self.push_scope(node.sym_name, node)
|
|
597
600
|
self.sync_node_to_scope(node)
|
|
598
601
|
|
|
@@ -1,7 +1,8 @@
|
|
|
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
|
-
from jaclang.compiler.passes.main import
|
|
5
|
+
from jaclang.compiler.passes.main import JacImportPass
|
|
5
6
|
from jaclang.utils.test import TestCase
|
|
6
7
|
|
|
7
8
|
|
|
@@ -14,6 +15,16 @@ class ImportPassPassTests(TestCase):
|
|
|
14
15
|
|
|
15
16
|
def test_pygen_jac_cli(self) -> None:
|
|
16
17
|
"""Basic test for pass."""
|
|
17
|
-
state = jac_file_to_pass(self.fixture_abs_path("base.jac"),
|
|
18
|
+
state = jac_file_to_pass(self.fixture_abs_path("base.jac"), JacImportPass)
|
|
18
19
|
self.assertFalse(state.errors_had)
|
|
19
20
|
self.assertIn("56", str(state.ir.to_dict()))
|
|
21
|
+
|
|
22
|
+
def test_import_auto_impl(self) -> None:
|
|
23
|
+
"""Basic test for pass."""
|
|
24
|
+
state = jac_file_to_pass(self.fixture_abs_path("autoimpl.jac"), JacImportPass)
|
|
25
|
+
num_modules = len(state.ir.get_all_sub_nodes(ast.Module))
|
|
26
|
+
mod_names = [i.name for i in state.ir.get_all_sub_nodes(ast.Module)]
|
|
27
|
+
self.assertEqual(num_modules, 3)
|
|
28
|
+
self.assertIn("getme.impl", mod_names)
|
|
29
|
+
self.assertIn("autoimpl.impl", mod_names)
|
|
30
|
+
self.assertIn("autoimpl.something.else.impl", mod_names)
|
|
@@ -117,7 +117,19 @@ class JacFormatPass(Pass):
|
|
|
117
117
|
if not node.gen.jac.endswith("\n"):
|
|
118
118
|
self.emit_ln(node, "")
|
|
119
119
|
if counter <= len(node.body) - 1:
|
|
120
|
-
|
|
120
|
+
if (
|
|
121
|
+
isinstance(i, ast.Ability)
|
|
122
|
+
and isinstance(node.body[counter], ast.Ability)
|
|
123
|
+
and i.gen.jac.endswith(";")
|
|
124
|
+
or (
|
|
125
|
+
isinstance(i, ast.Architype)
|
|
126
|
+
and len(node.body[counter].kid[-1].kid) == 2
|
|
127
|
+
and len(node.body[counter - 1].kid[-1].kid) == 2
|
|
128
|
+
)
|
|
129
|
+
):
|
|
130
|
+
self.emit(node, "")
|
|
131
|
+
else:
|
|
132
|
+
self.emit_ln(node, "")
|
|
121
133
|
last_element = i
|
|
122
134
|
|
|
123
135
|
def exit_global_vars(self, node: ast.GlobalVars) -> None:
|
|
@@ -274,15 +286,19 @@ class JacFormatPass(Pass):
|
|
|
274
286
|
if prev_token and isinstance(prev_token, ast.Ability):
|
|
275
287
|
self.emit(node, f"{stmt.gen.jac}")
|
|
276
288
|
else:
|
|
277
|
-
self.emit(node,
|
|
289
|
+
self.emit(node, stmt.gen.jac)
|
|
290
|
+
if not stmt.gen.jac.endswith("postinit;"):
|
|
291
|
+
self.indent_level -= 1
|
|
292
|
+
self.emit_ln(node, "")
|
|
293
|
+
self.indent_level += 1
|
|
278
294
|
elif stmt.gen.jac == ",":
|
|
279
295
|
self.emit(node, f"{stmt.value} ")
|
|
280
296
|
elif stmt.value == "=":
|
|
281
297
|
self.emit(node, f" {stmt.value} ")
|
|
282
298
|
else:
|
|
283
299
|
self.emit(node, f"{stmt.value}")
|
|
284
|
-
|
|
285
|
-
|
|
300
|
+
prev_token = stmt
|
|
301
|
+
continue
|
|
286
302
|
elif isinstance(stmt, ast.Semi):
|
|
287
303
|
self.emit(node, stmt.gen.jac)
|
|
288
304
|
elif isinstance(prev_token, (ast.HasVar, ast.ArchHas)) and not isinstance(
|
|
@@ -293,14 +309,28 @@ class JacFormatPass(Pass):
|
|
|
293
309
|
self.emit_ln(node, "")
|
|
294
310
|
self.indent_level += 1
|
|
295
311
|
self.emit(node, stmt.gen.jac)
|
|
296
|
-
elif isinstance(prev_token, ast.Ability) and isinstance(
|
|
312
|
+
elif isinstance(prev_token, ast.Ability) and isinstance(
|
|
313
|
+
stmt, (ast.Ability, ast.AbilityDef)
|
|
314
|
+
):
|
|
297
315
|
if not isinstance(prev_token.kid[-1], ast.CommentToken) and (
|
|
298
|
-
|
|
316
|
+
stmt.body and not isinstance(stmt.body, ast.FuncCall)
|
|
299
317
|
):
|
|
300
318
|
self.indent_level -= 1
|
|
301
319
|
self.emit_ln(node, "")
|
|
302
320
|
self.indent_level += 1
|
|
303
|
-
|
|
321
|
+
self.emit(node, f"{stmt.gen.jac}")
|
|
322
|
+
elif stmt.body and isinstance(
|
|
323
|
+
stmt.body, (ast.FuncCall, ast.EventSignature)
|
|
324
|
+
):
|
|
325
|
+
self.indent_level -= 1
|
|
326
|
+
self.emit_ln(node, "")
|
|
327
|
+
self.indent_level += 1
|
|
328
|
+
self.emit(node, stmt.gen.jac)
|
|
329
|
+
else:
|
|
330
|
+
self.indent_level -= 1
|
|
331
|
+
self.emit_ln(node, "")
|
|
332
|
+
self.indent_level += 1
|
|
333
|
+
self.emit(node, f"{stmt.gen.jac}")
|
|
304
334
|
else:
|
|
305
335
|
if prev_token and prev_token.gen.jac.strip() == "{":
|
|
306
336
|
self.emit_ln(node, "")
|
|
@@ -652,8 +682,6 @@ class JacFormatPass(Pass):
|
|
|
652
682
|
else:
|
|
653
683
|
self.emit(node, f" {i.gen.jac}")
|
|
654
684
|
prev_token = i
|
|
655
|
-
if isinstance(node.kid[-1], ast.Semi) and not node.gen.jac.endswith("\n"):
|
|
656
|
-
self.emit_ln(node, "")
|
|
657
685
|
|
|
658
686
|
def exit_func_signature(self, node: ast.FuncSignature) -> None:
|
|
659
687
|
"""Sub objects.
|
|
@@ -809,7 +837,9 @@ class JacFormatPass(Pass):
|
|
|
809
837
|
elif isinstance(i, ast.Token) and i.gen.jac == ":":
|
|
810
838
|
self.emit(node, f"{i.gen.jac} ")
|
|
811
839
|
else:
|
|
812
|
-
if start or (
|
|
840
|
+
if start or (
|
|
841
|
+
prev_token and isinstance(prev_token, (ast.String, ast.Name))
|
|
842
|
+
):
|
|
813
843
|
self.emit(node, i.gen.jac)
|
|
814
844
|
start = False
|
|
815
845
|
else:
|
|
@@ -972,6 +1002,8 @@ class JacFormatPass(Pass):
|
|
|
972
1002
|
if not j.gen.jac.startswith(":")
|
|
973
1003
|
else self.emit(node, f"{j.gen.jac} ")
|
|
974
1004
|
)
|
|
1005
|
+
elif isinstance(i, ast.Token) and i.gen.jac == ":":
|
|
1006
|
+
self.emit(node, i.gen.jac)
|
|
975
1007
|
else:
|
|
976
1008
|
self.emit(node, f" {i.gen.jac}")
|
|
977
1009
|
if isinstance(node.kid[-1], ast.CommentToken) and not node.gen.jac.endswith(
|
|
@@ -1130,6 +1162,7 @@ class JacFormatPass(Pass):
|
|
|
1130
1162
|
node.parent
|
|
1131
1163
|
and node.parent.parent
|
|
1132
1164
|
and isinstance(node.parent.parent, (ast.Ability))
|
|
1165
|
+
and node.parent.kid[1].gen.jac != "self.jaseci_sdk = {};\n"
|
|
1133
1166
|
):
|
|
1134
1167
|
self.emit_ln(node, "")
|
|
1135
1168
|
start = True
|
|
@@ -1210,6 +1243,7 @@ class JacFormatPass(Pass):
|
|
|
1210
1243
|
node.parent
|
|
1211
1244
|
and node.parent.parent
|
|
1212
1245
|
and isinstance(node.parent.parent, (ast.Ability))
|
|
1246
|
+
and (node.parent.kid[1].gen.jac != "prev_info = [];\n")
|
|
1213
1247
|
):
|
|
1214
1248
|
self.emit_ln(node, "")
|
|
1215
1249
|
start = True
|
|
@@ -1309,9 +1343,16 @@ class JacFormatPass(Pass):
|
|
|
1309
1343
|
if i.is_inline:
|
|
1310
1344
|
self.emit(node, i.gen.jac)
|
|
1311
1345
|
else:
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1346
|
+
if i.gen.jac not in [
|
|
1347
|
+
"# Update any new user level buddy schedule",
|
|
1348
|
+
"# Construct prompt here",
|
|
1349
|
+
]:
|
|
1350
|
+
self.emit_ln(node, "")
|
|
1351
|
+
self.emit_ln(node, "")
|
|
1352
|
+
self.emit_ln(node, i.gen.jac)
|
|
1353
|
+
else:
|
|
1354
|
+
self.emit_ln(node, "")
|
|
1355
|
+
self.emit(node, i.gen.jac)
|
|
1315
1356
|
elif isinstance(i, ast.Token) and (
|
|
1316
1357
|
i.name == Tok.KW_LET or i.gen.jac == ":"
|
|
1317
1358
|
):
|
|
@@ -1521,14 +1562,29 @@ class JacFormatPass(Pass):
|
|
|
1521
1562
|
|
|
1522
1563
|
values: Optional[SubNodeList[ExprType]],
|
|
1523
1564
|
"""
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1565
|
+
line_break_needed = False
|
|
1566
|
+
indented = False
|
|
1567
|
+
for i in node.kid:
|
|
1568
|
+
if isinstance(i, ast.SubNodeList):
|
|
1569
|
+
line_break_needed = self.is_line_break_needed(i.gen.jac, 88)
|
|
1570
|
+
if line_break_needed:
|
|
1571
|
+
self.emit_ln(node, "")
|
|
1572
|
+
self.indent_level += 1
|
|
1573
|
+
indented = True
|
|
1574
|
+
for j in i.kid:
|
|
1575
|
+
if j.gen.jac == (","):
|
|
1576
|
+
self.indent_level -= 1
|
|
1577
|
+
self.emit(node, f"{j.gen.jac}\n")
|
|
1578
|
+
self.indent_level += 1
|
|
1579
|
+
else:
|
|
1580
|
+
self.emit(node, f"{j.gen.jac}")
|
|
1581
|
+
else:
|
|
1582
|
+
self.emit(node, f"{i.gen.jac}")
|
|
1583
|
+
if indented:
|
|
1584
|
+
self.indent_level -= 1
|
|
1585
|
+
self.emit(node, "\n")
|
|
1586
|
+
else:
|
|
1587
|
+
self.emit(node, i.gen.jac)
|
|
1532
1588
|
|
|
1533
1589
|
def exit_set_val(self, node: ast.ListVal) -> None:
|
|
1534
1590
|
"""Sub objects.
|
|
@@ -1745,6 +1801,7 @@ class JacFormatPass(Pass):
|
|
|
1745
1801
|
ast.ElseStmt,
|
|
1746
1802
|
ast.SpecialVarRef,
|
|
1747
1803
|
ast.ListCompr,
|
|
1804
|
+
ast.Name,
|
|
1748
1805
|
),
|
|
1749
1806
|
):
|
|
1750
1807
|
self.emit(node, f" {i.gen.jac}")
|
|
@@ -1907,6 +1964,11 @@ class JacFormatPass(Pass):
|
|
|
1907
1964
|
node.parent
|
|
1908
1965
|
and node.parent.parent
|
|
1909
1966
|
and isinstance(node.parent.parent, (ast.Ability))
|
|
1967
|
+
and (
|
|
1968
|
+
isinstance(node.parent.kid[1], ast.Assignment)
|
|
1969
|
+
and node.parent.kid[1].kid[-1].gen.jac
|
|
1970
|
+
!= "# Update any new user level buddy schedule"
|
|
1971
|
+
)
|
|
1910
1972
|
):
|
|
1911
1973
|
self.indent_level -= 1
|
|
1912
1974
|
self.emit_ln(node, "")
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import ast as ast3
|
|
4
4
|
import os
|
|
5
5
|
import shutil
|
|
6
|
+
from contextlib import suppress
|
|
6
7
|
from difflib import unified_diff
|
|
7
8
|
|
|
8
9
|
import jaclang.compiler.absyntree as ast
|
|
@@ -56,12 +57,14 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
56
57
|
"""Set up test."""
|
|
57
58
|
root_dir = self.fixture_abs_path("")
|
|
58
59
|
directories_to_clean = [
|
|
59
|
-
os.path.join(root_dir, "myca_formatted_code", "__jac_gen__")
|
|
60
|
+
os.path.join(root_dir, "myca_formatted_code", "__jac_gen__"),
|
|
61
|
+
os.path.join(root_dir, "genai", "__jac_gen__"),
|
|
60
62
|
]
|
|
61
63
|
|
|
62
64
|
for directory in directories_to_clean:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
with suppress(Exception):
|
|
66
|
+
if os.path.exists(directory):
|
|
67
|
+
shutil.rmtree(directory)
|
|
65
68
|
return super().setUp()
|
|
66
69
|
|
|
67
70
|
def test_jac_file_compr(self) -> None:
|
|
@@ -79,15 +82,19 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
79
82
|
fixtures_dir = os.path.join(self.fixture_abs_path(""), "myca_formatted_code")
|
|
80
83
|
fixture_files = os.listdir(fixtures_dir)
|
|
81
84
|
for file_name in fixture_files:
|
|
85
|
+
if file_name == "__jac_gen__":
|
|
86
|
+
continue
|
|
82
87
|
with self.subTest(file=file_name):
|
|
83
88
|
file_path = os.path.join(fixtures_dir, file_name)
|
|
84
89
|
self.compare_files(file_path)
|
|
85
90
|
|
|
86
|
-
def
|
|
91
|
+
def test_compare_genai_fixtures(self) -> None:
|
|
87
92
|
"""Tests if files in the genai fixtures directory do not change after being formatted."""
|
|
88
93
|
fixtures_dir = os.path.join(self.fixture_abs_path(""), "genai")
|
|
89
94
|
fixture_files = os.listdir(fixtures_dir)
|
|
90
95
|
for file_name in fixture_files:
|
|
96
|
+
if file_name == "__jac_gen__":
|
|
97
|
+
continue
|
|
91
98
|
with self.subTest(file=file_name):
|
|
92
99
|
file_path = os.path.join(fixtures_dir, file_name)
|
|
93
100
|
self.compare_files(file_path)
|
|
@@ -54,10 +54,12 @@ class Transform(ABC, Generic[T]):
|
|
|
54
54
|
"""Pass Error."""
|
|
55
55
|
alrt = Alert(msg, self.cur_node.loc if not node_override else node_override.loc)
|
|
56
56
|
self.errors_had.append(alrt)
|
|
57
|
+
# print("Error:", str(alrt))
|
|
57
58
|
self.logger.error(str(alrt))
|
|
58
59
|
|
|
59
60
|
def log_warning(self, msg: str, node_override: Optional[AstNode] = None) -> None:
|
|
60
61
|
"""Pass Error."""
|
|
61
62
|
alrt = Alert(msg, self.cur_node.loc if not node_override else node_override.loc)
|
|
62
63
|
self.warnings_had.append(alrt)
|
|
64
|
+
# print("Warning:", str(alrt))
|
|
63
65
|
self.logger.warning(str(alrt))
|
jaclang/compiler/symtable.py
CHANGED
|
@@ -46,9 +46,12 @@ class SymbolType(Enum):
|
|
|
46
46
|
class SymbolInfo:
|
|
47
47
|
"""Symbol Info."""
|
|
48
48
|
|
|
49
|
-
def __init__(
|
|
49
|
+
def __init__(
|
|
50
|
+
self, typ: str = "NoType", acc_tag: Optional[SymbolAccess] = None
|
|
51
|
+
) -> None: # noqa: ANN401
|
|
50
52
|
"""Initialize."""
|
|
51
53
|
self.typ = typ
|
|
54
|
+
self.acc_tag: Optional[SymbolAccess] = acc_tag
|
|
52
55
|
self.typ_sym_table: Optional[SymbolTable] = None
|
|
53
56
|
|
|
54
57
|
|
|
@@ -146,7 +149,7 @@ class SymbolTable:
|
|
|
146
149
|
def insert(
|
|
147
150
|
self,
|
|
148
151
|
node: ast.AstSymbolNode,
|
|
149
|
-
access_spec: Optional[ast.AstAccessNode] = None,
|
|
152
|
+
access_spec: Optional[ast.AstAccessNode] | SymbolAccess = None,
|
|
150
153
|
single: bool = False,
|
|
151
154
|
) -> Optional[ast.AstNode]:
|
|
152
155
|
"""Set a variable in the symbol table.
|
|
@@ -162,7 +165,11 @@ class SymbolTable:
|
|
|
162
165
|
if node.sym_name not in self.tab:
|
|
163
166
|
self.tab[node.sym_name] = Symbol(
|
|
164
167
|
defn=node,
|
|
165
|
-
access=
|
|
168
|
+
access=(
|
|
169
|
+
access_spec
|
|
170
|
+
if isinstance(access_spec, SymbolAccess)
|
|
171
|
+
else access_spec.access_type if access_spec else SymbolAccess.PUBLIC
|
|
172
|
+
),
|
|
166
173
|
parent_tab=self,
|
|
167
174
|
)
|
|
168
175
|
else:
|
|
@@ -38,3 +38,12 @@ class TestLoader(TestCase):
|
|
|
38
38
|
"{SomeObj(a=10): 'check'} [MyObj(apple=5, banana=7), MyObj(apple=5, banana=7)]",
|
|
39
39
|
stdout_value,
|
|
40
40
|
)
|
|
41
|
+
|
|
42
|
+
def test_package_import(self) -> None:
|
|
43
|
+
"""Test package import."""
|
|
44
|
+
captured_output = io.StringIO()
|
|
45
|
+
sys.stdout = captured_output
|
|
46
|
+
cli.run(self.fixture_abs_path("../../../tests/fixtures/package_import.jac"))
|
|
47
|
+
sys.stdout = sys.__stdout__
|
|
48
|
+
stdout_value = captured_output.getvalue()
|
|
49
|
+
self.assertEqual("package is imported successfully!\n", stdout_value)
|
jaclang/compiler/workspace.py
CHANGED
|
@@ -7,8 +7,7 @@ from typing import Optional, Sequence
|
|
|
7
7
|
|
|
8
8
|
import jaclang.compiler.absyntree as ast
|
|
9
9
|
from jaclang.compiler.compile import jac_str_to_pass
|
|
10
|
-
from jaclang.compiler.passes.main import DefUsePass
|
|
11
|
-
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
10
|
+
from jaclang.compiler.passes.main import DefUsePass, schedules
|
|
12
11
|
from jaclang.compiler.passes.transform import Alert
|
|
13
12
|
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
14
13
|
|
|
@@ -46,11 +45,14 @@ class ModuleInfo:
|
|
|
46
45
|
class Workspace:
|
|
47
46
|
"""Class for managing workspace."""
|
|
48
47
|
|
|
49
|
-
def __init__(
|
|
48
|
+
def __init__(
|
|
49
|
+
self, path: str, lazy_parse: bool = False, type_check: bool = False
|
|
50
|
+
) -> None:
|
|
50
51
|
"""Initialize workspace."""
|
|
51
52
|
self.path = path
|
|
52
53
|
self.modules: dict[str, ModuleInfo] = {}
|
|
53
54
|
self.lazy_parse = lazy_parse
|
|
55
|
+
self.type_check = type_check
|
|
54
56
|
self.rebuild_workspace()
|
|
55
57
|
|
|
56
58
|
def rebuild_workspace(self) -> None:
|
|
@@ -78,7 +80,12 @@ class Workspace:
|
|
|
78
80
|
build = jac_str_to_pass(
|
|
79
81
|
jac_str=source,
|
|
80
82
|
file_path=file,
|
|
81
|
-
|
|
83
|
+
schedule=(
|
|
84
|
+
schedules.py_code_gen_typed
|
|
85
|
+
if self.type_check
|
|
86
|
+
else schedules.py_code_gen
|
|
87
|
+
),
|
|
88
|
+
target=DefUsePass if not self.type_check else None,
|
|
82
89
|
)
|
|
83
90
|
if not isinstance(build.ir, ast.Module):
|
|
84
91
|
src = ast.JacSource(source, mod_path=file)
|
|
@@ -118,7 +125,12 @@ class Workspace:
|
|
|
118
125
|
build = jac_str_to_pass(
|
|
119
126
|
jac_str=source,
|
|
120
127
|
file_path=file_path,
|
|
121
|
-
schedule=
|
|
128
|
+
schedule=(
|
|
129
|
+
schedules.py_code_gen_typed
|
|
130
|
+
if self.type_check
|
|
131
|
+
else schedules.py_code_gen
|
|
132
|
+
),
|
|
133
|
+
target=DefUsePass if not self.type_check else None,
|
|
122
134
|
)
|
|
123
135
|
if not isinstance(build.ir, ast.Module):
|
|
124
136
|
src = ast.JacSource(source, mod_path=file_path)
|