jaclang 0.8.8__py3-none-any.whl → 0.8.10__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 +194 -10
- jaclang/cli/cmdreg.py +144 -8
- jaclang/compiler/__init__.py +6 -1
- jaclang/compiler/codeinfo.py +16 -1
- jaclang/compiler/constant.py +33 -8
- jaclang/compiler/jac.lark +154 -62
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +656 -149
- jaclang/compiler/passes/__init__.py +2 -1
- jaclang/compiler/passes/ast_gen/__init__.py +5 -0
- jaclang/compiler/passes/ast_gen/base_ast_gen_pass.py +54 -0
- jaclang/compiler/passes/ast_gen/jsx_processor.py +344 -0
- jaclang/compiler/passes/ecmascript/__init__.py +25 -0
- jaclang/compiler/passes/ecmascript/es_unparse.py +576 -0
- jaclang/compiler/passes/ecmascript/esast_gen_pass.py +2068 -0
- jaclang/compiler/passes/ecmascript/estree.py +972 -0
- jaclang/compiler/passes/ecmascript/tests/__init__.py +1 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/advanced_language_features.jac +170 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.impl.jac +30 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.jac +14 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/client_jsx.jac +89 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/core_language_features.jac +195 -0
- jaclang/compiler/passes/ecmascript/tests/test_esast_gen_pass.py +167 -0
- jaclang/compiler/passes/ecmascript/tests/test_js_generation.py +239 -0
- jaclang/compiler/passes/main/__init__.py +0 -3
- jaclang/compiler/passes/main/annex_pass.py +23 -1
- jaclang/compiler/passes/main/def_use_pass.py +1 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +413 -255
- jaclang/compiler/passes/main/pyast_load_pass.py +48 -11
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +18 -1
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.cl.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +3 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_class_construct.jac +33 -0
- jaclang/compiler/passes/main/tests/fixtures/defuse_modpath.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +2 -1
- jaclang/compiler/passes/main/tests/test_checker_pass.py +31 -3
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +12 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +23 -4
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +13 -14
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +25 -0
- jaclang/compiler/passes/main/type_checker_pass.py +7 -0
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +219 -20
- jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
- jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
- jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +135 -29
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -1
- jaclang/compiler/passes/transform.py +9 -1
- jaclang/compiler/passes/uni_pass.py +5 -7
- jaclang/compiler/program.py +27 -26
- jaclang/compiler/tests/test_client_codegen.py +113 -0
- jaclang/compiler/tests/test_importer.py +12 -10
- jaclang/compiler/tests/test_parser.py +249 -3
- jaclang/compiler/type_system/type_evaluator.jac +1078 -0
- jaclang/compiler/type_system/type_utils.py +1 -1
- jaclang/compiler/type_system/types.py +6 -0
- jaclang/compiler/unitree.py +438 -82
- jaclang/langserve/engine.jac +224 -288
- jaclang/langserve/sem_manager.jac +12 -8
- jaclang/langserve/server.jac +48 -48
- jaclang/langserve/tests/fixtures/greet.py +17 -0
- jaclang/langserve/tests/fixtures/md_path.jac +22 -0
- jaclang/langserve/tests/fixtures/user.jac +15 -0
- jaclang/langserve/tests/test_server.py +66 -371
- jaclang/lib.py +17 -0
- jaclang/runtimelib/archetype.py +25 -25
- jaclang/runtimelib/client_bundle.py +169 -0
- jaclang/runtimelib/client_runtime.jac +586 -0
- jaclang/runtimelib/constructs.py +4 -2
- jaclang/runtimelib/machine.py +308 -139
- jaclang/runtimelib/meta_importer.py +111 -22
- jaclang/runtimelib/mtp.py +15 -0
- jaclang/runtimelib/server.py +1089 -0
- jaclang/runtimelib/tests/fixtures/client_app.jac +18 -0
- jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
- jaclang/runtimelib/tests/fixtures/savable_object.jac +4 -5
- jaclang/runtimelib/tests/fixtures/serve_api.jac +75 -0
- jaclang/runtimelib/tests/test_client_bundle.py +55 -0
- jaclang/runtimelib/tests/test_client_render.py +63 -0
- jaclang/runtimelib/tests/test_serve.py +1069 -0
- jaclang/settings.py +0 -3
- jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
- jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
- jaclang/tests/fixtures/funccall_genexpr.py +5 -0
- jaclang/tests/fixtures/iife_functions.jac +142 -0
- jaclang/tests/fixtures/iife_functions_client.jac +143 -0
- jaclang/tests/fixtures/multistatement_lambda.jac +116 -0
- jaclang/tests/fixtures/multistatement_lambda_client.jac +113 -0
- jaclang/tests/fixtures/needs_import_dup.jac +6 -4
- jaclang/tests/fixtures/py2jac_empty.py +0 -0
- jaclang/tests/fixtures/py_run.py +7 -5
- jaclang/tests/fixtures/pyfunc_fstr.py +2 -2
- jaclang/tests/fixtures/simple_lambda_test.jac +12 -0
- jaclang/tests/test_cli.py +134 -18
- jaclang/tests/test_language.py +120 -32
- jaclang/tests/test_reference.py +20 -3
- jaclang/utils/NonGPT.py +375 -0
- jaclang/utils/helpers.py +64 -20
- jaclang/utils/lang_tools.py +31 -4
- jaclang/utils/tests/test_lang_tools.py +5 -16
- jaclang/utils/treeprinter.py +8 -3
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/RECORD +106 -71
- jaclang/compiler/passes/main/binder_pass.py +0 -594
- jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +0 -47
- jaclang/compiler/passes/main/tests/test_binder_pass.py +0 -111
- jaclang/compiler/type_system/type_evaluator.py +0 -844
- jaclang/langserve/tests/session.jac +0 -294
- jaclang/langserve/tests/test_dev_server.py +0 -80
- jaclang/runtimelib/importer.py +0 -351
- jaclang/tests/test_typecheck.py +0 -542
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/entry_points.txt +0 -0
|
@@ -26,8 +26,8 @@ from typing import List, Optional, Sequence, TypeVar, Union, cast
|
|
|
26
26
|
|
|
27
27
|
import jaclang.compiler.unitree as uni
|
|
28
28
|
from jaclang.compiler.constant import Constants as Con, EdgeDir, Tokens as Tok
|
|
29
|
-
from jaclang.compiler.passes import
|
|
30
|
-
from jaclang.
|
|
29
|
+
from jaclang.compiler.passes.ast_gen import BaseAstGenPass
|
|
30
|
+
from jaclang.compiler.passes.ast_gen.jsx_processor import PyJsxProcessor
|
|
31
31
|
|
|
32
32
|
T = TypeVar("T", bound=ast3.AST)
|
|
33
33
|
|
|
@@ -64,7 +64,6 @@ TOKEN_AST_MAP: dict[Tok, type[ast3.AST]] = {
|
|
|
64
64
|
Tok.MINUS: ast3.Sub,
|
|
65
65
|
Tok.SUB_EQ: ast3.Sub,
|
|
66
66
|
Tok.BW_NOT: ast3.Invert,
|
|
67
|
-
Tok.BW_NOT_EQ: ast3.Invert,
|
|
68
67
|
Tok.NOT: ast3.Not,
|
|
69
68
|
Tok.EQ: ast3.NotEq,
|
|
70
69
|
Tok.EE: ast3.Eq,
|
|
@@ -89,14 +88,17 @@ UNARY_OP_MAP: dict[Tok, type[ast3.unaryop]] = {
|
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
|
|
92
|
-
class PyastGenPass(
|
|
91
|
+
class PyastGenPass(BaseAstGenPass[ast3.AST]):
|
|
93
92
|
"""Jac blue transpilation to python pass."""
|
|
94
93
|
|
|
95
94
|
def before_pass(self) -> None:
|
|
96
|
-
|
|
97
|
-
PyastGenPass(ir_in=i, prog=self.prog)
|
|
95
|
+
self.child_passes: list[PyastGenPass] = self._init_child_passes(PyastGenPass)
|
|
98
96
|
self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
|
|
99
97
|
self.already_added: list[str] = []
|
|
98
|
+
self.jaclib_imports: set[str] = set() # Track individual jaclib imports
|
|
99
|
+
self.builtin_imports: set[str] = set() # Track individual builtin imports
|
|
100
|
+
self._temp_name_counter: int = 0
|
|
101
|
+
self._hoisted_funcs: list[ast3.FunctionDef | ast3.AsyncFunctionDef] = []
|
|
100
102
|
self.preamble: list[ast3.AST] = [
|
|
101
103
|
self.sync(
|
|
102
104
|
ast3.ImportFrom(
|
|
@@ -106,44 +108,17 @@ class PyastGenPass(UniPass):
|
|
|
106
108
|
),
|
|
107
109
|
jac_node=self.ir_out,
|
|
108
110
|
),
|
|
109
|
-
(
|
|
110
|
-
self.sync(
|
|
111
|
-
ast3.ImportFrom(
|
|
112
|
-
module="jaclang.runtimelib.builtin",
|
|
113
|
-
names=[
|
|
114
|
-
self.sync(
|
|
115
|
-
ast3.alias(
|
|
116
|
-
name="*",
|
|
117
|
-
asname=None,
|
|
118
|
-
)
|
|
119
|
-
)
|
|
120
|
-
],
|
|
121
|
-
level=0,
|
|
122
|
-
),
|
|
123
|
-
jac_node=self.ir_out,
|
|
124
|
-
)
|
|
125
|
-
),
|
|
126
|
-
(
|
|
127
|
-
self.sync(
|
|
128
|
-
ast3.ImportFrom(
|
|
129
|
-
module="jaclang",
|
|
130
|
-
names=[
|
|
131
|
-
self.sync(
|
|
132
|
-
ast3.alias(
|
|
133
|
-
name="JacMachineInterface",
|
|
134
|
-
asname=settings.pyout_jaclib_alias,
|
|
135
|
-
)
|
|
136
|
-
),
|
|
137
|
-
],
|
|
138
|
-
level=0,
|
|
139
|
-
),
|
|
140
|
-
jac_node=self.ir_out,
|
|
141
|
-
)
|
|
142
|
-
),
|
|
143
111
|
]
|
|
112
|
+
self.jsx_processor = PyJsxProcessor(self)
|
|
144
113
|
|
|
145
114
|
def enter_node(self, node: uni.UniNode) -> None:
|
|
146
115
|
"""Enter node."""
|
|
116
|
+
if self._should_skip_client(node):
|
|
117
|
+
node.gen.py_ast = []
|
|
118
|
+
if hasattr(node.gen, "py"):
|
|
119
|
+
node.gen.py = "" # type: ignore[attr-defined]
|
|
120
|
+
self.prune()
|
|
121
|
+
return
|
|
147
122
|
if node.gen.py_ast:
|
|
148
123
|
self.prune()
|
|
149
124
|
return
|
|
@@ -151,25 +126,28 @@ class PyastGenPass(UniPass):
|
|
|
151
126
|
|
|
152
127
|
def exit_node(self, node: uni.UniNode) -> None:
|
|
153
128
|
"""Exit node."""
|
|
129
|
+
if self._should_skip_client(node):
|
|
130
|
+
node.gen.py_ast = []
|
|
131
|
+
if hasattr(node.gen, "py"):
|
|
132
|
+
node.gen.py = "" # type: ignore[attr-defined]
|
|
133
|
+
return
|
|
154
134
|
super().exit_node(node)
|
|
155
|
-
# for i in node.gen.py_ast: # Internal validation
|
|
156
|
-
# self.node_compilable_test(i)
|
|
157
|
-
|
|
158
|
-
# TODO: USE THIS TO SYNC
|
|
159
|
-
# if isinstance(i, ast3.AST):
|
|
160
|
-
# i.jac_link = node
|
|
161
135
|
|
|
162
|
-
def jaclib_obj(self, obj_name: str) -> ast3.Name
|
|
136
|
+
def jaclib_obj(self, obj_name: str) -> ast3.Name:
|
|
163
137
|
"""Return the object from jaclib as ast node based on the import config."""
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
138
|
+
self.jaclib_imports.add(obj_name)
|
|
139
|
+
return self.sync(ast3.Name(id=obj_name, ctx=ast3.Load()))
|
|
140
|
+
|
|
141
|
+
def builtin_name(self, name: str) -> ast3.Name:
|
|
142
|
+
"""Return a builtin name and track it for importing.
|
|
143
|
+
|
|
144
|
+
Note: Some names like 'Enum' are provided by other imports (e.g., needs_enum)
|
|
145
|
+
and should not be added to builtin_imports.
|
|
146
|
+
"""
|
|
147
|
+
# Enum is imported via needs_enum, not from builtins
|
|
148
|
+
if name not in ["Enum"]:
|
|
149
|
+
self.builtin_imports.add(name)
|
|
150
|
+
return self.sync(ast3.Name(id=name, ctx=ast3.Load()))
|
|
173
151
|
|
|
174
152
|
def _add_preamble_once(self, key: str, node: ast3.AST) -> None:
|
|
175
153
|
"""Append an import statement to the preamble once."""
|
|
@@ -187,15 +165,6 @@ class PyastGenPass(UniPass):
|
|
|
187
165
|
),
|
|
188
166
|
)
|
|
189
167
|
|
|
190
|
-
def needs_mtllm(self) -> None:
|
|
191
|
-
"""Ensure byLLM is imported only once."""
|
|
192
|
-
self._add_preamble_once(
|
|
193
|
-
self.needs_mtllm.__name__,
|
|
194
|
-
ast3.Import(
|
|
195
|
-
names=[self.sync(ast3.alias(name="byllm"), jac_node=self.ir_out)]
|
|
196
|
-
),
|
|
197
|
-
)
|
|
198
|
-
|
|
199
168
|
def needs_enum(self) -> None:
|
|
200
169
|
"""Ensure Enum utilities are imported only once."""
|
|
201
170
|
self._add_preamble_once(
|
|
@@ -221,6 +190,33 @@ class PyastGenPass(UniPass):
|
|
|
221
190
|
),
|
|
222
191
|
)
|
|
223
192
|
|
|
193
|
+
def _next_temp_name(self, prefix: str) -> str:
|
|
194
|
+
"""Generate a deterministic temporary name for synthesized definitions."""
|
|
195
|
+
self._temp_name_counter += 1
|
|
196
|
+
return f"__jac_{prefix}_{self._temp_name_counter}"
|
|
197
|
+
|
|
198
|
+
def _function_expr_from_def(
|
|
199
|
+
self,
|
|
200
|
+
func_def: ast3.FunctionDef | ast3.AsyncFunctionDef,
|
|
201
|
+
jac_node: uni.UniNode,
|
|
202
|
+
filename_hint: str,
|
|
203
|
+
) -> ast3.Name:
|
|
204
|
+
"""Convert a synthesized function definition into an executable expression.
|
|
205
|
+
|
|
206
|
+
Instead of using make_block_lambda at runtime, we hoist the function
|
|
207
|
+
definition to be emitted before the current statement, then return
|
|
208
|
+
a reference to the function name.
|
|
209
|
+
"""
|
|
210
|
+
# Ensure locations are fixed
|
|
211
|
+
ast3.fix_missing_locations(func_def)
|
|
212
|
+
# Add the function to the hoisted list - it will be emitted before the current statement
|
|
213
|
+
self._hoisted_funcs.append(func_def)
|
|
214
|
+
# Return a reference to the function name
|
|
215
|
+
return self.sync(
|
|
216
|
+
ast3.Name(id=func_def.name, ctx=ast3.Load()),
|
|
217
|
+
jac_node=jac_node,
|
|
218
|
+
)
|
|
219
|
+
|
|
224
220
|
def _get_sem_decorator(self, node: uni.UniNode) -> ast3.Call | None:
|
|
225
221
|
"""Create a semstring decorator for the given semantic strings.
|
|
226
222
|
|
|
@@ -283,7 +279,10 @@ class PyastGenPass(UniPass):
|
|
|
283
279
|
else {}
|
|
284
280
|
)
|
|
285
281
|
|
|
286
|
-
if
|
|
282
|
+
# Only add sem decorator if there's actual semantic content
|
|
283
|
+
if not semstr and (
|
|
284
|
+
not inner_semstr or all(not v for v in inner_semstr.values())
|
|
285
|
+
):
|
|
287
286
|
return None
|
|
288
287
|
|
|
289
288
|
return self.sync(
|
|
@@ -308,15 +307,9 @@ class PyastGenPass(UniPass):
|
|
|
308
307
|
)
|
|
309
308
|
)
|
|
310
309
|
|
|
311
|
-
def
|
|
312
|
-
"""
|
|
313
|
-
|
|
314
|
-
for item in body:
|
|
315
|
-
if isinstance(item, list):
|
|
316
|
-
new_body.extend(item)
|
|
317
|
-
elif item is not None:
|
|
318
|
-
new_body.append(item)
|
|
319
|
-
return new_body
|
|
310
|
+
def _should_skip_client(self, node: uni.UniNode) -> bool:
|
|
311
|
+
"""Check if node is a client-facing declaration that should skip Python codegen."""
|
|
312
|
+
return isinstance(node, uni.ClientFacingNode) and node.is_client_decl
|
|
320
313
|
|
|
321
314
|
def sync(
|
|
322
315
|
self, py_node: T, jac_node: Optional[uni.UniNode] = None, deep: bool = False
|
|
@@ -373,7 +366,7 @@ class PyastGenPass(UniPass):
|
|
|
373
366
|
[self.sync(ast3.Pass())]
|
|
374
367
|
if isinstance(node, Sequence) and not valid_stmts
|
|
375
368
|
else (
|
|
376
|
-
self.
|
|
369
|
+
self._flatten_ast_list(
|
|
377
370
|
[
|
|
378
371
|
x.gen.py_ast
|
|
379
372
|
for x in valid_stmts
|
|
@@ -417,31 +410,55 @@ class PyastGenPass(UniPass):
|
|
|
417
410
|
node.gen.py_ast = node.tag.gen.py_ast
|
|
418
411
|
|
|
419
412
|
def exit_module(self, node: uni.Module) -> None:
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
[
|
|
413
|
+
# Merge jaclib and builtin imports from child passes
|
|
414
|
+
for child_pass in self.child_passes:
|
|
415
|
+
self.jaclib_imports.update(child_pass.jaclib_imports)
|
|
416
|
+
self.builtin_imports.update(child_pass.builtin_imports)
|
|
417
|
+
|
|
418
|
+
# Add builtin imports if any were used
|
|
419
|
+
if self.builtin_imports:
|
|
420
|
+
self.preamble.append(
|
|
429
421
|
self.sync(
|
|
430
|
-
ast3.
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
422
|
+
ast3.ImportFrom(
|
|
423
|
+
module="jaclang.runtimelib.builtin",
|
|
424
|
+
names=[
|
|
425
|
+
self.sync(ast3.alias(name=name, asname=None))
|
|
426
|
+
for name in sorted(self.builtin_imports)
|
|
427
|
+
],
|
|
428
|
+
level=0,
|
|
429
|
+
),
|
|
430
|
+
jac_node=self.ir_out,
|
|
431
|
+
)
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
# Add library imports at the end of preamble
|
|
435
|
+
if self.jaclib_imports:
|
|
436
|
+
self.preamble.append(
|
|
437
|
+
self.sync(
|
|
438
|
+
ast3.ImportFrom(
|
|
439
|
+
module="jaclang.lib",
|
|
440
|
+
names=[
|
|
441
|
+
self.sync(ast3.alias(name=name, asname=None))
|
|
442
|
+
for name in sorted(self.jaclib_imports)
|
|
443
|
+
],
|
|
444
|
+
level=0,
|
|
445
|
+
),
|
|
446
|
+
jac_node=self.ir_out,
|
|
447
|
+
)
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
merged_body = self._merge_module_bodies(node)
|
|
451
|
+
body_items: list[ast3.AST | list[ast3.AST] | None] = [*self.preamble]
|
|
452
|
+
body_items.extend(item.gen.py_ast for item in merged_body)
|
|
453
|
+
|
|
454
|
+
if node.doc:
|
|
455
|
+
doc_stmt = self.sync(
|
|
456
|
+
ast3.Expr(value=cast(ast3.expr, node.doc.gen.py_ast[0])),
|
|
457
|
+
jac_node=node.doc,
|
|
458
|
+
)
|
|
459
|
+
body_items.insert(0, doc_stmt)
|
|
460
|
+
|
|
461
|
+
new_body = self._flatten_ast_list(body_items)
|
|
445
462
|
node.gen.py_ast = [
|
|
446
463
|
self.sync(
|
|
447
464
|
ast3.Module(
|
|
@@ -458,7 +475,7 @@ class PyastGenPass(UniPass):
|
|
|
458
475
|
ast3.Expr(value=cast(ast3.expr, node.doc.gen.py_ast[0])),
|
|
459
476
|
jac_node=node.doc,
|
|
460
477
|
)
|
|
461
|
-
assigns_ast: list[ast3.AST] = self.
|
|
478
|
+
assigns_ast: list[ast3.AST] = self._flatten_ast_list(
|
|
462
479
|
[a.gen.py_ast for a in node.assignments]
|
|
463
480
|
)
|
|
464
481
|
if isinstance(doc, ast3.AST):
|
|
@@ -466,7 +483,9 @@ class PyastGenPass(UniPass):
|
|
|
466
483
|
else:
|
|
467
484
|
raise self.ice()
|
|
468
485
|
else:
|
|
469
|
-
node.gen.py_ast = self.
|
|
486
|
+
node.gen.py_ast = self._flatten_ast_list(
|
|
487
|
+
[a.gen.py_ast for a in node.assignments]
|
|
488
|
+
)
|
|
470
489
|
|
|
471
490
|
def exit_test(self, node: uni.Test) -> None:
|
|
472
491
|
test_name = node.name.sym_name
|
|
@@ -687,18 +706,17 @@ class PyastGenPass(UniPass):
|
|
|
687
706
|
if node.arch_type.name != Tok.KW_CLASS:
|
|
688
707
|
base_classes.append(self.jaclib_obj(node.arch_type.value.capitalize()))
|
|
689
708
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
type_params=[],
|
|
699
|
-
)
|
|
709
|
+
class_def = self.sync(
|
|
710
|
+
ast3.ClassDef(
|
|
711
|
+
name=node.name.sym_name,
|
|
712
|
+
bases=[cast(ast3.expr, i) for i in base_classes],
|
|
713
|
+
keywords=[],
|
|
714
|
+
body=[cast(ast3.stmt, i) for i in body],
|
|
715
|
+
decorator_list=[cast(ast3.expr, i) for i in decorators],
|
|
716
|
+
type_params=[],
|
|
700
717
|
)
|
|
701
|
-
|
|
718
|
+
)
|
|
719
|
+
node.gen.py_ast = [class_def]
|
|
702
720
|
|
|
703
721
|
def enter_enum(self, node: uni.Enum) -> None:
|
|
704
722
|
if isinstance(node.body, uni.ImplDef):
|
|
@@ -722,19 +740,18 @@ class PyastGenPass(UniPass):
|
|
|
722
740
|
decorators.append(sem_decorator)
|
|
723
741
|
|
|
724
742
|
base_classes = [cast(ast3.expr, i.gen.py_ast[0]) for i in node.base_classes]
|
|
725
|
-
base_classes.append(self.
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
type_params=[],
|
|
735
|
-
)
|
|
743
|
+
base_classes.append(self.builtin_name("Enum"))
|
|
744
|
+
class_def = self.sync(
|
|
745
|
+
ast3.ClassDef(
|
|
746
|
+
name=node.name.sym_name,
|
|
747
|
+
bases=[cast(ast3.expr, i) for i in base_classes],
|
|
748
|
+
keywords=[],
|
|
749
|
+
body=[cast(ast3.stmt, i) for i in body],
|
|
750
|
+
decorator_list=[cast(ast3.expr, i) for i in decorators],
|
|
751
|
+
type_params=[],
|
|
736
752
|
)
|
|
737
|
-
|
|
753
|
+
)
|
|
754
|
+
node.gen.py_ast = [class_def]
|
|
738
755
|
|
|
739
756
|
def enter_ability(self, node: uni.Ability) -> None:
|
|
740
757
|
if isinstance(node.body, uni.ImplDef):
|
|
@@ -744,23 +761,9 @@ class PyastGenPass(UniPass):
|
|
|
744
761
|
self, model: ast3.expr, caller: ast3.expr, args: ast3.Dict
|
|
745
762
|
) -> ast3.Call:
|
|
746
763
|
"""Reusable method to codegen call_llm(model, caller, args)."""
|
|
747
|
-
self.needs_mtllm()
|
|
748
|
-
mtir_cls_ast = self.sync(
|
|
749
|
-
ast3.Attribute(
|
|
750
|
-
value=self.sync(ast3.Name(id="byllm", ctx=ast3.Load())),
|
|
751
|
-
attr="MTIR",
|
|
752
|
-
ctx=ast3.Load(),
|
|
753
|
-
)
|
|
754
|
-
)
|
|
755
764
|
mtir_ast = self.sync(
|
|
756
765
|
ast3.Call(
|
|
757
|
-
func=self.
|
|
758
|
-
ast3.Attribute(
|
|
759
|
-
value=mtir_cls_ast,
|
|
760
|
-
attr="factory",
|
|
761
|
-
ctx=ast3.Load(),
|
|
762
|
-
)
|
|
763
|
-
),
|
|
766
|
+
func=self.jaclib_obj("get_mtir"),
|
|
764
767
|
args=[],
|
|
765
768
|
keywords=[
|
|
766
769
|
self.sync(
|
|
@@ -928,7 +931,9 @@ class PyastGenPass(UniPass):
|
|
|
928
931
|
if isinstance(node.signature, uni.EventSignature):
|
|
929
932
|
decorator_list.append(
|
|
930
933
|
self.jaclib_obj(
|
|
931
|
-
"
|
|
934
|
+
"on_entry"
|
|
935
|
+
if node.signature.event.name == Tok.KW_ENTRY
|
|
936
|
+
else "on_exit"
|
|
932
937
|
)
|
|
933
938
|
)
|
|
934
939
|
|
|
@@ -943,11 +948,9 @@ class PyastGenPass(UniPass):
|
|
|
943
948
|
)
|
|
944
949
|
)
|
|
945
950
|
if node.is_abstract:
|
|
946
|
-
decorator_list.append(
|
|
947
|
-
self.sync(ast3.Name(id="abstractmethod", ctx=ast3.Load()))
|
|
948
|
-
)
|
|
951
|
+
decorator_list.append(self.builtin_name("abstractmethod"))
|
|
949
952
|
if node.is_override:
|
|
950
|
-
decorator_list.append(self.
|
|
953
|
+
decorator_list.append(self.builtin_name("override"))
|
|
951
954
|
if node.is_static:
|
|
952
955
|
decorator_list.insert(
|
|
953
956
|
0, self.sync(ast3.Name(id="staticmethod", ctx=ast3.Load()))
|
|
@@ -962,36 +965,35 @@ class PyastGenPass(UniPass):
|
|
|
962
965
|
if isinstance(node.signature, uni.FuncSignature) and node.signature.return_type:
|
|
963
966
|
ast_returns = cast(ast3.expr, node.signature.return_type.gen.py_ast[0])
|
|
964
967
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
defaults=[],
|
|
985
|
-
)
|
|
968
|
+
func_def = self.sync(
|
|
969
|
+
func_type(
|
|
970
|
+
name=node.name_ref.sym_name,
|
|
971
|
+
args=(
|
|
972
|
+
cast(ast3.arguments, node.signature.gen.py_ast[0])
|
|
973
|
+
if node.signature
|
|
974
|
+
else self.sync(
|
|
975
|
+
ast3.arguments(
|
|
976
|
+
posonlyargs=[],
|
|
977
|
+
args=(
|
|
978
|
+
[self.sync(ast3.arg(arg="self", annotation=None))]
|
|
979
|
+
if node.is_method
|
|
980
|
+
else []
|
|
981
|
+
),
|
|
982
|
+
vararg=None,
|
|
983
|
+
kwonlyargs=[],
|
|
984
|
+
kw_defaults=[],
|
|
985
|
+
kwarg=None,
|
|
986
|
+
defaults=[],
|
|
986
987
|
)
|
|
987
|
-
)
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
988
|
+
)
|
|
989
|
+
),
|
|
990
|
+
body=[cast(ast3.stmt, i) for i in body],
|
|
991
|
+
decorator_list=[cast(ast3.expr, i) for i in decorator_list],
|
|
992
|
+
returns=ast_returns,
|
|
993
|
+
type_params=[],
|
|
993
994
|
)
|
|
994
|
-
|
|
995
|
+
)
|
|
996
|
+
node.gen.py_ast = [func_def]
|
|
995
997
|
|
|
996
998
|
def exit_impl_def(self, node: uni.ImplDef) -> None:
|
|
997
999
|
pass
|
|
@@ -1111,7 +1113,9 @@ class PyastGenPass(UniPass):
|
|
|
1111
1113
|
]
|
|
1112
1114
|
|
|
1113
1115
|
def exit_arch_has(self, node: uni.ArchHas) -> None:
|
|
1114
|
-
vars_py: list[ast3.AST] = self.
|
|
1116
|
+
vars_py: list[ast3.AST] = self._flatten_ast_list(
|
|
1117
|
+
[v.gen.py_ast for v in node.vars]
|
|
1118
|
+
)
|
|
1115
1119
|
if node.doc:
|
|
1116
1120
|
doc = self.sync(
|
|
1117
1121
|
ast3.Expr(value=cast(ast3.expr, node.doc.gen.py_ast[0])),
|
|
@@ -1145,7 +1149,7 @@ class PyastGenPass(UniPass):
|
|
|
1145
1149
|
elif is_static_var:
|
|
1146
1150
|
annotation = self.sync(
|
|
1147
1151
|
ast3.Subscript(
|
|
1148
|
-
value=self.
|
|
1152
|
+
value=self.builtin_name("ClassVar"),
|
|
1149
1153
|
slice=cast(ast3.expr, annotation),
|
|
1150
1154
|
ctx=ast3.Load(),
|
|
1151
1155
|
)
|
|
@@ -1222,8 +1226,29 @@ class PyastGenPass(UniPass):
|
|
|
1222
1226
|
]
|
|
1223
1227
|
|
|
1224
1228
|
def exit_typed_ctx_block(self, node: uni.TypedCtxBlock) -> None:
|
|
1225
|
-
|
|
1226
|
-
|
|
1229
|
+
loc = self.sync(
|
|
1230
|
+
ast3.Name(id=Con.HERE.value, ctx=ast3.Load())
|
|
1231
|
+
if node.from_walker
|
|
1232
|
+
else ast3.Name(id=Con.VISITOR.value, ctx=ast3.Load())
|
|
1233
|
+
)
|
|
1234
|
+
node.gen.py_ast = [
|
|
1235
|
+
self.sync(
|
|
1236
|
+
ast3.If(
|
|
1237
|
+
test=self.sync(
|
|
1238
|
+
ast3.Call(
|
|
1239
|
+
func=self.sync(ast3.Name(id="isinstance", ctx=ast3.Load())),
|
|
1240
|
+
args=[
|
|
1241
|
+
loc,
|
|
1242
|
+
cast(ast3.expr, node.type_ctx.gen.py_ast[0]),
|
|
1243
|
+
],
|
|
1244
|
+
keywords=[],
|
|
1245
|
+
)
|
|
1246
|
+
),
|
|
1247
|
+
body=cast(list[ast3.stmt], self.resolve_stmt_block(node.body)),
|
|
1248
|
+
orelse=[],
|
|
1249
|
+
)
|
|
1250
|
+
)
|
|
1251
|
+
]
|
|
1227
1252
|
|
|
1228
1253
|
def exit_if_stmt(self, node: uni.IfStmt) -> None:
|
|
1229
1254
|
node.gen.py_ast = [
|
|
@@ -1259,19 +1284,24 @@ class PyastGenPass(UniPass):
|
|
|
1259
1284
|
node.gen.py_ast = self.resolve_stmt_block(node.body)
|
|
1260
1285
|
|
|
1261
1286
|
def exit_expr_stmt(self, node: uni.ExprStmt) -> None:
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
)
|
|
1287
|
+
# Collect any hoisted functions that were generated during expression evaluation
|
|
1288
|
+
hoisted = self._hoisted_funcs[:]
|
|
1289
|
+
self._hoisted_funcs.clear()
|
|
1290
|
+
|
|
1291
|
+
expr_stmt = (
|
|
1292
|
+
self.sync(ast3.Expr(value=cast(ast3.expr, node.expr.gen.py_ast[0])))
|
|
1293
|
+
if not node.in_fstring
|
|
1294
|
+
else self.sync(
|
|
1295
|
+
ast3.FormattedValue(
|
|
1296
|
+
value=cast(ast3.expr, node.expr.gen.py_ast[0]),
|
|
1297
|
+
conversion=-1,
|
|
1298
|
+
format_spec=None,
|
|
1272
1299
|
)
|
|
1273
1300
|
)
|
|
1274
|
-
|
|
1301
|
+
)
|
|
1302
|
+
|
|
1303
|
+
# Emit hoisted functions before the expression statement
|
|
1304
|
+
node.gen.py_ast = [*hoisted, expr_stmt]
|
|
1275
1305
|
|
|
1276
1306
|
def exit_concurrent_expr(self, node: uni.ConcurrentExpr) -> None:
|
|
1277
1307
|
func = ""
|
|
@@ -1708,7 +1738,7 @@ class PyastGenPass(UniPass):
|
|
|
1708
1738
|
value=self.sync(
|
|
1709
1739
|
self.sync(
|
|
1710
1740
|
ast3.Call(
|
|
1711
|
-
func=self.jaclib_obj("
|
|
1741
|
+
func=self.jaclib_obj("log_report"),
|
|
1712
1742
|
args=cast(list[ast3.expr], node.expr.gen.py_ast),
|
|
1713
1743
|
keywords=[],
|
|
1714
1744
|
)
|
|
@@ -1865,48 +1895,49 @@ class PyastGenPass(UniPass):
|
|
|
1865
1895
|
)
|
|
1866
1896
|
targets_ast = [cast(ast3.expr, t.gen.py_ast[0]) for t in node.target]
|
|
1867
1897
|
|
|
1898
|
+
# Collect any hoisted functions that were generated during expression evaluation
|
|
1899
|
+
hoisted = self._hoisted_funcs[:]
|
|
1900
|
+
self._hoisted_funcs.clear()
|
|
1901
|
+
|
|
1868
1902
|
if node.type_tag:
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
ast3.
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
value
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
simple=int(isinstance(targets_ast[0], ast3.Name)),
|
|
1880
|
-
)
|
|
1903
|
+
assignment_stmt: ast3.AnnAssign | ast3.Assign | ast3.AugAssign = self.sync(
|
|
1904
|
+
ast3.AnnAssign(
|
|
1905
|
+
target=cast(ast3.Name, targets_ast[0]),
|
|
1906
|
+
annotation=cast(ast3.expr, node.type_tag.gen.py_ast[0]),
|
|
1907
|
+
value=(
|
|
1908
|
+
cast(ast3.expr, node.value.gen.py_ast[0])
|
|
1909
|
+
if node.value
|
|
1910
|
+
else None
|
|
1911
|
+
),
|
|
1912
|
+
simple=int(isinstance(targets_ast[0], ast3.Name)),
|
|
1881
1913
|
)
|
|
1882
|
-
|
|
1914
|
+
)
|
|
1883
1915
|
elif node.aug_op:
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
ast3.
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
value
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
),
|
|
1894
|
-
)
|
|
1916
|
+
assignment_stmt = self.sync(
|
|
1917
|
+
ast3.AugAssign(
|
|
1918
|
+
target=cast(ast3.Name, targets_ast[0]),
|
|
1919
|
+
op=cast(ast3.operator, node.aug_op.gen.py_ast[0]),
|
|
1920
|
+
value=(
|
|
1921
|
+
cast(ast3.expr, value)
|
|
1922
|
+
if isinstance(value, ast3.expr)
|
|
1923
|
+
else ast3.Constant(value=None)
|
|
1924
|
+
),
|
|
1895
1925
|
)
|
|
1896
|
-
|
|
1926
|
+
)
|
|
1897
1927
|
else:
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
ast3.
|
|
1901
|
-
|
|
1902
|
-
value
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
),
|
|
1907
|
-
)
|
|
1928
|
+
assignment_stmt = self.sync(
|
|
1929
|
+
ast3.Assign(
|
|
1930
|
+
targets=cast(list[ast3.expr], targets_ast),
|
|
1931
|
+
value=(
|
|
1932
|
+
cast(ast3.expr, value)
|
|
1933
|
+
if isinstance(value, ast3.expr)
|
|
1934
|
+
else ast3.Constant(value=None)
|
|
1935
|
+
),
|
|
1908
1936
|
)
|
|
1909
|
-
|
|
1937
|
+
)
|
|
1938
|
+
|
|
1939
|
+
# Emit hoisted functions before the assignment
|
|
1940
|
+
node.gen.py_ast = [*hoisted, assignment_stmt]
|
|
1910
1941
|
|
|
1911
1942
|
def exit_binary_expr(self, node: uni.BinaryExpr) -> None:
|
|
1912
1943
|
if isinstance(node.op, uni.ConnectOp):
|
|
@@ -1999,7 +2030,7 @@ class PyastGenPass(UniPass):
|
|
|
1999
2030
|
keywords.append(
|
|
2000
2031
|
self.sync(
|
|
2001
2032
|
ast3.keyword(
|
|
2002
|
-
arg="
|
|
2033
|
+
arg="filter_on",
|
|
2003
2034
|
value=cast(
|
|
2004
2035
|
ast3.expr,
|
|
2005
2036
|
node.op.edge_spec.filter_cond.gen.py_ast[0],
|
|
@@ -2134,28 +2165,80 @@ class PyastGenPass(UniPass):
|
|
|
2134
2165
|
]
|
|
2135
2166
|
|
|
2136
2167
|
def exit_lambda_expr(self, node: uni.LambdaExpr) -> None:
|
|
2137
|
-
#
|
|
2168
|
+
# Multi-statement lambda emits a synthesized function definition that is
|
|
2169
|
+
# hoisted before the current statement.
|
|
2170
|
+
if isinstance(node.body, list):
|
|
2171
|
+
if node.signature and node.signature.gen.py_ast:
|
|
2172
|
+
arguments = cast(ast3.arguments, node.signature.gen.py_ast[0])
|
|
2173
|
+
else:
|
|
2174
|
+
arguments = self.sync(
|
|
2175
|
+
ast3.arguments(
|
|
2176
|
+
posonlyargs=[],
|
|
2177
|
+
args=[],
|
|
2178
|
+
kwonlyargs=[],
|
|
2179
|
+
kw_defaults=[],
|
|
2180
|
+
defaults=[],
|
|
2181
|
+
),
|
|
2182
|
+
jac_node=node,
|
|
2183
|
+
)
|
|
2184
|
+
body_stmts = [
|
|
2185
|
+
cast(ast3.stmt, stmt)
|
|
2186
|
+
for stmt in self.resolve_stmt_block(node.body, doc=None)
|
|
2187
|
+
]
|
|
2188
|
+
if not body_stmts:
|
|
2189
|
+
body_stmts = [self.sync(ast3.Pass(), jac_node=node)]
|
|
2190
|
+
func_name = self._next_temp_name("lambda")
|
|
2191
|
+
returns = (
|
|
2192
|
+
cast(ast3.expr, node.signature.return_type.gen.py_ast[0])
|
|
2193
|
+
if node.signature
|
|
2194
|
+
and node.signature.return_type
|
|
2195
|
+
and node.signature.return_type.gen.py_ast
|
|
2196
|
+
else None
|
|
2197
|
+
)
|
|
2198
|
+
func_def = self.sync(
|
|
2199
|
+
ast3.FunctionDef(
|
|
2200
|
+
name=func_name,
|
|
2201
|
+
args=arguments,
|
|
2202
|
+
body=body_stmts,
|
|
2203
|
+
decorator_list=[],
|
|
2204
|
+
returns=returns,
|
|
2205
|
+
type_params=[],
|
|
2206
|
+
),
|
|
2207
|
+
jac_node=node,
|
|
2208
|
+
)
|
|
2209
|
+
node.gen.py_ast = [
|
|
2210
|
+
self._function_expr_from_def(
|
|
2211
|
+
func_def=func_def,
|
|
2212
|
+
jac_node=node,
|
|
2213
|
+
filename_hint=f"<jac_lambda:{func_name}>",
|
|
2214
|
+
)
|
|
2215
|
+
]
|
|
2216
|
+
return
|
|
2217
|
+
|
|
2218
|
+
# Single-expression lambda maps directly to Python lambda; strip annotations.
|
|
2138
2219
|
if node.signature:
|
|
2139
2220
|
self._remove_lambda_param_annotations(node.signature)
|
|
2140
|
-
|
|
2221
|
+
if node.signature and node.signature.gen.py_ast:
|
|
2222
|
+
arguments = cast(ast3.arguments, node.signature.gen.py_ast[0])
|
|
2223
|
+
else:
|
|
2224
|
+
arguments = self.sync(
|
|
2225
|
+
ast3.arguments(
|
|
2226
|
+
posonlyargs=[],
|
|
2227
|
+
args=[],
|
|
2228
|
+
kwonlyargs=[],
|
|
2229
|
+
kw_defaults=[],
|
|
2230
|
+
defaults=[],
|
|
2231
|
+
),
|
|
2232
|
+
jac_node=node,
|
|
2233
|
+
)
|
|
2234
|
+
body_expr = cast(ast3.expr, node.body.gen.py_ast[0])
|
|
2141
2235
|
node.gen.py_ast = [
|
|
2142
2236
|
self.sync(
|
|
2143
2237
|
ast3.Lambda(
|
|
2144
|
-
args=
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
ast3.arguments(
|
|
2149
|
-
posonlyargs=[],
|
|
2150
|
-
args=[],
|
|
2151
|
-
kwonlyargs=[],
|
|
2152
|
-
kw_defaults=[],
|
|
2153
|
-
defaults=[],
|
|
2154
|
-
)
|
|
2155
|
-
)
|
|
2156
|
-
),
|
|
2157
|
-
body=cast(ast3.expr, node.body.gen.py_ast[0]),
|
|
2158
|
-
)
|
|
2238
|
+
args=arguments,
|
|
2239
|
+
body=body_expr,
|
|
2240
|
+
),
|
|
2241
|
+
jac_node=node,
|
|
2159
2242
|
)
|
|
2160
2243
|
]
|
|
2161
2244
|
|
|
@@ -2206,7 +2289,7 @@ class PyastGenPass(UniPass):
|
|
|
2206
2289
|
node.gen.py_ast = [
|
|
2207
2290
|
self.sync(
|
|
2208
2291
|
ast3.Call(
|
|
2209
|
-
func=self.
|
|
2292
|
+
func=self.builtin_name("jobj"),
|
|
2210
2293
|
args=[],
|
|
2211
2294
|
keywords=[
|
|
2212
2295
|
self.sync(
|
|
@@ -2239,9 +2322,8 @@ class PyastGenPass(UniPass):
|
|
|
2239
2322
|
for i in str_seq:
|
|
2240
2323
|
if isinstance(i, uni.String):
|
|
2241
2324
|
pieces.append(i.lit_value)
|
|
2242
|
-
elif isinstance(i, uni.FString):
|
|
2243
|
-
pieces.extend(get_pieces(i.parts)) if i.parts else None
|
|
2244
|
-
elif isinstance(i, uni.ExprStmt):
|
|
2325
|
+
elif isinstance(i, (uni.FString, uni.ExprStmt)):
|
|
2326
|
+
# pieces.extend(get_pieces(i.parts)) if i.parts else None
|
|
2245
2327
|
pieces.append(i.gen.py_ast[0])
|
|
2246
2328
|
elif isinstance(i, uni.Token) and i.name in [Tok.LBRACE, Tok.RBRACE]:
|
|
2247
2329
|
continue
|
|
@@ -2281,11 +2363,32 @@ class PyastGenPass(UniPass):
|
|
|
2281
2363
|
node.gen.py_ast = [combined_multi[0]]
|
|
2282
2364
|
|
|
2283
2365
|
def exit_f_string(self, node: uni.FString) -> None:
|
|
2284
|
-
|
|
2285
|
-
|
|
2366
|
+
node.gen.py_ast = [
|
|
2367
|
+
self.sync(
|
|
2368
|
+
ast3.JoinedStr(
|
|
2369
|
+
values=[
|
|
2370
|
+
cast(ast3.expr, part.gen.py_ast[0])
|
|
2371
|
+
for part in node.parts
|
|
2372
|
+
if part.gen.py_ast
|
|
2373
|
+
],
|
|
2374
|
+
)
|
|
2375
|
+
)
|
|
2376
|
+
]
|
|
2377
|
+
|
|
2378
|
+
def exit_formatted_value(self, node: uni.FormattedValue) -> None:
|
|
2379
|
+
node.gen.py_ast = [
|
|
2380
|
+
self.sync(
|
|
2381
|
+
ast3.FormattedValue(
|
|
2382
|
+
value=cast(ast3.expr, node.format_part.gen.py_ast[0]),
|
|
2383
|
+
conversion=node.conversion,
|
|
2384
|
+
format_spec=(
|
|
2385
|
+
cast(ast3.expr, node.format_spec.gen.py_ast[0])
|
|
2386
|
+
if node.format_spec
|
|
2387
|
+
else None
|
|
2388
|
+
),
|
|
2389
|
+
)
|
|
2390
|
+
)
|
|
2286
2391
|
]
|
|
2287
|
-
parts = self.flatten(cast(list[list[ast3.AST] | ast3.AST | None], py_parts))
|
|
2288
|
-
node.gen.py_ast = parts if parts else [self.sync(ast3.Constant(value=""))]
|
|
2289
2392
|
|
|
2290
2393
|
def exit_list_val(self, node: uni.ListVal) -> None:
|
|
2291
2394
|
elts = [cast(ast3.expr, v.gen.py_ast[0]) for v in node.values]
|
|
@@ -2431,7 +2534,7 @@ class PyastGenPass(UniPass):
|
|
|
2431
2534
|
node.gen.py_ast = [
|
|
2432
2535
|
self.sync(
|
|
2433
2536
|
ast3.Call(
|
|
2434
|
-
func=self.jaclib_obj("
|
|
2537
|
+
func=self.jaclib_obj("filter_on"),
|
|
2435
2538
|
args=[],
|
|
2436
2539
|
keywords=[
|
|
2437
2540
|
self.sync(
|
|
@@ -2454,7 +2557,7 @@ class PyastGenPass(UniPass):
|
|
|
2454
2557
|
node.gen.py_ast = [
|
|
2455
2558
|
self.sync(
|
|
2456
2559
|
ast3.Call(
|
|
2457
|
-
func=self.jaclib_obj("
|
|
2560
|
+
func=self.jaclib_obj("assign_all"),
|
|
2458
2561
|
args=cast(
|
|
2459
2562
|
list[ast3.expr],
|
|
2460
2563
|
[node.target.gen.py_ast[0], node.right.gen.py_ast[0]],
|
|
@@ -2501,6 +2604,24 @@ class PyastGenPass(UniPass):
|
|
|
2501
2604
|
]
|
|
2502
2605
|
|
|
2503
2606
|
def exit_atom_unit(self, node: uni.AtomUnit) -> None:
|
|
2607
|
+
if (
|
|
2608
|
+
isinstance(node.value, uni.Ability)
|
|
2609
|
+
and node.value.gen.py_ast
|
|
2610
|
+
and isinstance(
|
|
2611
|
+
node.value.gen.py_ast[0], (ast3.FunctionDef, ast3.AsyncFunctionDef)
|
|
2612
|
+
)
|
|
2613
|
+
):
|
|
2614
|
+
func_ast = cast(
|
|
2615
|
+
ast3.FunctionDef | ast3.AsyncFunctionDef, node.value.gen.py_ast[0]
|
|
2616
|
+
)
|
|
2617
|
+
node.gen.py_ast = [
|
|
2618
|
+
self._function_expr_from_def(
|
|
2619
|
+
func_def=func_ast,
|
|
2620
|
+
jac_node=node,
|
|
2621
|
+
filename_hint=f"<jac_iife:{func_ast.name}>",
|
|
2622
|
+
)
|
|
2623
|
+
]
|
|
2624
|
+
return
|
|
2504
2625
|
node.gen.py_ast = node.value.gen.py_ast
|
|
2505
2626
|
|
|
2506
2627
|
def gen_call_args(
|
|
@@ -2649,7 +2770,7 @@ class PyastGenPass(UniPass):
|
|
|
2649
2770
|
|
|
2650
2771
|
pynode = self.sync(
|
|
2651
2772
|
ast3.Call(
|
|
2652
|
-
func=self.jaclib_obj("
|
|
2773
|
+
func=self.jaclib_obj("OPath"),
|
|
2653
2774
|
args=[cast(ast3.expr, origin or cur.gen.py_ast[0])],
|
|
2654
2775
|
keywords=[],
|
|
2655
2776
|
)
|
|
@@ -2685,7 +2806,7 @@ class PyastGenPass(UniPass):
|
|
|
2685
2806
|
func=self.sync(
|
|
2686
2807
|
ast3.Attribute(
|
|
2687
2808
|
value=pynode,
|
|
2688
|
-
attr=f"
|
|
2809
|
+
attr=f"edge_{cur.edge_dir.name.lower()}",
|
|
2689
2810
|
ctx=ast3.Load(),
|
|
2690
2811
|
)
|
|
2691
2812
|
),
|
|
@@ -3026,6 +3147,11 @@ class PyastGenPass(UniPass):
|
|
|
3026
3147
|
|
|
3027
3148
|
def exit_name(self, node: uni.Name) -> None:
|
|
3028
3149
|
name = node.sym_name
|
|
3150
|
+
# Track if this name is a known builtin
|
|
3151
|
+
import jaclang.runtimelib.builtin
|
|
3152
|
+
|
|
3153
|
+
if name in set(jaclang.runtimelib.builtin.__all__):
|
|
3154
|
+
self.builtin_imports.add(name)
|
|
3029
3155
|
node.gen.py_ast = [self.sync(ast3.Name(id=name, ctx=node.py_ctx_func()))]
|
|
3030
3156
|
|
|
3031
3157
|
def exit_float(self, node: uni.Float) -> None:
|
|
@@ -3051,6 +3177,38 @@ class PyastGenPass(UniPass):
|
|
|
3051
3177
|
def exit_ellipsis(self, node: uni.Ellipsis) -> None:
|
|
3052
3178
|
node.gen.py_ast = [self.sync(ast3.Constant(value=...))]
|
|
3053
3179
|
|
|
3180
|
+
def exit_jsx_element(self, node: uni.JsxElement) -> None:
|
|
3181
|
+
"""Generate Python AST for JSX elements."""
|
|
3182
|
+
self.jsx_processor.element(node)
|
|
3183
|
+
|
|
3184
|
+
def exit_jsx_element_name(self, node: uni.JsxElementName) -> None:
|
|
3185
|
+
"""Generate Python AST for JSX element names."""
|
|
3186
|
+
self.jsx_processor.element_name(node)
|
|
3187
|
+
|
|
3188
|
+
def exit_jsx_attribute(self, node: uni.JsxAttribute) -> None:
|
|
3189
|
+
"""Bases class for JSX attributes - handled by subclasses."""
|
|
3190
|
+
pass
|
|
3191
|
+
|
|
3192
|
+
def exit_jsx_spread_attribute(self, node: uni.JsxSpreadAttribute) -> None:
|
|
3193
|
+
"""Generate Python AST for JSX spread attributes."""
|
|
3194
|
+
self.jsx_processor.spread_attribute(node)
|
|
3195
|
+
|
|
3196
|
+
def exit_jsx_normal_attribute(self, node: uni.JsxNormalAttribute) -> None:
|
|
3197
|
+
"""Generate Python AST for JSX normal attributes."""
|
|
3198
|
+
self.jsx_processor.normal_attribute(node)
|
|
3199
|
+
|
|
3200
|
+
def exit_jsx_child(self, node: uni.JsxChild) -> None:
|
|
3201
|
+
"""Bases class for JSX children - handled by subclasses."""
|
|
3202
|
+
pass
|
|
3203
|
+
|
|
3204
|
+
def exit_jsx_text(self, node: uni.JsxText) -> None:
|
|
3205
|
+
"""Generate Python AST for JSX text nodes."""
|
|
3206
|
+
self.jsx_processor.text(node)
|
|
3207
|
+
|
|
3208
|
+
def exit_jsx_expression(self, node: uni.JsxExpression) -> None:
|
|
3209
|
+
"""Generate Python AST for JSX expression children."""
|
|
3210
|
+
self.jsx_processor.expression(node)
|
|
3211
|
+
|
|
3054
3212
|
def exit_semi(self, node: uni.Semi) -> None:
|
|
3055
3213
|
pass
|
|
3056
3214
|
|