jaclang 0.8.9__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 +147 -25
- jaclang/cli/cmdreg.py +144 -8
- jaclang/compiler/__init__.py +6 -1
- jaclang/compiler/codeinfo.py +16 -1
- jaclang/compiler/constant.py +33 -13
- jaclang/compiler/jac.lark +130 -31
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +567 -176
- 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/pyast_gen_pass.py +324 -234
- jaclang/compiler/passes/main/pyast_load_pass.py +46 -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 -2
- 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_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 +115 -0
- jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
- 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 +22 -25
- 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 +169 -50
- jaclang/compiler/type_system/type_utils.py +1 -1
- jaclang/compiler/type_system/types.py +6 -0
- jaclang/compiler/unitree.py +430 -84
- 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 +1 -1
- jaclang/runtimelib/client_bundle.py +169 -0
- jaclang/runtimelib/client_runtime.jac +586 -0
- jaclang/runtimelib/constructs.py +2 -0
- jaclang/runtimelib/machine.py +259 -100
- 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 -2
- 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/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 +1 -1
- jaclang/tests/test_language.py +10 -39
- jaclang/tests/test_reference.py +17 -2
- jaclang/utils/NonGPT.py +375 -0
- jaclang/utils/helpers.py +44 -16
- jaclang/utils/lang_tools.py +31 -4
- jaclang/utils/tests/test_lang_tools.py +1 -1
- jaclang/utils/treeprinter.py +8 -3
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/RECORD +96 -66
- 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/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.9.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
- {jaclang-0.8.9.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
|
|
|
@@ -88,37 +88,17 @@ UNARY_OP_MAP: dict[Tok, type[ast3.unaryop]] = {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
class PyastGenPass(
|
|
91
|
+
class PyastGenPass(BaseAstGenPass[ast3.AST]):
|
|
92
92
|
"""Jac blue transpilation to python pass."""
|
|
93
93
|
|
|
94
|
-
# Builtins that should be imported from jaclang.runtimelib.builtin
|
|
95
|
-
KNOWN_BUILTINS = {
|
|
96
|
-
"abstractmethod",
|
|
97
|
-
"ClassVar",
|
|
98
|
-
"override",
|
|
99
|
-
"printgraph",
|
|
100
|
-
"jid",
|
|
101
|
-
"jobj",
|
|
102
|
-
"grant",
|
|
103
|
-
"revoke",
|
|
104
|
-
"allroots",
|
|
105
|
-
"save",
|
|
106
|
-
"commit",
|
|
107
|
-
"NoPerm",
|
|
108
|
-
"ReadPerm",
|
|
109
|
-
"ConnectPerm",
|
|
110
|
-
"WritePerm",
|
|
111
|
-
}
|
|
112
|
-
|
|
113
94
|
def before_pass(self) -> None:
|
|
114
|
-
self.child_passes: list[PyastGenPass] =
|
|
115
|
-
for i in self.ir_in.impl_mod + self.ir_in.test_mod:
|
|
116
|
-
child_pass = PyastGenPass(ir_in=i, prog=self.prog)
|
|
117
|
-
self.child_passes.append(child_pass)
|
|
95
|
+
self.child_passes: list[PyastGenPass] = self._init_child_passes(PyastGenPass)
|
|
118
96
|
self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
|
|
119
97
|
self.already_added: list[str] = []
|
|
120
98
|
self.jaclib_imports: set[str] = set() # Track individual jaclib imports
|
|
121
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] = []
|
|
122
102
|
self.preamble: list[ast3.AST] = [
|
|
123
103
|
self.sync(
|
|
124
104
|
ast3.ImportFrom(
|
|
@@ -129,9 +109,16 @@ class PyastGenPass(UniPass):
|
|
|
129
109
|
jac_node=self.ir_out,
|
|
130
110
|
),
|
|
131
111
|
]
|
|
112
|
+
self.jsx_processor = PyJsxProcessor(self)
|
|
132
113
|
|
|
133
114
|
def enter_node(self, node: uni.UniNode) -> None:
|
|
134
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
|
|
135
122
|
if node.gen.py_ast:
|
|
136
123
|
self.prune()
|
|
137
124
|
return
|
|
@@ -139,30 +126,17 @@ class PyastGenPass(UniPass):
|
|
|
139
126
|
|
|
140
127
|
def exit_node(self, node: uni.UniNode) -> None:
|
|
141
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
|
|
142
134
|
super().exit_node(node)
|
|
143
|
-
# for i in node.gen.py_ast: # Internal validation
|
|
144
|
-
# self.node_compilable_test(i)
|
|
145
|
-
|
|
146
|
-
# TODO: USE THIS TO SYNC
|
|
147
|
-
# if isinstance(i, ast3.AST):
|
|
148
|
-
# i.jac_link = node
|
|
149
135
|
|
|
150
|
-
def jaclib_obj(self, obj_name: str) -> ast3.Name
|
|
136
|
+
def jaclib_obj(self, obj_name: str) -> ast3.Name:
|
|
151
137
|
"""Return the object from jaclib as ast node based on the import config."""
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return self.sync(ast3.Name(id=obj_name, ctx=ast3.Load()))
|
|
155
|
-
else:
|
|
156
|
-
self.needs_jaclib()
|
|
157
|
-
return self.sync(
|
|
158
|
-
ast3.Attribute(
|
|
159
|
-
value=self.sync(
|
|
160
|
-
ast3.Name(id=settings.pyout_jaclib_alias, ctx=ast3.Load())
|
|
161
|
-
),
|
|
162
|
-
attr=obj_name,
|
|
163
|
-
ctx=ast3.Load(),
|
|
164
|
-
)
|
|
165
|
-
)
|
|
138
|
+
self.jaclib_imports.add(obj_name)
|
|
139
|
+
return self.sync(ast3.Name(id=obj_name, ctx=ast3.Load()))
|
|
166
140
|
|
|
167
141
|
def builtin_name(self, name: str) -> ast3.Name:
|
|
168
142
|
"""Return a builtin name and track it for importing.
|
|
@@ -216,22 +190,31 @@ class PyastGenPass(UniPass):
|
|
|
216
190
|
),
|
|
217
191
|
)
|
|
218
192
|
|
|
219
|
-
def
|
|
220
|
-
"""
|
|
221
|
-
self.
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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,
|
|
235
218
|
)
|
|
236
219
|
|
|
237
220
|
def _get_sem_decorator(self, node: uni.UniNode) -> ast3.Call | None:
|
|
@@ -324,15 +307,9 @@ class PyastGenPass(UniPass):
|
|
|
324
307
|
)
|
|
325
308
|
)
|
|
326
309
|
|
|
327
|
-
def
|
|
328
|
-
"""
|
|
329
|
-
|
|
330
|
-
for item in body:
|
|
331
|
-
if isinstance(item, list):
|
|
332
|
-
new_body.extend(item)
|
|
333
|
-
elif item is not None:
|
|
334
|
-
new_body.append(item)
|
|
335
|
-
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
|
|
336
313
|
|
|
337
314
|
def sync(
|
|
338
315
|
self, py_node: T, jac_node: Optional[uni.UniNode] = None, deep: bool = False
|
|
@@ -389,7 +366,7 @@ class PyastGenPass(UniPass):
|
|
|
389
366
|
[self.sync(ast3.Pass())]
|
|
390
367
|
if isinstance(node, Sequence) and not valid_stmts
|
|
391
368
|
else (
|
|
392
|
-
self.
|
|
369
|
+
self._flatten_ast_list(
|
|
393
370
|
[
|
|
394
371
|
x.gen.py_ast
|
|
395
372
|
for x in valid_stmts
|
|
@@ -433,14 +410,9 @@ class PyastGenPass(UniPass):
|
|
|
433
410
|
node.gen.py_ast = node.tag.gen.py_ast
|
|
434
411
|
|
|
435
412
|
def exit_module(self, node: uni.Module) -> None:
|
|
436
|
-
#
|
|
413
|
+
# Merge jaclib and builtin imports from child passes
|
|
437
414
|
for child_pass in self.child_passes:
|
|
438
|
-
|
|
439
|
-
self.needs_jaclib()
|
|
440
|
-
break
|
|
441
|
-
# Merge jaclib and builtin imports from child passes
|
|
442
|
-
if settings.library_mode:
|
|
443
|
-
self.jaclib_imports.update(child_pass.jaclib_imports)
|
|
415
|
+
self.jaclib_imports.update(child_pass.jaclib_imports)
|
|
444
416
|
self.builtin_imports.update(child_pass.builtin_imports)
|
|
445
417
|
|
|
446
418
|
# Add builtin imports if any were used
|
|
@@ -459,8 +431,8 @@ class PyastGenPass(UniPass):
|
|
|
459
431
|
)
|
|
460
432
|
)
|
|
461
433
|
|
|
462
|
-
# Add library
|
|
463
|
-
if
|
|
434
|
+
# Add library imports at the end of preamble
|
|
435
|
+
if self.jaclib_imports:
|
|
464
436
|
self.preamble.append(
|
|
465
437
|
self.sync(
|
|
466
438
|
ast3.ImportFrom(
|
|
@@ -475,31 +447,18 @@ class PyastGenPass(UniPass):
|
|
|
475
447
|
)
|
|
476
448
|
)
|
|
477
449
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
for
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
),
|
|
491
|
-
*self.preamble,
|
|
492
|
-
*[x.gen.py_ast for x in pre_body],
|
|
493
|
-
]
|
|
494
|
-
if node.doc
|
|
495
|
-
else [*self.preamble, *[x.gen.py_ast for x in pre_body]]
|
|
496
|
-
)
|
|
497
|
-
new_body = []
|
|
498
|
-
for i in body:
|
|
499
|
-
if isinstance(i, list):
|
|
500
|
-
new_body += i
|
|
501
|
-
else:
|
|
502
|
-
new_body.append(i) if i else None
|
|
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)
|
|
503
462
|
node.gen.py_ast = [
|
|
504
463
|
self.sync(
|
|
505
464
|
ast3.Module(
|
|
@@ -516,7 +475,7 @@ class PyastGenPass(UniPass):
|
|
|
516
475
|
ast3.Expr(value=cast(ast3.expr, node.doc.gen.py_ast[0])),
|
|
517
476
|
jac_node=node.doc,
|
|
518
477
|
)
|
|
519
|
-
assigns_ast: list[ast3.AST] = self.
|
|
478
|
+
assigns_ast: list[ast3.AST] = self._flatten_ast_list(
|
|
520
479
|
[a.gen.py_ast for a in node.assignments]
|
|
521
480
|
)
|
|
522
481
|
if isinstance(doc, ast3.AST):
|
|
@@ -524,7 +483,9 @@ class PyastGenPass(UniPass):
|
|
|
524
483
|
else:
|
|
525
484
|
raise self.ice()
|
|
526
485
|
else:
|
|
527
|
-
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
|
+
)
|
|
528
489
|
|
|
529
490
|
def exit_test(self, node: uni.Test) -> None:
|
|
530
491
|
test_name = node.name.sym_name
|
|
@@ -745,18 +706,17 @@ class PyastGenPass(UniPass):
|
|
|
745
706
|
if node.arch_type.name != Tok.KW_CLASS:
|
|
746
707
|
base_classes.append(self.jaclib_obj(node.arch_type.value.capitalize()))
|
|
747
708
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
type_params=[],
|
|
757
|
-
)
|
|
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=[],
|
|
758
717
|
)
|
|
759
|
-
|
|
718
|
+
)
|
|
719
|
+
node.gen.py_ast = [class_def]
|
|
760
720
|
|
|
761
721
|
def enter_enum(self, node: uni.Enum) -> None:
|
|
762
722
|
if isinstance(node.body, uni.ImplDef):
|
|
@@ -781,18 +741,17 @@ class PyastGenPass(UniPass):
|
|
|
781
741
|
|
|
782
742
|
base_classes = [cast(ast3.expr, i.gen.py_ast[0]) for i in node.base_classes]
|
|
783
743
|
base_classes.append(self.builtin_name("Enum"))
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
type_params=[],
|
|
793
|
-
)
|
|
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=[],
|
|
794
752
|
)
|
|
795
|
-
|
|
753
|
+
)
|
|
754
|
+
node.gen.py_ast = [class_def]
|
|
796
755
|
|
|
797
756
|
def enter_ability(self, node: uni.Ability) -> None:
|
|
798
757
|
if isinstance(node.body, uni.ImplDef):
|
|
@@ -1006,36 +965,35 @@ class PyastGenPass(UniPass):
|
|
|
1006
965
|
if isinstance(node.signature, uni.FuncSignature) and node.signature.return_type:
|
|
1007
966
|
ast_returns = cast(ast3.expr, node.signature.return_type.gen.py_ast[0])
|
|
1008
967
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
defaults=[],
|
|
1029
|
-
)
|
|
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=[],
|
|
1030
987
|
)
|
|
1031
|
-
)
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
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=[],
|
|
1037
994
|
)
|
|
1038
|
-
|
|
995
|
+
)
|
|
996
|
+
node.gen.py_ast = [func_def]
|
|
1039
997
|
|
|
1040
998
|
def exit_impl_def(self, node: uni.ImplDef) -> None:
|
|
1041
999
|
pass
|
|
@@ -1155,7 +1113,9 @@ class PyastGenPass(UniPass):
|
|
|
1155
1113
|
]
|
|
1156
1114
|
|
|
1157
1115
|
def exit_arch_has(self, node: uni.ArchHas) -> None:
|
|
1158
|
-
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
|
+
)
|
|
1159
1119
|
if node.doc:
|
|
1160
1120
|
doc = self.sync(
|
|
1161
1121
|
ast3.Expr(value=cast(ast3.expr, node.doc.gen.py_ast[0])),
|
|
@@ -1324,19 +1284,24 @@ class PyastGenPass(UniPass):
|
|
|
1324
1284
|
node.gen.py_ast = self.resolve_stmt_block(node.body)
|
|
1325
1285
|
|
|
1326
1286
|
def exit_expr_stmt(self, node: uni.ExprStmt) -> None:
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
)
|
|
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,
|
|
1337
1299
|
)
|
|
1338
1300
|
)
|
|
1339
|
-
|
|
1301
|
+
)
|
|
1302
|
+
|
|
1303
|
+
# Emit hoisted functions before the expression statement
|
|
1304
|
+
node.gen.py_ast = [*hoisted, expr_stmt]
|
|
1340
1305
|
|
|
1341
1306
|
def exit_concurrent_expr(self, node: uni.ConcurrentExpr) -> None:
|
|
1342
1307
|
func = ""
|
|
@@ -1773,7 +1738,7 @@ class PyastGenPass(UniPass):
|
|
|
1773
1738
|
value=self.sync(
|
|
1774
1739
|
self.sync(
|
|
1775
1740
|
ast3.Call(
|
|
1776
|
-
func=self.jaclib_obj("
|
|
1741
|
+
func=self.jaclib_obj("log_report"),
|
|
1777
1742
|
args=cast(list[ast3.expr], node.expr.gen.py_ast),
|
|
1778
1743
|
keywords=[],
|
|
1779
1744
|
)
|
|
@@ -1930,48 +1895,49 @@ class PyastGenPass(UniPass):
|
|
|
1930
1895
|
)
|
|
1931
1896
|
targets_ast = [cast(ast3.expr, t.gen.py_ast[0]) for t in node.target]
|
|
1932
1897
|
|
|
1898
|
+
# Collect any hoisted functions that were generated during expression evaluation
|
|
1899
|
+
hoisted = self._hoisted_funcs[:]
|
|
1900
|
+
self._hoisted_funcs.clear()
|
|
1901
|
+
|
|
1933
1902
|
if node.type_tag:
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
ast3.
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
value
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
simple=int(isinstance(targets_ast[0], ast3.Name)),
|
|
1945
|
-
)
|
|
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)),
|
|
1946
1913
|
)
|
|
1947
|
-
|
|
1914
|
+
)
|
|
1948
1915
|
elif node.aug_op:
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
ast3.
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
value
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
),
|
|
1959
|
-
)
|
|
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
|
+
),
|
|
1960
1925
|
)
|
|
1961
|
-
|
|
1926
|
+
)
|
|
1962
1927
|
else:
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
ast3.
|
|
1966
|
-
|
|
1967
|
-
value
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
),
|
|
1972
|
-
)
|
|
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
|
+
),
|
|
1973
1936
|
)
|
|
1974
|
-
|
|
1937
|
+
)
|
|
1938
|
+
|
|
1939
|
+
# Emit hoisted functions before the assignment
|
|
1940
|
+
node.gen.py_ast = [*hoisted, assignment_stmt]
|
|
1975
1941
|
|
|
1976
1942
|
def exit_binary_expr(self, node: uni.BinaryExpr) -> None:
|
|
1977
1943
|
if isinstance(node.op, uni.ConnectOp):
|
|
@@ -2199,28 +2165,80 @@ class PyastGenPass(UniPass):
|
|
|
2199
2165
|
]
|
|
2200
2166
|
|
|
2201
2167
|
def exit_lambda_expr(self, node: uni.LambdaExpr) -> None:
|
|
2202
|
-
#
|
|
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.
|
|
2203
2219
|
if node.signature:
|
|
2204
2220
|
self._remove_lambda_param_annotations(node.signature)
|
|
2205
|
-
|
|
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])
|
|
2206
2235
|
node.gen.py_ast = [
|
|
2207
2236
|
self.sync(
|
|
2208
2237
|
ast3.Lambda(
|
|
2209
|
-
args=
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
ast3.arguments(
|
|
2214
|
-
posonlyargs=[],
|
|
2215
|
-
args=[],
|
|
2216
|
-
kwonlyargs=[],
|
|
2217
|
-
kw_defaults=[],
|
|
2218
|
-
defaults=[],
|
|
2219
|
-
)
|
|
2220
|
-
)
|
|
2221
|
-
),
|
|
2222
|
-
body=cast(ast3.expr, node.body.gen.py_ast[0]),
|
|
2223
|
-
)
|
|
2238
|
+
args=arguments,
|
|
2239
|
+
body=body_expr,
|
|
2240
|
+
),
|
|
2241
|
+
jac_node=node,
|
|
2224
2242
|
)
|
|
2225
2243
|
]
|
|
2226
2244
|
|
|
@@ -2304,9 +2322,8 @@ class PyastGenPass(UniPass):
|
|
|
2304
2322
|
for i in str_seq:
|
|
2305
2323
|
if isinstance(i, uni.String):
|
|
2306
2324
|
pieces.append(i.lit_value)
|
|
2307
|
-
elif isinstance(i, uni.FString):
|
|
2308
|
-
pieces.extend(get_pieces(i.parts)) if i.parts else None
|
|
2309
|
-
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
|
|
2310
2327
|
pieces.append(i.gen.py_ast[0])
|
|
2311
2328
|
elif isinstance(i, uni.Token) and i.name in [Tok.LBRACE, Tok.RBRACE]:
|
|
2312
2329
|
continue
|
|
@@ -2346,11 +2363,32 @@ class PyastGenPass(UniPass):
|
|
|
2346
2363
|
node.gen.py_ast = [combined_multi[0]]
|
|
2347
2364
|
|
|
2348
2365
|
def exit_f_string(self, node: uni.FString) -> None:
|
|
2349
|
-
|
|
2350
|
-
|
|
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
|
+
)
|
|
2351
2391
|
]
|
|
2352
|
-
parts = self.flatten(cast(list[list[ast3.AST] | ast3.AST | None], py_parts))
|
|
2353
|
-
node.gen.py_ast = parts if parts else [self.sync(ast3.Constant(value=""))]
|
|
2354
2392
|
|
|
2355
2393
|
def exit_list_val(self, node: uni.ListVal) -> None:
|
|
2356
2394
|
elts = [cast(ast3.expr, v.gen.py_ast[0]) for v in node.values]
|
|
@@ -2566,6 +2604,24 @@ class PyastGenPass(UniPass):
|
|
|
2566
2604
|
]
|
|
2567
2605
|
|
|
2568
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
|
|
2569
2625
|
node.gen.py_ast = node.value.gen.py_ast
|
|
2570
2626
|
|
|
2571
2627
|
def gen_call_args(
|
|
@@ -2714,7 +2770,7 @@ class PyastGenPass(UniPass):
|
|
|
2714
2770
|
|
|
2715
2771
|
pynode = self.sync(
|
|
2716
2772
|
ast3.Call(
|
|
2717
|
-
func=self.jaclib_obj("
|
|
2773
|
+
func=self.jaclib_obj("OPath"),
|
|
2718
2774
|
args=[cast(ast3.expr, origin or cur.gen.py_ast[0])],
|
|
2719
2775
|
keywords=[],
|
|
2720
2776
|
)
|
|
@@ -3092,7 +3148,9 @@ class PyastGenPass(UniPass):
|
|
|
3092
3148
|
def exit_name(self, node: uni.Name) -> None:
|
|
3093
3149
|
name = node.sym_name
|
|
3094
3150
|
# Track if this name is a known builtin
|
|
3095
|
-
|
|
3151
|
+
import jaclang.runtimelib.builtin
|
|
3152
|
+
|
|
3153
|
+
if name in set(jaclang.runtimelib.builtin.__all__):
|
|
3096
3154
|
self.builtin_imports.add(name)
|
|
3097
3155
|
node.gen.py_ast = [self.sync(ast3.Name(id=name, ctx=node.py_ctx_func()))]
|
|
3098
3156
|
|
|
@@ -3119,6 +3177,38 @@ class PyastGenPass(UniPass):
|
|
|
3119
3177
|
def exit_ellipsis(self, node: uni.Ellipsis) -> None:
|
|
3120
3178
|
node.gen.py_ast = [self.sync(ast3.Constant(value=...))]
|
|
3121
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
|
+
|
|
3122
3212
|
def exit_semi(self, node: uni.Semi) -> None:
|
|
3123
3213
|
pass
|
|
3124
3214
|
|