jaclang 0.7.1__py3-none-any.whl → 0.7.7__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 (106) hide show
  1. jaclang/cli/cli.py +2 -2
  2. jaclang/compiler/absyntree.py +539 -297
  3. jaclang/compiler/codeloc.py +2 -2
  4. jaclang/compiler/constant.py +100 -2
  5. jaclang/compiler/jac.lark +27 -19
  6. jaclang/compiler/parser.py +119 -92
  7. jaclang/compiler/passes/main/access_modifier_pass.py +20 -12
  8. jaclang/compiler/passes/main/def_impl_match_pass.py +32 -12
  9. jaclang/compiler/passes/main/def_use_pass.py +59 -40
  10. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +71 -30
  11. jaclang/compiler/passes/main/import_pass.py +12 -7
  12. jaclang/compiler/passes/main/pyast_gen_pass.py +110 -47
  13. jaclang/compiler/passes/main/pyast_load_pass.py +49 -13
  14. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +25 -11
  15. jaclang/compiler/passes/main/pyout_pass.py +3 -1
  16. jaclang/compiler/passes/main/registry_pass.py +6 -6
  17. jaclang/compiler/passes/main/sub_node_tab_pass.py +0 -5
  18. jaclang/compiler/passes/main/sym_tab_build_pass.py +43 -235
  19. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +21 -4
  20. jaclang/compiler/passes/main/tests/test_def_use_pass.py +5 -10
  21. jaclang/compiler/passes/main/tests/test_import_pass.py +8 -0
  22. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  23. jaclang/compiler/passes/main/type_check_pass.py +2 -1
  24. jaclang/compiler/passes/tool/jac_formatter_pass.py +44 -11
  25. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
  26. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
  27. jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
  28. jaclang/compiler/passes/tool/tests/fixtures/genai/essay_review.jac +1 -1
  29. jaclang/compiler/passes/tool/tests/fixtures/genai/expert_answer.jac +1 -1
  30. jaclang/compiler/passes/tool/tests/fixtures/genai/joke_gen.jac +1 -1
  31. jaclang/compiler/passes/tool/tests/fixtures/genai/odd_word_out.jac +1 -1
  32. jaclang/compiler/passes/tool/tests/fixtures/genai/personality_finder.jac +1 -1
  33. jaclang/compiler/passes/tool/tests/fixtures/genai/text_to_type.jac +1 -1
  34. jaclang/compiler/passes/tool/tests/fixtures/genai/translator.jac +1 -1
  35. jaclang/compiler/passes/tool/tests/fixtures/genai/wikipedia.jac +1 -1
  36. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
  37. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
  38. jaclang/compiler/passes/transform.py +2 -4
  39. jaclang/{core/registry.py → compiler/semtable.py} +1 -3
  40. jaclang/compiler/symtable.py +150 -89
  41. jaclang/compiler/tests/test_parser.py +2 -2
  42. jaclang/core/aott.py +118 -18
  43. jaclang/core/{construct.py → architype.py} +44 -93
  44. jaclang/core/constructs.py +44 -0
  45. jaclang/core/context.py +157 -0
  46. jaclang/core/importer.py +18 -9
  47. jaclang/core/memory.py +53 -2
  48. jaclang/core/test.py +90 -0
  49. jaclang/core/utils.py +2 -2
  50. jaclang/langserve/engine.py +199 -138
  51. jaclang/langserve/server.py +48 -53
  52. jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -0
  53. jaclang/langserve/tests/fixtures/circle.jac +16 -12
  54. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  55. jaclang/langserve/tests/fixtures/circle_pure.impl.jac +8 -4
  56. jaclang/langserve/tests/fixtures/circle_pure.jac +2 -2
  57. jaclang/langserve/tests/fixtures/circle_pure.test.jac +15 -0
  58. jaclang/langserve/tests/fixtures/import_include_statements.jac +6 -0
  59. jaclang/langserve/tests/fixtures/py_import.py +26 -0
  60. jaclang/langserve/tests/test_server.py +200 -2
  61. jaclang/langserve/utils.py +214 -10
  62. jaclang/plugin/builtin.py +1 -1
  63. jaclang/plugin/default.py +48 -92
  64. jaclang/plugin/feature.py +33 -17
  65. jaclang/plugin/spec.py +18 -20
  66. jaclang/plugin/tests/test_features.py +0 -33
  67. jaclang/settings.py +4 -0
  68. jaclang/tests/fixtures/abc.jac +16 -12
  69. jaclang/tests/fixtures/aott_raise.jac +1 -1
  70. jaclang/tests/fixtures/byllmissue.jac +12 -0
  71. jaclang/tests/fixtures/edgetypeissue.jac +10 -0
  72. jaclang/tests/fixtures/hash_init_check.jac +17 -0
  73. jaclang/tests/fixtures/hello.jac +1 -1
  74. jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
  75. jaclang/tests/fixtures/impl_match_confused.jac +5 -0
  76. jaclang/tests/fixtures/math_question.jpg +0 -0
  77. jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
  78. jaclang/tests/fixtures/nosigself.jac +19 -0
  79. jaclang/tests/fixtures/run_test.jac +17 -5
  80. jaclang/tests/fixtures/walker_override.jac +21 -0
  81. jaclang/tests/fixtures/with_llm_function.jac +1 -1
  82. jaclang/tests/fixtures/with_llm_lower.jac +1 -1
  83. jaclang/tests/fixtures/with_llm_method.jac +1 -1
  84. jaclang/tests/fixtures/with_llm_type.jac +1 -1
  85. jaclang/tests/fixtures/with_llm_vision.jac +25 -0
  86. jaclang/tests/test_bugs.py +19 -0
  87. jaclang/tests/test_cli.py +1 -1
  88. jaclang/tests/test_language.py +197 -82
  89. jaclang/tests/test_reference.py +1 -1
  90. jaclang/utils/lang_tools.py +5 -4
  91. jaclang/utils/test.py +2 -1
  92. jaclang/utils/treeprinter.py +35 -4
  93. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/METADATA +3 -2
  94. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/RECORD +96 -88
  95. jaclang/core/llms/__init__.py +0 -20
  96. jaclang/core/llms/anthropic.py +0 -61
  97. jaclang/core/llms/base.py +0 -206
  98. jaclang/core/llms/groq.py +0 -67
  99. jaclang/core/llms/huggingface.py +0 -73
  100. jaclang/core/llms/ollama.py +0 -78
  101. jaclang/core/llms/openai.py +0 -61
  102. jaclang/core/llms/togetherai.py +0 -60
  103. jaclang/core/llms/utils.py +0 -9
  104. jaclang/core/shelve_storage.py +0 -55
  105. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/WHEEL +0 -0
  106. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/entry_points.txt +0 -0
@@ -3,24 +3,38 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import ast as ast3
6
+ import builtins
7
+ import os
6
8
  from hashlib import md5
7
9
  from types import EllipsisType
8
- from typing import Any, Callable, Generic, Optional, Sequence, Type, TypeVar
10
+ from typing import (
11
+ Any,
12
+ Callable,
13
+ Generic,
14
+ Optional,
15
+ Sequence,
16
+ TYPE_CHECKING,
17
+ Type,
18
+ TypeVar,
19
+ )
20
+
9
21
 
10
22
  from jaclang.compiler import TOKEN_MAP
11
23
  from jaclang.compiler.codeloc import CodeGenTarget, CodeLocInfo
12
- from jaclang.compiler.constant import Constants as Con, EdgeDir
13
- from jaclang.compiler.constant import DELIM_MAP, Tokens as Tok
14
- from jaclang.compiler.symtable import (
15
- Symbol,
16
- SymbolAccess,
17
- SymbolInfo,
18
- SymbolTable,
24
+ from jaclang.compiler.constant import (
25
+ Constants as Con,
26
+ EdgeDir,
27
+ JacSemTokenModifier as SemTokMod,
28
+ JacSemTokenType as SemTokType,
19
29
  SymbolType,
20
30
  )
21
- from jaclang.core.registry import SemRegistry
31
+ from jaclang.compiler.constant import DELIM_MAP, SymbolAccess, Tokens as Tok
32
+ from jaclang.compiler.semtable import SemRegistry
22
33
  from jaclang.utils.treeprinter import dotgen_ast_tree, print_ast_tree
23
34
 
35
+ if TYPE_CHECKING:
36
+ from jaclang.compiler.symtable import Symbol, SymbolTable
37
+
24
38
 
25
39
  class AstNode:
26
40
  """Abstract syntax tree node for Jac."""
@@ -29,13 +43,35 @@ class AstNode:
29
43
  """Initialize ast."""
30
44
  self.parent: Optional[AstNode] = None
31
45
  self.kid: list[AstNode] = [x.set_parent(self) for x in kid]
32
- self.sym_tab: Optional[SymbolTable] = None
46
+ self._sym_tab: Optional[SymbolTable] = None
33
47
  self._sub_node_tab: dict[type, list[AstNode]] = {}
34
- self._typ: type = type(None)
48
+ self._in_mod_nodes: list[AstNode] = []
35
49
  self.gen: CodeGenTarget = CodeGenTarget()
36
50
  self.meta: dict[str, str] = {}
37
51
  self.loc: CodeLocInfo = CodeLocInfo(*self.resolve_tok_range())
38
52
 
53
+ @property
54
+ def sym_tab(self) -> SymbolTable:
55
+ """Get symbol table."""
56
+ # sym_tab should never be accessed without being set in codebase
57
+ if not self._sym_tab:
58
+ import traceback
59
+
60
+ if self.parent:
61
+ print(f"Parent: {self.parent.pp()}")
62
+ print("Node: ", self.pp())
63
+ stack_trace = traceback.format_stack()
64
+ print("".join(stack_trace))
65
+ raise ValueError(
66
+ f"Symbol table not set for {type(self).__name__}. Impossible."
67
+ )
68
+ return self._sym_tab
69
+
70
+ @sym_tab.setter
71
+ def sym_tab(self, sym_tab: SymbolTable) -> None:
72
+ """Set symbol table."""
73
+ self._sym_tab = sym_tab
74
+
39
75
  def add_kids_left(
40
76
  self, nodes: Sequence[AstNode], pos_update: bool = True
41
77
  ) -> AstNode:
@@ -58,6 +94,17 @@ class AstNode:
58
94
  self.loc.update_last_token(self.kid[-1].loc.last_tok)
59
95
  return self
60
96
 
97
+ def insert_kids_at_pos(
98
+ self, nodes: Sequence[AstNode], pos: int, pos_update: bool = True
99
+ ) -> AstNode:
100
+ """Insert kids at position."""
101
+ self.kid = [*self.kid[:pos], *nodes, *self.kid[pos:]]
102
+ if pos_update:
103
+ for i in nodes:
104
+ i.parent = self
105
+ self.loc.update_token_range(*self.resolve_tok_range())
106
+ return self
107
+
61
108
  def set_kids(self, nodes: Sequence[AstNode]) -> AstNode:
62
109
  """Set kids."""
63
110
  self.kid = [*nodes]
@@ -101,6 +148,7 @@ class AstNode:
101
148
  col_start=self.loc.col_start,
102
149
  col_end=0,
103
150
  line=self.loc.first_line,
151
+ end_line=self.loc.last_line,
104
152
  pos_start=0,
105
153
  pos_end=0,
106
154
  )
@@ -111,11 +159,15 @@ class AstNode:
111
159
 
112
160
  return Pass.get_all_sub_nodes(node=self, typ=typ, brute_force=brute_force)
113
161
 
114
- def parent_of_type(self, typ: Type[T]) -> T:
162
+ def find_parent_of_type(self, typ: Type[T]) -> Optional[T]:
115
163
  """Get parent of type."""
116
164
  from jaclang.compiler.passes import Pass
117
165
 
118
- ret = Pass.has_parent_of_type(node=self, typ=typ)
166
+ return Pass.has_parent_of_type(node=self, typ=typ)
167
+
168
+ def parent_of_type(self, typ: Type[T]) -> T:
169
+ """Get parent of type."""
170
+ ret = self.find_parent_of_type(typ)
119
171
  if isinstance(ret, typ):
120
172
  return ret
121
173
  else:
@@ -172,15 +224,56 @@ class AstSymbolNode(AstNode):
172
224
  """Nodes that have link to a symbol in symbol table."""
173
225
 
174
226
  def __init__(
175
- self, sym_name: str, sym_name_node: AstNode, sym_type: SymbolType
227
+ self, sym_name: str, name_spec: NameAtom, sym_category: SymbolType
176
228
  ) -> None:
177
229
  """Initialize ast."""
178
- self.sym_link: Optional[Symbol] = None
179
- self.sym_name: str = sym_name
180
- self.sym_name_node = sym_name_node
181
- self.sym_type: SymbolType = sym_type
182
- self.sym_info: SymbolInfo = SymbolInfo()
183
- self.py_ctx_func: Type[ast3.AST] = ast3.Load
230
+ self.name_spec = name_spec
231
+ self.name_spec.name_of = self
232
+ self.name_spec._sym_name = sym_name
233
+ self.name_spec._sym_category = sym_category
234
+
235
+ @property
236
+ def sym(self) -> Optional[Symbol]:
237
+ """Get symbol."""
238
+ return self.name_spec.sym
239
+
240
+ @property
241
+ def sym_name(self) -> str:
242
+ """Get symbol name."""
243
+ return self.name_spec.sym_name
244
+
245
+ @property
246
+ def sym_category(self) -> SymbolType:
247
+ """Get symbol category."""
248
+ return self.name_spec.sym_category
249
+
250
+ @property
251
+ def py_ctx_func(self) -> Type[ast3.AST]:
252
+ """Get python context function."""
253
+ return self.name_spec.py_ctx_func
254
+
255
+ @property
256
+ def sym_type(self) -> str:
257
+ """Get symbol type."""
258
+ return self.name_spec.sym_type
259
+
260
+ @property
261
+ def type_sym_tab(self) -> Optional[SymbolTable]:
262
+ """Get type symbol table."""
263
+ return self.name_spec.type_sym_tab
264
+
265
+
266
+ class AstSymbolStubNode(AstSymbolNode):
267
+ """Nodes that have link to a symbol in symbol table."""
268
+
269
+ def __init__(self, sym_type: SymbolType) -> None:
270
+ """Initialize ast."""
271
+ AstSymbolNode.__init__(
272
+ self,
273
+ sym_name=f"[{self.__class__.__name__}]",
274
+ name_spec=Name.gen_stub_from_node(self, f"[{self.__class__.__name__}]"),
275
+ sym_category=sym_type,
276
+ )
184
277
 
185
278
 
186
279
  class AstAccessNode(AstNode):
@@ -255,13 +348,73 @@ class WalkerStmtOnlyNode(AstNode):
255
348
  self.from_walker: bool = False
256
349
 
257
350
 
258
- class AstImplOnlyNode(AstNode):
351
+ class Expr(AstNode):
352
+ """Expr node type for Jac Ast."""
353
+
354
+
355
+ class AtomExpr(Expr, AstSymbolStubNode):
356
+ """AtomExpr node type for Jac Ast."""
357
+
358
+
359
+ class ElementStmt(AstDocNode):
360
+ """ElementStmt node type for Jac Ast."""
361
+
362
+
363
+ class ArchBlockStmt(AstNode):
364
+ """ArchBlockStmt node type for Jac Ast."""
365
+
366
+
367
+ class EnumBlockStmt(AstNode):
368
+ """EnumBlockStmt node type for Jac Ast."""
369
+
370
+
371
+ class CodeBlockStmt(AstNode):
372
+ """CodeBlockStmt node type for Jac Ast."""
373
+
374
+
375
+ class AstImplOnlyNode(CodeBlockStmt, ElementStmt, AstSymbolNode):
259
376
  """ImplOnly node type for Jac Ast."""
260
377
 
261
- def __init__(self, body: SubNodeList, decl_link: Optional[AstNode]) -> None:
378
+ def __init__(
379
+ self, target: ArchRefChain, body: SubNodeList, decl_link: Optional[AstNode]
380
+ ) -> None:
262
381
  """Initialize impl only node."""
382
+ self.target = target
263
383
  self.body = body
264
384
  self.decl_link = decl_link
385
+ AstSymbolNode.__init__(
386
+ self,
387
+ sym_name=self.target.py_resolve_name(),
388
+ name_spec=self.create_impl_name_node(),
389
+ sym_category=SymbolType.IMPL,
390
+ )
391
+
392
+ @property
393
+ def sym_tab(self) -> SymbolTable:
394
+ """Get symbol table."""
395
+ return super().sym_tab
396
+
397
+ @sym_tab.setter
398
+ def sym_tab(self, sym_tab: SymbolTable) -> None:
399
+ """Set symbol table."""
400
+ self._sym_tab = sym_tab
401
+ self.name_spec._sym_tab = sym_tab
402
+
403
+ def create_impl_name_node(self) -> Name:
404
+ """Create impl name."""
405
+ ret = Name(
406
+ file_path=self.target.archs[-1].loc.mod_path,
407
+ name=Tok.NAME.value,
408
+ value=self.target.py_resolve_name(),
409
+ col_start=self.target.archs[0].loc.col_start,
410
+ col_end=self.target.archs[-1].loc.col_end,
411
+ line=self.target.archs[0].loc.first_line,
412
+ end_line=self.target.archs[-1].loc.last_line,
413
+ pos_start=self.target.archs[0].loc.pos_start,
414
+ pos_end=self.target.archs[-1].loc.pos_end,
415
+ )
416
+ ret.name_of = self
417
+ return ret
265
418
 
266
419
 
267
420
  class AstImplNeedingNode(AstSymbolNode, Generic[T]):
@@ -277,32 +430,109 @@ class AstImplNeedingNode(AstSymbolNode, Generic[T]):
277
430
  return self.body is None
278
431
 
279
432
 
280
- class Expr(AstNode):
281
- """Expr node type for Jac Ast."""
433
+ class NameAtom(AtomExpr, EnumBlockStmt):
434
+ """NameSpec node type for Jac Ast."""
282
435
 
436
+ def __init__(self) -> None:
437
+ """Initialize name spec node."""
438
+ self.name_of: AstSymbolNode = self
439
+ self._sym: Optional[Symbol] = None
440
+ self._sym_name: str = ""
441
+ self._sym_category: SymbolType = SymbolType.UNKNOWN
442
+ self._py_ctx_func: Type[ast3.AST] = ast3.Load
443
+ self._sym_type: str = "NoType"
444
+ self._type_sym_tab: Optional[SymbolTable] = None
283
445
 
284
- class AtomExpr(Expr, AstSymbolNode):
285
- """AtomExpr node type for Jac Ast."""
446
+ @property
447
+ def sym(self) -> Optional[Symbol]:
448
+ """Get symbol."""
449
+ return self._sym
286
450
 
451
+ @sym.setter
452
+ def sym(self, sym: Symbol) -> None:
453
+ """Set symbol."""
454
+ self._sym = sym
287
455
 
288
- class ElementStmt(AstDocNode):
289
- """ElementStmt node type for Jac Ast."""
456
+ @property
457
+ def sym_name(self) -> str:
458
+ """Get symbol name."""
459
+ return self._sym_name
290
460
 
461
+ @property
462
+ def sym_category(self) -> SymbolType:
463
+ """Get symbol category."""
464
+ return self._sym_category
291
465
 
292
- class ArchBlockStmt(AstNode):
293
- """ArchBlockStmt node type for Jac Ast."""
466
+ @property
467
+ def clean_type(self) -> str:
468
+ """Get clean type."""
469
+ ret_type = self.sym_type.replace("builtins.", "").replace("NoType", "")
470
+ return ret_type
294
471
 
472
+ @property
473
+ def py_ctx_func(self) -> Type[ast3.AST]:
474
+ """Get python context function."""
475
+ return self._py_ctx_func
295
476
 
296
- class EnumBlockStmt(AstNode):
297
- """EnumBlockStmt node type for Jac Ast."""
477
+ @py_ctx_func.setter
478
+ def py_ctx_func(self, py_ctx_func: Type[ast3.AST]) -> None:
479
+ """Set python context function."""
480
+ self._py_ctx_func = py_ctx_func
298
481
 
482
+ @property
483
+ def sym_type(self) -> str:
484
+ """Get symbol type."""
485
+ return self._sym_type
299
486
 
300
- class CodeBlockStmt(AstNode):
301
- """CodeBlockStmt node type for Jac Ast."""
487
+ @sym_type.setter
488
+ def sym_type(self, sym_type: str) -> None:
489
+ """Set symbol type."""
490
+ self._sym_type = sym_type
302
491
 
492
+ @property
493
+ def type_sym_tab(self) -> Optional[SymbolTable]:
494
+ """Get type symbol table."""
495
+ return self._type_sym_tab
303
496
 
304
- class NameSpec(AtomExpr, EnumBlockStmt):
305
- """NameSpec node type for Jac Ast."""
497
+ @type_sym_tab.setter
498
+ def type_sym_tab(self, type_sym_tab: SymbolTable) -> None:
499
+ """Set type symbol table."""
500
+ self._type_sym_tab = type_sym_tab
501
+
502
+ @property
503
+ def sem_token(self) -> Optional[tuple[SemTokType, SemTokMod]]:
504
+ """Resolve semantic token."""
505
+ if isinstance(self.name_of, BuiltinType):
506
+ return SemTokType.CLASS, SemTokMod.DECLARATION
507
+ name_of = (
508
+ self.sym.decl.name_of
509
+ if self.sym and not isinstance(self.sym.decl.name_of, Name)
510
+ else self.name_of
511
+ )
512
+ if isinstance(name_of, ModulePath):
513
+ return SemTokType.NAMESPACE, SemTokMod.DEFINITION
514
+ if isinstance(name_of, Architype):
515
+ return SemTokType.CLASS, SemTokMod.DECLARATION
516
+ if isinstance(name_of, Enum):
517
+ return SemTokType.ENUM, SemTokMod.DECLARATION
518
+ if isinstance(name_of, Ability) and name_of.is_method:
519
+ return SemTokType.METHOD, SemTokMod.DECLARATION
520
+ if isinstance(name_of, (Ability, Test)):
521
+ return SemTokType.FUNCTION, SemTokMod.DECLARATION
522
+ if isinstance(name_of, ParamVar):
523
+ return SemTokType.PARAMETER, SemTokMod.DECLARATION
524
+ if self.sym and self.sym_name.isupper():
525
+ return SemTokType.VARIABLE, SemTokMod.READONLY
526
+ if (
527
+ self.sym
528
+ and self.sym.decl.name_of == self.sym.decl
529
+ and self.sym_name in dir(builtins)
530
+ and callable(getattr(builtins, self.sym_name))
531
+ ):
532
+ return SemTokType.FUNCTION, SemTokMod.DEFINITION
533
+ if self.sym:
534
+ return SemTokType.PROPERTY, SemTokMod.DEFINITION
535
+ return None
306
536
 
307
537
 
308
538
  class ArchSpec(ElementStmt, CodeBlockStmt, AstSymbolNode, AstDocNode, AstSemStrNode):
@@ -392,7 +622,7 @@ class Module(AstDocNode):
392
622
  body: Sequence[ElementStmt | String | EmptyToken],
393
623
  is_imported: bool,
394
624
  kid: Sequence[AstNode],
395
- test_mod: Optional[Module] = None,
625
+ stub_only: bool = False,
396
626
  registry: Optional[SemRegistry] = None,
397
627
  ) -> None:
398
628
  """Initialize whole program node."""
@@ -400,13 +630,41 @@ class Module(AstDocNode):
400
630
  self.source = source
401
631
  self.body = body
402
632
  self.is_imported = is_imported
633
+ self.stub_only = stub_only
403
634
  self.impl_mod: list[Module] = []
404
- self.test_mod = test_mod
635
+ self.test_mod: list[Module] = []
405
636
  self.mod_deps: dict[str, Module] = {}
406
637
  self.registry = registry
407
638
  AstNode.__init__(self, kid=kid)
408
639
  AstDocNode.__init__(self, doc=doc)
409
640
 
641
+ @property
642
+ def annexable_by(self) -> Optional[str]:
643
+ """Get annexable by."""
644
+ if not self.stub_only and (
645
+ self.loc.mod_path.endswith("impl.jac")
646
+ or self.loc.mod_path.endswith("test.jac")
647
+ ):
648
+ head_mod_name = self.name.split(".")[0]
649
+ potential_path = os.path.join(
650
+ os.path.dirname(self.loc.mod_path),
651
+ f"{head_mod_name}.jac",
652
+ )
653
+ if os.path.exists(potential_path):
654
+ return potential_path
655
+ annex_dir = os.path.split(os.path.dirname(self.loc.mod_path))[-1]
656
+ if annex_dir.endswith(".impl") or annex_dir.endswith(".test"):
657
+ head_mod_name = os.path.split(os.path.dirname(self.loc.mod_path))[
658
+ -1
659
+ ].split(".")[0]
660
+ potential_path = os.path.join(
661
+ os.path.dirname(os.path.dirname(self.loc.mod_path)),
662
+ f"{head_mod_name}.jac",
663
+ )
664
+ if os.path.exists(potential_path):
665
+ return potential_path
666
+ return None
667
+
410
668
  def normalize(self, deep: bool = False) -> bool:
411
669
  """Normalize module node."""
412
670
  res = True
@@ -485,26 +743,31 @@ class Test(AstSymbolNode, ElementStmt):
485
743
  if isinstance(name, Name)
486
744
  else Name(
487
745
  file_path=name.file_path,
488
- name="NAME",
489
- value=f"test_t{Test.TEST_COUNT}",
746
+ name=Tok.NAME.value,
747
+ value=f"_jac_gen_{Test.TEST_COUNT}",
490
748
  col_start=name.loc.col_start,
491
749
  col_end=name.loc.col_end,
492
750
  line=name.loc.first_line,
751
+ end_line=name.loc.last_line,
493
752
  pos_start=name.pos_start,
494
753
  pos_end=name.pos_end,
495
754
  )
496
755
  )
497
756
  self.name.parent = self
498
- # kid[0] = self.name # Index is 0 since Doc string is inserted after init
757
+ self.name._sym_name = (
758
+ f"test_{self.name.value}"
759
+ if not self.name.value.startswith("test_")
760
+ else self.name.value
761
+ )
499
762
  self.body = body
500
763
  AstNode.__init__(self, kid=kid)
501
764
  if self.name not in self.kid:
502
- self.add_kids_left([self.name], pos_update=False)
765
+ self.insert_kids_at_pos([self.name], pos=1, pos_update=False)
503
766
  AstSymbolNode.__init__(
504
767
  self,
505
768
  sym_name=self.name.sym_name,
506
- sym_name_node=self.name,
507
- sym_type=SymbolType.TEST,
769
+ name_spec=self.name,
770
+ sym_category=SymbolType.TEST,
508
771
  )
509
772
  AstDocNode.__init__(self, doc=doc)
510
773
 
@@ -645,20 +908,22 @@ class ModulePath(AstSymbolNode):
645
908
  level: int,
646
909
  alias: Optional[Name],
647
910
  kid: Sequence[AstNode],
648
- sub_module: Optional[Module] = None,
649
911
  ) -> None:
650
912
  """Initialize module path node."""
651
913
  self.path = path
652
914
  self.level = level
653
915
  self.alias = alias
654
- self.sub_module = sub_module
916
+ self.sub_module: Optional[Module] = None
655
917
 
918
+ name_spec = alias if alias else path[0] if path else None
919
+ if not isinstance(name_spec, Name):
920
+ raise ValueError("ModulePath should have a name spec. Impossible.")
656
921
  AstNode.__init__(self, kid=kid)
657
922
  AstSymbolNode.__init__(
658
923
  self,
659
- sym_name=alias.sym_name if alias else self.path_str,
660
- sym_name_node=alias if alias else self,
661
- sym_type=SymbolType.MODULE,
924
+ sym_name=name_spec.sym_name,
925
+ name_spec=name_spec,
926
+ sym_category=SymbolType.MODULE,
662
927
  )
663
928
 
664
929
  @property
@@ -701,20 +966,37 @@ class ModuleItem(AstSymbolNode):
701
966
  name: Name,
702
967
  alias: Optional[Name],
703
968
  kid: Sequence[AstNode],
704
- sub_module: Optional[Module] = None,
705
969
  ) -> None:
706
970
  """Initialize module item node."""
707
971
  self.name = name
708
972
  self.alias = alias
709
- self.sub_module = sub_module
973
+ self.sub_module: Optional[Module] = None
710
974
  AstNode.__init__(self, kid=kid)
711
975
  AstSymbolNode.__init__(
712
976
  self,
713
977
  sym_name=alias.sym_name if alias else name.sym_name,
714
- sym_name_node=alias if alias else name,
715
- sym_type=SymbolType.MOD_VAR,
978
+ name_spec=alias if alias else name,
979
+ sym_category=SymbolType.MOD_VAR,
716
980
  )
717
981
 
982
+ @property
983
+ def from_parent(self) -> Import:
984
+ """Get import parent."""
985
+ if (
986
+ not self.parent
987
+ or not self.parent.parent
988
+ or not isinstance(self.parent.parent, Import)
989
+ ):
990
+ raise ValueError("Import parent not found. Not Possible.")
991
+ return self.parent.parent
992
+
993
+ @property
994
+ def from_mod_path(self) -> ModulePath:
995
+ """Get relevant module path."""
996
+ if not self.from_parent.from_loc:
997
+ raise ValueError("Module items should have module path. Not Possible.")
998
+ return self.from_parent.from_loc
999
+
718
1000
  def normalize(self, deep: bool = False) -> bool:
719
1001
  """Normalize module item node."""
720
1002
  res = True
@@ -752,8 +1034,8 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt, AstImplNeedingNode):
752
1034
  AstSymbolNode.__init__(
753
1035
  self,
754
1036
  sym_name=name.value,
755
- sym_name_node=name,
756
- sym_type=(
1037
+ name_spec=name,
1038
+ sym_category=(
757
1039
  SymbolType.OBJECT_ARCH
758
1040
  if arch_type.name == Tok.KW_OBJECT
759
1041
  else (
@@ -828,7 +1110,7 @@ class Architype(ArchSpec, AstAccessNode, ArchBlockStmt, AstImplNeedingNode):
828
1110
  return res
829
1111
 
830
1112
 
831
- class ArchDef(ArchSpec, AstImplOnlyNode):
1113
+ class ArchDef(AstImplOnlyNode):
832
1114
  """ArchDef node type for Jac Ast."""
833
1115
 
834
1116
  def __init__(
@@ -841,17 +1123,9 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
841
1123
  decl_link: Optional[Architype] = None,
842
1124
  ) -> None:
843
1125
  """Initialize arch def node."""
844
- self.target = target
845
1126
  AstNode.__init__(self, kid=kid)
846
- AstSymbolNode.__init__(
847
- self,
848
- sym_name=target.py_resolve_name(),
849
- sym_name_node=target,
850
- sym_type=SymbolType.IMPL,
851
- )
852
1127
  AstDocNode.__init__(self, doc=doc)
853
- ArchSpec.__init__(self, decorators=decorators)
854
- AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
1128
+ AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
855
1129
 
856
1130
  def normalize(self, deep: bool = False) -> bool:
857
1131
  """Normalize arch def node."""
@@ -860,7 +1134,6 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
860
1134
  res = self.target.normalize(deep)
861
1135
  res = res and self.body.normalize(deep)
862
1136
  res = res and self.doc.normalize(deep) if self.doc else res
863
- res = res and self.decorators.normalize(deep) if self.decorators else res
864
1137
  new_kid: list[AstNode] = []
865
1138
  if self.doc:
866
1139
  new_kid.append(self.doc)
@@ -891,8 +1164,8 @@ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt):
891
1164
  AstSymbolNode.__init__(
892
1165
  self,
893
1166
  sym_name=name.value,
894
- sym_name_node=name,
895
- sym_type=SymbolType.ENUM_ARCH,
1167
+ name_spec=name,
1168
+ sym_category=SymbolType.ENUM_ARCH,
896
1169
  )
897
1170
  AstImplNeedingNode.__init__(self, body=body)
898
1171
  AstAccessNode.__init__(self, access=access)
@@ -939,7 +1212,7 @@ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt):
939
1212
  return res
940
1213
 
941
1214
 
942
- class EnumDef(ArchSpec, AstImplOnlyNode):
1215
+ class EnumDef(AstImplOnlyNode):
943
1216
  """EnumDef node type for Jac Ast."""
944
1217
 
945
1218
  def __init__(
@@ -952,17 +1225,9 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
952
1225
  decl_link: Optional[Enum] = None,
953
1226
  ) -> None:
954
1227
  """Initialize arch def node."""
955
- self.target = target
956
1228
  AstNode.__init__(self, kid=kid)
957
- AstSymbolNode.__init__(
958
- self,
959
- sym_name=target.py_resolve_name(),
960
- sym_name_node=target,
961
- sym_type=SymbolType.IMPL,
962
- )
963
1229
  AstDocNode.__init__(self, doc=doc)
964
- ArchSpec.__init__(self, decorators=decorators)
965
- AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
1230
+ AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
966
1231
 
967
1232
  def normalize(self, deep: bool = False) -> bool:
968
1233
  """Normalize enum def node."""
@@ -971,7 +1236,6 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
971
1236
  res = self.target.normalize(deep)
972
1237
  res = res and self.body.normalize(deep)
973
1238
  res = res and self.doc.normalize(deep) if self.doc else res
974
- res = res and self.decorators.normalize(deep) if self.decorators else res
975
1239
  new_kid: list[AstNode] = []
976
1240
  if self.doc:
977
1241
  new_kid.append(self.doc)
@@ -988,6 +1252,7 @@ class Ability(
988
1252
  ElementStmt,
989
1253
  AstAsyncNode,
990
1254
  ArchBlockStmt,
1255
+ EnumBlockStmt,
991
1256
  CodeBlockStmt,
992
1257
  AstSemStrNode,
993
1258
  AstImplNeedingNode,
@@ -996,13 +1261,13 @@ class Ability(
996
1261
 
997
1262
  def __init__(
998
1263
  self,
999
- name_ref: NameSpec,
1264
+ name_ref: NameAtom,
1000
1265
  is_async: bool,
1001
1266
  is_override: bool,
1002
1267
  is_static: bool,
1003
1268
  is_abstract: bool,
1004
1269
  access: Optional[SubTag[Token]],
1005
- signature: Optional[FuncSignature | EventSignature],
1270
+ signature: FuncSignature | EventSignature,
1006
1271
  body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef | FuncCall],
1007
1272
  kid: Sequence[AstNode],
1008
1273
  semstr: Optional[String] = None,
@@ -1022,17 +1287,28 @@ class Ability(
1022
1287
  AstSymbolNode.__init__(
1023
1288
  self,
1024
1289
  sym_name=self.py_resolve_name(),
1025
- sym_name_node=name_ref,
1026
- sym_type=SymbolType.ABILITY,
1290
+ name_spec=name_ref,
1291
+ sym_category=SymbolType.ABILITY,
1027
1292
  )
1028
1293
  AstAccessNode.__init__(self, access=access)
1029
1294
  AstDocNode.__init__(self, doc=doc)
1030
1295
  AstAsyncNode.__init__(self, is_async=is_async)
1031
1296
 
1032
1297
  @property
1033
- def is_func(self) -> bool:
1298
+ def is_method(self) -> bool:
1034
1299
  """Check if is func."""
1035
- return isinstance(self.body, FuncSignature)
1300
+ return self.signature.is_method
1301
+
1302
+ @property
1303
+ def owner_method(self) -> Optional[Architype | Enum]:
1304
+ """Check if is owner method."""
1305
+ return (
1306
+ self.parent.parent
1307
+ if self.parent
1308
+ and self.parent.parent
1309
+ and isinstance(self.parent.parent, (Architype, Enum))
1310
+ else None
1311
+ )
1036
1312
 
1037
1313
  @property
1038
1314
  def is_genai_ability(self) -> bool:
@@ -1097,7 +1373,7 @@ class Ability(
1097
1373
  return res
1098
1374
 
1099
1375
 
1100
- class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
1376
+ class AbilityDef(AstImplOnlyNode):
1101
1377
  """AbilityDef node type for Jac Ast."""
1102
1378
 
1103
1379
  def __init__(
@@ -1111,18 +1387,11 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
1111
1387
  decl_link: Optional[Ability] = None,
1112
1388
  ) -> None:
1113
1389
  """Initialize ability def node."""
1114
- self.target = target
1115
1390
  self.signature = signature
1116
1391
  self.decorators = decorators
1117
1392
  AstNode.__init__(self, kid=kid)
1118
- AstSymbolNode.__init__(
1119
- self,
1120
- sym_name=target.py_resolve_name(),
1121
- sym_name_node=target,
1122
- sym_type=SymbolType.IMPL,
1123
- )
1124
1393
  AstDocNode.__init__(self, doc=doc)
1125
- AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
1394
+ AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
1126
1395
 
1127
1396
  def normalize(self, deep: bool = False) -> bool:
1128
1397
  """Normalize ability def node."""
@@ -1158,6 +1427,7 @@ class FuncSignature(AstSemStrNode):
1158
1427
  """Initialize method signature node."""
1159
1428
  self.params = params
1160
1429
  self.return_type = return_type
1430
+ self.is_method = False
1161
1431
  AstNode.__init__(self, kid=kid)
1162
1432
  AstSemStrNode.__init__(self, semstr=semstr)
1163
1433
 
@@ -1206,6 +1476,7 @@ class EventSignature(AstSemStrNode):
1206
1476
  self.event = event
1207
1477
  self.arch_tag_info = arch_tag_info
1208
1478
  self.return_type = return_type
1479
+ self.is_method = False
1209
1480
  AstNode.__init__(self, kid=kid)
1210
1481
  AstSemStrNode.__init__(self, semstr=semstr)
1211
1482
 
@@ -1264,11 +1535,11 @@ class ArchRefChain(AstNode):
1264
1535
  def get_tag(x: ArchRef) -> str:
1265
1536
  return (
1266
1537
  "en"
1267
- if x.arch.value == "enum"
1268
- else "cls" if x.arch.value == "class" else x.arch.value[1]
1538
+ if x.arch_type.value == "enum"
1539
+ else "cls" if x.arch_type.value == "class" else x.arch_type.value[1]
1269
1540
  )
1270
1541
 
1271
- return ".".join([f"({get_tag(x)}){x.py_resolve_name()}" for x in self.archs])
1542
+ return ".".join([f"({get_tag(x)}){x.sym_name}" for x in self.archs])
1272
1543
 
1273
1544
  def flat_name(self) -> str:
1274
1545
  """Resolve name for python gen."""
@@ -1297,8 +1568,8 @@ class ParamVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
1297
1568
  AstSymbolNode.__init__(
1298
1569
  self,
1299
1570
  sym_name=name.value,
1300
- sym_name_node=name,
1301
- sym_type=SymbolType.VAR,
1571
+ name_spec=name,
1572
+ sym_category=SymbolType.VAR,
1302
1573
  )
1303
1574
  AstTypedVarNode.__init__(self, type_tag=type_tag)
1304
1575
  AstSemStrNode.__init__(self, semstr=semstr)
@@ -1393,8 +1664,8 @@ class HasVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
1393
1664
  AstSymbolNode.__init__(
1394
1665
  self,
1395
1666
  sym_name=name.value,
1396
- sym_name_node=name,
1397
- sym_type=SymbolType.VAR,
1667
+ name_spec=name,
1668
+ sym_category=SymbolType.HAS_VAR,
1398
1669
  )
1399
1670
  AstTypedVarNode.__init__(self, type_tag=type_tag)
1400
1671
  AstSemStrNode.__init__(self, semstr=semstr)
@@ -1909,6 +2180,32 @@ class AssertStmt(CodeBlockStmt):
1909
2180
  return res
1910
2181
 
1911
2182
 
2183
+ class CheckStmt(CodeBlockStmt):
2184
+ """DeleteStmt node type for Jac Ast."""
2185
+
2186
+ def __init__(
2187
+ self,
2188
+ target: Expr,
2189
+ kid: Sequence[AstNode],
2190
+ ) -> None:
2191
+ """Initialize delete statement node."""
2192
+ self.target = target
2193
+ AstNode.__init__(self, kid=kid)
2194
+
2195
+ def normalize(self, deep: bool = False) -> bool:
2196
+ """Normalize delete statement node."""
2197
+ res = True
2198
+ if deep:
2199
+ res = self.target.normalize(deep)
2200
+ new_kid: list[AstNode] = [
2201
+ self.gen_token(Tok.KW_CHECK),
2202
+ self.target,
2203
+ self.gen_token(Tok.SEMI),
2204
+ ]
2205
+ self.set_kids(nodes=new_kid)
2206
+ return res
2207
+
2208
+
1912
2209
  class CtrlStmt(CodeBlockStmt):
1913
2210
  """CtrlStmt node type for Jac Ast."""
1914
2211
 
@@ -2158,7 +2455,7 @@ class GlobalStmt(CodeBlockStmt):
2158
2455
 
2159
2456
  def __init__(
2160
2457
  self,
2161
- target: SubNodeList[NameSpec],
2458
+ target: SubNodeList[NameAtom],
2162
2459
  kid: Sequence[AstNode],
2163
2460
  ) -> None:
2164
2461
  """Initialize global statement node."""
@@ -2451,12 +2748,7 @@ class MultiString(AtomExpr):
2451
2748
  """Initialize multi string expression node."""
2452
2749
  self.strings = strings
2453
2750
  AstNode.__init__(self, kid=kid)
2454
- AstSymbolNode.__init__(
2455
- self,
2456
- sym_name=f"[{self.__class__.__name__}]",
2457
- sym_name_node=self,
2458
- sym_type=SymbolType.STRING,
2459
- )
2751
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.STRING)
2460
2752
 
2461
2753
  def normalize(self, deep: bool = False) -> bool:
2462
2754
  """Normalize ast node."""
@@ -2482,12 +2774,7 @@ class FString(AtomExpr):
2482
2774
  """Initialize fstring expression node."""
2483
2775
  self.parts = parts
2484
2776
  AstNode.__init__(self, kid=kid)
2485
- AstSymbolNode.__init__(
2486
- self,
2487
- sym_name=f"[{self.__class__.__name__}]",
2488
- sym_name_node=self,
2489
- sym_type=SymbolType.STRING,
2490
- )
2777
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.STRING)
2491
2778
 
2492
2779
  def normalize(self, deep: bool = False) -> bool:
2493
2780
  """Normalize ast node."""
@@ -2517,12 +2804,7 @@ class ListVal(AtomExpr):
2517
2804
  """Initialize value node."""
2518
2805
  self.values = values
2519
2806
  AstNode.__init__(self, kid=kid)
2520
- AstSymbolNode.__init__(
2521
- self,
2522
- sym_name=f"[{self.__class__.__name__}]",
2523
- sym_name_node=self,
2524
- sym_type=SymbolType.SEQUENCE,
2525
- )
2807
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2526
2808
 
2527
2809
  def normalize(self, deep: bool = False) -> bool:
2528
2810
  """Normalize ast node."""
@@ -2550,12 +2832,7 @@ class SetVal(AtomExpr):
2550
2832
  """Initialize value node."""
2551
2833
  self.values = values
2552
2834
  AstNode.__init__(self, kid=kid)
2553
- AstSymbolNode.__init__(
2554
- self,
2555
- sym_name=f"[{self.__class__.__name__}]",
2556
- sym_name_node=self,
2557
- sym_type=SymbolType.SEQUENCE,
2558
- )
2835
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2559
2836
 
2560
2837
  def normalize(self, deep: bool = False) -> bool:
2561
2838
  """Normalize ast node."""
@@ -2583,12 +2860,7 @@ class TupleVal(AtomExpr):
2583
2860
  """Initialize tuple value node."""
2584
2861
  self.values = values
2585
2862
  AstNode.__init__(self, kid=kid)
2586
- AstSymbolNode.__init__(
2587
- self,
2588
- sym_name=f"[{self.__class__.__name__}]",
2589
- sym_name_node=self,
2590
- sym_type=SymbolType.SEQUENCE,
2591
- )
2863
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2592
2864
 
2593
2865
  def normalize(self, deep: bool = False) -> bool:
2594
2866
  """Normalize ast node."""
@@ -2631,12 +2903,7 @@ class DictVal(AtomExpr):
2631
2903
  """Initialize dict expression node."""
2632
2904
  self.kv_pairs = kv_pairs
2633
2905
  AstNode.__init__(self, kid=kid)
2634
- AstSymbolNode.__init__(
2635
- self,
2636
- sym_name=f"[{self.__class__.__name__}]",
2637
- sym_name_node=self,
2638
- sym_type=SymbolType.SEQUENCE,
2639
- )
2906
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2640
2907
 
2641
2908
  def normalize(self, deep: bool = False) -> bool:
2642
2909
  """Normalize ast node."""
@@ -2692,7 +2959,7 @@ class KWPair(AstNode):
2692
2959
 
2693
2960
  def __init__(
2694
2961
  self,
2695
- key: Optional[NameSpec], # is **value if blank
2962
+ key: Optional[NameAtom], # is **value if blank
2696
2963
  value: Expr,
2697
2964
  kid: Sequence[AstNode],
2698
2965
  ) -> None:
@@ -2769,12 +3036,7 @@ class ListCompr(AtomExpr):
2769
3036
  self.out_expr = out_expr
2770
3037
  self.compr = compr
2771
3038
  AstNode.__init__(self, kid=kid)
2772
- AstSymbolNode.__init__(
2773
- self,
2774
- sym_name=f"[{self.__class__.__name__}]",
2775
- sym_name_node=self,
2776
- sym_type=SymbolType.SEQUENCE,
2777
- )
3039
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2778
3040
 
2779
3041
  def normalize(self, deep: bool = False) -> bool:
2780
3042
  """Normalize ast node."""
@@ -2849,12 +3111,7 @@ class DictCompr(AtomExpr):
2849
3111
  self.kv_pair = kv_pair
2850
3112
  self.compr = compr
2851
3113
  AstNode.__init__(self, kid=kid)
2852
- AstSymbolNode.__init__(
2853
- self,
2854
- sym_name=f"[{self.__class__.__name__}]",
2855
- sym_name_node=self,
2856
- sym_type=SymbolType.SEQUENCE,
2857
- )
3114
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2858
3115
 
2859
3116
  def normalize(self, deep: bool = False) -> bool:
2860
3117
  """Normalize ast node."""
@@ -2909,6 +3166,22 @@ class AtomTrailer(Expr):
2909
3166
  self.set_kids(nodes=new_kid)
2910
3167
  return res
2911
3168
 
3169
+ @property
3170
+ def as_attr_list(self) -> list[AstSymbolNode]:
3171
+ """Unwind trailer into list of ast symbol nodes."""
3172
+ left = self.right if isinstance(self.right, AtomTrailer) else self.target
3173
+ right = self.target if isinstance(self.right, AtomTrailer) else self.right
3174
+ trag_list: list[AstSymbolNode] = (
3175
+ [right] if isinstance(right, AstSymbolNode) else []
3176
+ )
3177
+ while isinstance(left, AtomTrailer) and left.is_attr:
3178
+ if isinstance(left.right, AstSymbolNode):
3179
+ trag_list.insert(0, left.right)
3180
+ left = left.target
3181
+ if isinstance(left, AstSymbolNode):
3182
+ trag_list.insert(0, left)
3183
+ return trag_list
3184
+
2912
3185
 
2913
3186
  class AtomUnit(Expr):
2914
3187
  """AtomUnit node type for Jac Ast."""
@@ -3013,12 +3286,7 @@ class IndexSlice(AtomExpr):
3013
3286
  self.step = step
3014
3287
  self.is_range = is_range
3015
3288
  AstNode.__init__(self, kid=kid)
3016
- AstSymbolNode.__init__(
3017
- self,
3018
- sym_name=f"[{self.__class__.__name__}]",
3019
- sym_type=SymbolType.SEQUENCE,
3020
- sym_name_node=self,
3021
- )
3289
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3022
3290
 
3023
3291
  def normalize(self, deep: bool = True) -> bool:
3024
3292
  """Normalize ast node."""
@@ -3047,89 +3315,35 @@ class IndexSlice(AtomExpr):
3047
3315
  return res
3048
3316
 
3049
3317
 
3050
- class ArchRef(NameSpec):
3318
+ class ArchRef(AtomExpr):
3051
3319
  """ArchRef node type for Jac Ast."""
3052
3320
 
3053
3321
  def __init__(
3054
3322
  self,
3055
- name_ref: NameSpec,
3056
- arch: Token,
3323
+ arch_name: NameAtom,
3324
+ arch_type: Token,
3057
3325
  kid: Sequence[AstNode],
3058
3326
  ) -> None:
3059
3327
  """Initialize architype reference expression node."""
3060
- self.name_ref = name_ref
3061
- self.arch = arch
3062
- AstNode.__init__(self, kid=kid)
3063
- AstSymbolNode.__init__(
3064
- self,
3065
- sym_name=self.py_resolve_name(),
3066
- sym_name_node=name_ref,
3067
- sym_type=SymbolType.TYPE,
3068
- )
3069
-
3070
- def normalize(self, deep: bool = False) -> bool:
3071
- """Normalize ast node."""
3072
- res = True
3073
- if deep:
3074
- res = self.name_ref.normalize(deep)
3075
- new_kid: list[AstNode] = [self.arch, self.name_ref]
3076
- self.set_kids(nodes=new_kid)
3077
- return res
3078
-
3079
- def py_resolve_name(self) -> str:
3080
- """Resolve name."""
3081
- if isinstance(self.name_ref, Name):
3082
- return self.name_ref.value
3083
- elif isinstance(self.name_ref, SpecialVarRef):
3084
- return self.name_ref.py_resolve_name()
3085
- else:
3086
- raise NotImplementedError
3087
-
3088
-
3089
- class SpecialVarRef(NameSpec):
3090
- """HereRef node type for Jac Ast."""
3091
-
3092
- def __init__(
3093
- self,
3094
- var: Token,
3095
- kid: Sequence[AstNode],
3096
- ) -> None:
3097
- """Initialize special var reference expression node."""
3098
- self.var = var
3328
+ self.arch_name = arch_name
3329
+ self.arch_type = arch_type
3099
3330
  AstNode.__init__(self, kid=kid)
3100
3331
  AstSymbolNode.__init__(
3101
3332
  self,
3102
- sym_name=self.py_resolve_name(),
3103
- sym_name_node=var,
3104
- sym_type=SymbolType.VAR,
3333
+ sym_name=arch_name.sym_name,
3334
+ name_spec=arch_name,
3335
+ sym_category=SymbolType.TYPE,
3105
3336
  )
3106
3337
 
3107
3338
  def normalize(self, deep: bool = False) -> bool:
3108
3339
  """Normalize ast node."""
3109
3340
  res = True
3110
3341
  if deep:
3111
- res = self.var.normalize(deep)
3112
- new_kid: list[AstNode] = [self.var]
3342
+ res = self.arch_name.normalize(deep)
3343
+ new_kid: list[AstNode] = [self.arch_type, self.arch_name]
3113
3344
  self.set_kids(nodes=new_kid)
3114
3345
  return res
3115
3346
 
3116
- def py_resolve_name(self) -> str:
3117
- """Resolve name."""
3118
- if self.var.name == Tok.KW_SELF:
3119
- return "self"
3120
- elif self.var.name == Tok.KW_SUPER:
3121
- return "super()"
3122
- elif self.var.name == Tok.KW_ROOT:
3123
- return Con.ROOT.value
3124
- elif self.var.name == Tok.KW_HERE:
3125
- return Con.HERE.value
3126
- elif self.var.name == Tok.KW_INIT:
3127
- return "__init__"
3128
- elif self.var.name == Tok.KW_POST_INIT:
3129
- return "__post_init__"
3130
- else:
3131
- raise NotImplementedError("ICE: Special var reference not implemented")
3132
-
3133
3347
 
3134
3348
  class EdgeRefTrailer(Expr):
3135
3349
  """EdgeRefTrailer node type for Jac Ast."""
@@ -3174,12 +3388,7 @@ class EdgeOpRef(WalkerStmtOnlyNode, AtomExpr):
3174
3388
  self.edge_dir = edge_dir
3175
3389
  AstNode.__init__(self, kid=kid)
3176
3390
  WalkerStmtOnlyNode.__init__(self)
3177
- AstSymbolNode.__init__(
3178
- self,
3179
- sym_name=f"[{self.__class__.__name__}]",
3180
- sym_name_node=self,
3181
- sym_type=SymbolType.SEQUENCE,
3182
- )
3391
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3183
3392
 
3184
3393
  def normalize(self, deep: bool = False) -> bool:
3185
3394
  """Normalize ast node."""
@@ -3308,12 +3517,7 @@ class FilterCompr(AtomExpr):
3308
3517
  self.f_type = f_type
3309
3518
  self.compares = compares
3310
3519
  AstNode.__init__(self, kid=kid)
3311
- AstSymbolNode.__init__(
3312
- self,
3313
- sym_name=f"[{self.__class__.__name__}]",
3314
- sym_name_node=self,
3315
- sym_type=SymbolType.SEQUENCE,
3316
- )
3520
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3317
3521
 
3318
3522
  def normalize(self, deep: bool = False) -> bool:
3319
3523
  """Normalize ast node."""
@@ -3350,12 +3554,7 @@ class AssignCompr(AtomExpr):
3350
3554
  """Initialize assign compr expression node."""
3351
3555
  self.assigns = assigns
3352
3556
  AstNode.__init__(self, kid=kid)
3353
- AstSymbolNode.__init__(
3354
- self,
3355
- sym_name=f"[{self.__class__.__name__}]",
3356
- sym_name_node=self,
3357
- sym_type=SymbolType.SEQUENCE,
3358
- )
3557
+ AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3359
3558
 
3360
3559
  def normalize(self, deep: bool = False) -> bool:
3361
3560
  """Normalize ast node."""
@@ -3479,7 +3678,7 @@ class MatchAs(MatchPattern):
3479
3678
 
3480
3679
  def __init__(
3481
3680
  self,
3482
- name: NameSpec,
3681
+ name: NameAtom,
3483
3682
  pattern: Optional[MatchPattern],
3484
3683
  kid: Sequence[AstNode],
3485
3684
  ) -> None:
@@ -3518,6 +3717,7 @@ class MatchWild(MatchPattern):
3518
3717
  col_start=self.loc.col_start,
3519
3718
  col_end=self.loc.col_end,
3520
3719
  line=self.loc.first_line,
3720
+ end_line=self.loc.last_line,
3521
3721
  pos_start=self.loc.pos_start,
3522
3722
  pos_end=self.loc.pos_end,
3523
3723
  )
@@ -3627,7 +3827,7 @@ class MatchKVPair(MatchPattern):
3627
3827
 
3628
3828
  def __init__(
3629
3829
  self,
3630
- key: MatchPattern | NameSpec,
3830
+ key: MatchPattern | NameAtom,
3631
3831
  value: MatchPattern,
3632
3832
  kid: Sequence[AstNode],
3633
3833
  ) -> None:
@@ -3655,7 +3855,7 @@ class MatchStar(MatchPattern):
3655
3855
 
3656
3856
  def __init__(
3657
3857
  self,
3658
- name: NameSpec,
3858
+ name: NameAtom,
3659
3859
  is_list: bool,
3660
3860
  kid: Sequence[AstNode],
3661
3861
  ) -> None:
@@ -3682,7 +3882,7 @@ class MatchArch(MatchPattern):
3682
3882
 
3683
3883
  def __init__(
3684
3884
  self,
3685
- name: AtomTrailer | NameSpec,
3885
+ name: AtomTrailer | NameAtom,
3686
3886
  arg_patterns: Optional[SubNodeList[MatchPattern]],
3687
3887
  kw_patterns: Optional[SubNodeList[MatchKVPair]],
3688
3888
  kid: Sequence[AstNode],
@@ -3725,6 +3925,7 @@ class Token(AstNode):
3725
3925
  name: str,
3726
3926
  value: str,
3727
3927
  line: int,
3928
+ end_line: int,
3728
3929
  col_start: int,
3729
3930
  col_end: int,
3730
3931
  pos_start: int,
@@ -3735,6 +3936,7 @@ class Token(AstNode):
3735
3936
  self.name = name
3736
3937
  self.value = value
3737
3938
  self.line_no = line
3939
+ self.end_line = end_line
3738
3940
  self.c_start = col_start
3739
3941
  self.c_end = col_end
3740
3942
  self.pos_start = pos_start
@@ -3750,7 +3952,7 @@ class Token(AstNode):
3750
3952
  return self.value
3751
3953
 
3752
3954
 
3753
- class Name(Token, NameSpec):
3955
+ class Name(Token, NameAtom):
3754
3956
  """Name node type for Jac Ast."""
3755
3957
 
3756
3958
  def __init__(
@@ -3759,6 +3961,7 @@ class Name(Token, NameSpec):
3759
3961
  name: str,
3760
3962
  value: str,
3761
3963
  line: int,
3964
+ end_line: int,
3762
3965
  col_start: int,
3763
3966
  col_end: int,
3764
3967
  pos_start: int,
@@ -3775,16 +3978,18 @@ class Name(Token, NameSpec):
3775
3978
  name=name,
3776
3979
  value=value,
3777
3980
  line=line,
3981
+ end_line=end_line,
3778
3982
  col_start=col_start,
3779
3983
  col_end=col_end,
3780
3984
  pos_start=pos_start,
3781
3985
  pos_end=pos_end,
3782
3986
  )
3987
+ NameAtom.__init__(self)
3783
3988
  AstSymbolNode.__init__(
3784
3989
  self,
3785
3990
  sym_name=value,
3786
- sym_name_node=self,
3787
- sym_type=SymbolType.VAR,
3991
+ name_spec=self,
3992
+ sym_category=SymbolType.VAR,
3788
3993
  )
3789
3994
 
3790
3995
  def unparse(self) -> str:
@@ -3794,6 +3999,74 @@ class Name(Token, NameSpec):
3794
3999
  ",\n" if self.is_enum_singleton else ""
3795
4000
  )
3796
4001
 
4002
+ @staticmethod
4003
+ def gen_stub_from_node(
4004
+ node: AstSymbolNode, name_str: str, set_name_of: Optional[AstSymbolNode] = None
4005
+ ) -> Name:
4006
+ """Generate name from node."""
4007
+ ret = Name(
4008
+ file_path=node.loc.mod_path,
4009
+ name=Tok.NAME.value,
4010
+ value=name_str,
4011
+ col_start=node.loc.col_start,
4012
+ col_end=node.loc.col_end,
4013
+ line=node.loc.first_line,
4014
+ end_line=node.loc.last_line,
4015
+ pos_start=node.loc.pos_start,
4016
+ pos_end=node.loc.pos_end,
4017
+ )
4018
+ ret.name_of = set_name_of if set_name_of else ret
4019
+ if node._sym_tab:
4020
+ ret.sym_tab = node.sym_tab
4021
+ return ret
4022
+
4023
+
4024
+ class SpecialVarRef(Name):
4025
+ """HereRef node type for Jac Ast."""
4026
+
4027
+ def __init__(
4028
+ self,
4029
+ var: Name,
4030
+ ) -> None:
4031
+ """Initialize special var reference expression node."""
4032
+ self.orig = var
4033
+ Name.__init__(
4034
+ self,
4035
+ file_path=var.file_path,
4036
+ name=var.name,
4037
+ value=self.py_resolve_name(), # TODO: This shouldnt be necessary
4038
+ line=var.line_no,
4039
+ end_line=var.end_line,
4040
+ col_start=var.c_start,
4041
+ col_end=var.c_end,
4042
+ pos_start=var.pos_start,
4043
+ pos_end=var.pos_end,
4044
+ )
4045
+ NameAtom.__init__(self)
4046
+ AstSymbolNode.__init__(
4047
+ self,
4048
+ sym_name=self.py_resolve_name(),
4049
+ name_spec=self,
4050
+ sym_category=SymbolType.VAR,
4051
+ )
4052
+
4053
+ def py_resolve_name(self) -> str:
4054
+ """Resolve name."""
4055
+ if self.orig.name == Tok.KW_SELF:
4056
+ return "self"
4057
+ elif self.orig.name == Tok.KW_SUPER:
4058
+ return "super"
4059
+ elif self.orig.name == Tok.KW_ROOT:
4060
+ return Con.ROOT.value
4061
+ elif self.orig.name == Tok.KW_HERE:
4062
+ return Con.HERE.value
4063
+ elif self.orig.name == Tok.KW_INIT:
4064
+ return "__init__"
4065
+ elif self.orig.name == Tok.KW_POST_INIT:
4066
+ return "__post_init__"
4067
+ else:
4068
+ raise NotImplementedError("ICE: Special var reference not implemented")
4069
+
3797
4070
 
3798
4071
  class Literal(Token, AtomExpr):
3799
4072
  """Literal node type for Jac Ast."""
@@ -3819,6 +4092,7 @@ class Literal(Token, AtomExpr):
3819
4092
  name: str,
3820
4093
  value: str,
3821
4094
  line: int,
4095
+ end_line: int,
3822
4096
  col_start: int,
3823
4097
  col_end: int,
3824
4098
  pos_start: int,
@@ -3831,17 +4105,13 @@ class Literal(Token, AtomExpr):
3831
4105
  name=name,
3832
4106
  value=value,
3833
4107
  line=line,
4108
+ end_line=end_line,
3834
4109
  col_start=col_start,
3835
4110
  col_end=col_end,
3836
4111
  pos_start=pos_start,
3837
4112
  pos_end=pos_end,
3838
4113
  )
3839
- AstSymbolNode.__init__(
3840
- self,
3841
- sym_name=f"[{self.__class__.__name__}]",
3842
- sym_name_node=self,
3843
- sym_type=self.SYMBOL_TYPE,
3844
- )
4114
+ AstSymbolStubNode.__init__(self, sym_type=self.SYMBOL_TYPE)
3845
4115
 
3846
4116
  @property
3847
4117
  def lit_value(
@@ -3851,43 +4121,7 @@ class Literal(Token, AtomExpr):
3851
4121
  raise NotImplementedError
3852
4122
 
3853
4123
 
3854
- class TokenSymbol(Token, AstSymbolNode):
3855
- """TokenSymbol node type for Jac Ast."""
3856
-
3857
- SYMBOL_TYPE = SymbolType.VAR
3858
-
3859
- def __init__(
3860
- self,
3861
- file_path: str,
3862
- name: str,
3863
- value: str,
3864
- line: int,
3865
- col_start: int,
3866
- col_end: int,
3867
- pos_start: int,
3868
- pos_end: int,
3869
- ) -> None:
3870
- """Initialize token."""
3871
- Token.__init__(
3872
- self,
3873
- file_path=file_path,
3874
- name=name,
3875
- value=value,
3876
- line=line,
3877
- col_start=col_start,
3878
- col_end=col_end,
3879
- pos_start=pos_start,
3880
- pos_end=pos_end,
3881
- )
3882
- AstSymbolNode.__init__(
3883
- self,
3884
- sym_name=f"[{self.__class__.__name__}]",
3885
- sym_name_node=self,
3886
- sym_type=self.SYMBOL_TYPE,
3887
- )
3888
-
3889
-
3890
- class BuiltinType(Name, Literal, NameSpec):
4124
+ class BuiltinType(Name, Literal, NameAtom):
3891
4125
  """Type node type for Jac Ast."""
3892
4126
 
3893
4127
  SYMBOL_TYPE = SymbolType.VAR
@@ -4000,6 +4234,7 @@ class EmptyToken(Token):
4000
4234
  file_path="",
4001
4235
  value="",
4002
4236
  line=0,
4237
+ end_line=0,
4003
4238
  col_start=0,
4004
4239
  col_end=0,
4005
4240
  pos_start=0,
@@ -4020,6 +4255,7 @@ class CommentToken(Token):
4020
4255
  name: str,
4021
4256
  value: str,
4022
4257
  line: int,
4258
+ end_line: int,
4023
4259
  col_start: int,
4024
4260
  col_end: int,
4025
4261
  pos_start: int,
@@ -4028,15 +4264,21 @@ class CommentToken(Token):
4028
4264
  is_inline: bool = False,
4029
4265
  ) -> None:
4030
4266
  """Initialize token."""
4031
- self.file_path = file_path
4032
- self.name = name
4033
- self.value = value
4034
- self.line_no = line
4035
- self.c_start = col_start
4036
- self.c_end = col_end
4037
- self.pos_start = pos_start
4038
- self.pos_end = pos_end
4039
4267
  self.is_inline = is_inline
4268
+
4269
+ Token.__init__(
4270
+ self,
4271
+ file_path=file_path,
4272
+ name=name,
4273
+ value=value,
4274
+ line=line,
4275
+ end_line=end_line,
4276
+ col_start=col_start,
4277
+ col_end=col_end,
4278
+ pos_start=pos_start,
4279
+ pos_end=pos_end,
4280
+ )
4281
+
4040
4282
  AstNode.__init__(self, kid=kid)
4041
4283
 
4042
4284