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.

Files changed (114) hide show
  1. jaclang/cli/cli.py +194 -10
  2. jaclang/cli/cmdreg.py +144 -8
  3. jaclang/compiler/__init__.py +6 -1
  4. jaclang/compiler/codeinfo.py +16 -1
  5. jaclang/compiler/constant.py +33 -8
  6. jaclang/compiler/jac.lark +154 -62
  7. jaclang/compiler/larkparse/jac_parser.py +2 -2
  8. jaclang/compiler/parser.py +656 -149
  9. jaclang/compiler/passes/__init__.py +2 -1
  10. jaclang/compiler/passes/ast_gen/__init__.py +5 -0
  11. jaclang/compiler/passes/ast_gen/base_ast_gen_pass.py +54 -0
  12. jaclang/compiler/passes/ast_gen/jsx_processor.py +344 -0
  13. jaclang/compiler/passes/ecmascript/__init__.py +25 -0
  14. jaclang/compiler/passes/ecmascript/es_unparse.py +576 -0
  15. jaclang/compiler/passes/ecmascript/esast_gen_pass.py +2068 -0
  16. jaclang/compiler/passes/ecmascript/estree.py +972 -0
  17. jaclang/compiler/passes/ecmascript/tests/__init__.py +1 -0
  18. jaclang/compiler/passes/ecmascript/tests/fixtures/advanced_language_features.jac +170 -0
  19. jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.impl.jac +30 -0
  20. jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.jac +14 -0
  21. jaclang/compiler/passes/ecmascript/tests/fixtures/client_jsx.jac +89 -0
  22. jaclang/compiler/passes/ecmascript/tests/fixtures/core_language_features.jac +195 -0
  23. jaclang/compiler/passes/ecmascript/tests/test_esast_gen_pass.py +167 -0
  24. jaclang/compiler/passes/ecmascript/tests/test_js_generation.py +239 -0
  25. jaclang/compiler/passes/main/__init__.py +0 -3
  26. jaclang/compiler/passes/main/annex_pass.py +23 -1
  27. jaclang/compiler/passes/main/def_use_pass.py +1 -0
  28. jaclang/compiler/passes/main/pyast_gen_pass.py +413 -255
  29. jaclang/compiler/passes/main/pyast_load_pass.py +48 -11
  30. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +2 -0
  31. jaclang/compiler/passes/main/sym_tab_build_pass.py +18 -1
  32. jaclang/compiler/passes/main/tests/fixtures/autoimpl.cl.jac +7 -0
  33. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +3 -0
  34. jaclang/compiler/passes/main/tests/fixtures/checker_class_construct.jac +33 -0
  35. jaclang/compiler/passes/main/tests/fixtures/defuse_modpath.jac +7 -0
  36. jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +2 -1
  37. jaclang/compiler/passes/main/tests/test_checker_pass.py +31 -3
  38. jaclang/compiler/passes/main/tests/test_def_use_pass.py +12 -0
  39. jaclang/compiler/passes/main/tests/test_import_pass.py +23 -4
  40. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +13 -14
  41. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +25 -0
  42. jaclang/compiler/passes/main/type_checker_pass.py +7 -0
  43. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +219 -20
  44. jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
  45. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
  46. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
  47. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +135 -29
  48. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -1
  49. jaclang/compiler/passes/transform.py +9 -1
  50. jaclang/compiler/passes/uni_pass.py +5 -7
  51. jaclang/compiler/program.py +27 -26
  52. jaclang/compiler/tests/test_client_codegen.py +113 -0
  53. jaclang/compiler/tests/test_importer.py +12 -10
  54. jaclang/compiler/tests/test_parser.py +249 -3
  55. jaclang/compiler/type_system/type_evaluator.jac +1078 -0
  56. jaclang/compiler/type_system/type_utils.py +1 -1
  57. jaclang/compiler/type_system/types.py +6 -0
  58. jaclang/compiler/unitree.py +438 -82
  59. jaclang/langserve/engine.jac +224 -288
  60. jaclang/langserve/sem_manager.jac +12 -8
  61. jaclang/langserve/server.jac +48 -48
  62. jaclang/langserve/tests/fixtures/greet.py +17 -0
  63. jaclang/langserve/tests/fixtures/md_path.jac +22 -0
  64. jaclang/langserve/tests/fixtures/user.jac +15 -0
  65. jaclang/langserve/tests/test_server.py +66 -371
  66. jaclang/lib.py +17 -0
  67. jaclang/runtimelib/archetype.py +25 -25
  68. jaclang/runtimelib/client_bundle.py +169 -0
  69. jaclang/runtimelib/client_runtime.jac +586 -0
  70. jaclang/runtimelib/constructs.py +4 -2
  71. jaclang/runtimelib/machine.py +308 -139
  72. jaclang/runtimelib/meta_importer.py +111 -22
  73. jaclang/runtimelib/mtp.py +15 -0
  74. jaclang/runtimelib/server.py +1089 -0
  75. jaclang/runtimelib/tests/fixtures/client_app.jac +18 -0
  76. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  77. jaclang/runtimelib/tests/fixtures/savable_object.jac +4 -5
  78. jaclang/runtimelib/tests/fixtures/serve_api.jac +75 -0
  79. jaclang/runtimelib/tests/test_client_bundle.py +55 -0
  80. jaclang/runtimelib/tests/test_client_render.py +63 -0
  81. jaclang/runtimelib/tests/test_serve.py +1069 -0
  82. jaclang/settings.py +0 -3
  83. jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
  84. jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
  85. jaclang/tests/fixtures/funccall_genexpr.py +5 -0
  86. jaclang/tests/fixtures/iife_functions.jac +142 -0
  87. jaclang/tests/fixtures/iife_functions_client.jac +143 -0
  88. jaclang/tests/fixtures/multistatement_lambda.jac +116 -0
  89. jaclang/tests/fixtures/multistatement_lambda_client.jac +113 -0
  90. jaclang/tests/fixtures/needs_import_dup.jac +6 -4
  91. jaclang/tests/fixtures/py2jac_empty.py +0 -0
  92. jaclang/tests/fixtures/py_run.py +7 -5
  93. jaclang/tests/fixtures/pyfunc_fstr.py +2 -2
  94. jaclang/tests/fixtures/simple_lambda_test.jac +12 -0
  95. jaclang/tests/test_cli.py +134 -18
  96. jaclang/tests/test_language.py +120 -32
  97. jaclang/tests/test_reference.py +20 -3
  98. jaclang/utils/NonGPT.py +375 -0
  99. jaclang/utils/helpers.py +64 -20
  100. jaclang/utils/lang_tools.py +31 -4
  101. jaclang/utils/tests/test_lang_tools.py +5 -16
  102. jaclang/utils/treeprinter.py +8 -3
  103. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
  104. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/RECORD +106 -71
  105. jaclang/compiler/passes/main/binder_pass.py +0 -594
  106. jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +0 -47
  107. jaclang/compiler/passes/main/tests/test_binder_pass.py +0 -111
  108. jaclang/compiler/type_system/type_evaluator.py +0 -844
  109. jaclang/langserve/tests/session.jac +0 -294
  110. jaclang/langserve/tests/test_dev_server.py +0 -80
  111. jaclang/runtimelib/importer.py +0 -351
  112. jaclang/tests/test_typecheck.py +0 -542
  113. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
  114. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  """Passes for Jac."""
2
2
 
3
+ from .ast_gen import BaseAstGenPass
3
4
  from .uni_pass import Transform, UniPass
4
5
 
5
- __all__ = ["Transform", "UniPass"]
6
+ __all__ = ["Transform", "UniPass", "BaseAstGenPass"]
@@ -0,0 +1,5 @@
1
+ """Common helpers for AST generation passes."""
2
+
3
+ from .base_ast_gen_pass import BaseAstGenPass
4
+
5
+ __all__ = ["BaseAstGenPass"]
@@ -0,0 +1,54 @@
1
+ """Shared helpers for AST generation passes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Generic, Optional, Sequence, TypeVar
6
+
7
+ import jaclang.compiler.unitree as uni
8
+ from jaclang.compiler.passes.uni_pass import UniPass
9
+
10
+ T = TypeVar("T")
11
+ ChildPassT = TypeVar("ChildPassT", bound="BaseAstGenPass[Any]")
12
+
13
+
14
+ class BaseAstGenPass(UniPass, Generic[T]):
15
+ """Common functionality shared across AST generation passes."""
16
+
17
+ def _get_body_inner(
18
+ self, node: uni.Archetype | uni.Enum | uni.Ability
19
+ ) -> Optional[Sequence[uni.UniNode]]:
20
+ """Return the list of body statements regardless of ImplDef wrapping."""
21
+ body = getattr(node, "body", None)
22
+ if isinstance(body, uni.ImplDef) and isinstance(body.body, list):
23
+ return body.body
24
+ if isinstance(body, list):
25
+ return body
26
+ return None
27
+
28
+ def _merge_module_bodies(self, node: uni.Module) -> list[uni.UniNode]:
29
+ """Concatenate impl/test bodies with the main module body."""
30
+ clean_body = [item for item in node.body if not isinstance(item, uni.ImplDef)]
31
+ merged: list[uni.UniNode] = []
32
+ for mod in node.impl_mod:
33
+ merged.extend(mod.body)
34
+ merged.extend(clean_body)
35
+ for mod in node.test_mod:
36
+ merged.extend(mod.body)
37
+ return merged
38
+
39
+ def _init_child_passes(self, pass_class: type[ChildPassT]) -> list[ChildPassT]:
40
+ """Instantiate child passes for impl and test modules."""
41
+ return [
42
+ pass_class(ir_in=sub_module, prog=self.prog)
43
+ for sub_module in self.ir_in.impl_mod + self.ir_in.test_mod
44
+ ]
45
+
46
+ def _flatten_ast_list(self, items: list[T | list[T] | None]) -> list[T]:
47
+ """Flatten nested AST lists while skipping ``None`` entries."""
48
+ flattened: list[T] = []
49
+ for item in items:
50
+ if isinstance(item, list):
51
+ flattened.extend(item)
52
+ elif item is not None:
53
+ flattened.append(item)
54
+ return flattened
@@ -0,0 +1,344 @@
1
+ """Helpers for generating target-specific JSX AST nodes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ast as ast3
6
+ from typing import Optional, TYPE_CHECKING, Union, cast
7
+
8
+ import jaclang.compiler.unitree as uni
9
+
10
+ if TYPE_CHECKING:
11
+ from jaclang.compiler.passes.ecmascript.esast_gen_pass import EsastGenPass
12
+ from jaclang.compiler.passes.ecmascript.estree import (
13
+ Expression,
14
+ Property,
15
+ SpreadElement,
16
+ )
17
+ from jaclang.compiler.passes.main.pyast_gen_pass import PyastGenPass
18
+
19
+
20
+ class EsJsxProcessor:
21
+ """Generate ESTree structures for JSX nodes."""
22
+
23
+ def __init__(self, pass_ref: "EsastGenPass") -> None:
24
+ self.pass_ref = pass_ref
25
+ # Import estree at runtime to access AST node classes
26
+ from jaclang.compiler.passes.ecmascript import estree as es
27
+
28
+ self.es = es
29
+
30
+ def element(self, node: uni.JsxElement) -> "Expression":
31
+ """Process JSX element into __jacJsx(tag, props, children) call."""
32
+ es = self.es
33
+ if node.is_fragment or not node.name:
34
+ tag_expr: Expression = self.pass_ref.sync_loc(
35
+ es.Literal(value=None), jac_node=node
36
+ )
37
+ else:
38
+ tag_expr = (
39
+ node.name.gen.es_ast
40
+ if node.name.gen.es_ast
41
+ else self.pass_ref.sync_loc(es.Literal(value=None), jac_node=node.name)
42
+ )
43
+
44
+ attributes = node.attributes or []
45
+ has_spread = any(
46
+ isinstance(attr, uni.JsxSpreadAttribute) for attr in attributes
47
+ )
48
+ if not attributes:
49
+ props_expr: Expression = self.pass_ref.sync_loc(
50
+ es.ObjectExpression(properties=[]), jac_node=node
51
+ )
52
+ elif has_spread:
53
+ segments: list[Expression] = []
54
+ for attr in attributes:
55
+ if isinstance(attr, uni.JsxSpreadAttribute):
56
+ exp = getattr(attr.gen, "es_ast", None)
57
+ if isinstance(exp, es.Expression):
58
+ segments.append(exp)
59
+ elif isinstance(attr, uni.JsxNormalAttribute):
60
+ prop = getattr(attr.gen, "es_ast", None)
61
+ if isinstance(prop, es.Property):
62
+ segments.append(
63
+ self.pass_ref.sync_loc(
64
+ es.ObjectExpression(properties=[prop]), jac_node=attr
65
+ )
66
+ )
67
+ if segments:
68
+ assign_member = self.pass_ref.sync_loc(
69
+ es.MemberExpression(
70
+ object=self.pass_ref.sync_loc(
71
+ es.Identifier(name="Object"), jac_node=node
72
+ ),
73
+ property=self.pass_ref.sync_loc(
74
+ es.Identifier(name="assign"), jac_node=node
75
+ ),
76
+ computed=False,
77
+ optional=False,
78
+ ),
79
+ jac_node=node,
80
+ )
81
+ props_expr = self.pass_ref.sync_loc(
82
+ es.CallExpression(
83
+ callee=assign_member,
84
+ arguments=[
85
+ self.pass_ref.sync_loc(
86
+ es.ObjectExpression(properties=[]), jac_node=node
87
+ ),
88
+ *segments,
89
+ ],
90
+ ),
91
+ jac_node=node,
92
+ )
93
+ else:
94
+ props_expr = self.pass_ref.sync_loc(
95
+ es.ObjectExpression(properties=[]), jac_node=node
96
+ )
97
+ else:
98
+ properties: list[Property] = []
99
+ for attr in attributes:
100
+ prop = getattr(attr.gen, "es_ast", None)
101
+ if isinstance(prop, es.Property):
102
+ properties.append(prop)
103
+ props_expr = self.pass_ref.sync_loc(
104
+ es.ObjectExpression(properties=properties), jac_node=node
105
+ )
106
+
107
+ children_elements: list[Optional[Union[Expression, SpreadElement]]] = []
108
+ for child in node.children or []:
109
+ child_expr = getattr(child.gen, "es_ast", None)
110
+ if child_expr is None:
111
+ continue
112
+ if isinstance(child_expr, list):
113
+ children_elements.extend(child_expr) # type: ignore[arg-type]
114
+ else:
115
+ children_elements.append(child_expr)
116
+ children_expr = self.pass_ref.sync_loc(
117
+ es.ArrayExpression(elements=children_elements), jac_node=node
118
+ )
119
+
120
+ call_expr = self.pass_ref.sync_loc(
121
+ es.CallExpression(
122
+ callee=self.pass_ref.sync_loc(
123
+ es.Identifier(name="__jacJsx"), jac_node=node
124
+ ),
125
+ arguments=[tag_expr, props_expr, children_expr],
126
+ ),
127
+ jac_node=node,
128
+ )
129
+ return call_expr
130
+
131
+ def element_name(self, node: uni.JsxElementName) -> "Expression":
132
+ """Process JSX element name."""
133
+ es = self.es
134
+ if not node.parts:
135
+ expr = self.pass_ref.sync_loc(es.Literal(value=None), jac_node=node)
136
+ else:
137
+ parts = [part.value for part in node.parts]
138
+ first = parts[0]
139
+ if first and first[0].isupper():
140
+ expr = self.pass_ref.sync_loc(
141
+ es.Identifier(name=first), jac_node=node.parts[0]
142
+ )
143
+ for idx, part in enumerate(parts[1:], start=1):
144
+ expr = self.pass_ref.sync_loc(
145
+ es.MemberExpression(
146
+ object=expr,
147
+ property=self.pass_ref.sync_loc(
148
+ es.Identifier(name=part), jac_node=node.parts[idx]
149
+ ),
150
+ computed=False,
151
+ optional=False,
152
+ ),
153
+ jac_node=node,
154
+ )
155
+ else:
156
+ expr = self.pass_ref.sync_loc(
157
+ es.Literal(value=".".join(parts)), jac_node=node
158
+ )
159
+ node.gen.es_ast = expr
160
+ return expr
161
+
162
+ def spread_attribute(self, node: uni.JsxSpreadAttribute) -> "Expression":
163
+ """Process JSX spread attribute."""
164
+ es = self.es
165
+ expr = (
166
+ node.expr.gen.es_ast
167
+ if node.expr and node.expr.gen.es_ast
168
+ else self.pass_ref.sync_loc(
169
+ es.ObjectExpression(properties=[]), jac_node=node
170
+ )
171
+ )
172
+ node.gen.es_ast = expr
173
+ return expr
174
+
175
+ def normal_attribute(self, node: uni.JsxNormalAttribute) -> "Property":
176
+ """Process JSX normal attribute."""
177
+ es = self.es
178
+ key_expr = self.pass_ref.sync_loc(
179
+ es.Literal(value=node.name.value), jac_node=node.name
180
+ )
181
+ if node.value is None:
182
+ value_expr = self.pass_ref.sync_loc(es.Literal(value=True), jac_node=node)
183
+ elif isinstance(node.value, uni.String):
184
+ value_expr = self.pass_ref.sync_loc(
185
+ es.Literal(value=node.value.lit_value), jac_node=node.value
186
+ )
187
+ else:
188
+ value_expr = (
189
+ node.value.gen.es_ast
190
+ if node.value.gen.es_ast
191
+ else self.pass_ref.sync_loc(es.Literal(value=None), jac_node=node.value)
192
+ )
193
+
194
+ prop = self.pass_ref.sync_loc(
195
+ es.Property(
196
+ key=key_expr,
197
+ value=value_expr,
198
+ kind="init",
199
+ method=False,
200
+ shorthand=False,
201
+ computed=False,
202
+ ),
203
+ jac_node=node,
204
+ )
205
+ node.gen.es_ast = prop
206
+ return prop
207
+
208
+ def text(self, node: uni.JsxText) -> "Expression":
209
+ """Process JSX text node."""
210
+ es = self.es
211
+ raw_value = node.value.value if hasattr(node.value, "value") else node.value
212
+ expr = self.pass_ref.sync_loc(es.Literal(value=str(raw_value)), jac_node=node)
213
+ node.gen.es_ast = expr
214
+ return expr
215
+
216
+ def expression(self, node: uni.JsxExpression) -> "Expression":
217
+ """Process JSX expression child."""
218
+ es = self.es
219
+ expr = (
220
+ node.expr.gen.es_ast
221
+ if node.expr and node.expr.gen.es_ast
222
+ else self.pass_ref.sync_loc(es.Literal(value=None), jac_node=node.expr)
223
+ )
224
+ node.gen.es_ast = expr
225
+ return expr
226
+
227
+
228
+ class PyJsxProcessor:
229
+ """Generate Python AST structures for JSX nodes."""
230
+
231
+ def __init__(self, pass_ref: "PyastGenPass") -> None:
232
+ self.pass_ref = pass_ref
233
+
234
+ def element(self, node: uni.JsxElement) -> list[ast3.AST]:
235
+ """Generate Python AST for JSX elements."""
236
+ if node.is_fragment or not node.name:
237
+ tag_arg: ast3.expr = self.pass_ref.sync(ast3.Constant(value=None), node)
238
+ else:
239
+ tag_arg = cast(ast3.expr, node.name.gen.py_ast[0])
240
+
241
+ if not node.attributes:
242
+ attrs_expr = self.pass_ref.sync(ast3.Dict(keys=[], values=[]), node)
243
+ elif any(isinstance(attr, uni.JsxSpreadAttribute) for attr in node.attributes):
244
+ attrs_expr = self.pass_ref.sync(ast3.Dict(keys=[], values=[]), node)
245
+ for attr in node.attributes:
246
+ attr_ast = cast(ast3.expr, attr.gen.py_ast[0])
247
+ if isinstance(attr, uni.JsxSpreadAttribute):
248
+ attrs_expr = self.pass_ref.sync(
249
+ ast3.Dict(keys=[None, None], values=[attrs_expr, attr_ast]),
250
+ attr,
251
+ )
252
+ elif isinstance(attr, uni.JsxNormalAttribute):
253
+ key_ast, value_ast = attr_ast.elts # type: ignore[attr-defined]
254
+ attrs_expr = self.pass_ref.sync(
255
+ ast3.Dict(
256
+ keys=[None, key_ast],
257
+ values=[attrs_expr, cast(ast3.expr, value_ast)],
258
+ ),
259
+ attr,
260
+ )
261
+ else:
262
+ keys: list[ast3.expr | None] = []
263
+ values: list[ast3.expr] = []
264
+ for attr in node.attributes:
265
+ if isinstance(attr, uni.JsxNormalAttribute):
266
+ attr_ast = attr.gen.py_ast[0]
267
+ key_ast, value_ast = attr_ast.elts # type: ignore[attr-defined]
268
+ keys.append(cast(ast3.expr, key_ast))
269
+ values.append(cast(ast3.expr, value_ast))
270
+ attrs_expr = self.pass_ref.sync(ast3.Dict(keys=keys, values=values), node)
271
+
272
+ if node.children:
273
+ children_arg = self.pass_ref.sync(
274
+ ast3.List(
275
+ elts=[cast(ast3.expr, c.gen.py_ast[0]) for c in node.children],
276
+ ctx=ast3.Load(),
277
+ ),
278
+ node,
279
+ )
280
+ else:
281
+ children_arg = self.pass_ref.sync(ast3.List(elts=[], ctx=ast3.Load()), node)
282
+
283
+ call = self.pass_ref.sync(
284
+ ast3.Call(
285
+ func=self.pass_ref.jaclib_obj("jsx"),
286
+ args=[tag_arg, attrs_expr, children_arg],
287
+ keywords=[],
288
+ ),
289
+ node,
290
+ )
291
+ node.gen.py_ast = [call]
292
+ return node.gen.py_ast
293
+
294
+ def element_name(self, node: uni.JsxElementName) -> list[ast3.AST]:
295
+ """Generate Python AST for JSX element names."""
296
+ name_str = ".".join(part.value for part in node.parts)
297
+ if node.parts and node.parts[0].value[0].isupper():
298
+ expr = self.pass_ref.sync(
299
+ ast3.Name(id=name_str, ctx=ast3.Load()),
300
+ node,
301
+ )
302
+ else:
303
+ expr = self.pass_ref.sync(ast3.Constant(value=name_str), node)
304
+ node.gen.py_ast = [expr]
305
+ return node.gen.py_ast
306
+
307
+ def spread_attribute(self, node: uni.JsxSpreadAttribute) -> list[ast3.AST]:
308
+ """Generate Python AST for JSX spread attributes."""
309
+ node.gen.py_ast = [cast(ast3.expr, node.expr.gen.py_ast[0])]
310
+ return node.gen.py_ast
311
+
312
+ def normal_attribute(self, node: uni.JsxNormalAttribute) -> list[ast3.AST]:
313
+ """Generate Python AST for JSX normal attributes."""
314
+ if not node.name:
315
+ node.gen.py_ast = []
316
+ return node.gen.py_ast
317
+
318
+ key_ast = self.pass_ref.sync(ast3.Constant(value=node.name.value), node.name)
319
+ value_ast = (
320
+ cast(ast3.expr, node.value.gen.py_ast[0]) # type: ignore[index]
321
+ if node.value
322
+ else self.pass_ref.sync(ast3.Constant(value=True), node)
323
+ )
324
+ node.gen.py_ast = [
325
+ self.pass_ref.sync(
326
+ ast3.Tuple(elts=[key_ast, value_ast], ctx=ast3.Load()),
327
+ node,
328
+ )
329
+ ]
330
+ return node.gen.py_ast
331
+
332
+ def text(self, node: uni.JsxText) -> list[ast3.AST]:
333
+ """Generate Python AST for JSX text nodes."""
334
+ expr = self.pass_ref.sync(ast3.Constant(value=node.value.value), node)
335
+ node.gen.py_ast = [expr]
336
+ return node.gen.py_ast
337
+
338
+ def expression(self, node: uni.JsxExpression) -> list[ast3.AST]:
339
+ """Generate Python AST for JSX expression children."""
340
+ node.gen.py_ast = [cast(ast3.expr, node.expr.gen.py_ast[0])]
341
+ return node.gen.py_ast
342
+
343
+
344
+ __all__ = ["EsJsxProcessor", "PyJsxProcessor"]
@@ -0,0 +1,25 @@
1
+ """ECMAScript/JavaScript AST generation for Jac.
2
+
3
+ This package provides ECMAScript AST generation capabilities following the ESTree
4
+ specification, allowing Jac code to be transpiled to JavaScript/ECMAScript.
5
+ """
6
+
7
+ from jaclang.compiler.passes.ecmascript.esast_gen_pass import EsastGenPass
8
+ from jaclang.compiler.passes.ecmascript.estree import (
9
+ Declaration,
10
+ Expression,
11
+ Pattern,
12
+ Program,
13
+ Statement,
14
+ es_node_to_dict,
15
+ )
16
+
17
+ __all__ = [
18
+ "EsastGenPass",
19
+ "Expression",
20
+ "Declaration",
21
+ "Pattern",
22
+ "Program",
23
+ "Statement",
24
+ "es_node_to_dict",
25
+ ]