jaclang 0.8.7__py3-none-any.whl → 0.8.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/cli/cli.py +77 -29
- jaclang/cli/cmdreg.py +44 -0
- jaclang/compiler/constant.py +6 -2
- jaclang/compiler/jac.lark +37 -47
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +356 -61
- jaclang/compiler/passes/main/__init__.py +2 -4
- jaclang/compiler/passes/main/def_use_pass.py +1 -4
- jaclang/compiler/passes/main/predynamo_pass.py +221 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +221 -135
- jaclang/compiler/passes/main/pyast_load_pass.py +54 -20
- 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_cat_is_animal.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -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 +190 -0
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +56 -0
- jaclang/compiler/passes/main/type_checker_pass.py +29 -73
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +302 -58
- 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/import_fmt.jac +7 -1
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +276 -10
- jaclang/compiler/passes/transform.py +12 -8
- jaclang/compiler/program.py +19 -7
- 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/type_evaluator.jac +959 -0
- jaclang/compiler/type_system/type_utils.py +246 -0
- jaclang/compiler/type_system/types.py +58 -2
- jaclang/compiler/unitree.py +102 -107
- jaclang/langserve/engine.jac +138 -159
- jaclang/langserve/server.jac +25 -1
- 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 -309
- jaclang/langserve/tests/server_test/utils.py +153 -116
- jaclang/langserve/tests/test_server.py +21 -84
- jaclang/langserve/utils.jac +12 -15
- jaclang/lib.py +17 -0
- jaclang/runtimelib/archetype.py +25 -25
- jaclang/runtimelib/constructs.py +2 -2
- jaclang/runtimelib/machine.py +63 -46
- 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 +19 -16
- jaclang/tests/fixtures/abc_check.jac +3 -3
- jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
- jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
- jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
- jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
- jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
- jaclang/tests/fixtures/funccall_genexpr.py +5 -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 +159 -7
- jaclang/tests/test_language.py +213 -38
- jaclang/tests/test_reference.py +3 -1
- jaclang/utils/helpers.py +67 -6
- jaclang/utils/module_resolver.py +10 -0
- jaclang/utils/test.py +8 -0
- jaclang/utils/tests/test_lang_tools.py +4 -15
- jaclang/utils/treeprinter.py +0 -18
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -2
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/RECORD +95 -65
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/WHEEL +1 -1
- jaclang/compiler/passes/main/inheritance_pass.py +0 -131
- jaclang/compiler/type_system/type_evaluator.py +0 -560
- jaclang/langserve/dev_engine.jac +0 -645
- jaclang/langserve/dev_server.jac +0 -201
- /jaclang/{langserve/tests/server_test/code_test.py → tests/fixtures/py2jac_empty.py} +0 -0
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
jaclang/compiler/parser.py
CHANGED
|
@@ -5,12 +5,14 @@ from __future__ import annotations
|
|
|
5
5
|
import keyword
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
|
+
import sys
|
|
8
9
|
from typing import Callable, Sequence, TYPE_CHECKING, TypeAlias, TypeVar, cast
|
|
9
10
|
|
|
10
11
|
import jaclang.compiler.unitree as uni
|
|
11
|
-
from jaclang.compiler import jac_lark as jl
|
|
12
|
+
from jaclang.compiler import TOKEN_MAP, jac_lark as jl
|
|
12
13
|
from jaclang.compiler.constant import EdgeDir, Tokens as Tok
|
|
13
14
|
from jaclang.compiler.passes.main import Transform
|
|
15
|
+
from jaclang.utils.helpers import ANSIColors
|
|
14
16
|
from jaclang.vendor.lark import Lark, Transformer, Tree, logger
|
|
15
17
|
|
|
16
18
|
if TYPE_CHECKING:
|
|
@@ -39,22 +41,17 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
39
41
|
tree, comments = JacParser.parse(ir_in.value, on_error=self.error_callback)
|
|
40
42
|
mod = JacParser.TreeToAST(parser=self).transform(tree)
|
|
41
43
|
ir_in.comments = [self.proc_comment(i, mod) for i in comments]
|
|
42
|
-
if isinstance(mod, uni.Module):
|
|
43
|
-
self.ir_out = mod
|
|
44
|
-
return mod
|
|
45
|
-
else:
|
|
44
|
+
if not isinstance(mod, uni.Module):
|
|
46
45
|
raise self.ice()
|
|
46
|
+
if len(self.errors_had) != 0:
|
|
47
|
+
mod.has_syntax_errors = True
|
|
48
|
+
self.report_errors()
|
|
49
|
+
self.ir_out = mod
|
|
50
|
+
return mod
|
|
47
51
|
except jl.UnexpectedInput as e:
|
|
48
|
-
catch_error =
|
|
49
|
-
|
|
50
|
-
catch_error.line_no = e.line
|
|
51
|
-
catch_error.end_line = e.line
|
|
52
|
-
catch_error.c_start = e.column
|
|
53
|
-
catch_error.c_end = e.column + 1
|
|
54
|
-
catch_error.pos_start = e.pos_in_stream or 0
|
|
55
|
-
catch_error.pos_end = catch_error.pos_start + 1
|
|
52
|
+
catch_error = self.error_to_token(e)
|
|
53
|
+
error_msg = self.error_to_message(e)
|
|
56
54
|
|
|
57
|
-
error_msg = "Syntax Error"
|
|
58
55
|
if len(e.args) >= 1 and isinstance(e.args[0], str):
|
|
59
56
|
error_msg += e.args[0]
|
|
60
57
|
self.log_error(error_msg, node_override=catch_error)
|
|
@@ -62,7 +59,12 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
62
59
|
except Exception as e:
|
|
63
60
|
raise e
|
|
64
61
|
|
|
65
|
-
|
|
62
|
+
# If we reach here, there was a syntax error, mark the module as such
|
|
63
|
+
# and report errors.
|
|
64
|
+
self.report_errors()
|
|
65
|
+
mod = uni.Module.make_stub(inject_src=ir_in)
|
|
66
|
+
mod.has_syntax_errors = True
|
|
67
|
+
return mod
|
|
66
68
|
|
|
67
69
|
@staticmethod
|
|
68
70
|
def proc_comment(token: jl.Token, mod: uni.UniNode) -> uni.CommentToken:
|
|
@@ -80,10 +82,114 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
80
82
|
kid=[],
|
|
81
83
|
)
|
|
82
84
|
|
|
85
|
+
_MISSING_TOKENS = [
|
|
86
|
+
Tok.SEMI,
|
|
87
|
+
Tok.COMMA,
|
|
88
|
+
Tok.COLON,
|
|
89
|
+
Tok.RPAREN,
|
|
90
|
+
Tok.RBRACE,
|
|
91
|
+
Tok.RSQUARE,
|
|
92
|
+
Tok.RETURN_HINT,
|
|
93
|
+
]
|
|
94
|
+
|
|
83
95
|
def error_callback(self, e: jl.UnexpectedInput) -> bool:
|
|
84
96
|
"""Handle error."""
|
|
97
|
+
iparser = e.interactive_parser
|
|
98
|
+
|
|
99
|
+
def try_feed_missing_token(iparser: jl.InteractiveParser) -> Tok | None:
|
|
100
|
+
"""Feed a missing token to the parser."""
|
|
101
|
+
# If any of the below token is missing, insert them and continue parsing.
|
|
102
|
+
accepts = iparser.accepts()
|
|
103
|
+
for tok in JacParser._MISSING_TOKENS:
|
|
104
|
+
if tok.name in accepts:
|
|
105
|
+
iparser.feed_token(jl.Token(tok.name, TOKEN_MAP[tok.name]))
|
|
106
|
+
return tok
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
def feed_current_token(iparser: jl.InteractiveParser, tok: jl.Token) -> bool:
|
|
110
|
+
"""Feed the current token to the parser."""
|
|
111
|
+
max_attempts = 100 # Prevent infinite loops
|
|
112
|
+
attempts = 0
|
|
113
|
+
while tok.type not in iparser.accepts():
|
|
114
|
+
if attempts >= max_attempts:
|
|
115
|
+
return False # Give up after too many attempts
|
|
116
|
+
if not try_feed_missing_token(iparser):
|
|
117
|
+
return False
|
|
118
|
+
attempts += 1
|
|
119
|
+
iparser.feed_token(tok)
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
if isinstance(e, jl.UnexpectedToken):
|
|
123
|
+
# If last token is DOT and we expect a NAME, insert a NAME token
|
|
124
|
+
last_tok: jl.Token | None = (
|
|
125
|
+
e.token_history[-1]
|
|
126
|
+
if e.token_history and len(e.token_history) >= 1
|
|
127
|
+
else None
|
|
128
|
+
)
|
|
129
|
+
if (
|
|
130
|
+
last_tok
|
|
131
|
+
and last_tok.type == Tok.DOT.name
|
|
132
|
+
and (Tok.NAME.name in e.accepts)
|
|
133
|
+
):
|
|
134
|
+
self.log_error("Incomplete member access", self.error_to_token(e))
|
|
135
|
+
iparser.feed_token(jl.Token(Tok.NAME.name, "recover_name_token"))
|
|
136
|
+
return feed_current_token(iparser, e.token)
|
|
137
|
+
|
|
138
|
+
# We're calling try_feed_missing_token twice here because the first missing
|
|
139
|
+
# will be reported as such and we don't for the consequent missing token.
|
|
140
|
+
if tk := try_feed_missing_token(iparser):
|
|
141
|
+
self.log_error(f"Missing {tk.name}", self.error_to_token(e))
|
|
142
|
+
return feed_current_token(iparser, e.token)
|
|
143
|
+
|
|
144
|
+
# Ignore unexpected tokens and continue parsing till we reach a known state.
|
|
145
|
+
self.log_error(
|
|
146
|
+
f"Unexpected token '{e.token.value}'", self.error_to_token(e)
|
|
147
|
+
)
|
|
148
|
+
return True
|
|
149
|
+
|
|
85
150
|
return False
|
|
86
151
|
|
|
152
|
+
def error_to_message(self, e: jl.UnexpectedInput) -> str:
|
|
153
|
+
"""Return an error message based on the exception."""
|
|
154
|
+
# TODO: Match more specific errors with lark's example based matching.
|
|
155
|
+
# Reference: https://github.com/lark-parser/lark/blob/master/examples/advanced/error_reporting_lalr.py
|
|
156
|
+
# e.match_examples()
|
|
157
|
+
if isinstance(e, jl.UnexpectedToken):
|
|
158
|
+
return f"Unexpected token '{e.token.value}'"
|
|
159
|
+
return "Syntax Error"
|
|
160
|
+
|
|
161
|
+
def error_to_token(self, e: jl.UnexpectedInput) -> uni.Token:
|
|
162
|
+
"""Convert error to token."""
|
|
163
|
+
catch_error = uni.EmptyToken()
|
|
164
|
+
catch_error.orig_src = self.ir_in
|
|
165
|
+
catch_error.line_no = e.line
|
|
166
|
+
catch_error.end_line = e.line
|
|
167
|
+
catch_error.c_start = e.column
|
|
168
|
+
catch_error.pos_start = e.pos_in_stream or 0
|
|
169
|
+
if isinstance(e, jl.UnexpectedToken) and e.token:
|
|
170
|
+
catch_error.c_end = e.token.end_column or (e.column + 1)
|
|
171
|
+
catch_error.pos_end = e.token.end_pos or (catch_error.pos_start + 1)
|
|
172
|
+
else:
|
|
173
|
+
catch_error.c_end = e.column + 1
|
|
174
|
+
catch_error.pos_end = catch_error.pos_start + 1
|
|
175
|
+
return catch_error
|
|
176
|
+
|
|
177
|
+
def report_errors(self, *, colors: bool = True) -> None:
|
|
178
|
+
"""Report errors to the user."""
|
|
179
|
+
# TODO: Write a better IO system.
|
|
180
|
+
# NOTE: Currently it writes all the errors to stderr cause LSP JsonRPC uses stdout for IPC.
|
|
181
|
+
if not sys.stderr.isatty():
|
|
182
|
+
# FIXME: If we're outputting to a file (pipe, redirection, etc) other
|
|
183
|
+
# than a terminal we disable colors however we should be able to force
|
|
184
|
+
# colors with a configuration.
|
|
185
|
+
colors = False
|
|
186
|
+
for alrt in self.errors_had:
|
|
187
|
+
error_label = (
|
|
188
|
+
"Error:" if not colors else f"{ANSIColors.RED}Error:{ANSIColors.END}"
|
|
189
|
+
)
|
|
190
|
+
print(error_label, end=" ", file=sys.stderr)
|
|
191
|
+
print(alrt.pretty_print(colors=colors), file=sys.stderr)
|
|
192
|
+
|
|
87
193
|
@staticmethod
|
|
88
194
|
def _comment_callback(comment: jl.Token) -> None:
|
|
89
195
|
JacParser.comment_cache.append(comment)
|
|
@@ -549,11 +655,12 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
549
655
|
def sem_def(self, _: None) -> uni.SemDef:
|
|
550
656
|
"""Grammar rule.
|
|
551
657
|
|
|
552
|
-
sem_def: KW_SEM dotted_name EQ
|
|
658
|
+
sem_def: KW_SEM dotted_name (EQ | KW_IS) STRING SEMI
|
|
553
659
|
"""
|
|
554
660
|
self.consume_token(Tok.KW_SEM)
|
|
555
661
|
target = self.extract_from_list(self.consume(list), uni.NameAtom)
|
|
556
|
-
self.
|
|
662
|
+
if not self.match_token(Tok.KW_IS):
|
|
663
|
+
self.consume_token(Tok.EQ)
|
|
557
664
|
value = self.consume(uni.String)
|
|
558
665
|
self.consume_token(Tok.SEMI)
|
|
559
666
|
return uni.SemDef(
|
|
@@ -848,25 +955,104 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
848
955
|
if self.match_token(Tok.RETURN_HINT):
|
|
849
956
|
return_spec = self.consume(uni.Expr)
|
|
850
957
|
return uni.FuncSignature(
|
|
958
|
+
posonly_params=[],
|
|
851
959
|
params=[],
|
|
960
|
+
varargs=None,
|
|
961
|
+
kwonlyargs=[],
|
|
962
|
+
kwargs=None,
|
|
852
963
|
return_type=return_spec,
|
|
853
964
|
kid=self.flat_cur_nodes,
|
|
854
965
|
)
|
|
855
966
|
# Otherwise, parse the traditional parameter list form
|
|
856
967
|
else:
|
|
857
968
|
self.consume_token(Tok.LPAREN)
|
|
858
|
-
|
|
969
|
+
all_params = self.match(list) or []
|
|
970
|
+
posonly_params, params, varargs, kwonlyargs, kwargs = (
|
|
971
|
+
self._parse_parameter_categories(all_params)
|
|
972
|
+
)
|
|
859
973
|
self.consume_token(Tok.RPAREN)
|
|
860
974
|
if self.match_token(Tok.RETURN_HINT):
|
|
861
975
|
return_spec = self.consume(uni.Expr)
|
|
862
976
|
return uni.FuncSignature(
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
977
|
+
posonly_params=posonly_params,
|
|
978
|
+
params=params,
|
|
979
|
+
varargs=varargs,
|
|
980
|
+
kwonlyargs=kwonlyargs,
|
|
981
|
+
kwargs=kwargs,
|
|
866
982
|
return_type=return_spec,
|
|
867
983
|
kid=self.flat_cur_nodes,
|
|
868
984
|
)
|
|
869
985
|
|
|
986
|
+
def _parse_parameter_categories(self, all_params: list[uni.UniNode]) -> tuple[
|
|
987
|
+
list[uni.ParamVar],
|
|
988
|
+
list[uni.ParamVar],
|
|
989
|
+
uni.ParamVar | None,
|
|
990
|
+
list[uni.ParamVar],
|
|
991
|
+
uni.ParamVar | None,
|
|
992
|
+
]:
|
|
993
|
+
posonly_params = []
|
|
994
|
+
params = []
|
|
995
|
+
varargs = None
|
|
996
|
+
kwonlyargs = []
|
|
997
|
+
kwargs = None
|
|
998
|
+
|
|
999
|
+
# Initial state determination
|
|
1000
|
+
cur_state = "positional"
|
|
1001
|
+
for param in all_params:
|
|
1002
|
+
if isinstance(param, uni.Token) and param.name == Tok.DIV:
|
|
1003
|
+
cur_state = "posonly"
|
|
1004
|
+
break
|
|
1005
|
+
|
|
1006
|
+
for cur_nd in all_params:
|
|
1007
|
+
cur_state = self._update_parameter_state(cur_nd, cur_state)
|
|
1008
|
+
if isinstance(cur_nd, uni.ParamVar):
|
|
1009
|
+
if cur_state == "positional":
|
|
1010
|
+
cur_nd.param_kind = uni.ParamKind.NORMAL
|
|
1011
|
+
params.append(cur_nd)
|
|
1012
|
+
elif cur_state == "posonly":
|
|
1013
|
+
cur_nd.param_kind = uni.ParamKind.POSONLY
|
|
1014
|
+
posonly_params.append(cur_nd)
|
|
1015
|
+
elif cur_state == "varargs":
|
|
1016
|
+
cur_nd.param_kind = uni.ParamKind.VARARG
|
|
1017
|
+
varargs = cur_nd
|
|
1018
|
+
cur_state = "keyword_only"
|
|
1019
|
+
elif cur_state == "keyword_only":
|
|
1020
|
+
cur_nd.param_kind = uni.ParamKind.KWONLY
|
|
1021
|
+
kwonlyargs.append(cur_nd)
|
|
1022
|
+
elif cur_state == "kwargs":
|
|
1023
|
+
cur_nd.param_kind = uni.ParamKind.KWARG
|
|
1024
|
+
kwargs = cur_nd
|
|
1025
|
+
else:
|
|
1026
|
+
raise self.ice()
|
|
1027
|
+
|
|
1028
|
+
return posonly_params, params, varargs, kwonlyargs, kwargs
|
|
1029
|
+
|
|
1030
|
+
def _update_parameter_state(self, cur_nd: uni.UniNode, cur_state: str) -> str:
|
|
1031
|
+
if isinstance(cur_nd, uni.Token):
|
|
1032
|
+
if cur_nd.name == Tok.DIV:
|
|
1033
|
+
if cur_state in ["keyword_only", "kwargs", "positional"]:
|
|
1034
|
+
self.parse_ref.log_error(
|
|
1035
|
+
"Invalid syntax in function parameters: '/' cannot appear after '*' or '**'.",
|
|
1036
|
+
node_override=cur_nd,
|
|
1037
|
+
)
|
|
1038
|
+
return "positional"
|
|
1039
|
+
elif cur_nd.name == Tok.STAR_MUL:
|
|
1040
|
+
if cur_state in ["keyword_only", "kwargs"]:
|
|
1041
|
+
self.parse_ref.log_error(
|
|
1042
|
+
"Invalid syntax in function parameters: '*' cannot appear after '**'.",
|
|
1043
|
+
node_override=cur_nd,
|
|
1044
|
+
)
|
|
1045
|
+
return "keyword_only"
|
|
1046
|
+
elif cur_nd.name == Tok.COMMA:
|
|
1047
|
+
return cur_state
|
|
1048
|
+
|
|
1049
|
+
elif isinstance(cur_nd, uni.ParamVar):
|
|
1050
|
+
if cur_nd.is_vararg:
|
|
1051
|
+
return "varargs"
|
|
1052
|
+
if cur_nd.is_kwargs:
|
|
1053
|
+
return "kwargs"
|
|
1054
|
+
return cur_state
|
|
1055
|
+
|
|
870
1056
|
def func_decl_params(self, _: None) -> list[uni.UniNode]:
|
|
871
1057
|
"""Grammar rule.
|
|
872
1058
|
|
|
@@ -874,11 +1060,17 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
874
1060
|
"""
|
|
875
1061
|
return self.cur_nodes
|
|
876
1062
|
|
|
877
|
-
def param_var(self, _: None) -> uni.ParamVar:
|
|
1063
|
+
def param_var(self, _: None) -> uni.ParamVar | uni.Token:
|
|
878
1064
|
"""Grammar rule.
|
|
879
1065
|
|
|
880
|
-
param_var: (STAR_POW | STAR_MUL)?
|
|
1066
|
+
param_var: (STAR_POW | STAR_MUL)? named_ref type_tag (EQ expression)?
|
|
1067
|
+
| DIV
|
|
1068
|
+
| STAR_MUL
|
|
881
1069
|
"""
|
|
1070
|
+
if len(self.cur_nodes) == 1 and (
|
|
1071
|
+
star_only := self.match_token(Tok.DIV) or self.match_token(Tok.STAR_MUL)
|
|
1072
|
+
):
|
|
1073
|
+
return star_only
|
|
882
1074
|
star = self.match_token(Tok.STAR_POW) or self.match_token(Tok.STAR_MUL)
|
|
883
1075
|
name = self.consume(uni.Name)
|
|
884
1076
|
type_tag = self.consume(uni.SubTag)
|
|
@@ -1028,7 +1220,6 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
1028
1220
|
| (yield_expr | KW_YIELD) SEMI
|
|
1029
1221
|
| raise_stmt SEMI
|
|
1030
1222
|
| assert_stmt SEMI
|
|
1031
|
-
| check_stmt SEMI
|
|
1032
1223
|
| assignment SEMI
|
|
1033
1224
|
| delete_stmt SEMI
|
|
1034
1225
|
| report_stmt SEMI
|
|
@@ -1307,18 +1498,6 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
1307
1498
|
kid=self.cur_nodes,
|
|
1308
1499
|
)
|
|
1309
1500
|
|
|
1310
|
-
def check_stmt(self, _: None) -> uni.CheckStmt:
|
|
1311
|
-
"""Grammar rule.
|
|
1312
|
-
|
|
1313
|
-
check_stmt: KW_CHECK expression
|
|
1314
|
-
"""
|
|
1315
|
-
self.consume_token(Tok.KW_CHECK)
|
|
1316
|
-
target = self.consume(uni.Expr)
|
|
1317
|
-
return uni.CheckStmt(
|
|
1318
|
-
target=target,
|
|
1319
|
-
kid=self.cur_nodes,
|
|
1320
|
-
)
|
|
1321
|
-
|
|
1322
1501
|
def ctrl_stmt(self, _: None) -> uni.CtrlStmt | uni.DisengageStmt:
|
|
1323
1502
|
"""Grammar rule.
|
|
1324
1503
|
|
|
@@ -1532,29 +1711,40 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
1532
1711
|
lambda_expr: KW_LAMBDA func_decl_params? (RETURN_HINT expression)? COLON expression
|
|
1533
1712
|
"""
|
|
1534
1713
|
return_type: uni.Expr | None = None
|
|
1714
|
+
return_hint_tok: uni.Token | None = None
|
|
1535
1715
|
sig_kid: list[uni.UniNode] = []
|
|
1536
1716
|
self.consume_token(Tok.KW_LAMBDA)
|
|
1537
1717
|
params = self.match(list)
|
|
1538
|
-
if self.match_token(Tok.RETURN_HINT):
|
|
1718
|
+
if return_hint_tok := self.match_token(Tok.RETURN_HINT):
|
|
1539
1719
|
return_type = self.consume(uni.Expr)
|
|
1540
1720
|
self.consume_token(Tok.COLON)
|
|
1541
1721
|
body = self.consume(uni.Expr)
|
|
1542
1722
|
if params:
|
|
1543
1723
|
sig_kid.extend(params)
|
|
1724
|
+
if return_hint_tok:
|
|
1725
|
+
sig_kid.append(return_hint_tok)
|
|
1544
1726
|
if return_type:
|
|
1545
1727
|
sig_kid.append(return_type)
|
|
1546
1728
|
signature = (
|
|
1547
1729
|
uni.FuncSignature(
|
|
1730
|
+
posonly_params=[],
|
|
1548
1731
|
params=(
|
|
1549
1732
|
self.extract_from_list(params, uni.ParamVar) if params else []
|
|
1550
1733
|
),
|
|
1734
|
+
varargs=None,
|
|
1735
|
+
kwonlyargs=[],
|
|
1736
|
+
kwargs=None,
|
|
1551
1737
|
return_type=return_type,
|
|
1552
1738
|
kid=sig_kid,
|
|
1553
1739
|
)
|
|
1554
1740
|
if params or return_type
|
|
1555
1741
|
else None
|
|
1556
1742
|
)
|
|
1557
|
-
new_kid = [
|
|
1743
|
+
new_kid = [
|
|
1744
|
+
i
|
|
1745
|
+
for i in self.cur_nodes
|
|
1746
|
+
if i != params and i != return_type and i != return_hint_tok
|
|
1747
|
+
]
|
|
1558
1748
|
new_kid.insert(1, signature) if signature else None
|
|
1559
1749
|
return uni.LambdaExpr(
|
|
1560
1750
|
signature=signature,
|
|
@@ -1788,25 +1978,31 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
1788
1978
|
)
|
|
1789
1979
|
return self._binary_expr_unwind(self.cur_nodes)
|
|
1790
1980
|
|
|
1981
|
+
def await_expr(self, _: None) -> uni.Expr:
|
|
1982
|
+
"""Grammar rule.
|
|
1983
|
+
|
|
1984
|
+
await_expr: KW_AWAIT? pipe_call
|
|
1985
|
+
"""
|
|
1986
|
+
if self.match_token(Tok.KW_AWAIT):
|
|
1987
|
+
operand = self.consume(uni.Expr)
|
|
1988
|
+
return uni.AwaitExpr(
|
|
1989
|
+
target=operand,
|
|
1990
|
+
kid=self.cur_nodes,
|
|
1991
|
+
)
|
|
1992
|
+
return self._binary_expr_unwind(self.cur_nodes)
|
|
1993
|
+
|
|
1791
1994
|
def pipe_call(self, _: None) -> uni.Expr:
|
|
1792
1995
|
"""Grammar rule.
|
|
1793
1996
|
|
|
1794
|
-
pipe_call: (PIPE_FWD | A_PIPE_FWD | KW_SPAWN
|
|
1997
|
+
pipe_call: (PIPE_FWD | A_PIPE_FWD | KW_SPAWN)? atomic_chain
|
|
1795
1998
|
"""
|
|
1796
|
-
if len(self.cur_nodes) == 2:
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
elif op := self.match(uni.Token):
|
|
1804
|
-
operand = self.consume(uni.Expr)
|
|
1805
|
-
return uni.UnaryExpr(
|
|
1806
|
-
op=op,
|
|
1807
|
-
operand=operand,
|
|
1808
|
-
kid=self.cur_nodes,
|
|
1809
|
-
)
|
|
1999
|
+
if len(self.cur_nodes) == 2 and (op := self.match(uni.Token)):
|
|
2000
|
+
operand = self.consume(uni.Expr)
|
|
2001
|
+
return uni.UnaryExpr(
|
|
2002
|
+
op=op,
|
|
2003
|
+
operand=operand,
|
|
2004
|
+
kid=self.cur_nodes,
|
|
2005
|
+
)
|
|
1810
2006
|
return self._binary_expr_unwind(self.cur_nodes)
|
|
1811
2007
|
|
|
1812
2008
|
def aug_op(self, _: None) -> uni.Token:
|
|
@@ -1814,7 +2010,6 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
1814
2010
|
|
|
1815
2011
|
aug_op: RSHIFT_EQ
|
|
1816
2012
|
| LSHIFT_EQ
|
|
1817
|
-
| BW_NOT_EQ
|
|
1818
2013
|
| BW_XOR_EQ
|
|
1819
2014
|
| BW_OR_EQ
|
|
1820
2015
|
| BW_AND_EQ
|
|
@@ -1868,6 +2063,14 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
1868
2063
|
atomic_call: atomic_chain LPAREN param_list? by_llm? RPAREN
|
|
1869
2064
|
"""
|
|
1870
2065
|
target = self.consume(uni.Expr)
|
|
2066
|
+
gencompr = self.match(uni.GenCompr)
|
|
2067
|
+
if gencompr:
|
|
2068
|
+
return uni.FuncCall(
|
|
2069
|
+
target=target,
|
|
2070
|
+
params=[gencompr],
|
|
2071
|
+
genai_call=None,
|
|
2072
|
+
kid=self.cur_nodes,
|
|
2073
|
+
)
|
|
1871
2074
|
self.consume_token(Tok.LPAREN)
|
|
1872
2075
|
params_sn = self.match(list)
|
|
1873
2076
|
genai_call = self.match(uni.Expr)
|
|
@@ -2011,10 +2214,22 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2011
2214
|
|
|
2012
2215
|
fstring: FSTR_START fstr_parts FSTR_END
|
|
2013
2216
|
| FSTR_SQ_START fstr_sq_parts FSTR_SQ_END
|
|
2217
|
+
| FSTR_TRIPLE_START fstr_triple_parts FSTR_TRIPLE_END
|
|
2218
|
+
| FSTR_SQ_TRIPLE_START fstr_sq_triple_parts FSTR_SQ_TRIPLE_END
|
|
2014
2219
|
"""
|
|
2015
|
-
|
|
2220
|
+
(
|
|
2221
|
+
self.match_token(Tok.FSTR_TRIPLE_START)
|
|
2222
|
+
or self.match_token(Tok.FSTR_SQ_TRIPLE_START)
|
|
2223
|
+
or self.match_token(Tok.FSTR_START)
|
|
2224
|
+
or self.consume_token(Tok.FSTR_SQ_START)
|
|
2225
|
+
)
|
|
2016
2226
|
target = self.match(list)
|
|
2017
|
-
|
|
2227
|
+
(
|
|
2228
|
+
self.match_token(Tok.FSTR_TRIPLE_END)
|
|
2229
|
+
or self.match_token(Tok.FSTR_SQ_TRIPLE_END)
|
|
2230
|
+
or self.match_token(Tok.FSTR_END)
|
|
2231
|
+
or self.consume_token(Tok.FSTR_SQ_END)
|
|
2232
|
+
)
|
|
2018
2233
|
return uni.FString(
|
|
2019
2234
|
parts=(
|
|
2020
2235
|
self.extract_from_list(target, (uni.String, uni.ExprStmt))
|
|
@@ -2062,6 +2277,44 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2062
2277
|
]
|
|
2063
2278
|
return valid_parts
|
|
2064
2279
|
|
|
2280
|
+
def fstr_triple_parts(self, _: None) -> list[uni.UniNode]:
|
|
2281
|
+
"""Grammar rule.
|
|
2282
|
+
|
|
2283
|
+
fstr_triple_parts: (FSTR_TRIPLE_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
|
|
2284
|
+
"""
|
|
2285
|
+
valid_parts: list[uni.UniNode] = [
|
|
2286
|
+
(
|
|
2287
|
+
i
|
|
2288
|
+
if isinstance(i, uni.String)
|
|
2289
|
+
else (
|
|
2290
|
+
uni.ExprStmt(expr=i, in_fstring=True, kid=[i])
|
|
2291
|
+
if isinstance(i, uni.Expr)
|
|
2292
|
+
else i
|
|
2293
|
+
)
|
|
2294
|
+
)
|
|
2295
|
+
for i in self.cur_nodes
|
|
2296
|
+
]
|
|
2297
|
+
return valid_parts
|
|
2298
|
+
|
|
2299
|
+
def fstr_sq_triple_parts(self, _: None) -> list[uni.UniNode]:
|
|
2300
|
+
"""Grammar rule.
|
|
2301
|
+
|
|
2302
|
+
fstr_sq_triple_parts: (FSTR_SQ_TRIPLE_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
|
|
2303
|
+
"""
|
|
2304
|
+
valid_parts: list[uni.UniNode] = [
|
|
2305
|
+
(
|
|
2306
|
+
i
|
|
2307
|
+
if isinstance(i, uni.String)
|
|
2308
|
+
else (
|
|
2309
|
+
uni.ExprStmt(expr=i, in_fstring=True, kid=[i])
|
|
2310
|
+
if isinstance(i, uni.Expr)
|
|
2311
|
+
else i
|
|
2312
|
+
)
|
|
2313
|
+
)
|
|
2314
|
+
for i in self.cur_nodes
|
|
2315
|
+
]
|
|
2316
|
+
return valid_parts
|
|
2317
|
+
|
|
2065
2318
|
def list_val(self, _: None) -> uni.ListVal:
|
|
2066
2319
|
"""Grammar rule.
|
|
2067
2320
|
|
|
@@ -2291,7 +2544,7 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2291
2544
|
def assignment_list(self, _: None) -> list[uni.UniNode]:
|
|
2292
2545
|
"""Grammar rule.
|
|
2293
2546
|
|
|
2294
|
-
assignment_list: (
|
|
2547
|
+
assignment_list: (assignment | named_ref) (COMMA (assignment | named_ref))* COMMA?
|
|
2295
2548
|
"""
|
|
2296
2549
|
|
|
2297
2550
|
def name_to_assign(name_consume: uni.NameAtom) -> uni.Assignment:
|
|
@@ -2299,15 +2552,23 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2299
2552
|
target=[name_consume], value=None, type_tag=None, kid=[name_consume]
|
|
2300
2553
|
)
|
|
2301
2554
|
|
|
2302
|
-
|
|
2303
|
-
self.consume_token(Tok.COMMA)
|
|
2555
|
+
# Match first (assignment | named_ref)
|
|
2304
2556
|
if self.match(uni.Assignment):
|
|
2305
2557
|
pass
|
|
2306
2558
|
elif name_consume := self.match(uni.NameAtom):
|
|
2307
2559
|
self.cur_nodes[self.node_idx - 1] = name_to_assign(name_consume)
|
|
2308
2560
|
else:
|
|
2309
|
-
|
|
2310
|
-
|
|
2561
|
+
raise self.ice()
|
|
2562
|
+
|
|
2563
|
+
# Match (COMMA (assignment | named_ref))* COMMA?
|
|
2564
|
+
while self.match_token(Tok.COMMA):
|
|
2565
|
+
if self.match(uni.Assignment):
|
|
2566
|
+
pass
|
|
2567
|
+
elif name_consume := self.match(uni.NameAtom):
|
|
2568
|
+
self.cur_nodes[self.node_idx - 1] = name_to_assign(name_consume)
|
|
2569
|
+
else:
|
|
2570
|
+
break # trailing comma
|
|
2571
|
+
|
|
2311
2572
|
return self.flat_cur_nodes
|
|
2312
2573
|
|
|
2313
2574
|
def type_ref(self, kid: list[uni.UniNode]) -> uni.TypeRef:
|
|
@@ -2328,6 +2589,7 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2328
2589
|
LSQUARE (KW_NODE| KW_EDGE)? expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
|
|
2329
2590
|
"""
|
|
2330
2591
|
self.consume_token(Tok.LSQUARE)
|
|
2592
|
+
is_async = bool(self.match_token(Tok.KW_ASYNC))
|
|
2331
2593
|
edges_only = bool(self.match_token(Tok.KW_EDGE))
|
|
2332
2594
|
self.match_token(Tok.KW_NODE)
|
|
2333
2595
|
valid_chain = []
|
|
@@ -2338,6 +2600,7 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2338
2600
|
return uni.EdgeRefTrailer(
|
|
2339
2601
|
chain=valid_chain,
|
|
2340
2602
|
edges_only=edges_only,
|
|
2603
|
+
is_async=is_async,
|
|
2341
2604
|
kid=self.cur_nodes,
|
|
2342
2605
|
)
|
|
2343
2606
|
|
|
@@ -2767,6 +3030,36 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2767
3030
|
value = self.consume(uni.MatchPattern)
|
|
2768
3031
|
return uni.MatchKVPair(key=pattern, value=value, kid=self.cur_nodes)
|
|
2769
3032
|
|
|
3033
|
+
def attr_pattern(self, _: None) -> uni.MatchValue:
|
|
3034
|
+
"""Grammar rule.
|
|
3035
|
+
|
|
3036
|
+
attr_pattern: NAME (DOT NAME)+
|
|
3037
|
+
"""
|
|
3038
|
+
name_idx = 0
|
|
3039
|
+
cur_element = self.consume(uni.NameAtom)
|
|
3040
|
+
name_idx += 1
|
|
3041
|
+
trailer: uni.AtomTrailer | None = None
|
|
3042
|
+
while dot := self.match_token(Tok.DOT):
|
|
3043
|
+
target = trailer if trailer else cur_element
|
|
3044
|
+
right = self.consume(uni.NameAtom)
|
|
3045
|
+
name_idx += 2
|
|
3046
|
+
trailer = uni.AtomTrailer(
|
|
3047
|
+
target=target,
|
|
3048
|
+
right=right,
|
|
3049
|
+
is_attr=True,
|
|
3050
|
+
is_null_ok=False,
|
|
3051
|
+
kid=[target, dot, right],
|
|
3052
|
+
)
|
|
3053
|
+
name = trailer if trailer else cur_element
|
|
3054
|
+
if not isinstance(name, (uni.NameAtom, uni.AtomTrailer)):
|
|
3055
|
+
raise TypeError(
|
|
3056
|
+
f"Expected name to be either NameAtom or AtomTrailer, got {type(name)}"
|
|
3057
|
+
)
|
|
3058
|
+
return uni.MatchValue(
|
|
3059
|
+
value=name,
|
|
3060
|
+
kid=[name, *self.flat_cur_nodes[name_idx:]],
|
|
3061
|
+
)
|
|
3062
|
+
|
|
2770
3063
|
def class_pattern(self, _: None) -> uni.MatchArch:
|
|
2771
3064
|
"""Grammar rule.
|
|
2772
3065
|
|
|
@@ -2873,6 +3166,8 @@ class JacParser(Transform[uni.Source, uni.Module]):
|
|
|
2873
3166
|
Tok.FSTR_BESC,
|
|
2874
3167
|
Tok.FSTR_PIECE,
|
|
2875
3168
|
Tok.FSTR_SQ_PIECE,
|
|
3169
|
+
Tok.FSTR_TRIPLE_PIECE,
|
|
3170
|
+
Tok.FSTR_SQ_TRIPLE_PIECE,
|
|
2876
3171
|
]:
|
|
2877
3172
|
ret_type = uni.String
|
|
2878
3173
|
if token.type == Tok.FSTR_BESC:
|
|
@@ -4,7 +4,6 @@ from ..transform import Alert, Transform # noqa: I100
|
|
|
4
4
|
from .annex_pass import JacAnnexPass # noqa: I100
|
|
5
5
|
from .binder_pass import BinderPass # noqa: I100
|
|
6
6
|
from .sym_tab_build_pass import SymTabBuildPass, UniPass # noqa: I100
|
|
7
|
-
from .sym_tab_link_pass import SymTabLinkPass # noqa: I100
|
|
8
7
|
from .def_use_pass import DefUsePass # noqa: I100
|
|
9
8
|
from .sem_def_match_pass import SemDefMatchPass # noqa: I100
|
|
10
9
|
from .import_pass import JacImportDepsPass # noqa: I100
|
|
@@ -12,10 +11,10 @@ from .def_impl_match_pass import DeclImplMatchPass # noqa: I100
|
|
|
12
11
|
from .type_checker_pass import TypeCheckPass # noqa: I100
|
|
13
12
|
from .pyast_load_pass import PyastBuildPass # type: ignore # noqa: I100
|
|
14
13
|
from .pyast_gen_pass import PyastGenPass # noqa: I100
|
|
14
|
+
from .predynamo_pass import PreDynamoPass # noqa: I100
|
|
15
15
|
from .pybc_gen_pass import PyBytecodeGenPass # noqa: I100
|
|
16
16
|
from .cfg_build_pass import CFGBuildPass # noqa: I100
|
|
17
17
|
from .pyjac_ast_link_pass import PyJacAstLinkPass # noqa: I100
|
|
18
|
-
from .inheritance_pass import InheritancePass # noqa: I100
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
__all__ = [
|
|
@@ -28,14 +27,13 @@ __all__ = [
|
|
|
28
27
|
"BinderPass",
|
|
29
28
|
"TypeCheckPass",
|
|
30
29
|
"SymTabBuildPass",
|
|
31
|
-
"SymTabLinkPass",
|
|
32
30
|
"DeclImplMatchPass",
|
|
33
31
|
"DefUsePass",
|
|
34
32
|
"SemDefMatchPass",
|
|
35
33
|
"PyastBuildPass",
|
|
36
34
|
"PyastGenPass",
|
|
35
|
+
"PreDynamoPass",
|
|
37
36
|
"PyBytecodeGenPass",
|
|
38
37
|
"CFGBuildPass",
|
|
39
38
|
"PyJacAstLinkPass",
|
|
40
|
-
"InheritancePass",
|
|
41
39
|
]
|
|
@@ -30,7 +30,6 @@ class DefUsePass(UniPass):
|
|
|
30
30
|
"""Jac Ast build pass."""
|
|
31
31
|
|
|
32
32
|
def enter_archetype(self, node: uni.Archetype) -> None:
|
|
33
|
-
node.sym_tab.inherit_baseclasses_sym(node)
|
|
34
33
|
|
|
35
34
|
def inform_from_walker(node: uni.UniNode) -> None:
|
|
36
35
|
for i in (
|
|
@@ -38,6 +37,7 @@ class DefUsePass(UniPass):
|
|
|
38
37
|
+ node.get_all_sub_nodes(uni.DisengageStmt)
|
|
39
38
|
+ node.get_all_sub_nodes(uni.EdgeOpRef)
|
|
40
39
|
+ node.get_all_sub_nodes(uni.EventSignature)
|
|
40
|
+
+ node.get_all_sub_nodes(uni.TypedCtxBlock)
|
|
41
41
|
):
|
|
42
42
|
i.from_walker = True
|
|
43
43
|
|
|
@@ -47,9 +47,6 @@ class DefUsePass(UniPass):
|
|
|
47
47
|
if isinstance(i.body, uni.ImplDef):
|
|
48
48
|
inform_from_walker(i.body)
|
|
49
49
|
|
|
50
|
-
def enter_enum(self, node: uni.Enum) -> None:
|
|
51
|
-
node.sym_tab.inherit_baseclasses_sym(node)
|
|
52
|
-
|
|
53
50
|
def enter_type_ref(self, node: uni.TypeRef) -> None:
|
|
54
51
|
node.sym_tab.use_lookup(node)
|
|
55
52
|
|