jaclang 0.5.11__py3-none-any.whl → 0.5.16__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 (41) hide show
  1. jaclang/cli/cli.py +20 -0
  2. jaclang/compiler/__init__.py +35 -19
  3. jaclang/compiler/absyntree.py +106 -97
  4. jaclang/compiler/generated/jac_parser.py +4069 -0
  5. jaclang/compiler/jac.lark +655 -0
  6. jaclang/compiler/parser.py +44 -31
  7. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +92 -37
  8. jaclang/compiler/passes/main/import_pass.py +8 -5
  9. jaclang/compiler/passes/main/pyast_gen_pass.py +512 -352
  10. jaclang/compiler/passes/main/pyast_load_pass.py +271 -64
  11. jaclang/compiler/passes/main/registry_pass.py +3 -7
  12. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -0
  13. jaclang/compiler/passes/main/type_check_pass.py +4 -1
  14. jaclang/compiler/passes/tool/jac_formatter_pass.py +7 -0
  15. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +16 -0
  16. jaclang/compiler/passes/utils/mypy_ast_build.py +93 -0
  17. jaclang/compiler/tests/test_importer.py +15 -0
  18. jaclang/core/aott.py +4 -3
  19. jaclang/core/construct.py +1 -1
  20. jaclang/core/importer.py +109 -51
  21. jaclang/core/llms.py +29 -0
  22. jaclang/core/registry.py +22 -0
  23. jaclang/core/utils.py +72 -0
  24. jaclang/plugin/default.py +127 -8
  25. jaclang/plugin/feature.py +29 -2
  26. jaclang/plugin/spec.py +25 -2
  27. jaclang/utils/helpers.py +7 -9
  28. jaclang/utils/lang_tools.py +37 -13
  29. jaclang/utils/test.py +1 -3
  30. jaclang/utils/tests/test_lang_tools.py +6 -0
  31. jaclang/vendor/lark/grammars/common.lark +59 -0
  32. jaclang/vendor/lark/grammars/lark.lark +62 -0
  33. jaclang/vendor/lark/grammars/python.lark +302 -0
  34. jaclang/vendor/lark/grammars/unicode.lark +7 -0
  35. {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/METADATA +1 -1
  36. {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/RECORD +40 -34
  37. jaclang/compiler/__jac_gen__/jac_parser.py +0 -4069
  38. /jaclang/compiler/{__jac_gen__ → generated}/__init__.py +0 -0
  39. {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/WHEEL +0 -0
  40. {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/entry_points.txt +0 -0
  41. {jaclang-0.5.11.dist-info → jaclang-0.5.16.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import ast as py_ast
6
6
  import os
7
- from typing import Optional, TypeAlias, TypeVar
7
+ from typing import Optional, Sequence, TypeAlias, TypeVar
8
8
 
9
9
  import jaclang.compiler.absyntree as ast
10
10
  from jaclang.compiler.constant import Tokens as Tok
@@ -29,9 +29,9 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
29
29
 
30
30
  def pp(self, node: py_ast.AST) -> None:
31
31
  """Print python node."""
32
- print(
33
- f"{node.__class__.__name__} - {[(k, type(v)) for k, v in vars(node).items()]}"
34
- )
32
+ # print(
33
+ # f"{node.__class__.__name__} - {[(k, type(v)) for k, v in vars(node).items()]}"
34
+ # )
35
35
 
36
36
  def convert(self, node: py_ast.AST) -> ast.AstNode:
37
37
  """Get python node type."""
@@ -45,6 +45,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
45
45
  # print(f"finshed {type(node).__name__} ---------------------")
46
46
  # print("normalizing", ret.__class__.__name__)
47
47
  # print(ret.unparse())
48
+ # ret.unparse()
48
49
  return ret
49
50
 
50
51
  def transform(self, ir: ast.PythonModuleAst) -> ast.Module:
@@ -59,12 +60,16 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
59
60
 
60
61
  def gen_mod_code(with_entry_body: list[ast.CodeBlockStmt]) -> ast.ModuleCode:
61
62
  with_entry_subnodelist = ast.SubNodeList[ast.CodeBlockStmt](
62
- items=with_entry_body, delim=Tok.WS, kid=with_entry_body
63
+ items=with_entry_body,
64
+ delim=Tok.WS,
65
+ kid=with_entry_body,
66
+ left_enc=self.operator(Tok.LBRACE, "{"),
67
+ right_enc=self.operator(Tok.RBRACE, "}"),
63
68
  )
64
69
  return ast.ModuleCode(
65
70
  name=None,
66
71
  body=with_entry_subnodelist,
67
- kid=with_entry_body,
72
+ kid=[with_entry_subnodelist],
68
73
  doc=None,
69
74
  )
70
75
 
@@ -72,12 +77,16 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
72
77
  with_entry_body: list[ast.CodeBlockStmt] = []
73
78
  for i in body:
74
79
  if isinstance(i, exclude_types):
80
+ if len(with_entry_body):
81
+ extracted.append(gen_mod_code(with_entry_body))
82
+ with_entry_body = []
75
83
  extracted.append(i)
76
84
  elif isinstance(i, ast.CodeBlockStmt):
85
+ if isinstance(i, ast.ExprStmt) and isinstance(i.expr, ast.String):
86
+ self.convert_to_doc(i.expr)
77
87
  with_entry_body.append(i)
78
88
  else:
79
89
  self.ice("Invalid type for with entry body")
80
-
81
90
  if len(with_entry_body):
82
91
  extracted.append(gen_mod_code(with_entry_body))
83
92
  return extracted
@@ -97,14 +106,20 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
97
106
  and isinstance(elements[0].expr, ast.String)
98
107
  else elements[0]
99
108
  )
109
+ doc_str_list = [elements[0]] if isinstance(elements[0], ast.String) else []
100
110
  valid = (
101
- [elements[0]] if isinstance(elements[0], ast.String) else []
102
- ) + self.extract_with_entry(elements[1:], (ast.ElementStmt, ast.EmptyToken))
111
+ (doc_str_list)
112
+ + self.extract_with_entry(elements[1:], (ast.ElementStmt, ast.EmptyToken))
113
+ if doc_str_list
114
+ else self.extract_with_entry(elements[:], (ast.ElementStmt, ast.EmptyToken))
115
+ )
116
+ doc_str = elements[0] if isinstance(elements[0], ast.String) else None
117
+ self.convert_to_doc(doc_str) if doc_str else None
103
118
  ret = ast.Module(
104
119
  name=self.mod_path.split(os.path.sep)[-1].split(".")[0],
105
120
  source=ast.JacSource("", mod_path=self.mod_path),
106
- doc=(elements[0] if isinstance(elements[0], ast.String) else None),
107
- body=valid[1:] if isinstance(valid[0], ast.String) else valid,
121
+ doc=doc_str,
122
+ body=valid[1:] if valid and isinstance(valid[0], ast.String) else valid,
108
123
  is_imported=False,
109
124
  kid=valid,
110
125
  )
@@ -146,13 +161,22 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
146
161
  and isinstance(valid[0].expr, ast.String)
147
162
  ):
148
163
  doc = valid[0].expr
164
+ self.convert_to_doc(doc)
149
165
  valid_body = ast.SubNodeList[ast.CodeBlockStmt](
150
- items=valid[1:], delim=Tok.WS, kid=valid[1:]
166
+ items=valid[1:],
167
+ delim=Tok.WS,
168
+ kid=valid[1:],
169
+ left_enc=self.operator(Tok.LBRACE, "{"),
170
+ right_enc=self.operator(Tok.RBRACE, "}"),
151
171
  )
152
172
  else:
153
173
  doc = None
154
174
  valid_body = ast.SubNodeList[ast.CodeBlockStmt](
155
- items=valid, delim=Tok.WS, kid=valid
175
+ items=valid,
176
+ delim=Tok.WS,
177
+ kid=valid,
178
+ left_enc=self.operator(Tok.LBRACE, "{"),
179
+ right_enc=self.operator(Tok.RBRACE, "}"),
156
180
  )
157
181
  decorators = [self.convert(i) for i in node.decorator_list]
158
182
  valid_dec = [i for i in decorators if isinstance(i, ast.Expr)]
@@ -212,7 +236,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
212
236
  ability.is_async = True
213
237
  return ability
214
238
 
215
- def proc_class_def(self, node: py_ast.ClassDef) -> ast.Architype:
239
+ def proc_class_def(self, node: py_ast.ClassDef) -> ast.Architype | ast.Enum:
216
240
  """Process python node.
217
241
 
218
242
  class ClassDef(stmt):
@@ -239,7 +263,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
239
263
  arch_type = ast.Token(
240
264
  file_path=self.mod_path,
241
265
  name=Tok.KW_OBJECT,
242
- value="object",
266
+ value="obj",
243
267
  line=node.lineno,
244
268
  col_start=0,
245
269
  col_end=0,
@@ -247,37 +271,139 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
247
271
  pos_end=0,
248
272
  )
249
273
  body = [self.convert(i) for i in node.body]
250
- valid: list[ast.ArchBlockStmt] = self.extract_with_entry(
251
- body, ast.ArchBlockStmt
274
+ for body_stmt in body:
275
+ if (
276
+ isinstance(body_stmt, ast.Ability)
277
+ and isinstance(body_stmt.name_ref, ast.Name)
278
+ and body_stmt.name_ref.value == "__init__"
279
+ ):
280
+ tok = ast.Token(
281
+ file_path=self.mod_path,
282
+ name=Tok.KW_INIT,
283
+ value="init",
284
+ line=node.lineno,
285
+ col_start=node.col_offset,
286
+ col_end=node.col_offset + len("init"),
287
+ pos_start=0,
288
+ pos_end=0,
289
+ )
290
+ body_stmt.name_ref = ast.SpecialVarRef(var=tok, kid=[tok])
291
+ if (
292
+ isinstance(body_stmt, ast.Ability)
293
+ and body_stmt.signature
294
+ and isinstance(body_stmt.signature, ast.FuncSignature)
295
+ and body_stmt.signature.params
296
+ ):
297
+ body_stmt.signature.params.items = [
298
+ param
299
+ for param in body_stmt.signature.params.items
300
+ if param.name.value != "self"
301
+ ]
302
+ doc = (
303
+ body[0].expr
304
+ if isinstance(body[0], ast.ExprStmt)
305
+ and isinstance(body[0].expr, ast.String)
306
+ else None
307
+ )
308
+ self.convert_to_doc(doc) if doc else None
309
+ body = body[1:] if doc else body
310
+ valid: list[ast.ArchBlockStmt] = (
311
+ self.extract_with_entry(body, ast.ArchBlockStmt)
312
+ if not (isinstance(body[0], ast.Semi) and len(body) == 1)
313
+ else []
252
314
  )
315
+ empty_block: Sequence[ast.AstNode] = [
316
+ self.operator(Tok.LBRACE, "{"),
317
+ self.operator(Tok.RBRACE, "}"),
318
+ ]
253
319
  valid_body = ast.SubNodeList[ast.ArchBlockStmt](
254
- items=valid, delim=Tok.WS, kid=body
320
+ items=valid,
321
+ delim=Tok.WS,
322
+ kid=(valid if valid else empty_block),
323
+ left_enc=self.operator(Tok.LBRACE, "{"),
324
+ right_enc=self.operator(Tok.RBRACE, "}"),
255
325
  )
256
-
257
- base_classes = [self.convert(base) for base in node.bases]
258
- valid2: list[ast.Expr] = [
259
- base for base in base_classes if isinstance(base, ast.Expr)
326
+ converted_base_classes = [self.convert(base) for base in node.bases]
327
+ base_classes: list[ast.Expr] = [
328
+ base for base in converted_base_classes if isinstance(base, ast.Expr)
260
329
  ]
261
- if len(valid2) != len(base_classes):
262
- raise self.ice("Length mismatch in base classes")
263
330
  valid_bases = (
264
- ast.SubNodeList[ast.Expr](items=valid2, delim=Tok.COMMA, kid=base_classes)
265
- if len(valid2)
331
+ ast.SubNodeList[ast.Expr](
332
+ items=base_classes, delim=Tok.COMMA, kid=base_classes
333
+ )
334
+ if base_classes
266
335
  else None
267
336
  )
268
- doc = None
269
- decorators = [self.convert(i) for i in node.decorator_list]
270
- valid_dec = [i for i in decorators if isinstance(i, ast.Expr)]
271
- if len(valid_dec) != len(decorators):
272
- raise self.ice("Length mismatch in decorators in class")
337
+ converted_decorators_list = [self.convert(i) for i in node.decorator_list]
338
+ decorators = [i for i in converted_decorators_list if isinstance(i, ast.Expr)]
273
339
  valid_decorators = (
274
340
  ast.SubNodeList[ast.Expr](
275
- items=valid_dec, delim=Tok.DECOR_OP, kid=decorators
341
+ items=decorators, delim=Tok.DECOR_OP, kid=decorators
276
342
  )
277
- if len(valid_dec)
343
+ if decorators
278
344
  else None
279
345
  )
280
- kid = [name, valid_bases, valid_body] if valid_bases else [name, valid_body]
346
+ if (
347
+ base_classes
348
+ and isinstance(base_classes[0], ast.Name)
349
+ and base_classes[0].value == "Enum"
350
+ ):
351
+ if len(base_classes) > 1:
352
+ raise ValueError(
353
+ "Python's Enum class cannot be used with multiple inheritance."
354
+ )
355
+ arch_type.name = Tok.KW_ENUM
356
+ arch_type.value = "enum"
357
+ valid_enum_body: list[ast.EnumBlockStmt] = []
358
+ for class_body_stmt in node.body:
359
+ converted_stmt = self.convert(class_body_stmt)
360
+ if isinstance(converted_stmt, ast.EnumBlockStmt):
361
+ if isinstance(converted_stmt, ast.Assignment):
362
+ converted_stmt.is_enum_stmt = True
363
+ valid_enum_body.append(converted_stmt)
364
+ else:
365
+ if isinstance(converted_stmt, ast.ExprStmt) and isinstance(
366
+ converted_stmt.expr, ast.String
367
+ ):
368
+ continue
369
+ tok = ast.Token(
370
+ file_path=self.mod_path,
371
+ name=Tok.PYNLINE,
372
+ value=py_ast.unparse(class_body_stmt),
373
+ line=node.lineno,
374
+ col_start=node.col_offset,
375
+ col_end=node.col_offset + len(py_ast.unparse(class_body_stmt)),
376
+ pos_start=0,
377
+ pos_end=0,
378
+ )
379
+ valid_enum_body.append(ast.PyInlineCode(code=tok, kid=[tok]))
380
+
381
+ valid_enum_body2: list[ast.EnumBlockStmt] = [
382
+ i for i in valid_enum_body if isinstance(i, ast.EnumBlockStmt)
383
+ ]
384
+ enum_body = ast.SubNodeList[ast.EnumBlockStmt](
385
+ items=valid_enum_body2, delim=Tok.COMMA, kid=valid_enum_body2
386
+ )
387
+ if doc:
388
+ doc.line_no = name.line_no
389
+ return ast.Enum(
390
+ name=name,
391
+ access=None,
392
+ base_classes=None,
393
+ body=enum_body,
394
+ kid=[doc, name, enum_body] if doc else [name, enum_body],
395
+ doc=doc,
396
+ decorators=valid_decorators,
397
+ )
398
+ kid = (
399
+ [name, valid_bases, valid_body, doc]
400
+ if doc and valid_bases
401
+ else (
402
+ [name, valid_bases, valid_body]
403
+ if valid_bases
404
+ else [name, valid_body, doc] if doc else [name, valid_body]
405
+ )
406
+ )
281
407
  return ast.Architype(
282
408
  arch_type=arch_type,
283
409
  name=name,
@@ -320,13 +446,14 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
320
446
  target = ast.SubNodeList[ast.Expr | ast.KWPair](
321
447
  items=[*valid_exprs], delim=Tok.COMMA, kid=exprs
322
448
  )
449
+ target_1 = (
450
+ valid_exprs[0]
451
+ if len(valid_exprs) > 1
452
+ else ast.TupleVal(values=target, kid=[target])
453
+ )
323
454
  return ast.DeleteStmt(
324
- target=(
325
- valid_exprs[0]
326
- if len(valid_exprs) > 1
327
- else ast.TupleVal(values=target, kid=[target])
328
- ),
329
- kid=exprs,
455
+ target=target_1,
456
+ kid=[target],
330
457
  )
331
458
 
332
459
  def proc_assign(self, node: py_ast.Assign) -> ast.Assignment:
@@ -408,10 +535,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
408
535
  and isinstance(annotation, ast.Expr)
409
536
  and isinstance(target, ast.Expr)
410
537
  ):
538
+ target = ast.SubNodeList[ast.Expr](
539
+ items=[target], delim=Tok.EQ, kid=[target]
540
+ )
411
541
  return ast.Assignment(
412
- target=ast.SubNodeList[ast.Expr](
413
- items=[target], delim=Tok.EQ, kid=[target]
414
- ),
542
+ target=target,
415
543
  value=value if isinstance(value, (ast.Expr, ast.YieldExpr)) else None,
416
544
  type_tag=annotation_subtag,
417
545
  kid=(
@@ -441,7 +569,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
441
569
  raise self.ice("Length mismatch in for body")
442
570
 
443
571
  valid_body = ast.SubNodeList[ast.CodeBlockStmt](
444
- items=val_body, delim=Tok.WS, kid=val_body
572
+ items=val_body,
573
+ delim=Tok.WS,
574
+ kid=val_body,
575
+ left_enc=self.operator(Tok.LBRACE, "{"),
576
+ right_enc=self.operator(Tok.RBRACE, "}"),
445
577
  )
446
578
  orelse = [self.convert(i) for i in node.orelse]
447
579
  val_orelse = [i for i in orelse if isinstance(i, ast.CodeBlockStmt)]
@@ -449,7 +581,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
449
581
  raise self.ice("Length mismatch in for orelse")
450
582
  if orelse:
451
583
  valid_orelse = ast.SubNodeList[ast.CodeBlockStmt](
452
- items=val_orelse, delim=Tok.WS, kid=orelse
584
+ items=val_orelse,
585
+ delim=Tok.WS,
586
+ kid=orelse,
587
+ left_enc=self.operator(Tok.LBRACE, "{"),
588
+ right_enc=self.operator(Tok.RBRACE, "}"),
453
589
  )
454
590
  else:
455
591
  valid_orelse = None
@@ -492,7 +628,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
492
628
  raise self.ice("Length mismatch in for body")
493
629
 
494
630
  valid_body = ast.SubNodeList[ast.CodeBlockStmt](
495
- items=val_body, delim=Tok.WS, kid=val_body
631
+ items=val_body,
632
+ delim=Tok.WS,
633
+ kid=val_body,
634
+ left_enc=self.operator(Tok.LBRACE, "{"),
635
+ right_enc=self.operator(Tok.RBRACE, "}"),
496
636
  )
497
637
  orelse = [self.convert(i) for i in node.orelse]
498
638
  val_orelse = [i for i in orelse if isinstance(i, ast.CodeBlockStmt)]
@@ -500,7 +640,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
500
640
  raise self.ice("Length mismatch in for orelse")
501
641
  if orelse:
502
642
  valid_orelse = ast.SubNodeList[ast.CodeBlockStmt](
503
- items=val_orelse, delim=Tok.WS, kid=orelse
643
+ items=val_orelse,
644
+ delim=Tok.WS,
645
+ kid=orelse,
646
+ left_enc=self.operator(Tok.LBRACE, "{"),
647
+ right_enc=self.operator(Tok.RBRACE, "}"),
504
648
  )
505
649
  else:
506
650
  valid_orelse = None
@@ -540,7 +684,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
540
684
  if len(valid_body) != len(body):
541
685
  raise self.ice("Length mismatch in while body")
542
686
  fin_body = ast.SubNodeList[ast.CodeBlockStmt](
543
- items=valid_body, delim=Tok.WS, kid=valid_body
687
+ items=valid_body,
688
+ delim=Tok.WS,
689
+ kid=valid_body,
690
+ left_enc=self.operator(Tok.LBRACE, "{"),
691
+ right_enc=self.operator(Tok.RBRACE, "}"),
544
692
  )
545
693
  if isinstance(test, ast.Expr):
546
694
  return ast.WhileStmt(
@@ -566,7 +714,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
566
714
  if len(valid_body) != len(body):
567
715
  self.error("Length mismatch in async for body")
568
716
  body2 = ast.SubNodeList[ast.CodeBlockStmt](
569
- items=valid_body, delim=Tok.WS, kid=body
717
+ items=valid_body,
718
+ delim=Tok.WS,
719
+ kid=body,
720
+ left_enc=self.operator(Tok.LBRACE, "{"),
721
+ right_enc=self.operator(Tok.RBRACE, "}"),
570
722
  )
571
723
 
572
724
  orelse = [self.convert(stmt) for stmt in node.orelse]
@@ -584,7 +736,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
584
736
  )
585
737
  else:
586
738
  orelse2 = ast.SubNodeList[ast.CodeBlockStmt](
587
- items=valid_orelse, delim=Tok.WS, kid=orelse
739
+ items=valid_orelse,
740
+ delim=Tok.WS,
741
+ kid=orelse,
742
+ left_enc=self.operator(Tok.LBRACE, "{"),
743
+ right_enc=self.operator(Tok.RBRACE, "}"),
588
744
  )
589
745
  else_body = ast.ElseStmt(body=orelse2, kid=[orelse2])
590
746
  else:
@@ -622,7 +778,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
622
778
  if len(valid_body) != len(body):
623
779
  raise self.ice("Length mismatch in async for body")
624
780
  body_sub = ast.SubNodeList[ast.CodeBlockStmt](
625
- items=valid_body, delim=Tok.WS, kid=body
781
+ items=valid_body,
782
+ delim=Tok.WS,
783
+ kid=body,
784
+ left_enc=self.operator(Tok.LBRACE, "{"),
785
+ right_enc=self.operator(Tok.RBRACE, "}"),
626
786
  )
627
787
  return ast.WithStmt(
628
788
  is_async=False, exprs=items_sub, body=body_sub, kid=[items_sub, body_sub]
@@ -648,7 +808,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
648
808
  if len(valid_body) != len(body):
649
809
  raise self.ice("Length mismatch in async for body")
650
810
  body_sub = ast.SubNodeList[ast.CodeBlockStmt](
651
- items=valid_body, delim=Tok.WS, kid=body
811
+ items=valid_body,
812
+ delim=Tok.WS,
813
+ kid=body,
814
+ left_enc=self.operator(Tok.LBRACE, "{"),
815
+ right_enc=self.operator(Tok.RBRACE, "}"),
652
816
  )
653
817
  return ast.WithStmt(
654
818
  is_async=True, exprs=items_sub, body=body_sub, kid=[items_sub, body_sub]
@@ -855,6 +1019,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
855
1019
  return ast.FuncCall(
856
1020
  target=func,
857
1021
  params=params_in2,
1022
+ genai_call=None,
858
1023
  kid=[func, params_in2] if params_in2 else [func],
859
1024
  )
860
1025
  else:
@@ -924,7 +1089,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
924
1089
  return type_mapping[value_type](
925
1090
  file_path=self.mod_path,
926
1091
  name=token_type,
927
- value=str(node.value),
1092
+ value=(
1093
+ f'"{repr(node.value)[1:-1]}"'
1094
+ if value_type == str
1095
+ else str(node.value)
1096
+ ),
928
1097
  line=node.lineno,
929
1098
  col_start=node.col_offset,
930
1099
  col_end=node.col_offset + len(str(node.value)),
@@ -1014,6 +1183,17 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1014
1183
  body: list[stmt]
1015
1184
  """
1016
1185
  type = self.convert(node.type) if node.type is not None else None
1186
+ if not type:
1187
+ type = ast.Name(
1188
+ file_path=self.mod_path,
1189
+ name=Tok.NAME,
1190
+ value="Any",
1191
+ line=node.lineno,
1192
+ col_start=node.col_offset,
1193
+ col_end=node.col_offset + 3,
1194
+ pos_start=0,
1195
+ pos_end=0,
1196
+ )
1017
1197
  name = (
1018
1198
  ast.Name(
1019
1199
  file_path=self.mod_path,
@@ -1034,7 +1214,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1034
1214
  if len(valid) != len(body):
1035
1215
  raise self.ice("Length mismatch in except handler body")
1036
1216
  valid_body = ast.SubNodeList[ast.CodeBlockStmt](
1037
- items=valid, delim=Tok.WS, kid=valid
1217
+ items=valid,
1218
+ delim=Tok.WS,
1219
+ kid=valid,
1220
+ left_enc=self.operator(Tok.LBRACE, "{"),
1221
+ right_enc=self.operator(Tok.RBRACE, "}"),
1038
1222
  )
1039
1223
  kid = []
1040
1224
  if type:
@@ -1360,32 +1544,37 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1360
1544
  else:
1361
1545
  raise self.ice()
1362
1546
 
1363
- def proc_match_as(self, node: py_ast.MatchAs) -> ast.MatchAs:
1547
+ def proc_match_as(self, node: py_ast.MatchAs) -> ast.MatchAs | ast.MatchWild:
1364
1548
  """Process python node.
1365
1549
 
1366
1550
  class MatchAs(pattern):
1367
1551
  pattern: _Pattern | None
1368
1552
  name: _Identifier | None
1369
1553
  """
1370
- pattern = self.convert(node.pattern) if node.pattern is not None else None
1554
+ pattern = self.convert(node.pattern) if node.pattern else None
1371
1555
  name = ast.Name(
1372
1556
  file_path=self.mod_path,
1373
1557
  name=Tok.NAME,
1374
- value=node.name if node.name is not None else "_",
1558
+ value=node.name if node.name else "_",
1375
1559
  line=node.lineno,
1376
1560
  col_start=node.col_offset,
1377
- col_end=node.col_offset + len(node.name if node.name is not None else "_"),
1561
+ col_end=(
1562
+ (node.col_offset + len(node.name))
1563
+ if node.name
1564
+ else (node.col_offset + 1)
1565
+ ),
1378
1566
  pos_start=0,
1379
1567
  pos_end=0,
1380
1568
  )
1381
- if isinstance(pattern, ast.MatchPattern) or pattern is None:
1569
+
1570
+ if isinstance(pattern, ast.MatchPattern):
1382
1571
  return ast.MatchAs(
1383
1572
  name=name,
1384
1573
  pattern=pattern,
1385
- kid=[name, pattern] if pattern is not None else [name],
1574
+ kid=[name, pattern] if pattern else [name],
1386
1575
  )
1387
1576
  else:
1388
- raise self.ice()
1577
+ return ast.MatchWild(kid=[name])
1389
1578
 
1390
1579
  def proc_match_class(self, node: py_ast.MatchClass) -> ast.MatchArch:
1391
1580
  """Process python node.
@@ -1443,6 +1632,8 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1443
1632
  items=kv_pairs, delim=Tok.COMMA, kid=kv_pairs
1444
1633
  )
1445
1634
  kid.append(kw_patterns)
1635
+ else:
1636
+ kw_patterns = None
1446
1637
  if isinstance(cls, ast.NameSpec):
1447
1638
  return ast.MatchArch(
1448
1639
  name=cls, arg_patterns=patterns_sub, kw_patterns=kw_patterns, kid=kid
@@ -1764,7 +1955,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1764
1955
  if len(valid) != len(body):
1765
1956
  raise self.ice("Length mismatch in try body")
1766
1957
  valid_body = ast.SubNodeList[ast.CodeBlockStmt](
1767
- items=valid, delim=Tok.WS, kid=valid
1958
+ items=valid,
1959
+ delim=Tok.WS,
1960
+ kid=valid,
1961
+ left_enc=self.operator(Tok.LBRACE, "{"),
1962
+ right_enc=self.operator(Tok.RBRACE, "}"),
1768
1963
  )
1769
1964
  kid: list[ast.AstNode] = [valid_body]
1770
1965
 
@@ -1786,7 +1981,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1786
1981
  if len(orelse) != len(valid_orelse):
1787
1982
  raise self.ice("Length mismatch in try orelse")
1788
1983
  else_body = ast.SubNodeList[ast.CodeBlockStmt](
1789
- items=valid_orelse, delim=Tok.WS, kid=valid_orelse
1984
+ items=valid_orelse,
1985
+ delim=Tok.WS,
1986
+ kid=valid_orelse,
1987
+ left_enc=self.operator(Tok.LBRACE, "{"),
1988
+ right_enc=self.operator(Tok.RBRACE, "}"),
1790
1989
  )
1791
1990
  kid.append(else_body)
1792
1991
  else:
@@ -1800,7 +1999,11 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1800
1999
  if len(finalbody) != len(valid_finalbody):
1801
2000
  raise self.ice("Length mismatch in try finalbody")
1802
2001
  finally_body = ast.SubNodeList[ast.CodeBlockStmt](
1803
- items=valid_finalbody, delim=Tok.WS, kid=valid_finalbody
2002
+ items=valid_finalbody,
2003
+ delim=Tok.WS,
2004
+ kid=valid_finalbody,
2005
+ left_enc=self.operator(Tok.LBRACE, "{"),
2006
+ right_enc=self.operator(Tok.RBRACE, "}"),
1804
2007
  )
1805
2008
  kid.append(finally_body)
1806
2009
  else:
@@ -2270,3 +2473,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2270
2473
 
2271
2474
  def proc_type_var_tuple(self, node: py_ast.TypeVarTuple) -> None:
2272
2475
  """Process python node."""
2476
+
2477
+ def convert_to_doc(self, string: ast.String) -> None:
2478
+ """Convert a string to a docstring."""
2479
+ string.value = f'""{string.value}""'
@@ -28,10 +28,10 @@ class RegistryPass(Pass):
28
28
 
29
29
  def exit_module(self, node: ast.Module) -> None:
30
30
  """Save registry for each module."""
31
+ module_name = node.name
31
32
  module_dir = os.path.join(
32
33
  os.path.abspath(os.path.dirname(node.source.file_path)), Con.JAC_GEN_DIR
33
34
  )
34
- module_name = node.name
35
35
  os.makedirs(module_dir, exist_ok=True)
36
36
  with open(os.path.join(module_dir, f"{module_name}.registry.pkl"), "wb") as f:
37
37
  pickle.dump(node.registry, f)
@@ -68,9 +68,7 @@ class RegistryPass(Pass):
68
68
  def exit_has_var(self, node: ast.HasVar) -> None:
69
69
  """Save variable information."""
70
70
  extracted_type = (
71
- "".join(self.extract_type(node.type_tag.kid[1:][0]))
72
- if node.type_tag
73
- else None
71
+ "".join(self.extract_type(node.type_tag.tag)) if node.type_tag else None
74
72
  )
75
73
  scope = get_sem_scope(node)
76
74
  seminfo = SemInfo(
@@ -87,9 +85,7 @@ class RegistryPass(Pass):
87
85
  return
88
86
 
89
87
  extracted_type = (
90
- "".join(self.extract_type(node.type_tag.kid[1:][0]))
91
- if node.type_tag
92
- else None
88
+ "".join(self.extract_type(node.type_tag.tag)) if node.type_tag else None
93
89
  )
94
90
  scope = get_sem_scope(node)
95
91
  seminfo = SemInfo(
@@ -57,6 +57,8 @@ class PyastGenPassTests(TestCaseMicroSuite, AstSyncTestMixin):
57
57
  captured_output = io.StringIO()
58
58
  sys.stdout = captured_output
59
59
  module = types.ModuleType("__main__")
60
+ module.__dict__["__file__"] = code_gen.ir.loc.mod_path
61
+ module.__dict__["__jac_mod_bundle__"] = None
60
62
  exec(prog, module.__dict__)
61
63
  sys.stdout = sys.__stdout__
62
64
  stdout_value = captured_output.getvalue()
@@ -33,7 +33,10 @@ class JacTypeCheckPass(Pass):
33
33
 
34
34
  def after_pass(self) -> None:
35
35
  """Call mypy api after traversing all the modules."""
36
- self.api()
36
+ try:
37
+ self.api()
38
+ except Exception as e:
39
+ self.error(f"Unable to run type checking: {e}")
37
40
  return super().after_pass()
38
41
 
39
42
  def default_message_cb(
@@ -20,6 +20,11 @@ class JacFormatPass(Pass):
20
20
  self.indent_level = 0
21
21
  self.MAX_LINE_LENGTH = 44
22
22
 
23
+ def enter_node(self, node: ast.AstNode) -> None:
24
+ """Enter node."""
25
+ node.gen.jac = ""
26
+ super().enter_node(node)
27
+
23
28
  def indent_str(self) -> str:
24
29
  """Return string for indent."""
25
30
  return " " * self.indent_size * self.indent_level
@@ -337,6 +342,8 @@ class JacFormatPass(Pass):
337
342
  else:
338
343
  self.emit_ln(node, "")
339
344
  self.emit_ln(node, i.gen.jac)
345
+ if isinstance(i, ast.Token) and i.name == Tok.KW_BY:
346
+ self.emit(node, f"{i.gen.jac} ")
340
347
  else:
341
348
  self.emit(node, i.gen.jac)
342
349
  if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):