jaclang 0.4.6__py3-none-any.whl → 0.5.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 +5 -2
- jaclang/cli/cli.py +57 -10
- jaclang/cli/cmdreg.py +16 -9
- jaclang/compiler/__jac_gen__/jac_parser.py +11 -15
- jaclang/compiler/absyntree.py +53 -19
- jaclang/compiler/codeloc.py +3 -1
- jaclang/compiler/{transpiler.py → compile.py} +3 -2
- jaclang/compiler/constant.py +4 -0
- jaclang/compiler/parser.py +156 -108
- jaclang/compiler/passes/ir_pass.py +1 -0
- jaclang/compiler/passes/main/__init__.py +2 -1
- jaclang/compiler/passes/main/def_impl_match_pass.py +1 -0
- jaclang/compiler/passes/main/def_use_pass.py +1 -0
- jaclang/compiler/passes/main/import_pass.py +18 -18
- jaclang/compiler/passes/main/pyast_gen_pass.py +1228 -853
- jaclang/compiler/passes/main/pyast_load_pass.py +3 -1
- jaclang/compiler/passes/main/pybc_gen_pass.py +46 -0
- jaclang/compiler/passes/main/pyout_pass.py +6 -7
- jaclang/compiler/passes/main/schedules.py +5 -9
- jaclang/compiler/passes/main/sub_node_tab_pass.py +1 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +21 -9
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +2 -1
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +2 -1
- jaclang/compiler/passes/main/tests/test_import_pass.py +2 -1
- jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +1 -0
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +15 -38
- jaclang/compiler/passes/main/tests/test_pybc_gen_pass.py +25 -0
- jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -1
- jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +2 -1
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +17 -1
- jaclang/compiler/passes/main/type_check_pass.py +9 -6
- jaclang/compiler/passes/tool/__init__.py +1 -0
- jaclang/compiler/passes/tool/ast_printer_pass.py +1 -0
- jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +69 -32
- jaclang/compiler/passes/tool/schedules.py +1 -0
- jaclang/compiler/passes/tool/sym_tab_printer_pass.py +1 -0
- jaclang/compiler/passes/tool/tests/test_ast_print_pass.py +2 -1
- jaclang/compiler/passes/tool/tests/test_fuse_comments_pass.py +1 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -3
- jaclang/compiler/passes/tool/tests/test_symtab_print_pass.py +2 -1
- jaclang/compiler/passes/transform.py +1 -0
- jaclang/compiler/passes/utils/mypy_ast_build.py +203 -17
- jaclang/compiler/symtable.py +1 -0
- jaclang/compiler/tests/test_importer.py +3 -2
- jaclang/compiler/tests/test_parser.py +1 -0
- jaclang/compiler/tests/test_workspace.py +1 -0
- jaclang/compiler/workspace.py +18 -5
- jaclang/core/construct.py +9 -32
- jaclang/{compiler → core}/importer.py +95 -85
- jaclang/core/utils.py +17 -12
- jaclang/plugin/__init__.py +1 -0
- jaclang/plugin/default.py +145 -43
- jaclang/plugin/feature.py +65 -19
- jaclang/plugin/spec.py +56 -34
- jaclang/plugin/tests/test_features.py +9 -0
- jaclang/utils/helpers.py +1 -0
- jaclang/utils/lang_tools.py +13 -19
- jaclang/utils/tests/test_lang_tools.py +2 -1
- jaclang/utils/treeprinter.py +2 -1
- jaclang/vendor/lark/common.py +3 -1
- jaclang/vendor/lark/lexer.py +6 -12
- jaclang/vendor/lark/parsers/lalr_parser.py +1 -0
- jaclang/vendor/mypy/applytype.py +2 -1
- jaclang/vendor/mypy/binder.py +1 -1
- jaclang/vendor/mypy/build.py +7 -9
- jaclang/vendor/mypy/checker.py +57 -33
- jaclang/vendor/mypy/checkexpr.py +42 -29
- jaclang/vendor/mypy/checkmember.py +13 -1
- jaclang/vendor/mypy/checkpattern.py +1 -1
- jaclang/vendor/mypy/checkstrformat.py +2 -4
- jaclang/vendor/mypy/constraints.py +10 -5
- jaclang/vendor/mypy/dmypy_server.py +3 -3
- jaclang/vendor/mypy/dmypy_util.py +62 -3
- jaclang/vendor/mypy/errors.py +1 -1
- jaclang/vendor/mypy/evalexpr.py +1 -0
- jaclang/vendor/mypy/expandtype.py +29 -29
- jaclang/vendor/mypy/fastparse.py +51 -31
- jaclang/vendor/mypy/inspections.py +5 -3
- jaclang/vendor/mypy/join.py +4 -4
- jaclang/vendor/mypy/main.py +6 -6
- jaclang/vendor/mypy/message_registry.py +1 -2
- jaclang/vendor/mypy/messages.py +31 -23
- jaclang/vendor/mypy/metastore.py +1 -2
- jaclang/vendor/mypy/modulefinder.py +2 -22
- jaclang/vendor/mypy/nodes.py +22 -20
- jaclang/vendor/mypy/options.py +4 -0
- jaclang/vendor/mypy/parse.py +6 -2
- jaclang/vendor/mypy/patterns.py +6 -6
- jaclang/vendor/mypy/plugin.py +3 -1
- jaclang/vendor/mypy/plugins/attrs.py +52 -10
- jaclang/vendor/mypy/plugins/common.py +2 -1
- jaclang/vendor/mypy/plugins/enums.py +3 -2
- jaclang/vendor/mypy/plugins/functools.py +1 -0
- jaclang/vendor/mypy/renaming.py +1 -1
- jaclang/vendor/mypy/report.py +15 -15
- jaclang/vendor/mypy/semanal.py +22 -13
- jaclang/vendor/mypy/semanal_enum.py +1 -1
- jaclang/vendor/mypy/semanal_namedtuple.py +1 -2
- jaclang/vendor/mypy/semanal_shared.py +3 -6
- jaclang/vendor/mypy/semanal_typeddict.py +16 -5
- jaclang/vendor/mypy/server/astdiff.py +15 -9
- jaclang/vendor/mypy/server/astmerge.py +5 -5
- jaclang/vendor/mypy/stats.py +0 -5
- jaclang/vendor/mypy/stubdoc.py +1 -1
- jaclang/vendor/mypy/stubgen.py +12 -21
- jaclang/vendor/mypy/stubgenc.py +16 -8
- jaclang/vendor/mypy/stubtest.py +57 -48
- jaclang/vendor/mypy/stubutil.py +28 -15
- jaclang/vendor/mypy/subtypes.py +4 -4
- jaclang/vendor/mypy/test/helpers.py +2 -2
- jaclang/vendor/mypy/test/meta/test_parse_data.py +1 -0
- jaclang/vendor/mypy/test/meta/test_update_data.py +1 -0
- jaclang/vendor/mypy/test/testargs.py +1 -0
- jaclang/vendor/mypy/test/testcheck.py +4 -1
- jaclang/vendor/mypy/test/testconstraints.py +25 -7
- jaclang/vendor/mypy/test/testerrorstream.py +1 -0
- jaclang/vendor/mypy/test/testformatter.py +2 -2
- jaclang/vendor/mypy/test/testparse.py +6 -4
- jaclang/vendor/mypy/test/testpythoneval.py +1 -0
- jaclang/vendor/mypy/test/testreports.py +1 -0
- jaclang/vendor/mypy/test/teststubgen.py +1 -2
- jaclang/vendor/mypy/test/teststubtest.py +98 -4
- jaclang/vendor/mypy/test/testtypes.py +1 -1
- jaclang/vendor/mypy/test/testutil.py +22 -0
- jaclang/vendor/mypy/typeanal.py +302 -158
- jaclang/vendor/mypy/typeops.py +22 -13
- jaclang/vendor/mypy/types.py +33 -34
- jaclang/vendor/mypy/typestate.py +2 -2
- jaclang/vendor/mypy/util.py +7 -6
- jaclang/vendor/mypy/version.py +1 -1
- jaclang/vendor/mypyc/analysis/ircheck.py +1 -0
- jaclang/vendor/mypyc/codegen/emitfunc.py +5 -3
- jaclang/vendor/mypyc/codegen/emitmodule.py +12 -12
- jaclang/vendor/mypyc/codegen/emitwrapper.py +2 -2
- jaclang/vendor/mypyc/ir/class_ir.py +10 -6
- jaclang/vendor/mypyc/irbuild/builder.py +3 -4
- jaclang/vendor/mypyc/irbuild/function.py +5 -3
- jaclang/vendor/mypyc/irbuild/nonlocalcontrol.py +1 -2
- jaclang/vendor/mypyc/irbuild/prepare.py +6 -6
- jaclang/vendor/mypyc/primitives/registry.py +15 -5
- jaclang/vendor/mypyc/test/test_run.py +1 -2
- jaclang/vendor/mypyc/transform/uninit.py +3 -3
- jaclang/vendor/pluggy/_callers.py +1 -0
- jaclang/vendor/pluggy/_hooks.py +6 -10
- jaclang/vendor/pluggy/_result.py +1 -0
- jaclang/vendor/pluggy/_tracing.py +1 -0
- {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/METADATA +1 -1
- {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/RECORD +152 -150
- {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/WHEEL +0 -0
- {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/entry_points.txt +0 -0
- {jaclang-0.4.6.dist-info → jaclang-0.5.0.dist-info}/top_level.txt +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This is a pass for formatting Jac code.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
import re
|
|
6
7
|
|
|
7
8
|
import jaclang.compiler.absyntree as ast
|
|
@@ -196,28 +197,35 @@ class JacFormatPass(Pass):
|
|
|
196
197
|
):
|
|
197
198
|
self.emit_ln(node, "")
|
|
198
199
|
self.indent_level += 1
|
|
199
|
-
if stmt.name ==
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
and node.kid[i + 1].is_inline
|
|
203
|
-
):
|
|
200
|
+
if stmt.name == Tok.LBRACE:
|
|
201
|
+
next_kid = node.kid[i + 1]
|
|
202
|
+
if isinstance(next_kid, ast.CommentToken) and next_kid.is_inline:
|
|
204
203
|
self.emit(node, f" {stmt.value}")
|
|
205
204
|
else:
|
|
206
205
|
self.emit(node, f" {stmt.value}")
|
|
207
|
-
elif stmt.name ==
|
|
206
|
+
elif stmt.name == Tok.RBRACE:
|
|
208
207
|
if self.indent_level > 0:
|
|
209
208
|
self.indent_level -= 1
|
|
210
|
-
if stmt.parent.gen.jac.strip() == "{":
|
|
209
|
+
if stmt.parent and stmt.parent.gen.jac.strip() == "{":
|
|
211
210
|
self.emit_ln(node, stmt.gen.jac.strip())
|
|
212
|
-
elif
|
|
213
|
-
stmt.parent
|
|
214
|
-
|
|
211
|
+
elif (
|
|
212
|
+
stmt.parent
|
|
213
|
+
and stmt.parent.parent
|
|
214
|
+
and isinstance(
|
|
215
|
+
stmt.parent.parent,
|
|
216
|
+
(ast.ElseIf, ast.IfStmt, ast.IterForStmt, ast.TryStmt),
|
|
217
|
+
)
|
|
215
218
|
):
|
|
216
219
|
self.emit(node, f"{stmt.value}")
|
|
217
220
|
else:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
next_kid = (
|
|
222
|
+
node.kid[i + 1]
|
|
223
|
+
if i < (len(node.kid) - 1)
|
|
224
|
+
else ast.EmptyToken()
|
|
225
|
+
)
|
|
226
|
+
if (
|
|
227
|
+
isinstance(next_kid, ast.CommentToken)
|
|
228
|
+
and next_kid.is_inline
|
|
221
229
|
):
|
|
222
230
|
self.emit(node, f" {stmt.value}")
|
|
223
231
|
elif not (node.gen.jac).endswith("\n"):
|
|
@@ -229,10 +237,14 @@ class JacFormatPass(Pass):
|
|
|
229
237
|
self.emit(node, f"{stmt.value}")
|
|
230
238
|
elif isinstance(stmt, ast.CommentToken):
|
|
231
239
|
if stmt.is_inline:
|
|
232
|
-
if isinstance(prev_token, ast.Semi) or
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
240
|
+
if isinstance(prev_token, ast.Semi) or (
|
|
241
|
+
isinstance(prev_token, ast.Token)
|
|
242
|
+
and prev_token.name
|
|
243
|
+
in [
|
|
244
|
+
Tok.LBRACE,
|
|
245
|
+
Tok.RBRACE,
|
|
246
|
+
]
|
|
247
|
+
):
|
|
236
248
|
self.indent_level -= 1
|
|
237
249
|
self.emit(node, f" {stmt.gen.jac}")
|
|
238
250
|
self.emit_ln(node, "")
|
|
@@ -883,9 +895,11 @@ class JacFormatPass(Pass):
|
|
|
883
895
|
for i in node.kid:
|
|
884
896
|
if isinstance(i, ast.SubTag):
|
|
885
897
|
for j in i.kid:
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
898
|
+
(
|
|
899
|
+
self.emit(node, j.gen.jac)
|
|
900
|
+
if not j.gen.jac.startswith(":")
|
|
901
|
+
else self.emit(node, f"{j.gen.jac} ")
|
|
902
|
+
)
|
|
889
903
|
else:
|
|
890
904
|
self.emit(node, f" {i.gen.jac}")
|
|
891
905
|
if isinstance(node.kid[-1], ast.CommentToken) and not node.gen.jac.endswith(
|
|
@@ -1006,7 +1020,11 @@ class JacFormatPass(Pass):
|
|
|
1006
1020
|
count_by: ExprType,
|
|
1007
1021
|
body: CodeBlock,
|
|
1008
1022
|
"""
|
|
1009
|
-
if
|
|
1023
|
+
if (
|
|
1024
|
+
node.parent
|
|
1025
|
+
and node.parent.parent
|
|
1026
|
+
and isinstance(node.parent.parent, (ast.Ability))
|
|
1027
|
+
):
|
|
1010
1028
|
self.emit_ln(node, "")
|
|
1011
1029
|
|
|
1012
1030
|
start = True
|
|
@@ -1036,7 +1054,11 @@ class JacFormatPass(Pass):
|
|
|
1036
1054
|
excepts: Optional[ExceptList],
|
|
1037
1055
|
finally_body: Optional[FinallyStmt],
|
|
1038
1056
|
"""
|
|
1039
|
-
if
|
|
1057
|
+
if (
|
|
1058
|
+
node.parent
|
|
1059
|
+
and node.parent.parent
|
|
1060
|
+
and isinstance(node.parent.parent, (ast.Ability))
|
|
1061
|
+
):
|
|
1040
1062
|
self.emit_ln(node, "")
|
|
1041
1063
|
start = True
|
|
1042
1064
|
for i in node.kid:
|
|
@@ -1068,7 +1090,11 @@ class JacFormatPass(Pass):
|
|
|
1068
1090
|
name: Optional[Token],
|
|
1069
1091
|
body: CodeBlock,
|
|
1070
1092
|
"""
|
|
1071
|
-
if
|
|
1093
|
+
if (
|
|
1094
|
+
node.parent
|
|
1095
|
+
and node.parent.parent
|
|
1096
|
+
and isinstance(node.parent.parent, (ast.Ability))
|
|
1097
|
+
):
|
|
1072
1098
|
self.emit_ln(node, "")
|
|
1073
1099
|
start = True
|
|
1074
1100
|
for i in node.kid:
|
|
@@ -1108,7 +1134,11 @@ class JacFormatPass(Pass):
|
|
|
1108
1134
|
condition: ExprType,
|
|
1109
1135
|
body: CodeBlock,
|
|
1110
1136
|
"""
|
|
1111
|
-
if
|
|
1137
|
+
if (
|
|
1138
|
+
node.parent
|
|
1139
|
+
and node.parent.parent
|
|
1140
|
+
and isinstance(node.parent.parent, (ast.Ability))
|
|
1141
|
+
):
|
|
1112
1142
|
self.emit_ln(node, "")
|
|
1113
1143
|
start = True
|
|
1114
1144
|
for i in node.kid:
|
|
@@ -1314,7 +1344,7 @@ class JacFormatPass(Pass):
|
|
|
1314
1344
|
self.comma_sep_node_list(node.signature.params)
|
|
1315
1345
|
out += node.signature.params.gen.jac
|
|
1316
1346
|
if node.signature.return_type:
|
|
1317
|
-
out += f" -> {node.signature.return_type.
|
|
1347
|
+
out += f" -> {node.signature.return_type.gen.jac}"
|
|
1318
1348
|
self.emit(node, f"with {out} can {node.body.gen.jac}")
|
|
1319
1349
|
|
|
1320
1350
|
def exit_unary_expr(self, node: ast.UnaryExpr) -> None:
|
|
@@ -1417,7 +1447,7 @@ class JacFormatPass(Pass):
|
|
|
1417
1447
|
self.emit(node, f" {i.gen.jac}")
|
|
1418
1448
|
else:
|
|
1419
1449
|
self.emit_ln(node, i.gen.jac)
|
|
1420
|
-
elif isinstance(prev_token, ast.Token) and prev_token.name ==
|
|
1450
|
+
elif isinstance(prev_token, ast.Token) and prev_token.name == Tok.LBRACE:
|
|
1421
1451
|
self.emit(node, f"{i.gen.jac}")
|
|
1422
1452
|
elif isinstance(i, ast.Semi) or i.gen.jac == ",":
|
|
1423
1453
|
self.emit(node, i.gen.jac)
|
|
@@ -1504,7 +1534,10 @@ class JacFormatPass(Pass):
|
|
|
1504
1534
|
key: ExprType,
|
|
1505
1535
|
value: ExprType,
|
|
1506
1536
|
"""
|
|
1507
|
-
|
|
1537
|
+
if node.key:
|
|
1538
|
+
self.emit(node, f"{node.key.gen.jac}={node.value.gen.jac}")
|
|
1539
|
+
else:
|
|
1540
|
+
self.emit(node, f"**{node.value.gen.jac}")
|
|
1508
1541
|
|
|
1509
1542
|
def exit_disconnect_op(self, node: ast.DisconnectOp) -> None:
|
|
1510
1543
|
"""Sub objects.
|
|
@@ -1566,7 +1599,7 @@ class JacFormatPass(Pass):
|
|
|
1566
1599
|
from_walker: bool = False,
|
|
1567
1600
|
"""
|
|
1568
1601
|
for i in node.kid:
|
|
1569
|
-
if isinstance(i, (ast.EdgeOpRef, ast.ElseStmt)):
|
|
1602
|
+
if isinstance(i, (ast.EdgeOpRef, ast.ElseStmt, ast.SpecialVarRef)):
|
|
1570
1603
|
self.emit(node, f" {i.gen.jac}")
|
|
1571
1604
|
else:
|
|
1572
1605
|
self.emit(node, i.gen.jac)
|
|
@@ -1712,7 +1745,7 @@ class JacFormatPass(Pass):
|
|
|
1712
1745
|
alias: Optional[Token],
|
|
1713
1746
|
"""
|
|
1714
1747
|
if node.alias:
|
|
1715
|
-
self.emit(node, node.expr.gen.jac + " as " + node.alias.
|
|
1748
|
+
self.emit(node, node.expr.gen.jac + " as " + node.alias.gen.jac)
|
|
1716
1749
|
else:
|
|
1717
1750
|
self.emit(node, node.expr.gen.jac)
|
|
1718
1751
|
|
|
@@ -1723,7 +1756,11 @@ class JacFormatPass(Pass):
|
|
|
1723
1756
|
collection: ExprType,
|
|
1724
1757
|
body: SubNodeList[CodeBlockStmt],
|
|
1725
1758
|
"""
|
|
1726
|
-
if
|
|
1759
|
+
if (
|
|
1760
|
+
node.parent
|
|
1761
|
+
and node.parent.parent
|
|
1762
|
+
and isinstance(node.parent.parent, (ast.Ability))
|
|
1763
|
+
):
|
|
1727
1764
|
self.indent_level -= 1
|
|
1728
1765
|
self.emit_ln(node, "")
|
|
1729
1766
|
self.indent_level += 1
|
|
@@ -1831,10 +1868,10 @@ class JacFormatPass(Pass):
|
|
|
1831
1868
|
elif isinstance(i, ast.Semi):
|
|
1832
1869
|
self.emit(node, i.gen.jac)
|
|
1833
1870
|
elif isinstance(i, ast.Token):
|
|
1834
|
-
if i.name ==
|
|
1871
|
+
if i.name == Tok.LBRACE:
|
|
1835
1872
|
self.emit_ln(node, f" {i.value}")
|
|
1836
1873
|
self.indent_level += 1
|
|
1837
|
-
elif i.name ==
|
|
1874
|
+
elif i.name == Tok.RBRACE:
|
|
1838
1875
|
self.indent_level -= 1
|
|
1839
1876
|
self.emit(node, f"{i.value}")
|
|
1840
1877
|
else:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Test pass module."""
|
|
2
|
+
|
|
2
3
|
import os
|
|
3
4
|
|
|
5
|
+
from jaclang.compiler.compile import jac_file_to_pass
|
|
4
6
|
from jaclang.compiler.passes.tool import AstDotGraphPass, AstPrinterPass
|
|
5
|
-
from jaclang.compiler.transpiler import jac_file_to_pass
|
|
6
7
|
from jaclang.utils.test import TestCase
|
|
7
8
|
|
|
8
9
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"""Test ast build pass module."""
|
|
2
|
+
|
|
2
3
|
import ast as ast3
|
|
3
4
|
from difflib import unified_diff
|
|
4
5
|
|
|
5
6
|
import jaclang.compiler.absyntree as ast
|
|
7
|
+
from jaclang.compiler.compile import jac_file_to_pass, jac_str_to_pass
|
|
6
8
|
from jaclang.compiler.passes.main import PyastGenPass
|
|
7
9
|
from jaclang.compiler.passes.main.schedules import py_code_gen as without_format
|
|
8
10
|
from jaclang.compiler.passes.tool import JacFormatPass
|
|
9
11
|
from jaclang.compiler.passes.tool.schedules import format_pass
|
|
10
|
-
from jaclang.compiler.transpiler import jac_file_to_pass, jac_str_to_pass
|
|
11
12
|
from jaclang.utils.test import AstSyncTestMixin, TestCaseMicroSuite
|
|
12
13
|
|
|
13
14
|
|
|
@@ -107,8 +108,8 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
107
108
|
len(code_gen_pure.ir.source.comments),
|
|
108
109
|
len(code_gen_jac.ir.source.comments),
|
|
109
110
|
)
|
|
110
|
-
before = ast3.dump(code_gen_pure.ir.gen.py_ast, indent=2)
|
|
111
|
-
after = ast3.dump(code_gen_jac.ir.gen.py_ast, indent=2)
|
|
111
|
+
before = ast3.dump(code_gen_pure.ir.gen.py_ast[0], indent=2)
|
|
112
|
+
after = ast3.dump(code_gen_jac.ir.gen.py_ast[0], indent=2)
|
|
112
113
|
self.assertEqual(
|
|
113
114
|
len("\n".join(unified_diff(before.splitlines(), after.splitlines()))),
|
|
114
115
|
0,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"""Test pass module."""
|
|
2
|
+
|
|
2
3
|
import os
|
|
3
4
|
|
|
5
|
+
from jaclang.compiler.compile import jac_file_to_pass
|
|
4
6
|
from jaclang.compiler.passes.tool.schedules import (
|
|
5
7
|
SymbolTableDotGraphPass,
|
|
6
8
|
SymbolTablePrinterPass,
|
|
7
9
|
sym_tab_print,
|
|
8
10
|
)
|
|
9
|
-
from jaclang.compiler.transpiler import jac_file_to_pass
|
|
10
11
|
from jaclang.utils.test import TestCase
|
|
11
12
|
|
|
12
13
|
|
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
"""Overrides to mypy build manager for direct AST pass through."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
import ast
|
|
6
|
+
import os
|
|
7
|
+
import pathlib
|
|
5
8
|
|
|
6
|
-
import jaclang
|
|
7
|
-
import jaclang.vendor.mypy.errors as mye
|
|
8
|
-
import jaclang.vendor.mypy.fastparse as myfp
|
|
9
|
+
import jaclang
|
|
9
10
|
from jaclang.compiler.absyntree import AstNode
|
|
10
11
|
from jaclang.compiler.passes import Pass
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
12
|
+
|
|
13
|
+
import mypy.build as myb
|
|
14
|
+
import mypy.errors as mye
|
|
15
|
+
import mypy.fastparse as myfp
|
|
16
|
+
from mypy.build import BuildSource
|
|
17
|
+
from mypy.build import BuildSourceSet
|
|
18
|
+
from mypy.build import FileSystemCache
|
|
19
|
+
from mypy.build import Graph
|
|
20
|
+
from mypy.build import ModuleNotFound
|
|
21
|
+
from mypy.build import PRI_INDIRECT
|
|
22
|
+
from mypy.build import compute_search_paths
|
|
23
|
+
from mypy.build import find_module_simple
|
|
24
|
+
from mypy.build import load_plugins
|
|
25
|
+
from mypy.build import process_graph
|
|
26
|
+
from mypy.options import Options
|
|
27
|
+
from mypy.semanal_main import semantic_analysis_for_scc
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
os.environ["MYPYPATH"] = str(
|
|
31
|
+
pathlib.Path(os.path.dirname(jaclang.__file__)).parent / "stubs"
|
|
32
|
+
)
|
|
20
33
|
|
|
21
34
|
|
|
22
35
|
mypy_to_jac_node_map: dict[tuple[int, int | None, int | None, int | None], AstNode] = {}
|
|
@@ -32,7 +45,7 @@ class BuildManager(myb.BuildManager):
|
|
|
32
45
|
source: str,
|
|
33
46
|
ignore_errors: bool,
|
|
34
47
|
options: myb.Options,
|
|
35
|
-
ast_override:
|
|
48
|
+
ast_override: myb.MypyFile | None = None,
|
|
36
49
|
) -> myb.MypyFile:
|
|
37
50
|
"""Parse the source of a file with the given name.
|
|
38
51
|
|
|
@@ -83,7 +96,7 @@ class State(myb.State):
|
|
|
83
96
|
# process it. With this flag, any changes to external state as well
|
|
84
97
|
# as error reporting should be avoided.
|
|
85
98
|
temporary: bool = False,
|
|
86
|
-
ast_override:
|
|
99
|
+
ast_override: myb.MypyFile | None = None,
|
|
87
100
|
) -> None:
|
|
88
101
|
"""Override to mypy state for AST pass through."""
|
|
89
102
|
if not temporary:
|
|
@@ -187,7 +200,7 @@ class State(myb.State):
|
|
|
187
200
|
self.compute_dependencies()
|
|
188
201
|
|
|
189
202
|
def parse_file(
|
|
190
|
-
self, *, temporary: bool = False, ast_override:
|
|
203
|
+
self, *, temporary: bool = False, ast_override: myb.MypyFile | None = None
|
|
191
204
|
) -> None:
|
|
192
205
|
"""Parse file and run first pass of semantic analysis.
|
|
193
206
|
|
|
@@ -304,13 +317,14 @@ class ASTConverter(myfp.ASTConverter):
|
|
|
304
317
|
visitor = getattr(self, method)
|
|
305
318
|
self.visitor_cache[typeobj] = visitor
|
|
306
319
|
ret = visitor(node)
|
|
320
|
+
# Mypy sometimes inserts its own nodes, such as a Return around lambdas.
|
|
307
321
|
if hasattr(node, "jac_link"):
|
|
308
322
|
node.jac_link.gen.mypy_ast.append(ret)
|
|
309
323
|
mypy_to_jac_node_map[
|
|
310
324
|
(ret.line, ret.column, ret.end_line, ret.end_column)
|
|
311
325
|
] = node.jac_link
|
|
312
|
-
else:
|
|
313
|
-
|
|
326
|
+
# else:
|
|
327
|
+
# raise Exception("AST node not linked to Jac node")
|
|
314
328
|
return ret
|
|
315
329
|
|
|
316
330
|
|
|
@@ -364,6 +378,178 @@ class Errors(mye.Errors):
|
|
|
364
378
|
)
|
|
365
379
|
|
|
366
380
|
|
|
381
|
+
def load_graph(
|
|
382
|
+
sources: list[BuildSource],
|
|
383
|
+
manager: BuildManager,
|
|
384
|
+
old_graph: Graph | None = None,
|
|
385
|
+
new_modules: list[State] | None = None,
|
|
386
|
+
) -> Graph:
|
|
387
|
+
"""Given some source files, load the full dependency graph.
|
|
388
|
+
|
|
389
|
+
If an old_graph is passed in, it is used as the starting point and
|
|
390
|
+
modified during graph loading.
|
|
391
|
+
|
|
392
|
+
If a new_modules is passed in, any modules that are loaded are
|
|
393
|
+
added to the list. This is an argument and not a return value
|
|
394
|
+
so that the caller can access it even if load_graph fails.
|
|
395
|
+
|
|
396
|
+
As this may need to parse files, this can raise CompileError in case
|
|
397
|
+
there are syntax errors.
|
|
398
|
+
"""
|
|
399
|
+
graph: Graph = old_graph if old_graph is not None else {}
|
|
400
|
+
|
|
401
|
+
# The deque is used to implement breadth-first traversal.
|
|
402
|
+
# TODO: Consider whether to go depth-first instead. This may
|
|
403
|
+
# affect the order in which we process files within import cycles.
|
|
404
|
+
new = new_modules if new_modules is not None else []
|
|
405
|
+
entry_points: set[str] = set()
|
|
406
|
+
# Seed the graph with the initial root sources.
|
|
407
|
+
for bs in sources:
|
|
408
|
+
try:
|
|
409
|
+
st = State(
|
|
410
|
+
id=bs.module,
|
|
411
|
+
path=bs.path,
|
|
412
|
+
source=bs.text,
|
|
413
|
+
manager=manager,
|
|
414
|
+
root_source=not bs.followed,
|
|
415
|
+
)
|
|
416
|
+
except ModuleNotFound:
|
|
417
|
+
continue
|
|
418
|
+
if st.id in graph:
|
|
419
|
+
manager.errors.set_file(st.xpath, st.id, manager.options)
|
|
420
|
+
manager.errors.report(
|
|
421
|
+
-1,
|
|
422
|
+
-1,
|
|
423
|
+
f'Duplicate module named "{st.id}" (also at "{graph[st.id].xpath}")',
|
|
424
|
+
blocker=True,
|
|
425
|
+
)
|
|
426
|
+
manager.errors.report(
|
|
427
|
+
-1,
|
|
428
|
+
-1,
|
|
429
|
+
"See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules "
|
|
430
|
+
"for more info",
|
|
431
|
+
severity="note",
|
|
432
|
+
)
|
|
433
|
+
manager.errors.report(
|
|
434
|
+
-1,
|
|
435
|
+
-1,
|
|
436
|
+
"Common resolutions include: a) using `--exclude` to avoid checking one of them, "
|
|
437
|
+
"b) adding `__init__.py` somewhere, c) using `--explicit-package-bases` or "
|
|
438
|
+
"adjusting MYPYPATH",
|
|
439
|
+
severity="note",
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
manager.errors.raise_error()
|
|
443
|
+
graph[st.id] = st
|
|
444
|
+
new.append(st)
|
|
445
|
+
entry_points.add(bs.module)
|
|
446
|
+
|
|
447
|
+
# Note: Running this each time could be slow in the daemon. If it's a problem, we
|
|
448
|
+
# can do more work to maintain this incrementally.
|
|
449
|
+
seen_files = {st.abspath: st for st in graph.values() if st.path}
|
|
450
|
+
|
|
451
|
+
# Collect dependencies. We go breadth-first.
|
|
452
|
+
# More nodes might get added to new as we go, but that's fine.
|
|
453
|
+
for st in new:
|
|
454
|
+
assert st.ancestors is not None
|
|
455
|
+
# Strip out indirect dependencies. These will be dealt with
|
|
456
|
+
# when they show up as direct dependencies, and there's a
|
|
457
|
+
# scenario where they hurt:
|
|
458
|
+
# - Suppose A imports B and B imports C.
|
|
459
|
+
# - Suppose on the next round:
|
|
460
|
+
# - C is deleted;
|
|
461
|
+
# - B is updated to remove the dependency on C;
|
|
462
|
+
# - A is unchanged.
|
|
463
|
+
# - In this case A's cached *direct* dependencies are still valid
|
|
464
|
+
# (since direct dependencies reflect the imports found in the source)
|
|
465
|
+
# but A's cached *indirect* dependency on C is wrong.
|
|
466
|
+
dependencies = [
|
|
467
|
+
dep
|
|
468
|
+
for dep in st.dependencies
|
|
469
|
+
if st.priorities.get(dep) != PRI_INDIRECT and "jaclang.vendor" not in dep
|
|
470
|
+
]
|
|
471
|
+
if not manager.use_fine_grained_cache():
|
|
472
|
+
# TODO: Ideally we could skip here modules that appeared in st.suppressed
|
|
473
|
+
# because they are not in build with `follow-imports=skip`.
|
|
474
|
+
# This way we could avoid overhead of cloning options in `State.__init__()`
|
|
475
|
+
# below to get the option value. This is quite minor performance loss however.
|
|
476
|
+
added = [dep for dep in st.suppressed if find_module_simple(dep, manager)]
|
|
477
|
+
else:
|
|
478
|
+
# During initial loading we don't care about newly added modules,
|
|
479
|
+
# they will be taken care of during fine grained update. See also
|
|
480
|
+
# comment about this in `State.__init__()`.
|
|
481
|
+
added = []
|
|
482
|
+
for dep in st.ancestors + dependencies + st.suppressed:
|
|
483
|
+
ignored = dep in st.suppressed_set and dep not in entry_points
|
|
484
|
+
if ignored and dep not in added:
|
|
485
|
+
manager.missing_modules.add(dep)
|
|
486
|
+
elif dep not in graph:
|
|
487
|
+
try:
|
|
488
|
+
if dep in st.ancestors:
|
|
489
|
+
# TODO: Why not 'if dep not in st.dependencies' ?
|
|
490
|
+
# Ancestors don't have import context.
|
|
491
|
+
newst = State(
|
|
492
|
+
id=dep,
|
|
493
|
+
path=None,
|
|
494
|
+
source=None,
|
|
495
|
+
manager=manager,
|
|
496
|
+
ancestor_for=st,
|
|
497
|
+
)
|
|
498
|
+
else:
|
|
499
|
+
newst = State(
|
|
500
|
+
id=dep,
|
|
501
|
+
path=None,
|
|
502
|
+
source=None,
|
|
503
|
+
manager=manager,
|
|
504
|
+
caller_state=st,
|
|
505
|
+
caller_line=st.dep_line_map.get(dep, 1),
|
|
506
|
+
)
|
|
507
|
+
except ModuleNotFound:
|
|
508
|
+
if dep in st.dependencies_set:
|
|
509
|
+
st.suppress_dependency(dep)
|
|
510
|
+
else:
|
|
511
|
+
if newst.path:
|
|
512
|
+
newst_path = os.path.abspath(newst.path)
|
|
513
|
+
|
|
514
|
+
if newst_path in seen_files:
|
|
515
|
+
manager.errors.report(
|
|
516
|
+
-1,
|
|
517
|
+
0,
|
|
518
|
+
"Source file found twice under different module names: "
|
|
519
|
+
'"{}" and "{}"'.format(
|
|
520
|
+
seen_files[newst_path].id, newst.id
|
|
521
|
+
),
|
|
522
|
+
blocker=True,
|
|
523
|
+
)
|
|
524
|
+
manager.errors.report(
|
|
525
|
+
-1,
|
|
526
|
+
0,
|
|
527
|
+
"See https://mypy.readthedocs.io/en/stable/running"
|
|
528
|
+
+ "_mypy.html#mapping-file-paths-to-modules "
|
|
529
|
+
"for more info",
|
|
530
|
+
severity="note",
|
|
531
|
+
)
|
|
532
|
+
manager.errors.report(
|
|
533
|
+
-1,
|
|
534
|
+
0,
|
|
535
|
+
"Common resolutions include: a) adding `__init__.py` somewhere, "
|
|
536
|
+
"b) using `--explicit-package-bases` or adjusting MYPYPATH",
|
|
537
|
+
severity="note",
|
|
538
|
+
)
|
|
539
|
+
manager.errors.raise_error()
|
|
540
|
+
|
|
541
|
+
seen_files[newst_path] = newst
|
|
542
|
+
|
|
543
|
+
assert newst.id not in graph, newst.id
|
|
544
|
+
graph[newst.id] = newst
|
|
545
|
+
new.append(newst) # noqa: B038
|
|
546
|
+
if dep in graph and dep in st.suppressed_set:
|
|
547
|
+
# Previously suppressed file is now visible
|
|
548
|
+
st.add_dependency(dep)
|
|
549
|
+
manager.plugin.set_modules(manager.modules)
|
|
550
|
+
return graph
|
|
551
|
+
|
|
552
|
+
|
|
367
553
|
__all__ = [
|
|
368
554
|
"BuildManager",
|
|
369
555
|
"State",
|
jaclang/compiler/symtable.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Tests for Jac Loader."""
|
|
2
|
+
|
|
2
3
|
import sys
|
|
3
4
|
|
|
4
5
|
from jaclang import jac_import
|
|
@@ -14,11 +15,11 @@ class TestLoader(TestCase):
|
|
|
14
15
|
|
|
15
16
|
def test_import_basic_python(self) -> None:
|
|
16
17
|
"""Test basic self loading."""
|
|
17
|
-
h = jac_import("fixtures.hello_world")
|
|
18
|
+
h = jac_import("fixtures.hello_world", base_path=__file__)
|
|
18
19
|
self.assertEqual(h.hello(), "Hello World!") # type: ignore
|
|
19
20
|
|
|
20
21
|
def test_modules_correct(self) -> None:
|
|
21
22
|
"""Test basic self loading."""
|
|
22
|
-
jac_import("fixtures.hello_world")
|
|
23
|
+
jac_import("fixtures.hello_world", base_path=__file__)
|
|
23
24
|
self.assertIn("module 'hello_world'", str(sys.modules))
|
|
24
25
|
self.assertIn("/tests/fixtures/hello_world.jac", str(sys.modules))
|
jaclang/compiler/workspace.py
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"""Living Workspace of Jac project."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
import os
|
|
5
6
|
from typing import Sequence
|
|
6
7
|
|
|
7
8
|
import jaclang.compiler.absyntree as ast
|
|
9
|
+
from jaclang.compiler.compile import jac_str_to_pass
|
|
8
10
|
from jaclang.compiler.passes.main import DefUsePass
|
|
11
|
+
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
9
12
|
from jaclang.compiler.passes.transform import Alert
|
|
10
13
|
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
11
|
-
from jaclang.compiler.transpiler import jac_str_to_pass
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
def sym_tab_list(sym_tab: SymbolTable, file_path: str) -> Sequence[SymbolTable]:
|
|
@@ -103,7 +105,7 @@ class Workspace:
|
|
|
103
105
|
build = jac_str_to_pass(
|
|
104
106
|
jac_str=source,
|
|
105
107
|
file_path=file_path,
|
|
106
|
-
|
|
108
|
+
schedule=py_code_gen_typed,
|
|
107
109
|
)
|
|
108
110
|
if not isinstance(build.ir, ast.Module):
|
|
109
111
|
src = ast.JacSource(source, mod_path=file_path)
|
|
@@ -146,15 +148,26 @@ class Workspace:
|
|
|
146
148
|
"""Return a list of files in the workspace."""
|
|
147
149
|
return list(self.modules.keys())
|
|
148
150
|
|
|
149
|
-
def get_dependencies(
|
|
151
|
+
def get_dependencies(
|
|
152
|
+
self, file_path: str, deep: bool = False
|
|
153
|
+
) -> list[ast.ModulePath]:
|
|
150
154
|
"""Return a list of dependencies for a file."""
|
|
151
155
|
if deep:
|
|
152
|
-
return
|
|
156
|
+
return [
|
|
157
|
+
i
|
|
158
|
+
for i in self.modules[file_path].ir.get_all_sub_nodes(ast.ModulePath)
|
|
159
|
+
if i.parent
|
|
160
|
+
and isinstance(i.parent, ast.Import)
|
|
161
|
+
and i.parent.lang.tag.value == "jac"
|
|
162
|
+
]
|
|
153
163
|
else:
|
|
154
164
|
return [
|
|
155
165
|
i
|
|
156
|
-
for i in self.modules[file_path].ir.get_all_sub_nodes(ast.
|
|
166
|
+
for i in self.modules[file_path].ir.get_all_sub_nodes(ast.ModulePath)
|
|
157
167
|
if i.loc.mod_path == file_path
|
|
168
|
+
and i.parent
|
|
169
|
+
and isinstance(i.parent, ast.Import)
|
|
170
|
+
and i.parent.lang.tag.value == "jac"
|
|
158
171
|
]
|
|
159
172
|
|
|
160
173
|
def get_symbols(self, file_path: str) -> Sequence[Symbol]:
|