jaclang 0.8.8__py3-none-any.whl → 0.8.9__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 +64 -2
- jaclang/compiler/constant.py +6 -1
- jaclang/compiler/jac.lark +34 -41
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +143 -27
- jaclang/compiler/passes/main/def_use_pass.py +1 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +151 -83
- jaclang/compiler/passes/main/pyast_load_pass.py +2 -0
- jaclang/compiler/passes/main/tests/test_checker_pass.py +0 -1
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +13 -14
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +104 -20
- jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
- jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +135 -29
- jaclang/compiler/program.py +6 -2
- jaclang/compiler/type_system/type_evaluator.jac +959 -0
- jaclang/compiler/unitree.py +23 -13
- jaclang/lib.py +17 -0
- jaclang/runtimelib/archetype.py +25 -25
- jaclang/runtimelib/constructs.py +2 -2
- jaclang/runtimelib/machine.py +57 -47
- jaclang/settings.py +1 -2
- jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
- jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
- jaclang/tests/fixtures/funccall_genexpr.py +5 -0
- jaclang/tests/fixtures/py2jac_empty.py +0 -0
- jaclang/tests/test_cli.py +134 -18
- jaclang/tests/test_language.py +146 -29
- jaclang/tests/test_reference.py +3 -1
- jaclang/utils/helpers.py +20 -4
- jaclang/utils/tests/test_lang_tools.py +4 -15
- {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -1
- {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/RECORD +35 -30
- jaclang/compiler/type_system/type_evaluator.py +0 -844
- {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/WHEEL +0 -0
- {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
|
@@ -4,7 +4,7 @@ import io
|
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
|
-
from jaclang.compiler.program import JacProgram
|
|
7
|
+
from jaclang.compiler.program import JacProgram, py_code_gen
|
|
8
8
|
from jaclang.utils.test import TestCase
|
|
9
9
|
from jaclang.settings import settings
|
|
10
10
|
from jaclang.compiler.passes.main import PreDynamoPass
|
|
@@ -16,42 +16,41 @@ class PreDynamoPassTests(TestCase):
|
|
|
16
16
|
|
|
17
17
|
def setUp(self) -> None:
|
|
18
18
|
"""Set up test."""
|
|
19
|
+
settings.predynamo_pass = True
|
|
19
20
|
return super().setUp()
|
|
20
|
-
|
|
21
|
+
|
|
22
|
+
def tearDown(self) -> None:
|
|
23
|
+
"""Tear down test."""
|
|
24
|
+
settings.predynamo_pass = False
|
|
25
|
+
# Remove PreDynamoPass from global py_code_gen list if it was added
|
|
26
|
+
if PreDynamoPass in py_code_gen:
|
|
27
|
+
py_code_gen.remove(PreDynamoPass)
|
|
28
|
+
return super().tearDown()
|
|
29
|
+
|
|
21
30
|
def test_predynamo_where_assign(self) -> None:
|
|
22
31
|
"""Test torch.where transformation."""
|
|
23
32
|
captured_output = io.StringIO()
|
|
24
33
|
sys.stdout = captured_output
|
|
25
|
-
|
|
26
|
-
settings.load_env_vars()
|
|
34
|
+
settings.predynamo_pass = True
|
|
27
35
|
code_gen = JacProgram().compile(self.fixture_abs_path("predynamo_where_assign.jac"))
|
|
28
36
|
sys.stdout = sys.__stdout__
|
|
29
37
|
self.assertIn("torch.where", code_gen.unparse())
|
|
30
|
-
os.environ["JAC_PREDYNAMO_PASS"] = "false"
|
|
31
|
-
settings.load_env_vars()
|
|
32
38
|
|
|
33
39
|
def test_predynamo_where_return(self) -> None:
|
|
34
40
|
"""Test torch.where transformation."""
|
|
35
41
|
captured_output = io.StringIO()
|
|
36
42
|
sys.stdout = captured_output
|
|
37
|
-
os.environ["JAC_PREDYNAMO_PASS"] = "True"
|
|
38
|
-
settings.load_env_vars()
|
|
39
43
|
code_gen = JacProgram().compile(self.fixture_abs_path("predynamo_where_return.jac"))
|
|
40
44
|
sys.stdout = sys.__stdout__
|
|
41
45
|
self.assertIn("torch.where", code_gen.unparse())
|
|
42
|
-
|
|
43
|
-
settings.load_env_vars()
|
|
46
|
+
|
|
44
47
|
|
|
45
48
|
def test_predynamo_fix3(self) -> None:
|
|
46
49
|
"""Test torch.where transformation."""
|
|
47
50
|
captured_output = io.StringIO()
|
|
48
51
|
sys.stdout = captured_output
|
|
49
|
-
os.environ["JAC_PREDYNAMO_PASS"] = "True"
|
|
50
|
-
settings.load_env_vars()
|
|
51
52
|
code_gen = JacProgram().compile(self.fixture_abs_path("predynamo_fix3.jac"))
|
|
52
53
|
sys.stdout = sys.__stdout__
|
|
53
54
|
unparsed_code = code_gen.unparse()
|
|
54
55
|
self.assertIn("__inv_freq = torch.where(", unparsed_code)
|
|
55
56
|
self.assertIn("self.register_buffer('inv_freq', __inv_freq, persistent=False);", unparsed_code)
|
|
56
|
-
os.environ["JAC_PREDYNAMO_PASS"] = "false"
|
|
57
|
-
settings.load_env_vars()
|
|
@@ -135,20 +135,53 @@ class DocIRGenPass(UniPass):
|
|
|
135
135
|
def exit_import(self, node: uni.Import) -> None:
|
|
136
136
|
"""Exit import node."""
|
|
137
137
|
parts: list[doc.DocType] = []
|
|
138
|
+
mod_items: list[doc.DocType] = []
|
|
139
|
+
has_comment: Optional[doc.DocType] = None
|
|
140
|
+
is_in_items: bool = False
|
|
138
141
|
for i in node.kid:
|
|
139
142
|
if isinstance(i, uni.Token) and i.name == Tok.COMMA:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
if is_in_items:
|
|
144
|
+
mod_items.pop()
|
|
145
|
+
mod_items.append(i.gen.doc_ir)
|
|
146
|
+
mod_items.append(self.line())
|
|
147
|
+
else:
|
|
148
|
+
parts.pop()
|
|
149
|
+
parts.append(i.gen.doc_ir)
|
|
150
|
+
parts.append(self.line())
|
|
151
|
+
elif (
|
|
152
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
153
|
+
):
|
|
154
|
+
has_comment = i.gen.doc_ir
|
|
143
155
|
elif isinstance(i, uni.Token) and i.name == Tok.SEMI:
|
|
144
156
|
parts.pop()
|
|
145
157
|
parts.append(i.gen.doc_ir)
|
|
146
158
|
elif isinstance(i, uni.Token) and i.name == Tok.RBRACE:
|
|
159
|
+
is_in_items = False
|
|
160
|
+
mod_items.pop()
|
|
161
|
+
parts.append(
|
|
162
|
+
self.group(
|
|
163
|
+
self.concat(
|
|
164
|
+
[
|
|
165
|
+
self.indent(self.concat([self.line(), *mod_items])),
|
|
166
|
+
self.line(),
|
|
167
|
+
]
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
)
|
|
147
171
|
parts.append(i.gen.doc_ir)
|
|
148
|
-
|
|
172
|
+
elif isinstance(i, uni.Token) and i.name == Tok.LBRACE:
|
|
173
|
+
is_in_items = True
|
|
149
174
|
parts.append(i.gen.doc_ir)
|
|
150
|
-
|
|
175
|
+
else:
|
|
176
|
+
if is_in_items:
|
|
177
|
+
mod_items.append(i.gen.doc_ir)
|
|
178
|
+
mod_items.append(self.space())
|
|
179
|
+
else:
|
|
180
|
+
parts.append(i.gen.doc_ir)
|
|
181
|
+
parts.append(self.space())
|
|
151
182
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
183
|
+
if has_comment:
|
|
184
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
152
185
|
|
|
153
186
|
def exit_module_item(self, node: uni.ModuleItem) -> None:
|
|
154
187
|
"""Generate DocIR for module items."""
|
|
@@ -178,6 +211,7 @@ class DocIRGenPass(UniPass):
|
|
|
178
211
|
"""Generate DocIR for archetypes."""
|
|
179
212
|
parts: list[doc.DocType] = []
|
|
180
213
|
body_parts: list[doc.DocType] = []
|
|
214
|
+
has_comment: Optional[doc.DocType] = None
|
|
181
215
|
prev_item = None
|
|
182
216
|
in_body = False
|
|
183
217
|
for i in node.kid:
|
|
@@ -198,6 +232,10 @@ class DocIRGenPass(UniPass):
|
|
|
198
232
|
parts.pop()
|
|
199
233
|
parts.append(i.gen.doc_ir)
|
|
200
234
|
parts.append(self.space())
|
|
235
|
+
elif (
|
|
236
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
237
|
+
):
|
|
238
|
+
has_comment = i.gen.doc_ir
|
|
201
239
|
elif isinstance(node.body, Sequence) and i in node.body:
|
|
202
240
|
if not in_body:
|
|
203
241
|
body_parts.append(self.hard_line())
|
|
@@ -225,13 +263,15 @@ class DocIRGenPass(UniPass):
|
|
|
225
263
|
else:
|
|
226
264
|
parts.append(i.gen.doc_ir)
|
|
227
265
|
parts.append(self.space())
|
|
228
|
-
|
|
229
266
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
267
|
+
if has_comment:
|
|
268
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
230
269
|
|
|
231
270
|
def exit_ability(self, node: uni.Ability) -> None:
|
|
232
271
|
"""Generate DocIR for abilities."""
|
|
233
272
|
parts: list[doc.DocType] = []
|
|
234
273
|
body_parts: list[doc.DocType] = []
|
|
274
|
+
has_comment: Optional[doc.DocType] = None
|
|
235
275
|
in_body = False
|
|
236
276
|
for i in node.kid:
|
|
237
277
|
if i == node.doc or (node.decorators and i in node.decorators):
|
|
@@ -259,12 +299,18 @@ class DocIRGenPass(UniPass):
|
|
|
259
299
|
parts.pop()
|
|
260
300
|
parts.append(i.gen.doc_ir)
|
|
261
301
|
parts.append(self.space())
|
|
302
|
+
elif (
|
|
303
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
304
|
+
):
|
|
305
|
+
has_comment = i.gen.doc_ir
|
|
262
306
|
elif not in_body and isinstance(i, uni.Token) and i.name == Tok.DECOR_OP:
|
|
263
307
|
parts.append(i.gen.doc_ir)
|
|
264
308
|
else:
|
|
265
309
|
parts.append(i.gen.doc_ir)
|
|
266
310
|
parts.append(self.space())
|
|
267
311
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
312
|
+
if has_comment:
|
|
313
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
268
314
|
|
|
269
315
|
def exit_func_signature(self, node: uni.FuncSignature) -> None:
|
|
270
316
|
"""Generate DocIR for function signatures."""
|
|
@@ -401,7 +447,7 @@ class DocIRGenPass(UniPass):
|
|
|
401
447
|
]
|
|
402
448
|
)
|
|
403
449
|
)
|
|
404
|
-
parts.append(self.if_break(broken, flat))
|
|
450
|
+
parts.append(self.group(self.if_break(broken, flat)))
|
|
405
451
|
else:
|
|
406
452
|
parts.append(i.gen.doc_ir)
|
|
407
453
|
parts.append(self.space())
|
|
@@ -901,16 +947,16 @@ class DocIRGenPass(UniPass):
|
|
|
901
947
|
return [expr]
|
|
902
948
|
|
|
903
949
|
exprs = __flatten_bool_expr(node)
|
|
904
|
-
|
|
950
|
+
parts += [exprs[0].gen.doc_ir, self.line()]
|
|
951
|
+
for i in range(1, len(exprs), 2):
|
|
905
952
|
(
|
|
906
|
-
expr,
|
|
907
953
|
op,
|
|
954
|
+
expr,
|
|
908
955
|
) = (
|
|
909
|
-
exprs[i],
|
|
910
956
|
exprs[i + 1],
|
|
957
|
+
exprs[i],
|
|
911
958
|
)
|
|
912
959
|
parts += [expr.gen.doc_ir, self.space(), op.gen.doc_ir, self.line()]
|
|
913
|
-
parts += [exprs[-1].gen.doc_ir, self.line()]
|
|
914
960
|
parts.pop()
|
|
915
961
|
flat = self.concat(parts)
|
|
916
962
|
node.gen.doc_ir = self.group(flat)
|
|
@@ -1108,6 +1154,8 @@ class DocIRGenPass(UniPass):
|
|
|
1108
1154
|
"""Generate DocIR for assert statements."""
|
|
1109
1155
|
parts: list[doc.DocType] = []
|
|
1110
1156
|
for i in node.kid:
|
|
1157
|
+
if isinstance(i, uni.Token) and i.name == Tok.SEMI and len(parts):
|
|
1158
|
+
parts.pop()
|
|
1111
1159
|
parts.append(i.gen.doc_ir)
|
|
1112
1160
|
parts.append(self.space())
|
|
1113
1161
|
parts.pop()
|
|
@@ -1125,6 +1173,7 @@ class DocIRGenPass(UniPass):
|
|
|
1125
1173
|
def exit_global_vars(self, node: uni.GlobalVars) -> None:
|
|
1126
1174
|
"""Generate DocIR for global variables."""
|
|
1127
1175
|
parts: list[doc.DocType] = []
|
|
1176
|
+
has_comment: Optional[doc.DocType] = None
|
|
1128
1177
|
for i in node.kid:
|
|
1129
1178
|
if i == node.doc:
|
|
1130
1179
|
parts.append(i.gen.doc_ir)
|
|
@@ -1133,15 +1182,22 @@ class DocIRGenPass(UniPass):
|
|
|
1133
1182
|
parts.pop()
|
|
1134
1183
|
parts.append(i.gen.doc_ir)
|
|
1135
1184
|
parts.append(self.space())
|
|
1185
|
+
elif (
|
|
1186
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1187
|
+
):
|
|
1188
|
+
has_comment = i.gen.doc_ir
|
|
1136
1189
|
else:
|
|
1137
1190
|
parts.append(i.gen.doc_ir)
|
|
1138
1191
|
parts.append(self.space())
|
|
1139
1192
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1193
|
+
if has_comment:
|
|
1194
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1140
1195
|
|
|
1141
1196
|
def exit_module_code(self, node: uni.ModuleCode) -> None:
|
|
1142
1197
|
"""Generate DocIR for module code."""
|
|
1143
1198
|
parts: list[doc.DocType] = []
|
|
1144
1199
|
body_parts: list[doc.DocType] = []
|
|
1200
|
+
has_comment: Optional[doc.DocType] = None
|
|
1145
1201
|
in_body = False
|
|
1146
1202
|
for i in node.kid:
|
|
1147
1203
|
if node.doc and i is node.doc:
|
|
@@ -1153,6 +1209,10 @@ class DocIRGenPass(UniPass):
|
|
|
1153
1209
|
elif isinstance(i, uni.Token) and i.name == Tok.COLON:
|
|
1154
1210
|
parts.pop()
|
|
1155
1211
|
parts.append(i.gen.doc_ir)
|
|
1212
|
+
elif (
|
|
1213
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1214
|
+
):
|
|
1215
|
+
has_comment = i.gen.doc_ir
|
|
1156
1216
|
elif isinstance(node.body, Sequence) and i in node.body:
|
|
1157
1217
|
if not in_body:
|
|
1158
1218
|
parts.pop()
|
|
@@ -1175,6 +1235,8 @@ class DocIRGenPass(UniPass):
|
|
|
1175
1235
|
parts.append(i.gen.doc_ir)
|
|
1176
1236
|
parts.append(self.space())
|
|
1177
1237
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1238
|
+
if has_comment:
|
|
1239
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1178
1240
|
|
|
1179
1241
|
def exit_global_stmt(self, node: uni.GlobalStmt) -> None:
|
|
1180
1242
|
"""Generate DocIR for global statements."""
|
|
@@ -1264,7 +1326,9 @@ class DocIRGenPass(UniPass):
|
|
|
1264
1326
|
]
|
|
1265
1327
|
)
|
|
1266
1328
|
)
|
|
1267
|
-
if isinstance(node.parent, uni.Assignment)
|
|
1329
|
+
if isinstance(node.parent, (uni.Assignment)) or (
|
|
1330
|
+
isinstance(node.parent, uni.IfStmt) and isinstance(node.value, uni.BoolExpr)
|
|
1331
|
+
):
|
|
1268
1332
|
node.gen.doc_ir = self.if_break(
|
|
1269
1333
|
flat_contents=self.group(self.concat(parts[1:-1])),
|
|
1270
1334
|
break_contents=broken,
|
|
@@ -1300,6 +1364,7 @@ class DocIRGenPass(UniPass):
|
|
|
1300
1364
|
def exit_py_inline_code(self, node: uni.PyInlineCode) -> None:
|
|
1301
1365
|
"""Generate DocIR for Python inline code blocks."""
|
|
1302
1366
|
parts: list[doc.DocType] = []
|
|
1367
|
+
has_comment: Optional[doc.DocType] = None
|
|
1303
1368
|
for i in node.kid:
|
|
1304
1369
|
if i == node.doc:
|
|
1305
1370
|
parts.append(i.gen.doc_ir)
|
|
@@ -1309,14 +1374,21 @@ class DocIRGenPass(UniPass):
|
|
|
1309
1374
|
parts.append(i.gen.doc_ir)
|
|
1310
1375
|
parts.append(self.text("::py::"))
|
|
1311
1376
|
parts.append(self.hard_line())
|
|
1377
|
+
elif (
|
|
1378
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1379
|
+
):
|
|
1380
|
+
has_comment = i.gen.doc_ir
|
|
1312
1381
|
else:
|
|
1313
1382
|
parts.append(i.gen.doc_ir)
|
|
1314
1383
|
parts.append(self.space())
|
|
1315
1384
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1385
|
+
if has_comment:
|
|
1386
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1316
1387
|
|
|
1317
1388
|
def exit_test(self, node: uni.Test) -> None:
|
|
1318
1389
|
"""Generate DocIR for test nodes."""
|
|
1319
1390
|
parts: list[doc.DocType] = []
|
|
1391
|
+
has_comment: Optional[doc.DocType] = None
|
|
1320
1392
|
for i in node.kid:
|
|
1321
1393
|
if i == node.doc:
|
|
1322
1394
|
parts.append(i.gen.doc_ir)
|
|
@@ -1325,10 +1397,16 @@ class DocIRGenPass(UniPass):
|
|
|
1325
1397
|
if not i.value.startswith("_jac_gen_"):
|
|
1326
1398
|
parts.append(i.gen.doc_ir)
|
|
1327
1399
|
parts.append(self.space())
|
|
1400
|
+
elif (
|
|
1401
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1402
|
+
):
|
|
1403
|
+
has_comment = i.gen.doc_ir
|
|
1328
1404
|
else:
|
|
1329
1405
|
parts.append(i.gen.doc_ir)
|
|
1330
1406
|
parts.append(self.space())
|
|
1331
1407
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1408
|
+
if has_comment:
|
|
1409
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1332
1410
|
|
|
1333
1411
|
def exit_match_stmt(self, node: uni.MatchStmt) -> None:
|
|
1334
1412
|
"""Generate DocIR for match statements."""
|
|
@@ -1512,6 +1590,7 @@ class DocIRGenPass(UniPass):
|
|
|
1512
1590
|
"""Generate DocIR for implementation definitions."""
|
|
1513
1591
|
parts: list[doc.DocType] = []
|
|
1514
1592
|
body_parts: list[doc.DocType] = []
|
|
1593
|
+
has_comment: Optional[doc.DocType] = None
|
|
1515
1594
|
in_body = False
|
|
1516
1595
|
for i in node.kid:
|
|
1517
1596
|
if i == node.doc or (node.decorators and i in node.decorators):
|
|
@@ -1519,6 +1598,10 @@ class DocIRGenPass(UniPass):
|
|
|
1519
1598
|
parts.append(self.hard_line())
|
|
1520
1599
|
elif self.is_within(i, node.target):
|
|
1521
1600
|
parts.append(i.gen.doc_ir)
|
|
1601
|
+
elif (
|
|
1602
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1603
|
+
):
|
|
1604
|
+
has_comment = i.gen.doc_ir
|
|
1522
1605
|
elif (
|
|
1523
1606
|
in_body
|
|
1524
1607
|
or isinstance(node.body, Sequence)
|
|
@@ -1546,10 +1629,13 @@ class DocIRGenPass(UniPass):
|
|
|
1546
1629
|
parts.append(i.gen.doc_ir)
|
|
1547
1630
|
parts.append(self.space())
|
|
1548
1631
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1632
|
+
if has_comment:
|
|
1633
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1549
1634
|
|
|
1550
1635
|
def exit_sem_def(self, node: uni.SemDef) -> None:
|
|
1551
1636
|
"""Generate DocIR for semantic definitions."""
|
|
1552
1637
|
parts: list[doc.DocType] = []
|
|
1638
|
+
has_comment: Optional[doc.DocType] = None
|
|
1553
1639
|
for i in node.kid:
|
|
1554
1640
|
if i in node.target:
|
|
1555
1641
|
parts.append(i.gen.doc_ir)
|
|
@@ -1557,10 +1643,16 @@ class DocIRGenPass(UniPass):
|
|
|
1557
1643
|
parts.pop()
|
|
1558
1644
|
parts.append(i.gen.doc_ir)
|
|
1559
1645
|
parts.append(self.space())
|
|
1646
|
+
elif (
|
|
1647
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1648
|
+
):
|
|
1649
|
+
has_comment = i.gen.doc_ir
|
|
1560
1650
|
else:
|
|
1561
1651
|
parts.append(i.gen.doc_ir)
|
|
1562
1652
|
parts.append(self.space())
|
|
1563
1653
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1654
|
+
if has_comment:
|
|
1655
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1564
1656
|
|
|
1565
1657
|
def exit_event_signature(self, node: uni.EventSignature) -> None:
|
|
1566
1658
|
"""Generate DocIR for event signatures."""
|
|
@@ -1614,14 +1706,6 @@ class DocIRGenPass(UniPass):
|
|
|
1614
1706
|
and isinstance(node.parent, uni.FString)
|
|
1615
1707
|
)
|
|
1616
1708
|
|
|
1617
|
-
if "\n" in node.value:
|
|
1618
|
-
lines = node.value.split("\n")
|
|
1619
|
-
parts: list[doc.DocType] = [self.text(lines[0])]
|
|
1620
|
-
for line in lines[1:]:
|
|
1621
|
-
parts.append(self.hard_line())
|
|
1622
|
-
parts.append(self.text(line.lstrip()))
|
|
1623
|
-
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1624
|
-
return
|
|
1625
1709
|
if is_escaped_curly:
|
|
1626
1710
|
node.gen.doc_ir = self.concat(
|
|
1627
1711
|
[self.text(node.value), self.text(node.value)]
|
|
@@ -51,7 +51,7 @@ class JacFormatPass(Transform[uni.Module, uni.Module]):
|
|
|
51
51
|
|
|
52
52
|
if isinstance(cur, doc.Text):
|
|
53
53
|
remaining -= len(cur.text)
|
|
54
|
-
if remaining
|
|
54
|
+
if remaining <= 0:
|
|
55
55
|
return False
|
|
56
56
|
|
|
57
57
|
elif isinstance(cur, doc.Line):
|
|
@@ -63,7 +63,7 @@ class JacFormatPass(Transform[uni.Module, uni.Module]):
|
|
|
63
63
|
continue
|
|
64
64
|
# regular soft line becomes a single space in flat mode
|
|
65
65
|
remaining -= 1
|
|
66
|
-
if remaining
|
|
66
|
+
if remaining <= 0:
|
|
67
67
|
return False
|
|
68
68
|
|
|
69
69
|
# --- Structural nodes (walk children in LIFO) ---
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import from datetime { datetime }
|
|
2
2
|
import from uuid { UUID, uuid4 }
|
|
3
3
|
import from jaclang.compiler.constant { EdgeDir }
|
|
4
|
-
import from jaclang.plugin {
|
|
4
|
+
import from jaclang.plugin {
|
|
5
|
+
Archetype,
|
|
6
|
+
ArchetypeProtocol,
|
|
7
|
+
DSFunc,
|
|
8
|
+
AbsRootHook,
|
|
9
|
+
hookimpl
|
|
10
|
+
}
|
|
5
11
|
import math;
|
|
6
12
|
import numpy as np;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#this file is part of formatter tests and is not meant to be run
|
|
2
|
-
|
|
2
|
+
class SemTokManager {
|
|
3
3
|
"""Initialize semantic token manager."""
|
|
4
4
|
def init(self: SemTokManager, ir: uni.Module) -> None {
|
|
5
5
|
self.aaaaastatic_sem_tokens:
|
|
@@ -23,25 +23,23 @@ def walrus_example() {
|
|
|
23
23
|
with entry {
|
|
24
24
|
c = (
|
|
25
25
|
a()
|
|
26
|
-
if 1
|
|
27
|
-
isinstance(a, int)
|
|
28
|
-
isinstance(a, int)
|
|
29
|
-
isinstance(a, int)
|
|
30
|
-
isinstance(a, int)
|
|
31
|
-
isinstance(a, int)
|
|
26
|
+
if 1
|
|
27
|
+
and isinstance(a, int)
|
|
28
|
+
and isinstance(a, int)
|
|
29
|
+
and isinstance(a, int)
|
|
30
|
+
and isinstance(a, int)
|
|
31
|
+
and isinstance(a, int)
|
|
32
32
|
else (
|
|
33
33
|
999
|
|
34
|
-
if isinstance(a, int)
|
|
35
|
-
isinstance(a, int)
|
|
36
|
-
isinstance(a, int)
|
|
37
|
-
isinstance(4, bool)
|
|
34
|
+
if isinstance(a, int)
|
|
35
|
+
and isinstance(a, int)
|
|
36
|
+
and isinstance(a, int)
|
|
37
|
+
and isinstance(4, bool)
|
|
38
38
|
else 7
|
|
39
39
|
)
|
|
40
40
|
);
|
|
41
|
-
print(
|
|
42
|
-
"""
|
|
43
|
-
line of code."""
|
|
44
|
-
);
|
|
41
|
+
print("""This is a long
|
|
42
|
+
line of code.""");
|
|
45
43
|
}
|
|
46
44
|
|
|
47
45
|
|
|
@@ -95,7 +93,7 @@ class ModuleManager {
|
|
|
95
93
|
|
|
96
94
|
|
|
97
95
|
## expr as item extra space issue
|
|
98
|
-
|
|
96
|
+
with entry {
|
|
99
97
|
with open(f"Apple{apple}.txt") as f {
|
|
100
98
|
# Fix syntax highlighting
|
|
101
99
|
print(
|
|
@@ -106,7 +104,7 @@ class ModuleManager {
|
|
|
106
104
|
|
|
107
105
|
|
|
108
106
|
def func_with_very_long_params(
|
|
109
|
-
|
|
107
|
+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: int,
|
|
110
108
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: int,
|
|
111
109
|
) -> None {
|
|
112
110
|
print(
|
|
@@ -132,9 +130,9 @@ def func_with_short_params(a: int, b: int) -> None {
|
|
|
132
130
|
|
|
133
131
|
with entry {
|
|
134
132
|
if (
|
|
135
|
-
node_selected
|
|
136
|
-
node_selected.find_parent_of_type(uni.Archetype)
|
|
137
|
-
node_selected.find_parent_of_type(uni.ImplDef)
|
|
133
|
+
node_selected
|
|
134
|
+
and node_selected.find_parent_of_type(uni.Archetype)
|
|
135
|
+
or node_selected.find_parent_of_type(uni.ImplDef)
|
|
138
136
|
) {
|
|
139
137
|
self_symbol = [
|
|
140
138
|
lspt.CompletionItem(label='self', kind=lspt.CompletionItemKind.Variable)
|
|
@@ -143,27 +141,35 @@ with entry {
|
|
|
143
141
|
self_symbol = [];
|
|
144
142
|
}
|
|
145
143
|
x = (
|
|
146
|
-
1222222222
|
|
147
|
-
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
|
|
144
|
+
1222222222
|
|
145
|
+
and 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
|
|
148
146
|
);
|
|
149
147
|
a = 4 if True else 4;
|
|
150
148
|
}
|
|
151
149
|
|
|
152
150
|
|
|
151
|
+
import from typing { Any, Awaitable, Callable, Coroutine, Optional, ParamSpec, TypeVar }
|
|
152
|
+
|
|
153
|
+
import from jaclang.compiler.constant {
|
|
154
|
+
JacSemTokenModifier as SemTokMod,
|
|
155
|
+
JacSemTokenType as SemTokType,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
153
159
|
"""Return diagnostics."""
|
|
154
160
|
def gen_diagnostics(
|
|
155
161
|
from_path: str, errors: list[Alert], warnings: list[Alert]
|
|
156
162
|
) -> list[lspt.Diagnostic] {
|
|
157
163
|
if (
|
|
158
|
-
isinstance(node_selected, uni.Name)
|
|
159
|
-
node_selected.parent
|
|
160
|
-
isinstance(node_selected.parent, uni.ModulePath)
|
|
164
|
+
isinstance(node_selected, uni.Name)
|
|
165
|
+
and node_selected.parent
|
|
166
|
+
and isinstance(node_selected.parent, uni.ModulePath)
|
|
161
167
|
) {
|
|
162
168
|
node_selected = node_selected.name_of;
|
|
163
169
|
} elif (
|
|
164
|
-
isinstance(node_selected, uni.Name)
|
|
165
|
-
node_selected.parent
|
|
166
|
-
isinstance(node_selected.parent, uni.ModulePath)
|
|
170
|
+
isinstance(node_selected, uni.Name)
|
|
171
|
+
and node_selected.parent
|
|
172
|
+
and isinstance(node_selected.parent, uni.ModulePath)
|
|
167
173
|
) {
|
|
168
174
|
spec = node_selected.parent.parent.abs_path;
|
|
169
175
|
}
|
|
@@ -171,8 +177,108 @@ def gen_diagnostics(
|
|
|
171
177
|
|
|
172
178
|
|
|
173
179
|
@decorator
|
|
174
|
-
def x() {
|
|
180
|
+
def x() {
|
|
181
|
+
assert gg == 7;
|
|
182
|
+
}
|
|
175
183
|
|
|
176
184
|
|
|
177
185
|
@decorator()
|
|
178
186
|
class KK {}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# kkk
|
|
190
|
+
import pygame, random, math;
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
# fff
|
|
194
|
+
with entry {
|
|
195
|
+
# gg
|
|
196
|
+
a = 9;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# kkk
|
|
201
|
+
class X {}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# comment
|
|
205
|
+
@decorator
|
|
206
|
+
def xxx() { }
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# ddd
|
|
210
|
+
glob a = 7;
|
|
211
|
+
def get_node_info(self: JacLangServer, sym_node: uni.AstSymbolNode) -> Optional[str] {
|
|
212
|
+
try {
|
|
213
|
+
if isinstance(sym_node, uni.NameAtom) {
|
|
214
|
+
sym_node = sym_node.name_of;
|
|
215
|
+
}
|
|
216
|
+
access = (sym_node.sym.access.value + ' ') if sym_node.sym else None;
|
|
217
|
+
node_info = f"'('{(access if access else '')}{sym_node.sym_category.value}') '{sym_node.sym_name}";
|
|
218
|
+
if sym_node.name_spec.clean_type {
|
|
219
|
+
node_info += f"': '{sym_node.name_spec.clean_type}";
|
|
220
|
+
}
|
|
221
|
+
if (
|
|
222
|
+
isinstance(sym_node, uni.AstSymbolNode)
|
|
223
|
+
and isinstance(sym_node.name_spec.type, ClassType)
|
|
224
|
+
) {
|
|
225
|
+
node_info += f"': '{sym_node.name_spec.type.shared.class_name}";
|
|
226
|
+
}
|
|
227
|
+
if (isinstance(sym_node, uni.AstDocNode) and sym_node.doc) {
|
|
228
|
+
node_info += f"'\n'{sym_node.doc.value}";
|
|
229
|
+
}
|
|
230
|
+
if (isinstance(sym_node, uni.Ability) and sym_node.signature) {
|
|
231
|
+
node_info += f"'\n'{sym_node.signature.unparse()}";
|
|
232
|
+
}
|
|
233
|
+
} except AttributeError as e {
|
|
234
|
+
self.log_warning(f"'Attribute error when accessing node attributes: '{e}");
|
|
235
|
+
}
|
|
236
|
+
return node_info.strip();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class foo {
|
|
241
|
+
"""Get information about a node."""
|
|
242
|
+
def get_node_info(
|
|
243
|
+
self: JacLangServer, sym_node: uni.AstSymbolNode
|
|
244
|
+
) -> Optional[str] {
|
|
245
|
+
if isinstance(sym_node, uni.AstVarNode) {
|
|
246
|
+
var_name = sym_node.name;
|
|
247
|
+
var_type = sym_node.var_type if sym_node.var_type else 'unknown';
|
|
248
|
+
return f" 'Variable: ' {var_name} ', Type: ' {var_type} ";
|
|
249
|
+
} elif isinstance(sym_node, uni.AstFuncNode) {
|
|
250
|
+
func_name = sym_node.name;
|
|
251
|
+
params = ', '.join(
|
|
252
|
+
[f" {p.name} ': ' {p.param_type} " for p in sym_node.params]
|
|
253
|
+
);
|
|
254
|
+
return f" 'Function: ' {func_name} '(' {params} ')' ";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def x3() {
|
|
261
|
+
if dest_type.is_class_instance() and src_type.is_class_instance() {
|
|
262
|
+
print("x");
|
|
263
|
+
}
|
|
264
|
+
if (
|
|
265
|
+
dest_type.is_class_instance()
|
|
266
|
+
and src_type.is_class_instance()
|
|
267
|
+
and src_type.is_class_instance()
|
|
268
|
+
) {
|
|
269
|
+
print("x");
|
|
270
|
+
}
|
|
271
|
+
if (dest_type.is_class_instance() and src_type.is_class_instance()) {
|
|
272
|
+
print("x");
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class HH {
|
|
278
|
+
def test() -> Optional[str] {
|
|
279
|
+
a = """!
|
|
280
|
+
hello
|
|
281
|
+
hru
|
|
282
|
+
""";
|
|
283
|
+
}
|
|
284
|
+
}
|
jaclang/compiler/program.py
CHANGED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import ast as py_ast
|
|
6
6
|
import marshal
|
|
7
7
|
import types
|
|
8
|
-
from typing import Optional
|
|
8
|
+
from typing import Optional, TYPE_CHECKING
|
|
9
9
|
|
|
10
10
|
import jaclang.compiler.unitree as uni
|
|
11
11
|
from jaclang.compiler.parser import JacParser
|
|
@@ -32,11 +32,13 @@ from jaclang.compiler.passes.tool import (
|
|
|
32
32
|
FuseCommentsPass,
|
|
33
33
|
JacFormatPass,
|
|
34
34
|
)
|
|
35
|
-
from jaclang.compiler.type_system.type_evaluator import TypeEvaluator
|
|
36
35
|
from jaclang.runtimelib.utils import read_file_with_encoding
|
|
37
36
|
from jaclang.settings import settings
|
|
38
37
|
from jaclang.utils.log import logging
|
|
39
38
|
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from jaclang.compiler.type_system.type_evaluator import TypeEvaluator
|
|
41
|
+
|
|
40
42
|
|
|
41
43
|
logger = logging.getLogger(__name__)
|
|
42
44
|
|
|
@@ -71,6 +73,8 @@ class JacProgram:
|
|
|
71
73
|
|
|
72
74
|
def get_type_evaluator(self) -> TypeEvaluator:
|
|
73
75
|
"""Return the type evaluator."""
|
|
76
|
+
from jaclang.compiler.type_system.type_evaluator import TypeEvaluator
|
|
77
|
+
|
|
74
78
|
if not self.type_evaluator:
|
|
75
79
|
self.type_evaluator = TypeEvaluator(program=self)
|
|
76
80
|
return self.type_evaluator
|