jaclang 0.7.14__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 +86 -13
- jaclang/compiler/jac.lark +4 -3
- jaclang/compiler/parser.py +31 -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 +18 -23
- jaclang/compiler/passes/main/pyast_gen_pass.py +307 -559
- jaclang/compiler/passes/main/pyast_load_pass.py +32 -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/type_check_pass.py +7 -0
- jaclang/compiler/passes/tool/jac_formatter_pass.py +124 -86
- 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 +65 -118
- 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 +72 -16
- jaclang/langserve/utils.py +163 -96
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +212 -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/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 +74 -7
- 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.14.dist-info → jaclang-0.7.16.dist-info}/METADATA +3 -2
- {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/RECORD +89 -74
- 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.14.dist-info → jaclang-0.7.16.dist-info}/WHEEL +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/entry_points.txt +0 -0
|
@@ -144,12 +144,15 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
144
144
|
if sys.version_info >= (3, 12):
|
|
145
145
|
type_params: list[type_param]
|
|
146
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}"
|
|
147
152
|
name = ast.Name(
|
|
148
153
|
file_path=self.mod_path,
|
|
149
154
|
name=Tok.NAME,
|
|
150
|
-
value=
|
|
151
|
-
node.name if node.name != "root" else "root_"
|
|
152
|
-
), # root is a reserved keyword
|
|
155
|
+
value=value,
|
|
153
156
|
line=node.lineno,
|
|
154
157
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
155
158
|
col_start=node.col_offset,
|
|
@@ -1875,10 +1878,19 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1875
1878
|
id: _Identifier
|
|
1876
1879
|
ctx: expr_context
|
|
1877
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}"
|
|
1878
1890
|
ret = ast.Name(
|
|
1879
1891
|
file_path=self.mod_path,
|
|
1880
1892
|
name=Tok.NAME,
|
|
1881
|
-
value=
|
|
1893
|
+
value=value,
|
|
1882
1894
|
line=node.lineno,
|
|
1883
1895
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
1884
1896
|
col_start=node.col_offset,
|
|
@@ -1913,13 +1925,18 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1913
1925
|
class Nonlocal(stmt):
|
|
1914
1926
|
names: list[_Identifier]
|
|
1915
1927
|
"""
|
|
1928
|
+
from jaclang.compiler import TOKEN_MAP
|
|
1929
|
+
|
|
1930
|
+
reserved_keywords = [v for _, v in TOKEN_MAP.items()]
|
|
1931
|
+
|
|
1916
1932
|
names: list[ast.NameAtom] = []
|
|
1917
1933
|
for name in node.names:
|
|
1934
|
+
value = name if name not in reserved_keywords else f"<>{name}"
|
|
1918
1935
|
names.append(
|
|
1919
1936
|
ast.Name(
|
|
1920
1937
|
file_path=self.mod_path,
|
|
1921
1938
|
name=Tok.NAME,
|
|
1922
|
-
value=
|
|
1939
|
+
value=value,
|
|
1923
1940
|
line=node.lineno,
|
|
1924
1941
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
1925
1942
|
col_start=node.col_offset,
|
|
@@ -2238,10 +2255,19 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2238
2255
|
arg: _Identifier
|
|
2239
2256
|
annotation: expr | None
|
|
2240
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}"
|
|
2241
2267
|
name = ast.Name(
|
|
2242
2268
|
file_path=self.mod_path,
|
|
2243
2269
|
name=Tok.NAME,
|
|
2244
|
-
value=
|
|
2270
|
+
value=value,
|
|
2245
2271
|
line=node.lineno,
|
|
2246
2272
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
2247
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."""
|
|
@@ -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))
|
|
@@ -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,7 +21,7 @@ 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."""
|
|
@@ -49,7 +50,8 @@ class JacFormatPass(Pass):
|
|
|
49
50
|
|
|
50
51
|
def emit(self, node: ast.AstNode, s: str, strip_mode: bool = True) -> None:
|
|
51
52
|
"""Emit code to node."""
|
|
52
|
-
|
|
53
|
+
indented_str = re.sub(r"\n(?!\n)", f"\n{self.indent_str()}", s)
|
|
54
|
+
node.gen.jac += self.indent_str() + indented_str
|
|
53
55
|
if "\n" in node.gen.jac:
|
|
54
56
|
if strip_mode:
|
|
55
57
|
node.gen.jac = node.gen.jac.rstrip(" ")
|
|
@@ -129,9 +131,15 @@ class JacFormatPass(Pass):
|
|
|
129
131
|
else:
|
|
130
132
|
if isinstance(last_element, ast.Import):
|
|
131
133
|
self.emit_ln(node, "")
|
|
132
|
-
|
|
133
|
-
|
|
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
|
+
):
|
|
134
140
|
self.emit_ln(node, "")
|
|
141
|
+
self.emit_ln(node, i.gen.jac)
|
|
142
|
+
|
|
135
143
|
if counter <= len(node.body) - 1:
|
|
136
144
|
if (
|
|
137
145
|
isinstance(i, ast.Ability)
|
|
@@ -142,6 +150,7 @@ class JacFormatPass(Pass):
|
|
|
142
150
|
and len(node.body[counter].kid[-1].kid) == 2
|
|
143
151
|
and len(node.body[counter - 1].kid[-1].kid) == 2
|
|
144
152
|
)
|
|
153
|
+
and node.gen.jac.endswith("\n")
|
|
145
154
|
):
|
|
146
155
|
self.emit(node, "")
|
|
147
156
|
else:
|
|
@@ -212,7 +221,7 @@ class JacFormatPass(Pass):
|
|
|
212
221
|
items: list[T],
|
|
213
222
|
"""
|
|
214
223
|
prev_token = None
|
|
215
|
-
for
|
|
224
|
+
for stmt in node.kid:
|
|
216
225
|
if isinstance(node.parent, (ast.EnumDef, ast.Enum)) and stmt.gen.jac == ",":
|
|
217
226
|
self.indent_level -= 1
|
|
218
227
|
self.emit_ln(node, f"{stmt.gen.jac}")
|
|
@@ -238,42 +247,18 @@ class JacFormatPass(Pass):
|
|
|
238
247
|
if stmt.name == Tok.LBRACE:
|
|
239
248
|
self.emit(node, f" {stmt.value}")
|
|
240
249
|
elif stmt.name == Tok.RBRACE:
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (stmt.parent and stmt.parent.gen.jac.strip() == "{") or (
|
|
244
|
-
stmt.parent
|
|
245
|
-
and stmt.parent.parent
|
|
246
|
-
and isinstance(
|
|
247
|
-
stmt.parent.parent,
|
|
248
|
-
(ast.ElseIf, ast.IfStmt, ast.IterForStmt, ast.TryStmt),
|
|
249
|
-
)
|
|
250
|
-
):
|
|
250
|
+
self.indent_level = max(0, self.indent_level - 1)
|
|
251
|
+
if stmt.parent and stmt.parent.gen.jac.strip() == "{":
|
|
251
252
|
self.emit(node, f"{stmt.value}")
|
|
252
253
|
else:
|
|
253
|
-
|
|
254
|
-
node.kid[i + 1]
|
|
255
|
-
if i < (len(node.kid) - 1)
|
|
256
|
-
else ast.EmptyToken()
|
|
257
|
-
)
|
|
258
|
-
if (
|
|
259
|
-
isinstance(next_kid, ast.CommentToken)
|
|
260
|
-
and next_kid.is_inline
|
|
261
|
-
):
|
|
262
|
-
self.emit(node, f" {stmt.value}")
|
|
263
|
-
elif not (node.gen.jac).endswith("\n"):
|
|
254
|
+
if not node.gen.jac.endswith("\n"):
|
|
264
255
|
self.emit_ln(node, "")
|
|
265
|
-
|
|
266
|
-
else:
|
|
267
|
-
self.emit(node, f"{stmt.value}")
|
|
256
|
+
self.emit(node, f"{stmt.value}")
|
|
268
257
|
elif isinstance(stmt, ast.CommentToken):
|
|
269
258
|
if stmt.is_inline:
|
|
270
259
|
if isinstance(prev_token, ast.Semi) or (
|
|
271
260
|
isinstance(prev_token, ast.Token)
|
|
272
|
-
and prev_token.name
|
|
273
|
-
in [
|
|
274
|
-
Tok.LBRACE,
|
|
275
|
-
Tok.RBRACE,
|
|
276
|
-
]
|
|
261
|
+
and prev_token.name in [Tok.LBRACE, Tok.RBRACE]
|
|
277
262
|
):
|
|
278
263
|
self.indent_level -= 1
|
|
279
264
|
self.emit(node, f" {stmt.gen.jac}")
|
|
@@ -297,48 +282,33 @@ class JacFormatPass(Pass):
|
|
|
297
282
|
self.emit(node, stmt.gen.jac)
|
|
298
283
|
if not stmt.gen.jac.endswith("postinit;"):
|
|
299
284
|
self.indent_level -= 1
|
|
285
|
+
self.emit_ln(stmt, "")
|
|
300
286
|
self.emit_ln(node, "")
|
|
301
287
|
self.indent_level += 1
|
|
302
288
|
elif stmt.gen.jac == ",":
|
|
303
289
|
self.emit(node, f"{stmt.value} ")
|
|
304
290
|
elif stmt.value == "=":
|
|
305
291
|
self.emit(node, f" {stmt.value} ")
|
|
292
|
+
elif prev_token and prev_token.gen.jac.strip() == "@":
|
|
293
|
+
self.emit_ln(node, stmt.value)
|
|
306
294
|
else:
|
|
307
|
-
self.emit(node, f"{stmt.
|
|
295
|
+
self.emit(node, f"{stmt.gen.jac}")
|
|
308
296
|
prev_token = stmt
|
|
309
297
|
continue
|
|
310
298
|
elif isinstance(stmt, ast.Semi):
|
|
311
299
|
self.emit(node, stmt.gen.jac)
|
|
312
|
-
elif
|
|
313
|
-
|
|
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))
|
|
314
306
|
):
|
|
315
307
|
if not isinstance(prev_token.kid[-1], ast.CommentToken):
|
|
316
308
|
self.indent_level -= 1
|
|
317
309
|
self.emit_ln(node, "")
|
|
318
310
|
self.indent_level += 1
|
|
319
311
|
self.emit(node, stmt.gen.jac)
|
|
320
|
-
elif isinstance(prev_token, ast.Ability) and isinstance(
|
|
321
|
-
stmt, (ast.Ability, ast.AbilityDef)
|
|
322
|
-
):
|
|
323
|
-
if not isinstance(prev_token.kid[-1], ast.CommentToken) and (
|
|
324
|
-
stmt.body and not isinstance(stmt.body, ast.FuncCall)
|
|
325
|
-
):
|
|
326
|
-
self.indent_level -= 1
|
|
327
|
-
self.emit_ln(node, "")
|
|
328
|
-
self.indent_level += 1
|
|
329
|
-
self.emit(node, f"{stmt.gen.jac}")
|
|
330
|
-
elif stmt.body and isinstance(
|
|
331
|
-
stmt.body, (ast.FuncCall, ast.EventSignature)
|
|
332
|
-
):
|
|
333
|
-
self.indent_level -= 1
|
|
334
|
-
self.emit_ln(node, "")
|
|
335
|
-
self.indent_level += 1
|
|
336
|
-
self.emit(node, stmt.gen.jac)
|
|
337
|
-
else:
|
|
338
|
-
self.indent_level -= 1
|
|
339
|
-
self.emit_ln(node, "")
|
|
340
|
-
self.indent_level += 1
|
|
341
|
-
self.emit(node, f"{stmt.gen.jac}")
|
|
342
312
|
else:
|
|
343
313
|
if prev_token and prev_token.gen.jac.strip() == "{":
|
|
344
314
|
self.emit_ln(node, "")
|
|
@@ -763,7 +733,7 @@ class JacFormatPass(Pass):
|
|
|
763
733
|
self.indent_level += indent_val
|
|
764
734
|
indented = True
|
|
765
735
|
else:
|
|
766
|
-
self.emit(node,
|
|
736
|
+
self.emit(node, j.gen.jac.lstrip())
|
|
767
737
|
if indented:
|
|
768
738
|
self.indent_level -= indent_val
|
|
769
739
|
else:
|
|
@@ -929,6 +899,8 @@ class JacFormatPass(Pass):
|
|
|
929
899
|
"""Check if the length of the current generated code exceeds the max line length."""
|
|
930
900
|
if max_line_length == 0:
|
|
931
901
|
max_line_length = self.MAX_LINE_LENGTH
|
|
902
|
+
# print(content)
|
|
903
|
+
# print(len(content))
|
|
932
904
|
return len(content) > max_line_length
|
|
933
905
|
|
|
934
906
|
def exit_binary_expr(self, node: ast.BinaryExpr) -> None:
|
|
@@ -978,6 +950,7 @@ class JacFormatPass(Pass):
|
|
|
978
950
|
self.error(
|
|
979
951
|
f"Binary operator {node.op.value} not supported in bootstrap Jac"
|
|
980
952
|
)
|
|
953
|
+
# print(node.gen)
|
|
981
954
|
if isinstance(
|
|
982
955
|
node.kid[-1], (ast.Semi, ast.CommentToken)
|
|
983
956
|
) and not node.gen.jac.endswith("\n"):
|
|
@@ -1110,6 +1083,9 @@ class JacFormatPass(Pass):
|
|
|
1110
1083
|
if isinstance(i, ast.CommentToken):
|
|
1111
1084
|
if i.is_inline:
|
|
1112
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)
|
|
1113
1089
|
else:
|
|
1114
1090
|
self.emit_ln(node, "")
|
|
1115
1091
|
self.emit_ln(node, "")
|
|
@@ -1340,38 +1316,96 @@ class JacFormatPass(Pass):
|
|
|
1340
1316
|
if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):
|
|
1341
1317
|
self.emit_ln(node, "")
|
|
1342
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
|
+
|
|
1343
1356
|
def exit_assignment(self, node: ast.Assignment) -> None:
|
|
1344
1357
|
"""Sub objects.
|
|
1345
1358
|
|
|
1346
|
-
target: SubNodeList[
|
|
1347
|
-
value: Optional[
|
|
1348
|
-
type_tag: Optional[SubTag[
|
|
1359
|
+
target: SubNodeList[Expr],
|
|
1360
|
+
value: Optional[Expr | YieldExpr],
|
|
1361
|
+
type_tag: Optional[SubTag[Expr]],
|
|
1349
1362
|
mutable: bool = True,
|
|
1350
|
-
aug_op: Optional[Token] = None
|
|
1363
|
+
aug_op: Optional[Token] = None,
|
|
1364
|
+
semstr: Optional[String] = None,
|
|
1365
|
+
is_enum_stmt: bool = False,
|
|
1351
1366
|
"""
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
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)
|
|
1356
1372
|
else:
|
|
1357
|
-
if
|
|
1373
|
+
if kid.gen.jac not in [
|
|
1358
1374
|
"# Update any new user level buddy schedule",
|
|
1359
1375
|
"# Construct prompt here",
|
|
1360
1376
|
]:
|
|
1361
1377
|
self.emit_ln(node, "")
|
|
1362
1378
|
self.emit_ln(node, "")
|
|
1363
|
-
self.emit_ln(node,
|
|
1379
|
+
self.emit_ln(node, kid.gen.jac)
|
|
1364
1380
|
else:
|
|
1365
1381
|
self.emit_ln(node, "")
|
|
1366
|
-
self.emit(node,
|
|
1367
|
-
elif isinstance(
|
|
1368
|
-
|
|
1382
|
+
self.emit(node, kid.gen.jac)
|
|
1383
|
+
elif isinstance(kid, ast.Token) and (
|
|
1384
|
+
kid.name == Tok.KW_LET or kid.gen.jac == ":"
|
|
1369
1385
|
):
|
|
1370
|
-
self.emit(node, f"{
|
|
1371
|
-
elif isinstance(
|
|
1372
|
-
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)
|
|
1373
1406
|
else:
|
|
1374
|
-
self.emit(node,
|
|
1407
|
+
self.emit(node, kid.gen.jac)
|
|
1408
|
+
prev_token = kid
|
|
1375
1409
|
if isinstance(
|
|
1376
1410
|
node.kid[-1], (ast.Semi, ast.CommentToken)
|
|
1377
1411
|
) and not node.gen.jac.endswith("\n"):
|
|
@@ -2386,7 +2420,7 @@ class JacFormatPass(Pass):
|
|
|
2386
2420
|
"""
|
|
2387
2421
|
self.emit(node, f"<>{node.value}" if node.is_kwesc else node.value)
|
|
2388
2422
|
|
|
2389
|
-
def
|
|
2423
|
+
def exit_float(self, node: ast.Float) -> None:
|
|
2390
2424
|
"""Sub objects.
|
|
2391
2425
|
|
|
2392
2426
|
name: str,
|
|
@@ -2399,7 +2433,7 @@ class JacFormatPass(Pass):
|
|
|
2399
2433
|
"""
|
|
2400
2434
|
self.emit(node, node.value)
|
|
2401
2435
|
|
|
2402
|
-
def
|
|
2436
|
+
def exit_int(self, node: ast.Int) -> None:
|
|
2403
2437
|
"""Sub objects.
|
|
2404
2438
|
|
|
2405
2439
|
name: str,
|
|
@@ -2412,7 +2446,7 @@ class JacFormatPass(Pass):
|
|
|
2412
2446
|
"""
|
|
2413
2447
|
self.emit(node, node.value)
|
|
2414
2448
|
|
|
2415
|
-
def
|
|
2449
|
+
def exit_string(self, node: ast.String) -> None:
|
|
2416
2450
|
"""Sub objects.
|
|
2417
2451
|
|
|
2418
2452
|
name: str,
|
|
@@ -2424,7 +2458,11 @@ class JacFormatPass(Pass):
|
|
|
2424
2458
|
pos_end: int,
|
|
2425
2459
|
"""
|
|
2426
2460
|
# if string is in docstring format and spans multiple lines turn into the multiple single quoted strings
|
|
2427
|
-
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
|
+
):
|
|
2428
2466
|
string_type = node.value[0:3]
|
|
2429
2467
|
pure_string = node.value[3:-3]
|
|
2430
2468
|
lines = pure_string.split("\n")
|
|
@@ -2442,14 +2480,14 @@ class JacFormatPass(Pass):
|
|
|
2442
2480
|
string_type = node.value[0:3]
|
|
2443
2481
|
pure_string = node.value[3:-3]
|
|
2444
2482
|
lines = pure_string.split("\n")
|
|
2445
|
-
self.
|
|
2446
|
-
for line in lines[:-1]:
|
|
2447
|
-
self.emit_ln(node, line)
|
|
2448
|
-
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}")
|
|
2449
2487
|
else:
|
|
2450
2488
|
self.emit(node, node.value)
|
|
2451
2489
|
|
|
2452
|
-
def
|
|
2490
|
+
def exit_bool(self, node: ast.Bool) -> None:
|
|
2453
2491
|
"""Sub objects.
|
|
2454
2492
|
|
|
2455
2493
|
name: str,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
obj inner_red {
|
|
2
|
+
has color22: string = 'red',
|
|
3
|
+
# self
|
|
4
|
+
doublepoint11: int = 2,
|
|
5
|
+
doublepoint22: float = 2.0,
|
|
6
|
+
# self
|
|
7
|
+
doublepoint33: int = 2,
|
|
8
|
+
# Comments explaining each attribute
|
|
9
|
+
# color22: represents the color, set to 'red'
|
|
10
|
+
point22: int = 20;
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
with entry:__main__ {
|
|
2
|
+
app = App();
|
|
3
|
+
app.run();
|
|
4
|
+
# ray.init_window(800, 450, "Hello");
|
|
5
|
+
# while not ray.window_should_close() {
|
|
6
|
+
# ray.begin_drawing();
|
|
7
|
+
# ray.clear_background(ray.WHITE);
|
|
8
|
+
# ray.draw_text("Hello world", 190, 200, 20, ray.VIOLET);
|
|
9
|
+
# ray.end_drawing();
|
|
10
|
+
# }
|
|
11
|
+
|
|
12
|
+
# ray.close_window();
|
|
13
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
can star(func: Any) {
|
|
2
|
+
can inner(x: Any) {
|
|
3
|
+
print(("*" * 30));
|
|
4
|
+
func(x);
|
|
5
|
+
print(("*" * 30));
|
|
6
|
+
}
|
|
7
|
+
return inner;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
can percent(func: Any) {
|
|
11
|
+
can inner(y: Any) {
|
|
12
|
+
print(("%" * 30));
|
|
13
|
+
func(y);
|
|
14
|
+
print(("%" * 30));
|
|
15
|
+
}
|
|
16
|
+
return inner;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
can percent2(func: Any) {
|
|
20
|
+
can inner(y: Any) {
|
|
21
|
+
print(("-" * 30));
|
|
22
|
+
func(y);
|
|
23
|
+
print(("+" * 30));
|
|
24
|
+
}
|
|
25
|
+
return inner;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@star
|
|
29
|
+
@percent
|
|
30
|
+
@percent2
|
|
31
|
+
can printer(msg: Any) {
|
|
32
|
+
print(msg);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
with entry {
|
|
36
|
+
printer("Hello");
|
|
37
|
+
}
|