jaclang 0.7.13__py3-none-any.whl → 0.7.16__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 +15 -10
- jaclang/cli/cmdreg.py +9 -12
- jaclang/compiler/__init__.py +19 -53
- jaclang/compiler/absyntree.py +95 -17
- jaclang/compiler/jac.lark +4 -3
- jaclang/compiler/parser.py +35 -23
- jaclang/compiler/passes/ir_pass.py +4 -13
- jaclang/compiler/passes/main/access_modifier_pass.py +1 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +4 -5
- jaclang/compiler/passes/main/import_pass.py +19 -23
- jaclang/compiler/passes/main/pyast_gen_pass.py +308 -567
- jaclang/compiler/passes/main/pyast_load_pass.py +33 -6
- jaclang/compiler/passes/main/registry_pass.py +37 -3
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
- jaclang/compiler/passes/main/tests/__init__.py +1 -1
- jaclang/compiler/passes/main/tests/test_import_pass.py +5 -1
- jaclang/compiler/passes/main/type_check_pass.py +7 -0
- jaclang/compiler/passes/tool/fuse_comments_pass.py +14 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +144 -94
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +0 -1
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
- jaclang/compiler/passes/transform.py +4 -0
- jaclang/compiler/semtable.py +31 -7
- jaclang/compiler/tests/test_importer.py +12 -5
- jaclang/langserve/engine.py +82 -143
- jaclang/langserve/sem_manager.py +379 -0
- jaclang/langserve/server.py +8 -10
- jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
- jaclang/langserve/tests/fixtures/circle.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/test_sem_tokens.py +277 -0
- jaclang/langserve/tests/test_server.py +96 -16
- jaclang/langserve/utils.py +163 -96
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +214 -24
- jaclang/plugin/feature.py +59 -11
- jaclang/plugin/spec.py +58 -6
- jaclang/{core → runtimelib}/architype.py +1 -1
- jaclang/{core → runtimelib}/context.py +8 -1
- jaclang/runtimelib/importer.py +361 -0
- jaclang/runtimelib/machine.py +94 -0
- jaclang/{core → runtimelib}/utils.py +13 -5
- jaclang/settings.py +4 -1
- jaclang/tests/fixtures/abc.jac +3 -3
- jaclang/tests/fixtures/blankwithentry.jac +3 -0
- jaclang/tests/fixtures/byllmissue.jac +1 -5
- jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
- jaclang/tests/fixtures/cls_method.jac +41 -0
- jaclang/tests/fixtures/dblhello.jac +6 -0
- jaclang/tests/fixtures/deep/one_lev.jac +3 -3
- jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
- jaclang/tests/fixtures/deep_import_mods.jac +13 -0
- jaclang/tests/fixtures/err.impl.jac +3 -0
- jaclang/tests/fixtures/err.jac +4 -2
- jaclang/tests/fixtures/err.test.jac +3 -0
- jaclang/tests/fixtures/err_runtime.jac +15 -0
- jaclang/tests/fixtures/game1.jac +1 -1
- jaclang/tests/fixtures/hello.jac +4 -0
- jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
- jaclang/tests/fixtures/impl_grab.jac +4 -1
- jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/needs_import.jac +2 -2
- jaclang/tests/fixtures/pyfunc_2.py +3 -0
- jaclang/tests/fixtures/registry.jac +9 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/fixtures/semstr.jac +1 -4
- jaclang/tests/fixtures/simple_archs.jac +1 -1
- jaclang/tests/test_cli.py +65 -2
- jaclang/tests/test_language.py +83 -7
- jaclang/tests/test_man_code.py +17 -0
- jaclang/tests/test_reference.py +6 -0
- jaclang/utils/helpers.py +45 -21
- jaclang/utils/test.py +9 -0
- jaclang/utils/treeprinter.py +0 -4
- {jaclang-0.7.13.dist-info → jaclang-0.7.16.dist-info}/METADATA +3 -2
- {jaclang-0.7.13.dist-info → jaclang-0.7.16.dist-info}/RECORD +93 -77
- jaclang/core/importer.py +0 -344
- jaclang/tests/fixtures/aott_raise.jac +0 -25
- jaclang/tests/fixtures/package_import.jac +0 -6
- /jaclang/{core → runtimelib}/__init__.py +0 -0
- /jaclang/{core → runtimelib}/constructs.py +0 -0
- /jaclang/{core → runtimelib}/memory.py +0 -0
- /jaclang/{core → runtimelib}/test.py +0 -0
- {jaclang-0.7.13.dist-info → jaclang-0.7.16.dist-info}/WHEEL +0 -0
- {jaclang-0.7.13.dist-info → jaclang-0.7.16.dist-info}/entry_points.txt +0 -0
|
@@ -124,6 +124,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
124
124
|
source=ast.JacSource("", mod_path=self.mod_path),
|
|
125
125
|
doc=doc_str,
|
|
126
126
|
body=valid[1:] if valid and isinstance(valid[0], ast.String) else valid,
|
|
127
|
+
terminals=[],
|
|
127
128
|
is_imported=False,
|
|
128
129
|
kid=valid,
|
|
129
130
|
)
|
|
@@ -143,12 +144,15 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
143
144
|
if sys.version_info >= (3, 12):
|
|
144
145
|
type_params: list[type_param]
|
|
145
146
|
"""
|
|
147
|
+
from jaclang.compiler import TOKEN_MAP
|
|
148
|
+
|
|
149
|
+
reserved_keywords = [v for _, v in TOKEN_MAP.items()]
|
|
150
|
+
|
|
151
|
+
value = node.name if node.name not in reserved_keywords else f"<>{node.name}"
|
|
146
152
|
name = ast.Name(
|
|
147
153
|
file_path=self.mod_path,
|
|
148
154
|
name=Tok.NAME,
|
|
149
|
-
value=
|
|
150
|
-
node.name if node.name != "root" else "root_"
|
|
151
|
-
), # root is a reserved keyword
|
|
155
|
+
value=value,
|
|
152
156
|
line=node.lineno,
|
|
153
157
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
154
158
|
col_start=node.col_offset,
|
|
@@ -1874,10 +1878,19 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1874
1878
|
id: _Identifier
|
|
1875
1879
|
ctx: expr_context
|
|
1876
1880
|
"""
|
|
1881
|
+
from jaclang.compiler import TOKEN_MAP
|
|
1882
|
+
|
|
1883
|
+
reserved_keywords = [
|
|
1884
|
+
v
|
|
1885
|
+
for _, v in TOKEN_MAP.items()
|
|
1886
|
+
if v not in ["float", "int", "str", "bool", "self"]
|
|
1887
|
+
]
|
|
1888
|
+
|
|
1889
|
+
value = node.id if node.id not in reserved_keywords else f"<>{node.id}"
|
|
1877
1890
|
ret = ast.Name(
|
|
1878
1891
|
file_path=self.mod_path,
|
|
1879
1892
|
name=Tok.NAME,
|
|
1880
|
-
value=
|
|
1893
|
+
value=value,
|
|
1881
1894
|
line=node.lineno,
|
|
1882
1895
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
1883
1896
|
col_start=node.col_offset,
|
|
@@ -1912,13 +1925,18 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1912
1925
|
class Nonlocal(stmt):
|
|
1913
1926
|
names: list[_Identifier]
|
|
1914
1927
|
"""
|
|
1928
|
+
from jaclang.compiler import TOKEN_MAP
|
|
1929
|
+
|
|
1930
|
+
reserved_keywords = [v for _, v in TOKEN_MAP.items()]
|
|
1931
|
+
|
|
1915
1932
|
names: list[ast.NameAtom] = []
|
|
1916
1933
|
for name in node.names:
|
|
1934
|
+
value = name if name not in reserved_keywords else f"<>{name}"
|
|
1917
1935
|
names.append(
|
|
1918
1936
|
ast.Name(
|
|
1919
1937
|
file_path=self.mod_path,
|
|
1920
1938
|
name=Tok.NAME,
|
|
1921
|
-
value=
|
|
1939
|
+
value=value,
|
|
1922
1940
|
line=node.lineno,
|
|
1923
1941
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
1924
1942
|
col_start=node.col_offset,
|
|
@@ -2237,10 +2255,19 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2237
2255
|
arg: _Identifier
|
|
2238
2256
|
annotation: expr | None
|
|
2239
2257
|
"""
|
|
2258
|
+
from jaclang.compiler import TOKEN_MAP
|
|
2259
|
+
|
|
2260
|
+
reserved_keywords = [
|
|
2261
|
+
v
|
|
2262
|
+
for _, v in TOKEN_MAP.items()
|
|
2263
|
+
if v not in ["float", "int", "str", "bool", "self"]
|
|
2264
|
+
]
|
|
2265
|
+
|
|
2266
|
+
value = node.arg if node.arg not in reserved_keywords else f"<>{node.arg}"
|
|
2240
2267
|
name = ast.Name(
|
|
2241
2268
|
file_path=self.mod_path,
|
|
2242
2269
|
name=Tok.NAME,
|
|
2243
|
-
value=
|
|
2270
|
+
value=value,
|
|
2244
2271
|
line=node.lineno,
|
|
2245
2272
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
2246
2273
|
col_start=node.col_offset,
|
|
@@ -13,7 +13,7 @@ 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
15
|
from jaclang.compiler.semtable import SemInfo, SemRegistry
|
|
16
|
-
from jaclang.
|
|
16
|
+
from jaclang.runtimelib.utils import get_sem_scope
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class RegistryPass(Pass):
|
|
@@ -46,6 +46,7 @@ class RegistryPass(Pass):
|
|
|
46
46
|
"""Save architype information."""
|
|
47
47
|
scope = get_sem_scope(node)
|
|
48
48
|
seminfo = SemInfo(
|
|
49
|
+
node,
|
|
49
50
|
node.name.value,
|
|
50
51
|
node.arch_type.value,
|
|
51
52
|
node.semstr.lit_value if node.semstr else "",
|
|
@@ -61,7 +62,7 @@ class RegistryPass(Pass):
|
|
|
61
62
|
"""Save enum information."""
|
|
62
63
|
scope = get_sem_scope(node)
|
|
63
64
|
seminfo = SemInfo(
|
|
64
|
-
node.name.value, "Enum", node.semstr.lit_value if node.semstr else ""
|
|
65
|
+
node, node.name.value, "Enum", node.semstr.lit_value if node.semstr else ""
|
|
65
66
|
)
|
|
66
67
|
if (
|
|
67
68
|
len(self.modules_visited)
|
|
@@ -77,6 +78,38 @@ class RegistryPass(Pass):
|
|
|
77
78
|
)
|
|
78
79
|
scope = get_sem_scope(node)
|
|
79
80
|
seminfo = SemInfo(
|
|
81
|
+
node,
|
|
82
|
+
node.name.value,
|
|
83
|
+
extracted_type,
|
|
84
|
+
node.semstr.lit_value if node.semstr else "",
|
|
85
|
+
)
|
|
86
|
+
if len(self.modules_visited) and self.modules_visited[-1].registry:
|
|
87
|
+
self.modules_visited[-1].registry.add(scope, seminfo)
|
|
88
|
+
|
|
89
|
+
def exit_ability(self, node: ast.Ability) -> None:
|
|
90
|
+
"""Save ability information."""
|
|
91
|
+
scope = get_sem_scope(node)
|
|
92
|
+
seminfo = SemInfo(
|
|
93
|
+
node,
|
|
94
|
+
node.name_ref.sym_name,
|
|
95
|
+
"Ability",
|
|
96
|
+
node.semstr.lit_value if node.semstr else "",
|
|
97
|
+
)
|
|
98
|
+
if len(self.modules_visited) and self.modules_visited[-1].registry:
|
|
99
|
+
(
|
|
100
|
+
self.modules_visited[-1].registry.add(scope.parent, seminfo)
|
|
101
|
+
if scope.parent
|
|
102
|
+
else None
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def exit_param_var(self, node: ast.ParamVar) -> None:
|
|
106
|
+
"""Save param information."""
|
|
107
|
+
scope = get_sem_scope(node)
|
|
108
|
+
extracted_type = (
|
|
109
|
+
"".join(self.extract_type(node.type_tag.tag)) if node.type_tag else None
|
|
110
|
+
)
|
|
111
|
+
seminfo = SemInfo(
|
|
112
|
+
node,
|
|
80
113
|
node.name.value,
|
|
81
114
|
extracted_type,
|
|
82
115
|
node.semstr.lit_value if node.semstr else "",
|
|
@@ -94,6 +127,7 @@ class RegistryPass(Pass):
|
|
|
94
127
|
)
|
|
95
128
|
scope = get_sem_scope(node)
|
|
96
129
|
seminfo = SemInfo(
|
|
130
|
+
node,
|
|
97
131
|
(
|
|
98
132
|
node.target.items[0].value
|
|
99
133
|
if isinstance(node.target.items[0], ast.Name)
|
|
@@ -113,7 +147,7 @@ class RegistryPass(Pass):
|
|
|
113
147
|
and node.parent.parent.__class__.__name__ == "Enum"
|
|
114
148
|
):
|
|
115
149
|
scope = get_sem_scope(node)
|
|
116
|
-
seminfo = SemInfo(node.value, None, "")
|
|
150
|
+
seminfo = SemInfo(node, node.value, None, "")
|
|
117
151
|
if len(self.modules_visited) and self.modules_visited[-1].registry:
|
|
118
152
|
self.modules_visited[-1].registry.add(scope, seminfo)
|
|
119
153
|
|
|
@@ -193,7 +193,7 @@ class SymTabBuildPass(Pass):
|
|
|
193
193
|
if not node.is_absorb:
|
|
194
194
|
for i in node.items.items:
|
|
195
195
|
i.sym_tab.def_insert(i, single_decl="import item")
|
|
196
|
-
elif node.is_absorb and node.
|
|
196
|
+
elif node.is_absorb and node.is_jac:
|
|
197
197
|
source = node.items.items[0]
|
|
198
198
|
if not isinstance(source, ast.ModulePath) or not source.sub_module:
|
|
199
199
|
self.error(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Various tests for Jac passes."""
|
|
@@ -47,8 +47,12 @@ class ImportPassPassTests(TestCase):
|
|
|
47
47
|
state = jac_file_to_pass(
|
|
48
48
|
self.fixture_abs_path("incautoimpl.jac"), JacImportPass
|
|
49
49
|
)
|
|
50
|
+
count = 0
|
|
50
51
|
for i in state.ir.get_all_sub_nodes(ast.Module):
|
|
51
|
-
|
|
52
|
+
if i.name != "autoimpl":
|
|
53
|
+
count += 1
|
|
54
|
+
self.assertEqual(i.annexable_by, self.fixture_abs_path("autoimpl.jac"))
|
|
55
|
+
self.assertEqual(count, 3)
|
|
52
56
|
|
|
53
57
|
def test_py_resolve_list(self) -> None:
|
|
54
58
|
"""Basic test for pass."""
|
|
@@ -49,7 +49,14 @@ class JacTypeCheckPass(Pass):
|
|
|
49
49
|
"""Call mypy APIs to implement type checking in Jac."""
|
|
50
50
|
# Creating mypy api objects
|
|
51
51
|
options = myab.myb.Options()
|
|
52
|
+
options.ignore_missing_imports = True
|
|
52
53
|
options.cache_dir = Con.JAC_MYPY_CACHE
|
|
54
|
+
options.mypy_path = [
|
|
55
|
+
str(
|
|
56
|
+
pathlib.Path(os.path.dirname(__file__)).parent.parent.parent.parent
|
|
57
|
+
/ "stubs"
|
|
58
|
+
)
|
|
59
|
+
]
|
|
53
60
|
errors = myab.Errors(self, options)
|
|
54
61
|
fs_cache = myab.FileSystemCache()
|
|
55
62
|
search_paths = myab.compute_search_paths([], options, str(self.__path))
|
|
@@ -27,7 +27,12 @@ class FuseCommentsPass(Pass):
|
|
|
27
27
|
"""Insert comment tokens into all_tokens."""
|
|
28
28
|
comment_stream = iter(self.comments) # Iterator for comments
|
|
29
29
|
code_stream = iter(self.all_tokens) # Iterator for code tokens
|
|
30
|
-
new_stream: list[ast.
|
|
30
|
+
new_stream: list[ast.Token] = [] # New stream to hold ordered tokens
|
|
31
|
+
|
|
32
|
+
if not isinstance(self.ir, ast.Module):
|
|
33
|
+
raise self.ice(
|
|
34
|
+
f"FuseCommentsPass can only be run on a Module, not a {type(self.ir)}"
|
|
35
|
+
)
|
|
31
36
|
|
|
32
37
|
try:
|
|
33
38
|
next_comment = next(comment_stream) # Get the first comment
|
|
@@ -39,12 +44,20 @@ class FuseCommentsPass(Pass):
|
|
|
39
44
|
except StopIteration:
|
|
40
45
|
next_code = None
|
|
41
46
|
|
|
47
|
+
if next_comment and (not next_code or is_comment_next(next_comment, next_code)):
|
|
48
|
+
self.ir.terminals.insert(0, next_comment)
|
|
49
|
+
|
|
42
50
|
while next_comment or next_code:
|
|
43
51
|
if next_comment and (
|
|
44
52
|
not next_code or is_comment_next(next_comment, next_code)
|
|
45
53
|
):
|
|
46
54
|
# Add the comment to the new stream
|
|
55
|
+
last_tok = new_stream[-1] if len(new_stream) else None
|
|
47
56
|
new_stream.append(next_comment)
|
|
57
|
+
if last_tok:
|
|
58
|
+
self.ir.terminals.insert(
|
|
59
|
+
self.ir.terminals.index(last_tok) + 1, next_comment
|
|
60
|
+
)
|
|
48
61
|
try:
|
|
49
62
|
next_comment = next(comment_stream)
|
|
50
63
|
except StopIteration:
|
|
@@ -70,7 +83,6 @@ class FuseCommentsPass(Pass):
|
|
|
70
83
|
parent_kids.insert(insert_index, token)
|
|
71
84
|
prev_token.parent.set_kids(parent_kids)
|
|
72
85
|
else:
|
|
73
|
-
prev_token.pp()
|
|
74
86
|
raise self.ice(
|
|
75
87
|
"Token without parent in AST should be impossible"
|
|
76
88
|
)
|
|
@@ -10,6 +10,7 @@ import jaclang.compiler.absyntree as ast
|
|
|
10
10
|
from jaclang.compiler.absyntree import AstNode
|
|
11
11
|
from jaclang.compiler.constant import Tokens as Tok
|
|
12
12
|
from jaclang.compiler.passes import Pass
|
|
13
|
+
from jaclang.settings import settings
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class JacFormatPass(Pass):
|
|
@@ -20,20 +21,37 @@ class JacFormatPass(Pass):
|
|
|
20
21
|
self.comments: list[ast.CommentToken] = []
|
|
21
22
|
self.indent_size = 4
|
|
22
23
|
self.indent_level = 0
|
|
23
|
-
self.MAX_LINE_LENGTH =
|
|
24
|
+
self.MAX_LINE_LENGTH = int(float(settings.max_line_length) / 2)
|
|
24
25
|
|
|
25
26
|
def enter_node(self, node: ast.AstNode) -> None:
|
|
26
27
|
"""Enter node."""
|
|
27
28
|
node.gen.jac = ""
|
|
28
29
|
super().enter_node(node)
|
|
29
30
|
|
|
31
|
+
def token_before(self, node: ast.Token) -> Optional[ast.Token]:
|
|
32
|
+
"""Token before."""
|
|
33
|
+
if not isinstance(self.ir, ast.Module):
|
|
34
|
+
raise self.ice("IR must be module. Impossible")
|
|
35
|
+
if self.ir.terminals.index(node) == 0:
|
|
36
|
+
return None
|
|
37
|
+
return self.ir.terminals[self.ir.terminals.index(node) - 1]
|
|
38
|
+
|
|
39
|
+
def token_after(self, node: ast.Token) -> Optional[ast.Token]:
|
|
40
|
+
"""Token after."""
|
|
41
|
+
if not isinstance(self.ir, ast.Module):
|
|
42
|
+
raise self.ice("IR must be module. Impossible")
|
|
43
|
+
if self.ir.terminals.index(node) == len(self.ir.terminals) - 1:
|
|
44
|
+
return None
|
|
45
|
+
return self.ir.terminals[self.ir.terminals.index(node) + 1]
|
|
46
|
+
|
|
30
47
|
def indent_str(self) -> str:
|
|
31
48
|
"""Return string for indent."""
|
|
32
49
|
return " " * self.indent_size * self.indent_level
|
|
33
50
|
|
|
34
51
|
def emit(self, node: ast.AstNode, s: str, strip_mode: bool = True) -> None:
|
|
35
52
|
"""Emit code to node."""
|
|
36
|
-
|
|
53
|
+
indented_str = re.sub(r"\n(?!\n)", f"\n{self.indent_str()}", s)
|
|
54
|
+
node.gen.jac += self.indent_str() + indented_str
|
|
37
55
|
if "\n" in node.gen.jac:
|
|
38
56
|
if strip_mode:
|
|
39
57
|
node.gen.jac = node.gen.jac.rstrip(" ")
|
|
@@ -113,9 +131,15 @@ class JacFormatPass(Pass):
|
|
|
113
131
|
else:
|
|
114
132
|
if isinstance(last_element, ast.Import):
|
|
115
133
|
self.emit_ln(node, "")
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
if last_element and (
|
|
135
|
+
isinstance(i, ast.Architype)
|
|
136
|
+
and isinstance(last_element, ast.Architype)
|
|
137
|
+
and i.loc.first_line - last_element.loc.last_line == 2
|
|
138
|
+
and not node.gen.jac.endswith("\n\n")
|
|
139
|
+
):
|
|
118
140
|
self.emit_ln(node, "")
|
|
141
|
+
self.emit_ln(node, i.gen.jac)
|
|
142
|
+
|
|
119
143
|
if counter <= len(node.body) - 1:
|
|
120
144
|
if (
|
|
121
145
|
isinstance(i, ast.Ability)
|
|
@@ -126,6 +150,7 @@ class JacFormatPass(Pass):
|
|
|
126
150
|
and len(node.body[counter].kid[-1].kid) == 2
|
|
127
151
|
and len(node.body[counter - 1].kid[-1].kid) == 2
|
|
128
152
|
)
|
|
153
|
+
and node.gen.jac.endswith("\n")
|
|
129
154
|
):
|
|
130
155
|
self.emit(node, "")
|
|
131
156
|
else:
|
|
@@ -196,7 +221,7 @@ class JacFormatPass(Pass):
|
|
|
196
221
|
items: list[T],
|
|
197
222
|
"""
|
|
198
223
|
prev_token = None
|
|
199
|
-
for
|
|
224
|
+
for stmt in node.kid:
|
|
200
225
|
if isinstance(node.parent, (ast.EnumDef, ast.Enum)) and stmt.gen.jac == ",":
|
|
201
226
|
self.indent_level -= 1
|
|
202
227
|
self.emit_ln(node, f"{stmt.gen.jac}")
|
|
@@ -220,52 +245,20 @@ class JacFormatPass(Pass):
|
|
|
220
245
|
self.emit_ln(node, "")
|
|
221
246
|
self.indent_level += 1
|
|
222
247
|
if stmt.name == Tok.LBRACE:
|
|
223
|
-
|
|
224
|
-
if isinstance(next_kid, ast.CommentToken) and next_kid.is_inline:
|
|
225
|
-
self.emit(node, f" {stmt.value}")
|
|
226
|
-
else:
|
|
227
|
-
self.emit(node, f" {stmt.value}")
|
|
248
|
+
self.emit(node, f" {stmt.value}")
|
|
228
249
|
elif stmt.name == Tok.RBRACE:
|
|
229
|
-
|
|
230
|
-
self.indent_level -= 1
|
|
250
|
+
self.indent_level = max(0, self.indent_level - 1)
|
|
231
251
|
if stmt.parent and stmt.parent.gen.jac.strip() == "{":
|
|
232
|
-
self.emit_ln(node, stmt.gen.jac.strip())
|
|
233
|
-
elif (
|
|
234
|
-
stmt.parent
|
|
235
|
-
and stmt.parent.parent
|
|
236
|
-
and isinstance(
|
|
237
|
-
stmt.parent.parent,
|
|
238
|
-
(ast.ElseIf, ast.IfStmt, ast.IterForStmt, ast.TryStmt),
|
|
239
|
-
)
|
|
240
|
-
):
|
|
241
252
|
self.emit(node, f"{stmt.value}")
|
|
242
253
|
else:
|
|
243
|
-
|
|
244
|
-
node.kid[i + 1]
|
|
245
|
-
if i < (len(node.kid) - 1)
|
|
246
|
-
else ast.EmptyToken()
|
|
247
|
-
)
|
|
248
|
-
if (
|
|
249
|
-
isinstance(next_kid, ast.CommentToken)
|
|
250
|
-
and next_kid.is_inline
|
|
251
|
-
):
|
|
252
|
-
self.emit(node, f" {stmt.value}")
|
|
253
|
-
elif not (node.gen.jac).endswith("\n"):
|
|
254
|
-
self.indent_level -= 1
|
|
254
|
+
if not node.gen.jac.endswith("\n"):
|
|
255
255
|
self.emit_ln(node, "")
|
|
256
|
-
|
|
257
|
-
self.emit(node, f"{stmt.value}")
|
|
258
|
-
else:
|
|
259
|
-
self.emit(node, f"{stmt.value}")
|
|
256
|
+
self.emit(node, f"{stmt.value}")
|
|
260
257
|
elif isinstance(stmt, ast.CommentToken):
|
|
261
258
|
if stmt.is_inline:
|
|
262
259
|
if isinstance(prev_token, ast.Semi) or (
|
|
263
260
|
isinstance(prev_token, ast.Token)
|
|
264
|
-
and prev_token.name
|
|
265
|
-
in [
|
|
266
|
-
Tok.LBRACE,
|
|
267
|
-
Tok.RBRACE,
|
|
268
|
-
]
|
|
261
|
+
and prev_token.name in [Tok.LBRACE, Tok.RBRACE]
|
|
269
262
|
):
|
|
270
263
|
self.indent_level -= 1
|
|
271
264
|
self.emit(node, f" {stmt.gen.jac}")
|
|
@@ -289,48 +282,33 @@ class JacFormatPass(Pass):
|
|
|
289
282
|
self.emit(node, stmt.gen.jac)
|
|
290
283
|
if not stmt.gen.jac.endswith("postinit;"):
|
|
291
284
|
self.indent_level -= 1
|
|
285
|
+
self.emit_ln(stmt, "")
|
|
292
286
|
self.emit_ln(node, "")
|
|
293
287
|
self.indent_level += 1
|
|
294
288
|
elif stmt.gen.jac == ",":
|
|
295
289
|
self.emit(node, f"{stmt.value} ")
|
|
296
290
|
elif stmt.value == "=":
|
|
297
291
|
self.emit(node, f" {stmt.value} ")
|
|
292
|
+
elif prev_token and prev_token.gen.jac.strip() == "@":
|
|
293
|
+
self.emit_ln(node, stmt.value)
|
|
298
294
|
else:
|
|
299
|
-
self.emit(node, f"{stmt.
|
|
295
|
+
self.emit(node, f"{stmt.gen.jac}")
|
|
300
296
|
prev_token = stmt
|
|
301
297
|
continue
|
|
302
298
|
elif isinstance(stmt, ast.Semi):
|
|
303
299
|
self.emit(node, stmt.gen.jac)
|
|
304
|
-
elif
|
|
305
|
-
|
|
300
|
+
elif (
|
|
301
|
+
isinstance(prev_token, (ast.HasVar, ast.ArchHas))
|
|
302
|
+
and not isinstance(stmt, (ast.HasVar, ast.ArchHas))
|
|
303
|
+
) or (
|
|
304
|
+
isinstance(prev_token, ast.Ability)
|
|
305
|
+
and isinstance(stmt, (ast.Ability, ast.AbilityDef))
|
|
306
306
|
):
|
|
307
307
|
if not isinstance(prev_token.kid[-1], ast.CommentToken):
|
|
308
308
|
self.indent_level -= 1
|
|
309
309
|
self.emit_ln(node, "")
|
|
310
310
|
self.indent_level += 1
|
|
311
311
|
self.emit(node, stmt.gen.jac)
|
|
312
|
-
elif isinstance(prev_token, ast.Ability) and isinstance(
|
|
313
|
-
stmt, (ast.Ability, ast.AbilityDef)
|
|
314
|
-
):
|
|
315
|
-
if not isinstance(prev_token.kid[-1], ast.CommentToken) and (
|
|
316
|
-
stmt.body and not isinstance(stmt.body, ast.FuncCall)
|
|
317
|
-
):
|
|
318
|
-
self.indent_level -= 1
|
|
319
|
-
self.emit_ln(node, "")
|
|
320
|
-
self.indent_level += 1
|
|
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}")
|
|
334
312
|
else:
|
|
335
313
|
if prev_token and prev_token.gen.jac.strip() == "{":
|
|
336
314
|
self.emit_ln(node, "")
|
|
@@ -755,7 +733,7 @@ class JacFormatPass(Pass):
|
|
|
755
733
|
self.indent_level += indent_val
|
|
756
734
|
indented = True
|
|
757
735
|
else:
|
|
758
|
-
self.emit(node,
|
|
736
|
+
self.emit(node, j.gen.jac.lstrip())
|
|
759
737
|
if indented:
|
|
760
738
|
self.indent_level -= indent_val
|
|
761
739
|
else:
|
|
@@ -921,6 +899,8 @@ class JacFormatPass(Pass):
|
|
|
921
899
|
"""Check if the length of the current generated code exceeds the max line length."""
|
|
922
900
|
if max_line_length == 0:
|
|
923
901
|
max_line_length = self.MAX_LINE_LENGTH
|
|
902
|
+
# print(content)
|
|
903
|
+
# print(len(content))
|
|
924
904
|
return len(content) > max_line_length
|
|
925
905
|
|
|
926
906
|
def exit_binary_expr(self, node: ast.BinaryExpr) -> None:
|
|
@@ -970,6 +950,7 @@ class JacFormatPass(Pass):
|
|
|
970
950
|
self.error(
|
|
971
951
|
f"Binary operator {node.op.value} not supported in bootstrap Jac"
|
|
972
952
|
)
|
|
953
|
+
# print(node.gen)
|
|
973
954
|
if isinstance(
|
|
974
955
|
node.kid[-1], (ast.Semi, ast.CommentToken)
|
|
975
956
|
) and not node.gen.jac.endswith("\n"):
|
|
@@ -1102,6 +1083,9 @@ class JacFormatPass(Pass):
|
|
|
1102
1083
|
if isinstance(i, ast.CommentToken):
|
|
1103
1084
|
if i.is_inline:
|
|
1104
1085
|
self.emit(node, f" {i.gen.jac}")
|
|
1086
|
+
elif (tok := self.token_before(i)) and (i.line_no - tok.line_no == 1):
|
|
1087
|
+
self.emit_ln(node, "")
|
|
1088
|
+
self.emit(node, i.gen.jac)
|
|
1105
1089
|
else:
|
|
1106
1090
|
self.emit_ln(node, "")
|
|
1107
1091
|
self.emit_ln(node, "")
|
|
@@ -1332,38 +1316,96 @@ class JacFormatPass(Pass):
|
|
|
1332
1316
|
if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):
|
|
1333
1317
|
self.emit_ln(node, "")
|
|
1334
1318
|
|
|
1319
|
+
def handle_long_assignment(self, node: ast.Assignment, kid: ast.AstNode) -> None:
|
|
1320
|
+
"""Handle long assignment lines."""
|
|
1321
|
+
parts = re.split(r"(=)", kid.gen.jac)
|
|
1322
|
+
first_part = parts.pop(0).strip()
|
|
1323
|
+
self.emit_ln(
|
|
1324
|
+
node, f"{first_part} {parts.pop(0).strip()} {parts.pop(0).strip()}"
|
|
1325
|
+
)
|
|
1326
|
+
for j in range(0, len(parts) - 1, 2):
|
|
1327
|
+
op = parts[j]
|
|
1328
|
+
var = parts[j + 1].strip() if j + 1 < len(parts) else ""
|
|
1329
|
+
if var:
|
|
1330
|
+
self.indent_level += 1
|
|
1331
|
+
self.emit(node, f"{op} {var}")
|
|
1332
|
+
self.indent_level -= 1
|
|
1333
|
+
self.emit_ln(node, "")
|
|
1334
|
+
else:
|
|
1335
|
+
self.indent_level += 1
|
|
1336
|
+
self.emit(node, op)
|
|
1337
|
+
self.indent_level -= 1
|
|
1338
|
+
|
|
1339
|
+
def handle_long_expression(self, node: ast.AstNode, kid: ast.AstNode) -> None:
|
|
1340
|
+
"""Handle long expressions with multiple operators."""
|
|
1341
|
+
parts = re.split(r"(\+|\-|\*|\/)", kid.gen.jac)
|
|
1342
|
+
self.emit_ln(node, f"{parts.pop(0).strip()}")
|
|
1343
|
+
for j in range(0, len(parts) - 1, 2):
|
|
1344
|
+
op = parts[j]
|
|
1345
|
+
var = parts[j + 1].strip() if j + 1 < len(parts) else ""
|
|
1346
|
+
if j < len(parts) - 2:
|
|
1347
|
+
self.indent_level += 1
|
|
1348
|
+
self.emit(node, f"{op} {var}")
|
|
1349
|
+
self.indent_level -= 1
|
|
1350
|
+
self.emit_ln(node, "")
|
|
1351
|
+
else:
|
|
1352
|
+
self.indent_level += 1
|
|
1353
|
+
self.emit(node, f"{op} {var}")
|
|
1354
|
+
self.indent_level -= 1
|
|
1355
|
+
|
|
1335
1356
|
def exit_assignment(self, node: ast.Assignment) -> None:
|
|
1336
1357
|
"""Sub objects.
|
|
1337
1358
|
|
|
1338
|
-
target: SubNodeList[
|
|
1339
|
-
value: Optional[
|
|
1340
|
-
type_tag: Optional[SubTag[
|
|
1359
|
+
target: SubNodeList[Expr],
|
|
1360
|
+
value: Optional[Expr | YieldExpr],
|
|
1361
|
+
type_tag: Optional[SubTag[Expr]],
|
|
1341
1362
|
mutable: bool = True,
|
|
1342
|
-
aug_op: Optional[Token] = None
|
|
1363
|
+
aug_op: Optional[Token] = None,
|
|
1364
|
+
semstr: Optional[String] = None,
|
|
1365
|
+
is_enum_stmt: bool = False,
|
|
1343
1366
|
"""
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1367
|
+
prev_token = None
|
|
1368
|
+
for kid in node.kid:
|
|
1369
|
+
if isinstance(kid, ast.CommentToken):
|
|
1370
|
+
if kid.is_inline:
|
|
1371
|
+
self.emit(node, kid.gen.jac)
|
|
1348
1372
|
else:
|
|
1349
|
-
if
|
|
1373
|
+
if kid.gen.jac not in [
|
|
1350
1374
|
"# Update any new user level buddy schedule",
|
|
1351
1375
|
"# Construct prompt here",
|
|
1352
1376
|
]:
|
|
1353
1377
|
self.emit_ln(node, "")
|
|
1354
1378
|
self.emit_ln(node, "")
|
|
1355
|
-
self.emit_ln(node,
|
|
1379
|
+
self.emit_ln(node, kid.gen.jac)
|
|
1356
1380
|
else:
|
|
1357
1381
|
self.emit_ln(node, "")
|
|
1358
|
-
self.emit(node,
|
|
1359
|
-
elif isinstance(
|
|
1360
|
-
|
|
1382
|
+
self.emit(node, kid.gen.jac)
|
|
1383
|
+
elif isinstance(kid, ast.Token) and (
|
|
1384
|
+
kid.name == Tok.KW_LET or kid.gen.jac == ":"
|
|
1361
1385
|
):
|
|
1362
|
-
self.emit(node, f"{
|
|
1363
|
-
elif isinstance(
|
|
1364
|
-
self.emit(node, f" {
|
|
1386
|
+
self.emit(node, f"{kid.gen.jac} ")
|
|
1387
|
+
elif isinstance(kid, ast.Token) and "=" in kid.gen.jac:
|
|
1388
|
+
self.emit(node, f" {kid.gen.jac} ")
|
|
1389
|
+
elif (
|
|
1390
|
+
"=" in kid.gen.jac
|
|
1391
|
+
and self.is_line_break_needed(
|
|
1392
|
+
kid.gen.jac, max_line_length=self.MAX_LINE_LENGTH * 2
|
|
1393
|
+
)
|
|
1394
|
+
and "\n" not in kid.gen.jac
|
|
1395
|
+
):
|
|
1396
|
+
self.handle_long_assignment(node, kid)
|
|
1397
|
+
elif (
|
|
1398
|
+
prev_token
|
|
1399
|
+
and "=" in prev_token.gen.jac
|
|
1400
|
+
and self.is_line_break_needed(
|
|
1401
|
+
kid.gen.jac, max_line_length=self.MAX_LINE_LENGTH * 2
|
|
1402
|
+
)
|
|
1403
|
+
and "\n" not in kid.gen.jac
|
|
1404
|
+
):
|
|
1405
|
+
self.handle_long_expression(node, kid)
|
|
1365
1406
|
else:
|
|
1366
|
-
self.emit(node,
|
|
1407
|
+
self.emit(node, kid.gen.jac)
|
|
1408
|
+
prev_token = kid
|
|
1367
1409
|
if isinstance(
|
|
1368
1410
|
node.kid[-1], (ast.Semi, ast.CommentToken)
|
|
1369
1411
|
) and not node.gen.jac.endswith("\n"):
|
|
@@ -1392,8 +1434,12 @@ class JacFormatPass(Pass):
|
|
|
1392
1434
|
self.emit(node, i.gen.jac)
|
|
1393
1435
|
if isinstance(prev_token, ast.Semi):
|
|
1394
1436
|
self.emit_ln(node, "")
|
|
1437
|
+
elif (tok := self.token_before(i)) and (i.line_no - tok.line_no > 1):
|
|
1438
|
+
self.emit_ln(node, "")
|
|
1439
|
+
self.emit_ln(node, i.gen.jac)
|
|
1395
1440
|
else:
|
|
1396
1441
|
self.emit_ln(node, i.gen.jac)
|
|
1442
|
+
self.emit_ln(node, "")
|
|
1397
1443
|
elif isinstance(i, ast.Semi):
|
|
1398
1444
|
self.emit(node, f"{i.gen.jac} ")
|
|
1399
1445
|
elif isinstance(i, ast.SubNodeList) and i.gen.jac.startswith("@"):
|
|
@@ -2374,7 +2420,7 @@ class JacFormatPass(Pass):
|
|
|
2374
2420
|
"""
|
|
2375
2421
|
self.emit(node, f"<>{node.value}" if node.is_kwesc else node.value)
|
|
2376
2422
|
|
|
2377
|
-
def
|
|
2423
|
+
def exit_float(self, node: ast.Float) -> None:
|
|
2378
2424
|
"""Sub objects.
|
|
2379
2425
|
|
|
2380
2426
|
name: str,
|
|
@@ -2387,7 +2433,7 @@ class JacFormatPass(Pass):
|
|
|
2387
2433
|
"""
|
|
2388
2434
|
self.emit(node, node.value)
|
|
2389
2435
|
|
|
2390
|
-
def
|
|
2436
|
+
def exit_int(self, node: ast.Int) -> None:
|
|
2391
2437
|
"""Sub objects.
|
|
2392
2438
|
|
|
2393
2439
|
name: str,
|
|
@@ -2400,7 +2446,7 @@ class JacFormatPass(Pass):
|
|
|
2400
2446
|
"""
|
|
2401
2447
|
self.emit(node, node.value)
|
|
2402
2448
|
|
|
2403
|
-
def
|
|
2449
|
+
def exit_string(self, node: ast.String) -> None:
|
|
2404
2450
|
"""Sub objects.
|
|
2405
2451
|
|
|
2406
2452
|
name: str,
|
|
@@ -2412,7 +2458,11 @@ class JacFormatPass(Pass):
|
|
|
2412
2458
|
pos_end: int,
|
|
2413
2459
|
"""
|
|
2414
2460
|
# if string is in docstring format and spans multiple lines turn into the multiple single quoted strings
|
|
2415
|
-
if "\n" in node.value and
|
|
2461
|
+
if "\n" in node.value and (
|
|
2462
|
+
node.parent
|
|
2463
|
+
and isinstance(node.parent, ast.Expr)
|
|
2464
|
+
and not isinstance(node.parent, ast.MultiString)
|
|
2465
|
+
):
|
|
2416
2466
|
string_type = node.value[0:3]
|
|
2417
2467
|
pure_string = node.value[3:-3]
|
|
2418
2468
|
lines = pure_string.split("\n")
|
|
@@ -2430,14 +2480,14 @@ class JacFormatPass(Pass):
|
|
|
2430
2480
|
string_type = node.value[0:3]
|
|
2431
2481
|
pure_string = node.value[3:-3]
|
|
2432
2482
|
lines = pure_string.split("\n")
|
|
2433
|
-
self.
|
|
2434
|
-
for line in lines[:-1]:
|
|
2435
|
-
self.emit_ln(node, line)
|
|
2436
|
-
self.
|
|
2483
|
+
self.emit_ln(node, f"{string_type}{lines[0].lstrip()}")
|
|
2484
|
+
for line in lines[1:-1]:
|
|
2485
|
+
self.emit_ln(node, line.lstrip())
|
|
2486
|
+
self.emit(node, f"{lines[-1].lstrip()}{string_type}")
|
|
2437
2487
|
else:
|
|
2438
2488
|
self.emit(node, node.value)
|
|
2439
2489
|
|
|
2440
|
-
def
|
|
2490
|
+
def exit_bool(self, node: ast.Bool) -> None:
|
|
2441
2491
|
"""Sub objects.
|
|
2442
2492
|
|
|
2443
2493
|
name: str,
|