jaclang 0.8.6__py3-none-any.whl → 0.8.8__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.md +3 -3
- jaclang/cli/cli.py +37 -37
- jaclang/cli/cmdreg.py +45 -140
- jaclang/compiler/constant.py +0 -1
- jaclang/compiler/jac.lark +3 -6
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +213 -34
- jaclang/compiler/passes/main/__init__.py +2 -4
- jaclang/compiler/passes/main/def_use_pass.py +0 -4
- jaclang/compiler/passes/main/predynamo_pass.py +221 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +83 -55
- jaclang/compiler/passes/main/pyast_load_pass.py +66 -40
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
- jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
- jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
- jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_binary_op.jac +21 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_call_expr_class.jac +12 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_cyclic_symbol.jac +4 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_expr_call.jac +9 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_import_missing_module.jac +13 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_magic_call.jac +17 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_mod_path.jac +8 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
- jaclang/compiler/passes/main/tests/test_checker_pass.py +265 -0
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +57 -0
- jaclang/compiler/passes/main/type_checker_pass.py +36 -61
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +204 -44
- jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +171 -11
- jaclang/compiler/passes/transform.py +12 -8
- jaclang/compiler/program.py +14 -6
- jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
- jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
- jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
- jaclang/compiler/tests/fixtures/python_module.py +1 -0
- jaclang/compiler/tests/test_importer.py +39 -0
- jaclang/compiler/tests/test_parser.py +49 -0
- jaclang/compiler/type_system/operations.py +104 -0
- jaclang/compiler/type_system/type_evaluator.py +470 -47
- jaclang/compiler/type_system/type_utils.py +246 -0
- jaclang/compiler/type_system/types.py +58 -2
- jaclang/compiler/unitree.py +79 -94
- jaclang/langserve/engine.jac +253 -230
- jaclang/langserve/server.jac +46 -15
- jaclang/langserve/tests/fixtures/circle.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
- jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
- jaclang/langserve/tests/server_test/circle_template.jac +80 -0
- jaclang/langserve/tests/server_test/glob_template.jac +4 -0
- jaclang/langserve/tests/server_test/test_lang_serve.py +154 -312
- jaclang/langserve/tests/server_test/utils.py +153 -116
- jaclang/langserve/tests/test_dev_server.py +1 -1
- jaclang/langserve/tests/test_server.py +30 -86
- jaclang/langserve/utils.jac +56 -63
- jaclang/runtimelib/machine.py +7 -0
- jaclang/runtimelib/meta_importer.py +27 -1
- jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
- jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
- jaclang/settings.py +18 -14
- jaclang/tests/fixtures/abc_check.jac +3 -3
- jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
- jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
- jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
- jaclang/tests/fixtures/jac_run_py_bugs.py +18 -0
- jaclang/tests/fixtures/jac_run_py_import.py +13 -0
- jaclang/tests/fixtures/lambda_arg_annotation.jac +15 -0
- jaclang/tests/fixtures/lambda_self.jac +18 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
- jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
- jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
- jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
- jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
- jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
- jaclang/tests/fixtures/py2jac_params.py +8 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/test_cli.py +103 -18
- jaclang/tests/test_language.py +74 -16
- jaclang/utils/helpers.py +47 -2
- jaclang/utils/module_resolver.py +11 -1
- jaclang/utils/test.py +8 -0
- jaclang/utils/treeprinter.py +0 -18
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/METADATA +3 -3
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/RECORD +99 -62
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/WHEEL +1 -1
- jaclang/compiler/passes/main/inheritance_pass.py +0 -131
- jaclang/langserve/dev_engine.jac +0 -645
- jaclang/langserve/dev_server.jac +0 -201
- jaclang/langserve/tests/server_test/code_test.py +0 -0
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/entry_points.txt +0 -0
|
@@ -1000,37 +1000,45 @@ class PyastGenPass(UniPass):
|
|
|
1000
1000
|
pass
|
|
1001
1001
|
|
|
1002
1002
|
def exit_func_signature(self, node: uni.FuncSignature) -> None:
|
|
1003
|
+
posonlyargs = [i.gen.py_ast[0] for i in node.posonly_params]
|
|
1004
|
+
vararg = node.varargs.gen.py_ast[0] if node.varargs else None
|
|
1005
|
+
kwarg = node.kwargs.gen.py_ast[0] if node.kwargs else None
|
|
1003
1006
|
params = (
|
|
1004
1007
|
[self.sync(ast3.arg(arg="self", annotation=None))]
|
|
1005
|
-
if (abl := node.
|
|
1008
|
+
if (abl := node.parent)
|
|
1009
|
+
and isinstance(abl, uni.Ability)
|
|
1006
1010
|
and abl.is_method
|
|
1007
1011
|
and not node.is_static
|
|
1008
1012
|
and not node.is_in_py_class
|
|
1009
1013
|
else []
|
|
1010
1014
|
)
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1015
|
+
if posonlyargs:
|
|
1016
|
+
posonlyargs = params + posonlyargs
|
|
1017
|
+
params = [i.gen.py_ast[0] for i in node.params]
|
|
1018
|
+
else:
|
|
1019
|
+
params = params + [i.gen.py_ast[0] for i in node.params]
|
|
1020
|
+
defaults = []
|
|
1021
|
+
for i in [*node.posonly_params, *node.params]:
|
|
1022
|
+
if i.value:
|
|
1023
|
+
defaults.append(cast(ast3.expr, i.value.gen.py_ast[0]))
|
|
1024
|
+
kwonly_args = [i.gen.py_ast[0] for i in node.kwonlyargs]
|
|
1025
|
+
# kw_defaults must be the same length as kwonlyargs
|
|
1026
|
+
# it will have None for args that don't have defaults
|
|
1027
|
+
kw_defaults: list[ast3.expr | None] = []
|
|
1028
|
+
for i in node.kwonlyargs:
|
|
1029
|
+
if i.value:
|
|
1030
|
+
kw_defaults.append(cast(ast3.expr, i.value.gen.py_ast[0]))
|
|
1018
1031
|
else:
|
|
1019
|
-
(
|
|
1020
|
-
params.append(i.gen.py_ast[0])
|
|
1021
|
-
if isinstance(i.gen.py_ast[0], ast3.arg)
|
|
1022
|
-
else self.ice("This list should only be Args")
|
|
1023
|
-
)
|
|
1024
|
-
defaults = [x.value.gen.py_ast[0] for x in node.params if x.value]
|
|
1032
|
+
kw_defaults.append(None)
|
|
1025
1033
|
node.gen.py_ast = [
|
|
1026
1034
|
self.sync(
|
|
1027
1035
|
ast3.arguments(
|
|
1028
|
-
posonlyargs=[],
|
|
1036
|
+
posonlyargs=[cast(ast3.arg, param) for param in posonlyargs],
|
|
1029
1037
|
args=[cast(ast3.arg, param) for param in params],
|
|
1030
|
-
kwonlyargs=
|
|
1038
|
+
kwonlyargs=kwonly_args,
|
|
1031
1039
|
vararg=cast(ast3.arg, vararg) if vararg else None,
|
|
1032
1040
|
kwarg=cast(ast3.arg, kwarg) if kwarg else None,
|
|
1033
|
-
kw_defaults=
|
|
1041
|
+
kw_defaults=kw_defaults,
|
|
1034
1042
|
defaults=[cast(ast3.expr, default) for default in defaults],
|
|
1035
1043
|
)
|
|
1036
1044
|
)
|
|
@@ -1466,20 +1474,23 @@ class PyastGenPass(UniPass):
|
|
|
1466
1474
|
]
|
|
1467
1475
|
|
|
1468
1476
|
def exit_assert_stmt(self, node: uni.AssertStmt) -> None:
|
|
1469
|
-
node.
|
|
1470
|
-
self.
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1477
|
+
if isinstance(node.parent, uni.Test):
|
|
1478
|
+
self.assert_helper(node)
|
|
1479
|
+
else:
|
|
1480
|
+
node.gen.py_ast = [
|
|
1481
|
+
self.sync(
|
|
1482
|
+
ast3.Assert(
|
|
1483
|
+
test=cast(ast3.expr, node.condition.gen.py_ast[0]),
|
|
1484
|
+
msg=(
|
|
1485
|
+
cast(ast3.expr, node.error_msg.gen.py_ast[0])
|
|
1486
|
+
if node.error_msg
|
|
1487
|
+
else None
|
|
1488
|
+
),
|
|
1489
|
+
)
|
|
1478
1490
|
)
|
|
1479
|
-
|
|
1480
|
-
]
|
|
1491
|
+
]
|
|
1481
1492
|
|
|
1482
|
-
def
|
|
1493
|
+
def assert_helper(self, node: uni.AssertStmt) -> None:
|
|
1483
1494
|
"""Sub objects.
|
|
1484
1495
|
|
|
1485
1496
|
target: ExprType,
|
|
@@ -1535,16 +1546,16 @@ class PyastGenPass(UniPass):
|
|
|
1535
1546
|
|
|
1536
1547
|
# By default the check expression will become assertTrue(<expr>), unless any pattern detected.
|
|
1537
1548
|
assert_func_name = "assertTrue"
|
|
1538
|
-
assert_args_list = node.
|
|
1549
|
+
assert_args_list = node.condition.gen.py_ast
|
|
1539
1550
|
|
|
1540
1551
|
# Compare operations. Note that We're only considering the compare
|
|
1541
1552
|
# operation with a single operation ie. a < b < c is ignored here.
|
|
1542
1553
|
if (
|
|
1543
|
-
isinstance(node.
|
|
1544
|
-
and isinstance(node.
|
|
1545
|
-
and len(node.
|
|
1554
|
+
isinstance(node.condition, uni.CompareExpr)
|
|
1555
|
+
and isinstance(node.condition.gen.py_ast[0], ast3.Compare)
|
|
1556
|
+
and len(node.condition.ops) == 1
|
|
1546
1557
|
):
|
|
1547
|
-
expr: uni.CompareExpr = node.
|
|
1558
|
+
expr: uni.CompareExpr = node.condition
|
|
1548
1559
|
opty: uni.Token = expr.ops[0]
|
|
1549
1560
|
|
|
1550
1561
|
optype2fn = {
|
|
@@ -1578,10 +1589,10 @@ class PyastGenPass(UniPass):
|
|
|
1578
1589
|
assert_args_list.pop()
|
|
1579
1590
|
|
|
1580
1591
|
# Check if 'isinstance' is called.
|
|
1581
|
-
elif isinstance(node.
|
|
1582
|
-
node.
|
|
1592
|
+
elif isinstance(node.condition, uni.FuncCall) and isinstance(
|
|
1593
|
+
node.condition.gen.py_ast[0], ast3.Call
|
|
1583
1594
|
):
|
|
1584
|
-
res = check_node_isinstance_call(node.
|
|
1595
|
+
res = check_node_isinstance_call(node.condition)
|
|
1585
1596
|
if res.isit:
|
|
1586
1597
|
# These assertions will make mypy happy.
|
|
1587
1598
|
assert isinstance(res.inst, ast3.AST)
|
|
@@ -1591,12 +1602,12 @@ class PyastGenPass(UniPass):
|
|
|
1591
1602
|
|
|
1592
1603
|
# Check if 'not isinstance(<expr>, <expr>)' is called.
|
|
1593
1604
|
elif (
|
|
1594
|
-
isinstance(node.
|
|
1595
|
-
and isinstance(node.
|
|
1596
|
-
and isinstance(node.
|
|
1597
|
-
and isinstance(node.
|
|
1605
|
+
isinstance(node.condition, uni.UnaryExpr)
|
|
1606
|
+
and isinstance(node.condition, uni.UnaryExpr)
|
|
1607
|
+
and isinstance(node.condition.operand, uni.FuncCall)
|
|
1608
|
+
and isinstance(node.condition.operand, uni.UnaryExpr)
|
|
1598
1609
|
):
|
|
1599
|
-
res = check_node_isinstance_call(node.
|
|
1610
|
+
res = check_node_isinstance_call(node.condition.operand)
|
|
1600
1611
|
if res.isit:
|
|
1601
1612
|
# These assertions will make mypy happy.
|
|
1602
1613
|
assert isinstance(res.inst, ast3.AST)
|
|
@@ -1609,14 +1620,14 @@ class PyastGenPass(UniPass):
|
|
|
1609
1620
|
# the almost equal functionality (snice there is no almost equal operator in jac and never needed ig.).
|
|
1610
1621
|
|
|
1611
1622
|
# Check if 'almostEqual' is called.
|
|
1612
|
-
if isinstance(node.
|
|
1613
|
-
node.
|
|
1623
|
+
if isinstance(node.condition, uni.FuncCall) and isinstance(
|
|
1624
|
+
node.condition.gen.py_ast[0], ast3.Call
|
|
1614
1625
|
):
|
|
1615
|
-
func = node.
|
|
1626
|
+
func = node.condition.target
|
|
1616
1627
|
if isinstance(func, uni.Name) and func.value == "almostEqual":
|
|
1617
1628
|
assert_func_name = "assertAlmostEqual"
|
|
1618
1629
|
assert_args_list = []
|
|
1619
|
-
for param in node.
|
|
1630
|
+
for param in node.condition.params:
|
|
1620
1631
|
assert_args_list.append(param.gen.py_ast[0])
|
|
1621
1632
|
|
|
1622
1633
|
# assert_func_expr = "Con.JAC_CHECK.value.assertXXX"
|
|
@@ -2123,6 +2134,10 @@ class PyastGenPass(UniPass):
|
|
|
2123
2134
|
]
|
|
2124
2135
|
|
|
2125
2136
|
def exit_lambda_expr(self, node: uni.LambdaExpr) -> None:
|
|
2137
|
+
# Python lambda expressions don't support type annotations
|
|
2138
|
+
if node.signature:
|
|
2139
|
+
self._remove_lambda_param_annotations(node.signature)
|
|
2140
|
+
|
|
2126
2141
|
node.gen.py_ast = [
|
|
2127
2142
|
self.sync(
|
|
2128
2143
|
ast3.Lambda(
|
|
@@ -2144,6 +2159,11 @@ class PyastGenPass(UniPass):
|
|
|
2144
2159
|
)
|
|
2145
2160
|
]
|
|
2146
2161
|
|
|
2162
|
+
def _remove_lambda_param_annotations(self, signature: uni.FuncSignature) -> None:
|
|
2163
|
+
for param in signature.params:
|
|
2164
|
+
if param.gen.py_ast and isinstance(param.gen.py_ast[0], ast3.arg):
|
|
2165
|
+
param.gen.py_ast[0].annotation = None
|
|
2166
|
+
|
|
2147
2167
|
def exit_unary_expr(self, node: uni.UnaryExpr) -> None:
|
|
2148
2168
|
op_cls = UNARY_OP_MAP.get(node.op.name)
|
|
2149
2169
|
if op_cls:
|
|
@@ -2400,7 +2420,7 @@ class PyastGenPass(UniPass):
|
|
|
2400
2420
|
self.sync(
|
|
2401
2421
|
ast3.Attribute(
|
|
2402
2422
|
value=cast(ast3.expr, node.target.gen.py_ast[0]),
|
|
2403
|
-
attr=
|
|
2423
|
+
attr=node.right.sym_name,
|
|
2404
2424
|
ctx=cast(ast3.expr_context, node.right.py_ctx_func()),
|
|
2405
2425
|
)
|
|
2406
2426
|
)
|
|
@@ -2708,14 +2728,22 @@ class PyastGenPass(UniPass):
|
|
|
2708
2728
|
keywords=[],
|
|
2709
2729
|
)
|
|
2710
2730
|
)
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2731
|
+
if node.is_async:
|
|
2732
|
+
pynode = self.sync(
|
|
2733
|
+
ast3.Call(
|
|
2734
|
+
func=self.jaclib_obj("arefs"),
|
|
2735
|
+
args=[pynode],
|
|
2736
|
+
keywords=[],
|
|
2737
|
+
)
|
|
2738
|
+
)
|
|
2739
|
+
else:
|
|
2740
|
+
pynode = self.sync(
|
|
2741
|
+
ast3.Call(
|
|
2742
|
+
func=self.jaclib_obj("refs"),
|
|
2743
|
+
args=[pynode],
|
|
2744
|
+
keywords=[],
|
|
2745
|
+
)
|
|
2717
2746
|
)
|
|
2718
|
-
)
|
|
2719
2747
|
|
|
2720
2748
|
node.gen.py_ast = [pynode]
|
|
2721
2749
|
|
|
@@ -2997,7 +3025,7 @@ class PyastGenPass(UniPass):
|
|
|
2997
3025
|
node.gen.py_ast = [self.sync(op_cls())]
|
|
2998
3026
|
|
|
2999
3027
|
def exit_name(self, node: uni.Name) -> None:
|
|
3000
|
-
name = node.sym_name
|
|
3028
|
+
name = node.sym_name
|
|
3001
3029
|
node.gen.py_ast = [self.sync(ast3.Name(id=name, ctx=node.py_ctx_func()))]
|
|
3002
3030
|
|
|
3003
3031
|
def exit_float(self, node: uni.Float) -> None:
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
import ast as py_ast
|
|
18
18
|
import os
|
|
19
|
-
from typing import Optional, Sequence, TYPE_CHECKING, TypeAlias, TypeVar
|
|
19
|
+
from typing import Optional, Sequence, TYPE_CHECKING, TypeAlias, TypeVar, cast
|
|
20
20
|
|
|
21
21
|
import jaclang.compiler.unitree as uni
|
|
22
22
|
from jaclang.compiler.constant import Tokens as Tok
|
|
@@ -141,17 +141,17 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
141
141
|
|
|
142
142
|
reserved_keywords = [v for _, v in TOKEN_MAP.items()]
|
|
143
143
|
|
|
144
|
-
value = node.name if node.name not in reserved_keywords else f"<>{node.name}"
|
|
145
144
|
name = uni.Name(
|
|
146
145
|
orig_src=self.orig_src,
|
|
147
146
|
name=Tok.NAME,
|
|
148
|
-
value=
|
|
147
|
+
value=node.name,
|
|
149
148
|
line=node.lineno,
|
|
150
149
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
151
150
|
col_start=node.col_offset,
|
|
152
151
|
col_end=node.col_offset + len(node.name),
|
|
153
152
|
pos_start=0,
|
|
154
153
|
pos_end=0,
|
|
154
|
+
is_kwesc=(node.name in reserved_keywords),
|
|
155
155
|
)
|
|
156
156
|
body = [self.convert(i) for i in node.body]
|
|
157
157
|
valid = [i for i in body if isinstance(i, (uni.CodeBlockStmt))]
|
|
@@ -285,8 +285,8 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
285
285
|
and body_stmt.signature.params
|
|
286
286
|
):
|
|
287
287
|
for param in body_stmt.signature.params:
|
|
288
|
-
if param.name.value == "self":
|
|
289
|
-
param.type_tag
|
|
288
|
+
if param.name.value == "self" and param.type_tag:
|
|
289
|
+
param.type_tag.tag.value = name.value
|
|
290
290
|
doc = (
|
|
291
291
|
body[0].expr
|
|
292
292
|
if isinstance(body[0], uni.ExprStmt)
|
|
@@ -748,17 +748,14 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
748
748
|
attribute = uni.Name(
|
|
749
749
|
orig_src=self.orig_src,
|
|
750
750
|
name=Tok.NAME,
|
|
751
|
-
value=
|
|
752
|
-
("<>" + node.attr)
|
|
753
|
-
if node.attr == "init"
|
|
754
|
-
else "init" if node.attr == "__init__" else node.attr
|
|
755
|
-
),
|
|
751
|
+
value="init" if node.attr == "__init__" else node.attr,
|
|
756
752
|
line=node.lineno,
|
|
757
753
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
758
754
|
col_start=node.col_offset,
|
|
759
755
|
col_end=node.col_offset + len(node.attr),
|
|
760
756
|
pos_start=0,
|
|
761
757
|
pos_end=0,
|
|
758
|
+
is_kwesc=node.attr == "init",
|
|
762
759
|
)
|
|
763
760
|
if isinstance(value, uni.Expr):
|
|
764
761
|
return uni.AtomTrailer(
|
|
@@ -1680,18 +1677,17 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
1680
1677
|
for _, v in TOKEN_MAP.items()
|
|
1681
1678
|
if v not in ["float", "int", "str", "bool", "self"]
|
|
1682
1679
|
]
|
|
1683
|
-
|
|
1684
|
-
value = node.id if node.id not in reserved_keywords else f"<>{node.id}"
|
|
1685
1680
|
ret = uni.Name(
|
|
1686
1681
|
orig_src=self.orig_src,
|
|
1687
1682
|
name=Tok.NAME,
|
|
1688
|
-
value=
|
|
1683
|
+
value=node.id,
|
|
1689
1684
|
line=node.lineno,
|
|
1690
1685
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
1691
1686
|
col_start=node.col_offset,
|
|
1692
1687
|
col_end=node.col_offset + len(node.id),
|
|
1693
1688
|
pos_start=0,
|
|
1694
1689
|
pos_end=0,
|
|
1690
|
+
is_kwesc=(node.id in reserved_keywords),
|
|
1695
1691
|
)
|
|
1696
1692
|
return ret
|
|
1697
1693
|
|
|
@@ -1735,18 +1731,18 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
1735
1731
|
|
|
1736
1732
|
names: list[uni.NameAtom] = []
|
|
1737
1733
|
for name in node.names:
|
|
1738
|
-
value = name if name not in reserved_keywords else f"<>{name}"
|
|
1739
1734
|
names.append(
|
|
1740
1735
|
uni.Name(
|
|
1741
1736
|
orig_src=self.orig_src,
|
|
1742
1737
|
name=Tok.NAME,
|
|
1743
|
-
value=
|
|
1738
|
+
value=name,
|
|
1744
1739
|
line=node.lineno,
|
|
1745
1740
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
1746
1741
|
col_start=node.col_offset,
|
|
1747
1742
|
col_end=node.col_offset + len(name),
|
|
1748
1743
|
pos_start=0,
|
|
1749
1744
|
pos_end=0,
|
|
1745
|
+
is_kwesc=(name in reserved_keywords),
|
|
1750
1746
|
)
|
|
1751
1747
|
)
|
|
1752
1748
|
return uni.NonLocalStmt(target=names, kid=names)
|
|
@@ -2056,17 +2052,17 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
2056
2052
|
if v not in ["float", "int", "str", "bool", "self"]
|
|
2057
2053
|
]
|
|
2058
2054
|
|
|
2059
|
-
value = node.arg if node.arg not in reserved_keywords else f"<>{node.arg}"
|
|
2060
2055
|
name = uni.Name(
|
|
2061
2056
|
orig_src=self.orig_src,
|
|
2062
2057
|
name=Tok.NAME,
|
|
2063
|
-
value=
|
|
2058
|
+
value=node.arg,
|
|
2064
2059
|
line=node.lineno,
|
|
2065
2060
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
2066
2061
|
col_start=node.col_offset,
|
|
2067
2062
|
col_end=node.col_offset + len(node.arg),
|
|
2068
2063
|
pos_start=0,
|
|
2069
2064
|
pos_end=0,
|
|
2065
|
+
is_kwesc=(node.arg in reserved_keywords),
|
|
2070
2066
|
)
|
|
2071
2067
|
ann_expr = (
|
|
2072
2068
|
self.convert(node.annotation)
|
|
@@ -2095,6 +2091,7 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
2095
2091
|
"""Process python node.
|
|
2096
2092
|
|
|
2097
2093
|
class arguments(AST):
|
|
2094
|
+
posonlyargs: list[arg]
|
|
2098
2095
|
args: list[arg]
|
|
2099
2096
|
vararg: arg | None
|
|
2100
2097
|
kwonlyargs: list[arg]
|
|
@@ -2102,9 +2099,23 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
2102
2099
|
kwarg: arg | None
|
|
2103
2100
|
defaults: list[expr]
|
|
2104
2101
|
"""
|
|
2105
|
-
|
|
2102
|
+
|
|
2103
|
+
def _apply_kind(params: list, kind: uni.ParamKind) -> list:
|
|
2104
|
+
for param in params:
|
|
2105
|
+
cast(uni.ParamVar, param).param_kind = kind
|
|
2106
|
+
return params
|
|
2107
|
+
|
|
2108
|
+
posonlyargs = _apply_kind(
|
|
2109
|
+
[self.convert(arg) for arg in node.posonlyargs], uni.ParamKind.POSONLY
|
|
2110
|
+
)
|
|
2111
|
+
args = _apply_kind(
|
|
2112
|
+
[self.convert(arg) for arg in node.args], uni.ParamKind.NORMAL
|
|
2113
|
+
)
|
|
2114
|
+
|
|
2106
2115
|
vararg = self.convert(node.vararg) if node.vararg else None
|
|
2116
|
+
|
|
2107
2117
|
if vararg and isinstance(vararg, uni.ParamVar):
|
|
2118
|
+
vararg.param_kind = uni.ParamKind.VARARG
|
|
2108
2119
|
vararg.unpack = uni.Token(
|
|
2109
2120
|
orig_src=self.orig_src,
|
|
2110
2121
|
name=Tok.STAR_MUL,
|
|
@@ -2117,7 +2128,10 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
2117
2128
|
pos_end=0,
|
|
2118
2129
|
)
|
|
2119
2130
|
vararg.add_kids_left([vararg.unpack])
|
|
2120
|
-
|
|
2131
|
+
|
|
2132
|
+
kwonlyargs = _apply_kind(
|
|
2133
|
+
[self.convert(arg) for arg in node.kwonlyargs], uni.ParamKind.KWONLY
|
|
2134
|
+
)
|
|
2121
2135
|
for i in range(len(kwonlyargs)):
|
|
2122
2136
|
kwa = kwonlyargs[i]
|
|
2123
2137
|
kwd = node.kw_defaults[i]
|
|
@@ -2131,6 +2145,7 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
2131
2145
|
kwa.add_kids_right([kwa.value])
|
|
2132
2146
|
kwarg = self.convert(node.kwarg) if node.kwarg else None
|
|
2133
2147
|
if kwarg and isinstance(kwarg, uni.ParamVar):
|
|
2148
|
+
kwarg.param_kind = uni.ParamKind.KWARG
|
|
2134
2149
|
kwarg.unpack = uni.Token(
|
|
2135
2150
|
orig_src=self.orig_src,
|
|
2136
2151
|
name=Tok.STAR_POW,
|
|
@@ -2144,29 +2159,42 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
2144
2159
|
)
|
|
2145
2160
|
kwarg.add_kids_left([kwarg.unpack])
|
|
2146
2161
|
defaults = [self.convert(expr) for expr in node.defaults]
|
|
2147
|
-
|
|
2148
|
-
for
|
|
2149
|
-
if
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
if
|
|
2161
|
-
|
|
2162
|
+
# iterate reverse to match from the end
|
|
2163
|
+
for para in [*posonlyargs, *args][::-1]:
|
|
2164
|
+
if not defaults:
|
|
2165
|
+
break
|
|
2166
|
+
default = defaults.pop()
|
|
2167
|
+
if (
|
|
2168
|
+
default
|
|
2169
|
+
and isinstance(para, uni.ParamVar)
|
|
2170
|
+
and isinstance(default, uni.Expr)
|
|
2171
|
+
):
|
|
2172
|
+
para.value = default
|
|
2173
|
+
para.add_kids_right([para.value])
|
|
2174
|
+
|
|
2175
|
+
if kwonlyargs or args or posonlyargs or vararg or kwarg:
|
|
2176
|
+
kids = []
|
|
2177
|
+
kids.extend(posonlyargs) if posonlyargs else None
|
|
2178
|
+
kids.extend(args) if args else None
|
|
2179
|
+
kids.append(vararg) if vararg else None
|
|
2180
|
+
kids.extend(kwonlyargs) if kwonlyargs else None
|
|
2181
|
+
kids.append(kwarg) if kwarg else None
|
|
2162
2182
|
return uni.FuncSignature(
|
|
2163
|
-
|
|
2183
|
+
posonly_params=posonlyargs,
|
|
2184
|
+
params=args,
|
|
2185
|
+
varargs=vararg,
|
|
2186
|
+
kwonlyargs=kwonlyargs,
|
|
2187
|
+
kwargs=kwarg,
|
|
2164
2188
|
return_type=None,
|
|
2165
|
-
kid=
|
|
2189
|
+
kid=kids,
|
|
2166
2190
|
)
|
|
2167
2191
|
else:
|
|
2168
2192
|
return uni.FuncSignature(
|
|
2193
|
+
posonly_params=posonlyargs,
|
|
2169
2194
|
params=[],
|
|
2195
|
+
varargs=vararg,
|
|
2196
|
+
kwonlyargs=kwonlyargs,
|
|
2197
|
+
kwargs=kwarg,
|
|
2170
2198
|
return_type=None,
|
|
2171
2199
|
kid=[self.operator(Tok.LPAREN, "("), self.operator(Tok.RPAREN, ")")],
|
|
2172
2200
|
)
|
|
@@ -2343,19 +2371,17 @@ class PyastBuildPass(Transform[uni.PythonModuleAst, uni.Module]):
|
|
|
2343
2371
|
from jaclang.compiler import TOKEN_MAP
|
|
2344
2372
|
|
|
2345
2373
|
reserved_keywords = [v for _, v in TOKEN_MAP.items()]
|
|
2346
|
-
arg_value = (
|
|
2347
|
-
node.arg if node.arg not in reserved_keywords else f"<>{node.arg}"
|
|
2348
|
-
)
|
|
2349
2374
|
arg = uni.Name(
|
|
2350
2375
|
orig_src=self.orig_src,
|
|
2351
2376
|
name=Tok.NAME,
|
|
2352
|
-
value=
|
|
2377
|
+
value=node.arg,
|
|
2353
2378
|
line=node.lineno,
|
|
2354
2379
|
end_line=node.end_lineno if node.end_lineno else node.lineno,
|
|
2355
2380
|
col_start=node.col_offset,
|
|
2356
2381
|
col_end=node.col_offset + len(node.arg if node.arg else "_"),
|
|
2357
2382
|
pos_start=0,
|
|
2358
2383
|
pos_end=0,
|
|
2384
|
+
is_kwesc=(node.arg in reserved_keywords),
|
|
2359
2385
|
)
|
|
2360
2386
|
value = self.convert(node.value)
|
|
2361
2387
|
if isinstance(value, uni.Expr):
|
|
@@ -75,7 +75,7 @@ class SymTabBuildPass(UniPass):
|
|
|
75
75
|
def exit_module_path(self, node: uni.ModulePath) -> None:
|
|
76
76
|
if node.alias:
|
|
77
77
|
node.alias.sym_tab.def_insert(node.alias, single_decl="import")
|
|
78
|
-
elif node.path
|
|
78
|
+
elif node.path:
|
|
79
79
|
if node.parent_of_type(uni.Import) and not (
|
|
80
80
|
node.parent_of_type(uni.Import).from_loc
|
|
81
81
|
and node.parent_of_type(uni.Import).is_jac
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
class Foo {
|
|
3
|
+
def bar(self: Foo, a:int) -> None {}
|
|
4
|
+
static def baz(self: int, a: int) -> None {}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
def foo(a: int, b: int, /, c:int, d:int, *args:int, e:int, f:int, **kwargs:int) -> None {}
|
|
8
|
+
def bar(a: int, b: int, /, c:int, d:int, e:int, f:int) -> None {}
|
|
9
|
+
def baz(a: int, *, b:int) -> None {}
|
|
10
|
+
|
|
11
|
+
with entry {
|
|
12
|
+
f = Foo();
|
|
13
|
+
|
|
14
|
+
f.bar();
|
|
15
|
+
f.bar(1);
|
|
16
|
+
f.bar(1, 2);
|
|
17
|
+
|
|
18
|
+
f.baz();
|
|
19
|
+
f.baz(1);
|
|
20
|
+
f.baz(1, 2);
|
|
21
|
+
|
|
22
|
+
foo(1, 2, 3, d=4, e=5, f=6, g=7, h=8); # c is positional and d is named
|
|
23
|
+
foo(1, 2, 3, 4, 5, 6, 7, 8, e=5, f=6); # marching extra with *args
|
|
24
|
+
foo(1, 2, d=3, e=4, f=5, c=4); # order does not matter for named
|
|
25
|
+
|
|
26
|
+
foo(1, 2, 3, d=4, e=5, g=7, h=8); # missing argument 'f'
|
|
27
|
+
foo(1, b=2, c=3, d=4, e=5, f=6); # b is positional only
|
|
28
|
+
|
|
29
|
+
bar(1, 2, 3, 4, 5, f=6);
|
|
30
|
+
bar(1, 2, 3, 4, 5, 6, 7, 8, 9); # too many args
|
|
31
|
+
bar(1, 2, 3, 4, 5, 6, c=3); # already matched
|
|
32
|
+
bar(1, 2, 3, 4, 5, 6, h=1); # h is not matched
|
|
33
|
+
|
|
34
|
+
baz(a=1, b=2);
|
|
35
|
+
baz(1, b=2); # a can be both positional and keyword
|
|
36
|
+
baz(1, 2); # 'b' can only be keyword arg
|
|
37
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
class Foo {
|
|
3
|
+
def first_is_self(self: Foo) -> None {}
|
|
4
|
+
|
|
5
|
+
def with_default_args(self: Foo, a:int, b:int=42) -> None {}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
with entry {
|
|
10
|
+
f = Foo();
|
|
11
|
+
f.first_is_self(); # <-- Ok
|
|
12
|
+
f.first_is_self(f); # <-- Error
|
|
13
|
+
|
|
14
|
+
f.with_default_args(1); # <-- Ok
|
|
15
|
+
f.with_default_args(1, 2); # <-- Ok
|
|
16
|
+
f.with_default_args(1, 2, 3); # <-- Error
|
|
17
|
+
f.with_default_args(); # <-- Error
|
|
18
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
node B {
|
|
2
|
+
def __mul__(other: B) -> int {
|
|
3
|
+
return 0;
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
node A {
|
|
8
|
+
def __add__(other: A) -> B {
|
|
9
|
+
return B();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
with entry {
|
|
14
|
+
a: A = A();
|
|
15
|
+
|
|
16
|
+
r1: B = a + a; # <-- Ok
|
|
17
|
+
r2: A = a + a; # <-- Error
|
|
18
|
+
|
|
19
|
+
r3: int = (a+a) * B(); # <-- Ok
|
|
20
|
+
r4: str = (a+a) * B(); # <-- Error
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
obj Animal {}
|
|
3
|
+
obj Cat(Animal) {}
|
|
4
|
+
obj Lion(Cat) {}
|
|
5
|
+
|
|
6
|
+
obj NotAnimal {}
|
|
7
|
+
|
|
8
|
+
def animal_func(a: Animal) -> None {}
|
|
9
|
+
|
|
10
|
+
with entry {
|
|
11
|
+
cat: Cat = Cat();
|
|
12
|
+
lion: Lion = Lion();
|
|
13
|
+
not_animal: NotAnimal = NotAnimal();
|
|
14
|
+
|
|
15
|
+
animal_func(cat); # <-- Ok
|
|
16
|
+
animal_func(lion); # <-- Ok
|
|
17
|
+
animal_func(not_animal); # <-- Error
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import from scipy { stats, optimize }
|
|
2
|
+
import from utils.fake_helpers { helper_func }
|
|
3
|
+
import from non_existent_module { foo }
|
|
4
|
+
import nonexistent_module as nm;
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
with entry {
|
|
8
|
+
a: int = stats.norm.cdf(0);
|
|
9
|
+
d: float = optimize.minimize_scalar(lambda x: int: x ** 2).fun;
|
|
10
|
+
result = helper_func();
|
|
11
|
+
b: int = foo();
|
|
12
|
+
c = nm.some_func();
|
|
13
|
+
}
|