jaclang 0.5.7__py3-none-any.whl → 0.5.9__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 (49) hide show
  1. jaclang/cli/cli.py +113 -7
  2. jaclang/cli/cmdreg.py +12 -0
  3. jaclang/compiler/__init__.py +58 -2
  4. jaclang/compiler/absyntree.py +1775 -61
  5. jaclang/compiler/codeloc.py +7 -0
  6. jaclang/compiler/compile.py +1 -1
  7. jaclang/compiler/constant.py +17 -0
  8. jaclang/compiler/parser.py +134 -112
  9. jaclang/compiler/passes/ir_pass.py +18 -0
  10. jaclang/compiler/passes/main/__init__.py +2 -0
  11. jaclang/compiler/passes/main/def_impl_match_pass.py +19 -3
  12. jaclang/compiler/passes/main/def_use_pass.py +1 -1
  13. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +357 -0
  14. jaclang/compiler/passes/main/import_pass.py +7 -3
  15. jaclang/compiler/passes/main/pyast_gen_pass.py +350 -109
  16. jaclang/compiler/passes/main/pyast_load_pass.py +1779 -206
  17. jaclang/compiler/passes/main/registry_pass.py +126 -0
  18. jaclang/compiler/passes/main/schedules.py +4 -1
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +20 -28
  20. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +14 -5
  21. jaclang/compiler/passes/main/tests/test_registry_pass.py +39 -0
  22. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +8 -8
  23. jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +7 -0
  24. jaclang/compiler/passes/main/type_check_pass.py +0 -1
  25. jaclang/compiler/passes/tool/jac_formatter_pass.py +8 -17
  26. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +65 -0
  27. jaclang/compiler/passes/utils/mypy_ast_build.py +28 -14
  28. jaclang/compiler/symtable.py +23 -2
  29. jaclang/compiler/tests/test_parser.py +53 -0
  30. jaclang/compiler/workspace.py +52 -26
  31. jaclang/core/aott.py +193 -28
  32. jaclang/core/construct.py +59 -2
  33. jaclang/core/registry.py +115 -0
  34. jaclang/core/utils.py +25 -0
  35. jaclang/plugin/default.py +108 -26
  36. jaclang/plugin/feature.py +22 -4
  37. jaclang/plugin/spec.py +13 -7
  38. jaclang/utils/helpers.py +66 -3
  39. jaclang/utils/lang_tools.py +6 -38
  40. jaclang/utils/test.py +1 -0
  41. jaclang/utils/tests/test_lang_tools.py +11 -14
  42. jaclang/utils/treeprinter.py +10 -2
  43. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/METADATA +1 -1
  44. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/RECORD +47 -43
  45. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/WHEEL +1 -1
  46. jaclang/compiler/__jac_gen__/__init__.py +0 -0
  47. jaclang/compiler/__jac_gen__/jac_parser.py +0 -4069
  48. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/entry_points.txt +0 -0
  49. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/top_level.txt +0 -0
@@ -6,10 +6,18 @@ import ast as ast3
6
6
  from types import EllipsisType
7
7
  from typing import Any, Callable, Generic, Optional, Sequence, Type, TypeVar
8
8
 
9
+ from jaclang.compiler import TOKEN_MAP
9
10
  from jaclang.compiler.codeloc import CodeGenTarget, CodeLocInfo
10
11
  from jaclang.compiler.constant import Constants as Con, EdgeDir
11
- from jaclang.compiler.constant import Tokens as Tok
12
- from jaclang.compiler.symtable import Symbol, SymbolAccess, SymbolTable, SymbolType
12
+ from jaclang.compiler.constant import DELIM_MAP, Tokens as Tok
13
+ from jaclang.compiler.symtable import (
14
+ Symbol,
15
+ SymbolAccess,
16
+ SymbolInfo,
17
+ SymbolTable,
18
+ SymbolType,
19
+ )
20
+ from jaclang.core.registry import SemRegistry
13
21
  from jaclang.utils.treeprinter import dotgen_ast_tree, print_ast_tree
14
22
 
15
23
 
@@ -74,12 +82,46 @@ class AstNode:
74
82
  else:
75
83
  raise ValueError(f"Empty kid for Token {type(self).__name__}")
76
84
 
85
+ def gen_token(self, name: Tok, value: Optional[str] = None) -> Token:
86
+ """Generate token."""
87
+ value = (
88
+ value
89
+ if value
90
+ else (
91
+ DELIM_MAP[name]
92
+ if name in DELIM_MAP
93
+ else TOKEN_MAP[name.value] if name.value in TOKEN_MAP else name.value
94
+ )
95
+ )
96
+ return Token(
97
+ name=name,
98
+ value=value,
99
+ file_path=self.loc.mod_path,
100
+ col_start=self.loc.col_start,
101
+ col_end=0,
102
+ line=self.loc.first_line,
103
+ pos_start=0,
104
+ pos_end=0,
105
+ )
106
+
77
107
  def get_all_sub_nodes(self, typ: Type[T], brute_force: bool = True) -> list[T]:
78
108
  """Get all sub nodes of type."""
79
109
  from jaclang.compiler.passes import Pass
80
110
 
81
111
  return Pass.get_all_sub_nodes(node=self, typ=typ, brute_force=brute_force)
82
112
 
113
+ def has_parent_of_type(self, typ: Type[T]) -> Optional[T]:
114
+ """Get parent of type."""
115
+ from jaclang.compiler.passes import Pass
116
+
117
+ return Pass.has_parent_of_type(node=self, typ=typ)
118
+
119
+ def format(self) -> str:
120
+ """Get all sub nodes of type."""
121
+ from jaclang.compiler.passes.tool import JacFormatPass
122
+
123
+ return JacFormatPass(self, None).ir.gen.jac
124
+
83
125
  def to_dict(self) -> dict[str, str]:
84
126
  """Return dict representation of node."""
85
127
  ret = {
@@ -108,6 +150,18 @@ class AstNode:
108
150
  ret += k.flatten()
109
151
  return ret
110
152
 
153
+ def normalize(self, deep: bool = False) -> bool:
154
+ """Normalize ast node."""
155
+ return False
156
+
157
+ def unparse(self) -> str:
158
+ """Unparse ast node."""
159
+ valid = self.normalize()
160
+ res = " ".join([i.unparse() for i in self.kid])
161
+ if not valid:
162
+ raise NotImplementedError(f"Node {type(self).__name__} is not valid.")
163
+ return res
164
+
111
165
 
112
166
  class AstSymbolNode(AstNode):
113
167
  """Nodes that have link to a symbol in symbol table."""
@@ -120,6 +174,7 @@ class AstSymbolNode(AstNode):
120
174
  self.sym_name: str = sym_name
121
175
  self.sym_name_node = sym_name_node
122
176
  self.sym_type: SymbolType = sym_type
177
+ self.sym_info: SymbolInfo = SymbolInfo()
123
178
  self.py_ctx_func: Type[ast3.AST] = ast3.Load
124
179
 
125
180
 
@@ -144,6 +199,9 @@ class AstAccessNode(AstNode):
144
199
  )
145
200
 
146
201
 
202
+ T = TypeVar("T", bound=AstNode)
203
+
204
+
147
205
  class AstDocNode(AstNode):
148
206
  """Nodes that have access."""
149
207
 
@@ -195,11 +253,25 @@ class WalkerStmtOnlyNode(AstNode):
195
253
  class AstImplOnlyNode(AstNode):
196
254
  """ImplOnly node type for Jac Ast."""
197
255
 
198
- def __init__(self, decl_link: Optional[AstNode]) -> None:
256
+ def __init__(self, body: SubNodeList, decl_link: Optional[AstNode]) -> None:
199
257
  """Initialize impl only node."""
258
+ self.body = body
200
259
  self.decl_link = decl_link
201
260
 
202
261
 
262
+ class AstImplNeedingNode(AstSymbolNode, Generic[T]):
263
+ """Impl needing node type for Jac Ast."""
264
+
265
+ def __init__(self, body: Optional[T]) -> None:
266
+ """Initialize impl needing node."""
267
+ self.body = body
268
+
269
+ @property
270
+ def needs_impl(self) -> bool:
271
+ """Need impl."""
272
+ return self.body is None
273
+
274
+
203
275
  class Expr(AstNode):
204
276
  """Expr node type for Jac Ast."""
205
277
 
@@ -240,9 +312,6 @@ class MatchPattern(AstNode):
240
312
  """MatchPattern node type for Jac Ast."""
241
313
 
242
314
 
243
- T = TypeVar("T", bound=AstNode)
244
-
245
-
246
315
  class SubTag(AstNode, Generic[T]):
247
316
  """SubTag node type for Jac Ast."""
248
317
 
@@ -255,22 +324,54 @@ class SubTag(AstNode, Generic[T]):
255
324
  self.tag = tag
256
325
  AstNode.__init__(self, kid=kid)
257
326
 
327
+ def normalize(self, deep: bool = False) -> bool:
328
+ """Normalize sub tag node."""
329
+ res = self.tag.normalize() if deep else True
330
+ AstNode.set_kids(self, nodes=[self.gen_token(Tok.COLON), self.tag])
331
+ return res
332
+
258
333
 
259
334
  # SubNodeList were created to simplify the type safety of the
260
335
  # parser's implementation. We basically need to maintain tokens
261
- # in the kid list as well as separating out items of interest in
262
- # the ast node class body.
336
+ # of mixed type in the kid list of the subnodelist as well as
337
+ # separating out typed items of interest in the ast node class body.
263
338
  class SubNodeList(AstNode, Generic[T]):
264
339
  """SubNodeList node type for Jac Ast."""
265
340
 
266
341
  def __init__(
267
342
  self,
268
343
  items: list[T],
344
+ delim: Optional[Tok],
269
345
  kid: Sequence[AstNode],
346
+ left_enc: Optional[Token] = None,
347
+ right_enc: Optional[Token] = None,
270
348
  ) -> None:
271
349
  """Initialize sub node list node."""
272
350
  self.items = items
273
- AstNode.__init__(self, kid=kid)
351
+ self.delim = delim
352
+ self.left_enc = left_enc
353
+ self.right_enc = right_enc
354
+ AstNode.__init__(self, kid=kid)
355
+
356
+ def normalize(self, deep: bool = False) -> bool:
357
+ """Normalize sub node list node."""
358
+ res = True
359
+ if deep:
360
+ for i in self.items:
361
+ res = res and i.normalize()
362
+ new_kid: list[AstNode] = []
363
+ if self.left_enc:
364
+ new_kid.append(self.left_enc)
365
+ for i in self.items:
366
+ new_kid.append(i)
367
+ if self.delim:
368
+ new_kid.append(self.gen_token(self.delim))
369
+ if self.delim and self.items:
370
+ new_kid.pop()
371
+ if self.right_enc:
372
+ new_kid.append(self.right_enc)
373
+ AstNode.set_kids(self, nodes=new_kid if len(new_kid) else [EmptyToken()])
374
+ return res
274
375
 
275
376
 
276
377
  # AST Mid Level Node Types
@@ -288,6 +389,7 @@ class Module(AstDocNode):
288
389
  kid: Sequence[AstNode],
289
390
  impl_mod: Optional[Module] = None,
290
391
  test_mod: Optional[Module] = None,
392
+ registry: Optional[SemRegistry] = None,
291
393
  ) -> None:
292
394
  """Initialize whole program node."""
293
395
  self.name = name
@@ -297,9 +399,29 @@ class Module(AstDocNode):
297
399
  self.impl_mod = impl_mod
298
400
  self.test_mod = test_mod
299
401
  self.mod_deps: dict[str, Module] = {}
402
+ self.registry = registry
300
403
  AstNode.__init__(self, kid=kid)
301
404
  AstDocNode.__init__(self, doc=doc)
302
405
 
406
+ def normalize(self, deep: bool = False) -> bool:
407
+ """Normalize module node."""
408
+ res = True
409
+ if deep:
410
+ res = self.doc.normalize() if self.doc else True
411
+ for i in self.body:
412
+ res = res and i.normalize()
413
+ new_kid: list[AstNode] = []
414
+ if self.doc:
415
+ new_kid.append(self.doc)
416
+ new_kid.extend(self.body)
417
+ AstNode.set_kids(self, nodes=new_kid)
418
+ return res
419
+
420
+ def unparse(self) -> str:
421
+ """Unparse module node."""
422
+ super().unparse()
423
+ return self.format()
424
+
303
425
 
304
426
  class GlobalVars(ElementStmt, AstAccessNode):
305
427
  """GlobalVars node type for Jac Ast."""
@@ -319,6 +441,26 @@ class GlobalVars(ElementStmt, AstAccessNode):
319
441
  AstAccessNode.__init__(self, access=access)
320
442
  AstDocNode.__init__(self, doc=doc)
321
443
 
444
+ def normalize(self, deep: bool = False) -> bool:
445
+ """Normalize global var node."""
446
+ res = True
447
+ if deep:
448
+ res = self.access.normalize(deep) if self.access else True
449
+ res = res and self.assignments.normalize(deep)
450
+ res = res and self.doc.normalize(deep) if self.doc else res
451
+ new_kid: list[AstNode] = []
452
+ if self.doc:
453
+ new_kid.append(self.doc)
454
+ if self.is_frozen:
455
+ new_kid.append(self.gen_token(Tok.KW_LET))
456
+ else:
457
+ new_kid.append(self.gen_token(Tok.KW_GLOBAL))
458
+ if self.access:
459
+ new_kid.append(self.access)
460
+ new_kid.append(self.assignments)
461
+ AstNode.set_kids(self, nodes=new_kid)
462
+ return res
463
+
322
464
 
323
465
  class Test(AstSymbolNode, ElementStmt):
324
466
  """Test node type for Jac Ast."""
@@ -346,7 +488,6 @@ class Test(AstSymbolNode, ElementStmt):
346
488
  line=name.loc.first_line,
347
489
  pos_start=name.pos_start,
348
490
  pos_end=name.pos_end,
349
- kid=name.kid,
350
491
  )
351
492
  )
352
493
  self.name.parent = self
@@ -363,8 +504,24 @@ class Test(AstSymbolNode, ElementStmt):
363
504
  )
364
505
  AstDocNode.__init__(self, doc=doc)
365
506
 
366
-
367
- class ModuleCode(ElementStmt):
507
+ def normalize(self, deep: bool = False) -> bool:
508
+ """Normalize test node."""
509
+ res = True
510
+ if deep:
511
+ res = self.name.normalize(deep)
512
+ res = res and self.body.normalize(deep)
513
+ res = res and self.doc.normalize(deep) if self.doc else res
514
+ new_kid: list[AstNode] = []
515
+ if self.doc:
516
+ new_kid.append(self.doc)
517
+ new_kid.append(self.gen_token(Tok.KW_TEST))
518
+ new_kid.append(self.name)
519
+ new_kid.append(self.body)
520
+ AstNode.set_kids(self, nodes=new_kid)
521
+ return res
522
+
523
+
524
+ class ModuleCode(ElementStmt, ArchBlockStmt, EnumBlockStmt):
368
525
  """Free mod code for Jac Ast."""
369
526
 
370
527
  def __init__(
@@ -380,6 +537,24 @@ class ModuleCode(ElementStmt):
380
537
  AstNode.__init__(self, kid=kid)
381
538
  AstDocNode.__init__(self, doc=doc)
382
539
 
540
+ def normalize(self, deep: bool = False) -> bool:
541
+ """Normalize module code node."""
542
+ res = True
543
+ if deep:
544
+ res = self.name.normalize(deep) if self.name else res
545
+ res = res and self.body.normalize(deep)
546
+ res = res and self.doc.normalize(deep) if self.doc else res
547
+ new_kid: list[AstNode] = []
548
+ if self.doc:
549
+ new_kid.append(self.doc)
550
+ new_kid.append(self.gen_token(Tok.KW_WITH))
551
+ new_kid.append(self.gen_token(Tok.KW_ENTRY))
552
+ if self.name:
553
+ new_kid.append(self.name)
554
+ new_kid.append(self.body)
555
+ AstNode.set_kids(self, nodes=new_kid)
556
+ return res
557
+
383
558
 
384
559
  class PyInlineCode(ElementStmt, ArchBlockStmt, EnumBlockStmt, CodeBlockStmt):
385
560
  """Inline Python code node type for Jac Ast."""
@@ -395,6 +570,21 @@ class PyInlineCode(ElementStmt, ArchBlockStmt, EnumBlockStmt, CodeBlockStmt):
395
570
  AstNode.__init__(self, kid=kid)
396
571
  AstDocNode.__init__(self, doc=doc)
397
572
 
573
+ def normalize(self, deep: bool = False) -> bool:
574
+ """Normalize inline python code node."""
575
+ res = True
576
+ if deep:
577
+ res = self.code.normalize(deep)
578
+ res = res and self.doc.normalize(deep) if self.doc else res
579
+ new_kid: list[AstNode] = []
580
+ if self.doc:
581
+ new_kid.append(self.doc)
582
+ new_kid.append(self.gen_token(Tok.PYNLINE))
583
+ new_kid.append(self.code)
584
+ new_kid.append(self.gen_token(Tok.PYNLINE))
585
+ AstNode.set_kids(self, nodes=new_kid)
586
+ return res
587
+
398
588
 
399
589
  class Import(ElementStmt, CodeBlockStmt):
400
590
  """Import node type for Jac Ast."""
@@ -416,6 +606,36 @@ class Import(ElementStmt, CodeBlockStmt):
416
606
  AstNode.__init__(self, kid=kid)
417
607
  AstDocNode.__init__(self, doc=doc)
418
608
 
609
+ def normalize(self, deep: bool = False) -> bool:
610
+ """Normalize import node."""
611
+ res = True
612
+ if deep:
613
+ res = self.lang.normalize(deep)
614
+ for p in self.paths:
615
+ res = res and p.normalize(deep)
616
+ res = res and self.items.normalize(deep) if self.items else res
617
+ res = res and self.doc.normalize(deep) if self.doc else res
618
+ new_kid: list[AstNode] = []
619
+ if self.doc:
620
+ new_kid.append(self.doc)
621
+ if self.is_absorb:
622
+ new_kid.append(self.gen_token(Tok.KW_INCLUDE))
623
+ else:
624
+ new_kid.append(self.gen_token(Tok.KW_IMPORT))
625
+ new_kid.append(self.lang)
626
+ if self.items:
627
+ new_kid.append(self.gen_token(Tok.KW_FROM))
628
+ for p in self.paths:
629
+ new_kid.append(p)
630
+ new_kid.append(self.gen_token(Tok.COMMA))
631
+ new_kid.pop()
632
+ if self.items:
633
+ new_kid.append(self.gen_token(Tok.COMMA))
634
+ new_kid.append(self.items)
635
+ new_kid.append(self.gen_token(Tok.SEMI))
636
+ AstNode.set_kids(self, nodes=new_kid)
637
+ return res
638
+
419
639
 
420
640
  class ModulePath(AstSymbolNode):
421
641
  """ModulePath node type for Jac Ast."""
@@ -442,6 +662,29 @@ class ModulePath(AstSymbolNode):
442
662
  sym_type=SymbolType.MODULE,
443
663
  )
444
664
 
665
+ def normalize(self, deep: bool = False) -> bool:
666
+ """Normalize module path node."""
667
+ res = True
668
+ if deep:
669
+ if self.path:
670
+ for p in self.path:
671
+ res = res and p.normalize(deep)
672
+ res = res and self.alias.normalize(deep) if self.alias else res
673
+ new_kid: list[AstNode] = []
674
+ # for _ in range(self.level):
675
+ # new_kid.append(self.gen_token(Tok.DOT))
676
+ if self.path:
677
+ for p in self.path:
678
+ res = res and p.normalize(deep)
679
+ new_kid.append(p)
680
+ new_kid.append(self.gen_token(Tok.DOT))
681
+ new_kid.pop()
682
+ if self.alias:
683
+ res = res and self.alias.normalize(deep)
684
+ new_kid.append(self.alias)
685
+ AstNode.set_kids(self, nodes=new_kid)
686
+ return res
687
+
445
688
  @property
446
689
  def path_str(self) -> str:
447
690
  """Get path string."""
@@ -470,8 +713,21 @@ class ModuleItem(AstSymbolNode):
470
713
  sym_type=SymbolType.MOD_VAR,
471
714
  )
472
715
 
473
-
474
- class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
716
+ def normalize(self, deep: bool = False) -> bool:
717
+ """Normalize module item node."""
718
+ res = True
719
+ if deep:
720
+ res = res and self.name.normalize(deep)
721
+ res = res and self.alias.normalize(deep) if self.alias else res
722
+ new_kid: list[AstNode] = [self.name]
723
+ if self.alias:
724
+ new_kid.append(self.gen_token(Tok.KW_AS))
725
+ new_kid.append(self.alias)
726
+ AstNode.set_kids(self, nodes=new_kid)
727
+ return res
728
+
729
+
730
+ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt, AstImplNeedingNode):
475
731
  """ObjectArch node type for Jac Ast."""
476
732
 
477
733
  def __init__(
@@ -490,7 +746,6 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
490
746
  self.name = name
491
747
  self.arch_type = arch_type
492
748
  self.base_classes = base_classes
493
- self.body = body
494
749
  AstNode.__init__(self, kid=kid)
495
750
  AstSymbolNode.__init__(
496
751
  self,
@@ -514,6 +769,7 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
514
769
  )
515
770
  ),
516
771
  )
772
+ AstImplNeedingNode.__init__(self, body=body)
517
773
  AstAccessNode.__init__(self, access=access)
518
774
  AstDocNode.__init__(self, doc=doc)
519
775
  AstSemStrNode.__init__(self, semstr=semstr)
@@ -529,6 +785,46 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
529
785
  )
530
786
  return any(isinstance(i, Ability) and i.is_abstract for i in body)
531
787
 
788
+ def normalize(self, deep: bool = False) -> bool:
789
+ """Normalize architype node."""
790
+ res = True
791
+ if deep:
792
+ res = self.name.normalize(deep)
793
+ res = res and self.arch_type.normalize(deep)
794
+ res = res and self.access.normalize(deep) if self.access else res
795
+ res = (
796
+ res and self.base_classes.normalize(deep) if self.base_classes else res
797
+ )
798
+ res = res and self.body.normalize(deep) if self.body else res
799
+ res = res and self.doc.normalize(deep) if self.doc else res
800
+ res = res and self.semstr.normalize(deep) if self.semstr else res
801
+ res = res and self.decorators.normalize(deep) if self.decorators else res
802
+ new_kid: list[AstNode] = []
803
+ if self.doc:
804
+ new_kid.append(self.doc)
805
+ if self.decorators:
806
+ new_kid.append(self.gen_token(Tok.DECOR_OP))
807
+ new_kid.append(self.decorators)
808
+ new_kid.append(self.arch_type)
809
+ if self.access:
810
+ new_kid.append(self.access)
811
+ if self.semstr:
812
+ new_kid.append(self.semstr)
813
+ new_kid.append(self.name)
814
+ if self.base_classes:
815
+ new_kid.append(self.gen_token(Tok.COLON))
816
+ new_kid.append(self.base_classes)
817
+ new_kid.append(self.gen_token(Tok.COLON))
818
+ if self.body:
819
+ if isinstance(self.body, AstImplOnlyNode):
820
+ new_kid.append(self.gen_token(Tok.SEMI))
821
+ else:
822
+ new_kid.append(self.body)
823
+ else:
824
+ new_kid.append(self.gen_token(Tok.SEMI))
825
+ AstNode.set_kids(self, nodes=new_kid)
826
+ return res
827
+
532
828
 
533
829
  class ArchDef(ArchSpec, AstImplOnlyNode):
534
830
  """ArchDef node type for Jac Ast."""
@@ -544,7 +840,6 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
544
840
  ) -> None:
545
841
  """Initialize arch def node."""
546
842
  self.target = target
547
- self.body = body
548
843
  AstNode.__init__(self, kid=kid)
549
844
  AstSymbolNode.__init__(
550
845
  self,
@@ -554,10 +849,26 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
554
849
  )
555
850
  AstDocNode.__init__(self, doc=doc)
556
851
  ArchSpec.__init__(self, decorators=decorators)
557
- AstImplOnlyNode.__init__(self, decl_link=decl_link)
558
-
559
-
560
- class Enum(ArchSpec, AstAccessNode):
852
+ AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
853
+
854
+ def normalize(self, deep: bool = False) -> bool:
855
+ """Normalize arch def node."""
856
+ res = True
857
+ if deep:
858
+ res = self.target.normalize(deep)
859
+ res = res and self.body.normalize(deep)
860
+ res = res and self.doc.normalize(deep) if self.doc else res
861
+ res = res and self.decorators.normalize(deep) if self.decorators else res
862
+ new_kid: list[AstNode] = []
863
+ if self.doc:
864
+ new_kid.append(self.doc)
865
+ new_kid.append(self.target)
866
+ new_kid.append(self.body)
867
+ AstNode.set_kids(self, nodes=new_kid)
868
+ return res
869
+
870
+
871
+ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt):
561
872
  """Enum node type for Jac Ast."""
562
873
 
563
874
  def __init__(
@@ -574,7 +885,6 @@ class Enum(ArchSpec, AstAccessNode):
574
885
  """Initialize object arch node."""
575
886
  self.name = name
576
887
  self.base_classes = base_classes
577
- self.body = body
578
888
  AstNode.__init__(self, kid=kid)
579
889
  AstSymbolNode.__init__(
580
890
  self,
@@ -582,11 +892,50 @@ class Enum(ArchSpec, AstAccessNode):
582
892
  sym_name_node=name,
583
893
  sym_type=SymbolType.ENUM_ARCH,
584
894
  )
895
+ AstImplNeedingNode.__init__(self, body=body)
585
896
  AstAccessNode.__init__(self, access=access)
586
897
  AstDocNode.__init__(self, doc=doc)
587
898
  AstSemStrNode.__init__(self, semstr=semstr)
588
899
  ArchSpec.__init__(self, decorators=decorators)
589
900
 
901
+ def normalize(self, deep: bool = False) -> bool:
902
+ """Normalize enum node."""
903
+ res = True
904
+ if deep:
905
+ res = self.name.normalize(deep)
906
+ res = res and self.access.normalize(deep) if self.access else res
907
+ res = (
908
+ res and self.base_classes.normalize(deep) if self.base_classes else res
909
+ )
910
+ res = res and self.body.normalize(deep) if self.body else res
911
+ res = res and self.doc.normalize(deep) if self.doc else res
912
+ res = res and self.semstr.normalize(deep) if self.semstr else res
913
+ res = res and self.decorators.normalize(deep) if self.decorators else res
914
+ new_kid: list[AstNode] = []
915
+ if self.doc:
916
+ new_kid.append(self.doc)
917
+ new_kid.append(self.gen_token(Tok.KW_ENUM))
918
+ if self.access:
919
+ new_kid.append(self.access)
920
+ if self.semstr:
921
+ new_kid.append(self.semstr)
922
+ new_kid.append(self.name)
923
+ if self.base_classes:
924
+ new_kid.append(self.gen_token(Tok.COLON))
925
+ new_kid.append(self.base_classes)
926
+ new_kid.append(self.gen_token(Tok.COLON))
927
+ if self.body:
928
+ if isinstance(self.body, AstImplOnlyNode):
929
+ new_kid.append(self.gen_token(Tok.SEMI))
930
+ else:
931
+ new_kid.append(self.gen_token(Tok.LBRACE))
932
+ new_kid.append(self.body)
933
+ new_kid.append(self.gen_token(Tok.RBRACE))
934
+ else:
935
+ new_kid.append(self.gen_token(Tok.SEMI))
936
+ AstNode.set_kids(self, nodes=new_kid)
937
+ return res
938
+
590
939
 
591
940
  class EnumDef(ArchSpec, AstImplOnlyNode):
592
941
  """EnumDef node type for Jac Ast."""
@@ -602,7 +951,6 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
602
951
  ) -> None:
603
952
  """Initialize arch def node."""
604
953
  self.target = target
605
- self.body = body
606
954
  AstNode.__init__(self, kid=kid)
607
955
  AstSymbolNode.__init__(
608
956
  self,
@@ -612,24 +960,41 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
612
960
  )
613
961
  AstDocNode.__init__(self, doc=doc)
614
962
  ArchSpec.__init__(self, decorators=decorators)
615
- AstImplOnlyNode.__init__(self, decl_link=decl_link)
963
+ AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
964
+
965
+ def normalize(self, deep: bool = False) -> bool:
966
+ """Normalize enum def node."""
967
+ res = True
968
+ if deep:
969
+ res = self.target.normalize(deep)
970
+ res = res and self.body.normalize(deep)
971
+ res = res and self.doc.normalize(deep) if self.doc else res
972
+ res = res and self.decorators.normalize(deep) if self.decorators else res
973
+ new_kid: list[AstNode] = []
974
+ if self.doc:
975
+ new_kid.append(self.doc)
976
+ new_kid.append(self.target)
977
+ new_kid.append(self.gen_token(Tok.LBRACE))
978
+ new_kid.append(self.body)
979
+ new_kid.append(self.gen_token(Tok.RBRACE))
980
+ AstNode.set_kids(self, nodes=new_kid)
981
+ return res
616
982
 
617
983
 
618
984
  class Ability(
619
- AstSymbolNode,
620
985
  AstAccessNode,
621
986
  ElementStmt,
622
987
  AstAsyncNode,
623
988
  ArchBlockStmt,
624
989
  CodeBlockStmt,
625
990
  AstSemStrNode,
991
+ AstImplNeedingNode,
626
992
  ):
627
993
  """Ability node type for Jac Ast."""
628
994
 
629
995
  def __init__(
630
996
  self,
631
997
  name_ref: NameSpec,
632
- is_func: bool,
633
998
  is_async: bool,
634
999
  is_override: bool,
635
1000
  is_static: bool,
@@ -644,14 +1009,13 @@ class Ability(
644
1009
  ) -> None:
645
1010
  """Initialize func arch node."""
646
1011
  self.name_ref = name_ref
647
- self.is_func = is_func
648
1012
  self.is_override = is_override
649
1013
  self.is_static = is_static
650
1014
  self.is_abstract = is_abstract
651
1015
  self.decorators = decorators
652
1016
  self.signature = signature
653
- self.body = body
654
1017
  AstNode.__init__(self, kid=kid)
1018
+ AstImplNeedingNode.__init__(self, body=body)
655
1019
  AstSemStrNode.__init__(self, semstr=semstr)
656
1020
  AstSymbolNode.__init__(
657
1021
  self,
@@ -673,6 +1037,11 @@ class Ability(
673
1037
  self.sym_type = SymbolType.METHOD
674
1038
  return check
675
1039
 
1040
+ @property
1041
+ def is_func(self) -> bool:
1042
+ """Check if is func."""
1043
+ return isinstance(self.body, FuncSignature)
1044
+
676
1045
  @property
677
1046
  def is_genai_ability(self) -> bool:
678
1047
  """Check if is genai_ability."""
@@ -687,6 +1056,54 @@ class Ability(
687
1056
  else:
688
1057
  raise NotImplementedError
689
1058
 
1059
+ def normalize(self, deep: bool = False) -> bool:
1060
+ """Normalize ast node."""
1061
+ res = True
1062
+ if deep:
1063
+ res = self.name_ref.normalize(deep)
1064
+ res = res and self.access.normalize(deep) if self.access else res
1065
+ res = res and self.signature.normalize(deep) if self.signature else res
1066
+ res = res and self.body.normalize(deep) if self.body else res
1067
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1068
+ res = res and self.decorators.normalize(deep) if self.decorators else res
1069
+ res = res and self.doc.normalize(deep) if self.doc else res
1070
+ new_kid: list[AstNode] = []
1071
+ if self.doc:
1072
+ new_kid.append(self.doc)
1073
+ if self.decorators:
1074
+ new_kid.append(self.gen_token(Tok.DECOR_OP))
1075
+ new_kid.append(self.decorators)
1076
+ new_kid.append(self.gen_token(Tok.WS))
1077
+ if self.is_async:
1078
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1079
+ if self.is_override:
1080
+ new_kid.append(self.gen_token(Tok.KW_OVERRIDE))
1081
+ if self.is_static:
1082
+ new_kid.append(self.gen_token(Tok.KW_STATIC))
1083
+ new_kid.append(self.gen_token(Tok.KW_CAN))
1084
+ if self.access:
1085
+ new_kid.append(self.access)
1086
+ if self.semstr:
1087
+ new_kid.append(self.semstr)
1088
+ new_kid.append(self.name_ref)
1089
+ if self.signature:
1090
+ new_kid.append(self.signature)
1091
+ if self.is_genai_ability:
1092
+ new_kid.append(self.gen_token(Tok.KW_BY))
1093
+ if self.is_abstract:
1094
+ new_kid.append(self.gen_token(Tok.KW_ABSTRACT))
1095
+ if self.body:
1096
+ if isinstance(self.body, AstImplOnlyNode):
1097
+ new_kid.append(self.gen_token(Tok.SEMI))
1098
+ else:
1099
+ new_kid.append(self.body)
1100
+ if self.is_genai_ability:
1101
+ new_kid.append(self.gen_token(Tok.SEMI))
1102
+ else:
1103
+ new_kid.append(self.gen_token(Tok.SEMI))
1104
+ AstNode.set_kids(self, nodes=new_kid)
1105
+ return res
1106
+
690
1107
 
691
1108
  class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
692
1109
  """AbilityDef node type for Jac Ast."""
@@ -704,7 +1121,6 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
704
1121
  """Initialize ability def node."""
705
1122
  self.target = target
706
1123
  self.signature = signature
707
- self.body = body
708
1124
  self.decorators = decorators
709
1125
  AstNode.__init__(self, kid=kid)
710
1126
  AstSymbolNode.__init__(
@@ -714,7 +1130,27 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
714
1130
  sym_type=SymbolType.IMPL,
715
1131
  )
716
1132
  AstDocNode.__init__(self, doc=doc)
717
- AstImplOnlyNode.__init__(self, decl_link=decl_link)
1133
+ AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
1134
+
1135
+ def normalize(self, deep: bool = False) -> bool:
1136
+ """Normalize ability def node."""
1137
+ res = True
1138
+ if deep:
1139
+ res = self.target.normalize(deep)
1140
+ res = res and self.signature.normalize(deep)
1141
+ res = res and self.body.normalize(deep)
1142
+ res = res and self.doc.normalize(deep) if self.doc else res
1143
+ res = res and self.decorators.normalize(deep) if self.decorators else res
1144
+ new_kid: list[AstNode] = []
1145
+ if self.doc:
1146
+ new_kid.append(self.doc)
1147
+ new_kid.append(self.target)
1148
+ new_kid.append(self.signature)
1149
+
1150
+ new_kid.append(self.body)
1151
+
1152
+ AstNode.set_kids(self, nodes=new_kid)
1153
+ return res
718
1154
 
719
1155
  @property
720
1156
  def is_method(self) -> bool:
@@ -741,6 +1177,26 @@ class FuncSignature(AstSemStrNode):
741
1177
  AstNode.__init__(self, kid=kid)
742
1178
  AstSemStrNode.__init__(self, semstr=semstr)
743
1179
 
1180
+ def normalize(self, deep: bool = False) -> bool:
1181
+ """Normalize ast node."""
1182
+ res = True
1183
+ if deep:
1184
+ res = self.params.normalize(deep) if self.params else res
1185
+ res = res and self.return_type.normalize(deep) if self.return_type else res
1186
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1187
+ new_kid: list[AstNode] = [self.gen_token(Tok.LPAREN)]
1188
+ if self.params:
1189
+ new_kid.append(self.params)
1190
+ new_kid.append(self.gen_token(Tok.RPAREN))
1191
+ if self.return_type:
1192
+ new_kid.append(self.gen_token(Tok.RETURN_HINT))
1193
+ if self.semstr:
1194
+ new_kid.append(self.semstr)
1195
+ new_kid.append(self.gen_token(Tok.COLON))
1196
+ new_kid.append(self.return_type)
1197
+ AstNode.set_kids(self, nodes=new_kid)
1198
+ return res
1199
+
744
1200
  @property
745
1201
  def is_method(self) -> bool:
746
1202
  """Check if is method."""
@@ -776,6 +1232,30 @@ class EventSignature(AstSemStrNode):
776
1232
  AstNode.__init__(self, kid=kid)
777
1233
  AstSemStrNode.__init__(self, semstr=semstr)
778
1234
 
1235
+ def normalize(self, deep: bool = False) -> bool:
1236
+ """Normalize ast node."""
1237
+ res = True
1238
+ if deep:
1239
+ res = self.event.normalize(deep)
1240
+ res = (
1241
+ res and self.arch_tag_info.normalize(deep)
1242
+ if self.arch_tag_info
1243
+ else res
1244
+ )
1245
+ res = res and self.return_type.normalize(deep) if self.return_type else res
1246
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1247
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_WITH)]
1248
+ if self.arch_tag_info:
1249
+ new_kid.append(self.arch_tag_info)
1250
+ new_kid.append(self.event)
1251
+ if self.return_type:
1252
+ if self.semstr:
1253
+ new_kid.append(self.semstr)
1254
+ new_kid.append(self.gen_token(Tok.RETURN_HINT))
1255
+ new_kid.append(self.return_type)
1256
+ AstNode.set_kids(self, nodes=new_kid)
1257
+ return res
1258
+
779
1259
  @property
780
1260
  def is_method(self) -> bool:
781
1261
  """Check if is method."""
@@ -800,6 +1280,18 @@ class ArchRefChain(AstNode):
800
1280
  self.archs = archs
801
1281
  AstNode.__init__(self, kid=kid)
802
1282
 
1283
+ def normalize(self, deep: bool = False) -> bool:
1284
+ """Normalize ast node."""
1285
+ res = True
1286
+ if deep:
1287
+ for a in self.archs:
1288
+ res = res and a.normalize(deep)
1289
+ new_kid: list[AstNode] = []
1290
+ for a in self.archs:
1291
+ new_kid.append(a)
1292
+ AstNode.set_kids(self, nodes=new_kid)
1293
+ return res
1294
+
803
1295
  def py_resolve_name(self) -> str:
804
1296
  """Resolve name."""
805
1297
 
@@ -845,6 +1337,30 @@ class ParamVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
845
1337
  AstTypedVarNode.__init__(self, type_tag=type_tag)
846
1338
  AstSemStrNode.__init__(self, semstr=semstr)
847
1339
 
1340
+ def normalize(self, deep: bool = True) -> bool:
1341
+ """Normalize ast node."""
1342
+ res = True
1343
+ if deep:
1344
+ res = self.name.normalize(deep)
1345
+ res = res and self.unpack.normalize(deep) if self.unpack else res
1346
+ res = res and self.type_tag.normalize(deep) if self.type_tag else res
1347
+ res = res and self.value.normalize(deep) if self.value else res
1348
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1349
+ new_kid: list[AstNode] = []
1350
+ if self.unpack:
1351
+ new_kid.append(self.unpack)
1352
+ new_kid.append(self.name)
1353
+ if self.semstr:
1354
+ new_kid.append(self.gen_token(Tok.COLON))
1355
+ new_kid.append(self.semstr)
1356
+ if self.type_tag:
1357
+ new_kid.append(self.type_tag)
1358
+ if self.value:
1359
+ new_kid.append(self.gen_token(Tok.EQ))
1360
+ new_kid.append(self.value)
1361
+ AstNode.set_kids(self, nodes=new_kid)
1362
+ return res
1363
+
848
1364
 
849
1365
  class ArchHas(AstAccessNode, AstDocNode, ArchBlockStmt):
850
1366
  """HasStmt node type for Jac Ast."""
@@ -866,6 +1382,30 @@ class ArchHas(AstAccessNode, AstDocNode, ArchBlockStmt):
866
1382
  AstAccessNode.__init__(self, access=access)
867
1383
  AstDocNode.__init__(self, doc=doc)
868
1384
 
1385
+ def normalize(self, deep: bool = False) -> bool:
1386
+ """Normalize has statement node."""
1387
+ res = True
1388
+ if deep:
1389
+ res = self.access.normalize(deep) if self.access else res
1390
+ res = res and self.vars.normalize(deep) if self.vars else res
1391
+ res = res and self.doc.normalize(deep) if self.doc else res
1392
+ new_kid: list[AstNode] = []
1393
+ if self.doc:
1394
+ new_kid.append(self.doc)
1395
+ if self.is_static:
1396
+ new_kid.append(self.gen_token(Tok.KW_STATIC))
1397
+ (
1398
+ new_kid.append(self.gen_token(Tok.KW_LET))
1399
+ if self.is_frozen
1400
+ else new_kid.append(self.gen_token(Tok.KW_HAS))
1401
+ )
1402
+ if self.access:
1403
+ new_kid.append(self.access)
1404
+ new_kid.append(self.vars)
1405
+ new_kid.append(self.gen_token(Tok.SEMI))
1406
+ AstNode.set_kids(self, nodes=new_kid)
1407
+ return res
1408
+
869
1409
 
870
1410
  class HasVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
871
1411
  """HasVar node type for Jac Ast."""
@@ -893,6 +1433,29 @@ class HasVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
893
1433
  AstTypedVarNode.__init__(self, type_tag=type_tag)
894
1434
  AstSemStrNode.__init__(self, semstr=semstr)
895
1435
 
1436
+ def normalize(self, deep: bool = False) -> bool:
1437
+ """Normalize has var node."""
1438
+ res = True
1439
+ if deep:
1440
+ res = self.name.normalize(deep)
1441
+ res = res and self.type_tag.normalize(deep) if self.type_tag else res
1442
+ res = res and self.value.normalize(deep) if self.value else res
1443
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1444
+ new_kid: list[AstNode] = [self.name]
1445
+ if self.semstr:
1446
+ new_kid.append(self.gen_token(Tok.COLON))
1447
+ new_kid.append(self.semstr)
1448
+ if self.type_tag:
1449
+ new_kid.append(self.type_tag)
1450
+ if self.value:
1451
+ new_kid.append(self.gen_token(Tok.EQ))
1452
+ new_kid.append(self.value)
1453
+ if self.defer:
1454
+ new_kid.append(self.gen_token(Tok.KW_BY))
1455
+ new_kid.append(self.gen_token(Tok.KW_POST_INIT))
1456
+ AstNode.set_kids(self, nodes=new_kid)
1457
+ return res
1458
+
896
1459
 
897
1460
  class TypedCtxBlock(CodeBlockStmt):
898
1461
  """TypedCtxBlock node type for Jac Ast."""
@@ -908,6 +1471,20 @@ class TypedCtxBlock(CodeBlockStmt):
908
1471
  self.body = body
909
1472
  AstNode.__init__(self, kid=kid)
910
1473
 
1474
+ def normalize(self, deep: bool = False) -> bool:
1475
+ """Normalize typed context block node."""
1476
+ res = True
1477
+ if deep:
1478
+ res = self.type_ctx.normalize(deep)
1479
+ res = res and self.body.normalize(deep)
1480
+ new_kid: list[AstNode] = [
1481
+ self.gen_token(Tok.RETURN_HINT),
1482
+ self.type_ctx,
1483
+ self.body,
1484
+ ]
1485
+ AstNode.set_kids(self, nodes=new_kid)
1486
+ return res
1487
+
911
1488
 
912
1489
  class IfStmt(CodeBlockStmt, AstElseBodyNode):
913
1490
  """IfStmt node type for Jac Ast."""
@@ -925,10 +1502,44 @@ class IfStmt(CodeBlockStmt, AstElseBodyNode):
925
1502
  AstNode.__init__(self, kid=kid)
926
1503
  AstElseBodyNode.__init__(self, else_body=else_body)
927
1504
 
1505
+ def normalize(self, deep: bool = False) -> bool:
1506
+ """Normalize if statement node."""
1507
+ res = True
1508
+ if deep:
1509
+ res = self.condition.normalize(deep)
1510
+ res = res and self.body.normalize(deep)
1511
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1512
+ new_kid: list[AstNode] = [
1513
+ self.gen_token(Tok.KW_IF),
1514
+ self.condition,
1515
+ self.body,
1516
+ ]
1517
+ if self.else_body:
1518
+ new_kid.append(self.else_body)
1519
+ AstNode.set_kids(self, nodes=new_kid)
1520
+ return res
1521
+
928
1522
 
929
1523
  class ElseIf(IfStmt):
930
1524
  """ElseIfs node type for Jac Ast."""
931
1525
 
1526
+ def normalize(self, deep: bool = False) -> bool:
1527
+ """Normalize else if statement node."""
1528
+ res = True
1529
+ if deep:
1530
+ res = self.condition.normalize(deep)
1531
+ res = res and self.body.normalize(deep)
1532
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1533
+ new_kid: list[AstNode] = [
1534
+ self.gen_token(Tok.KW_ELIF),
1535
+ self.condition,
1536
+ self.body,
1537
+ ]
1538
+ if self.else_body:
1539
+ new_kid.append(self.else_body)
1540
+ AstNode.set_kids(self, nodes=new_kid)
1541
+ return res
1542
+
932
1543
 
933
1544
  class ElseStmt(AstNode):
934
1545
  """Else node type for Jac Ast."""
@@ -942,6 +1553,18 @@ class ElseStmt(AstNode):
942
1553
  self.body = body
943
1554
  AstNode.__init__(self, kid=kid)
944
1555
 
1556
+ def normalize(self, deep: bool = False) -> bool:
1557
+ """Normalize else statement node."""
1558
+ res = True
1559
+ if deep:
1560
+ res = self.body.normalize(deep)
1561
+ new_kid: list[AstNode] = [
1562
+ self.gen_token(Tok.KW_ELSE),
1563
+ self.body,
1564
+ ]
1565
+ AstNode.set_kids(self, nodes=new_kid)
1566
+ return res
1567
+
945
1568
 
946
1569
  class ExprStmt(CodeBlockStmt):
947
1570
  """ExprStmt node type for Jac Ast."""
@@ -957,6 +1580,19 @@ class ExprStmt(CodeBlockStmt):
957
1580
  self.in_fstring = in_fstring
958
1581
  AstNode.__init__(self, kid=kid)
959
1582
 
1583
+ def normalize(self, deep: bool = True) -> bool:
1584
+ """Normalize ast node."""
1585
+ if deep:
1586
+ res = self.expr.normalize(deep)
1587
+ new_kid: list[AstNode] = []
1588
+ if self.in_fstring:
1589
+ new_kid.append(self.expr)
1590
+ else:
1591
+ new_kid.append(self.expr)
1592
+ new_kid.append(self.gen_token(Tok.SEMI))
1593
+ AstNode.set_kids(self, nodes=new_kid)
1594
+ return res and self.expr is not None
1595
+
960
1596
 
961
1597
  class TryStmt(AstElseBodyNode, CodeBlockStmt):
962
1598
  """TryStmt node type for Jac Ast."""
@@ -976,6 +1612,29 @@ class TryStmt(AstElseBodyNode, CodeBlockStmt):
976
1612
  AstNode.__init__(self, kid=kid)
977
1613
  AstElseBodyNode.__init__(self, else_body=else_body)
978
1614
 
1615
+ def normalize(self, deep: bool = False) -> bool:
1616
+ """Normalize try statement node."""
1617
+ res = True
1618
+ if deep:
1619
+ res = self.body.normalize(deep)
1620
+ res = res and self.excepts.normalize(deep) if self.excepts else res
1621
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1622
+ res = (
1623
+ res and self.finally_body.normalize(deep) if self.finally_body else res
1624
+ )
1625
+ new_kid: list[AstNode] = [
1626
+ self.gen_token(Tok.KW_TRY),
1627
+ ]
1628
+ new_kid.append(self.body)
1629
+ if self.excepts:
1630
+ new_kid.append(self.excepts)
1631
+ if self.else_body:
1632
+ new_kid.append(self.else_body)
1633
+ if self.finally_body:
1634
+ new_kid.append(self.finally_body)
1635
+ AstNode.set_kids(self, nodes=new_kid)
1636
+ return res
1637
+
979
1638
 
980
1639
  class Except(CodeBlockStmt):
981
1640
  """Except node type for Jac Ast."""
@@ -993,6 +1652,24 @@ class Except(CodeBlockStmt):
993
1652
  self.body = body
994
1653
  AstNode.__init__(self, kid=kid)
995
1654
 
1655
+ def normalize(self, deep: bool = False) -> bool:
1656
+ """Normalize except node."""
1657
+ res = True
1658
+ if deep:
1659
+ res = self.ex_type.normalize(deep)
1660
+ res = res and self.name.normalize(deep) if self.name else res
1661
+ res = res and self.body.normalize(deep) if self.body else res
1662
+ new_kid: list[AstNode] = [
1663
+ self.gen_token(Tok.KW_EXCEPT),
1664
+ self.ex_type,
1665
+ ]
1666
+ if self.name:
1667
+ new_kid.append(self.gen_token(Tok.KW_AS))
1668
+ new_kid.append(self.name)
1669
+ new_kid.append(self.body)
1670
+ AstNode.set_kids(self, nodes=new_kid)
1671
+ return res
1672
+
996
1673
 
997
1674
  class FinallyStmt(CodeBlockStmt):
998
1675
  """FinallyStmt node type for Jac Ast."""
@@ -1006,6 +1683,18 @@ class FinallyStmt(CodeBlockStmt):
1006
1683
  self.body = body
1007
1684
  AstNode.__init__(self, kid=kid)
1008
1685
 
1686
+ def normalize(self, deep: bool = False) -> bool:
1687
+ """Normalize finally statement node."""
1688
+ res = True
1689
+ if deep:
1690
+ res = self.body.normalize(deep)
1691
+ new_kid: list[AstNode] = [
1692
+ self.gen_token(Tok.KW_FINALLY),
1693
+ ]
1694
+ new_kid.append(self.body)
1695
+ AstNode.set_kids(self, nodes=new_kid)
1696
+ return res
1697
+
1009
1698
 
1010
1699
  class IterForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1011
1700
  """IterFor node type for Jac Ast."""
@@ -1029,6 +1718,30 @@ class IterForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1029
1718
  AstAsyncNode.__init__(self, is_async=is_async)
1030
1719
  AstElseBodyNode.__init__(self, else_body=else_body)
1031
1720
 
1721
+ def normalize(self, deep: bool = False) -> bool:
1722
+ """Normalize iter for node."""
1723
+ res = True
1724
+ if deep:
1725
+ res = self.iter.normalize(deep)
1726
+ res = self.condition.normalize(deep)
1727
+ res = self.count_by.normalize(deep)
1728
+ res = self.body.normalize(deep)
1729
+ res = self.else_body.normalize(deep) if self.else_body else res
1730
+ new_kid: list[AstNode] = []
1731
+ if self.is_async:
1732
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1733
+ new_kid.append(self.gen_token(Tok.KW_FOR))
1734
+ new_kid.append(self.iter)
1735
+ new_kid.append(self.gen_token(Tok.KW_TO))
1736
+ new_kid.append(self.condition)
1737
+ new_kid.append(self.gen_token(Tok.KW_BY))
1738
+ new_kid.append(self.count_by)
1739
+ new_kid.append(self.body)
1740
+ if self.else_body:
1741
+ new_kid.append(self.else_body)
1742
+ AstNode.set_kids(self, nodes=new_kid)
1743
+ return res
1744
+
1032
1745
 
1033
1746
  class InForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1034
1747
  """InFor node type for Jac Ast."""
@@ -1050,6 +1763,29 @@ class InForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1050
1763
  AstAsyncNode.__init__(self, is_async=is_async)
1051
1764
  AstElseBodyNode.__init__(self, else_body=else_body)
1052
1765
 
1766
+ def normalize(self, deep: bool = False) -> bool:
1767
+ """Normalize in for node."""
1768
+ res = True
1769
+ if deep:
1770
+ res = self.target.normalize(deep)
1771
+ res = res and self.collection.normalize(deep)
1772
+ res = res and self.body.normalize(deep)
1773
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1774
+ new_kid: list[AstNode] = []
1775
+ if self.is_async:
1776
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1777
+ new_kid.append(self.gen_token(Tok.KW_FOR))
1778
+ new_kid.append(self.target)
1779
+ new_kid.append(self.gen_token(Tok.KW_IN))
1780
+ new_kid.append(self.collection)
1781
+
1782
+ if self.body:
1783
+ new_kid.append(self.body)
1784
+ if self.else_body:
1785
+ new_kid.append(self.else_body)
1786
+ AstNode.set_kids(self, nodes=new_kid)
1787
+ return res
1788
+
1053
1789
 
1054
1790
  class WhileStmt(CodeBlockStmt):
1055
1791
  """WhileStmt node type for Jac Ast."""
@@ -1065,6 +1801,21 @@ class WhileStmt(CodeBlockStmt):
1065
1801
  self.body = body
1066
1802
  AstNode.__init__(self, kid=kid)
1067
1803
 
1804
+ def normalize(self, deep: bool = False) -> bool:
1805
+ """Normalize while statement node."""
1806
+ res = True
1807
+ if deep:
1808
+ res = self.condition.normalize(deep)
1809
+ res = res and self.body.normalize(deep)
1810
+ new_kid: list[AstNode] = [
1811
+ self.gen_token(Tok.KW_WHILE),
1812
+ self.condition,
1813
+ ]
1814
+ if self.body:
1815
+ new_kid.append(self.body)
1816
+ AstNode.set_kids(self, nodes=new_kid)
1817
+ return res
1818
+
1068
1819
 
1069
1820
  class WithStmt(AstAsyncNode, CodeBlockStmt):
1070
1821
  """WithStmt node type for Jac Ast."""
@@ -1082,6 +1833,24 @@ class WithStmt(AstAsyncNode, CodeBlockStmt):
1082
1833
  AstNode.__init__(self, kid=kid)
1083
1834
  AstAsyncNode.__init__(self, is_async=is_async)
1084
1835
 
1836
+ def normalize(self, deep: bool = False) -> bool:
1837
+ """Normalize with statement node."""
1838
+ res = True
1839
+ if deep:
1840
+ res = self.exprs.normalize(deep)
1841
+ res = res and self.body.normalize(deep)
1842
+ new_kid: list[AstNode] = []
1843
+ if self.is_async:
1844
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1845
+ new_kid.append(self.gen_token(Tok.KW_WITH))
1846
+ new_kid.append(self.exprs)
1847
+ new_kid.append(self.gen_token(Tok.LBRACE))
1848
+ new_kid.append(self.body)
1849
+ new_kid.append(self.gen_token(Tok.RBRACE))
1850
+
1851
+ AstNode.set_kids(self, nodes=new_kid)
1852
+ return res
1853
+
1085
1854
 
1086
1855
  class ExprAsItem(AstNode):
1087
1856
  """ExprAsItem node type for Jac Ast."""
@@ -1097,6 +1866,19 @@ class ExprAsItem(AstNode):
1097
1866
  self.alias = alias
1098
1867
  AstNode.__init__(self, kid=kid)
1099
1868
 
1869
+ def normalize(self, deep: bool = True) -> bool:
1870
+ """Normalize ast node."""
1871
+ res = True
1872
+ if deep:
1873
+ res = self.expr.normalize(deep)
1874
+ res = res and self.alias.normalize(deep) if self.alias else res
1875
+ new_kid: list[AstNode] = [self.expr]
1876
+ if self.alias:
1877
+ new_kid.append(self.gen_token(Tok.KW_AS))
1878
+ new_kid.append(self.alias)
1879
+ AstNode.set_kids(self, nodes=new_kid)
1880
+ return res
1881
+
1100
1882
 
1101
1883
  class RaiseStmt(CodeBlockStmt):
1102
1884
  """RaiseStmt node type for Jac Ast."""
@@ -1112,6 +1894,22 @@ class RaiseStmt(CodeBlockStmt):
1112
1894
  self.from_target = from_target
1113
1895
  AstNode.__init__(self, kid=kid)
1114
1896
 
1897
+ def normalize(self, deep: bool = False) -> bool:
1898
+ """Normalize raise statement node."""
1899
+ res = True
1900
+ if deep:
1901
+ res = res and self.cause.normalize(deep) if self.cause else res
1902
+ res = res and self.from_target.normalize(deep) if self.from_target else res
1903
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_RAISE)]
1904
+ if self.cause:
1905
+ new_kid.append(self.cause)
1906
+ if self.from_target:
1907
+ new_kid.append(self.gen_token(Tok.KW_FROM))
1908
+ new_kid.append(self.from_target)
1909
+ new_kid.append(self.gen_token(Tok.SEMI))
1910
+ AstNode.set_kids(self, nodes=new_kid)
1911
+ return res
1912
+
1115
1913
 
1116
1914
  class AssertStmt(CodeBlockStmt):
1117
1915
  """AssertStmt node type for Jac Ast."""
@@ -1127,6 +1925,23 @@ class AssertStmt(CodeBlockStmt):
1127
1925
  self.error_msg = error_msg
1128
1926
  AstNode.__init__(self, kid=kid)
1129
1927
 
1928
+ def normalize(self, deep: bool = False) -> bool:
1929
+ """Normalize assert statement node."""
1930
+ res = True
1931
+ if deep:
1932
+ res = self.condition.normalize(deep)
1933
+ res = res and self.error_msg.normalize(deep) if self.error_msg else res
1934
+ new_kid: list[AstNode] = [
1935
+ self.gen_token(Tok.KW_ASSERT),
1936
+ self.condition,
1937
+ ]
1938
+ if self.error_msg:
1939
+ new_kid.append(self.gen_token(Tok.COMMA))
1940
+ new_kid.append(self.error_msg)
1941
+ new_kid.append(self.gen_token(Tok.SEMI))
1942
+ AstNode.set_kids(self, nodes=new_kid)
1943
+ return res
1944
+
1130
1945
 
1131
1946
  class CtrlStmt(CodeBlockStmt):
1132
1947
  """CtrlStmt node type for Jac Ast."""
@@ -1140,6 +1955,15 @@ class CtrlStmt(CodeBlockStmt):
1140
1955
  self.ctrl = ctrl
1141
1956
  AstNode.__init__(self, kid=kid)
1142
1957
 
1958
+ def normalize(self, deep: bool = False) -> bool:
1959
+ """Normalize control statement node."""
1960
+ res = True
1961
+ if deep:
1962
+ res = self.ctrl.normalize(deep)
1963
+ new_kid: list[AstNode] = [self.ctrl, self.gen_token(Tok.SEMI)]
1964
+ AstNode.set_kids(self, nodes=new_kid)
1965
+ return res
1966
+
1143
1967
 
1144
1968
  class DeleteStmt(CodeBlockStmt):
1145
1969
  """DeleteStmt node type for Jac Ast."""
@@ -1153,6 +1977,19 @@ class DeleteStmt(CodeBlockStmt):
1153
1977
  self.target = target
1154
1978
  AstNode.__init__(self, kid=kid)
1155
1979
 
1980
+ def normalize(self, deep: bool = False) -> bool:
1981
+ """Normalize delete statement node."""
1982
+ res = True
1983
+ if deep:
1984
+ res = self.target.normalize(deep)
1985
+ new_kid: list[AstNode] = [
1986
+ self.gen_token(Tok.KW_DELETE),
1987
+ self.target,
1988
+ self.gen_token(Tok.SEMI),
1989
+ ]
1990
+ AstNode.set_kids(self, nodes=new_kid)
1991
+ return res
1992
+
1156
1993
 
1157
1994
  class ReportStmt(CodeBlockStmt):
1158
1995
  """ReportStmt node type for Jac Ast."""
@@ -1166,6 +2003,19 @@ class ReportStmt(CodeBlockStmt):
1166
2003
  self.expr = expr
1167
2004
  AstNode.__init__(self, kid=kid)
1168
2005
 
2006
+ def normalize(self, deep: bool = False) -> bool:
2007
+ """Normalize report statement node."""
2008
+ res = True
2009
+ if deep:
2010
+ res = self.expr.normalize(deep)
2011
+ new_kid: list[AstNode] = [
2012
+ self.gen_token(Tok.KW_REPORT),
2013
+ self.expr,
2014
+ self.gen_token(Tok.SEMI),
2015
+ ]
2016
+ AstNode.set_kids(self, nodes=new_kid)
2017
+ return res
2018
+
1169
2019
 
1170
2020
  class ReturnStmt(CodeBlockStmt):
1171
2021
  """ReturnStmt node type for Jac Ast."""
@@ -1179,6 +2029,20 @@ class ReturnStmt(CodeBlockStmt):
1179
2029
  self.expr = expr
1180
2030
  AstNode.__init__(self, kid=kid)
1181
2031
 
2032
+ def normalize(self, deep: bool = False) -> bool:
2033
+ """Normalize return statement node."""
2034
+ res = True
2035
+ if deep:
2036
+ res = self.expr.normalize(deep) if self.expr else res
2037
+ new_kid: list[AstNode] = [
2038
+ self.gen_token(Tok.KW_RETURN),
2039
+ ]
2040
+ if self.expr:
2041
+ new_kid.append(self.expr)
2042
+ new_kid.append(self.gen_token(Tok.SEMI))
2043
+ AstNode.set_kids(self, nodes=new_kid)
2044
+ return res
2045
+
1182
2046
 
1183
2047
  class IgnoreStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1184
2048
  """IgnoreStmt node type for Jac Ast."""
@@ -1193,6 +2057,19 @@ class IgnoreStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1193
2057
  AstNode.__init__(self, kid=kid)
1194
2058
  WalkerStmtOnlyNode.__init__(self)
1195
2059
 
2060
+ def normalize(self, deep: bool = False) -> bool:
2061
+ """Normalize ignore statement node."""
2062
+ res = True
2063
+ if deep:
2064
+ res = self.target.normalize(deep)
2065
+ new_kid: list[AstNode] = [
2066
+ self.gen_token(Tok.KW_IGNORE),
2067
+ self.target,
2068
+ self.gen_token(Tok.SEMI),
2069
+ ]
2070
+ AstNode.set_kids(self, nodes=new_kid)
2071
+ return res
2072
+
1196
2073
 
1197
2074
  class VisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1198
2075
  """VisitStmt node type for Jac Ast."""
@@ -1211,6 +2088,27 @@ class VisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1211
2088
  WalkerStmtOnlyNode.__init__(self)
1212
2089
  AstElseBodyNode.__init__(self, else_body=else_body)
1213
2090
 
2091
+ def normalize(self, deep: bool = False) -> bool:
2092
+ """Normalize visit statement node."""
2093
+ res = True
2094
+ if deep:
2095
+ res = self.vis_type.normalize(deep) if self.vis_type else res
2096
+ res = self.target.normalize(deep)
2097
+ res = res and self.else_body.normalize(deep) if self.else_body else res
2098
+ new_kid: list[AstNode] = []
2099
+ new_kid.append(self.gen_token(Tok.KW_VISIT))
2100
+ if self.vis_type:
2101
+ new_kid.append(self.gen_token(Tok.COLON))
2102
+ new_kid.append(self.vis_type)
2103
+ new_kid.append(self.gen_token(Tok.COLON))
2104
+ new_kid.append(self.target)
2105
+ if self.else_body:
2106
+ new_kid.append(self.else_body)
2107
+ else:
2108
+ new_kid.append(self.gen_token(Tok.SEMI))
2109
+ AstNode.set_kids(self, nodes=new_kid)
2110
+ return res
2111
+
1214
2112
 
1215
2113
  class RevisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1216
2114
  """ReVisitStmt node type for Jac Ast."""
@@ -1227,6 +2125,21 @@ class RevisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1227
2125
  WalkerStmtOnlyNode.__init__(self)
1228
2126
  AstElseBodyNode.__init__(self, else_body=else_body)
1229
2127
 
2128
+ def normalize(self, deep: bool = False) -> bool:
2129
+ """Normalize revisit statement node."""
2130
+ res = True
2131
+ if deep:
2132
+ res = self.hops.normalize(deep) if self.hops else res
2133
+ res = res and self.else_body.normalize(deep) if self.else_body else res
2134
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_REVISIT)]
2135
+ if self.hops:
2136
+ new_kid.append(self.hops)
2137
+ if self.else_body:
2138
+ new_kid.append(self.else_body)
2139
+ new_kid.append(self.gen_token(Tok.SEMI))
2140
+ AstNode.set_kids(self, nodes=new_kid)
2141
+ return res
2142
+
1230
2143
 
1231
2144
  class DisengageStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1232
2145
  """DisengageStmt node type for Jac Ast."""
@@ -1239,6 +2152,15 @@ class DisengageStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1239
2152
  AstNode.__init__(self, kid=kid)
1240
2153
  WalkerStmtOnlyNode.__init__(self)
1241
2154
 
2155
+ def normalize(self, deep: bool = False) -> bool:
2156
+ """Normalize disengage statement node."""
2157
+ new_kid: list[AstNode] = [
2158
+ self.gen_token(Tok.KW_DISENGAGE),
2159
+ self.gen_token(Tok.SEMI),
2160
+ ]
2161
+ AstNode.set_kids(self, nodes=new_kid)
2162
+ return True
2163
+
1242
2164
 
1243
2165
  class AwaitExpr(Expr):
1244
2166
  """AwaitStmt node type for Jac Ast."""
@@ -1252,6 +2174,18 @@ class AwaitExpr(Expr):
1252
2174
  self.target = target
1253
2175
  AstNode.__init__(self, kid=kid)
1254
2176
 
2177
+ def normalize(self, deep: bool = False) -> bool:
2178
+ """Normalize sync statement node."""
2179
+ res = True
2180
+ if deep:
2181
+ res = self.target.normalize(deep)
2182
+ new_kid: list[AstNode] = [
2183
+ self.gen_token(Tok.KW_AWAIT),
2184
+ self.target,
2185
+ ]
2186
+ AstNode.set_kids(self, nodes=new_kid)
2187
+ return res
2188
+
1255
2189
 
1256
2190
  class GlobalStmt(CodeBlockStmt):
1257
2191
  """GlobalStmt node type for Jac Ast."""
@@ -1265,12 +2199,38 @@ class GlobalStmt(CodeBlockStmt):
1265
2199
  self.target = target
1266
2200
  AstNode.__init__(self, kid=kid)
1267
2201
 
2202
+ def normalize(self, deep: bool = False) -> bool:
2203
+ """Normalize global statement node."""
2204
+ res = True
2205
+ if deep:
2206
+ res = self.target.normalize(deep)
2207
+ new_kid: list[AstNode] = [
2208
+ self.gen_token(Tok.GLOBAL_OP),
2209
+ self.target,
2210
+ self.gen_token(Tok.SEMI),
2211
+ ]
2212
+ AstNode.set_kids(self, nodes=new_kid)
2213
+ return res
2214
+
1268
2215
 
1269
2216
  class NonLocalStmt(GlobalStmt):
1270
2217
  """NonlocalStmt node type for Jac Ast."""
1271
2218
 
1272
-
1273
- class Assignment(AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
2219
+ def normalize(self, deep: bool = False) -> bool:
2220
+ """Normalize nonlocal statement node."""
2221
+ res = True
2222
+ if deep:
2223
+ res = self.target.normalize(deep)
2224
+ new_kid: list[AstNode] = [
2225
+ self.gen_token(Tok.NONLOCAL_OP),
2226
+ self.target,
2227
+ self.gen_token(Tok.SEMI),
2228
+ ]
2229
+ AstNode.set_kids(self, nodes=new_kid)
2230
+ return res
2231
+
2232
+
2233
+ class Assignment(AstSemStrNode, AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
1274
2234
  """Assignment node type for Jac Ast."""
1275
2235
 
1276
2236
  def __init__(
@@ -1281,15 +2241,50 @@ class Assignment(AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
1281
2241
  kid: Sequence[AstNode],
1282
2242
  mutable: bool = True,
1283
2243
  aug_op: Optional[Token] = None,
2244
+ semstr: Optional[String] = None,
2245
+ is_enum_stmt: bool = False,
1284
2246
  ) -> None:
1285
2247
  """Initialize assignment node."""
1286
2248
  self.target = target
1287
2249
  self.value = value
1288
2250
  self.mutable = mutable
1289
2251
  self.aug_op = aug_op
2252
+ self.is_enum_stmt = is_enum_stmt
1290
2253
  AstNode.__init__(self, kid=kid)
2254
+ AstSemStrNode.__init__(self, semstr=semstr)
1291
2255
  AstTypedVarNode.__init__(self, type_tag=type_tag)
1292
2256
 
2257
+ def normalize(self, deep: bool = True) -> bool:
2258
+ """Normalize ast node."""
2259
+ res = True
2260
+ if deep:
2261
+ res = self.target.normalize(deep)
2262
+ res = res and self.value.normalize(deep) if self.value else res
2263
+ res = res and self.type_tag.normalize(deep) if self.type_tag else res
2264
+ res = res and self.aug_op.normalize(deep) if self.aug_op else res
2265
+ new_kid: list[AstNode] = []
2266
+ new_kid.append(self.target)
2267
+ if self.semstr:
2268
+ new_kid.append(self.gen_token(Tok.COLON))
2269
+ new_kid.append(self.semstr)
2270
+ if self.type_tag:
2271
+ new_kid.append(self.type_tag)
2272
+ if self.aug_op:
2273
+ new_kid.append(self.aug_op)
2274
+ if self.value:
2275
+ if not self.aug_op:
2276
+ new_kid.append(self.gen_token(Tok.EQ))
2277
+ new_kid.append(self.value)
2278
+ if isinstance(self.parent, SubNodeList) and isinstance(
2279
+ self.parent.parent, GlobalVars
2280
+ ):
2281
+ if self.parent.kid.index(self) == len(self.parent.kid) - 1:
2282
+ new_kid.append(self.gen_token(Tok.SEMI))
2283
+ elif (not self.is_enum_stmt) and not isinstance(self.parent, IterForStmt):
2284
+ new_kid.append(self.gen_token(Tok.SEMI))
2285
+ AstNode.set_kids(self, nodes=new_kid)
2286
+ return res
2287
+
1293
2288
 
1294
2289
  class BinaryExpr(Expr):
1295
2290
  """ExprBinary node type for Jac Ast."""
@@ -1307,6 +2302,23 @@ class BinaryExpr(Expr):
1307
2302
  self.op = op
1308
2303
  AstNode.__init__(self, kid=kid)
1309
2304
 
2305
+ def normalize(self, deep: bool = False) -> bool:
2306
+ """Normalize ast node."""
2307
+ res = True
2308
+ if deep:
2309
+ res = self.left.normalize(deep)
2310
+ res = res and self.right.normalize(deep) if self.right else res
2311
+ res = res and self.op.normalize(deep) if self.op else res
2312
+ new_kid: list[AstNode] = [
2313
+ self.gen_token(Tok.LPAREN),
2314
+ self.left,
2315
+ self.op,
2316
+ self.right,
2317
+ self.gen_token(Tok.RPAREN),
2318
+ ]
2319
+ AstNode.set_kids(self, nodes=new_kid)
2320
+ return res
2321
+
1310
2322
 
1311
2323
  class CompareExpr(Expr):
1312
2324
  """CompareExpr node type for Jac Ast."""
@@ -1324,6 +2336,22 @@ class CompareExpr(Expr):
1324
2336
  self.ops = ops
1325
2337
  AstNode.__init__(self, kid=kid)
1326
2338
 
2339
+ def normalize(self, deep: bool = False) -> bool:
2340
+ """Normalize ast node."""
2341
+ res = True
2342
+ if deep:
2343
+ res = self.left.normalize(deep)
2344
+ for right in self.rights:
2345
+ res = res and right.normalize(deep)
2346
+ for op in self.ops:
2347
+ res = res and op.normalize(deep)
2348
+ new_kid: list[AstNode] = [self.left]
2349
+ for i, right in enumerate(self.rights):
2350
+ new_kid.append(self.ops[i])
2351
+ new_kid.append(right)
2352
+ AstNode.set_kids(self, nodes=new_kid)
2353
+ return res
2354
+
1327
2355
 
1328
2356
  class BoolExpr(Expr):
1329
2357
  """BoolExpr node type for Jac Ast."""
@@ -1339,6 +2367,21 @@ class BoolExpr(Expr):
1339
2367
  self.op = op
1340
2368
  AstNode.__init__(self, kid=kid)
1341
2369
 
2370
+ def normalize(self, deep: bool = False) -> bool:
2371
+ """Normalize ast node."""
2372
+ res = True
2373
+ if deep:
2374
+ for value in self.values:
2375
+ res = res and value.normalize(deep)
2376
+ res = res and self.op.normalize(deep) if self.op else res
2377
+ new_kid: list[AstNode] = []
2378
+ for i, value in enumerate(self.values):
2379
+ if i > 0:
2380
+ new_kid.append(self.op)
2381
+ new_kid.append(value)
2382
+ AstNode.set_kids(self, nodes=new_kid)
2383
+ return res
2384
+
1342
2385
 
1343
2386
  class LambdaExpr(Expr):
1344
2387
  """ExprLambda node type for Jac Ast."""
@@ -1354,6 +2397,22 @@ class LambdaExpr(Expr):
1354
2397
  self.body = body
1355
2398
  AstNode.__init__(self, kid=kid)
1356
2399
 
2400
+ def normalize(self, deep: bool = False) -> bool:
2401
+ """Normalize ast node."""
2402
+ res = True
2403
+ if deep:
2404
+ res = self.signature.normalize(deep)
2405
+ res = res and self.body.normalize(deep)
2406
+ new_kid: list[AstNode] = [
2407
+ self.gen_token(Tok.KW_WITH),
2408
+ self.signature,
2409
+ self.gen_token(Tok.KW_CAN),
2410
+ self.body,
2411
+ self.gen_token(Tok.SEMI),
2412
+ ]
2413
+ AstNode.set_kids(self, nodes=new_kid)
2414
+ return res
2415
+
1357
2416
 
1358
2417
  class UnaryExpr(Expr):
1359
2418
  """ExprUnary node type for Jac Ast."""
@@ -1369,6 +2428,16 @@ class UnaryExpr(Expr):
1369
2428
  self.op = op
1370
2429
  AstNode.__init__(self, kid=kid)
1371
2430
 
2431
+ def normalize(self, deep: bool = False) -> bool:
2432
+ """Normalize ast node."""
2433
+ res = True
2434
+ if deep:
2435
+ res = self.operand.normalize(deep)
2436
+ res = res and self.op.normalize(deep) if self.op else res
2437
+ new_kid: list[AstNode] = [self.op, self.operand]
2438
+ AstNode.set_kids(self, nodes=new_kid)
2439
+ return res
2440
+
1372
2441
 
1373
2442
  class IfElseExpr(Expr):
1374
2443
  """ExprIfElse node type for Jac Ast."""
@@ -1386,6 +2455,23 @@ class IfElseExpr(Expr):
1386
2455
  self.else_value = else_value
1387
2456
  AstNode.__init__(self, kid=kid)
1388
2457
 
2458
+ def normalize(self, deep: bool = False) -> bool:
2459
+ """Normalize ast node."""
2460
+ res = True
2461
+ if deep:
2462
+ res = self.condition.normalize(deep)
2463
+ res = res and self.value.normalize(deep)
2464
+ res = res and self.else_value.normalize(deep)
2465
+ new_kid: list[AstNode] = [
2466
+ self.value,
2467
+ self.gen_token(Tok.KW_IF),
2468
+ self.condition,
2469
+ self.gen_token(Tok.KW_ELSE),
2470
+ self.else_value,
2471
+ ]
2472
+ AstNode.set_kids(self, nodes=new_kid)
2473
+ return res
2474
+
1389
2475
 
1390
2476
  class MultiString(AtomExpr):
1391
2477
  """ExprMultiString node type for Jac Ast."""
@@ -1405,8 +2491,20 @@ class MultiString(AtomExpr):
1405
2491
  sym_type=SymbolType.STRING,
1406
2492
  )
1407
2493
 
2494
+ def normalize(self, deep: bool = False) -> bool:
2495
+ """Normalize ast node."""
2496
+ res = True
2497
+ if deep:
2498
+ for string in self.strings:
2499
+ res = res and string.normalize(deep)
2500
+ new_kid: list[AstNode] = []
2501
+ for string in self.strings:
2502
+ new_kid.append(string)
2503
+ AstNode.set_kids(self, nodes=new_kid)
2504
+ return res
1408
2505
 
1409
- class FString(AstSymbolNode):
2506
+
2507
+ class FString(AtomExpr):
1410
2508
  """FString node type for Jac Ast."""
1411
2509
 
1412
2510
  def __init__(
@@ -1424,18 +2522,21 @@ class FString(AstSymbolNode):
1424
2522
  sym_type=SymbolType.STRING,
1425
2523
  )
1426
2524
 
1427
-
1428
- class ExprList(AstNode):
1429
- """ExprList node type for Jac Ast."""
1430
-
1431
- def __init__(
1432
- self,
1433
- values: Optional[SubNodeList[Expr]],
1434
- kid: Sequence[AstNode],
1435
- ) -> None:
1436
- """Initialize expr value node."""
1437
- self.values = values
1438
- AstNode.__init__(self, kid=kid)
2525
+ def normalize(self, deep: bool = False) -> bool:
2526
+ """Normalize ast node."""
2527
+ res = True
2528
+ if deep:
2529
+ res = self.parts.normalize(deep) if self.parts else res
2530
+ new_kid: list[AstNode] = []
2531
+ if self.parts:
2532
+ for i in self.parts.items:
2533
+ if isinstance(i, String):
2534
+ i.value = (
2535
+ "{{" if i.value == "{" else "}}" if i.value == "}" else i.value
2536
+ )
2537
+ new_kid.append(self.parts)
2538
+ AstNode.set_kids(self, nodes=new_kid)
2539
+ return res
1439
2540
 
1440
2541
 
1441
2542
  class ListVal(AtomExpr):
@@ -1456,6 +2557,20 @@ class ListVal(AtomExpr):
1456
2557
  sym_type=SymbolType.SEQUENCE,
1457
2558
  )
1458
2559
 
2560
+ def normalize(self, deep: bool = False) -> bool:
2561
+ """Normalize ast node."""
2562
+ res = True
2563
+ if deep:
2564
+ res = self.values.normalize(deep) if self.values else res
2565
+ new_kid: list[AstNode] = [
2566
+ self.gen_token(Tok.LSQUARE),
2567
+ ]
2568
+ if self.values:
2569
+ new_kid.append(self.values)
2570
+ new_kid.append(self.gen_token(Tok.RSQUARE))
2571
+ AstNode.set_kids(self, nodes=new_kid)
2572
+ return res
2573
+
1459
2574
 
1460
2575
  class SetVal(AtomExpr):
1461
2576
  """SetVal node type for Jac Ast."""
@@ -1475,6 +2590,20 @@ class SetVal(AtomExpr):
1475
2590
  sym_type=SymbolType.SEQUENCE,
1476
2591
  )
1477
2592
 
2593
+ def normalize(self, deep: bool = False) -> bool:
2594
+ """Normalize ast node."""
2595
+ res = True
2596
+ if deep:
2597
+ res = self.values.normalize(deep) if self.values else res
2598
+ new_kid: list[AstNode] = [
2599
+ self.gen_token(Tok.LBRACE),
2600
+ ]
2601
+ if self.values:
2602
+ new_kid.append(self.values)
2603
+ new_kid.append(self.gen_token(Tok.RBRACE))
2604
+ AstNode.set_kids(self, nodes=new_kid)
2605
+ return res
2606
+
1478
2607
 
1479
2608
  class TupleVal(AtomExpr):
1480
2609
  """TupleVal node type for Jac Ast."""
@@ -1494,6 +2623,35 @@ class TupleVal(AtomExpr):
1494
2623
  sym_type=SymbolType.SEQUENCE,
1495
2624
  )
1496
2625
 
2626
+ def normalize(self, deep: bool = False) -> bool:
2627
+ """Normalize ast node."""
2628
+ res = True
2629
+ if deep:
2630
+ res = self.values.normalize(deep) if self.values else res
2631
+ in_ret_type = (
2632
+ self.parent
2633
+ and isinstance(self.parent, IndexSlice)
2634
+ and self.parent
2635
+ and isinstance(self.parent.parent, AtomTrailer)
2636
+ and self.parent.parent
2637
+ and isinstance(self.parent.parent.parent, FuncSignature)
2638
+ )
2639
+ new_kid: list[AstNode] = (
2640
+ [
2641
+ self.gen_token(Tok.LPAREN),
2642
+ ]
2643
+ if not in_ret_type
2644
+ else []
2645
+ )
2646
+ if self.values:
2647
+ new_kid.append(self.values)
2648
+ if len(self.values.items) < 2:
2649
+ new_kid.append(self.gen_token(Tok.COMMA))
2650
+ if not in_ret_type:
2651
+ new_kid.append(self.gen_token(Tok.RPAREN))
2652
+ AstNode.set_kids(self, nodes=new_kid)
2653
+ return res
2654
+
1497
2655
 
1498
2656
  class DictVal(AtomExpr):
1499
2657
  """ExprDict node type for Jac Ast."""
@@ -1513,6 +2671,23 @@ class DictVal(AtomExpr):
1513
2671
  sym_type=SymbolType.SEQUENCE,
1514
2672
  )
1515
2673
 
2674
+ def normalize(self, deep: bool = False) -> bool:
2675
+ """Normalize ast node."""
2676
+ res = True
2677
+ if deep:
2678
+ for kv_pair in self.kv_pairs:
2679
+ res = res and kv_pair.normalize(deep)
2680
+ new_kid: list[AstNode] = [
2681
+ self.gen_token(Tok.LBRACE),
2682
+ ]
2683
+ for i, kv_pair in enumerate(self.kv_pairs):
2684
+ new_kid.append(kv_pair)
2685
+ if i < len(self.kv_pairs) - 1:
2686
+ new_kid.append(self.gen_token(Tok.COMMA))
2687
+ new_kid.append(self.gen_token(Tok.RBRACE))
2688
+ AstNode.set_kids(self, nodes=new_kid)
2689
+ return res
2690
+
1516
2691
 
1517
2692
  class KVPair(AstNode):
1518
2693
  """ExprKVPair node type for Jac Ast."""
@@ -1528,6 +2703,22 @@ class KVPair(AstNode):
1528
2703
  self.value = value
1529
2704
  AstNode.__init__(self, kid=kid)
1530
2705
 
2706
+ def normalize(self, deep: bool = False) -> bool:
2707
+ """Normalize ast node."""
2708
+ res = True
2709
+ if deep:
2710
+ res = self.key.normalize(deep) if self.key else res
2711
+ res = res and self.value.normalize(deep)
2712
+ new_kid: list[AstNode] = []
2713
+ if self.key:
2714
+ new_kid.append(self.key)
2715
+ new_kid.append(self.gen_token(Tok.COLON))
2716
+ else:
2717
+ new_kid.append(self.gen_token(Tok.STAR_POW))
2718
+ new_kid.append(self.value)
2719
+ AstNode.set_kids(self, nodes=new_kid)
2720
+ return res
2721
+
1531
2722
 
1532
2723
  class KWPair(AstNode):
1533
2724
  """ExprKWPair node type for Jac Ast."""
@@ -1543,6 +2734,20 @@ class KWPair(AstNode):
1543
2734
  self.value = value
1544
2735
  AstNode.__init__(self, kid=kid)
1545
2736
 
2737
+ def normalize(self, deep: bool = False) -> bool:
2738
+ """Normalize ast node."""
2739
+ res = True
2740
+ if deep:
2741
+ res = self.key.normalize(deep) if self.key else res
2742
+ res = res and self.value.normalize(deep)
2743
+ new_kid: list[AstNode] = []
2744
+ if self.key:
2745
+ new_kid.append(self.key)
2746
+ new_kid.append(self.gen_token(Tok.EQ))
2747
+ new_kid.append(self.value)
2748
+ AstNode.set_kids(self, nodes=new_kid)
2749
+ return res
2750
+
1546
2751
 
1547
2752
  class InnerCompr(AstAsyncNode):
1548
2753
  """ListCompr node type for Jac Ast."""
@@ -1552,7 +2757,7 @@ class InnerCompr(AstAsyncNode):
1552
2757
  is_async: bool,
1553
2758
  target: Expr,
1554
2759
  collection: Expr,
1555
- conditional: Optional[Expr],
2760
+ conditional: Optional[list[Expr]],
1556
2761
  kid: Sequence[AstNode],
1557
2762
  ) -> None:
1558
2763
  """Initialize comprehension expression node."""
@@ -1562,6 +2767,27 @@ class InnerCompr(AstAsyncNode):
1562
2767
  AstNode.__init__(self, kid=kid)
1563
2768
  AstAsyncNode.__init__(self, is_async=is_async)
1564
2769
 
2770
+ def normalize(self, deep: bool = False) -> bool:
2771
+ """Normalize ast node."""
2772
+ res = True
2773
+ if deep:
2774
+ res = self.target.normalize(deep)
2775
+ res = res and self.collection.normalize(deep)
2776
+ for cond in self.conditional if self.conditional else []:
2777
+ res = res and cond.normalize(deep)
2778
+ new_kid: list[AstNode] = []
2779
+ if self.is_async:
2780
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
2781
+ new_kid.append(self.gen_token(Tok.KW_FOR))
2782
+ new_kid.append(self.target)
2783
+ new_kid.append(self.gen_token(Tok.KW_IN))
2784
+ new_kid.append(self.collection)
2785
+ for cond in self.conditional if self.conditional else []:
2786
+ new_kid.append(self.gen_token(Tok.KW_IF))
2787
+ new_kid.append(cond)
2788
+ AstNode.set_kids(self, nodes=new_kid)
2789
+ return res
2790
+
1565
2791
 
1566
2792
  class ListCompr(AtomExpr):
1567
2793
  """ListCompr node type for Jac Ast."""
@@ -1583,14 +2809,65 @@ class ListCompr(AtomExpr):
1583
2809
  sym_type=SymbolType.SEQUENCE,
1584
2810
  )
1585
2811
 
2812
+ def normalize(self, deep: bool = False) -> bool:
2813
+ """Normalize ast node."""
2814
+ res = True
2815
+ if deep:
2816
+ res = self.out_expr.normalize(deep)
2817
+ for comp in self.compr:
2818
+ res = res and comp.normalize(deep)
2819
+ new_kid: list[AstNode] = [
2820
+ self.gen_token(Tok.LSQUARE),
2821
+ self.out_expr,
2822
+ ]
2823
+ for comp in self.compr:
2824
+ new_kid.append(comp)
2825
+ new_kid.append(self.gen_token(Tok.RSQUARE))
2826
+ AstNode.set_kids(self, nodes=new_kid)
2827
+ return res
2828
+
1586
2829
 
1587
2830
  class GenCompr(ListCompr):
1588
2831
  """GenCompr node type for Jac Ast."""
1589
2832
 
2833
+ def normalize(self, deep: bool = False) -> bool:
2834
+ """Normalize ast node."""
2835
+ res = True
2836
+ if deep:
2837
+ res = self.out_expr.normalize(deep)
2838
+ for comp in self.compr:
2839
+ res = res and comp.normalize(deep)
2840
+ new_kid: list[AstNode] = [
2841
+ self.gen_token(Tok.LPAREN),
2842
+ self.out_expr,
2843
+ ]
2844
+ for comp in self.compr:
2845
+ new_kid.append(comp)
2846
+ new_kid.append(self.gen_token(Tok.RPAREN))
2847
+ AstNode.set_kids(self, nodes=new_kid)
2848
+ return res
2849
+
1590
2850
 
1591
2851
  class SetCompr(ListCompr):
1592
2852
  """SetCompr node type for Jac Ast."""
1593
2853
 
2854
+ def normalize(self, deep: bool = False) -> bool:
2855
+ """Normalize ast node."""
2856
+ res = True
2857
+ if deep:
2858
+ res = self.out_expr.normalize(deep)
2859
+ for comp in self.compr:
2860
+ res = res and comp.normalize(deep)
2861
+ new_kid: list[AstNode] = [
2862
+ self.gen_token(Tok.LBRACE),
2863
+ self.out_expr,
2864
+ ]
2865
+ for comp in self.compr:
2866
+ new_kid.append(comp)
2867
+ new_kid.append(self.gen_token(Tok.RBRACE))
2868
+ AstNode.set_kids(self, nodes=new_kid)
2869
+ return res
2870
+
1594
2871
 
1595
2872
  class DictCompr(AtomExpr):
1596
2873
  """DictCompr node type for Jac Ast."""
@@ -1612,6 +2889,22 @@ class DictCompr(AtomExpr):
1612
2889
  sym_type=SymbolType.SEQUENCE,
1613
2890
  )
1614
2891
 
2892
+ def normalize(self, deep: bool = False) -> bool:
2893
+ """Normalize ast node."""
2894
+ res = True
2895
+ res = self.kv_pair.normalize(deep)
2896
+ for comp in self.compr:
2897
+ res = res and comp.normalize(deep)
2898
+ new_kid: list[AstNode] = [
2899
+ self.gen_token(Tok.LBRACE),
2900
+ self.kv_pair,
2901
+ ]
2902
+ for comp in self.compr:
2903
+ new_kid.append(comp)
2904
+ new_kid.append(self.gen_token(Tok.RBRACE))
2905
+ AstNode.set_kids(self, nodes=new_kid)
2906
+ return res
2907
+
1615
2908
 
1616
2909
  class AtomTrailer(Expr):
1617
2910
  """AtomTrailer node type for Jac Ast."""
@@ -1620,7 +2913,7 @@ class AtomTrailer(Expr):
1620
2913
  self,
1621
2914
  target: Expr,
1622
2915
  right: AtomExpr | Expr,
1623
- is_attr: Optional[Token],
2916
+ is_attr: bool,
1624
2917
  is_null_ok: bool,
1625
2918
  kid: Sequence[AstNode],
1626
2919
  ) -> None:
@@ -1631,6 +2924,22 @@ class AtomTrailer(Expr):
1631
2924
  self.is_null_ok = is_null_ok
1632
2925
  AstNode.__init__(self, kid=kid)
1633
2926
 
2927
+ def normalize(self, deep: bool = True) -> bool:
2928
+ """Normalize ast node."""
2929
+ res = True
2930
+ if deep:
2931
+ res = self.target.normalize(deep)
2932
+ res = res and self.right.normalize(deep) if self.right else res
2933
+ new_kid: list[AstNode] = [self.target]
2934
+ if self.is_null_ok:
2935
+ new_kid.append(self.gen_token(Tok.NULL_OK))
2936
+ if self.is_attr:
2937
+ new_kid.append(self.gen_token(Tok.DOT))
2938
+ if self.right:
2939
+ new_kid.append(self.right)
2940
+ AstNode.set_kids(self, nodes=new_kid)
2941
+ return res
2942
+
1634
2943
 
1635
2944
  class AtomUnit(Expr):
1636
2945
  """AtomUnit node type for Jac Ast."""
@@ -1638,14 +2947,24 @@ class AtomUnit(Expr):
1638
2947
  def __init__(
1639
2948
  self,
1640
2949
  value: Expr | YieldExpr,
1641
- is_paren: bool,
1642
2950
  kid: Sequence[AstNode],
1643
2951
  ) -> None:
1644
2952
  """Initialize atom unit expression node."""
1645
2953
  self.value = value
1646
- self.is_paren = is_paren
1647
2954
  AstNode.__init__(self, kid=kid)
1648
2955
 
2956
+ def normalize(self, deep: bool = True) -> bool:
2957
+ """Normalize ast node."""
2958
+ res = True
2959
+ if deep:
2960
+ res = self.value.normalize(deep)
2961
+ new_kid: list[AstNode] = []
2962
+ new_kid.append(self.gen_token(Tok.LPAREN))
2963
+ new_kid.append(self.value)
2964
+ new_kid.append(self.gen_token(Tok.RPAREN))
2965
+ AstNode.set_kids(self, nodes=new_kid)
2966
+ return res
2967
+
1649
2968
 
1650
2969
  class YieldExpr(Expr):
1651
2970
  """YieldStmt node type for Jac Ast."""
@@ -1661,6 +2980,20 @@ class YieldExpr(Expr):
1661
2980
  self.with_from = with_from
1662
2981
  AstNode.__init__(self, kid=kid)
1663
2982
 
2983
+ def normalize(self, deep: bool = False) -> bool:
2984
+ """Normalize yield statement node."""
2985
+ res = True
2986
+ if deep:
2987
+ res = self.expr.normalize(deep) if self.expr else res
2988
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_YIELD)]
2989
+ if self.with_from:
2990
+ new_kid.append(self.gen_token(Tok.KW_FROM))
2991
+ if self.expr:
2992
+ new_kid.append(self.expr)
2993
+ new_kid.append(self.gen_token(Tok.SEMI))
2994
+ AstNode.set_kids(self, nodes=new_kid)
2995
+ return res
2996
+
1664
2997
 
1665
2998
  class FuncCall(Expr):
1666
2999
  """FuncCall node type for Jac Ast."""
@@ -1676,6 +3009,17 @@ class FuncCall(Expr):
1676
3009
  self.params = params
1677
3010
  AstNode.__init__(self, kid=kid)
1678
3011
 
3012
+ def normalize(self, deep: bool = True) -> bool:
3013
+ """Normalize ast node."""
3014
+ if deep:
3015
+ res = self.target.normalize(deep)
3016
+ res = res and (not self.params or self.params.normalize(deep))
3017
+ AstNode.__init__(self, kid=[self.target, self.gen_token(Tok.LPAREN, "(")])
3018
+ if self.params: # TODO: Fix
3019
+ self.kid.append(self.params)
3020
+ self.kid.append(self.gen_token(Tok.RPAREN, ")"))
3021
+ return res
3022
+
1679
3023
 
1680
3024
  class IndexSlice(AtomExpr):
1681
3025
  """IndexSlice node type for Jac Ast."""
@@ -1701,6 +3045,32 @@ class IndexSlice(AtomExpr):
1701
3045
  sym_name_node=self,
1702
3046
  )
1703
3047
 
3048
+ def normalize(self, deep: bool = True) -> bool:
3049
+ """Normalize ast node."""
3050
+ res = True
3051
+ if deep:
3052
+ res = self.start.normalize(deep) if self.start else res
3053
+ res = res and self.stop.normalize(deep) if self.stop else res
3054
+ res = res and self.step.normalize(deep) if self.step else res
3055
+ new_kid: list[AstNode] = []
3056
+ new_kid.append(self.gen_token(Tok.LSQUARE))
3057
+ if self.is_range:
3058
+ if self.start:
3059
+ new_kid.append(self.start)
3060
+ if self.stop:
3061
+ new_kid.append(self.gen_token(Tok.COLON))
3062
+ new_kid.append(self.stop)
3063
+ if self.step:
3064
+ new_kid.append(self.gen_token(Tok.COLON))
3065
+ new_kid.append(self.step)
3066
+ elif self.start:
3067
+ new_kid.append(self.start)
3068
+ else:
3069
+ res = False
3070
+ new_kid.append(self.gen_token(Tok.RSQUARE))
3071
+ AstNode.set_kids(self, nodes=new_kid)
3072
+ return res
3073
+
1704
3074
 
1705
3075
  class ArchRef(NameSpec):
1706
3076
  """ArchRef node type for Jac Ast."""
@@ -1722,6 +3092,15 @@ class ArchRef(NameSpec):
1722
3092
  sym_type=SymbolType.TYPE,
1723
3093
  )
1724
3094
 
3095
+ def normalize(self, deep: bool = False) -> bool:
3096
+ """Normalize ast node."""
3097
+ res = True
3098
+ if deep:
3099
+ res = self.name_ref.normalize(deep)
3100
+ new_kid: list[AstNode] = [self.arch, self.name_ref]
3101
+ AstNode.set_kids(self, nodes=new_kid)
3102
+ return res
3103
+
1725
3104
  def py_resolve_name(self) -> str:
1726
3105
  """Resolve name."""
1727
3106
  if isinstance(self.name_ref, Name):
@@ -1750,6 +3129,15 @@ class SpecialVarRef(NameSpec):
1750
3129
  sym_type=SymbolType.VAR,
1751
3130
  )
1752
3131
 
3132
+ def normalize(self, deep: bool = False) -> bool:
3133
+ """Normalize ast node."""
3134
+ res = True
3135
+ if deep:
3136
+ res = self.var.normalize(deep)
3137
+ new_kid: list[AstNode] = [self.var]
3138
+ AstNode.set_kids(self, nodes=new_kid)
3139
+ return res
3140
+
1753
3141
  def py_resolve_name(self) -> str:
1754
3142
  """Resolve name."""
1755
3143
  if self.var.name == Tok.KW_SELF:
@@ -1782,6 +3170,20 @@ class EdgeRefTrailer(Expr):
1782
3170
  self.edges_only = edges_only
1783
3171
  AstNode.__init__(self, kid=kid)
1784
3172
 
3173
+ def normalize(self, deep: bool = True) -> bool:
3174
+ """Normalize ast node."""
3175
+ res = True
3176
+ for expr in self.chain:
3177
+ res = res and expr.normalize(deep)
3178
+ new_kid: list[AstNode] = []
3179
+ if self.edges_only:
3180
+ new_kid.append(self.gen_token(Tok.EDGE_OP))
3181
+ new_kid.append(self.gen_token(Tok.LSQUARE))
3182
+ new_kid.extend(self.chain)
3183
+ new_kid.append(self.gen_token(Tok.RSQUARE))
3184
+ AstNode.set_kids(self, nodes=new_kid)
3185
+ return res
3186
+
1785
3187
 
1786
3188
  class EdgeOpRef(WalkerStmtOnlyNode, AtomExpr):
1787
3189
  """EdgeOpRef node type for Jac Ast."""
@@ -1804,6 +3206,36 @@ class EdgeOpRef(WalkerStmtOnlyNode, AtomExpr):
1804
3206
  sym_type=SymbolType.SEQUENCE,
1805
3207
  )
1806
3208
 
3209
+ def normalize(self, deep: bool = False) -> bool:
3210
+ """Normalize ast node."""
3211
+ res = True
3212
+ if deep:
3213
+ res = self.filter_cond.normalize(deep) if self.filter_cond else res
3214
+ new_kid: list[AstNode] = []
3215
+ if self.edge_dir == EdgeDir.IN:
3216
+ if not self.filter_cond:
3217
+ new_kid.append(self.gen_token(Tok.ARROW_L))
3218
+ else:
3219
+ new_kid.append(self.gen_token(Tok.ARROW_L_P1))
3220
+ new_kid.append(self.filter_cond)
3221
+ new_kid.append(self.gen_token(Tok.ARROW_L_P2))
3222
+ elif self.edge_dir == EdgeDir.OUT:
3223
+ if not self.filter_cond:
3224
+ new_kid.append(self.gen_token(Tok.ARROW_R))
3225
+ else:
3226
+ new_kid.append(self.gen_token(Tok.ARROW_R_P1))
3227
+ new_kid.append(self.filter_cond)
3228
+ new_kid.append(self.gen_token(Tok.ARROW_R_P2))
3229
+ else:
3230
+ if not self.filter_cond:
3231
+ new_kid.append(self.gen_token(Tok.ARROW_BI))
3232
+ else:
3233
+ new_kid.append(self.gen_token(Tok.ARROW_L_P1))
3234
+ new_kid.append(self.filter_cond)
3235
+ new_kid.append(self.gen_token(Tok.ARROW_R_P2))
3236
+ AstNode.set_kids(self, nodes=new_kid)
3237
+ return res
3238
+
1807
3239
 
1808
3240
  class DisconnectOp(WalkerStmtOnlyNode):
1809
3241
  """DisconnectOpRef node type for Jac Ast."""
@@ -1818,6 +3250,15 @@ class DisconnectOp(WalkerStmtOnlyNode):
1818
3250
  AstNode.__init__(self, kid=kid)
1819
3251
  WalkerStmtOnlyNode.__init__(self)
1820
3252
 
3253
+ def normalize(self, deep: bool = False) -> bool:
3254
+ """Normalize ast node."""
3255
+ res = True
3256
+ if deep:
3257
+ res = self.edge_spec.normalize(deep)
3258
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_DELETE), self.edge_spec]
3259
+ AstNode.set_kids(self, nodes=new_kid)
3260
+ return res
3261
+
1821
3262
 
1822
3263
  class ConnectOp(AstNode):
1823
3264
  """ConnectOpRef node type for Jac Ast."""
@@ -1835,6 +3276,49 @@ class ConnectOp(AstNode):
1835
3276
  self.edge_dir = edge_dir
1836
3277
  AstNode.__init__(self, kid=kid)
1837
3278
 
3279
+ def normalize(self, deep: bool = False) -> bool:
3280
+ """Normalize ast node."""
3281
+ res = True
3282
+ if deep:
3283
+ res = self.conn_type.normalize(deep) if self.conn_type else res
3284
+ res = res and self.conn_assign.normalize(deep) if self.conn_assign else res
3285
+ new_kid: list[AstNode] = []
3286
+ if self.edge_dir == EdgeDir.IN:
3287
+ if not self.conn_assign and not self.conn_type:
3288
+ new_kid.append(self.gen_token(Tok.CARROW_L))
3289
+ else:
3290
+ new_kid.append(self.gen_token(Tok.CARROW_L_P1))
3291
+ if self.conn_type:
3292
+ new_kid.append(self.conn_type)
3293
+ if self.conn_assign:
3294
+ new_kid.append(self.gen_token(Tok.COLON))
3295
+ new_kid.append(self.conn_assign)
3296
+ new_kid.append(self.gen_token(Tok.CARROW_L_P2))
3297
+ elif self.edge_dir == EdgeDir.OUT:
3298
+ if not self.conn_assign and not self.conn_type:
3299
+ new_kid.append(self.gen_token(Tok.CARROW_R))
3300
+ else:
3301
+ new_kid.append(self.gen_token(Tok.CARROW_R_P1))
3302
+ if self.conn_type:
3303
+ new_kid.append(self.conn_type)
3304
+ if self.conn_assign:
3305
+ new_kid.append(self.gen_token(Tok.COLON))
3306
+ new_kid.append(self.conn_assign)
3307
+ new_kid.append(self.gen_token(Tok.CARROW_R_P2))
3308
+ else:
3309
+ if not self.conn_assign and not self.conn_type:
3310
+ new_kid.append(self.gen_token(Tok.CARROW_BI))
3311
+ else:
3312
+ new_kid.append(self.gen_token(Tok.CARROW_L_P1))
3313
+ if self.conn_type:
3314
+ new_kid.append(self.conn_type)
3315
+ if self.conn_assign:
3316
+ new_kid.append(self.gen_token(Tok.COLON))
3317
+ new_kid.append(self.conn_assign)
3318
+ new_kid.append(self.gen_token(Tok.CARROW_R_P2))
3319
+ AstNode.set_kids(self, nodes=new_kid)
3320
+ return res
3321
+
1838
3322
 
1839
3323
  class FilterCompr(AtomExpr):
1840
3324
  """FilterCtx node type for Jac Ast."""
@@ -1856,6 +3340,29 @@ class FilterCompr(AtomExpr):
1856
3340
  sym_type=SymbolType.SEQUENCE,
1857
3341
  )
1858
3342
 
3343
+ def normalize(self, deep: bool = False) -> bool:
3344
+ """Normalize ast node."""
3345
+ res = True
3346
+ if deep:
3347
+ res = self.f_type.normalize(deep) if self.f_type else res
3348
+ res = res and self.compares.normalize(deep) if self.compares else res
3349
+ new_kid: list[AstNode] = []
3350
+ if not isinstance(self.parent, EdgeOpRef):
3351
+ new_kid.append(self.gen_token(Tok.LPAREN))
3352
+ if self.f_type:
3353
+ new_kid.append(self.gen_token(Tok.TYPE_OP))
3354
+ new_kid.append(self.gen_token(Tok.NULL_OK))
3355
+ if self.f_type:
3356
+ new_kid.append(self.f_type)
3357
+ if self.compares:
3358
+ if self.f_type:
3359
+ new_kid.append(self.gen_token(Tok.COLON))
3360
+ new_kid.append(self.compares)
3361
+ if not isinstance(self.parent, EdgeOpRef):
3362
+ new_kid.append(self.gen_token(Tok.RPAREN))
3363
+ AstNode.set_kids(self, nodes=new_kid)
3364
+ return res
3365
+
1859
3366
 
1860
3367
  class AssignCompr(AtomExpr):
1861
3368
  """AssignCtx node type for Jac Ast."""
@@ -1875,6 +3382,22 @@ class AssignCompr(AtomExpr):
1875
3382
  sym_type=SymbolType.SEQUENCE,
1876
3383
  )
1877
3384
 
3385
+ def normalize(self, deep: bool = False) -> bool:
3386
+ """Normalize ast node."""
3387
+ res = True
3388
+ if deep:
3389
+ res = self.assigns.normalize(deep)
3390
+ new_kid: list[AstNode] = []
3391
+ if isinstance(self.parent, ConnectOp):
3392
+ new_kid.append(self.assigns)
3393
+ else:
3394
+ new_kid.append(self.gen_token(Tok.LPAREN))
3395
+ new_kid.append(self.gen_token(Tok.EQ))
3396
+ new_kid.append(self.assigns)
3397
+ new_kid.append(self.gen_token(Tok.RPAREN))
3398
+ AstNode.set_kids(self, nodes=new_kid)
3399
+ return res
3400
+
1878
3401
 
1879
3402
  # Match Nodes
1880
3403
  # ------------
@@ -1894,6 +3417,25 @@ class MatchStmt(CodeBlockStmt):
1894
3417
  self.cases = cases
1895
3418
  AstNode.__init__(self, kid=kid)
1896
3419
 
3420
+ def normalize(self, deep: bool = False) -> bool:
3421
+ """Normalize match statement node."""
3422
+ res = True
3423
+ if deep:
3424
+ res = self.target.normalize(deep)
3425
+ for case in self.cases:
3426
+ res = res and case.normalize(deep)
3427
+ new_kid: list[AstNode] = [
3428
+ self.gen_token(Tok.KW_MATCH),
3429
+ self.target,
3430
+ ]
3431
+ new_kid.append(self.gen_token(Tok.LBRACE))
3432
+ for case in self.cases:
3433
+ new_kid.append(case)
3434
+ new_kid.append(self.gen_token(Tok.RBRACE))
3435
+
3436
+ AstNode.set_kids(self, nodes=new_kid)
3437
+ return res
3438
+
1897
3439
 
1898
3440
  class MatchCase(AstNode):
1899
3441
  """MatchCase node type for Jac Ast."""
@@ -1902,7 +3444,7 @@ class MatchCase(AstNode):
1902
3444
  self,
1903
3445
  pattern: MatchPattern,
1904
3446
  guard: Optional[Expr],
1905
- body: SubNodeList[CodeBlockStmt],
3447
+ body: list[CodeBlockStmt],
1906
3448
  kid: Sequence[AstNode],
1907
3449
  ) -> None:
1908
3450
  """Initialize match case node."""
@@ -1911,6 +3453,24 @@ class MatchCase(AstNode):
1911
3453
  self.body = body
1912
3454
  AstNode.__init__(self, kid=kid)
1913
3455
 
3456
+ def normalize(self, deep: bool = False) -> bool:
3457
+ """Normalize match case node."""
3458
+ res = True
3459
+ if deep:
3460
+ res = self.pattern.normalize(deep)
3461
+ res = res and self.guard.normalize(deep) if self.guard else res
3462
+ for stmt in self.body:
3463
+ res = res and stmt.normalize(deep)
3464
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_CASE), self.pattern]
3465
+ if self.guard:
3466
+ new_kid.append(self.gen_token(Tok.KW_IF))
3467
+ new_kid.append(self.guard)
3468
+ new_kid.append(self.gen_token(Tok.COLON))
3469
+ if self.body:
3470
+ new_kid.extend([*self.body])
3471
+ AstNode.set_kids(self, nodes=new_kid)
3472
+ return res
3473
+
1914
3474
 
1915
3475
  class MatchOr(MatchPattern):
1916
3476
  """MatchOr node type for Jac Ast."""
@@ -1924,6 +3484,20 @@ class MatchOr(MatchPattern):
1924
3484
  self.patterns = patterns
1925
3485
  AstNode.__init__(self, kid=kid)
1926
3486
 
3487
+ def normalize(self, deep: bool = False) -> bool:
3488
+ """Normalize match or node."""
3489
+ res = True
3490
+ if deep:
3491
+ for pattern in self.patterns:
3492
+ res = res and pattern.normalize(deep)
3493
+ new_kid: list[AstNode] = []
3494
+ for pattern in self.patterns:
3495
+ new_kid.append(pattern)
3496
+ new_kid.append(self.gen_token(Tok.KW_OR))
3497
+ new_kid.pop()
3498
+ AstNode.set_kids(self, nodes=new_kid)
3499
+ return res
3500
+
1927
3501
 
1928
3502
  class MatchAs(MatchPattern):
1929
3503
  """MatchAs node type for Jac Ast."""
@@ -1939,10 +3513,43 @@ class MatchAs(MatchPattern):
1939
3513
  self.pattern = pattern
1940
3514
  AstNode.__init__(self, kid=kid)
1941
3515
 
3516
+ def normalize(self, deep: bool = False) -> bool:
3517
+ """Normalize match as node."""
3518
+ res = True
3519
+ if deep:
3520
+ res = self.name.normalize(deep)
3521
+ res = res and self.pattern.normalize(deep) if self.pattern else res
3522
+ new_kid: list[AstNode] = []
3523
+ if self.pattern:
3524
+ new_kid.append(self.pattern)
3525
+ new_kid.append(self.gen_token(Tok.KW_AS))
3526
+ new_kid.append(self.name)
3527
+ AstNode.set_kids(self, nodes=new_kid)
3528
+ return res
3529
+
1942
3530
 
1943
3531
  class MatchWild(MatchPattern):
1944
3532
  """Match wild card node type for Jac Ast."""
1945
3533
 
3534
+ def normalize(self, deep: bool = False) -> bool:
3535
+ """Normalize match wild card node."""
3536
+ AstNode.set_kids(
3537
+ self,
3538
+ nodes=[
3539
+ Name(
3540
+ file_path=self.loc.mod_path,
3541
+ name=Tok.NAME,
3542
+ value="_",
3543
+ col_start=self.loc.col_start,
3544
+ col_end=self.loc.col_end,
3545
+ line=self.loc.first_line,
3546
+ pos_start=self.loc.pos_start,
3547
+ pos_end=self.loc.pos_end,
3548
+ )
3549
+ ],
3550
+ )
3551
+ return True
3552
+
1946
3553
 
1947
3554
  class MatchValue(MatchPattern):
1948
3555
  """MatchValue node type for Jac Ast."""
@@ -1956,6 +3563,14 @@ class MatchValue(MatchPattern):
1956
3563
  self.value = value
1957
3564
  AstNode.__init__(self, kid=kid)
1958
3565
 
3566
+ def normalize(self, deep: bool = False) -> bool:
3567
+ """Normalize match value node."""
3568
+ res = True
3569
+ if deep:
3570
+ res = self.value.normalize(deep)
3571
+ AstNode.set_kids(self, nodes=[self.value])
3572
+ return res
3573
+
1959
3574
 
1960
3575
  class MatchSingleton(MatchPattern):
1961
3576
  """MatchSingleton node type for Jac Ast."""
@@ -1969,6 +3584,12 @@ class MatchSingleton(MatchPattern):
1969
3584
  self.value = value
1970
3585
  AstNode.__init__(self, kid=kid)
1971
3586
 
3587
+ def normalize(self, deep: bool = False) -> bool:
3588
+ """Normalize match singleton node."""
3589
+ res = True
3590
+ AstNode.set_kids(self, nodes=[self.value])
3591
+ return res
3592
+
1972
3593
 
1973
3594
  class MatchSequence(MatchPattern):
1974
3595
  """MatchSequence node type for Jac Ast."""
@@ -1982,6 +3603,21 @@ class MatchSequence(MatchPattern):
1982
3603
  self.values = values
1983
3604
  AstNode.__init__(self, kid=kid)
1984
3605
 
3606
+ def normalize(self, deep: bool = False) -> bool:
3607
+ """Normalize match sequence node."""
3608
+ res = True
3609
+ if deep:
3610
+ for value in self.values:
3611
+ res = res and value.normalize(deep)
3612
+ new_kid: list[AstNode] = [self.gen_token(Tok.LSQUARE)]
3613
+ for value in self.values:
3614
+ new_kid.append(value)
3615
+ new_kid.append(self.gen_token(Tok.COMMA))
3616
+ new_kid.pop()
3617
+ new_kid.append(self.gen_token(Tok.RSQUARE))
3618
+ AstNode.set_kids(self, nodes=new_kid)
3619
+ return res
3620
+
1985
3621
 
1986
3622
  class MatchMapping(MatchPattern):
1987
3623
  """MatchMapping node type for Jac Ast."""
@@ -1995,6 +3631,21 @@ class MatchMapping(MatchPattern):
1995
3631
  self.values = values
1996
3632
  AstNode.__init__(self, kid=kid)
1997
3633
 
3634
+ def normalize(self, deep: bool = False) -> bool:
3635
+ """Normalize match mapping node."""
3636
+ res = True
3637
+ if deep:
3638
+ for value in self.values:
3639
+ res = res and value.normalize(deep)
3640
+ new_kid: list[AstNode] = [self.gen_token(Tok.LBRACE)]
3641
+ for value in self.values:
3642
+ new_kid.append(value)
3643
+ new_kid.append(self.gen_token(Tok.COMMA))
3644
+ new_kid.pop()
3645
+ new_kid.append(self.gen_token(Tok.RBRACE))
3646
+ AstNode.set_kids(self, nodes=new_kid)
3647
+ return res
3648
+
1998
3649
 
1999
3650
  class MatchKVPair(MatchPattern):
2000
3651
  """MatchKVPair node type for Jac Ast."""
@@ -2010,6 +3661,19 @@ class MatchKVPair(MatchPattern):
2010
3661
  self.value = value
2011
3662
  AstNode.__init__(self, kid=kid)
2012
3663
 
3664
+ def normalize(self, deep: bool = False) -> bool:
3665
+ """Normalize match key value pair node."""
3666
+ res = True
3667
+ if deep:
3668
+ res = (
3669
+ self.key.normalize(deep) if isinstance(self.key, MatchPattern) else True
3670
+ )
3671
+ res = res and self.value.normalize(deep)
3672
+ op = Tok.EQ if isinstance(self.key, Name) else Tok.COLON
3673
+ new_kid: list[AstNode] = [self.key, self.gen_token(op), self.value]
3674
+ AstNode.set_kids(self, nodes=new_kid)
3675
+ return res
3676
+
2013
3677
 
2014
3678
  class MatchStar(MatchPattern):
2015
3679
  """MatchStar node type for Jac Ast."""
@@ -2025,6 +3689,18 @@ class MatchStar(MatchPattern):
2025
3689
  self.is_list = is_list
2026
3690
  AstNode.__init__(self, kid=kid)
2027
3691
 
3692
+ def normalize(self, deep: bool = False) -> bool:
3693
+ """Normalize match star node."""
3694
+ res = True
3695
+ if deep:
3696
+ res = self.name.normalize(deep)
3697
+ new_kid: list[AstNode] = [
3698
+ self.gen_token(Tok.STAR_MUL if self.is_list else Tok.STAR_POW)
3699
+ ]
3700
+ new_kid.append(self.name)
3701
+ AstNode.set_kids(self, nodes=new_kid)
3702
+ return res
3703
+
2028
3704
 
2029
3705
  class MatchArch(MatchPattern):
2030
3706
  """MatchClass node type for Jac Ast."""
@@ -2042,6 +3718,26 @@ class MatchArch(MatchPattern):
2042
3718
  self.kw_patterns = kw_patterns
2043
3719
  AstNode.__init__(self, kid=kid)
2044
3720
 
3721
+ def normalize(self, deep: bool = False) -> bool:
3722
+ """Normalize match class node."""
3723
+ res = True
3724
+ if deep:
3725
+ res = self.name.normalize(deep)
3726
+ res = res and (not self.arg_patterns or self.arg_patterns.normalize(deep))
3727
+ res = res and (not self.kw_patterns or self.kw_patterns.normalize(deep))
3728
+ new_kid: list[AstNode] = [self.name]
3729
+ new_kid.append(self.gen_token(Tok.LPAREN))
3730
+ if self.arg_patterns:
3731
+ new_kid.append(self.arg_patterns)
3732
+ new_kid.append(self.gen_token(Tok.COMMA))
3733
+ if self.kw_patterns:
3734
+ new_kid.append(self.kw_patterns)
3735
+ else:
3736
+ new_kid.pop()
3737
+ new_kid.append(self.gen_token(Tok.RPAREN))
3738
+ AstNode.set_kids(self, nodes=new_kid)
3739
+ return res
3740
+
2045
3741
 
2046
3742
  # AST Terminal Node Types
2047
3743
  # --------------------------
@@ -2058,7 +3754,6 @@ class Token(AstNode):
2058
3754
  col_end: int,
2059
3755
  pos_start: int,
2060
3756
  pos_end: int,
2061
- kid: Sequence[AstNode],
2062
3757
  ) -> None:
2063
3758
  """Initialize token."""
2064
3759
  self.file_path = file_path
@@ -2069,7 +3764,15 @@ class Token(AstNode):
2069
3764
  self.c_end = col_end
2070
3765
  self.pos_start = pos_start
2071
3766
  self.pos_end = pos_end
2072
- AstNode.__init__(self, kid=kid)
3767
+ AstNode.__init__(self, kid=[])
3768
+
3769
+ def normalize(self, deep: bool = True) -> bool:
3770
+ """Normalize token."""
3771
+ return bool(self.value and self.name)
3772
+
3773
+ def unparse(self) -> str:
3774
+ """Unparse token."""
3775
+ return self.value
2073
3776
 
2074
3777
 
2075
3778
  class Name(Token, NameSpec):
@@ -2085,7 +3788,6 @@ class Name(Token, NameSpec):
2085
3788
  col_end: int,
2086
3789
  pos_start: int,
2087
3790
  pos_end: int,
2088
- kid: Sequence[AstNode],
2089
3791
  is_enum_singleton: bool = False,
2090
3792
  is_kwesc: bool = False,
2091
3793
  ) -> None:
@@ -2102,7 +3804,6 @@ class Name(Token, NameSpec):
2102
3804
  col_end=col_end,
2103
3805
  pos_start=pos_start,
2104
3806
  pos_end=pos_end,
2105
- kid=kid,
2106
3807
  )
2107
3808
  AstSymbolNode.__init__(
2108
3809
  self,
@@ -2111,6 +3812,13 @@ class Name(Token, NameSpec):
2111
3812
  sym_type=SymbolType.VAR,
2112
3813
  )
2113
3814
 
3815
+ def unparse(self) -> str:
3816
+ """Unparse name."""
3817
+ super().unparse()
3818
+ return (f"<>{self.value}" if self.is_kwesc else self.value) + (
3819
+ ",\n" if self.is_enum_singleton else ""
3820
+ )
3821
+
2114
3822
 
2115
3823
  class Literal(Token, AtomExpr):
2116
3824
  """Literal node type for Jac Ast."""
@@ -2140,7 +3848,6 @@ class Literal(Token, AtomExpr):
2140
3848
  col_end: int,
2141
3849
  pos_start: int,
2142
3850
  pos_end: int,
2143
- kid: Sequence[AstNode],
2144
3851
  ) -> None:
2145
3852
  """Initialize token."""
2146
3853
  Token.__init__(
@@ -2153,7 +3860,6 @@ class Literal(Token, AtomExpr):
2153
3860
  col_end=col_end,
2154
3861
  pos_start=pos_start,
2155
3862
  pos_end=pos_end,
2156
- kid=kid,
2157
3863
  )
2158
3864
  AstSymbolNode.__init__(
2159
3865
  self,
@@ -2185,7 +3891,6 @@ class TokenSymbol(Token, AstSymbolNode):
2185
3891
  col_end: int,
2186
3892
  pos_start: int,
2187
3893
  pos_end: int,
2188
- kid: Sequence[AstNode],
2189
3894
  ) -> None:
2190
3895
  """Initialize token."""
2191
3896
  Token.__init__(
@@ -2198,7 +3903,6 @@ class TokenSymbol(Token, AstSymbolNode):
2198
3903
  col_end=col_end,
2199
3904
  pos_start=pos_start,
2200
3905
  pos_end=pos_end,
2201
- kid=kid,
2202
3906
  )
2203
3907
  AstSymbolNode.__init__(
2204
3908
  self,
@@ -2251,6 +3955,8 @@ class String(Literal):
2251
3955
  @property
2252
3956
  def lit_value(self) -> str:
2253
3957
  """Return literal value in its python type."""
3958
+ if isinstance(self.value, bytes):
3959
+ return self.value
2254
3960
  prefix_len = 3 if self.value.startswith(("'''", '"""')) else 1
2255
3961
  if any(
2256
3962
  self.value.startswith(prefix)
@@ -2261,10 +3967,19 @@ class String(Literal):
2261
3967
 
2262
3968
  elif self.value.startswith(("'", '"')):
2263
3969
  ret_str = self.value[prefix_len:-prefix_len]
3970
+ return ret_str.encode().decode("unicode_escape", errors="backslashreplace")
2264
3971
  else:
2265
- ret_str = self.value
2266
- ret_str = ret_str.encode().decode("unicode_escape")
2267
- return ret_str
3972
+ return self.value
3973
+
3974
+ def normalize(self, deep: bool = True) -> bool:
3975
+ """Normalize string."""
3976
+ self.value = r"%s" % self.value
3977
+ return True
3978
+
3979
+ def unparse(self) -> str:
3980
+ """Unparse string."""
3981
+ super().unparse()
3982
+ return repr(self.value)
2268
3983
 
2269
3984
 
2270
3985
  class Bool(Literal):
@@ -2314,7 +4029,6 @@ class EmptyToken(Token):
2314
4029
  col_end=0,
2315
4030
  pos_start=0,
2316
4031
  pos_end=0,
2317
- kid=[],
2318
4032
  )
2319
4033
 
2320
4034