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
|
@@ -135,20 +135,53 @@ class DocIRGenPass(UniPass):
|
|
|
135
135
|
def exit_import(self, node: uni.Import) -> None:
|
|
136
136
|
"""Exit import node."""
|
|
137
137
|
parts: list[doc.DocType] = []
|
|
138
|
+
mod_items: list[doc.DocType] = []
|
|
139
|
+
has_comment: Optional[doc.DocType] = None
|
|
140
|
+
is_in_items: bool = False
|
|
138
141
|
for i in node.kid:
|
|
139
142
|
if isinstance(i, uni.Token) and i.name == Tok.COMMA:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
if is_in_items:
|
|
144
|
+
mod_items.pop()
|
|
145
|
+
mod_items.append(i.gen.doc_ir)
|
|
146
|
+
mod_items.append(self.line())
|
|
147
|
+
else:
|
|
148
|
+
parts.pop()
|
|
149
|
+
parts.append(i.gen.doc_ir)
|
|
150
|
+
parts.append(self.line())
|
|
151
|
+
elif (
|
|
152
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
153
|
+
):
|
|
154
|
+
has_comment = i.gen.doc_ir
|
|
143
155
|
elif isinstance(i, uni.Token) and i.name == Tok.SEMI:
|
|
144
156
|
parts.pop()
|
|
145
157
|
parts.append(i.gen.doc_ir)
|
|
146
158
|
elif isinstance(i, uni.Token) and i.name == Tok.RBRACE:
|
|
159
|
+
is_in_items = False
|
|
160
|
+
mod_items.pop()
|
|
161
|
+
parts.append(
|
|
162
|
+
self.group(
|
|
163
|
+
self.concat(
|
|
164
|
+
[
|
|
165
|
+
self.indent(self.concat([self.line(), *mod_items])),
|
|
166
|
+
self.line(),
|
|
167
|
+
]
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
)
|
|
147
171
|
parts.append(i.gen.doc_ir)
|
|
148
|
-
|
|
172
|
+
elif isinstance(i, uni.Token) and i.name == Tok.LBRACE:
|
|
173
|
+
is_in_items = True
|
|
149
174
|
parts.append(i.gen.doc_ir)
|
|
150
|
-
|
|
175
|
+
else:
|
|
176
|
+
if is_in_items:
|
|
177
|
+
mod_items.append(i.gen.doc_ir)
|
|
178
|
+
mod_items.append(self.space())
|
|
179
|
+
else:
|
|
180
|
+
parts.append(i.gen.doc_ir)
|
|
181
|
+
parts.append(self.space())
|
|
151
182
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
183
|
+
if has_comment:
|
|
184
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
152
185
|
|
|
153
186
|
def exit_module_item(self, node: uni.ModuleItem) -> None:
|
|
154
187
|
"""Generate DocIR for module items."""
|
|
@@ -178,6 +211,7 @@ class DocIRGenPass(UniPass):
|
|
|
178
211
|
"""Generate DocIR for archetypes."""
|
|
179
212
|
parts: list[doc.DocType] = []
|
|
180
213
|
body_parts: list[doc.DocType] = []
|
|
214
|
+
has_comment: Optional[doc.DocType] = None
|
|
181
215
|
prev_item = None
|
|
182
216
|
in_body = False
|
|
183
217
|
for i in node.kid:
|
|
@@ -198,6 +232,10 @@ class DocIRGenPass(UniPass):
|
|
|
198
232
|
parts.pop()
|
|
199
233
|
parts.append(i.gen.doc_ir)
|
|
200
234
|
parts.append(self.space())
|
|
235
|
+
elif (
|
|
236
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
237
|
+
):
|
|
238
|
+
has_comment = i.gen.doc_ir
|
|
201
239
|
elif isinstance(node.body, Sequence) and i in node.body:
|
|
202
240
|
if not in_body:
|
|
203
241
|
body_parts.append(self.hard_line())
|
|
@@ -225,13 +263,15 @@ class DocIRGenPass(UniPass):
|
|
|
225
263
|
else:
|
|
226
264
|
parts.append(i.gen.doc_ir)
|
|
227
265
|
parts.append(self.space())
|
|
228
|
-
|
|
229
266
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
267
|
+
if has_comment:
|
|
268
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
230
269
|
|
|
231
270
|
def exit_ability(self, node: uni.Ability) -> None:
|
|
232
271
|
"""Generate DocIR for abilities."""
|
|
233
272
|
parts: list[doc.DocType] = []
|
|
234
273
|
body_parts: list[doc.DocType] = []
|
|
274
|
+
has_comment: Optional[doc.DocType] = None
|
|
235
275
|
in_body = False
|
|
236
276
|
for i in node.kid:
|
|
237
277
|
if i == node.doc or (node.decorators and i in node.decorators):
|
|
@@ -259,12 +299,18 @@ class DocIRGenPass(UniPass):
|
|
|
259
299
|
parts.pop()
|
|
260
300
|
parts.append(i.gen.doc_ir)
|
|
261
301
|
parts.append(self.space())
|
|
302
|
+
elif (
|
|
303
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
304
|
+
):
|
|
305
|
+
has_comment = i.gen.doc_ir
|
|
262
306
|
elif not in_body and isinstance(i, uni.Token) and i.name == Tok.DECOR_OP:
|
|
263
307
|
parts.append(i.gen.doc_ir)
|
|
264
308
|
else:
|
|
265
309
|
parts.append(i.gen.doc_ir)
|
|
266
310
|
parts.append(self.space())
|
|
267
311
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
312
|
+
if has_comment:
|
|
313
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
268
314
|
|
|
269
315
|
def exit_func_signature(self, node: uni.FuncSignature) -> None:
|
|
270
316
|
"""Generate DocIR for function signatures."""
|
|
@@ -401,7 +447,7 @@ class DocIRGenPass(UniPass):
|
|
|
401
447
|
]
|
|
402
448
|
)
|
|
403
449
|
)
|
|
404
|
-
parts.append(self.if_break(broken, flat))
|
|
450
|
+
parts.append(self.group(self.if_break(broken, flat)))
|
|
405
451
|
else:
|
|
406
452
|
parts.append(i.gen.doc_ir)
|
|
407
453
|
parts.append(self.space())
|
|
@@ -846,6 +892,13 @@ class DocIRGenPass(UniPass):
|
|
|
846
892
|
parts.append(i.gen.doc_ir)
|
|
847
893
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
848
894
|
|
|
895
|
+
def exit_formatted_value(self, node: uni.FormattedValue) -> None:
|
|
896
|
+
"""Generate DocIR for formatted value expressions."""
|
|
897
|
+
parts: list[doc.DocType] = []
|
|
898
|
+
for i in node.kid:
|
|
899
|
+
parts.append(i.gen.doc_ir)
|
|
900
|
+
node.gen.doc_ir = self.group(self.concat(parts))
|
|
901
|
+
|
|
849
902
|
def exit_if_else_expr(self, node: uni.IfElseExpr) -> None:
|
|
850
903
|
"""Generate DocIR for conditional expressions."""
|
|
851
904
|
parts: list[doc.DocType] = []
|
|
@@ -901,16 +954,16 @@ class DocIRGenPass(UniPass):
|
|
|
901
954
|
return [expr]
|
|
902
955
|
|
|
903
956
|
exprs = __flatten_bool_expr(node)
|
|
904
|
-
|
|
957
|
+
parts += [exprs[0].gen.doc_ir, self.line()]
|
|
958
|
+
for i in range(1, len(exprs), 2):
|
|
905
959
|
(
|
|
906
|
-
expr,
|
|
907
960
|
op,
|
|
961
|
+
expr,
|
|
908
962
|
) = (
|
|
909
|
-
exprs[i],
|
|
910
963
|
exprs[i + 1],
|
|
964
|
+
exprs[i],
|
|
911
965
|
)
|
|
912
966
|
parts += [expr.gen.doc_ir, self.space(), op.gen.doc_ir, self.line()]
|
|
913
|
-
parts += [exprs[-1].gen.doc_ir, self.line()]
|
|
914
967
|
parts.pop()
|
|
915
968
|
flat = self.concat(parts)
|
|
916
969
|
node.gen.doc_ir = self.group(flat)
|
|
@@ -1108,6 +1161,8 @@ class DocIRGenPass(UniPass):
|
|
|
1108
1161
|
"""Generate DocIR for assert statements."""
|
|
1109
1162
|
parts: list[doc.DocType] = []
|
|
1110
1163
|
for i in node.kid:
|
|
1164
|
+
if isinstance(i, uni.Token) and i.name == Tok.SEMI and len(parts):
|
|
1165
|
+
parts.pop()
|
|
1111
1166
|
parts.append(i.gen.doc_ir)
|
|
1112
1167
|
parts.append(self.space())
|
|
1113
1168
|
parts.pop()
|
|
@@ -1125,6 +1180,7 @@ class DocIRGenPass(UniPass):
|
|
|
1125
1180
|
def exit_global_vars(self, node: uni.GlobalVars) -> None:
|
|
1126
1181
|
"""Generate DocIR for global variables."""
|
|
1127
1182
|
parts: list[doc.DocType] = []
|
|
1183
|
+
has_comment: Optional[doc.DocType] = None
|
|
1128
1184
|
for i in node.kid:
|
|
1129
1185
|
if i == node.doc:
|
|
1130
1186
|
parts.append(i.gen.doc_ir)
|
|
@@ -1133,15 +1189,22 @@ class DocIRGenPass(UniPass):
|
|
|
1133
1189
|
parts.pop()
|
|
1134
1190
|
parts.append(i.gen.doc_ir)
|
|
1135
1191
|
parts.append(self.space())
|
|
1192
|
+
elif (
|
|
1193
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1194
|
+
):
|
|
1195
|
+
has_comment = i.gen.doc_ir
|
|
1136
1196
|
else:
|
|
1137
1197
|
parts.append(i.gen.doc_ir)
|
|
1138
1198
|
parts.append(self.space())
|
|
1139
1199
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1200
|
+
if has_comment:
|
|
1201
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1140
1202
|
|
|
1141
1203
|
def exit_module_code(self, node: uni.ModuleCode) -> None:
|
|
1142
1204
|
"""Generate DocIR for module code."""
|
|
1143
1205
|
parts: list[doc.DocType] = []
|
|
1144
1206
|
body_parts: list[doc.DocType] = []
|
|
1207
|
+
has_comment: Optional[doc.DocType] = None
|
|
1145
1208
|
in_body = False
|
|
1146
1209
|
for i in node.kid:
|
|
1147
1210
|
if node.doc and i is node.doc:
|
|
@@ -1153,6 +1216,10 @@ class DocIRGenPass(UniPass):
|
|
|
1153
1216
|
elif isinstance(i, uni.Token) and i.name == Tok.COLON:
|
|
1154
1217
|
parts.pop()
|
|
1155
1218
|
parts.append(i.gen.doc_ir)
|
|
1219
|
+
elif (
|
|
1220
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1221
|
+
):
|
|
1222
|
+
has_comment = i.gen.doc_ir
|
|
1156
1223
|
elif isinstance(node.body, Sequence) and i in node.body:
|
|
1157
1224
|
if not in_body:
|
|
1158
1225
|
parts.pop()
|
|
@@ -1175,6 +1242,8 @@ class DocIRGenPass(UniPass):
|
|
|
1175
1242
|
parts.append(i.gen.doc_ir)
|
|
1176
1243
|
parts.append(self.space())
|
|
1177
1244
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1245
|
+
if has_comment:
|
|
1246
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1178
1247
|
|
|
1179
1248
|
def exit_global_stmt(self, node: uni.GlobalStmt) -> None:
|
|
1180
1249
|
"""Generate DocIR for global statements."""
|
|
@@ -1264,7 +1333,9 @@ class DocIRGenPass(UniPass):
|
|
|
1264
1333
|
]
|
|
1265
1334
|
)
|
|
1266
1335
|
)
|
|
1267
|
-
if isinstance(node.parent, uni.Assignment)
|
|
1336
|
+
if isinstance(node.parent, (uni.Assignment)) or (
|
|
1337
|
+
isinstance(node.parent, uni.IfStmt) and isinstance(node.value, uni.BoolExpr)
|
|
1338
|
+
):
|
|
1268
1339
|
node.gen.doc_ir = self.if_break(
|
|
1269
1340
|
flat_contents=self.group(self.concat(parts[1:-1])),
|
|
1270
1341
|
break_contents=broken,
|
|
@@ -1300,6 +1371,7 @@ class DocIRGenPass(UniPass):
|
|
|
1300
1371
|
def exit_py_inline_code(self, node: uni.PyInlineCode) -> None:
|
|
1301
1372
|
"""Generate DocIR for Python inline code blocks."""
|
|
1302
1373
|
parts: list[doc.DocType] = []
|
|
1374
|
+
has_comment: Optional[doc.DocType] = None
|
|
1303
1375
|
for i in node.kid:
|
|
1304
1376
|
if i == node.doc:
|
|
1305
1377
|
parts.append(i.gen.doc_ir)
|
|
@@ -1309,14 +1381,21 @@ class DocIRGenPass(UniPass):
|
|
|
1309
1381
|
parts.append(i.gen.doc_ir)
|
|
1310
1382
|
parts.append(self.text("::py::"))
|
|
1311
1383
|
parts.append(self.hard_line())
|
|
1384
|
+
elif (
|
|
1385
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1386
|
+
):
|
|
1387
|
+
has_comment = i.gen.doc_ir
|
|
1312
1388
|
else:
|
|
1313
1389
|
parts.append(i.gen.doc_ir)
|
|
1314
1390
|
parts.append(self.space())
|
|
1315
1391
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1392
|
+
if has_comment:
|
|
1393
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1316
1394
|
|
|
1317
1395
|
def exit_test(self, node: uni.Test) -> None:
|
|
1318
1396
|
"""Generate DocIR for test nodes."""
|
|
1319
1397
|
parts: list[doc.DocType] = []
|
|
1398
|
+
has_comment: Optional[doc.DocType] = None
|
|
1320
1399
|
for i in node.kid:
|
|
1321
1400
|
if i == node.doc:
|
|
1322
1401
|
parts.append(i.gen.doc_ir)
|
|
@@ -1325,10 +1404,16 @@ class DocIRGenPass(UniPass):
|
|
|
1325
1404
|
if not i.value.startswith("_jac_gen_"):
|
|
1326
1405
|
parts.append(i.gen.doc_ir)
|
|
1327
1406
|
parts.append(self.space())
|
|
1407
|
+
elif (
|
|
1408
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1409
|
+
):
|
|
1410
|
+
has_comment = i.gen.doc_ir
|
|
1328
1411
|
else:
|
|
1329
1412
|
parts.append(i.gen.doc_ir)
|
|
1330
1413
|
parts.append(self.space())
|
|
1331
1414
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1415
|
+
if has_comment:
|
|
1416
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1332
1417
|
|
|
1333
1418
|
def exit_match_stmt(self, node: uni.MatchStmt) -> None:
|
|
1334
1419
|
"""Generate DocIR for match statements."""
|
|
@@ -1512,6 +1597,7 @@ class DocIRGenPass(UniPass):
|
|
|
1512
1597
|
"""Generate DocIR for implementation definitions."""
|
|
1513
1598
|
parts: list[doc.DocType] = []
|
|
1514
1599
|
body_parts: list[doc.DocType] = []
|
|
1600
|
+
has_comment: Optional[doc.DocType] = None
|
|
1515
1601
|
in_body = False
|
|
1516
1602
|
for i in node.kid:
|
|
1517
1603
|
if i == node.doc or (node.decorators and i in node.decorators):
|
|
@@ -1519,6 +1605,10 @@ class DocIRGenPass(UniPass):
|
|
|
1519
1605
|
parts.append(self.hard_line())
|
|
1520
1606
|
elif self.is_within(i, node.target):
|
|
1521
1607
|
parts.append(i.gen.doc_ir)
|
|
1608
|
+
elif (
|
|
1609
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1610
|
+
):
|
|
1611
|
+
has_comment = i.gen.doc_ir
|
|
1522
1612
|
elif (
|
|
1523
1613
|
in_body
|
|
1524
1614
|
or isinstance(node.body, Sequence)
|
|
@@ -1546,10 +1636,13 @@ class DocIRGenPass(UniPass):
|
|
|
1546
1636
|
parts.append(i.gen.doc_ir)
|
|
1547
1637
|
parts.append(self.space())
|
|
1548
1638
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1639
|
+
if has_comment:
|
|
1640
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1549
1641
|
|
|
1550
1642
|
def exit_sem_def(self, node: uni.SemDef) -> None:
|
|
1551
1643
|
"""Generate DocIR for semantic definitions."""
|
|
1552
1644
|
parts: list[doc.DocType] = []
|
|
1645
|
+
has_comment: Optional[doc.DocType] = None
|
|
1553
1646
|
for i in node.kid:
|
|
1554
1647
|
if i in node.target:
|
|
1555
1648
|
parts.append(i.gen.doc_ir)
|
|
@@ -1557,10 +1650,16 @@ class DocIRGenPass(UniPass):
|
|
|
1557
1650
|
parts.pop()
|
|
1558
1651
|
parts.append(i.gen.doc_ir)
|
|
1559
1652
|
parts.append(self.space())
|
|
1653
|
+
elif (
|
|
1654
|
+
i == node.kid[0] and isinstance(i, uni.Token) and i.name == Tok.COMMENT
|
|
1655
|
+
):
|
|
1656
|
+
has_comment = i.gen.doc_ir
|
|
1560
1657
|
else:
|
|
1561
1658
|
parts.append(i.gen.doc_ir)
|
|
1562
1659
|
parts.append(self.space())
|
|
1563
1660
|
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1661
|
+
if has_comment:
|
|
1662
|
+
node.gen.doc_ir = self.concat([has_comment, node.gen.doc_ir])
|
|
1564
1663
|
|
|
1565
1664
|
def exit_event_signature(self, node: uni.EventSignature) -> None:
|
|
1566
1665
|
"""Generate DocIR for event signatures."""
|
|
@@ -1614,14 +1713,6 @@ class DocIRGenPass(UniPass):
|
|
|
1614
1713
|
and isinstance(node.parent, uni.FString)
|
|
1615
1714
|
)
|
|
1616
1715
|
|
|
1617
|
-
if "\n" in node.value:
|
|
1618
|
-
lines = node.value.split("\n")
|
|
1619
|
-
parts: list[doc.DocType] = [self.text(lines[0])]
|
|
1620
|
-
for line in lines[1:]:
|
|
1621
|
-
parts.append(self.hard_line())
|
|
1622
|
-
parts.append(self.text(line.lstrip()))
|
|
1623
|
-
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1624
|
-
return
|
|
1625
1716
|
if is_escaped_curly:
|
|
1626
1717
|
node.gen.doc_ir = self.concat(
|
|
1627
1718
|
[self.text(node.value), self.text(node.value)]
|
|
@@ -1663,3 +1754,111 @@ class DocIRGenPass(UniPass):
|
|
|
1663
1754
|
node.gen.doc_ir = self.group(
|
|
1664
1755
|
self.concat([self.text(node.value), self.hard_line()])
|
|
1665
1756
|
)
|
|
1757
|
+
|
|
1758
|
+
def exit_jsx_element(self, node: uni.JsxElement) -> None:
|
|
1759
|
+
"""Generate DocIR for JSX elements - kid-centric beautiful formatting!"""
|
|
1760
|
+
parts: list[doc.DocType] = []
|
|
1761
|
+
prev = None
|
|
1762
|
+
|
|
1763
|
+
# Check if we have any JSX element children
|
|
1764
|
+
# Use node.children instead of node.kid to avoid counting opening/closing tags
|
|
1765
|
+
has_jsx_elem_children = any(
|
|
1766
|
+
isinstance(k, uni.JsxElement) for k in node.children
|
|
1767
|
+
)
|
|
1768
|
+
|
|
1769
|
+
# Only break/indent if we have JSX element children
|
|
1770
|
+
# (simple text/expression children stay inline)
|
|
1771
|
+
should_format_children = has_jsx_elem_children
|
|
1772
|
+
|
|
1773
|
+
for i in node.kid:
|
|
1774
|
+
# Add line break between attributes (allows them to wrap nicely)
|
|
1775
|
+
if (
|
|
1776
|
+
prev
|
|
1777
|
+
and isinstance(prev, (uni.JsxElementName, uni.JsxAttribute))
|
|
1778
|
+
and isinstance(i, uni.JsxAttribute)
|
|
1779
|
+
):
|
|
1780
|
+
parts.append(self.line())
|
|
1781
|
+
# Add hard line between JSX element children, or before first child
|
|
1782
|
+
elif (
|
|
1783
|
+
prev
|
|
1784
|
+
and (
|
|
1785
|
+
(
|
|
1786
|
+
isinstance(prev, (uni.JsxChild, uni.JsxElement))
|
|
1787
|
+
and isinstance(i, (uni.JsxChild, uni.JsxElement))
|
|
1788
|
+
)
|
|
1789
|
+
or (
|
|
1790
|
+
isinstance(prev, (uni.JsxElementName, uni.JsxAttribute))
|
|
1791
|
+
and isinstance(i, (uni.JsxChild, uni.JsxElement))
|
|
1792
|
+
)
|
|
1793
|
+
)
|
|
1794
|
+
and should_format_children
|
|
1795
|
+
):
|
|
1796
|
+
parts.append(self.hard_line())
|
|
1797
|
+
|
|
1798
|
+
# Indent JSX element children, but not text/expression children
|
|
1799
|
+
if isinstance(i, uni.JsxElement) and should_format_children:
|
|
1800
|
+
parts.append(self.indent(i.gen.doc_ir))
|
|
1801
|
+
else:
|
|
1802
|
+
parts.append(i.gen.doc_ir)
|
|
1803
|
+
|
|
1804
|
+
prev = i
|
|
1805
|
+
|
|
1806
|
+
node.gen.doc_ir = self.group(self.concat(parts))
|
|
1807
|
+
|
|
1808
|
+
def exit_jsx_element_name(self, node: uni.JsxElementName) -> None:
|
|
1809
|
+
"""Generate DocIR for JSX element names."""
|
|
1810
|
+
parts: list[doc.DocType] = []
|
|
1811
|
+
for i in node.kid:
|
|
1812
|
+
parts.append(i.gen.doc_ir)
|
|
1813
|
+
node.gen.doc_ir = self.concat(parts)
|
|
1814
|
+
|
|
1815
|
+
def exit_jsx_spread_attribute(self, node: uni.JsxSpreadAttribute) -> None:
|
|
1816
|
+
"""Generate DocIR for JSX spread attributes."""
|
|
1817
|
+
parts: list[doc.DocType] = []
|
|
1818
|
+
for i in node.kid:
|
|
1819
|
+
parts.append(i.gen.doc_ir)
|
|
1820
|
+
node.gen.doc_ir = self.concat(parts)
|
|
1821
|
+
|
|
1822
|
+
def exit_jsx_normal_attribute(self, node: uni.JsxNormalAttribute) -> None:
|
|
1823
|
+
"""Generate DocIR for JSX normal attributes."""
|
|
1824
|
+
# Normalize to ensure LBRACE/RBRACE tokens are added for expression values
|
|
1825
|
+
node.normalize()
|
|
1826
|
+
parts: list[doc.DocType] = []
|
|
1827
|
+
for i in node.kid:
|
|
1828
|
+
# Tokens created by normalize() have empty doc_ir, so regenerate it
|
|
1829
|
+
if (
|
|
1830
|
+
isinstance(i, uni.Token)
|
|
1831
|
+
and isinstance(i.gen.doc_ir, doc.Text)
|
|
1832
|
+
and not i.gen.doc_ir.text
|
|
1833
|
+
):
|
|
1834
|
+
i.gen.doc_ir = self.text(i.value)
|
|
1835
|
+
elif not isinstance(
|
|
1836
|
+
i.gen.doc_ir,
|
|
1837
|
+
(
|
|
1838
|
+
doc.Text,
|
|
1839
|
+
doc.Concat,
|
|
1840
|
+
doc.Group,
|
|
1841
|
+
doc.Indent,
|
|
1842
|
+
doc.Line,
|
|
1843
|
+
doc.Align,
|
|
1844
|
+
doc.IfBreak,
|
|
1845
|
+
),
|
|
1846
|
+
):
|
|
1847
|
+
# For nodes with invalid doc_ir, generate it by visiting
|
|
1848
|
+
self.enter_exit(i)
|
|
1849
|
+
parts.append(i.gen.doc_ir)
|
|
1850
|
+
node.gen.doc_ir = self.concat(parts)
|
|
1851
|
+
|
|
1852
|
+
def exit_jsx_text(self, node: uni.JsxText) -> None:
|
|
1853
|
+
"""Generate DocIR for JSX text."""
|
|
1854
|
+
parts: list[doc.DocType] = []
|
|
1855
|
+
for i in node.kid:
|
|
1856
|
+
parts.append(i.gen.doc_ir)
|
|
1857
|
+
node.gen.doc_ir = self.concat(parts)
|
|
1858
|
+
|
|
1859
|
+
def exit_jsx_expression(self, node: uni.JsxExpression) -> None:
|
|
1860
|
+
"""Generate DocIR for JSX expressions."""
|
|
1861
|
+
parts: list[doc.DocType] = []
|
|
1862
|
+
for i in node.kid:
|
|
1863
|
+
parts.append(i.gen.doc_ir)
|
|
1864
|
+
node.gen.doc_ir = self.concat(parts)
|
|
@@ -41,19 +41,9 @@ class FuseCommentsPass(UniPass):
|
|
|
41
41
|
except StopIteration:
|
|
42
42
|
next_comment = None
|
|
43
43
|
|
|
44
|
-
# Handle possible leading comments
|
|
45
|
-
if next_comment and (not next_code or _is_before(next_comment, next_code)):
|
|
46
|
-
self.ir_out.src_terminals.insert(0, next_comment)
|
|
47
|
-
|
|
48
44
|
# Merge streams in order
|
|
49
45
|
while next_comment or next_code:
|
|
50
46
|
if next_comment and (not next_code or _is_before(next_comment, next_code)):
|
|
51
|
-
# Add comment token
|
|
52
|
-
if merged and (last_token := merged[-1]):
|
|
53
|
-
self.ir_out.src_terminals.insert(
|
|
54
|
-
self.ir_out.src_terminals.index(last_token) + 1,
|
|
55
|
-
next_comment,
|
|
56
|
-
)
|
|
57
47
|
merged.append(next_comment)
|
|
58
48
|
try:
|
|
59
49
|
next_comment = next(comments)
|
|
@@ -66,6 +56,7 @@ class FuseCommentsPass(UniPass):
|
|
|
66
56
|
next_code = next(code_tokens)
|
|
67
57
|
except StopIteration:
|
|
68
58
|
next_code = None
|
|
59
|
+
self.ir_out.src_terminals[:] = merged
|
|
69
60
|
|
|
70
61
|
return merged
|
|
71
62
|
|
|
@@ -51,7 +51,7 @@ class JacFormatPass(Transform[uni.Module, uni.Module]):
|
|
|
51
51
|
|
|
52
52
|
if isinstance(cur, doc.Text):
|
|
53
53
|
remaining -= len(cur.text)
|
|
54
|
-
if remaining
|
|
54
|
+
if remaining <= 0:
|
|
55
55
|
return False
|
|
56
56
|
|
|
57
57
|
elif isinstance(cur, doc.Line):
|
|
@@ -63,7 +63,7 @@ class JacFormatPass(Transform[uni.Module, uni.Module]):
|
|
|
63
63
|
continue
|
|
64
64
|
# regular soft line becomes a single space in flat mode
|
|
65
65
|
remaining -= 1
|
|
66
|
-
if remaining
|
|
66
|
+
if remaining <= 0:
|
|
67
67
|
return False
|
|
68
68
|
|
|
69
69
|
# --- Structural nodes (walk children in LIFO) ---
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import from datetime { datetime }
|
|
2
2
|
import from uuid { UUID, uuid4 }
|
|
3
3
|
import from jaclang.compiler.constant { EdgeDir }
|
|
4
|
-
import from jaclang.plugin {
|
|
4
|
+
import from jaclang.plugin {
|
|
5
|
+
Archetype,
|
|
6
|
+
ArchetypeProtocol,
|
|
7
|
+
DSFunc,
|
|
8
|
+
AbsRootHook,
|
|
9
|
+
hookimpl
|
|
10
|
+
}
|
|
5
11
|
import math;
|
|
6
12
|
import numpy as np;
|