jaclang 0.5.11__py3-none-any.whl → 0.5.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 +20 -0
- jaclang/compiler/__init__.py +35 -19
- jaclang/compiler/absyntree.py +106 -97
- jaclang/compiler/generated/jac_parser.py +4069 -0
- jaclang/compiler/jac.lark +655 -0
- jaclang/compiler/parser.py +44 -31
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +92 -37
- jaclang/compiler/passes/main/import_pass.py +8 -5
- jaclang/compiler/passes/main/pyast_gen_pass.py +512 -352
- jaclang/compiler/passes/main/pyast_load_pass.py +271 -64
- jaclang/compiler/passes/main/registry_pass.py +3 -7
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -0
- jaclang/compiler/passes/main/type_check_pass.py +4 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +7 -0
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +16 -0
- jaclang/compiler/passes/utils/mypy_ast_build.py +93 -0
- jaclang/compiler/tests/test_importer.py +15 -0
- jaclang/core/aott.py +4 -3
- jaclang/core/construct.py +1 -1
- jaclang/core/importer.py +109 -51
- jaclang/core/llms.py +29 -0
- jaclang/core/registry.py +22 -0
- jaclang/core/utils.py +72 -0
- jaclang/plugin/default.py +127 -8
- jaclang/plugin/feature.py +29 -2
- jaclang/plugin/spec.py +25 -2
- jaclang/utils/helpers.py +7 -9
- jaclang/utils/lang_tools.py +37 -13
- jaclang/utils/test.py +1 -3
- jaclang/utils/tests/test_lang_tools.py +6 -0
- jaclang/vendor/lark/grammars/common.lark +59 -0
- jaclang/vendor/lark/grammars/lark.lark +62 -0
- jaclang/vendor/lark/grammars/python.lark +302 -0
- jaclang/vendor/lark/grammars/unicode.lark +7 -0
- {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/METADATA +1 -1
- {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/RECORD +40 -34
- jaclang/compiler/__jac_gen__/jac_parser.py +0 -4069
- /jaclang/compiler/{__jac_gen__ → generated}/__init__.py +0 -0
- {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/WHEEL +0 -0
- {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/entry_points.txt +0 -0
- {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import ast as py_ast
|
|
6
6
|
import os
|
|
7
|
-
from typing import Optional, TypeAlias, TypeVar
|
|
7
|
+
from typing import Optional, Sequence, TypeAlias, TypeVar
|
|
8
8
|
|
|
9
9
|
import jaclang.compiler.absyntree as ast
|
|
10
10
|
from jaclang.compiler.constant import Tokens as Tok
|
|
@@ -29,9 +29,9 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
29
29
|
|
|
30
30
|
def pp(self, node: py_ast.AST) -> None:
|
|
31
31
|
"""Print python node."""
|
|
32
|
-
print(
|
|
33
|
-
|
|
34
|
-
)
|
|
32
|
+
# print(
|
|
33
|
+
# f"{node.__class__.__name__} - {[(k, type(v)) for k, v in vars(node).items()]}"
|
|
34
|
+
# )
|
|
35
35
|
|
|
36
36
|
def convert(self, node: py_ast.AST) -> ast.AstNode:
|
|
37
37
|
"""Get python node type."""
|
|
@@ -45,6 +45,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
45
45
|
# print(f"finshed {type(node).__name__} ---------------------")
|
|
46
46
|
# print("normalizing", ret.__class__.__name__)
|
|
47
47
|
# print(ret.unparse())
|
|
48
|
+
# ret.unparse()
|
|
48
49
|
return ret
|
|
49
50
|
|
|
50
51
|
def transform(self, ir: ast.PythonModuleAst) -> ast.Module:
|
|
@@ -59,12 +60,16 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
59
60
|
|
|
60
61
|
def gen_mod_code(with_entry_body: list[ast.CodeBlockStmt]) -> ast.ModuleCode:
|
|
61
62
|
with_entry_subnodelist = ast.SubNodeList[ast.CodeBlockStmt](
|
|
62
|
-
items=with_entry_body,
|
|
63
|
+
items=with_entry_body,
|
|
64
|
+
delim=Tok.WS,
|
|
65
|
+
kid=with_entry_body,
|
|
66
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
67
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
63
68
|
)
|
|
64
69
|
return ast.ModuleCode(
|
|
65
70
|
name=None,
|
|
66
71
|
body=with_entry_subnodelist,
|
|
67
|
-
kid=
|
|
72
|
+
kid=[with_entry_subnodelist],
|
|
68
73
|
doc=None,
|
|
69
74
|
)
|
|
70
75
|
|
|
@@ -72,12 +77,16 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
72
77
|
with_entry_body: list[ast.CodeBlockStmt] = []
|
|
73
78
|
for i in body:
|
|
74
79
|
if isinstance(i, exclude_types):
|
|
80
|
+
if len(with_entry_body):
|
|
81
|
+
extracted.append(gen_mod_code(with_entry_body))
|
|
82
|
+
with_entry_body = []
|
|
75
83
|
extracted.append(i)
|
|
76
84
|
elif isinstance(i, ast.CodeBlockStmt):
|
|
85
|
+
if isinstance(i, ast.ExprStmt) and isinstance(i.expr, ast.String):
|
|
86
|
+
self.convert_to_doc(i.expr)
|
|
77
87
|
with_entry_body.append(i)
|
|
78
88
|
else:
|
|
79
89
|
self.ice("Invalid type for with entry body")
|
|
80
|
-
|
|
81
90
|
if len(with_entry_body):
|
|
82
91
|
extracted.append(gen_mod_code(with_entry_body))
|
|
83
92
|
return extracted
|
|
@@ -97,14 +106,20 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
97
106
|
and isinstance(elements[0].expr, ast.String)
|
|
98
107
|
else elements[0]
|
|
99
108
|
)
|
|
109
|
+
doc_str_list = [elements[0]] if isinstance(elements[0], ast.String) else []
|
|
100
110
|
valid = (
|
|
101
|
-
|
|
102
|
-
|
|
111
|
+
(doc_str_list)
|
|
112
|
+
+ self.extract_with_entry(elements[1:], (ast.ElementStmt, ast.EmptyToken))
|
|
113
|
+
if doc_str_list
|
|
114
|
+
else self.extract_with_entry(elements[:], (ast.ElementStmt, ast.EmptyToken))
|
|
115
|
+
)
|
|
116
|
+
doc_str = elements[0] if isinstance(elements[0], ast.String) else None
|
|
117
|
+
self.convert_to_doc(doc_str) if doc_str else None
|
|
103
118
|
ret = ast.Module(
|
|
104
119
|
name=self.mod_path.split(os.path.sep)[-1].split(".")[0],
|
|
105
120
|
source=ast.JacSource("", mod_path=self.mod_path),
|
|
106
|
-
doc=
|
|
107
|
-
body=valid[1:] if isinstance(valid[0], ast.String) else valid,
|
|
121
|
+
doc=doc_str,
|
|
122
|
+
body=valid[1:] if valid and isinstance(valid[0], ast.String) else valid,
|
|
108
123
|
is_imported=False,
|
|
109
124
|
kid=valid,
|
|
110
125
|
)
|
|
@@ -146,13 +161,22 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
146
161
|
and isinstance(valid[0].expr, ast.String)
|
|
147
162
|
):
|
|
148
163
|
doc = valid[0].expr
|
|
164
|
+
self.convert_to_doc(doc)
|
|
149
165
|
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
150
|
-
items=valid[1:],
|
|
166
|
+
items=valid[1:],
|
|
167
|
+
delim=Tok.WS,
|
|
168
|
+
kid=valid[1:],
|
|
169
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
170
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
151
171
|
)
|
|
152
172
|
else:
|
|
153
173
|
doc = None
|
|
154
174
|
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
155
|
-
items=valid,
|
|
175
|
+
items=valid,
|
|
176
|
+
delim=Tok.WS,
|
|
177
|
+
kid=valid,
|
|
178
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
179
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
156
180
|
)
|
|
157
181
|
decorators = [self.convert(i) for i in node.decorator_list]
|
|
158
182
|
valid_dec = [i for i in decorators if isinstance(i, ast.Expr)]
|
|
@@ -212,7 +236,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
212
236
|
ability.is_async = True
|
|
213
237
|
return ability
|
|
214
238
|
|
|
215
|
-
def proc_class_def(self, node: py_ast.ClassDef) -> ast.Architype:
|
|
239
|
+
def proc_class_def(self, node: py_ast.ClassDef) -> ast.Architype | ast.Enum:
|
|
216
240
|
"""Process python node.
|
|
217
241
|
|
|
218
242
|
class ClassDef(stmt):
|
|
@@ -239,7 +263,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
239
263
|
arch_type = ast.Token(
|
|
240
264
|
file_path=self.mod_path,
|
|
241
265
|
name=Tok.KW_OBJECT,
|
|
242
|
-
value="
|
|
266
|
+
value="obj",
|
|
243
267
|
line=node.lineno,
|
|
244
268
|
col_start=0,
|
|
245
269
|
col_end=0,
|
|
@@ -247,37 +271,139 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
247
271
|
pos_end=0,
|
|
248
272
|
)
|
|
249
273
|
body = [self.convert(i) for i in node.body]
|
|
250
|
-
|
|
251
|
-
|
|
274
|
+
for body_stmt in body:
|
|
275
|
+
if (
|
|
276
|
+
isinstance(body_stmt, ast.Ability)
|
|
277
|
+
and isinstance(body_stmt.name_ref, ast.Name)
|
|
278
|
+
and body_stmt.name_ref.value == "__init__"
|
|
279
|
+
):
|
|
280
|
+
tok = ast.Token(
|
|
281
|
+
file_path=self.mod_path,
|
|
282
|
+
name=Tok.KW_INIT,
|
|
283
|
+
value="init",
|
|
284
|
+
line=node.lineno,
|
|
285
|
+
col_start=node.col_offset,
|
|
286
|
+
col_end=node.col_offset + len("init"),
|
|
287
|
+
pos_start=0,
|
|
288
|
+
pos_end=0,
|
|
289
|
+
)
|
|
290
|
+
body_stmt.name_ref = ast.SpecialVarRef(var=tok, kid=[tok])
|
|
291
|
+
if (
|
|
292
|
+
isinstance(body_stmt, ast.Ability)
|
|
293
|
+
and body_stmt.signature
|
|
294
|
+
and isinstance(body_stmt.signature, ast.FuncSignature)
|
|
295
|
+
and body_stmt.signature.params
|
|
296
|
+
):
|
|
297
|
+
body_stmt.signature.params.items = [
|
|
298
|
+
param
|
|
299
|
+
for param in body_stmt.signature.params.items
|
|
300
|
+
if param.name.value != "self"
|
|
301
|
+
]
|
|
302
|
+
doc = (
|
|
303
|
+
body[0].expr
|
|
304
|
+
if isinstance(body[0], ast.ExprStmt)
|
|
305
|
+
and isinstance(body[0].expr, ast.String)
|
|
306
|
+
else None
|
|
307
|
+
)
|
|
308
|
+
self.convert_to_doc(doc) if doc else None
|
|
309
|
+
body = body[1:] if doc else body
|
|
310
|
+
valid: list[ast.ArchBlockStmt] = (
|
|
311
|
+
self.extract_with_entry(body, ast.ArchBlockStmt)
|
|
312
|
+
if not (isinstance(body[0], ast.Semi) and len(body) == 1)
|
|
313
|
+
else []
|
|
252
314
|
)
|
|
315
|
+
empty_block: Sequence[ast.AstNode] = [
|
|
316
|
+
self.operator(Tok.LBRACE, "{"),
|
|
317
|
+
self.operator(Tok.RBRACE, "}"),
|
|
318
|
+
]
|
|
253
319
|
valid_body = ast.SubNodeList[ast.ArchBlockStmt](
|
|
254
|
-
items=valid,
|
|
320
|
+
items=valid,
|
|
321
|
+
delim=Tok.WS,
|
|
322
|
+
kid=(valid if valid else empty_block),
|
|
323
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
324
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
255
325
|
)
|
|
256
|
-
|
|
257
|
-
base_classes
|
|
258
|
-
|
|
259
|
-
base for base in base_classes if isinstance(base, ast.Expr)
|
|
326
|
+
converted_base_classes = [self.convert(base) for base in node.bases]
|
|
327
|
+
base_classes: list[ast.Expr] = [
|
|
328
|
+
base for base in converted_base_classes if isinstance(base, ast.Expr)
|
|
260
329
|
]
|
|
261
|
-
if len(valid2) != len(base_classes):
|
|
262
|
-
raise self.ice("Length mismatch in base classes")
|
|
263
330
|
valid_bases = (
|
|
264
|
-
ast.SubNodeList[ast.Expr](
|
|
265
|
-
|
|
331
|
+
ast.SubNodeList[ast.Expr](
|
|
332
|
+
items=base_classes, delim=Tok.COMMA, kid=base_classes
|
|
333
|
+
)
|
|
334
|
+
if base_classes
|
|
266
335
|
else None
|
|
267
336
|
)
|
|
268
|
-
|
|
269
|
-
decorators = [
|
|
270
|
-
valid_dec = [i for i in decorators if isinstance(i, ast.Expr)]
|
|
271
|
-
if len(valid_dec) != len(decorators):
|
|
272
|
-
raise self.ice("Length mismatch in decorators in class")
|
|
337
|
+
converted_decorators_list = [self.convert(i) for i in node.decorator_list]
|
|
338
|
+
decorators = [i for i in converted_decorators_list if isinstance(i, ast.Expr)]
|
|
273
339
|
valid_decorators = (
|
|
274
340
|
ast.SubNodeList[ast.Expr](
|
|
275
|
-
items=
|
|
341
|
+
items=decorators, delim=Tok.DECOR_OP, kid=decorators
|
|
276
342
|
)
|
|
277
|
-
if
|
|
343
|
+
if decorators
|
|
278
344
|
else None
|
|
279
345
|
)
|
|
280
|
-
|
|
346
|
+
if (
|
|
347
|
+
base_classes
|
|
348
|
+
and isinstance(base_classes[0], ast.Name)
|
|
349
|
+
and base_classes[0].value == "Enum"
|
|
350
|
+
):
|
|
351
|
+
if len(base_classes) > 1:
|
|
352
|
+
raise ValueError(
|
|
353
|
+
"Python's Enum class cannot be used with multiple inheritance."
|
|
354
|
+
)
|
|
355
|
+
arch_type.name = Tok.KW_ENUM
|
|
356
|
+
arch_type.value = "enum"
|
|
357
|
+
valid_enum_body: list[ast.EnumBlockStmt] = []
|
|
358
|
+
for class_body_stmt in node.body:
|
|
359
|
+
converted_stmt = self.convert(class_body_stmt)
|
|
360
|
+
if isinstance(converted_stmt, ast.EnumBlockStmt):
|
|
361
|
+
if isinstance(converted_stmt, ast.Assignment):
|
|
362
|
+
converted_stmt.is_enum_stmt = True
|
|
363
|
+
valid_enum_body.append(converted_stmt)
|
|
364
|
+
else:
|
|
365
|
+
if isinstance(converted_stmt, ast.ExprStmt) and isinstance(
|
|
366
|
+
converted_stmt.expr, ast.String
|
|
367
|
+
):
|
|
368
|
+
continue
|
|
369
|
+
tok = ast.Token(
|
|
370
|
+
file_path=self.mod_path,
|
|
371
|
+
name=Tok.PYNLINE,
|
|
372
|
+
value=py_ast.unparse(class_body_stmt),
|
|
373
|
+
line=node.lineno,
|
|
374
|
+
col_start=node.col_offset,
|
|
375
|
+
col_end=node.col_offset + len(py_ast.unparse(class_body_stmt)),
|
|
376
|
+
pos_start=0,
|
|
377
|
+
pos_end=0,
|
|
378
|
+
)
|
|
379
|
+
valid_enum_body.append(ast.PyInlineCode(code=tok, kid=[tok]))
|
|
380
|
+
|
|
381
|
+
valid_enum_body2: list[ast.EnumBlockStmt] = [
|
|
382
|
+
i for i in valid_enum_body if isinstance(i, ast.EnumBlockStmt)
|
|
383
|
+
]
|
|
384
|
+
enum_body = ast.SubNodeList[ast.EnumBlockStmt](
|
|
385
|
+
items=valid_enum_body2, delim=Tok.COMMA, kid=valid_enum_body2
|
|
386
|
+
)
|
|
387
|
+
if doc:
|
|
388
|
+
doc.line_no = name.line_no
|
|
389
|
+
return ast.Enum(
|
|
390
|
+
name=name,
|
|
391
|
+
access=None,
|
|
392
|
+
base_classes=None,
|
|
393
|
+
body=enum_body,
|
|
394
|
+
kid=[doc, name, enum_body] if doc else [name, enum_body],
|
|
395
|
+
doc=doc,
|
|
396
|
+
decorators=valid_decorators,
|
|
397
|
+
)
|
|
398
|
+
kid = (
|
|
399
|
+
[name, valid_bases, valid_body, doc]
|
|
400
|
+
if doc and valid_bases
|
|
401
|
+
else (
|
|
402
|
+
[name, valid_bases, valid_body]
|
|
403
|
+
if valid_bases
|
|
404
|
+
else [name, valid_body, doc] if doc else [name, valid_body]
|
|
405
|
+
)
|
|
406
|
+
)
|
|
281
407
|
return ast.Architype(
|
|
282
408
|
arch_type=arch_type,
|
|
283
409
|
name=name,
|
|
@@ -320,13 +446,14 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
320
446
|
target = ast.SubNodeList[ast.Expr | ast.KWPair](
|
|
321
447
|
items=[*valid_exprs], delim=Tok.COMMA, kid=exprs
|
|
322
448
|
)
|
|
449
|
+
target_1 = (
|
|
450
|
+
valid_exprs[0]
|
|
451
|
+
if len(valid_exprs) > 1
|
|
452
|
+
else ast.TupleVal(values=target, kid=[target])
|
|
453
|
+
)
|
|
323
454
|
return ast.DeleteStmt(
|
|
324
|
-
target=
|
|
325
|
-
|
|
326
|
-
if len(valid_exprs) > 1
|
|
327
|
-
else ast.TupleVal(values=target, kid=[target])
|
|
328
|
-
),
|
|
329
|
-
kid=exprs,
|
|
455
|
+
target=target_1,
|
|
456
|
+
kid=[target],
|
|
330
457
|
)
|
|
331
458
|
|
|
332
459
|
def proc_assign(self, node: py_ast.Assign) -> ast.Assignment:
|
|
@@ -408,10 +535,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
408
535
|
and isinstance(annotation, ast.Expr)
|
|
409
536
|
and isinstance(target, ast.Expr)
|
|
410
537
|
):
|
|
538
|
+
target = ast.SubNodeList[ast.Expr](
|
|
539
|
+
items=[target], delim=Tok.EQ, kid=[target]
|
|
540
|
+
)
|
|
411
541
|
return ast.Assignment(
|
|
412
|
-
target=
|
|
413
|
-
items=[target], delim=Tok.EQ, kid=[target]
|
|
414
|
-
),
|
|
542
|
+
target=target,
|
|
415
543
|
value=value if isinstance(value, (ast.Expr, ast.YieldExpr)) else None,
|
|
416
544
|
type_tag=annotation_subtag,
|
|
417
545
|
kid=(
|
|
@@ -441,7 +569,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
441
569
|
raise self.ice("Length mismatch in for body")
|
|
442
570
|
|
|
443
571
|
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
444
|
-
items=val_body,
|
|
572
|
+
items=val_body,
|
|
573
|
+
delim=Tok.WS,
|
|
574
|
+
kid=val_body,
|
|
575
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
576
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
445
577
|
)
|
|
446
578
|
orelse = [self.convert(i) for i in node.orelse]
|
|
447
579
|
val_orelse = [i for i in orelse if isinstance(i, ast.CodeBlockStmt)]
|
|
@@ -449,7 +581,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
449
581
|
raise self.ice("Length mismatch in for orelse")
|
|
450
582
|
if orelse:
|
|
451
583
|
valid_orelse = ast.SubNodeList[ast.CodeBlockStmt](
|
|
452
|
-
items=val_orelse,
|
|
584
|
+
items=val_orelse,
|
|
585
|
+
delim=Tok.WS,
|
|
586
|
+
kid=orelse,
|
|
587
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
588
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
453
589
|
)
|
|
454
590
|
else:
|
|
455
591
|
valid_orelse = None
|
|
@@ -492,7 +628,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
492
628
|
raise self.ice("Length mismatch in for body")
|
|
493
629
|
|
|
494
630
|
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
495
|
-
items=val_body,
|
|
631
|
+
items=val_body,
|
|
632
|
+
delim=Tok.WS,
|
|
633
|
+
kid=val_body,
|
|
634
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
635
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
496
636
|
)
|
|
497
637
|
orelse = [self.convert(i) for i in node.orelse]
|
|
498
638
|
val_orelse = [i for i in orelse if isinstance(i, ast.CodeBlockStmt)]
|
|
@@ -500,7 +640,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
500
640
|
raise self.ice("Length mismatch in for orelse")
|
|
501
641
|
if orelse:
|
|
502
642
|
valid_orelse = ast.SubNodeList[ast.CodeBlockStmt](
|
|
503
|
-
items=val_orelse,
|
|
643
|
+
items=val_orelse,
|
|
644
|
+
delim=Tok.WS,
|
|
645
|
+
kid=orelse,
|
|
646
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
647
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
504
648
|
)
|
|
505
649
|
else:
|
|
506
650
|
valid_orelse = None
|
|
@@ -540,7 +684,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
540
684
|
if len(valid_body) != len(body):
|
|
541
685
|
raise self.ice("Length mismatch in while body")
|
|
542
686
|
fin_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
543
|
-
items=valid_body,
|
|
687
|
+
items=valid_body,
|
|
688
|
+
delim=Tok.WS,
|
|
689
|
+
kid=valid_body,
|
|
690
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
691
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
544
692
|
)
|
|
545
693
|
if isinstance(test, ast.Expr):
|
|
546
694
|
return ast.WhileStmt(
|
|
@@ -566,7 +714,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
566
714
|
if len(valid_body) != len(body):
|
|
567
715
|
self.error("Length mismatch in async for body")
|
|
568
716
|
body2 = ast.SubNodeList[ast.CodeBlockStmt](
|
|
569
|
-
items=valid_body,
|
|
717
|
+
items=valid_body,
|
|
718
|
+
delim=Tok.WS,
|
|
719
|
+
kid=body,
|
|
720
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
721
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
570
722
|
)
|
|
571
723
|
|
|
572
724
|
orelse = [self.convert(stmt) for stmt in node.orelse]
|
|
@@ -584,7 +736,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
584
736
|
)
|
|
585
737
|
else:
|
|
586
738
|
orelse2 = ast.SubNodeList[ast.CodeBlockStmt](
|
|
587
|
-
items=valid_orelse,
|
|
739
|
+
items=valid_orelse,
|
|
740
|
+
delim=Tok.WS,
|
|
741
|
+
kid=orelse,
|
|
742
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
743
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
588
744
|
)
|
|
589
745
|
else_body = ast.ElseStmt(body=orelse2, kid=[orelse2])
|
|
590
746
|
else:
|
|
@@ -622,7 +778,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
622
778
|
if len(valid_body) != len(body):
|
|
623
779
|
raise self.ice("Length mismatch in async for body")
|
|
624
780
|
body_sub = ast.SubNodeList[ast.CodeBlockStmt](
|
|
625
|
-
items=valid_body,
|
|
781
|
+
items=valid_body,
|
|
782
|
+
delim=Tok.WS,
|
|
783
|
+
kid=body,
|
|
784
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
785
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
626
786
|
)
|
|
627
787
|
return ast.WithStmt(
|
|
628
788
|
is_async=False, exprs=items_sub, body=body_sub, kid=[items_sub, body_sub]
|
|
@@ -648,7 +808,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
648
808
|
if len(valid_body) != len(body):
|
|
649
809
|
raise self.ice("Length mismatch in async for body")
|
|
650
810
|
body_sub = ast.SubNodeList[ast.CodeBlockStmt](
|
|
651
|
-
items=valid_body,
|
|
811
|
+
items=valid_body,
|
|
812
|
+
delim=Tok.WS,
|
|
813
|
+
kid=body,
|
|
814
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
815
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
652
816
|
)
|
|
653
817
|
return ast.WithStmt(
|
|
654
818
|
is_async=True, exprs=items_sub, body=body_sub, kid=[items_sub, body_sub]
|
|
@@ -855,6 +1019,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
855
1019
|
return ast.FuncCall(
|
|
856
1020
|
target=func,
|
|
857
1021
|
params=params_in2,
|
|
1022
|
+
genai_call=None,
|
|
858
1023
|
kid=[func, params_in2] if params_in2 else [func],
|
|
859
1024
|
)
|
|
860
1025
|
else:
|
|
@@ -924,7 +1089,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
924
1089
|
return type_mapping[value_type](
|
|
925
1090
|
file_path=self.mod_path,
|
|
926
1091
|
name=token_type,
|
|
927
|
-
value=
|
|
1092
|
+
value=(
|
|
1093
|
+
f'"{repr(node.value)[1:-1]}"'
|
|
1094
|
+
if value_type == str
|
|
1095
|
+
else str(node.value)
|
|
1096
|
+
),
|
|
928
1097
|
line=node.lineno,
|
|
929
1098
|
col_start=node.col_offset,
|
|
930
1099
|
col_end=node.col_offset + len(str(node.value)),
|
|
@@ -1014,6 +1183,17 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1014
1183
|
body: list[stmt]
|
|
1015
1184
|
"""
|
|
1016
1185
|
type = self.convert(node.type) if node.type is not None else None
|
|
1186
|
+
if not type:
|
|
1187
|
+
type = ast.Name(
|
|
1188
|
+
file_path=self.mod_path,
|
|
1189
|
+
name=Tok.NAME,
|
|
1190
|
+
value="Any",
|
|
1191
|
+
line=node.lineno,
|
|
1192
|
+
col_start=node.col_offset,
|
|
1193
|
+
col_end=node.col_offset + 3,
|
|
1194
|
+
pos_start=0,
|
|
1195
|
+
pos_end=0,
|
|
1196
|
+
)
|
|
1017
1197
|
name = (
|
|
1018
1198
|
ast.Name(
|
|
1019
1199
|
file_path=self.mod_path,
|
|
@@ -1034,7 +1214,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1034
1214
|
if len(valid) != len(body):
|
|
1035
1215
|
raise self.ice("Length mismatch in except handler body")
|
|
1036
1216
|
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1037
|
-
items=valid,
|
|
1217
|
+
items=valid,
|
|
1218
|
+
delim=Tok.WS,
|
|
1219
|
+
kid=valid,
|
|
1220
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
1221
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
1038
1222
|
)
|
|
1039
1223
|
kid = []
|
|
1040
1224
|
if type:
|
|
@@ -1360,32 +1544,37 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1360
1544
|
else:
|
|
1361
1545
|
raise self.ice()
|
|
1362
1546
|
|
|
1363
|
-
def proc_match_as(self, node: py_ast.MatchAs) -> ast.MatchAs:
|
|
1547
|
+
def proc_match_as(self, node: py_ast.MatchAs) -> ast.MatchAs | ast.MatchWild:
|
|
1364
1548
|
"""Process python node.
|
|
1365
1549
|
|
|
1366
1550
|
class MatchAs(pattern):
|
|
1367
1551
|
pattern: _Pattern | None
|
|
1368
1552
|
name: _Identifier | None
|
|
1369
1553
|
"""
|
|
1370
|
-
pattern = self.convert(node.pattern) if node.pattern
|
|
1554
|
+
pattern = self.convert(node.pattern) if node.pattern else None
|
|
1371
1555
|
name = ast.Name(
|
|
1372
1556
|
file_path=self.mod_path,
|
|
1373
1557
|
name=Tok.NAME,
|
|
1374
|
-
value=node.name if node.name
|
|
1558
|
+
value=node.name if node.name else "_",
|
|
1375
1559
|
line=node.lineno,
|
|
1376
1560
|
col_start=node.col_offset,
|
|
1377
|
-
col_end=
|
|
1561
|
+
col_end=(
|
|
1562
|
+
(node.col_offset + len(node.name))
|
|
1563
|
+
if node.name
|
|
1564
|
+
else (node.col_offset + 1)
|
|
1565
|
+
),
|
|
1378
1566
|
pos_start=0,
|
|
1379
1567
|
pos_end=0,
|
|
1380
1568
|
)
|
|
1381
|
-
|
|
1569
|
+
|
|
1570
|
+
if isinstance(pattern, ast.MatchPattern):
|
|
1382
1571
|
return ast.MatchAs(
|
|
1383
1572
|
name=name,
|
|
1384
1573
|
pattern=pattern,
|
|
1385
|
-
kid=[name, pattern] if pattern
|
|
1574
|
+
kid=[name, pattern] if pattern else [name],
|
|
1386
1575
|
)
|
|
1387
1576
|
else:
|
|
1388
|
-
|
|
1577
|
+
return ast.MatchWild(kid=[name])
|
|
1389
1578
|
|
|
1390
1579
|
def proc_match_class(self, node: py_ast.MatchClass) -> ast.MatchArch:
|
|
1391
1580
|
"""Process python node.
|
|
@@ -1443,6 +1632,8 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1443
1632
|
items=kv_pairs, delim=Tok.COMMA, kid=kv_pairs
|
|
1444
1633
|
)
|
|
1445
1634
|
kid.append(kw_patterns)
|
|
1635
|
+
else:
|
|
1636
|
+
kw_patterns = None
|
|
1446
1637
|
if isinstance(cls, ast.NameSpec):
|
|
1447
1638
|
return ast.MatchArch(
|
|
1448
1639
|
name=cls, arg_patterns=patterns_sub, kw_patterns=kw_patterns, kid=kid
|
|
@@ -1764,7 +1955,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1764
1955
|
if len(valid) != len(body):
|
|
1765
1956
|
raise self.ice("Length mismatch in try body")
|
|
1766
1957
|
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1767
|
-
items=valid,
|
|
1958
|
+
items=valid,
|
|
1959
|
+
delim=Tok.WS,
|
|
1960
|
+
kid=valid,
|
|
1961
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
1962
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
1768
1963
|
)
|
|
1769
1964
|
kid: list[ast.AstNode] = [valid_body]
|
|
1770
1965
|
|
|
@@ -1786,7 +1981,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1786
1981
|
if len(orelse) != len(valid_orelse):
|
|
1787
1982
|
raise self.ice("Length mismatch in try orelse")
|
|
1788
1983
|
else_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1789
|
-
items=valid_orelse,
|
|
1984
|
+
items=valid_orelse,
|
|
1985
|
+
delim=Tok.WS,
|
|
1986
|
+
kid=valid_orelse,
|
|
1987
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
1988
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
1790
1989
|
)
|
|
1791
1990
|
kid.append(else_body)
|
|
1792
1991
|
else:
|
|
@@ -1800,7 +1999,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1800
1999
|
if len(finalbody) != len(valid_finalbody):
|
|
1801
2000
|
raise self.ice("Length mismatch in try finalbody")
|
|
1802
2001
|
finally_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
1803
|
-
items=valid_finalbody,
|
|
2002
|
+
items=valid_finalbody,
|
|
2003
|
+
delim=Tok.WS,
|
|
2004
|
+
kid=valid_finalbody,
|
|
2005
|
+
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
2006
|
+
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
1804
2007
|
)
|
|
1805
2008
|
kid.append(finally_body)
|
|
1806
2009
|
else:
|
|
@@ -2270,3 +2473,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2270
2473
|
|
|
2271
2474
|
def proc_type_var_tuple(self, node: py_ast.TypeVarTuple) -> None:
|
|
2272
2475
|
"""Process python node."""
|
|
2476
|
+
|
|
2477
|
+
def convert_to_doc(self, string: ast.String) -> None:
|
|
2478
|
+
"""Convert a string to a docstring."""
|
|
2479
|
+
string.value = f'""{string.value}""'
|
|
@@ -28,10 +28,10 @@ class RegistryPass(Pass):
|
|
|
28
28
|
|
|
29
29
|
def exit_module(self, node: ast.Module) -> None:
|
|
30
30
|
"""Save registry for each module."""
|
|
31
|
+
module_name = node.name
|
|
31
32
|
module_dir = os.path.join(
|
|
32
33
|
os.path.abspath(os.path.dirname(node.source.file_path)), Con.JAC_GEN_DIR
|
|
33
34
|
)
|
|
34
|
-
module_name = node.name
|
|
35
35
|
os.makedirs(module_dir, exist_ok=True)
|
|
36
36
|
with open(os.path.join(module_dir, f"{module_name}.registry.pkl"), "wb") as f:
|
|
37
37
|
pickle.dump(node.registry, f)
|
|
@@ -68,9 +68,7 @@ class RegistryPass(Pass):
|
|
|
68
68
|
def exit_has_var(self, node: ast.HasVar) -> None:
|
|
69
69
|
"""Save variable information."""
|
|
70
70
|
extracted_type = (
|
|
71
|
-
"".join(self.extract_type(node.type_tag.
|
|
72
|
-
if node.type_tag
|
|
73
|
-
else None
|
|
71
|
+
"".join(self.extract_type(node.type_tag.tag)) if node.type_tag else None
|
|
74
72
|
)
|
|
75
73
|
scope = get_sem_scope(node)
|
|
76
74
|
seminfo = SemInfo(
|
|
@@ -87,9 +85,7 @@ class RegistryPass(Pass):
|
|
|
87
85
|
return
|
|
88
86
|
|
|
89
87
|
extracted_type = (
|
|
90
|
-
"".join(self.extract_type(node.type_tag.
|
|
91
|
-
if node.type_tag
|
|
92
|
-
else None
|
|
88
|
+
"".join(self.extract_type(node.type_tag.tag)) if node.type_tag else None
|
|
93
89
|
)
|
|
94
90
|
scope = get_sem_scope(node)
|
|
95
91
|
seminfo = SemInfo(
|
|
@@ -57,6 +57,8 @@ class PyastGenPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
57
57
|
captured_output = io.StringIO()
|
|
58
58
|
sys.stdout = captured_output
|
|
59
59
|
module = types.ModuleType("__main__")
|
|
60
|
+
module.__dict__["__file__"] = code_gen.ir.loc.mod_path
|
|
61
|
+
module.__dict__["__jac_mod_bundle__"] = None
|
|
60
62
|
exec(prog, module.__dict__)
|
|
61
63
|
sys.stdout = sys.__stdout__
|
|
62
64
|
stdout_value = captured_output.getvalue()
|
|
@@ -33,7 +33,10 @@ class JacTypeCheckPass(Pass):
|
|
|
33
33
|
|
|
34
34
|
def after_pass(self) -> None:
|
|
35
35
|
"""Call mypy api after traversing all the modules."""
|
|
36
|
-
|
|
36
|
+
try:
|
|
37
|
+
self.api()
|
|
38
|
+
except Exception as e:
|
|
39
|
+
self.error(f"Unable to run type checking: {e}")
|
|
37
40
|
return super().after_pass()
|
|
38
41
|
|
|
39
42
|
def default_message_cb(
|
|
@@ -20,6 +20,11 @@ class JacFormatPass(Pass):
|
|
|
20
20
|
self.indent_level = 0
|
|
21
21
|
self.MAX_LINE_LENGTH = 44
|
|
22
22
|
|
|
23
|
+
def enter_node(self, node: ast.AstNode) -> None:
|
|
24
|
+
"""Enter node."""
|
|
25
|
+
node.gen.jac = ""
|
|
26
|
+
super().enter_node(node)
|
|
27
|
+
|
|
23
28
|
def indent_str(self) -> str:
|
|
24
29
|
"""Return string for indent."""
|
|
25
30
|
return " " * self.indent_size * self.indent_level
|
|
@@ -337,6 +342,8 @@ class JacFormatPass(Pass):
|
|
|
337
342
|
else:
|
|
338
343
|
self.emit_ln(node, "")
|
|
339
344
|
self.emit_ln(node, i.gen.jac)
|
|
345
|
+
if isinstance(i, ast.Token) and i.name == Tok.KW_BY:
|
|
346
|
+
self.emit(node, f"{i.gen.jac} ")
|
|
340
347
|
else:
|
|
341
348
|
self.emit(node, i.gen.jac)
|
|
342
349
|
if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):
|