jaclang 0.5.7__py3-none-any.whl → 0.5.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jaclang might be problematic. Click here for more details.

Files changed (41) hide show
  1. jaclang/cli/cli.py +55 -7
  2. jaclang/cli/cmdreg.py +12 -0
  3. jaclang/compiler/__init__.py +6 -3
  4. jaclang/compiler/__jac_gen__/jac_parser.py +2 -2
  5. jaclang/compiler/absyntree.py +1725 -55
  6. jaclang/compiler/codeloc.py +7 -0
  7. jaclang/compiler/compile.py +1 -1
  8. jaclang/compiler/constant.py +17 -0
  9. jaclang/compiler/parser.py +131 -112
  10. jaclang/compiler/passes/main/def_impl_match_pass.py +19 -3
  11. jaclang/compiler/passes/main/def_use_pass.py +1 -1
  12. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +357 -0
  13. jaclang/compiler/passes/main/import_pass.py +7 -3
  14. jaclang/compiler/passes/main/pyast_gen_pass.py +112 -76
  15. jaclang/compiler/passes/main/pyast_load_pass.py +1779 -206
  16. jaclang/compiler/passes/main/schedules.py +2 -1
  17. jaclang/compiler/passes/main/sym_tab_build_pass.py +20 -28
  18. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +14 -5
  19. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +8 -8
  20. jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +7 -0
  21. jaclang/compiler/passes/main/type_check_pass.py +0 -1
  22. jaclang/compiler/passes/tool/jac_formatter_pass.py +8 -17
  23. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +43 -0
  24. jaclang/compiler/passes/utils/mypy_ast_build.py +28 -14
  25. jaclang/compiler/symtable.py +23 -2
  26. jaclang/compiler/tests/test_parser.py +53 -0
  27. jaclang/compiler/workspace.py +52 -26
  28. jaclang/core/construct.py +54 -2
  29. jaclang/plugin/default.py +51 -13
  30. jaclang/plugin/feature.py +16 -2
  31. jaclang/plugin/spec.py +9 -5
  32. jaclang/utils/helpers.py +25 -0
  33. jaclang/utils/lang_tools.py +4 -1
  34. jaclang/utils/test.py +1 -0
  35. jaclang/utils/tests/test_lang_tools.py +11 -14
  36. jaclang/utils/treeprinter.py +10 -2
  37. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/METADATA +1 -1
  38. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/RECORD +41 -38
  39. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/WHEEL +1 -1
  40. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/entry_points.txt +0 -0
  41. {jaclang-0.5.7.dist-info → jaclang-0.5.8.dist-info}/top_level.txt +0 -0
@@ -6,10 +6,17 @@ 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
+ )
13
20
  from jaclang.utils.treeprinter import dotgen_ast_tree, print_ast_tree
14
21
 
15
22
 
@@ -74,12 +81,40 @@ class AstNode:
74
81
  else:
75
82
  raise ValueError(f"Empty kid for Token {type(self).__name__}")
76
83
 
84
+ def gen_token(self, name: Tok, value: Optional[str] = None) -> Token:
85
+ """Generate token."""
86
+ value = (
87
+ value
88
+ if value
89
+ else (
90
+ DELIM_MAP[name]
91
+ if name in DELIM_MAP
92
+ else TOKEN_MAP[name.value] if name.value in TOKEN_MAP else name.value
93
+ )
94
+ )
95
+ return Token(
96
+ name=name,
97
+ value=value,
98
+ file_path=self.loc.mod_path,
99
+ col_start=self.loc.col_start,
100
+ col_end=0,
101
+ line=self.loc.first_line,
102
+ pos_start=0,
103
+ pos_end=0,
104
+ )
105
+
77
106
  def get_all_sub_nodes(self, typ: Type[T], brute_force: bool = True) -> list[T]:
78
107
  """Get all sub nodes of type."""
79
108
  from jaclang.compiler.passes import Pass
80
109
 
81
110
  return Pass.get_all_sub_nodes(node=self, typ=typ, brute_force=brute_force)
82
111
 
112
+ def format(self) -> str:
113
+ """Get all sub nodes of type."""
114
+ from jaclang.compiler.passes.tool import JacFormatPass
115
+
116
+ return JacFormatPass(self, None).ir.gen.jac
117
+
83
118
  def to_dict(self) -> dict[str, str]:
84
119
  """Return dict representation of node."""
85
120
  ret = {
@@ -108,6 +143,18 @@ class AstNode:
108
143
  ret += k.flatten()
109
144
  return ret
110
145
 
146
+ def normalize(self, deep: bool = False) -> bool:
147
+ """Normalize ast node."""
148
+ return False
149
+
150
+ def unparse(self) -> str:
151
+ """Unparse ast node."""
152
+ valid = self.normalize()
153
+ res = " ".join([i.unparse() for i in self.kid])
154
+ if not valid:
155
+ raise NotImplementedError(f"Node {type(self).__name__} is not valid.")
156
+ return res
157
+
111
158
 
112
159
  class AstSymbolNode(AstNode):
113
160
  """Nodes that have link to a symbol in symbol table."""
@@ -120,6 +167,7 @@ class AstSymbolNode(AstNode):
120
167
  self.sym_name: str = sym_name
121
168
  self.sym_name_node = sym_name_node
122
169
  self.sym_type: SymbolType = sym_type
170
+ self.sym_info: SymbolInfo = SymbolInfo()
123
171
  self.py_ctx_func: Type[ast3.AST] = ast3.Load
124
172
 
125
173
 
@@ -144,6 +192,9 @@ class AstAccessNode(AstNode):
144
192
  )
145
193
 
146
194
 
195
+ T = TypeVar("T", bound=AstNode)
196
+
197
+
147
198
  class AstDocNode(AstNode):
148
199
  """Nodes that have access."""
149
200
 
@@ -195,11 +246,25 @@ class WalkerStmtOnlyNode(AstNode):
195
246
  class AstImplOnlyNode(AstNode):
196
247
  """ImplOnly node type for Jac Ast."""
197
248
 
198
- def __init__(self, decl_link: Optional[AstNode]) -> None:
249
+ def __init__(self, body: SubNodeList, decl_link: Optional[AstNode]) -> None:
199
250
  """Initialize impl only node."""
251
+ self.body = body
200
252
  self.decl_link = decl_link
201
253
 
202
254
 
255
+ class AstImplNeedingNode(AstSymbolNode, Generic[T]):
256
+ """Impl needing node type for Jac Ast."""
257
+
258
+ def __init__(self, body: Optional[T]) -> None:
259
+ """Initialize impl needing node."""
260
+ self.body = body
261
+
262
+ @property
263
+ def needs_impl(self) -> bool:
264
+ """Need impl."""
265
+ return self.body is None
266
+
267
+
203
268
  class Expr(AstNode):
204
269
  """Expr node type for Jac Ast."""
205
270
 
@@ -240,9 +305,6 @@ class MatchPattern(AstNode):
240
305
  """MatchPattern node type for Jac Ast."""
241
306
 
242
307
 
243
- T = TypeVar("T", bound=AstNode)
244
-
245
-
246
308
  class SubTag(AstNode, Generic[T]):
247
309
  """SubTag node type for Jac Ast."""
248
310
 
@@ -255,22 +317,54 @@ class SubTag(AstNode, Generic[T]):
255
317
  self.tag = tag
256
318
  AstNode.__init__(self, kid=kid)
257
319
 
320
+ def normalize(self, deep: bool = False) -> bool:
321
+ """Normalize sub tag node."""
322
+ res = self.tag.normalize() if deep else True
323
+ AstNode.__init__(self, kid=[self.gen_token(Tok.COLON), self.tag])
324
+ return res
325
+
258
326
 
259
327
  # SubNodeList were created to simplify the type safety of the
260
328
  # 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.
329
+ # of mixed type in the kid list of the subnodelist as well as
330
+ # separating out typed items of interest in the ast node class body.
263
331
  class SubNodeList(AstNode, Generic[T]):
264
332
  """SubNodeList node type for Jac Ast."""
265
333
 
266
334
  def __init__(
267
335
  self,
268
336
  items: list[T],
337
+ delim: Optional[Tok],
269
338
  kid: Sequence[AstNode],
339
+ left_enc: Optional[Token] = None,
340
+ right_enc: Optional[Token] = None,
270
341
  ) -> None:
271
342
  """Initialize sub node list node."""
272
343
  self.items = items
273
- AstNode.__init__(self, kid=kid)
344
+ self.delim = delim
345
+ self.left_enc = left_enc
346
+ self.right_enc = right_enc
347
+ AstNode.__init__(self, kid=kid)
348
+
349
+ def normalize(self, deep: bool = False) -> bool:
350
+ """Normalize sub node list node."""
351
+ res = True
352
+ if deep:
353
+ for i in self.items:
354
+ res = res and i.normalize()
355
+ new_kid: list[AstNode] = []
356
+ if self.left_enc:
357
+ new_kid.append(self.left_enc)
358
+ for i in self.items:
359
+ new_kid.append(i)
360
+ if self.delim:
361
+ new_kid.append(self.gen_token(self.delim))
362
+ if self.delim and self.items:
363
+ new_kid.pop()
364
+ if self.right_enc:
365
+ new_kid.append(self.right_enc)
366
+ AstNode.__init__(self, kid=new_kid if len(new_kid) else [EmptyToken()])
367
+ return res
274
368
 
275
369
 
276
370
  # AST Mid Level Node Types
@@ -300,6 +394,25 @@ class Module(AstDocNode):
300
394
  AstNode.__init__(self, kid=kid)
301
395
  AstDocNode.__init__(self, doc=doc)
302
396
 
397
+ def normalize(self, deep: bool = False) -> bool:
398
+ """Normalize module node."""
399
+ res = True
400
+ if deep:
401
+ res = self.doc.normalize() if self.doc else True
402
+ for i in self.body:
403
+ res = res and i.normalize()
404
+ new_kid: list[AstNode] = []
405
+ if self.doc:
406
+ new_kid.append(self.doc)
407
+ new_kid.extend(self.body)
408
+ AstNode.__init__(self, kid=new_kid)
409
+ return res
410
+
411
+ def unparse(self) -> str:
412
+ """Unparse module node."""
413
+ super().unparse()
414
+ return self.format()
415
+
303
416
 
304
417
  class GlobalVars(ElementStmt, AstAccessNode):
305
418
  """GlobalVars node type for Jac Ast."""
@@ -319,6 +432,27 @@ class GlobalVars(ElementStmt, AstAccessNode):
319
432
  AstAccessNode.__init__(self, access=access)
320
433
  AstDocNode.__init__(self, doc=doc)
321
434
 
435
+ def normalize(self, deep: bool = False) -> bool:
436
+ """Normalize global var node."""
437
+ res = True
438
+ if deep:
439
+ res = self.access.normalize(deep) if self.access else True
440
+ res = res and self.assignments.normalize(deep)
441
+ res = res and self.doc.normalize(deep) if self.doc else res
442
+ new_kid: list[AstNode] = []
443
+ if self.is_frozen:
444
+ new_kid.append(self.gen_token(Tok.KW_LET))
445
+ else:
446
+ new_kid.append(self.gen_token(Tok.KW_GLOBAL))
447
+ if self.doc:
448
+ new_kid.append(self.doc)
449
+ if self.access:
450
+ new_kid.append(self.access)
451
+ new_kid.append(self.assignments)
452
+ new_kid.append(self.gen_token(Tok.SEMI))
453
+ AstNode.__init__(self, kid=new_kid)
454
+ return res
455
+
322
456
 
323
457
  class Test(AstSymbolNode, ElementStmt):
324
458
  """Test node type for Jac Ast."""
@@ -346,7 +480,6 @@ class Test(AstSymbolNode, ElementStmt):
346
480
  line=name.loc.first_line,
347
481
  pos_start=name.pos_start,
348
482
  pos_end=name.pos_end,
349
- kid=name.kid,
350
483
  )
351
484
  )
352
485
  self.name.parent = self
@@ -363,8 +496,26 @@ class Test(AstSymbolNode, ElementStmt):
363
496
  )
364
497
  AstDocNode.__init__(self, doc=doc)
365
498
 
499
+ def normalize(self, deep: bool = False) -> bool:
500
+ """Normalize test node."""
501
+ res = True
502
+ if deep:
503
+ res = self.name.normalize(deep)
504
+ res = res and self.body.normalize(deep)
505
+ res = res and self.doc.normalize(deep) if self.doc else res
506
+ new_kid: list[AstNode] = []
507
+ if self.doc:
508
+ new_kid.append(self.doc)
509
+ new_kid.append(self.gen_token(Tok.KW_TEST))
510
+ new_kid.append(self.name)
511
+
512
+ new_kid.append(self.body)
513
+
514
+ AstNode.__init__(self, kid=new_kid)
515
+ return res
366
516
 
367
- class ModuleCode(ElementStmt):
517
+
518
+ class ModuleCode(ElementStmt, ArchBlockStmt, EnumBlockStmt):
368
519
  """Free mod code for Jac Ast."""
369
520
 
370
521
  def __init__(
@@ -380,6 +531,26 @@ class ModuleCode(ElementStmt):
380
531
  AstNode.__init__(self, kid=kid)
381
532
  AstDocNode.__init__(self, doc=doc)
382
533
 
534
+ def normalize(self, deep: bool = False) -> bool:
535
+ """Normalize module code node."""
536
+ res = True
537
+ if deep:
538
+ res = self.name.normalize(deep) if self.name else res
539
+ res = res and self.body.normalize(deep)
540
+ res = res and self.doc.normalize(deep) if self.doc else res
541
+ new_kid: list[AstNode] = []
542
+ if self.doc:
543
+ new_kid.append(self.doc)
544
+ new_kid.append(self.gen_token(Tok.KW_WITH))
545
+ new_kid.append(self.gen_token(Tok.KW_ENTRY))
546
+ if self.name:
547
+ new_kid.append(self.name)
548
+
549
+ new_kid.append(self.body)
550
+
551
+ AstNode.__init__(self, kid=new_kid)
552
+ return res
553
+
383
554
 
384
555
  class PyInlineCode(ElementStmt, ArchBlockStmt, EnumBlockStmt, CodeBlockStmt):
385
556
  """Inline Python code node type for Jac Ast."""
@@ -395,6 +566,21 @@ class PyInlineCode(ElementStmt, ArchBlockStmt, EnumBlockStmt, CodeBlockStmt):
395
566
  AstNode.__init__(self, kid=kid)
396
567
  AstDocNode.__init__(self, doc=doc)
397
568
 
569
+ def normalize(self, deep: bool = False) -> bool:
570
+ """Normalize inline python code node."""
571
+ res = True
572
+ if deep:
573
+ res = self.code.normalize(deep)
574
+ res = res and self.doc.normalize(deep) if self.doc else res
575
+ new_kid: list[AstNode] = []
576
+ if self.doc:
577
+ new_kid.append(self.doc)
578
+ new_kid.append(self.gen_token(Tok.PYNLINE))
579
+ new_kid.append(self.code)
580
+ new_kid.append(self.gen_token(Tok.PYNLINE))
581
+ AstNode.__init__(self, kid=new_kid)
582
+ return res
583
+
398
584
 
399
585
  class Import(ElementStmt, CodeBlockStmt):
400
586
  """Import node type for Jac Ast."""
@@ -416,6 +602,36 @@ class Import(ElementStmt, CodeBlockStmt):
416
602
  AstNode.__init__(self, kid=kid)
417
603
  AstDocNode.__init__(self, doc=doc)
418
604
 
605
+ def normalize(self, deep: bool = False) -> bool:
606
+ """Normalize import node."""
607
+ res = True
608
+ if deep:
609
+ res = self.lang.normalize(deep)
610
+ for p in self.paths:
611
+ res = res and p.normalize(deep)
612
+ res = res and self.items.normalize(deep) if self.items else res
613
+ res = res and self.doc.normalize(deep) if self.doc else res
614
+ new_kid: list[AstNode] = []
615
+ if self.doc:
616
+ new_kid.append(self.doc)
617
+ if self.is_absorb:
618
+ new_kid.append(self.gen_token(Tok.KW_INCLUDE))
619
+ else:
620
+ new_kid.append(self.gen_token(Tok.KW_IMPORT))
621
+ new_kid.append(self.lang)
622
+ if self.items:
623
+ new_kid.append(self.gen_token(Tok.KW_FROM))
624
+ for p in self.paths:
625
+ new_kid.append(p)
626
+ new_kid.append(self.gen_token(Tok.COMMA))
627
+ new_kid.pop()
628
+ if self.items:
629
+ new_kid.append(self.gen_token(Tok.COMMA))
630
+ new_kid.append(self.items)
631
+ new_kid.append(self.gen_token(Tok.SEMI))
632
+ AstNode.__init__(self, kid=new_kid)
633
+ return res
634
+
419
635
 
420
636
  class ModulePath(AstSymbolNode):
421
637
  """ModulePath node type for Jac Ast."""
@@ -442,6 +658,29 @@ class ModulePath(AstSymbolNode):
442
658
  sym_type=SymbolType.MODULE,
443
659
  )
444
660
 
661
+ def normalize(self, deep: bool = False) -> bool:
662
+ """Normalize module path node."""
663
+ res = True
664
+ if deep:
665
+ if self.path:
666
+ for p in self.path:
667
+ res = res and p.normalize(deep)
668
+ res = res and self.alias.normalize(deep) if self.alias else res
669
+ new_kid: list[AstNode] = []
670
+ for _ in range(self.level):
671
+ new_kid.append(self.gen_token(Tok.DOT))
672
+ if self.path:
673
+ for p in self.path:
674
+ res = res and p.normalize(deep)
675
+ new_kid.append(p)
676
+ new_kid.append(self.gen_token(Tok.DOT))
677
+ new_kid.pop()
678
+ if self.alias:
679
+ res = res and self.alias.normalize(deep)
680
+ new_kid.append(self.alias)
681
+ AstNode.__init__(self, kid=new_kid)
682
+ return res
683
+
445
684
  @property
446
685
  def path_str(self) -> str:
447
686
  """Get path string."""
@@ -470,8 +709,21 @@ class ModuleItem(AstSymbolNode):
470
709
  sym_type=SymbolType.MOD_VAR,
471
710
  )
472
711
 
473
-
474
- class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
712
+ def normalize(self, deep: bool = False) -> bool:
713
+ """Normalize module item node."""
714
+ res = True
715
+ if deep:
716
+ res = res and self.name.normalize(deep)
717
+ res = res and self.alias.normalize(deep) if self.alias else res
718
+ new_kid: list[AstNode] = [self.name]
719
+ if self.alias:
720
+ new_kid.append(self.gen_token(Tok.KW_AS))
721
+ new_kid.append(self.alias)
722
+ AstNode.__init__(self, kid=new_kid)
723
+ return res
724
+
725
+
726
+ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt, AstImplNeedingNode):
475
727
  """ObjectArch node type for Jac Ast."""
476
728
 
477
729
  def __init__(
@@ -490,7 +742,6 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
490
742
  self.name = name
491
743
  self.arch_type = arch_type
492
744
  self.base_classes = base_classes
493
- self.body = body
494
745
  AstNode.__init__(self, kid=kid)
495
746
  AstSymbolNode.__init__(
496
747
  self,
@@ -514,6 +765,7 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
514
765
  )
515
766
  ),
516
767
  )
768
+ AstImplNeedingNode.__init__(self, body=body)
517
769
  AstAccessNode.__init__(self, access=access)
518
770
  AstDocNode.__init__(self, doc=doc)
519
771
  AstSemStrNode.__init__(self, semstr=semstr)
@@ -529,6 +781,41 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt):
529
781
  )
530
782
  return any(isinstance(i, Ability) and i.is_abstract for i in body)
531
783
 
784
+ def normalize(self, deep: bool = False) -> bool:
785
+ """Normalize architype node."""
786
+ res = True
787
+ if deep:
788
+ res = self.name.normalize(deep)
789
+ res = res and self.arch_type.normalize(deep)
790
+ res = res and self.access.normalize(deep) if self.access else res
791
+ res = (
792
+ res and self.base_classes.normalize(deep) if self.base_classes else res
793
+ )
794
+ res = res and self.body.normalize(deep) if self.body else res
795
+ res = res and self.doc.normalize(deep) if self.doc else res
796
+ res = res and self.semstr.normalize(deep) if self.semstr else res
797
+ res = res and self.decorators.normalize(deep) if self.decorators else res
798
+ new_kid: list[AstNode] = []
799
+ if self.doc:
800
+ new_kid.append(self.doc)
801
+ new_kid.append(self.arch_type)
802
+ if self.access:
803
+ new_kid.append(self.access)
804
+ new_kid.append(self.name)
805
+ if self.base_classes:
806
+ new_kid.append(self.gen_token(Tok.COLON))
807
+ new_kid.append(self.base_classes)
808
+ new_kid.append(self.gen_token(Tok.COLON))
809
+ if self.body:
810
+ if isinstance(self.body, AstImplOnlyNode):
811
+ new_kid.append(self.body.body)
812
+ else:
813
+ new_kid.append(self.body)
814
+ else:
815
+ new_kid.append(self.gen_token(Tok.SEMI))
816
+ AstNode.__init__(self, kid=new_kid)
817
+ return res
818
+
532
819
 
533
820
  class ArchDef(ArchSpec, AstImplOnlyNode):
534
821
  """ArchDef node type for Jac Ast."""
@@ -544,7 +831,6 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
544
831
  ) -> None:
545
832
  """Initialize arch def node."""
546
833
  self.target = target
547
- self.body = body
548
834
  AstNode.__init__(self, kid=kid)
549
835
  AstSymbolNode.__init__(
550
836
  self,
@@ -554,10 +840,28 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
554
840
  )
555
841
  AstDocNode.__init__(self, doc=doc)
556
842
  ArchSpec.__init__(self, decorators=decorators)
557
- AstImplOnlyNode.__init__(self, decl_link=decl_link)
843
+ AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
844
+
845
+ def normalize(self, deep: bool = False) -> bool:
846
+ """Normalize arch def node."""
847
+ res = True
848
+ if deep:
849
+ res = self.target.normalize(deep)
850
+ res = res and self.body.normalize(deep)
851
+ res = res and self.doc.normalize(deep) if self.doc else res
852
+ res = res and self.decorators.normalize(deep) if self.decorators else res
853
+ new_kid: list[AstNode] = []
854
+ if self.doc:
855
+ new_kid.append(self.doc)
856
+ new_kid.append(self.target)
558
857
 
858
+ new_kid.append(self.body)
559
859
 
560
- class Enum(ArchSpec, AstAccessNode):
860
+ AstNode.__init__(self, kid=new_kid)
861
+ return res
862
+
863
+
864
+ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode):
561
865
  """Enum node type for Jac Ast."""
562
866
 
563
867
  def __init__(
@@ -574,7 +878,6 @@ class Enum(ArchSpec, AstAccessNode):
574
878
  """Initialize object arch node."""
575
879
  self.name = name
576
880
  self.base_classes = base_classes
577
- self.body = body
578
881
  AstNode.__init__(self, kid=kid)
579
882
  AstSymbolNode.__init__(
580
883
  self,
@@ -582,11 +885,46 @@ class Enum(ArchSpec, AstAccessNode):
582
885
  sym_name_node=name,
583
886
  sym_type=SymbolType.ENUM_ARCH,
584
887
  )
888
+ AstImplNeedingNode.__init__(self, body=body)
585
889
  AstAccessNode.__init__(self, access=access)
586
890
  AstDocNode.__init__(self, doc=doc)
587
891
  AstSemStrNode.__init__(self, semstr=semstr)
588
892
  ArchSpec.__init__(self, decorators=decorators)
589
893
 
894
+ def normalize(self, deep: bool = False) -> bool:
895
+ """Normalize enum node."""
896
+ res = True
897
+ if deep:
898
+ res = self.name.normalize(deep)
899
+ res = res and self.access.normalize(deep) if self.access else res
900
+ res = (
901
+ res and self.base_classes.normalize(deep) if self.base_classes else res
902
+ )
903
+ res = res and self.body.normalize(deep) if self.body else res
904
+ res = res and self.doc.normalize(deep) if self.doc else res
905
+ res = res and self.semstr.normalize(deep) if self.semstr else res
906
+ res = res and self.decorators.normalize(deep) if self.decorators else res
907
+ new_kid: list[AstNode] = []
908
+ if self.doc:
909
+ new_kid.append(self.doc)
910
+ new_kid.append(self.gen_token(Tok.KW_ENUM))
911
+ if self.access:
912
+ new_kid.append(self.access)
913
+ new_kid.append(self.name)
914
+ if self.base_classes:
915
+ new_kid.append(self.gen_token(Tok.COLON))
916
+ new_kid.append(self.base_classes)
917
+ new_kid.append(self.gen_token(Tok.COLON))
918
+ if self.body:
919
+ if isinstance(self.body, AstImplOnlyNode):
920
+ new_kid.append(self.body.body)
921
+ else:
922
+ new_kid.append(self.body)
923
+ else:
924
+ new_kid.append(self.gen_token(Tok.SEMI))
925
+ AstNode.__init__(self, kid=new_kid)
926
+ return res
927
+
590
928
 
591
929
  class EnumDef(ArchSpec, AstImplOnlyNode):
592
930
  """EnumDef node type for Jac Ast."""
@@ -602,7 +940,6 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
602
940
  ) -> None:
603
941
  """Initialize arch def node."""
604
942
  self.target = target
605
- self.body = body
606
943
  AstNode.__init__(self, kid=kid)
607
944
  AstSymbolNode.__init__(
608
945
  self,
@@ -612,24 +949,41 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
612
949
  )
613
950
  AstDocNode.__init__(self, doc=doc)
614
951
  ArchSpec.__init__(self, decorators=decorators)
615
- AstImplOnlyNode.__init__(self, decl_link=decl_link)
952
+ AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
953
+
954
+ def normalize(self, deep: bool = False) -> bool:
955
+ """Normalize enum def node."""
956
+ res = True
957
+ if deep:
958
+ res = self.target.normalize(deep)
959
+ res = res and self.body.normalize(deep)
960
+ res = res and self.doc.normalize(deep) if self.doc else res
961
+ res = res and self.decorators.normalize(deep) if self.decorators else res
962
+ new_kid: list[AstNode] = []
963
+ if self.doc:
964
+ new_kid.append(self.doc)
965
+ new_kid.append(self.target)
966
+
967
+ new_kid.append(self.body)
968
+
969
+ AstNode.__init__(self, kid=new_kid)
970
+ return res
616
971
 
617
972
 
618
973
  class Ability(
619
- AstSymbolNode,
620
974
  AstAccessNode,
621
975
  ElementStmt,
622
976
  AstAsyncNode,
623
977
  ArchBlockStmt,
624
978
  CodeBlockStmt,
625
979
  AstSemStrNode,
980
+ AstImplNeedingNode,
626
981
  ):
627
982
  """Ability node type for Jac Ast."""
628
983
 
629
984
  def __init__(
630
985
  self,
631
986
  name_ref: NameSpec,
632
- is_func: bool,
633
987
  is_async: bool,
634
988
  is_override: bool,
635
989
  is_static: bool,
@@ -644,14 +998,13 @@ class Ability(
644
998
  ) -> None:
645
999
  """Initialize func arch node."""
646
1000
  self.name_ref = name_ref
647
- self.is_func = is_func
648
1001
  self.is_override = is_override
649
1002
  self.is_static = is_static
650
1003
  self.is_abstract = is_abstract
651
1004
  self.decorators = decorators
652
1005
  self.signature = signature
653
- self.body = body
654
1006
  AstNode.__init__(self, kid=kid)
1007
+ AstImplNeedingNode.__init__(self, body=body)
655
1008
  AstSemStrNode.__init__(self, semstr=semstr)
656
1009
  AstSymbolNode.__init__(
657
1010
  self,
@@ -673,6 +1026,11 @@ class Ability(
673
1026
  self.sym_type = SymbolType.METHOD
674
1027
  return check
675
1028
 
1029
+ @property
1030
+ def is_func(self) -> bool:
1031
+ """Check if is func."""
1032
+ return isinstance(self.body, FuncSignature)
1033
+
676
1034
  @property
677
1035
  def is_genai_ability(self) -> bool:
678
1036
  """Check if is genai_ability."""
@@ -687,6 +1045,46 @@ class Ability(
687
1045
  else:
688
1046
  raise NotImplementedError
689
1047
 
1048
+ def normalize(self, deep: bool = False) -> bool:
1049
+ """Normalize ast node."""
1050
+ res = True
1051
+ if deep:
1052
+ res = self.name_ref.normalize(deep)
1053
+ res = res and self.access.normalize(deep) if self.access else res
1054
+ res = res and self.signature.normalize(deep) if self.signature else res
1055
+ res = res and self.body.normalize(deep) if self.body else res
1056
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1057
+ res = res and self.decorators.normalize(deep) if self.decorators else res
1058
+ res = res and self.doc.normalize(deep) if self.doc else res
1059
+ new_kid: list[AstNode] = []
1060
+ if self.doc:
1061
+ new_kid.append(self.doc)
1062
+ if self.is_async:
1063
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1064
+ if self.is_override:
1065
+ new_kid.append(self.gen_token(Tok.KW_OVERRIDE))
1066
+ if self.is_static:
1067
+ new_kid.append(self.gen_token(Tok.KW_STATIC))
1068
+ new_kid.append(self.gen_token(Tok.KW_CAN))
1069
+ if self.access:
1070
+ new_kid.append(self.access)
1071
+ if self.semstr:
1072
+ new_kid.append(self.semstr)
1073
+ new_kid.append(self.name_ref)
1074
+ if self.signature:
1075
+ new_kid.append(self.signature)
1076
+ if self.body:
1077
+ if isinstance(self.body, AstImplOnlyNode):
1078
+ new_kid.append(self.body.body)
1079
+ else:
1080
+ new_kid.append(self.gen_token(Tok.LBRACE))
1081
+ new_kid.append(self.body)
1082
+ new_kid.append(self.gen_token(Tok.RBRACE))
1083
+ else:
1084
+ new_kid.append(self.gen_token(Tok.SEMI))
1085
+ AstNode.__init__(self, kid=new_kid)
1086
+ return res
1087
+
690
1088
 
691
1089
  class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
692
1090
  """AbilityDef node type for Jac Ast."""
@@ -704,7 +1102,6 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
704
1102
  """Initialize ability def node."""
705
1103
  self.target = target
706
1104
  self.signature = signature
707
- self.body = body
708
1105
  self.decorators = decorators
709
1106
  AstNode.__init__(self, kid=kid)
710
1107
  AstSymbolNode.__init__(
@@ -714,7 +1111,27 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
714
1111
  sym_type=SymbolType.IMPL,
715
1112
  )
716
1113
  AstDocNode.__init__(self, doc=doc)
717
- AstImplOnlyNode.__init__(self, decl_link=decl_link)
1114
+ AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
1115
+
1116
+ def normalize(self, deep: bool = False) -> bool:
1117
+ """Normalize ability def node."""
1118
+ res = True
1119
+ if deep:
1120
+ res = self.target.normalize(deep)
1121
+ res = res and self.signature.normalize(deep)
1122
+ res = res and self.body.normalize(deep)
1123
+ res = res and self.doc.normalize(deep) if self.doc else res
1124
+ res = res and self.decorators.normalize(deep) if self.decorators else res
1125
+ new_kid: list[AstNode] = []
1126
+ if self.doc:
1127
+ new_kid.append(self.doc)
1128
+ new_kid.append(self.target)
1129
+ new_kid.append(self.signature)
1130
+
1131
+ new_kid.append(self.body)
1132
+
1133
+ AstNode.__init__(self, kid=new_kid)
1134
+ return res
718
1135
 
719
1136
  @property
720
1137
  def is_method(self) -> bool:
@@ -741,6 +1158,23 @@ class FuncSignature(AstSemStrNode):
741
1158
  AstNode.__init__(self, kid=kid)
742
1159
  AstSemStrNode.__init__(self, semstr=semstr)
743
1160
 
1161
+ def normalize(self, deep: bool = False) -> bool:
1162
+ """Normalize ast node."""
1163
+ res = True
1164
+ if deep:
1165
+ res = self.params.normalize(deep) if self.params else res
1166
+ res = res and self.return_type.normalize(deep) if self.return_type else res
1167
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1168
+ new_kid: list[AstNode] = [self.gen_token(Tok.LPAREN)]
1169
+ if self.params:
1170
+ new_kid.append(self.params)
1171
+ new_kid.append(self.gen_token(Tok.RPAREN))
1172
+ if self.return_type:
1173
+ new_kid.append(self.gen_token(Tok.RETURN_HINT))
1174
+ new_kid.append(self.return_type)
1175
+ AstNode.__init__(self, kid=new_kid)
1176
+ return res
1177
+
744
1178
  @property
745
1179
  def is_method(self) -> bool:
746
1180
  """Check if is method."""
@@ -776,6 +1210,30 @@ class EventSignature(AstSemStrNode):
776
1210
  AstNode.__init__(self, kid=kid)
777
1211
  AstSemStrNode.__init__(self, semstr=semstr)
778
1212
 
1213
+ def normalize(self, deep: bool = False) -> bool:
1214
+ """Normalize ast node."""
1215
+ res = True
1216
+ if deep:
1217
+ res = self.event.normalize(deep)
1218
+ res = (
1219
+ res and self.arch_tag_info.normalize(deep)
1220
+ if self.arch_tag_info
1221
+ else res
1222
+ )
1223
+ res = res and self.return_type.normalize(deep) if self.return_type else res
1224
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1225
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_WITH)]
1226
+ if self.arch_tag_info:
1227
+ new_kid.append(self.arch_tag_info)
1228
+ new_kid.append(self.event)
1229
+ if self.return_type:
1230
+ if self.semstr:
1231
+ new_kid.append(self.semstr)
1232
+ new_kid.append(self.gen_token(Tok.RETURN_HINT))
1233
+ new_kid.append(self.return_type)
1234
+ AstNode.__init__(self, kid=new_kid)
1235
+ return res
1236
+
779
1237
  @property
780
1238
  def is_method(self) -> bool:
781
1239
  """Check if is method."""
@@ -800,6 +1258,18 @@ class ArchRefChain(AstNode):
800
1258
  self.archs = archs
801
1259
  AstNode.__init__(self, kid=kid)
802
1260
 
1261
+ def normalize(self, deep: bool = False) -> bool:
1262
+ """Normalize ast node."""
1263
+ res = True
1264
+ if deep:
1265
+ for a in self.archs:
1266
+ res = res and a.normalize(deep)
1267
+ new_kid: list[AstNode] = []
1268
+ for a in self.archs:
1269
+ new_kid.append(a)
1270
+ AstNode.__init__(self, kid=new_kid)
1271
+ return res
1272
+
803
1273
  def py_resolve_name(self) -> str:
804
1274
  """Resolve name."""
805
1275
 
@@ -845,6 +1315,27 @@ class ParamVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
845
1315
  AstTypedVarNode.__init__(self, type_tag=type_tag)
846
1316
  AstSemStrNode.__init__(self, semstr=semstr)
847
1317
 
1318
+ def normalize(self, deep: bool = True) -> bool:
1319
+ """Normalize ast node."""
1320
+ res = True
1321
+ if deep:
1322
+ res = self.name.normalize(deep)
1323
+ res = res and self.unpack.normalize(deep) if self.unpack else res
1324
+ res = res and self.type_tag.normalize(deep) if self.type_tag else res
1325
+ res = res and self.value.normalize(deep) if self.value else res
1326
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1327
+ new_kid: list[AstNode] = []
1328
+ if self.unpack:
1329
+ new_kid.append(self.unpack)
1330
+ new_kid.append(self.name)
1331
+ if self.type_tag:
1332
+ new_kid.append(self.type_tag)
1333
+ if self.value:
1334
+ new_kid.append(self.gen_token(Tok.EQ))
1335
+ new_kid.append(self.value)
1336
+ AstNode.__init__(self, kid=new_kid)
1337
+ return res
1338
+
848
1339
 
849
1340
  class ArchHas(AstAccessNode, AstDocNode, ArchBlockStmt):
850
1341
  """HasStmt node type for Jac Ast."""
@@ -866,6 +1357,30 @@ class ArchHas(AstAccessNode, AstDocNode, ArchBlockStmt):
866
1357
  AstAccessNode.__init__(self, access=access)
867
1358
  AstDocNode.__init__(self, doc=doc)
868
1359
 
1360
+ def normalize(self, deep: bool = False) -> bool:
1361
+ """Normalize has statement node."""
1362
+ res = True
1363
+ if deep:
1364
+ res = self.access.normalize(deep) if self.access else res
1365
+ res = res and self.vars.normalize(deep) if self.vars else res
1366
+ res = res and self.doc.normalize(deep) if self.doc else res
1367
+ new_kid: list[AstNode] = []
1368
+ if self.doc:
1369
+ new_kid.append(self.doc)
1370
+ if self.is_static:
1371
+ new_kid.append(self.gen_token(Tok.KW_STATIC))
1372
+ (
1373
+ new_kid.append(self.gen_token(Tok.KW_LET))
1374
+ if self.is_frozen
1375
+ else new_kid.append(self.gen_token(Tok.KW_HAS))
1376
+ )
1377
+ if self.access:
1378
+ new_kid.append(self.access)
1379
+ new_kid.append(self.vars)
1380
+ new_kid.append(self.gen_token(Tok.SEMI))
1381
+ AstNode.__init__(self, kid=new_kid)
1382
+ return res
1383
+
869
1384
 
870
1385
  class HasVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
871
1386
  """HasVar node type for Jac Ast."""
@@ -893,6 +1408,29 @@ class HasVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
893
1408
  AstTypedVarNode.__init__(self, type_tag=type_tag)
894
1409
  AstSemStrNode.__init__(self, semstr=semstr)
895
1410
 
1411
+ def normalize(self, deep: bool = False) -> bool:
1412
+ """Normalize has var node."""
1413
+ res = True
1414
+ if deep:
1415
+ res = self.name.normalize(deep)
1416
+ res = res and self.type_tag.normalize(deep) if self.type_tag else res
1417
+ res = res and self.value.normalize(deep) if self.value else res
1418
+ res = res and self.semstr.normalize(deep) if self.semstr else res
1419
+ new_kid: list[AstNode] = [self.name]
1420
+ if self.semstr:
1421
+ new_kid.append(self.gen_token(Tok.COLON))
1422
+ new_kid.append(self.semstr)
1423
+ if self.type_tag:
1424
+ new_kid.append(self.type_tag)
1425
+ if self.value:
1426
+ new_kid.append(self.gen_token(Tok.EQ))
1427
+ new_kid.append(self.value)
1428
+ if self.defer:
1429
+ new_kid.append(self.gen_token(Tok.KW_BY))
1430
+ new_kid.append(self.gen_token(Tok.KW_POST_INIT))
1431
+ AstNode.__init__(self, kid=new_kid)
1432
+ return res
1433
+
896
1434
 
897
1435
  class TypedCtxBlock(CodeBlockStmt):
898
1436
  """TypedCtxBlock node type for Jac Ast."""
@@ -908,6 +1446,20 @@ class TypedCtxBlock(CodeBlockStmt):
908
1446
  self.body = body
909
1447
  AstNode.__init__(self, kid=kid)
910
1448
 
1449
+ def normalize(self, deep: bool = False) -> bool:
1450
+ """Normalize typed context block node."""
1451
+ res = True
1452
+ if deep:
1453
+ res = self.type_ctx.normalize(deep)
1454
+ res = res and self.body.normalize(deep)
1455
+ new_kid: list[AstNode] = [
1456
+ self.gen_token(Tok.RETURN_HINT),
1457
+ self.type_ctx,
1458
+ self.body,
1459
+ ]
1460
+ AstNode.__init__(self, kid=new_kid)
1461
+ return res
1462
+
911
1463
 
912
1464
  class IfStmt(CodeBlockStmt, AstElseBodyNode):
913
1465
  """IfStmt node type for Jac Ast."""
@@ -925,10 +1477,48 @@ class IfStmt(CodeBlockStmt, AstElseBodyNode):
925
1477
  AstNode.__init__(self, kid=kid)
926
1478
  AstElseBodyNode.__init__(self, else_body=else_body)
927
1479
 
1480
+ def normalize(self, deep: bool = False) -> bool:
1481
+ """Normalize if statement node."""
1482
+ res = True
1483
+ if deep:
1484
+ res = self.condition.normalize(deep)
1485
+ res = res and self.body.normalize(deep)
1486
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1487
+ new_kid: list[AstNode] = [
1488
+ self.gen_token(Tok.KW_IF),
1489
+ self.condition,
1490
+ self.gen_token(Tok.LBRACE),
1491
+ self.body,
1492
+ self.gen_token(Tok.RBRACE),
1493
+ ]
1494
+ if self.else_body:
1495
+ new_kid.append(self.else_body)
1496
+ AstNode.__init__(self, kid=new_kid)
1497
+ return res
1498
+
928
1499
 
929
1500
  class ElseIf(IfStmt):
930
1501
  """ElseIfs node type for Jac Ast."""
931
1502
 
1503
+ def normalize(self, deep: bool = False) -> bool:
1504
+ """Normalize else if statement node."""
1505
+ res = True
1506
+ if deep:
1507
+ res = self.condition.normalize(deep)
1508
+ res = res and self.body.normalize(deep)
1509
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1510
+ new_kid: list[AstNode] = [
1511
+ self.gen_token(Tok.KW_ELIF),
1512
+ self.condition,
1513
+ self.gen_token(Tok.LBRACE),
1514
+ self.body,
1515
+ self.gen_token(Tok.RBRACE),
1516
+ ]
1517
+ if self.else_body:
1518
+ new_kid.append(self.else_body)
1519
+ AstNode.__init__(self, kid=new_kid)
1520
+ return res
1521
+
932
1522
 
933
1523
  class ElseStmt(AstNode):
934
1524
  """Else node type for Jac Ast."""
@@ -942,6 +1532,20 @@ class ElseStmt(AstNode):
942
1532
  self.body = body
943
1533
  AstNode.__init__(self, kid=kid)
944
1534
 
1535
+ def normalize(self, deep: bool = False) -> bool:
1536
+ """Normalize else statement node."""
1537
+ res = True
1538
+ if deep:
1539
+ res = self.body.normalize(deep)
1540
+ new_kid: list[AstNode] = [
1541
+ self.gen_token(Tok.KW_ELSE),
1542
+ self.gen_token(Tok.LBRACE),
1543
+ self.body,
1544
+ self.gen_token(Tok.RBRACE),
1545
+ ]
1546
+ AstNode.__init__(self, kid=new_kid)
1547
+ return res
1548
+
945
1549
 
946
1550
  class ExprStmt(CodeBlockStmt):
947
1551
  """ExprStmt node type for Jac Ast."""
@@ -957,6 +1561,20 @@ class ExprStmt(CodeBlockStmt):
957
1561
  self.in_fstring = in_fstring
958
1562
  AstNode.__init__(self, kid=kid)
959
1563
 
1564
+ def normalize(self, deep: bool = True) -> bool:
1565
+ """Normalize ast node."""
1566
+ if deep:
1567
+ res = self.expr.normalize(deep)
1568
+ AstNode.__init__(
1569
+ self,
1570
+ kid=(
1571
+ [self.expr, self.gen_token(Tok.SEMI)]
1572
+ if not self.in_fstring
1573
+ else [self.expr]
1574
+ ),
1575
+ )
1576
+ return res and self.expr is not None
1577
+
960
1578
 
961
1579
  class TryStmt(AstElseBodyNode, CodeBlockStmt):
962
1580
  """TryStmt node type for Jac Ast."""
@@ -976,6 +1594,31 @@ class TryStmt(AstElseBodyNode, CodeBlockStmt):
976
1594
  AstNode.__init__(self, kid=kid)
977
1595
  AstElseBodyNode.__init__(self, else_body=else_body)
978
1596
 
1597
+ def normalize(self, deep: bool = False) -> bool:
1598
+ """Normalize try statement node."""
1599
+ res = True
1600
+ if deep:
1601
+ res = self.body.normalize(deep)
1602
+ res = res and self.excepts.normalize(deep) if self.excepts else res
1603
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1604
+ res = (
1605
+ res and self.finally_body.normalize(deep) if self.finally_body else res
1606
+ )
1607
+ new_kid: list[AstNode] = [
1608
+ self.gen_token(Tok.KW_TRY),
1609
+ ]
1610
+ new_kid.append(self.gen_token(Tok.LBRACE))
1611
+ new_kid.append(self.body)
1612
+ new_kid.append(self.gen_token(Tok.RBRACE))
1613
+ if self.excepts:
1614
+ new_kid.append(self.excepts)
1615
+ if self.else_body:
1616
+ new_kid.append(self.else_body)
1617
+ if self.finally_body:
1618
+ new_kid.append(self.finally_body)
1619
+ AstNode.__init__(self, kid=new_kid)
1620
+ return res
1621
+
979
1622
 
980
1623
  class Except(CodeBlockStmt):
981
1624
  """Except node type for Jac Ast."""
@@ -993,6 +1636,26 @@ class Except(CodeBlockStmt):
993
1636
  self.body = body
994
1637
  AstNode.__init__(self, kid=kid)
995
1638
 
1639
+ def normalize(self, deep: bool = False) -> bool:
1640
+ """Normalize except node."""
1641
+ res = True
1642
+ if deep:
1643
+ res = self.ex_type.normalize(deep)
1644
+ res = res and self.name.normalize(deep) if self.name else res
1645
+ res = res and self.body.normalize(deep) if self.body else res
1646
+ new_kid: list[AstNode] = [
1647
+ self.gen_token(Tok.KW_EXCEPT),
1648
+ self.ex_type,
1649
+ ]
1650
+ if self.name:
1651
+ new_kid.append(self.gen_token(Tok.KW_AS))
1652
+ new_kid.append(self.name)
1653
+ new_kid.append(self.gen_token(Tok.LBRACE))
1654
+ new_kid.append(self.body)
1655
+ new_kid.append(self.gen_token(Tok.RBRACE))
1656
+ AstNode.__init__(self, kid=new_kid)
1657
+ return res
1658
+
996
1659
 
997
1660
  class FinallyStmt(CodeBlockStmt):
998
1661
  """FinallyStmt node type for Jac Ast."""
@@ -1006,6 +1669,20 @@ class FinallyStmt(CodeBlockStmt):
1006
1669
  self.body = body
1007
1670
  AstNode.__init__(self, kid=kid)
1008
1671
 
1672
+ def normalize(self, deep: bool = False) -> bool:
1673
+ """Normalize finally statement node."""
1674
+ res = True
1675
+ if deep:
1676
+ res = self.body.normalize(deep)
1677
+ new_kid: list[AstNode] = [
1678
+ self.gen_token(Tok.KW_FINALLY),
1679
+ ]
1680
+ new_kid.append(self.gen_token(Tok.LBRACE))
1681
+ new_kid.append(self.body)
1682
+ new_kid.append(self.gen_token(Tok.RBRACE))
1683
+ AstNode.__init__(self, kid=new_kid)
1684
+ return res
1685
+
1009
1686
 
1010
1687
  class IterForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1011
1688
  """IterFor node type for Jac Ast."""
@@ -1029,6 +1706,32 @@ class IterForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1029
1706
  AstAsyncNode.__init__(self, is_async=is_async)
1030
1707
  AstElseBodyNode.__init__(self, else_body=else_body)
1031
1708
 
1709
+ def normalize(self, deep: bool = False) -> bool:
1710
+ """Normalize iter for node."""
1711
+ res = True
1712
+ if deep:
1713
+ res = self.iter.normalize(deep)
1714
+ res = self.condition.normalize(deep)
1715
+ res = self.count_by.normalize(deep)
1716
+ res = self.body.normalize(deep)
1717
+ res = self.else_body.normalize(deep) if self.else_body else res
1718
+ new_kid: list[AstNode] = []
1719
+ if self.is_async:
1720
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1721
+ new_kid.append(self.gen_token(Tok.KW_FOR))
1722
+ new_kid.append(self.iter)
1723
+ new_kid.append(self.gen_token(Tok.KW_TO))
1724
+ new_kid.append(self.condition)
1725
+ new_kid.append(self.gen_token(Tok.KW_BY))
1726
+ new_kid.append(self.count_by)
1727
+ new_kid.append(self.gen_token(Tok.LBRACE))
1728
+ new_kid.append(self.body)
1729
+ new_kid.append(self.gen_token(Tok.RBRACE))
1730
+ if self.else_body:
1731
+ new_kid.append(self.else_body)
1732
+ AstNode.__init__(self, kid=new_kid)
1733
+ return res
1734
+
1032
1735
 
1033
1736
  class InForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1034
1737
  """InFor node type for Jac Ast."""
@@ -1050,6 +1753,32 @@ class InForStmt(AstAsyncNode, AstElseBodyNode, CodeBlockStmt):
1050
1753
  AstAsyncNode.__init__(self, is_async=is_async)
1051
1754
  AstElseBodyNode.__init__(self, else_body=else_body)
1052
1755
 
1756
+ def normalize(self, deep: bool = False) -> bool:
1757
+ """Normalize in for node."""
1758
+ res = True
1759
+ if deep:
1760
+ res = self.target.normalize(deep)
1761
+ res = res and self.collection.normalize(deep)
1762
+ res = res and self.body.normalize(deep)
1763
+ res = res and self.else_body.normalize(deep) if self.else_body else res
1764
+ new_kid: list[AstNode] = []
1765
+ if self.is_async:
1766
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1767
+ new_kid.append(self.gen_token(Tok.KW_FOR))
1768
+ new_kid.append(self.target)
1769
+ new_kid.append(self.gen_token(Tok.KW_IN))
1770
+ new_kid.append(self.collection)
1771
+
1772
+ if self.body:
1773
+ new_kid.append(self.gen_token(Tok.LBRACE))
1774
+ new_kid.append(self.body)
1775
+ new_kid.append(self.gen_token(Tok.RBRACE))
1776
+
1777
+ if self.else_body:
1778
+ new_kid.append(self.else_body)
1779
+ AstNode.__init__(self, kid=new_kid)
1780
+ return res
1781
+
1053
1782
 
1054
1783
  class WhileStmt(CodeBlockStmt):
1055
1784
  """WhileStmt node type for Jac Ast."""
@@ -1065,6 +1794,24 @@ class WhileStmt(CodeBlockStmt):
1065
1794
  self.body = body
1066
1795
  AstNode.__init__(self, kid=kid)
1067
1796
 
1797
+ def normalize(self, deep: bool = False) -> bool:
1798
+ """Normalize while statement node."""
1799
+ res = True
1800
+ if deep:
1801
+ res = self.condition.normalize(deep)
1802
+ res = res and self.body.normalize(deep)
1803
+ new_kid: list[AstNode] = [
1804
+ self.gen_token(Tok.KW_WHILE),
1805
+ self.condition,
1806
+ ]
1807
+ if self.body:
1808
+ new_kid.append(self.gen_token(Tok.LBRACE))
1809
+ new_kid.append(self.body)
1810
+ new_kid.append(self.gen_token(Tok.RBRACE))
1811
+
1812
+ AstNode.__init__(self, kid=new_kid)
1813
+ return res
1814
+
1068
1815
 
1069
1816
  class WithStmt(AstAsyncNode, CodeBlockStmt):
1070
1817
  """WithStmt node type for Jac Ast."""
@@ -1082,6 +1829,25 @@ class WithStmt(AstAsyncNode, CodeBlockStmt):
1082
1829
  AstNode.__init__(self, kid=kid)
1083
1830
  AstAsyncNode.__init__(self, is_async=is_async)
1084
1831
 
1832
+ def normalize(self, deep: bool = False) -> bool:
1833
+ """Normalize with statement node."""
1834
+ res = True
1835
+ if deep:
1836
+ res = self.exprs.normalize(deep)
1837
+ res = res and self.body.normalize(deep)
1838
+ new_kid: list[AstNode] = []
1839
+ if self.is_async:
1840
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
1841
+ new_kid.append(self.gen_token(Tok.KW_WITH))
1842
+ new_kid.append(self.exprs)
1843
+
1844
+ new_kid.append(self.gen_token(Tok.LBRACE))
1845
+ new_kid.append(self.body)
1846
+ new_kid.append(self.gen_token(Tok.RBRACE))
1847
+
1848
+ AstNode.__init__(self, kid=new_kid)
1849
+ return res
1850
+
1085
1851
 
1086
1852
  class ExprAsItem(AstNode):
1087
1853
  """ExprAsItem node type for Jac Ast."""
@@ -1097,6 +1863,19 @@ class ExprAsItem(AstNode):
1097
1863
  self.alias = alias
1098
1864
  AstNode.__init__(self, kid=kid)
1099
1865
 
1866
+ def normalize(self, deep: bool = True) -> bool:
1867
+ """Normalize ast node."""
1868
+ res = True
1869
+ if deep:
1870
+ res = self.expr.normalize(deep)
1871
+ res = res and self.alias.normalize(deep) if self.alias else res
1872
+ new_kid: list[AstNode] = [self.expr]
1873
+ if self.alias:
1874
+ new_kid.append(self.gen_token(Tok.KW_AS))
1875
+ new_kid.append(self.alias)
1876
+ AstNode.__init__(self, kid=new_kid)
1877
+ return res
1878
+
1100
1879
 
1101
1880
  class RaiseStmt(CodeBlockStmt):
1102
1881
  """RaiseStmt node type for Jac Ast."""
@@ -1112,6 +1891,22 @@ class RaiseStmt(CodeBlockStmt):
1112
1891
  self.from_target = from_target
1113
1892
  AstNode.__init__(self, kid=kid)
1114
1893
 
1894
+ def normalize(self, deep: bool = False) -> bool:
1895
+ """Normalize raise statement node."""
1896
+ res = True
1897
+ if deep:
1898
+ res = res and self.cause.normalize(deep) if self.cause else res
1899
+ res = res and self.from_target.normalize(deep) if self.from_target else res
1900
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_RAISE)]
1901
+ if self.cause:
1902
+ new_kid.append(self.cause)
1903
+ if self.from_target:
1904
+ new_kid.append(self.gen_token(Tok.KW_FROM))
1905
+ new_kid.append(self.from_target)
1906
+ new_kid.append(self.gen_token(Tok.SEMI))
1907
+ AstNode.__init__(self, kid=new_kid)
1908
+ return res
1909
+
1115
1910
 
1116
1911
  class AssertStmt(CodeBlockStmt):
1117
1912
  """AssertStmt node type for Jac Ast."""
@@ -1127,6 +1922,23 @@ class AssertStmt(CodeBlockStmt):
1127
1922
  self.error_msg = error_msg
1128
1923
  AstNode.__init__(self, kid=kid)
1129
1924
 
1925
+ def normalize(self, deep: bool = False) -> bool:
1926
+ """Normalize assert statement node."""
1927
+ res = True
1928
+ if deep:
1929
+ res = self.condition.normalize(deep)
1930
+ res = res and self.error_msg.normalize(deep) if self.error_msg else res
1931
+ new_kid: list[AstNode] = [
1932
+ self.gen_token(Tok.KW_ASSERT),
1933
+ self.condition,
1934
+ ]
1935
+ if self.error_msg:
1936
+ new_kid.append(self.gen_token(Tok.COMMA))
1937
+ new_kid.append(self.error_msg)
1938
+ new_kid.append(self.gen_token(Tok.SEMI))
1939
+ AstNode.__init__(self, kid=new_kid)
1940
+ return res
1941
+
1130
1942
 
1131
1943
  class CtrlStmt(CodeBlockStmt):
1132
1944
  """CtrlStmt node type for Jac Ast."""
@@ -1140,6 +1952,15 @@ class CtrlStmt(CodeBlockStmt):
1140
1952
  self.ctrl = ctrl
1141
1953
  AstNode.__init__(self, kid=kid)
1142
1954
 
1955
+ def normalize(self, deep: bool = False) -> bool:
1956
+ """Normalize control statement node."""
1957
+ res = True
1958
+ if deep:
1959
+ res = self.ctrl.normalize(deep)
1960
+ new_kid: list[AstNode] = [self.ctrl, self.gen_token(Tok.SEMI)]
1961
+ AstNode.__init__(self, kid=new_kid)
1962
+ return res
1963
+
1143
1964
 
1144
1965
  class DeleteStmt(CodeBlockStmt):
1145
1966
  """DeleteStmt node type for Jac Ast."""
@@ -1153,6 +1974,19 @@ class DeleteStmt(CodeBlockStmt):
1153
1974
  self.target = target
1154
1975
  AstNode.__init__(self, kid=kid)
1155
1976
 
1977
+ def normalize(self, deep: bool = False) -> bool:
1978
+ """Normalize delete statement node."""
1979
+ res = True
1980
+ if deep:
1981
+ res = self.target.normalize(deep)
1982
+ new_kid: list[AstNode] = [
1983
+ self.gen_token(Tok.KW_DELETE),
1984
+ self.target,
1985
+ self.gen_token(Tok.SEMI),
1986
+ ]
1987
+ AstNode.__init__(self, kid=new_kid)
1988
+ return res
1989
+
1156
1990
 
1157
1991
  class ReportStmt(CodeBlockStmt):
1158
1992
  """ReportStmt node type for Jac Ast."""
@@ -1166,6 +2000,19 @@ class ReportStmt(CodeBlockStmt):
1166
2000
  self.expr = expr
1167
2001
  AstNode.__init__(self, kid=kid)
1168
2002
 
2003
+ def normalize(self, deep: bool = False) -> bool:
2004
+ """Normalize report statement node."""
2005
+ res = True
2006
+ if deep:
2007
+ res = self.expr.normalize(deep)
2008
+ new_kid: list[AstNode] = [
2009
+ self.gen_token(Tok.KW_REPORT),
2010
+ self.expr,
2011
+ self.gen_token(Tok.SEMI),
2012
+ ]
2013
+ AstNode.__init__(self, kid=new_kid)
2014
+ return res
2015
+
1169
2016
 
1170
2017
  class ReturnStmt(CodeBlockStmt):
1171
2018
  """ReturnStmt node type for Jac Ast."""
@@ -1179,6 +2026,20 @@ class ReturnStmt(CodeBlockStmt):
1179
2026
  self.expr = expr
1180
2027
  AstNode.__init__(self, kid=kid)
1181
2028
 
2029
+ def normalize(self, deep: bool = False) -> bool:
2030
+ """Normalize return statement node."""
2031
+ res = True
2032
+ if deep:
2033
+ res = self.expr.normalize(deep) if self.expr else res
2034
+ new_kid: list[AstNode] = [
2035
+ self.gen_token(Tok.KW_RETURN),
2036
+ ]
2037
+ if self.expr:
2038
+ new_kid.append(self.expr)
2039
+ new_kid.append(self.gen_token(Tok.SEMI))
2040
+ AstNode.__init__(self, kid=new_kid)
2041
+ return res
2042
+
1182
2043
 
1183
2044
  class IgnoreStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1184
2045
  """IgnoreStmt node type for Jac Ast."""
@@ -1193,6 +2054,19 @@ class IgnoreStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1193
2054
  AstNode.__init__(self, kid=kid)
1194
2055
  WalkerStmtOnlyNode.__init__(self)
1195
2056
 
2057
+ def normalize(self, deep: bool = False) -> bool:
2058
+ """Normalize ignore statement node."""
2059
+ res = True
2060
+ if deep:
2061
+ res = self.target.normalize(deep)
2062
+ new_kid: list[AstNode] = [
2063
+ self.gen_token(Tok.KW_IGNORE),
2064
+ self.target,
2065
+ self.gen_token(Tok.SEMI),
2066
+ ]
2067
+ AstNode.__init__(self, kid=new_kid)
2068
+ return res
2069
+
1196
2070
 
1197
2071
  class VisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1198
2072
  """VisitStmt node type for Jac Ast."""
@@ -1211,6 +2085,26 @@ class VisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1211
2085
  WalkerStmtOnlyNode.__init__(self)
1212
2086
  AstElseBodyNode.__init__(self, else_body=else_body)
1213
2087
 
2088
+ def normalize(self, deep: bool = False) -> bool:
2089
+ """Normalize visit statement node."""
2090
+ res = True
2091
+ if deep:
2092
+ res = self.vis_type.normalize(deep) if self.vis_type else res
2093
+ res = self.target.normalize(deep)
2094
+ res = res and self.else_body.normalize(deep) if self.else_body else res
2095
+ new_kid: list[AstNode] = []
2096
+ new_kid.append(self.gen_token(Tok.KW_VISIT))
2097
+ if self.vis_type:
2098
+ new_kid.append(self.gen_token(Tok.COLON))
2099
+ new_kid.append(self.vis_type)
2100
+ new_kid.append(self.gen_token(Tok.COLON))
2101
+ new_kid.append(self.target)
2102
+ new_kid.append(self.gen_token(Tok.SEMI))
2103
+ if self.else_body:
2104
+ new_kid.append(self.else_body)
2105
+ AstNode.__init__(self, kid=new_kid)
2106
+ return res
2107
+
1214
2108
 
1215
2109
  class RevisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1216
2110
  """ReVisitStmt node type for Jac Ast."""
@@ -1227,6 +2121,21 @@ class RevisitStmt(WalkerStmtOnlyNode, AstElseBodyNode, CodeBlockStmt):
1227
2121
  WalkerStmtOnlyNode.__init__(self)
1228
2122
  AstElseBodyNode.__init__(self, else_body=else_body)
1229
2123
 
2124
+ def normalize(self, deep: bool = False) -> bool:
2125
+ """Normalize revisit statement node."""
2126
+ res = True
2127
+ if deep:
2128
+ res = self.hops.normalize(deep) if self.hops else res
2129
+ res = res and self.else_body.normalize(deep) if self.else_body else res
2130
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_REVISIT)]
2131
+ if self.hops:
2132
+ new_kid.append(self.hops)
2133
+ if self.else_body:
2134
+ new_kid.append(self.else_body)
2135
+ new_kid.append(self.gen_token(Tok.SEMI))
2136
+ AstNode.__init__(self, kid=new_kid)
2137
+ return res
2138
+
1230
2139
 
1231
2140
  class DisengageStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1232
2141
  """DisengageStmt node type for Jac Ast."""
@@ -1239,6 +2148,15 @@ class DisengageStmt(WalkerStmtOnlyNode, CodeBlockStmt):
1239
2148
  AstNode.__init__(self, kid=kid)
1240
2149
  WalkerStmtOnlyNode.__init__(self)
1241
2150
 
2151
+ def normalize(self, deep: bool = False) -> bool:
2152
+ """Normalize disengage statement node."""
2153
+ new_kid: list[AstNode] = [
2154
+ self.gen_token(Tok.KW_DISENGAGE),
2155
+ self.gen_token(Tok.SEMI),
2156
+ ]
2157
+ AstNode.__init__(self, kid=new_kid)
2158
+ return True
2159
+
1242
2160
 
1243
2161
  class AwaitExpr(Expr):
1244
2162
  """AwaitStmt node type for Jac Ast."""
@@ -1252,6 +2170,18 @@ class AwaitExpr(Expr):
1252
2170
  self.target = target
1253
2171
  AstNode.__init__(self, kid=kid)
1254
2172
 
2173
+ def normalize(self, deep: bool = False) -> bool:
2174
+ """Normalize sync statement node."""
2175
+ res = True
2176
+ if deep:
2177
+ res = self.target.normalize(deep)
2178
+ new_kid: list[AstNode] = [
2179
+ self.gen_token(Tok.KW_AWAIT),
2180
+ self.target,
2181
+ ]
2182
+ AstNode.__init__(self, kid=new_kid)
2183
+ return res
2184
+
1255
2185
 
1256
2186
  class GlobalStmt(CodeBlockStmt):
1257
2187
  """GlobalStmt node type for Jac Ast."""
@@ -1265,12 +2195,38 @@ class GlobalStmt(CodeBlockStmt):
1265
2195
  self.target = target
1266
2196
  AstNode.__init__(self, kid=kid)
1267
2197
 
2198
+ def normalize(self, deep: bool = False) -> bool:
2199
+ """Normalize global statement node."""
2200
+ res = True
2201
+ if deep:
2202
+ res = self.target.normalize(deep)
2203
+ new_kid: list[AstNode] = [
2204
+ self.gen_token(Tok.GLOBAL_OP),
2205
+ self.target,
2206
+ self.gen_token(Tok.SEMI),
2207
+ ]
2208
+ AstNode.__init__(self, kid=new_kid)
2209
+ return res
2210
+
1268
2211
 
1269
2212
  class NonLocalStmt(GlobalStmt):
1270
2213
  """NonlocalStmt node type for Jac Ast."""
1271
2214
 
1272
-
1273
- class Assignment(AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
2215
+ def normalize(self, deep: bool = False) -> bool:
2216
+ """Normalize nonlocal statement node."""
2217
+ res = True
2218
+ if deep:
2219
+ res = self.target.normalize(deep)
2220
+ new_kid: list[AstNode] = [
2221
+ self.gen_token(Tok.NONLOCAL_OP),
2222
+ self.target,
2223
+ self.gen_token(Tok.SEMI),
2224
+ ]
2225
+ AstNode.__init__(self, kid=new_kid)
2226
+ return res
2227
+
2228
+
2229
+ class Assignment(AstSemStrNode, AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
1274
2230
  """Assignment node type for Jac Ast."""
1275
2231
 
1276
2232
  def __init__(
@@ -1281,15 +2237,43 @@ class Assignment(AstTypedVarNode, EnumBlockStmt, CodeBlockStmt):
1281
2237
  kid: Sequence[AstNode],
1282
2238
  mutable: bool = True,
1283
2239
  aug_op: Optional[Token] = None,
2240
+ semstr: Optional[String] = None,
2241
+ is_enum_stmt: bool = False,
1284
2242
  ) -> None:
1285
2243
  """Initialize assignment node."""
1286
2244
  self.target = target
1287
2245
  self.value = value
1288
2246
  self.mutable = mutable
1289
2247
  self.aug_op = aug_op
2248
+ self.is_enum_stmt = is_enum_stmt
1290
2249
  AstNode.__init__(self, kid=kid)
2250
+ AstSemStrNode.__init__(self, semstr=semstr)
1291
2251
  AstTypedVarNode.__init__(self, type_tag=type_tag)
1292
2252
 
2253
+ def normalize(self, deep: bool = True) -> bool:
2254
+ """Normalize ast node."""
2255
+ res = True
2256
+ if deep:
2257
+ res = self.target.normalize(deep)
2258
+ res = res and self.value.normalize(deep) if self.value else res
2259
+ res = res and self.type_tag.normalize(deep) if self.type_tag else res
2260
+ res = res and self.aug_op.normalize(deep) if self.aug_op else res
2261
+ new_kid: list[AstNode] = []
2262
+ new_kid.append(self.target)
2263
+ if self.type_tag:
2264
+ new_kid.append(self.type_tag)
2265
+ if self.aug_op:
2266
+ new_kid.append(self.aug_op)
2267
+ new_kid.append(self.gen_token(Tok.EQ))
2268
+ else:
2269
+ new_kid.append(self.gen_token(Tok.EQ))
2270
+ if self.value:
2271
+ new_kid.append(self.value)
2272
+ if not isinstance(self.parent, (GlobalVars)):
2273
+ new_kid.append(self.gen_token(Tok.SEMI))
2274
+ AstNode.__init__(self, kid=new_kid)
2275
+ return res
2276
+
1293
2277
 
1294
2278
  class BinaryExpr(Expr):
1295
2279
  """ExprBinary node type for Jac Ast."""
@@ -1307,6 +2291,23 @@ class BinaryExpr(Expr):
1307
2291
  self.op = op
1308
2292
  AstNode.__init__(self, kid=kid)
1309
2293
 
2294
+ def normalize(self, deep: bool = False) -> bool:
2295
+ """Normalize ast node."""
2296
+ res = True
2297
+ if deep:
2298
+ res = self.left.normalize(deep)
2299
+ res = res and self.right.normalize(deep) if self.right else res
2300
+ res = res and self.op.normalize(deep) if self.op else res
2301
+ new_kid: list[AstNode] = [
2302
+ self.gen_token(Tok.LPAREN),
2303
+ self.left,
2304
+ self.op,
2305
+ self.right,
2306
+ self.gen_token(Tok.RPAREN),
2307
+ ]
2308
+ AstNode.__init__(self, kid=new_kid)
2309
+ return res
2310
+
1310
2311
 
1311
2312
  class CompareExpr(Expr):
1312
2313
  """CompareExpr node type for Jac Ast."""
@@ -1324,6 +2325,22 @@ class CompareExpr(Expr):
1324
2325
  self.ops = ops
1325
2326
  AstNode.__init__(self, kid=kid)
1326
2327
 
2328
+ def normalize(self, deep: bool = False) -> bool:
2329
+ """Normalize ast node."""
2330
+ res = True
2331
+ if deep:
2332
+ res = self.left.normalize(deep)
2333
+ for right in self.rights:
2334
+ res = res and right.normalize(deep)
2335
+ for op in self.ops:
2336
+ res = res and op.normalize(deep)
2337
+ new_kid: list[AstNode] = [self.left]
2338
+ for i, right in enumerate(self.rights):
2339
+ new_kid.append(self.ops[i])
2340
+ new_kid.append(right)
2341
+ AstNode.__init__(self, kid=new_kid)
2342
+ return res
2343
+
1327
2344
 
1328
2345
  class BoolExpr(Expr):
1329
2346
  """BoolExpr node type for Jac Ast."""
@@ -1339,6 +2356,21 @@ class BoolExpr(Expr):
1339
2356
  self.op = op
1340
2357
  AstNode.__init__(self, kid=kid)
1341
2358
 
2359
+ def normalize(self, deep: bool = False) -> bool:
2360
+ """Normalize ast node."""
2361
+ res = True
2362
+ if deep:
2363
+ for value in self.values:
2364
+ res = res and value.normalize(deep)
2365
+ res = res and self.op.normalize(deep) if self.op else res
2366
+ new_kid: list[AstNode] = []
2367
+ for i, value in enumerate(self.values):
2368
+ if i > 0:
2369
+ new_kid.append(self.op)
2370
+ new_kid.append(value)
2371
+ AstNode.__init__(self, kid=new_kid)
2372
+ return res
2373
+
1342
2374
 
1343
2375
  class LambdaExpr(Expr):
1344
2376
  """ExprLambda node type for Jac Ast."""
@@ -1354,6 +2386,22 @@ class LambdaExpr(Expr):
1354
2386
  self.body = body
1355
2387
  AstNode.__init__(self, kid=kid)
1356
2388
 
2389
+ def normalize(self, deep: bool = False) -> bool:
2390
+ """Normalize ast node."""
2391
+ res = True
2392
+ if deep:
2393
+ res = self.signature.normalize(deep)
2394
+ res = res and self.body.normalize(deep)
2395
+ new_kid: list[AstNode] = [
2396
+ self.gen_token(Tok.KW_WITH),
2397
+ self.signature,
2398
+ self.gen_token(Tok.KW_CAN),
2399
+ self.body,
2400
+ self.gen_token(Tok.SEMI),
2401
+ ]
2402
+ AstNode.__init__(self, kid=new_kid)
2403
+ return res
2404
+
1357
2405
 
1358
2406
  class UnaryExpr(Expr):
1359
2407
  """ExprUnary node type for Jac Ast."""
@@ -1369,6 +2417,16 @@ class UnaryExpr(Expr):
1369
2417
  self.op = op
1370
2418
  AstNode.__init__(self, kid=kid)
1371
2419
 
2420
+ def normalize(self, deep: bool = False) -> bool:
2421
+ """Normalize ast node."""
2422
+ res = True
2423
+ if deep:
2424
+ res = self.operand.normalize(deep)
2425
+ res = res and self.op.normalize(deep) if self.op else res
2426
+ new_kid: list[AstNode] = [self.op, self.operand]
2427
+ AstNode.__init__(self, kid=new_kid)
2428
+ return res
2429
+
1372
2430
 
1373
2431
  class IfElseExpr(Expr):
1374
2432
  """ExprIfElse node type for Jac Ast."""
@@ -1386,6 +2444,23 @@ class IfElseExpr(Expr):
1386
2444
  self.else_value = else_value
1387
2445
  AstNode.__init__(self, kid=kid)
1388
2446
 
2447
+ def normalize(self, deep: bool = False) -> bool:
2448
+ """Normalize ast node."""
2449
+ res = True
2450
+ if deep:
2451
+ res = self.condition.normalize(deep)
2452
+ res = res and self.value.normalize(deep)
2453
+ res = res and self.else_value.normalize(deep)
2454
+ new_kid: list[AstNode] = [
2455
+ self.value,
2456
+ self.gen_token(Tok.KW_IF),
2457
+ self.condition,
2458
+ self.gen_token(Tok.KW_ELSE),
2459
+ self.else_value,
2460
+ ]
2461
+ AstNode.__init__(self, kid=new_kid)
2462
+ return res
2463
+
1389
2464
 
1390
2465
  class MultiString(AtomExpr):
1391
2466
  """ExprMultiString node type for Jac Ast."""
@@ -1405,8 +2480,20 @@ class MultiString(AtomExpr):
1405
2480
  sym_type=SymbolType.STRING,
1406
2481
  )
1407
2482
 
2483
+ def normalize(self, deep: bool = False) -> bool:
2484
+ """Normalize ast node."""
2485
+ res = True
2486
+ if deep:
2487
+ for string in self.strings:
2488
+ res = res and string.normalize(deep)
2489
+ new_kid: list[AstNode] = []
2490
+ for string in self.strings:
2491
+ new_kid.append(string)
2492
+ AstNode.__init__(self, kid=new_kid)
2493
+ return res
2494
+
1408
2495
 
1409
- class FString(AstSymbolNode):
2496
+ class FString(AtomExpr):
1410
2497
  """FString node type for Jac Ast."""
1411
2498
 
1412
2499
  def __init__(
@@ -1424,18 +2511,16 @@ class FString(AstSymbolNode):
1424
2511
  sym_type=SymbolType.STRING,
1425
2512
  )
1426
2513
 
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)
2514
+ def normalize(self, deep: bool = False) -> bool:
2515
+ """Normalize ast node."""
2516
+ res = True
2517
+ if deep:
2518
+ res = self.parts.normalize(deep) if self.parts else res
2519
+ new_kid: list[AstNode] = []
2520
+ if self.parts:
2521
+ new_kid.append(self.parts)
2522
+ AstNode.__init__(self, kid=new_kid)
2523
+ return res
1439
2524
 
1440
2525
 
1441
2526
  class ListVal(AtomExpr):
@@ -1456,6 +2541,20 @@ class ListVal(AtomExpr):
1456
2541
  sym_type=SymbolType.SEQUENCE,
1457
2542
  )
1458
2543
 
2544
+ def normalize(self, deep: bool = False) -> bool:
2545
+ """Normalize ast node."""
2546
+ res = True
2547
+ if deep:
2548
+ res = self.values.normalize(deep) if self.values else res
2549
+ new_kid: list[AstNode] = [
2550
+ self.gen_token(Tok.LSQUARE),
2551
+ ]
2552
+ if self.values:
2553
+ new_kid.append(self.values)
2554
+ new_kid.append(self.gen_token(Tok.RSQUARE))
2555
+ AstNode.__init__(self, kid=new_kid)
2556
+ return res
2557
+
1459
2558
 
1460
2559
  class SetVal(AtomExpr):
1461
2560
  """SetVal node type for Jac Ast."""
@@ -1475,6 +2574,18 @@ class SetVal(AtomExpr):
1475
2574
  sym_type=SymbolType.SEQUENCE,
1476
2575
  )
1477
2576
 
2577
+ def normalize(self, deep: bool = False) -> bool:
2578
+ """Normalize ast node."""
2579
+ res = True
2580
+ if deep:
2581
+ res = self.values.normalize(deep) if self.values else res
2582
+ new_kid: list[AstNode] = []
2583
+ if self.values:
2584
+ new_kid.append(self.values)
2585
+
2586
+ AstNode.__init__(self, kid=new_kid)
2587
+ return res
2588
+
1478
2589
 
1479
2590
  class TupleVal(AtomExpr):
1480
2591
  """TupleVal node type for Jac Ast."""
@@ -1494,6 +2605,22 @@ class TupleVal(AtomExpr):
1494
2605
  sym_type=SymbolType.SEQUENCE,
1495
2606
  )
1496
2607
 
2608
+ def normalize(self, deep: bool = False) -> bool:
2609
+ """Normalize ast node."""
2610
+ res = True
2611
+ if deep:
2612
+ res = self.values.normalize(deep) if self.values else res
2613
+ new_kid: list[AstNode] = [
2614
+ self.gen_token(Tok.LPAREN),
2615
+ ]
2616
+ if self.values:
2617
+ new_kid.append(self.values)
2618
+ if len(self.values.items) < 2:
2619
+ new_kid.append(self.gen_token(Tok.COMMA))
2620
+ new_kid.append(self.gen_token(Tok.RPAREN))
2621
+ AstNode.__init__(self, kid=new_kid)
2622
+ return res
2623
+
1497
2624
 
1498
2625
  class DictVal(AtomExpr):
1499
2626
  """ExprDict node type for Jac Ast."""
@@ -1513,6 +2640,23 @@ class DictVal(AtomExpr):
1513
2640
  sym_type=SymbolType.SEQUENCE,
1514
2641
  )
1515
2642
 
2643
+ def normalize(self, deep: bool = False) -> bool:
2644
+ """Normalize ast node."""
2645
+ res = True
2646
+ if deep:
2647
+ for kv_pair in self.kv_pairs:
2648
+ res = res and kv_pair.normalize(deep)
2649
+ new_kid: list[AstNode] = [
2650
+ self.gen_token(Tok.LBRACE),
2651
+ ]
2652
+ for i, kv_pair in enumerate(self.kv_pairs):
2653
+ new_kid.append(kv_pair)
2654
+ if i < len(self.kv_pairs) - 1:
2655
+ new_kid.append(self.gen_token(Tok.COMMA))
2656
+ new_kid.append(self.gen_token(Tok.RBRACE))
2657
+ AstNode.__init__(self, kid=new_kid)
2658
+ return res
2659
+
1516
2660
 
1517
2661
  class KVPair(AstNode):
1518
2662
  """ExprKVPair node type for Jac Ast."""
@@ -1528,6 +2672,22 @@ class KVPair(AstNode):
1528
2672
  self.value = value
1529
2673
  AstNode.__init__(self, kid=kid)
1530
2674
 
2675
+ def normalize(self, deep: bool = False) -> bool:
2676
+ """Normalize ast node."""
2677
+ res = True
2678
+ if deep:
2679
+ res = self.key.normalize(deep) if self.key else res
2680
+ res = res and self.value.normalize(deep)
2681
+ new_kid: list[AstNode] = []
2682
+ if self.key:
2683
+ new_kid.append(self.key)
2684
+ new_kid.append(self.gen_token(Tok.COLON))
2685
+ else:
2686
+ new_kid.append(self.gen_token(Tok.STAR_POW))
2687
+ new_kid.append(self.value)
2688
+ AstNode.__init__(self, kid=new_kid)
2689
+ return res
2690
+
1531
2691
 
1532
2692
  class KWPair(AstNode):
1533
2693
  """ExprKWPair node type for Jac Ast."""
@@ -1543,6 +2703,20 @@ class KWPair(AstNode):
1543
2703
  self.value = value
1544
2704
  AstNode.__init__(self, kid=kid)
1545
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.EQ))
2716
+ new_kid.append(self.value)
2717
+ AstNode.__init__(self, kid=new_kid)
2718
+ return res
2719
+
1546
2720
 
1547
2721
  class InnerCompr(AstAsyncNode):
1548
2722
  """ListCompr node type for Jac Ast."""
@@ -1552,7 +2726,7 @@ class InnerCompr(AstAsyncNode):
1552
2726
  is_async: bool,
1553
2727
  target: Expr,
1554
2728
  collection: Expr,
1555
- conditional: Optional[Expr],
2729
+ conditional: Optional[list[Expr]],
1556
2730
  kid: Sequence[AstNode],
1557
2731
  ) -> None:
1558
2732
  """Initialize comprehension expression node."""
@@ -1562,6 +2736,26 @@ class InnerCompr(AstAsyncNode):
1562
2736
  AstNode.__init__(self, kid=kid)
1563
2737
  AstAsyncNode.__init__(self, is_async=is_async)
1564
2738
 
2739
+ def normalize(self, deep: bool = False) -> bool:
2740
+ """Normalize ast node."""
2741
+ res = True
2742
+ if deep:
2743
+ res = self.target.normalize(deep)
2744
+ res = res and self.collection.normalize(deep)
2745
+ for cond in self.conditional if self.conditional else []:
2746
+ res = res and cond.normalize(deep)
2747
+ new_kid: list[AstNode] = []
2748
+ if self.is_async:
2749
+ new_kid.append(self.gen_token(Tok.KW_ASYNC))
2750
+ new_kid.append(self.gen_token(Tok.KW_FOR))
2751
+ new_kid.append(self.target)
2752
+ new_kid.append(self.gen_token(Tok.KW_IN))
2753
+ new_kid.append(self.collection)
2754
+ for cond in self.conditional if self.conditional else []:
2755
+ new_kid.append(cond)
2756
+ AstNode.__init__(self, kid=new_kid)
2757
+ return res
2758
+
1565
2759
 
1566
2760
  class ListCompr(AtomExpr):
1567
2761
  """ListCompr node type for Jac Ast."""
@@ -1583,14 +2777,64 @@ class ListCompr(AtomExpr):
1583
2777
  sym_type=SymbolType.SEQUENCE,
1584
2778
  )
1585
2779
 
2780
+ def normalize(self, deep: bool = False) -> bool:
2781
+ """Normalize ast node."""
2782
+ res = True
2783
+ if deep:
2784
+ res = self.out_expr.normalize(deep)
2785
+ for comp in self.compr:
2786
+ res = res and comp.normalize(deep)
2787
+ new_kid: list[AstNode] = [
2788
+ self.gen_token(Tok.LSQUARE),
2789
+ self.out_expr,
2790
+ ]
2791
+ for comp in self.compr:
2792
+ new_kid.append(comp)
2793
+ new_kid.append(self.gen_token(Tok.RSQUARE))
2794
+ AstNode.__init__(self, kid=new_kid)
2795
+ return res
2796
+
1586
2797
 
1587
2798
  class GenCompr(ListCompr):
1588
2799
  """GenCompr node type for Jac Ast."""
1589
2800
 
2801
+ def normalize(self, deep: bool = False) -> bool:
2802
+ """Normalize ast node."""
2803
+ res = True
2804
+ if deep:
2805
+ res = self.out_expr.normalize(deep)
2806
+ for comp in self.compr:
2807
+ res = res and comp.normalize(deep)
2808
+ new_kid: list[AstNode] = [
2809
+ self.gen_token(Tok.LPAREN),
2810
+ self.out_expr,
2811
+ ]
2812
+ for comp in self.compr:
2813
+ new_kid.append(comp)
2814
+ new_kid.append(self.gen_token(Tok.RPAREN))
2815
+ AstNode.__init__(self, kid=new_kid)
2816
+ return res
2817
+
1590
2818
 
1591
2819
  class SetCompr(ListCompr):
1592
2820
  """SetCompr node type for Jac Ast."""
1593
2821
 
2822
+ def normalize(self, deep: bool = False) -> bool:
2823
+ """Normalize ast node."""
2824
+ res = True
2825
+ if deep:
2826
+ res = self.out_expr.normalize(deep)
2827
+ for comp in self.compr:
2828
+ res = res and comp.normalize(deep)
2829
+ new_kid: list[AstNode] = [
2830
+ self.out_expr,
2831
+ ]
2832
+ for comp in self.compr:
2833
+ new_kid.append(comp)
2834
+
2835
+ AstNode.__init__(self, kid=new_kid)
2836
+ return res
2837
+
1594
2838
 
1595
2839
  class DictCompr(AtomExpr):
1596
2840
  """DictCompr node type for Jac Ast."""
@@ -1612,6 +2856,21 @@ class DictCompr(AtomExpr):
1612
2856
  sym_type=SymbolType.SEQUENCE,
1613
2857
  )
1614
2858
 
2859
+ def normalize(self, deep: bool = False) -> bool:
2860
+ """Normalize ast node."""
2861
+ res = True
2862
+ res = self.kv_pair.normalize(deep)
2863
+ for comp in self.compr:
2864
+ res = res and comp.normalize(deep)
2865
+ new_kid: list[AstNode] = [
2866
+ self.kv_pair,
2867
+ ]
2868
+ for comp in self.compr:
2869
+ new_kid.append(comp)
2870
+
2871
+ AstNode.__init__(self, kid=new_kid)
2872
+ return res
2873
+
1615
2874
 
1616
2875
  class AtomTrailer(Expr):
1617
2876
  """AtomTrailer node type for Jac Ast."""
@@ -1620,7 +2879,7 @@ class AtomTrailer(Expr):
1620
2879
  self,
1621
2880
  target: Expr,
1622
2881
  right: AtomExpr | Expr,
1623
- is_attr: Optional[Token],
2882
+ is_attr: bool,
1624
2883
  is_null_ok: bool,
1625
2884
  kid: Sequence[AstNode],
1626
2885
  ) -> None:
@@ -1631,6 +2890,22 @@ class AtomTrailer(Expr):
1631
2890
  self.is_null_ok = is_null_ok
1632
2891
  AstNode.__init__(self, kid=kid)
1633
2892
 
2893
+ def normalize(self, deep: bool = True) -> bool:
2894
+ """Normalize ast node."""
2895
+ res = True
2896
+ if deep:
2897
+ res = self.target.normalize(deep)
2898
+ res = res and self.right.normalize(deep) if self.right else res
2899
+ new_kid: list[AstNode] = [self.target]
2900
+ if self.is_null_ok:
2901
+ new_kid.append(self.gen_token(Tok.NULL_OK))
2902
+ if self.is_attr:
2903
+ new_kid.append(self.gen_token(Tok.DOT))
2904
+ if self.right:
2905
+ new_kid.append(self.right)
2906
+ AstNode.__init__(self, kid=new_kid)
2907
+ return res
2908
+
1634
2909
 
1635
2910
  class AtomUnit(Expr):
1636
2911
  """AtomUnit node type for Jac Ast."""
@@ -1638,14 +2913,24 @@ class AtomUnit(Expr):
1638
2913
  def __init__(
1639
2914
  self,
1640
2915
  value: Expr | YieldExpr,
1641
- is_paren: bool,
1642
2916
  kid: Sequence[AstNode],
1643
2917
  ) -> None:
1644
2918
  """Initialize atom unit expression node."""
1645
2919
  self.value = value
1646
- self.is_paren = is_paren
1647
2920
  AstNode.__init__(self, kid=kid)
1648
2921
 
2922
+ def normalize(self, deep: bool = True) -> bool:
2923
+ """Normalize ast node."""
2924
+ res = True
2925
+ if deep:
2926
+ res = self.value.normalize(deep)
2927
+ new_kid: list[AstNode] = []
2928
+ new_kid.append(self.gen_token(Tok.LPAREN))
2929
+ new_kid.append(self.value)
2930
+ new_kid.append(self.gen_token(Tok.RPAREN))
2931
+ AstNode.__init__(self, kid=new_kid)
2932
+ return res
2933
+
1649
2934
 
1650
2935
  class YieldExpr(Expr):
1651
2936
  """YieldStmt node type for Jac Ast."""
@@ -1661,6 +2946,20 @@ class YieldExpr(Expr):
1661
2946
  self.with_from = with_from
1662
2947
  AstNode.__init__(self, kid=kid)
1663
2948
 
2949
+ def normalize(self, deep: bool = False) -> bool:
2950
+ """Normalize yield statement node."""
2951
+ res = True
2952
+ if deep:
2953
+ res = self.expr.normalize(deep) if self.expr else res
2954
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_YIELD)]
2955
+ if self.with_from:
2956
+ new_kid.append(self.gen_token(Tok.KW_FROM))
2957
+ if self.expr:
2958
+ new_kid.append(self.expr)
2959
+ new_kid.append(self.gen_token(Tok.SEMI))
2960
+ AstNode.__init__(self, kid=new_kid)
2961
+ return res
2962
+
1664
2963
 
1665
2964
  class FuncCall(Expr):
1666
2965
  """FuncCall node type for Jac Ast."""
@@ -1676,6 +2975,17 @@ class FuncCall(Expr):
1676
2975
  self.params = params
1677
2976
  AstNode.__init__(self, kid=kid)
1678
2977
 
2978
+ def normalize(self, deep: bool = True) -> bool:
2979
+ """Normalize ast node."""
2980
+ if deep:
2981
+ res = self.target.normalize(deep)
2982
+ res = res and (not self.params or self.params.normalize(deep))
2983
+ AstNode.__init__(self, kid=[self.target, self.gen_token(Tok.LPAREN, "(")])
2984
+ if self.params: # TODO: Fix
2985
+ self.kid.append(self.params)
2986
+ self.kid.append(self.gen_token(Tok.RPAREN, ")"))
2987
+ return res
2988
+
1679
2989
 
1680
2990
  class IndexSlice(AtomExpr):
1681
2991
  """IndexSlice node type for Jac Ast."""
@@ -1701,6 +3011,32 @@ class IndexSlice(AtomExpr):
1701
3011
  sym_name_node=self,
1702
3012
  )
1703
3013
 
3014
+ def normalize(self, deep: bool = True) -> bool:
3015
+ """Normalize ast node."""
3016
+ res = True
3017
+ if deep:
3018
+ res = self.start.normalize(deep) if self.start else res
3019
+ res = res and self.stop.normalize(deep) if self.stop else res
3020
+ res = res and self.step.normalize(deep) if self.step else res
3021
+ new_kid: list[AstNode] = []
3022
+ new_kid.append(self.gen_token(Tok.LSQUARE))
3023
+ if self.is_range:
3024
+ if self.start:
3025
+ new_kid.append(self.start)
3026
+ new_kid.append(self.gen_token(Tok.COLON))
3027
+ if self.stop:
3028
+ new_kid.append(self.stop)
3029
+ new_kid.append(self.gen_token(Tok.COLON))
3030
+ if self.step:
3031
+ new_kid.append(self.step)
3032
+ elif self.start:
3033
+ new_kid.append(self.start)
3034
+ else:
3035
+ res = False
3036
+ new_kid.append(self.gen_token(Tok.RSQUARE))
3037
+ AstNode.__init__(self, kid=new_kid)
3038
+ return res
3039
+
1704
3040
 
1705
3041
  class ArchRef(NameSpec):
1706
3042
  """ArchRef node type for Jac Ast."""
@@ -1722,6 +3058,15 @@ class ArchRef(NameSpec):
1722
3058
  sym_type=SymbolType.TYPE,
1723
3059
  )
1724
3060
 
3061
+ def normalize(self, deep: bool = False) -> bool:
3062
+ """Normalize ast node."""
3063
+ res = True
3064
+ if deep:
3065
+ res = self.name_ref.normalize(deep)
3066
+ new_kid: list[AstNode] = [self.arch, self.name_ref]
3067
+ AstNode.__init__(self, kid=new_kid)
3068
+ return res
3069
+
1725
3070
  def py_resolve_name(self) -> str:
1726
3071
  """Resolve name."""
1727
3072
  if isinstance(self.name_ref, Name):
@@ -1750,6 +3095,15 @@ class SpecialVarRef(NameSpec):
1750
3095
  sym_type=SymbolType.VAR,
1751
3096
  )
1752
3097
 
3098
+ def normalize(self, deep: bool = False) -> bool:
3099
+ """Normalize ast node."""
3100
+ res = True
3101
+ if deep:
3102
+ res = self.var.normalize(deep)
3103
+ new_kid: list[AstNode] = [self.var]
3104
+ AstNode.__init__(self, kid=new_kid)
3105
+ return res
3106
+
1753
3107
  def py_resolve_name(self) -> str:
1754
3108
  """Resolve name."""
1755
3109
  if self.var.name == Tok.KW_SELF:
@@ -1782,6 +3136,21 @@ class EdgeRefTrailer(Expr):
1782
3136
  self.edges_only = edges_only
1783
3137
  AstNode.__init__(self, kid=kid)
1784
3138
 
3139
+ def normalize(self, deep: bool = True) -> bool:
3140
+ """Normalize ast node."""
3141
+ res = True
3142
+ for expr in self.chain:
3143
+ res = res and expr.normalize(deep)
3144
+ new_kid: list[AstNode] = []
3145
+ if self.edges_only:
3146
+ new_kid.append(self.gen_token(Tok.EDGE_OP))
3147
+ self.gen_token(Tok.LSQUARE)
3148
+ for expr in self.chain:
3149
+ new_kid.append(expr)
3150
+ self.gen_token(Tok.RSQUARE)
3151
+ AstNode.__init__(self, kid=new_kid)
3152
+ return res
3153
+
1785
3154
 
1786
3155
  class EdgeOpRef(WalkerStmtOnlyNode, AtomExpr):
1787
3156
  """EdgeOpRef node type for Jac Ast."""
@@ -1804,6 +3173,36 @@ class EdgeOpRef(WalkerStmtOnlyNode, AtomExpr):
1804
3173
  sym_type=SymbolType.SEQUENCE,
1805
3174
  )
1806
3175
 
3176
+ def normalize(self, deep: bool = False) -> bool:
3177
+ """Normalize ast node."""
3178
+ res = True
3179
+ if deep:
3180
+ res = self.filter_cond.normalize(deep) if self.filter_cond else res
3181
+ new_kid: list[AstNode] = []
3182
+ if self.edge_dir == EdgeDir.IN:
3183
+ if not self.filter_cond:
3184
+ new_kid.append(self.gen_token(Tok.ARROW_L))
3185
+ else:
3186
+ new_kid.append(self.gen_token(Tok.ARROW_L_P1))
3187
+ new_kid.append(self.filter_cond)
3188
+ new_kid.append(self.gen_token(Tok.ARROW_L_P2))
3189
+ elif self.edge_dir == EdgeDir.OUT:
3190
+ if not self.filter_cond:
3191
+ new_kid.append(self.gen_token(Tok.ARROW_R))
3192
+ else:
3193
+ new_kid.append(self.gen_token(Tok.ARROW_R_P1))
3194
+ new_kid.append(self.filter_cond)
3195
+ new_kid.append(self.gen_token(Tok.ARROW_R_P2))
3196
+ else:
3197
+ if not self.filter_cond:
3198
+ new_kid.append(self.gen_token(Tok.ARROW_BI))
3199
+ else:
3200
+ new_kid.append(self.gen_token(Tok.ARROW_L_P1))
3201
+ new_kid.append(self.filter_cond)
3202
+ new_kid.append(self.gen_token(Tok.ARROW_R_P2))
3203
+ AstNode.__init__(self, kid=new_kid)
3204
+ return res
3205
+
1807
3206
 
1808
3207
  class DisconnectOp(WalkerStmtOnlyNode):
1809
3208
  """DisconnectOpRef node type for Jac Ast."""
@@ -1818,6 +3217,15 @@ class DisconnectOp(WalkerStmtOnlyNode):
1818
3217
  AstNode.__init__(self, kid=kid)
1819
3218
  WalkerStmtOnlyNode.__init__(self)
1820
3219
 
3220
+ def normalize(self, deep: bool = False) -> bool:
3221
+ """Normalize ast node."""
3222
+ res = True
3223
+ if deep:
3224
+ res = self.edge_spec.normalize(deep)
3225
+ new_kid: list[AstNode] = [self.gen_token(Tok.NOT), self.edge_spec]
3226
+ AstNode.__init__(self, kid=new_kid)
3227
+ return res
3228
+
1821
3229
 
1822
3230
  class ConnectOp(AstNode):
1823
3231
  """ConnectOpRef node type for Jac Ast."""
@@ -1835,6 +3243,49 @@ class ConnectOp(AstNode):
1835
3243
  self.edge_dir = edge_dir
1836
3244
  AstNode.__init__(self, kid=kid)
1837
3245
 
3246
+ def normalize(self, deep: bool = False) -> bool:
3247
+ """Normalize ast node."""
3248
+ res = True
3249
+ if deep:
3250
+ res = self.conn_type.normalize(deep) if self.conn_type else res
3251
+ res = res and self.conn_assign.normalize(deep) if self.conn_assign else res
3252
+ new_kid: list[AstNode] = []
3253
+ if self.edge_dir == EdgeDir.IN:
3254
+ if not self.conn_assign and not self.conn_type:
3255
+ new_kid.append(self.gen_token(Tok.CARROW_L))
3256
+ else:
3257
+ new_kid.append(self.gen_token(Tok.CARROW_L_P1))
3258
+ if self.conn_type:
3259
+ new_kid.append(self.conn_type)
3260
+ if self.conn_assign:
3261
+ new_kid.append(self.gen_token(Tok.COLON))
3262
+ new_kid.append(self.conn_assign)
3263
+ new_kid.append(self.gen_token(Tok.CARROW_L_P2))
3264
+ elif self.edge_dir == EdgeDir.OUT:
3265
+ if not self.conn_assign and not self.conn_type:
3266
+ new_kid.append(self.gen_token(Tok.CARROW_R))
3267
+ else:
3268
+ new_kid.append(self.gen_token(Tok.CARROW_R_P1))
3269
+ if self.conn_type:
3270
+ new_kid.append(self.conn_type)
3271
+ if self.conn_assign:
3272
+ new_kid.append(self.gen_token(Tok.COLON))
3273
+ new_kid.append(self.conn_assign)
3274
+ new_kid.append(self.gen_token(Tok.CARROW_R_P2))
3275
+ else:
3276
+ if not self.conn_assign and not self.conn_type:
3277
+ new_kid.append(self.gen_token(Tok.CARROW_BI))
3278
+ else:
3279
+ new_kid.append(self.gen_token(Tok.CARROW_L_P1))
3280
+ if self.conn_type:
3281
+ new_kid.append(self.conn_type)
3282
+ if self.conn_assign:
3283
+ new_kid.append(self.gen_token(Tok.COLON))
3284
+ new_kid.append(self.conn_assign)
3285
+ new_kid.append(self.gen_token(Tok.CARROW_R_P2))
3286
+ AstNode.__init__(self, kid=new_kid)
3287
+ return res
3288
+
1838
3289
 
1839
3290
  class FilterCompr(AtomExpr):
1840
3291
  """FilterCtx node type for Jac Ast."""
@@ -1856,6 +3307,26 @@ class FilterCompr(AtomExpr):
1856
3307
  sym_type=SymbolType.SEQUENCE,
1857
3308
  )
1858
3309
 
3310
+ def normalize(self, deep: bool = False) -> bool:
3311
+ """Normalize ast node."""
3312
+ res = True
3313
+ if deep:
3314
+ res = self.f_type.normalize(deep) if self.f_type else res
3315
+ res = res and self.compares.normalize(deep) if self.compares else res
3316
+ new_kid: list[AstNode] = []
3317
+ new_kid.append(self.gen_token(Tok.LPAREN))
3318
+ if self.f_type:
3319
+ new_kid.append(self.gen_token(Tok.TYPE_OP))
3320
+ new_kid.append(self.gen_token(Tok.NULL_OK))
3321
+ if self.f_type:
3322
+ new_kid.append(self.f_type)
3323
+ new_kid.append(self.gen_token(Tok.COLON))
3324
+ if self.compares:
3325
+ new_kid.append(self.compares)
3326
+ new_kid.append(self.gen_token(Tok.RPAREN))
3327
+ AstNode.__init__(self, kid=new_kid)
3328
+ return res
3329
+
1859
3330
 
1860
3331
  class AssignCompr(AtomExpr):
1861
3332
  """AssignCtx node type for Jac Ast."""
@@ -1875,6 +3346,19 @@ class AssignCompr(AtomExpr):
1875
3346
  sym_type=SymbolType.SEQUENCE,
1876
3347
  )
1877
3348
 
3349
+ def normalize(self, deep: bool = False) -> bool:
3350
+ """Normalize ast node."""
3351
+ res = True
3352
+ if deep:
3353
+ res = self.assigns.normalize(deep)
3354
+ new_kid: list[AstNode] = []
3355
+ new_kid.append(self.gen_token(Tok.LPAREN))
3356
+ new_kid.append(self.gen_token(Tok.EQ))
3357
+ new_kid.append(self.assigns)
3358
+ new_kid.append(self.gen_token(Tok.RPAREN))
3359
+ AstNode.__init__(self, kid=new_kid)
3360
+ return res
3361
+
1878
3362
 
1879
3363
  # Match Nodes
1880
3364
  # ------------
@@ -1894,6 +3378,23 @@ class MatchStmt(CodeBlockStmt):
1894
3378
  self.cases = cases
1895
3379
  AstNode.__init__(self, kid=kid)
1896
3380
 
3381
+ def normalize(self, deep: bool = False) -> bool:
3382
+ """Normalize match statement node."""
3383
+ res = True
3384
+ if deep:
3385
+ res = self.target.normalize(deep)
3386
+ for case in self.cases:
3387
+ res = res and case.normalize(deep)
3388
+ new_kid: list[AstNode] = [
3389
+ self.gen_token(Tok.KW_MATCH),
3390
+ self.target,
3391
+ ]
3392
+ for case in self.cases:
3393
+ new_kid.append(case)
3394
+
3395
+ AstNode.__init__(self, kid=new_kid)
3396
+ return res
3397
+
1897
3398
 
1898
3399
  class MatchCase(AstNode):
1899
3400
  """MatchCase node type for Jac Ast."""
@@ -1902,7 +3403,7 @@ class MatchCase(AstNode):
1902
3403
  self,
1903
3404
  pattern: MatchPattern,
1904
3405
  guard: Optional[Expr],
1905
- body: SubNodeList[CodeBlockStmt],
3406
+ body: list[CodeBlockStmt],
1906
3407
  kid: Sequence[AstNode],
1907
3408
  ) -> None:
1908
3409
  """Initialize match case node."""
@@ -1911,6 +3412,24 @@ class MatchCase(AstNode):
1911
3412
  self.body = body
1912
3413
  AstNode.__init__(self, kid=kid)
1913
3414
 
3415
+ def normalize(self, deep: bool = False) -> bool:
3416
+ """Normalize match case node."""
3417
+ res = True
3418
+ if deep:
3419
+ res = self.pattern.normalize(deep)
3420
+ res = res and self.guard.normalize(deep) if self.guard else res
3421
+ for stmt in self.body:
3422
+ res = res and stmt.normalize(deep)
3423
+ new_kid: list[AstNode] = [self.gen_token(Tok.KW_CASE), self.pattern]
3424
+ if self.guard:
3425
+ new_kid.append(self.gen_token(Tok.KW_IF))
3426
+ new_kid.append(self.guard)
3427
+ new_kid.append(self.gen_token(Tok.COLON))
3428
+ if self.body:
3429
+ new_kid.extend([*self.body])
3430
+ AstNode.__init__(self, kid=new_kid)
3431
+ return res
3432
+
1914
3433
 
1915
3434
  class MatchOr(MatchPattern):
1916
3435
  """MatchOr node type for Jac Ast."""
@@ -1924,6 +3443,20 @@ class MatchOr(MatchPattern):
1924
3443
  self.patterns = patterns
1925
3444
  AstNode.__init__(self, kid=kid)
1926
3445
 
3446
+ def normalize(self, deep: bool = False) -> bool:
3447
+ """Normalize match or node."""
3448
+ res = True
3449
+ if deep:
3450
+ for pattern in self.patterns:
3451
+ res = res and pattern.normalize(deep)
3452
+ new_kid: list[AstNode] = []
3453
+ for pattern in self.patterns:
3454
+ new_kid.append(pattern)
3455
+ new_kid.append(self.gen_token(Tok.KW_OR))
3456
+ new_kid.pop()
3457
+ AstNode.__init__(self, kid=new_kid)
3458
+ return res
3459
+
1927
3460
 
1928
3461
  class MatchAs(MatchPattern):
1929
3462
  """MatchAs node type for Jac Ast."""
@@ -1939,10 +3472,43 @@ class MatchAs(MatchPattern):
1939
3472
  self.pattern = pattern
1940
3473
  AstNode.__init__(self, kid=kid)
1941
3474
 
3475
+ def normalize(self, deep: bool = False) -> bool:
3476
+ """Normalize match as node."""
3477
+ res = True
3478
+ if deep:
3479
+ res = self.name.normalize(deep)
3480
+ res = res and self.pattern.normalize(deep) if self.pattern else res
3481
+ new_kid: list[AstNode] = []
3482
+ if self.pattern:
3483
+ new_kid.append(self.pattern)
3484
+ new_kid.append(self.gen_token(Tok.KW_AS))
3485
+ new_kid.append(self.name)
3486
+ AstNode.__init__(self, kid=new_kid)
3487
+ return res
3488
+
1942
3489
 
1943
3490
  class MatchWild(MatchPattern):
1944
3491
  """Match wild card node type for Jac Ast."""
1945
3492
 
3493
+ def normalize(self, deep: bool = False) -> bool:
3494
+ """Normalize match wild card node."""
3495
+ AstNode.__init__(
3496
+ self,
3497
+ kid=[
3498
+ Name(
3499
+ file_path=self.loc.mod_path,
3500
+ name=Tok.NAME,
3501
+ value="_",
3502
+ col_start=self.loc.col_start,
3503
+ col_end=self.loc.col_end,
3504
+ line=self.loc.first_line,
3505
+ pos_start=self.loc.pos_start,
3506
+ pos_end=self.loc.pos_end,
3507
+ )
3508
+ ],
3509
+ )
3510
+ return True
3511
+
1946
3512
 
1947
3513
  class MatchValue(MatchPattern):
1948
3514
  """MatchValue node type for Jac Ast."""
@@ -1956,6 +3522,14 @@ class MatchValue(MatchPattern):
1956
3522
  self.value = value
1957
3523
  AstNode.__init__(self, kid=kid)
1958
3524
 
3525
+ def normalize(self, deep: bool = False) -> bool:
3526
+ """Normalize match value node."""
3527
+ res = True
3528
+ if deep:
3529
+ res = self.value.normalize(deep)
3530
+ AstNode.__init__(self, kid=[self.value])
3531
+ return res
3532
+
1959
3533
 
1960
3534
  class MatchSingleton(MatchPattern):
1961
3535
  """MatchSingleton node type for Jac Ast."""
@@ -1969,6 +3543,12 @@ class MatchSingleton(MatchPattern):
1969
3543
  self.value = value
1970
3544
  AstNode.__init__(self, kid=kid)
1971
3545
 
3546
+ def normalize(self, deep: bool = False) -> bool:
3547
+ """Normalize match singleton node."""
3548
+ res = True
3549
+ AstNode.__init__(self, kid=[self.value])
3550
+ return res
3551
+
1972
3552
 
1973
3553
  class MatchSequence(MatchPattern):
1974
3554
  """MatchSequence node type for Jac Ast."""
@@ -1982,6 +3562,21 @@ class MatchSequence(MatchPattern):
1982
3562
  self.values = values
1983
3563
  AstNode.__init__(self, kid=kid)
1984
3564
 
3565
+ def normalize(self, deep: bool = False) -> bool:
3566
+ """Normalize match sequence node."""
3567
+ res = True
3568
+ if deep:
3569
+ for value in self.values:
3570
+ res = res and value.normalize(deep)
3571
+ new_kid: list[AstNode] = [self.gen_token(Tok.LSQUARE)]
3572
+ for value in self.values:
3573
+ new_kid.append(value)
3574
+ new_kid.append(self.gen_token(Tok.COMMA))
3575
+ new_kid.pop()
3576
+ new_kid.append(self.gen_token(Tok.RSQUARE))
3577
+ AstNode.__init__(self, kid=new_kid)
3578
+ return res
3579
+
1985
3580
 
1986
3581
  class MatchMapping(MatchPattern):
1987
3582
  """MatchMapping node type for Jac Ast."""
@@ -1995,6 +3590,21 @@ class MatchMapping(MatchPattern):
1995
3590
  self.values = values
1996
3591
  AstNode.__init__(self, kid=kid)
1997
3592
 
3593
+ def normalize(self, deep: bool = False) -> bool:
3594
+ """Normalize match mapping node."""
3595
+ res = True
3596
+ if deep:
3597
+ for value in self.values:
3598
+ res = res and value.normalize(deep)
3599
+ new_kid: list[AstNode] = [self.gen_token(Tok.LBRACE)]
3600
+ for value in self.values:
3601
+ new_kid.append(value)
3602
+ new_kid.append(self.gen_token(Tok.COMMA))
3603
+ new_kid.pop()
3604
+ new_kid.append(self.gen_token(Tok.RBRACE))
3605
+ AstNode.__init__(self, kid=new_kid)
3606
+ return res
3607
+
1998
3608
 
1999
3609
  class MatchKVPair(MatchPattern):
2000
3610
  """MatchKVPair node type for Jac Ast."""
@@ -2010,6 +3620,18 @@ class MatchKVPair(MatchPattern):
2010
3620
  self.value = value
2011
3621
  AstNode.__init__(self, kid=kid)
2012
3622
 
3623
+ def normalize(self, deep: bool = False) -> bool:
3624
+ """Normalize match key value pair node."""
3625
+ res = True
3626
+ if deep:
3627
+ res = (
3628
+ self.key.normalize(deep) if isinstance(self.key, MatchPattern) else True
3629
+ )
3630
+ res = res and self.value.normalize(deep)
3631
+ new_kid: list[AstNode] = [self.key, self.gen_token(Tok.COLON), self.value]
3632
+ AstNode.__init__(self, kid=new_kid)
3633
+ return res
3634
+
2013
3635
 
2014
3636
  class MatchStar(MatchPattern):
2015
3637
  """MatchStar node type for Jac Ast."""
@@ -2025,6 +3647,18 @@ class MatchStar(MatchPattern):
2025
3647
  self.is_list = is_list
2026
3648
  AstNode.__init__(self, kid=kid)
2027
3649
 
3650
+ def normalize(self, deep: bool = False) -> bool:
3651
+ """Normalize match star node."""
3652
+ res = True
3653
+ if deep:
3654
+ res = self.name.normalize(deep)
3655
+ new_kid: list[AstNode] = [
3656
+ self.gen_token(Tok.STAR_MUL if self.is_list else Tok.STAR_POW)
3657
+ ]
3658
+ new_kid.append(self.name)
3659
+ AstNode.__init__(self, kid=new_kid)
3660
+ return res
3661
+
2028
3662
 
2029
3663
  class MatchArch(MatchPattern):
2030
3664
  """MatchClass node type for Jac Ast."""
@@ -2042,6 +3676,26 @@ class MatchArch(MatchPattern):
2042
3676
  self.kw_patterns = kw_patterns
2043
3677
  AstNode.__init__(self, kid=kid)
2044
3678
 
3679
+ def normalize(self, deep: bool = False) -> bool:
3680
+ """Normalize match class node."""
3681
+ res = True
3682
+ if deep:
3683
+ res = self.name.normalize(deep)
3684
+ res = res and (not self.arg_patterns or self.arg_patterns.normalize(deep))
3685
+ res = res and (not self.kw_patterns or self.kw_patterns.normalize(deep))
3686
+ new_kid: list[AstNode] = [self.name]
3687
+ new_kid.append(self.gen_token(Tok.LPAREN))
3688
+ if self.arg_patterns:
3689
+ new_kid.append(self.arg_patterns)
3690
+ new_kid.append(self.gen_token(Tok.COMMA))
3691
+ if self.kw_patterns:
3692
+ new_kid.append(self.kw_patterns)
3693
+ else:
3694
+ new_kid.pop()
3695
+ new_kid.append(self.gen_token(Tok.RPAREN))
3696
+ AstNode.__init__(self, kid=new_kid)
3697
+ return res
3698
+
2045
3699
 
2046
3700
  # AST Terminal Node Types
2047
3701
  # --------------------------
@@ -2058,7 +3712,6 @@ class Token(AstNode):
2058
3712
  col_end: int,
2059
3713
  pos_start: int,
2060
3714
  pos_end: int,
2061
- kid: Sequence[AstNode],
2062
3715
  ) -> None:
2063
3716
  """Initialize token."""
2064
3717
  self.file_path = file_path
@@ -2069,7 +3722,15 @@ class Token(AstNode):
2069
3722
  self.c_end = col_end
2070
3723
  self.pos_start = pos_start
2071
3724
  self.pos_end = pos_end
2072
- AstNode.__init__(self, kid=kid)
3725
+ AstNode.__init__(self, kid=[])
3726
+
3727
+ def normalize(self, deep: bool = True) -> bool:
3728
+ """Normalize token."""
3729
+ return bool(self.value and self.name)
3730
+
3731
+ def unparse(self) -> str:
3732
+ """Unparse token."""
3733
+ return self.value
2073
3734
 
2074
3735
 
2075
3736
  class Name(Token, NameSpec):
@@ -2085,7 +3746,6 @@ class Name(Token, NameSpec):
2085
3746
  col_end: int,
2086
3747
  pos_start: int,
2087
3748
  pos_end: int,
2088
- kid: Sequence[AstNode],
2089
3749
  is_enum_singleton: bool = False,
2090
3750
  is_kwesc: bool = False,
2091
3751
  ) -> None:
@@ -2102,7 +3762,6 @@ class Name(Token, NameSpec):
2102
3762
  col_end=col_end,
2103
3763
  pos_start=pos_start,
2104
3764
  pos_end=pos_end,
2105
- kid=kid,
2106
3765
  )
2107
3766
  AstSymbolNode.__init__(
2108
3767
  self,
@@ -2111,6 +3770,13 @@ class Name(Token, NameSpec):
2111
3770
  sym_type=SymbolType.VAR,
2112
3771
  )
2113
3772
 
3773
+ def unparse(self) -> str:
3774
+ """Unparse name."""
3775
+ super().unparse()
3776
+ return (f"<>{self.value}" if self.is_kwesc else self.value) + (
3777
+ ",\n" if self.is_enum_singleton else ""
3778
+ )
3779
+
2114
3780
 
2115
3781
  class Literal(Token, AtomExpr):
2116
3782
  """Literal node type for Jac Ast."""
@@ -2140,7 +3806,6 @@ class Literal(Token, AtomExpr):
2140
3806
  col_end: int,
2141
3807
  pos_start: int,
2142
3808
  pos_end: int,
2143
- kid: Sequence[AstNode],
2144
3809
  ) -> None:
2145
3810
  """Initialize token."""
2146
3811
  Token.__init__(
@@ -2153,7 +3818,6 @@ class Literal(Token, AtomExpr):
2153
3818
  col_end=col_end,
2154
3819
  pos_start=pos_start,
2155
3820
  pos_end=pos_end,
2156
- kid=kid,
2157
3821
  )
2158
3822
  AstSymbolNode.__init__(
2159
3823
  self,
@@ -2185,7 +3849,6 @@ class TokenSymbol(Token, AstSymbolNode):
2185
3849
  col_end: int,
2186
3850
  pos_start: int,
2187
3851
  pos_end: int,
2188
- kid: Sequence[AstNode],
2189
3852
  ) -> None:
2190
3853
  """Initialize token."""
2191
3854
  Token.__init__(
@@ -2198,7 +3861,6 @@ class TokenSymbol(Token, AstSymbolNode):
2198
3861
  col_end=col_end,
2199
3862
  pos_start=pos_start,
2200
3863
  pos_end=pos_end,
2201
- kid=kid,
2202
3864
  )
2203
3865
  AstSymbolNode.__init__(
2204
3866
  self,
@@ -2266,6 +3928,15 @@ class String(Literal):
2266
3928
  ret_str = ret_str.encode().decode("unicode_escape")
2267
3929
  return ret_str
2268
3930
 
3931
+ def normalize(self, deep: bool = True) -> bool:
3932
+ """Normalize string."""
3933
+ return True
3934
+
3935
+ def unparse(self) -> str:
3936
+ """Unparse string."""
3937
+ super().unparse()
3938
+ return repr(self.value)
3939
+
2269
3940
 
2270
3941
  class Bool(Literal):
2271
3942
  """Bool node type for Jac Ast."""
@@ -2314,7 +3985,6 @@ class EmptyToken(Token):
2314
3985
  col_end=0,
2315
3986
  pos_start=0,
2316
3987
  pos_end=0,
2317
- kid=[],
2318
3988
  )
2319
3989
 
2320
3990