jaclang 0.5.17__py3-none-any.whl → 0.6.0__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/__init__.py +2 -6
- jaclang/cli/cli.py +4 -2
- jaclang/compiler/__init__.py +12 -5
- jaclang/compiler/absyntree.py +23 -23
- jaclang/compiler/generated/jac_parser.py +2 -2
- jaclang/compiler/jac.lark +9 -9
- jaclang/compiler/parser.py +76 -21
- jaclang/compiler/passes/ir_pass.py +10 -8
- jaclang/compiler/passes/main/__init__.py +3 -2
- jaclang/compiler/passes/main/access_modifier_pass.py +173 -0
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +3 -2
- jaclang/compiler/passes/main/import_pass.py +33 -21
- jaclang/compiler/passes/main/pyast_gen_pass.py +99 -44
- jaclang/compiler/passes/main/pyast_load_pass.py +141 -77
- jaclang/compiler/passes/main/pyout_pass.py +14 -13
- jaclang/compiler/passes/main/registry_pass.py +8 -3
- jaclang/compiler/passes/main/schedules.py +5 -3
- jaclang/compiler/passes/main/sym_tab_build_pass.py +47 -37
- jaclang/compiler/passes/main/tests/test_import_pass.py +2 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +85 -23
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -4
- jaclang/compiler/passes/transform.py +2 -0
- jaclang/compiler/symtable.py +10 -3
- jaclang/compiler/tests/test_importer.py +9 -0
- jaclang/compiler/workspace.py +19 -11
- jaclang/core/aott.py +34 -63
- jaclang/core/importer.py +73 -65
- jaclang/core/llms/__init__.py +20 -0
- jaclang/core/llms/anthropic.py +61 -0
- jaclang/core/llms/base.py +206 -0
- jaclang/core/llms/groq.py +67 -0
- jaclang/core/llms/huggingface.py +73 -0
- jaclang/core/llms/ollama.py +78 -0
- jaclang/core/llms/openai.py +61 -0
- jaclang/core/llms/togetherai.py +60 -0
- jaclang/core/llms/utils.py +9 -0
- jaclang/core/utils.py +16 -1
- jaclang/plugin/default.py +47 -16
- jaclang/plugin/feature.py +9 -6
- jaclang/plugin/spec.py +8 -1
- jaclang/settings.py +95 -0
- jaclang/utils/helpers.py +6 -2
- jaclang/utils/treeprinter.py +9 -6
- jaclang/vendor/mypy/checker.py +2 -3
- jaclang-0.6.0.dist-info/METADATA +17 -0
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/RECORD +49 -39
- jaclang/core/llms.py +0 -29
- jaclang-0.5.17.dist-info/METADATA +0 -7
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/WHEEL +0 -0
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/entry_points.txt +0 -0
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/top_level.txt +0 -0
|
@@ -6,6 +6,8 @@ import ast as py_ast
|
|
|
6
6
|
import os
|
|
7
7
|
from typing import Optional, Sequence, TypeAlias, TypeVar
|
|
8
8
|
|
|
9
|
+
# from icecream import ic
|
|
10
|
+
|
|
9
11
|
import jaclang.compiler.absyntree as ast
|
|
10
12
|
from jaclang.compiler.constant import Tokens as Tok
|
|
11
13
|
from jaclang.compiler.passes.ir_pass import Pass
|
|
@@ -44,6 +46,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
44
46
|
raise self.ice(f"Unknown node type {type(node).__name__}")
|
|
45
47
|
# print(f"finshed {type(node).__name__} ---------------------")
|
|
46
48
|
# print("normalizing", ret.__class__.__name__)
|
|
49
|
+
# ic("normalizing", ret.__class__.__name__)
|
|
47
50
|
# print(ret.unparse())
|
|
48
51
|
# ret.unparse()
|
|
49
52
|
return ret
|
|
@@ -140,10 +143,13 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
140
143
|
if sys.version_info >= (3, 12):
|
|
141
144
|
type_params: list[type_param]
|
|
142
145
|
"""
|
|
146
|
+
# ic("----")
|
|
143
147
|
name = ast.Name(
|
|
144
148
|
file_path=self.mod_path,
|
|
145
149
|
name=Tok.NAME,
|
|
146
|
-
value=
|
|
150
|
+
value=(
|
|
151
|
+
node.name if node.name != "root" else "root_"
|
|
152
|
+
), # root is a reserved keyword
|
|
147
153
|
line=node.lineno,
|
|
148
154
|
col_start=node.col_offset,
|
|
149
155
|
col_end=node.col_offset + len(node.name),
|
|
@@ -160,12 +166,12 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
160
166
|
and isinstance(valid[0], ast.ExprStmt)
|
|
161
167
|
and isinstance(valid[0].expr, ast.String)
|
|
162
168
|
):
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
self.convert_to_doc(valid[0].expr)
|
|
170
|
+
doc = valid[0]
|
|
165
171
|
valid_body = ast.SubNodeList[ast.CodeBlockStmt](
|
|
166
|
-
items=valid[1:],
|
|
172
|
+
items=[doc] + valid[1:],
|
|
167
173
|
delim=Tok.WS,
|
|
168
|
-
kid=valid[1:],
|
|
174
|
+
kid=valid[1:] + [doc],
|
|
169
175
|
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
170
176
|
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
171
177
|
)
|
|
@@ -213,7 +219,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
213
219
|
signature=sig,
|
|
214
220
|
body=valid_body,
|
|
215
221
|
decorators=valid_decorators,
|
|
216
|
-
doc=
|
|
222
|
+
doc=None,
|
|
217
223
|
kid=kid,
|
|
218
224
|
)
|
|
219
225
|
return ret
|
|
@@ -262,8 +268,8 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
262
268
|
)
|
|
263
269
|
arch_type = ast.Token(
|
|
264
270
|
file_path=self.mod_path,
|
|
265
|
-
name=Tok.
|
|
266
|
-
value="
|
|
271
|
+
name=Tok.KW_CLASS,
|
|
272
|
+
value="class",
|
|
267
273
|
line=node.lineno,
|
|
268
274
|
col_start=0,
|
|
269
275
|
col_end=0,
|
|
@@ -309,7 +315,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
309
315
|
body = body[1:] if doc else body
|
|
310
316
|
valid: list[ast.ArchBlockStmt] = (
|
|
311
317
|
self.extract_with_entry(body, ast.ArchBlockStmt)
|
|
312
|
-
if not (isinstance(body[0], ast.Semi) and len(body) == 1)
|
|
318
|
+
if body and not (isinstance(body[0], ast.Semi) and len(body) == 1)
|
|
313
319
|
else []
|
|
314
320
|
)
|
|
315
321
|
empty_block: Sequence[ast.AstNode] = [
|
|
@@ -491,8 +497,12 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
491
497
|
op: operator
|
|
492
498
|
value: expr
|
|
493
499
|
"""
|
|
500
|
+
from jaclang.compiler import TOKEN_MAP
|
|
501
|
+
|
|
494
502
|
target = self.convert(node.target)
|
|
495
503
|
op = self.convert(node.op)
|
|
504
|
+
if isinstance(op, ast.Token):
|
|
505
|
+
op.name = self.aug_op_map(TOKEN_MAP, op)
|
|
496
506
|
value = self.convert(node.value)
|
|
497
507
|
if (
|
|
498
508
|
isinstance(value, ast.Expr)
|
|
@@ -750,9 +760,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
750
760
|
condition=test,
|
|
751
761
|
body=body2,
|
|
752
762
|
else_body=else_body,
|
|
753
|
-
kid=(
|
|
754
|
-
[test, body2, else_body] if else_body is not None else [test, body2]
|
|
755
|
-
),
|
|
763
|
+
kid=([test, body2, else_body] if else_body else [test, body2]),
|
|
756
764
|
)
|
|
757
765
|
else:
|
|
758
766
|
raise self.ice()
|
|
@@ -837,11 +845,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
837
845
|
if (isinstance(cause, ast.Expr) or cause is None) and (
|
|
838
846
|
isinstance(exc, ast.Expr) or exc is None
|
|
839
847
|
):
|
|
840
|
-
if
|
|
848
|
+
if exc and not node.cause:
|
|
841
849
|
return ast.RaiseStmt(
|
|
842
|
-
cause=
|
|
850
|
+
cause=exc,
|
|
843
851
|
from_target=None,
|
|
844
|
-
kid=[self.operator(Tok.KW_RAISE, "raise")],
|
|
852
|
+
kid=[self.operator(Tok.KW_RAISE, "raise"), exc],
|
|
845
853
|
)
|
|
846
854
|
else:
|
|
847
855
|
return ast.RaiseStmt(cause=cause, from_target=exc, kid=kid)
|
|
@@ -856,12 +864,12 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
856
864
|
msg: expr | None
|
|
857
865
|
"""
|
|
858
866
|
test = self.convert(node.test)
|
|
859
|
-
msg = self.convert(node.msg) if node.msg
|
|
867
|
+
msg = self.convert(node.msg) if node.msg else None
|
|
860
868
|
if isinstance(test, ast.Expr) and (isinstance(msg, ast.Expr) or msg is None):
|
|
861
869
|
return ast.AssertStmt(
|
|
862
870
|
condition=test,
|
|
863
871
|
error_msg=msg,
|
|
864
|
-
kid=[test, msg] if msg
|
|
872
|
+
kid=[test, msg] if msg else [test],
|
|
865
873
|
)
|
|
866
874
|
else:
|
|
867
875
|
raise self.ice()
|
|
@@ -877,11 +885,31 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
877
885
|
ctx: expr_context
|
|
878
886
|
"""
|
|
879
887
|
value = self.convert(node.value)
|
|
880
|
-
|
|
888
|
+
if (
|
|
889
|
+
isinstance(value, ast.FuncCall)
|
|
890
|
+
and isinstance(value.target, ast.Name)
|
|
891
|
+
and value.target.value == "super"
|
|
892
|
+
):
|
|
893
|
+
tok = ast.Token(
|
|
894
|
+
file_path=self.mod_path,
|
|
895
|
+
name=Tok.KW_SUPER,
|
|
896
|
+
value="super",
|
|
897
|
+
line=node.lineno,
|
|
898
|
+
col_start=node.col_offset,
|
|
899
|
+
col_end=node.col_offset + len("super"),
|
|
900
|
+
pos_start=0,
|
|
901
|
+
pos_end=0,
|
|
902
|
+
)
|
|
903
|
+
value = ast.SpecialVarRef(var=tok, kid=[tok])
|
|
904
|
+
# exit()
|
|
881
905
|
attribute = ast.Name(
|
|
882
906
|
file_path=self.mod_path,
|
|
883
907
|
name=Tok.NAME,
|
|
884
|
-
value=
|
|
908
|
+
value=(
|
|
909
|
+
("<>" + node.attr)
|
|
910
|
+
if node.attr == "init"
|
|
911
|
+
else "init" if node.attr == "__init__" else node.attr
|
|
912
|
+
),
|
|
885
913
|
line=node.lineno,
|
|
886
914
|
col_start=node.col_offset,
|
|
887
915
|
col_end=node.col_offset + len(node.attr),
|
|
@@ -911,7 +939,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
911
939
|
else:
|
|
912
940
|
raise self.ice()
|
|
913
941
|
|
|
914
|
-
def proc_bin_op(self, node: py_ast.BinOp) -> ast.
|
|
942
|
+
def proc_bin_op(self, node: py_ast.BinOp) -> ast.AtomUnit:
|
|
915
943
|
"""Process python node.
|
|
916
944
|
|
|
917
945
|
class BinOp(expr):
|
|
@@ -929,12 +957,20 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
929
957
|
and isinstance(op, ast.Token)
|
|
930
958
|
and isinstance(right, ast.Expr)
|
|
931
959
|
):
|
|
932
|
-
|
|
960
|
+
value = ast.BinaryExpr(
|
|
933
961
|
left=left,
|
|
934
962
|
op=op,
|
|
935
963
|
right=right,
|
|
936
964
|
kid=[left, op, right],
|
|
937
965
|
)
|
|
966
|
+
return ast.AtomUnit(
|
|
967
|
+
value=value,
|
|
968
|
+
kid=[
|
|
969
|
+
self.operator(Tok.RPAREN, "("),
|
|
970
|
+
value,
|
|
971
|
+
self.operator(Tok.LPAREN, ")"),
|
|
972
|
+
],
|
|
973
|
+
)
|
|
938
974
|
else:
|
|
939
975
|
raise self.ice()
|
|
940
976
|
|
|
@@ -1134,11 +1170,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1134
1170
|
kvp = ast.KVPair(
|
|
1135
1171
|
key=key_pluck,
|
|
1136
1172
|
value=valid_values[i],
|
|
1137
|
-
kid=(
|
|
1138
|
-
[key_pluck, valid_values[i]]
|
|
1139
|
-
if key_pluck is not None
|
|
1140
|
-
else [valid_values[i]]
|
|
1141
|
-
),
|
|
1173
|
+
kid=([key_pluck, valid_values[i]] if key_pluck else [valid_values[i]]),
|
|
1142
1174
|
)
|
|
1143
1175
|
kvpair.append(kvp)
|
|
1144
1176
|
return ast.DictVal(
|
|
@@ -1182,32 +1214,54 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1182
1214
|
name: _Identifier | None
|
|
1183
1215
|
body: list[stmt]
|
|
1184
1216
|
"""
|
|
1185
|
-
type = self.convert(node.type) if node.type
|
|
1186
|
-
|
|
1217
|
+
type = self.convert(node.type) if node.type else None
|
|
1218
|
+
name: ast.Name | None = None
|
|
1219
|
+
if not type and not node.name:
|
|
1187
1220
|
type = ast.Name(
|
|
1188
1221
|
file_path=self.mod_path,
|
|
1189
1222
|
name=Tok.NAME,
|
|
1190
|
-
value="
|
|
1223
|
+
value="Exception",
|
|
1191
1224
|
line=node.lineno,
|
|
1192
1225
|
col_start=node.col_offset,
|
|
1193
|
-
col_end=node.col_offset +
|
|
1226
|
+
col_end=node.col_offset + 9,
|
|
1194
1227
|
pos_start=0,
|
|
1195
1228
|
pos_end=0,
|
|
1196
1229
|
)
|
|
1197
|
-
|
|
1198
|
-
ast.Name(
|
|
1230
|
+
name = ast.Name(
|
|
1199
1231
|
file_path=self.mod_path,
|
|
1200
1232
|
name=Tok.NAME,
|
|
1201
|
-
value=
|
|
1233
|
+
value="e",
|
|
1202
1234
|
line=node.lineno,
|
|
1203
1235
|
col_start=node.col_offset,
|
|
1204
|
-
col_end=node.col_offset +
|
|
1236
|
+
col_end=node.col_offset + 1,
|
|
1205
1237
|
pos_start=0,
|
|
1206
1238
|
pos_end=0,
|
|
1207
1239
|
)
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1240
|
+
else:
|
|
1241
|
+
# type = ast.Name(
|
|
1242
|
+
# file_path=self.mod_path,
|
|
1243
|
+
# name=Tok.NAME,
|
|
1244
|
+
# value=no,
|
|
1245
|
+
# line=node.lineno,
|
|
1246
|
+
# col_start=node.col_offset,
|
|
1247
|
+
# col_end=node.col_offset + 9,
|
|
1248
|
+
# pos_start=0,
|
|
1249
|
+
# pos_end=0,
|
|
1250
|
+
# )
|
|
1251
|
+
name = (
|
|
1252
|
+
ast.Name(
|
|
1253
|
+
file_path=self.mod_path,
|
|
1254
|
+
name=Tok.NAME,
|
|
1255
|
+
value=node.name,
|
|
1256
|
+
line=node.lineno,
|
|
1257
|
+
col_start=node.col_offset,
|
|
1258
|
+
col_end=node.col_offset + len(node.name),
|
|
1259
|
+
pos_start=0,
|
|
1260
|
+
pos_end=0,
|
|
1261
|
+
)
|
|
1262
|
+
if node.name
|
|
1263
|
+
else None
|
|
1264
|
+
)
|
|
1211
1265
|
|
|
1212
1266
|
body = [self.convert(i) for i in node.body]
|
|
1213
1267
|
valid = [i for i in body if isinstance(i, (ast.CodeBlockStmt))]
|
|
@@ -1220,12 +1274,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1220
1274
|
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
1221
1275
|
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
1222
1276
|
)
|
|
1223
|
-
kid = []
|
|
1224
|
-
if type:
|
|
1225
|
-
kid.append(type)
|
|
1226
|
-
if name:
|
|
1227
|
-
kid.append(name)
|
|
1228
|
-
kid.append(valid_body)
|
|
1277
|
+
kid = [item for item in [type, name, valid_body] if item]
|
|
1229
1278
|
if isinstance(type, ast.Expr) and (isinstance(name, ast.Name) or not name):
|
|
1230
1279
|
return ast.Except(
|
|
1231
1280
|
ex_type=type,
|
|
@@ -1372,12 +1421,13 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1372
1421
|
pos_end=0,
|
|
1373
1422
|
)
|
|
1374
1423
|
pytag = ast.SubTag[ast.Name](tag=lang, kid=[lang])
|
|
1424
|
+
items = ast.SubNodeList[ast.ModulePath](items=paths, delim=Tok.COMMA, kid=paths)
|
|
1375
1425
|
ret = ast.Import(
|
|
1376
1426
|
hint=pytag,
|
|
1377
|
-
|
|
1378
|
-
items=
|
|
1427
|
+
from_loc=None,
|
|
1428
|
+
items=items,
|
|
1379
1429
|
is_absorb=False,
|
|
1380
|
-
kid=[pytag,
|
|
1430
|
+
kid=[pytag, items],
|
|
1381
1431
|
)
|
|
1382
1432
|
return ret
|
|
1383
1433
|
|
|
@@ -1431,7 +1481,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1431
1481
|
valid_names.append(
|
|
1432
1482
|
ast.ModuleItem(
|
|
1433
1483
|
name=name.expr,
|
|
1434
|
-
alias=name.alias if name.alias
|
|
1484
|
+
alias=name.alias if name.alias else None,
|
|
1435
1485
|
kid=[i for i in name.kid if i],
|
|
1436
1486
|
)
|
|
1437
1487
|
)
|
|
@@ -1447,9 +1497,21 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1447
1497
|
if not items:
|
|
1448
1498
|
raise self.ice("No valid names in import from")
|
|
1449
1499
|
pytag = ast.SubTag[ast.Name](tag=lang, kid=[lang])
|
|
1500
|
+
if len(node.names) == 1 and node.names[0].name == "*":
|
|
1501
|
+
path_in = ast.SubNodeList[ast.ModulePath](
|
|
1502
|
+
items=[path], delim=Tok.COMMA, kid=[path]
|
|
1503
|
+
)
|
|
1504
|
+
ret = ast.Import(
|
|
1505
|
+
hint=pytag,
|
|
1506
|
+
from_loc=None,
|
|
1507
|
+
items=path_in,
|
|
1508
|
+
is_absorb=True,
|
|
1509
|
+
kid=[pytag, path_in],
|
|
1510
|
+
)
|
|
1511
|
+
return ret
|
|
1450
1512
|
ret = ast.Import(
|
|
1451
1513
|
hint=pytag,
|
|
1452
|
-
|
|
1514
|
+
from_loc=path,
|
|
1453
1515
|
items=items,
|
|
1454
1516
|
is_absorb=False,
|
|
1455
1517
|
kid=[pytag, path, items],
|
|
@@ -1634,7 +1696,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1634
1696
|
kid.append(kw_patterns)
|
|
1635
1697
|
else:
|
|
1636
1698
|
kw_patterns = None
|
|
1637
|
-
if isinstance(cls, ast.NameSpec):
|
|
1699
|
+
if isinstance(cls, (ast.NameSpec, ast.AtomTrailer)):
|
|
1638
1700
|
return ast.MatchArch(
|
|
1639
1701
|
name=cls, arg_patterns=patterns_sub, kw_patterns=kw_patterns, kid=kid
|
|
1640
1702
|
)
|
|
@@ -1732,10 +1794,10 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1732
1794
|
name = ast.Name(
|
|
1733
1795
|
file_path=self.mod_path,
|
|
1734
1796
|
name=Tok.NAME,
|
|
1735
|
-
value=node.name if node.name
|
|
1797
|
+
value=node.name if node.name else "_",
|
|
1736
1798
|
line=node.lineno,
|
|
1737
1799
|
col_start=node.col_offset,
|
|
1738
|
-
col_end=node.col_offset + len(node.name if node.name
|
|
1800
|
+
col_end=node.col_offset + len(node.name if node.name else "_"),
|
|
1739
1801
|
pos_start=0,
|
|
1740
1802
|
pos_end=0,
|
|
1741
1803
|
)
|
|
@@ -1765,7 +1827,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1765
1827
|
ret = ast.Name(
|
|
1766
1828
|
file_path=self.mod_path,
|
|
1767
1829
|
name=Tok.NAME,
|
|
1768
|
-
value=node.id,
|
|
1830
|
+
value=node.id if node.id != "root" else "root_", # reserved word
|
|
1769
1831
|
line=node.lineno,
|
|
1770
1832
|
col_start=node.col_offset,
|
|
1771
1833
|
col_end=node.col_offset + len(node.id),
|
|
@@ -1987,6 +2049,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1987
2049
|
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
1988
2050
|
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
1989
2051
|
)
|
|
2052
|
+
elsestmt = ast.ElseStmt(body=else_body, kid=[else_body])
|
|
1990
2053
|
kid.append(else_body)
|
|
1991
2054
|
else:
|
|
1992
2055
|
else_body = None
|
|
@@ -2005,23 +2068,19 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2005
2068
|
left_enc=self.operator(Tok.LBRACE, "{"),
|
|
2006
2069
|
right_enc=self.operator(Tok.RBRACE, "}"),
|
|
2007
2070
|
)
|
|
2008
|
-
|
|
2071
|
+
finally_stmt = ast.FinallyStmt(body=finally_body, kid=[finally_body])
|
|
2072
|
+
|
|
2073
|
+
kid.append(finally_stmt)
|
|
2009
2074
|
else:
|
|
2010
2075
|
finally_body = None
|
|
2011
|
-
|
|
2012
|
-
return ast.TryStmt(
|
|
2076
|
+
ret = ast.TryStmt(
|
|
2013
2077
|
body=valid_body,
|
|
2014
2078
|
excepts=excepts,
|
|
2015
|
-
else_body=
|
|
2016
|
-
|
|
2017
|
-
),
|
|
2018
|
-
finally_body=(
|
|
2019
|
-
ast.FinallyStmt(body=finally_body, kid=[finally_body])
|
|
2020
|
-
if finally_body
|
|
2021
|
-
else None
|
|
2022
|
-
),
|
|
2079
|
+
else_body=elsestmt if else_body else None,
|
|
2080
|
+
finally_body=finally_stmt if finally_body else None,
|
|
2023
2081
|
kid=kid,
|
|
2024
2082
|
)
|
|
2083
|
+
return ret
|
|
2025
2084
|
|
|
2026
2085
|
def proc_try_star(self, node: py_ast.TryStar) -> ast.TryStmt:
|
|
2027
2086
|
"""Process python node.
|
|
@@ -2122,7 +2181,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2122
2181
|
name = ast.Name(
|
|
2123
2182
|
file_path=self.mod_path,
|
|
2124
2183
|
name=Tok.NAME,
|
|
2125
|
-
value=node.arg,
|
|
2184
|
+
value=node.arg if node.arg != "root" else "root_", # reserved word
|
|
2126
2185
|
line=node.lineno,
|
|
2127
2186
|
col_start=node.col_offset,
|
|
2128
2187
|
col_end=node.col_offset + len(node.arg),
|
|
@@ -2201,9 +2260,12 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2201
2260
|
pos_end=0,
|
|
2202
2261
|
)
|
|
2203
2262
|
kwarg.add_kids_left([kwarg.unpack])
|
|
2204
|
-
defaults = [self.convert(expr) for expr in node.defaults
|
|
2205
|
-
|
|
2263
|
+
defaults = [self.convert(expr) for expr in node.defaults]
|
|
2206
2264
|
params = [*args]
|
|
2265
|
+
for param, default in zip(params[::-1], defaults[::-1]):
|
|
2266
|
+
if isinstance(default, ast.Expr) and isinstance(param, ast.ParamVar):
|
|
2267
|
+
param.value = default
|
|
2268
|
+
param.add_kids_right([default])
|
|
2207
2269
|
if vararg:
|
|
2208
2270
|
params.append(vararg)
|
|
2209
2271
|
params += kwonlyargs
|
|
@@ -2212,8 +2274,6 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2212
2274
|
params += defaults
|
|
2213
2275
|
|
|
2214
2276
|
valid_params = [param for param in params if isinstance(param, ast.ParamVar)]
|
|
2215
|
-
if len(valid_params) != len(params):
|
|
2216
|
-
raise self.ice("Length mismatch in arguments")
|
|
2217
2277
|
if valid_params:
|
|
2218
2278
|
fs_params = ast.SubNodeList[ast.ParamVar](
|
|
2219
2279
|
items=valid_params, delim=Tok.COMMA, kid=valid_params
|
|
@@ -2401,10 +2461,10 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2401
2461
|
arg = ast.Name(
|
|
2402
2462
|
file_path=self.mod_path,
|
|
2403
2463
|
name=Tok.NAME,
|
|
2404
|
-
value=node.arg if node.arg
|
|
2464
|
+
value=node.arg if node.arg else "_",
|
|
2405
2465
|
line=node.lineno,
|
|
2406
2466
|
col_start=node.col_offset,
|
|
2407
|
-
col_end=node.col_offset + len(node.arg if node.arg
|
|
2467
|
+
col_end=node.col_offset + len(node.arg if node.arg else "_"),
|
|
2408
2468
|
pos_start=0,
|
|
2409
2469
|
pos_end=0,
|
|
2410
2470
|
)
|
|
@@ -2423,7 +2483,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2423
2483
|
body: list[stmt]
|
|
2424
2484
|
"""
|
|
2425
2485
|
pattern = self.convert(node.pattern)
|
|
2426
|
-
guard = self.convert(node.guard) if node.guard
|
|
2486
|
+
guard = self.convert(node.guard) if node.guard else None
|
|
2427
2487
|
body = [self.convert(i) for i in node.body]
|
|
2428
2488
|
valid = [i for i in body if isinstance(i, ast.CodeBlockStmt)]
|
|
2429
2489
|
if isinstance(pattern, ast.MatchPattern) and (
|
|
@@ -2433,9 +2493,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2433
2493
|
pattern=pattern,
|
|
2434
2494
|
guard=guard,
|
|
2435
2495
|
body=valid,
|
|
2436
|
-
kid=(
|
|
2437
|
-
[pattern, guard, *valid] if guard is not None else [pattern, *valid]
|
|
2438
|
-
),
|
|
2496
|
+
kid=([pattern, guard, *valid] if guard else [pattern, *valid]),
|
|
2439
2497
|
)
|
|
2440
2498
|
else:
|
|
2441
2499
|
raise self.ice()
|
|
@@ -2448,9 +2506,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2448
2506
|
optional_vars: expr | None
|
|
2449
2507
|
"""
|
|
2450
2508
|
context_expr = self.convert(node.context_expr)
|
|
2451
|
-
optional_vars = (
|
|
2452
|
-
self.convert(node.optional_vars) if node.optional_vars is not None else None
|
|
2453
|
-
)
|
|
2509
|
+
optional_vars = self.convert(node.optional_vars) if node.optional_vars else None
|
|
2454
2510
|
if isinstance(context_expr, ast.Expr) and (
|
|
2455
2511
|
isinstance(optional_vars, ast.Expr) or optional_vars is None
|
|
2456
2512
|
):
|
|
@@ -2477,3 +2533,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2477
2533
|
def convert_to_doc(self, string: ast.String) -> None:
|
|
2478
2534
|
"""Convert a string to a docstring."""
|
|
2479
2535
|
string.value = f'""{string.value}""'
|
|
2536
|
+
|
|
2537
|
+
def aug_op_map(self, tok_dict: dict, op: ast.Token) -> str:
|
|
2538
|
+
"""aug_mapper."""
|
|
2539
|
+
op.value += "="
|
|
2540
|
+
for _key, value in tok_dict.items():
|
|
2541
|
+
if value == op.value:
|
|
2542
|
+
break
|
|
2543
|
+
return _key
|
|
@@ -5,7 +5,6 @@ also creates bytecode files from the Python code, and manages the caching of
|
|
|
5
5
|
relevant files.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import ast as ast3
|
|
9
8
|
import os
|
|
10
9
|
|
|
11
10
|
|
|
@@ -43,18 +42,17 @@ class PyOutPass(Pass):
|
|
|
43
42
|
out_path_pyc
|
|
44
43
|
) > os.path.getmtime(mod_path):
|
|
45
44
|
continue
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
try:
|
|
46
|
+
self.gen_python(mod, out_path=out_path_py)
|
|
47
|
+
self.dump_bytecode(mod, mod_path=mod_path, out_path=out_path_pyc)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
self.warning(f"Error in generating Python code: {e}", node)
|
|
48
50
|
self.terminate()
|
|
49
51
|
|
|
50
52
|
def gen_python(self, node: ast.Module, out_path: str) -> None:
|
|
51
53
|
"""Generate Python."""
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
f.write(node.gen.py)
|
|
55
|
-
except Exception as e:
|
|
56
|
-
print(ast3.dump(node.gen.py_ast[0], indent=2))
|
|
57
|
-
raise e
|
|
54
|
+
with open(out_path, "w") as f:
|
|
55
|
+
f.write(node.gen.py)
|
|
58
56
|
|
|
59
57
|
def dump_bytecode(self, node: ast.Module, mod_path: str, out_path: str) -> None:
|
|
60
58
|
"""Generate Python."""
|
|
@@ -70,14 +68,17 @@ class PyOutPass(Pass):
|
|
|
70
68
|
"""Get output targets."""
|
|
71
69
|
base_path, file_name = os.path.split(node.loc.mod_path)
|
|
72
70
|
gen_path = os.path.join(base_path, Con.JAC_GEN_DIR)
|
|
73
|
-
os.makedirs(gen_path, exist_ok=True)
|
|
74
|
-
with open(os.path.join(gen_path, "__init__.py"), "w"):
|
|
75
|
-
pass
|
|
76
71
|
mod_dir, file_name = os.path.split(node.loc.mod_path)
|
|
77
72
|
mod_dir = mod_dir.replace(base_path, "").lstrip(os.sep)
|
|
78
73
|
base_name, _ = os.path.splitext(file_name)
|
|
79
74
|
out_dir = os.path.join(gen_path, mod_dir)
|
|
80
|
-
|
|
75
|
+
try:
|
|
76
|
+
os.makedirs(gen_path, exist_ok=True)
|
|
77
|
+
with open(os.path.join(gen_path, "__init__.py"), "w"):
|
|
78
|
+
pass
|
|
79
|
+
os.makedirs(out_dir, exist_ok=True)
|
|
80
|
+
except Exception as e:
|
|
81
|
+
self.warning(f"Can't create directory {out_dir}: {e}", node)
|
|
81
82
|
out_path_py = os.path.join(out_dir, f"{base_name}.py")
|
|
82
83
|
out_path_pyc = os.path.join(out_dir, f"{base_name}.jbc")
|
|
83
84
|
return node.loc.mod_path, out_path_py, out_path_pyc
|
|
@@ -32,9 +32,14 @@ class RegistryPass(Pass):
|
|
|
32
32
|
module_dir = os.path.join(
|
|
33
33
|
os.path.abspath(os.path.dirname(node.source.file_path)), Con.JAC_GEN_DIR
|
|
34
34
|
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
try:
|
|
36
|
+
os.makedirs(module_dir, exist_ok=True)
|
|
37
|
+
with open(
|
|
38
|
+
os.path.join(module_dir, f"{module_name}.registry.pkl"), "wb"
|
|
39
|
+
) as f:
|
|
40
|
+
pickle.dump(node.registry, f)
|
|
41
|
+
except Exception as e:
|
|
42
|
+
self.warning(f"Can't save registry for {module_name}: {e}")
|
|
38
43
|
self.modules_visited.pop()
|
|
39
44
|
|
|
40
45
|
def exit_architype(self, node: ast.Architype) -> None:
|
|
@@ -7,7 +7,7 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
from .sub_node_tab_pass import SubNodeTabPass # noqa: I100
|
|
10
|
-
from .import_pass import
|
|
10
|
+
from .import_pass import JacImportPass, PyImportPass # noqa: I100
|
|
11
11
|
from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
|
|
12
12
|
from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
|
|
13
13
|
from .def_use_pass import DefUsePass # noqa: I100
|
|
@@ -17,10 +17,12 @@ from .pyast_gen_pass import PyastGenPass # noqa: I100
|
|
|
17
17
|
from .type_check_pass import JacTypeCheckPass # noqa: I100
|
|
18
18
|
from .fuse_typeinfo_pass import FuseTypeInfoPass # noqa: I100
|
|
19
19
|
from .registry_pass import RegistryPass # noqa: I100
|
|
20
|
+
from .access_modifier_pass import AccessCheckPass # noqa: I100
|
|
20
21
|
|
|
21
22
|
py_code_gen = [
|
|
22
23
|
SubNodeTabPass,
|
|
23
|
-
|
|
24
|
+
JacImportPass,
|
|
25
|
+
PyImportPass,
|
|
24
26
|
SymTabBuildPass,
|
|
25
27
|
DeclDefMatchPass,
|
|
26
28
|
DefUsePass,
|
|
@@ -29,5 +31,5 @@ py_code_gen = [
|
|
|
29
31
|
PyBytecodeGenPass,
|
|
30
32
|
]
|
|
31
33
|
|
|
32
|
-
py_code_gen_typed = [*py_code_gen, JacTypeCheckPass, FuseTypeInfoPass]
|
|
34
|
+
py_code_gen_typed = [*py_code_gen, JacTypeCheckPass, FuseTypeInfoPass, AccessCheckPass]
|
|
33
35
|
py_compiler = [*py_code_gen, PyOutPass]
|