jaclang 0.7.0__py3-none-any.whl → 0.7.2__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 (62) hide show
  1. jaclang/compiler/absyntree.py +53 -50
  2. jaclang/compiler/compile.py +21 -0
  3. jaclang/compiler/passes/main/__init__.py +2 -2
  4. jaclang/compiler/passes/main/def_impl_match_pass.py +10 -8
  5. jaclang/compiler/passes/main/def_use_pass.py +14 -7
  6. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +20 -1
  7. jaclang/compiler/passes/main/import_pass.py +60 -11
  8. jaclang/compiler/passes/main/pyast_gen_pass.py +65 -4
  9. jaclang/compiler/passes/main/pyast_load_pass.py +2 -1
  10. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +6 -1
  11. jaclang/compiler/passes/main/pyout_pass.py +3 -1
  12. jaclang/compiler/passes/main/schedules.py +4 -3
  13. jaclang/compiler/passes/main/tests/fixtures/incautoimpl.jac +7 -0
  14. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +4 -4
  15. jaclang/compiler/passes/main/tests/test_import_pass.py +21 -0
  16. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  17. jaclang/compiler/passes/tool/jac_formatter_pass.py +14 -2
  18. jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
  19. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
  20. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
  21. jaclang/compiler/symtable.py +21 -1
  22. jaclang/core/aott.py +107 -11
  23. jaclang/core/construct.py +171 -5
  24. jaclang/core/llms/anthropic.py +31 -2
  25. jaclang/core/llms/base.py +3 -3
  26. jaclang/core/llms/groq.py +4 -1
  27. jaclang/core/llms/huggingface.py +4 -1
  28. jaclang/core/llms/ollama.py +4 -1
  29. jaclang/core/llms/openai.py +6 -2
  30. jaclang/core/llms/togetherai.py +4 -1
  31. jaclang/langserve/engine.py +193 -121
  32. jaclang/langserve/server.py +35 -6
  33. jaclang/langserve/tests/fixtures/circle.jac +73 -0
  34. jaclang/langserve/tests/fixtures/circle_err.jac +73 -0
  35. jaclang/langserve/tests/fixtures/circle_pure.impl.jac +32 -0
  36. jaclang/langserve/tests/fixtures/circle_pure.jac +34 -0
  37. jaclang/langserve/tests/fixtures/circle_pure_err.impl.jac +32 -0
  38. jaclang/langserve/tests/fixtures/circle_pure_err.jac +34 -0
  39. jaclang/langserve/tests/test_server.py +156 -1
  40. jaclang/langserve/utils.py +127 -2
  41. jaclang/plugin/default.py +25 -83
  42. jaclang/plugin/feature.py +10 -12
  43. jaclang/plugin/tests/test_features.py +0 -33
  44. jaclang/settings.py +1 -0
  45. jaclang/tests/fixtures/byllmissue.jac +3 -0
  46. jaclang/tests/fixtures/hash_init_check.jac +17 -0
  47. jaclang/tests/fixtures/math_question.jpg +0 -0
  48. jaclang/tests/fixtures/nosigself.jac +19 -0
  49. jaclang/tests/fixtures/type_info.jac +1 -1
  50. jaclang/tests/fixtures/walker_override.jac +21 -0
  51. jaclang/tests/fixtures/with_llm_vision.jac +25 -0
  52. jaclang/tests/test_cli.py +1 -1
  53. jaclang/tests/test_language.py +61 -11
  54. jaclang/utils/helpers.py +3 -5
  55. jaclang/utils/test.py +1 -1
  56. jaclang/utils/treeprinter.py +19 -2
  57. {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/METADATA +3 -2
  58. {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/RECORD +60 -48
  59. jaclang/core/memory.py +0 -48
  60. jaclang/core/shelve_storage.py +0 -55
  61. {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/WHEEL +0 -0
  62. {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/entry_points.txt +0 -0
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import ast as ast3
6
+ import os
6
7
  from hashlib import md5
7
8
  from types import EllipsisType
8
9
  from typing import Any, Callable, Generic, Optional, Sequence, Type, TypeVar
@@ -31,7 +32,6 @@ class AstNode:
31
32
  self.kid: list[AstNode] = [x.set_parent(self) for x in kid]
32
33
  self.sym_tab: Optional[SymbolTable] = None
33
34
  self._sub_node_tab: dict[type, list[AstNode]] = {}
34
- self._typ: type = type(None)
35
35
  self.gen: CodeGenTarget = CodeGenTarget()
36
36
  self.meta: dict[str, str] = {}
37
37
  self.loc: CodeLocInfo = CodeLocInfo(*self.resolve_tok_range())
@@ -111,11 +111,15 @@ class AstNode:
111
111
 
112
112
  return Pass.get_all_sub_nodes(node=self, typ=typ, brute_force=brute_force)
113
113
 
114
- def parent_of_type(self, typ: Type[T]) -> T:
114
+ def find_parent_of_type(self, typ: Type[T]) -> Optional[T]:
115
115
  """Get parent of type."""
116
116
  from jaclang.compiler.passes import Pass
117
117
 
118
- ret = Pass.has_parent_of_type(node=self, typ=typ)
118
+ return Pass.has_parent_of_type(node=self, typ=typ)
119
+
120
+ def parent_of_type(self, typ: Type[T]) -> T:
121
+ """Get parent of type."""
122
+ ret = self.find_parent_of_type(typ)
119
123
  if isinstance(ret, typ):
120
124
  return ret
121
125
  else:
@@ -178,6 +182,8 @@ class AstSymbolNode(AstNode):
178
182
  self.sym_link: Optional[Symbol] = None
179
183
  self.sym_name: str = sym_name
180
184
  self.sym_name_node = sym_name_node
185
+ if isinstance(self.sym_name_node, NameSpec):
186
+ self.sym_name_node.name_of = self
181
187
  self.sym_type: SymbolType = sym_type
182
188
  self.sym_info: SymbolInfo = SymbolInfo()
183
189
  self.py_ctx_func: Type[ast3.AST] = ast3.Load
@@ -258,8 +264,11 @@ class WalkerStmtOnlyNode(AstNode):
258
264
  class AstImplOnlyNode(AstNode):
259
265
  """ImplOnly node type for Jac Ast."""
260
266
 
261
- def __init__(self, body: SubNodeList, decl_link: Optional[AstNode]) -> None:
267
+ def __init__(
268
+ self, target: ArchRefChain, body: SubNodeList, decl_link: Optional[AstNode]
269
+ ) -> None:
262
270
  """Initialize impl only node."""
271
+ self.target = target
263
272
  self.body = body
264
273
  self.decl_link = decl_link
265
274
 
@@ -304,6 +313,10 @@ class CodeBlockStmt(AstNode):
304
313
  class NameSpec(AtomExpr, EnumBlockStmt):
305
314
  """NameSpec node type for Jac Ast."""
306
315
 
316
+ def __init__(self) -> None:
317
+ """Initialize name spec node."""
318
+ self.name_of: AstSymbolNode = self
319
+
307
320
 
308
321
  class ArchSpec(ElementStmt, CodeBlockStmt, AstSymbolNode, AstDocNode, AstSemStrNode):
309
322
  """ArchSpec node type for Jac Ast."""
@@ -392,7 +405,7 @@ class Module(AstDocNode):
392
405
  body: Sequence[ElementStmt | String | EmptyToken],
393
406
  is_imported: bool,
394
407
  kid: Sequence[AstNode],
395
- test_mod: Optional[Module] = None,
408
+ stub_only: bool = False,
396
409
  registry: Optional[SemRegistry] = None,
397
410
  ) -> None:
398
411
  """Initialize whole program node."""
@@ -400,13 +413,37 @@ class Module(AstDocNode):
400
413
  self.source = source
401
414
  self.body = body
402
415
  self.is_imported = is_imported
416
+ self.stub_only = stub_only
403
417
  self.impl_mod: list[Module] = []
404
- self.test_mod = test_mod
418
+ self.test_mod: list[Module] = []
405
419
  self.mod_deps: dict[str, Module] = {}
406
420
  self.registry = registry
407
421
  AstNode.__init__(self, kid=kid)
408
422
  AstDocNode.__init__(self, doc=doc)
409
423
 
424
+ @property
425
+ def annexable_by(self) -> Optional[str]:
426
+ """Get annexable by."""
427
+ if not self.stub_only and self.loc.mod_path.endswith("impl.jac"):
428
+ head_mod_name = self.name.split(".")[0]
429
+ potential_path = os.path.join(
430
+ os.path.dirname(self.loc.mod_path),
431
+ f"{head_mod_name}.jac",
432
+ )
433
+ if os.path.exists(potential_path):
434
+ return potential_path
435
+ if os.path.split(os.path.dirname(self.loc.mod_path))[-1].endswith(".impl"):
436
+ head_mod_name = os.path.split(os.path.dirname(self.loc.mod_path))[
437
+ -1
438
+ ].split(".")[0]
439
+ potential_path = os.path.join(
440
+ os.path.dirname(os.path.dirname(self.loc.mod_path)),
441
+ f"{head_mod_name}.jac",
442
+ )
443
+ if os.path.exists(potential_path):
444
+ return potential_path
445
+ return None
446
+
410
447
  def normalize(self, deep: bool = False) -> bool:
411
448
  """Normalize module node."""
412
449
  res = True
@@ -701,10 +738,12 @@ class ModuleItem(AstSymbolNode):
701
738
  name: Name,
702
739
  alias: Optional[Name],
703
740
  kid: Sequence[AstNode],
741
+ sub_module: Optional[Module] = None,
704
742
  ) -> None:
705
743
  """Initialize module item node."""
706
744
  self.name = name
707
745
  self.alias = alias
746
+ self.sub_module = sub_module
708
747
  AstNode.__init__(self, kid=kid)
709
748
  AstSymbolNode.__init__(
710
749
  self,
@@ -839,7 +878,6 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
839
878
  decl_link: Optional[Architype] = None,
840
879
  ) -> None:
841
880
  """Initialize arch def node."""
842
- self.target = target
843
881
  AstNode.__init__(self, kid=kid)
844
882
  AstSymbolNode.__init__(
845
883
  self,
@@ -849,7 +887,7 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
849
887
  )
850
888
  AstDocNode.__init__(self, doc=doc)
851
889
  ArchSpec.__init__(self, decorators=decorators)
852
- AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
890
+ AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
853
891
 
854
892
  def normalize(self, deep: bool = False) -> bool:
855
893
  """Normalize arch def node."""
@@ -950,7 +988,6 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
950
988
  decl_link: Optional[Enum] = None,
951
989
  ) -> None:
952
990
  """Initialize arch def node."""
953
- self.target = target
954
991
  AstNode.__init__(self, kid=kid)
955
992
  AstSymbolNode.__init__(
956
993
  self,
@@ -960,7 +997,7 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
960
997
  )
961
998
  AstDocNode.__init__(self, doc=doc)
962
999
  ArchSpec.__init__(self, decorators=decorators)
963
- AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
1000
+ AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
964
1001
 
965
1002
  def normalize(self, deep: bool = False) -> bool:
966
1003
  """Normalize enum def node."""
@@ -1000,7 +1037,7 @@ class Ability(
1000
1037
  is_static: bool,
1001
1038
  is_abstract: bool,
1002
1039
  access: Optional[SubTag[Token]],
1003
- signature: Optional[FuncSignature | EventSignature],
1040
+ signature: FuncSignature | EventSignature,
1004
1041
  body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef | FuncCall],
1005
1042
  kid: Sequence[AstNode],
1006
1043
  semstr: Optional[String] = None,
@@ -1027,16 +1064,6 @@ class Ability(
1027
1064
  AstDocNode.__init__(self, doc=doc)
1028
1065
  AstAsyncNode.__init__(self, is_async=is_async)
1029
1066
 
1030
- @property
1031
- def is_method(self) -> bool:
1032
- """Check if is method."""
1033
- check = isinstance(self.parent, SubNodeList) and isinstance(
1034
- self.parent.parent, Architype
1035
- )
1036
- if check:
1037
- self.sym_type = SymbolType.METHOD
1038
- return check
1039
-
1040
1067
  @property
1041
1068
  def is_func(self) -> bool:
1042
1069
  """Check if is func."""
@@ -1119,7 +1146,6 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
1119
1146
  decl_link: Optional[Ability] = None,
1120
1147
  ) -> None:
1121
1148
  """Initialize ability def node."""
1122
- self.target = target
1123
1149
  self.signature = signature
1124
1150
  self.decorators = decorators
1125
1151
  AstNode.__init__(self, kid=kid)
@@ -1130,7 +1156,7 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
1130
1156
  sym_type=SymbolType.IMPL,
1131
1157
  )
1132
1158
  AstDocNode.__init__(self, doc=doc)
1133
- AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
1159
+ AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
1134
1160
 
1135
1161
  def normalize(self, deep: bool = False) -> bool:
1136
1162
  """Normalize ability def node."""
@@ -1152,14 +1178,6 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
1152
1178
  self.set_kids(nodes=new_kid)
1153
1179
  return res
1154
1180
 
1155
- @property
1156
- def is_method(self) -> bool:
1157
- """Check if is method."""
1158
- return (
1159
- len(self.target.archs) > 1
1160
- and self.target.archs[-2].arch.name != Tok.ABILITY_OP
1161
- )
1162
-
1163
1181
 
1164
1182
  class FuncSignature(AstSemStrNode):
1165
1183
  """FuncSignature node type for Jac Ast."""
@@ -1197,13 +1215,6 @@ class FuncSignature(AstSemStrNode):
1197
1215
  self.set_kids(nodes=new_kid)
1198
1216
  return res
1199
1217
 
1200
- @property
1201
- def is_method(self) -> bool:
1202
- """Check if is method."""
1203
- return (isinstance(self.parent, Ability) and self.parent.is_method) or (
1204
- isinstance(self.parent, AbilityDef) and self.parent.is_method
1205
- )
1206
-
1207
1218
  @property
1208
1219
  def is_static(self) -> bool:
1209
1220
  """Check if is static."""
@@ -1256,17 +1267,6 @@ class EventSignature(AstSemStrNode):
1256
1267
  self.set_kids(nodes=new_kid)
1257
1268
  return res
1258
1269
 
1259
- @property
1260
- def is_method(self) -> bool:
1261
- """Check if is method."""
1262
- if (isinstance(self.parent, Ability) and self.parent.is_method) or (
1263
- isinstance(self.parent, AbilityDef)
1264
- and isinstance(self.parent.decl_link, Ability)
1265
- and self.parent.decl_link.is_method
1266
- ):
1267
- return True
1268
- return False
1269
-
1270
1270
 
1271
1271
  class ArchRefChain(AstNode):
1272
1272
  """Arch ref list node type for Jac Ast."""
@@ -1428,7 +1428,7 @@ class HasVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
1428
1428
  self,
1429
1429
  sym_name=name.value,
1430
1430
  sym_name_node=name,
1431
- sym_type=SymbolType.VAR,
1431
+ sym_type=SymbolType.HAS_VAR,
1432
1432
  )
1433
1433
  AstTypedVarNode.__init__(self, type_tag=type_tag)
1434
1434
  AstSemStrNode.__init__(self, semstr=semstr)
@@ -3100,6 +3100,7 @@ class ArchRef(NameSpec):
3100
3100
  sym_name_node=name_ref,
3101
3101
  sym_type=SymbolType.TYPE,
3102
3102
  )
3103
+ NameSpec.__init__(self)
3103
3104
 
3104
3105
  def normalize(self, deep: bool = False) -> bool:
3105
3106
  """Normalize ast node."""
@@ -3137,6 +3138,7 @@ class SpecialVarRef(NameSpec):
3137
3138
  sym_name_node=var,
3138
3139
  sym_type=SymbolType.VAR,
3139
3140
  )
3141
+ NameSpec.__init__(self)
3140
3142
 
3141
3143
  def normalize(self, deep: bool = False) -> bool:
3142
3144
  """Normalize ast node."""
@@ -3820,6 +3822,7 @@ class Name(Token, NameSpec):
3820
3822
  sym_name_node=self,
3821
3823
  sym_type=SymbolType.VAR,
3822
3824
  )
3825
+ NameSpec.__init__(self)
3823
3826
 
3824
3827
  def unparse(self) -> str:
3825
3828
  """Unparse name."""
@@ -57,6 +57,27 @@ def jac_str_to_pass(
57
57
  return ast_ret
58
58
 
59
59
 
60
+ def jac_ir_to_pass(
61
+ ir: ast.AstNode,
62
+ target: Optional[Type[Pass]] = None,
63
+ schedule: list[Type[Pass]] = pass_schedule,
64
+ ) -> Pass:
65
+ """Convert a Jac file to an AST."""
66
+ if not target:
67
+ target = schedule[-1] if schedule else None
68
+ ast_ret = (
69
+ Pass(input_ir=ir, prior=None)
70
+ if not len(schedule)
71
+ else schedule[0](input_ir=ir, prior=None)
72
+ )
73
+ for i in schedule[1:]:
74
+ if i == target:
75
+ break
76
+ ast_ret = i(input_ir=ast_ret.ir, prior=ast_ret)
77
+ ast_ret = target(input_ir=ast_ret.ir, prior=ast_ret) if target else ast_ret
78
+ return ast_ret
79
+
80
+
60
81
  def jac_pass_to_pass(
61
82
  in_pass: Pass,
62
83
  target: Optional[Type[Pass]] = None,
@@ -3,7 +3,7 @@
3
3
  from .sub_node_tab_pass import SubNodeTabPass
4
4
  from .import_pass import JacImportPass, PyImportPass # noqa: I100
5
5
  from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
6
- from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
6
+ from .def_impl_match_pass import DeclImplMatchPass # noqa: I100
7
7
  from .def_use_pass import DefUsePass # noqa: I100
8
8
  from .pyout_pass import PyOutPass # noqa: I100
9
9
  from .pyast_load_pass import PyastBuildPass # type: ignore # noqa: I100
@@ -20,7 +20,7 @@ __all__ = [
20
20
  "JacImportPass",
21
21
  "PyImportPass",
22
22
  "SymTabBuildPass",
23
- "DeclDefMatchPass",
23
+ "DeclImplMatchPass",
24
24
  "DefUsePass",
25
25
  "PyOutPass",
26
26
  "PyastBuildPass",
@@ -9,10 +9,10 @@ body field.
9
9
  import jaclang.compiler.absyntree as ast
10
10
  from jaclang.compiler.passes import Pass
11
11
  from jaclang.compiler.passes.main import SubNodeTabPass
12
- from jaclang.compiler.symtable import Symbol, SymbolTable, SymbolType
12
+ from jaclang.compiler.symtable import Symbol, SymbolTable
13
13
 
14
14
 
15
- class DeclDefMatchPass(Pass):
15
+ class DeclImplMatchPass(Pass):
16
16
  """Decls and Def matching pass."""
17
17
 
18
18
  def enter_module(self, node: ast.Module) -> None:
@@ -39,11 +39,12 @@ class DeclDefMatchPass(Pass):
39
39
  def connect_def_impl(self, sym_tab: SymbolTable) -> None:
40
40
  """Connect Decls and Defs."""
41
41
  for sym in sym_tab.tab.values():
42
- if sym.sym_type == SymbolType.IMPL:
42
+ if isinstance(sym.decl, ast.AstImplOnlyNode):
43
43
  # currently strips the type info from impls
44
44
  arch_refs = [x[3:] for x in sym.sym_name.split(".")]
45
+ name_of_links = [] # to link archref names to decls
45
46
  lookup = sym_tab.lookup(arch_refs[0])
46
- # Below may need to be a while instead of if to skip over local
47
+ # If below may need to be a while instead of if to skip over local
47
48
  # import name collisions (see test: test_impl_decl_resolution_fix)
48
49
  if lookup and not isinstance(lookup.decl, ast.AstImplNeedingNode):
49
50
  lookup = sym_tab.parent.lookup(arch_refs[0])
@@ -52,6 +53,7 @@ class DeclDefMatchPass(Pass):
52
53
  if len(arch_refs) == 1 and lookup
53
54
  else lookup.defn[-1] if lookup else None
54
55
  )
56
+ name_of_links.append(decl_node) if decl_node else None
55
57
  for name in arch_refs[1:]:
56
58
  if decl_node:
57
59
  lookup = (
@@ -64,6 +66,7 @@ class DeclDefMatchPass(Pass):
64
66
  if len(arch_refs) == 1 and lookup
65
67
  else lookup.defn[-1] if lookup else None
66
68
  )
69
+ name_of_links.append(decl_node) if decl_node else None
67
70
  else:
68
71
  break
69
72
  if not decl_node:
@@ -76,10 +79,9 @@ class DeclDefMatchPass(Pass):
76
79
  continue
77
80
  decl_node.body = sym.decl # type: ignore
78
81
  sym.decl.decl_link = decl_node # type: ignore
79
- source_node = sym.decl.parent
80
- decl_node.add_kids_right([sym.decl]) # type: ignore
81
- if source_node and sym.decl in source_node.kid:
82
- source_node.kid.remove(sym.decl)
82
+ for idx, a in enumerate(sym.decl.target.archs):
83
+ if isinstance(a.name_ref.sym_name_node, ast.NameSpec):
84
+ a.name_ref.sym_name_node.name_of = name_of_links[idx]
83
85
  decl_node.sym_tab.tab = sym.decl.sym_tab.tab # type: ignore
84
86
  for i in sym_tab.kid:
85
87
  self.connect_def_impl(i)
@@ -28,13 +28,20 @@ class DefUsePass(SymTabPass):
28
28
  sym_tab: Optional[SymbolTable],
29
29
  """
30
30
  if node.arch_type.name == Tok.KW_WALKER:
31
- for i in (
32
- self.get_all_sub_nodes(node, ast.VisitStmt)
33
- + self.get_all_sub_nodes(node, ast.IgnoreStmt)
34
- + self.get_all_sub_nodes(node, ast.DisengageStmt)
35
- + self.get_all_sub_nodes(node, ast.EdgeOpRef)
36
- ):
37
- i.from_walker = True
31
+ self.inform_from_walker(node)
32
+ for i in self.get_all_sub_nodes(node, ast.Ability):
33
+ if isinstance(i.body, ast.AbilityDef):
34
+ self.inform_from_walker(i.body)
35
+
36
+ def inform_from_walker(self, node: ast.AstNode) -> None:
37
+ """Inform all sub nodes that they are from a walker."""
38
+ for i in (
39
+ self.get_all_sub_nodes(node, ast.VisitStmt)
40
+ + self.get_all_sub_nodes(node, ast.IgnoreStmt)
41
+ + self.get_all_sub_nodes(node, ast.DisengageStmt)
42
+ + self.get_all_sub_nodes(node, ast.EdgeOpRef)
43
+ ):
44
+ i.from_walker = True
38
45
 
39
46
  def enter_arch_ref(self, node: ast.ArchRef) -> None:
40
47
  """Sub objects.
@@ -129,8 +129,10 @@ class FuseTypeInfoPass(Pass):
129
129
  if isinstance(mypy_node, MypyNodes.MemberExpr):
130
130
  if mypy_node in self.node_type_hash:
131
131
  t = str(self.node_type_hash[mypy_node])
132
- if "->" in t:
132
+ if "def" in t and "->" in t:
133
133
  t = t.split("->")[1].strip()
134
+ elif "def" in t:
135
+ t = "None"
134
136
  node.sym_info.typ = t
135
137
  else:
136
138
  self.__debug_print(f"{node.loc} MemberExpr type is not found")
@@ -181,6 +183,18 @@ class FuseTypeInfoPass(Pass):
181
183
  """Pass handler for name nodes."""
182
184
  self.__collect_type_from_symbol(node)
183
185
 
186
+ # Assign correct symbols to sym_link in case of
187
+ # AtomTrailer Object
188
+ if isinstance(node.parent, ast.AtomTrailer):
189
+ target_node = node.parent.target
190
+ if isinstance(target_node, ast.AstSymbolNode):
191
+ parent_symbol_table = target_node.sym_info.typ_sym_table
192
+ if isinstance(parent_symbol_table, ast.SymbolTable):
193
+ owner = parent_symbol_table.owner
194
+ if isinstance(owner, ast.AstSymbolNode):
195
+ target_node.sym_link = owner.sym_link
196
+ node.sym_link = parent_symbol_table.lookup(node.sym_name)
197
+
184
198
  @__handle_node
185
199
  def enter_module_path(self, node: ast.ModulePath) -> None:
186
200
  """Pass handler for ModulePath nodes."""
@@ -263,6 +277,11 @@ class FuseTypeInfoPass(Pass):
263
277
  "Getting type of 'HasVar' is only supported with AssignmentStmt"
264
278
  )
265
279
 
280
+ def exit_has_var(self, node: ast.HasVar) -> None:
281
+ """Pass handler for HasVar nodes."""
282
+ node.sym_info.typ = node.name.sym_info.typ
283
+ node.sym_info.typ_sym_table = node.name.sym_info.typ_sym_table
284
+
266
285
  @__handle_node
267
286
  def enter_multi_string(self, node: ast.MultiString) -> None:
268
287
  """Pass handler for MultiString nodes."""
@@ -46,17 +46,25 @@ class JacImportPass(Pass):
46
46
  """Process an import."""
47
47
  lang = i.parent_of_type(ast.Import).hint.tag.value
48
48
  if lang == "jac" and not i.sub_module:
49
- mod = self.import_jac_module(
49
+ self.import_jac_module(
50
50
  node=i,
51
51
  mod_path=node.loc.mod_path,
52
52
  )
53
- if mod:
54
- self.run_again = True
55
- i.sub_module = mod
56
- i.add_kids_right([mod], pos_update=False)
53
+
54
+ def attach_mod_to_node(
55
+ self, node: ast.ModulePath | ast.ModuleItem, mod: ast.Module | None
56
+ ) -> None:
57
+ """Attach a module to a node."""
58
+ if mod:
59
+ self.run_again = True
60
+ node.sub_module = mod
61
+ self.__annex_impl(mod)
62
+ node.add_kids_right([mod], pos_update=False)
57
63
 
58
64
  def __annex_impl(self, node: ast.Module) -> None:
59
65
  """Annex impl and test modules."""
66
+ if node.stub_only:
67
+ return
60
68
  if not node.loc.mod_path:
61
69
  self.error("Module has no path")
62
70
  if not node.loc.mod_path.endswith(".jac"):
@@ -99,7 +107,7 @@ class JacImportPass(Pass):
99
107
  ) and cur_file.endswith(".test.jac"):
100
108
  mod = self.import_jac_mod_from_file(cur_file)
101
109
  if mod:
102
- node.test_mod = mod
110
+ node.test_mod.append(mod)
103
111
  node.add_kids_right([mod], pos_update=False)
104
112
  mod.parent = node
105
113
 
@@ -114,15 +122,56 @@ class JacImportPass(Pass):
114
122
  node.sub_module.name = node.alias.value
115
123
  # Items matched during def/decl pass
116
124
 
117
- def import_jac_module(
118
- self, node: ast.ModulePath, mod_path: str
119
- ) -> ast.Module | None:
125
+ def import_jac_module(self, node: ast.ModulePath, mod_path: str) -> None:
120
126
  """Import a module."""
121
127
  self.cur_node = node # impacts error reporting
122
128
  target = import_target_to_relative_path(
123
- node.level, node.path_str, os.path.dirname(node.loc.mod_path)
129
+ level=node.level,
130
+ target=node.path_str,
131
+ base_path=os.path.dirname(node.loc.mod_path),
124
132
  )
125
- return self.import_jac_mod_from_file(target)
133
+ # If the module is a package (dir)
134
+ if os.path.isdir(target):
135
+ self.attach_mod_to_node(node, self.import_jac_mod_from_dir(target))
136
+ import_node = node.parent_of_type(ast.Import)
137
+ # And the import is a from import and I am the from module
138
+ if node == import_node.from_loc:
139
+ # Import all from items as modules or packages
140
+ for i in import_node.items.items:
141
+ if isinstance(i, ast.ModuleItem):
142
+ from_mod_target = import_target_to_relative_path(
143
+ level=node.level,
144
+ target=node.path_str + "." + i.name.value,
145
+ base_path=os.path.dirname(node.loc.mod_path),
146
+ )
147
+ # If package
148
+ if os.path.isdir(from_mod_target):
149
+ self.attach_mod_to_node(
150
+ i, self.import_jac_mod_from_dir(from_mod_target)
151
+ )
152
+ # Else module
153
+ else:
154
+ self.attach_mod_to_node(
155
+ i, self.import_jac_mod_from_file(from_mod_target)
156
+ )
157
+ else:
158
+ self.attach_mod_to_node(node, self.import_jac_mod_from_file(target))
159
+
160
+ def import_jac_mod_from_dir(self, target: str) -> ast.Module | None:
161
+ """Import a module from a directory."""
162
+ with_init = os.path.join(target, "__init__.jac")
163
+ if os.path.exists(with_init):
164
+ return self.import_jac_mod_from_file(with_init)
165
+ else:
166
+ return ast.Module(
167
+ name=target.split(os.path.sep)[-1],
168
+ source=ast.JacSource("", mod_path=target),
169
+ doc=None,
170
+ body=[],
171
+ is_imported=False,
172
+ stub_only=True,
173
+ kid=[ast.EmptyToken()],
174
+ )
126
175
 
127
176
  def import_jac_mod_from_file(self, target: str) -> ast.Module | None:
128
177
  """Import a module from a file."""
@@ -42,6 +42,7 @@ class PyastGenPass(Pass):
42
42
  """Initialize pass."""
43
43
  self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
44
44
  self.already_added: list[str] = []
45
+ self.method_sigs: list[ast.FuncSignature | ast.EventSignature] = []
45
46
  self.preamble: list[ast3.AST] = [
46
47
  self.sync(
47
48
  ast3.ImportFrom(
@@ -53,6 +54,13 @@ class PyastGenPass(Pass):
53
54
  )
54
55
  ]
55
56
 
57
+ def enter_node(self, node: ast.AstNode) -> None:
58
+ """Enter node."""
59
+ if node.gen.py_ast:
60
+ self.prune()
61
+ return
62
+ super().enter_node(node)
63
+
56
64
  def exit_node(self, node: ast.AstNode) -> None:
57
65
  """Exit node."""
58
66
  super().exit_node(node)
@@ -324,7 +332,8 @@ class PyastGenPass(Pass):
324
332
  for pbody in node.impl_mod:
325
333
  pre_body = [*pre_body, *pbody.body]
326
334
  pre_body = [*pre_body, *clean_body]
327
- pre_body = [*pre_body, *node.test_mod.body] if node.test_mod else pre_body
335
+ for pbody in node.test_mod:
336
+ pre_body = [*pre_body, *pbody.body]
328
337
  body = (
329
338
  [
330
339
  self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc),
@@ -658,6 +667,28 @@ class PyastGenPass(Pass):
658
667
  )
659
668
  ]
660
669
 
670
+ def enter_architype(self, node: ast.Architype) -> None:
671
+ """Sub objects.
672
+
673
+ name: Name,
674
+ arch_type: Token,
675
+ access: Optional[SubTag[Token]],
676
+ base_classes: Optional[SubNodeList[AtomType]],
677
+ body: Optional[SubNodeList[ArchBlockStmt] | ArchDef],
678
+ doc: Optional[String],
679
+ decorators: Optional[SubNodeList[ExprType]],
680
+ """
681
+ # Record all signatures that are part of methods
682
+ for i in (
683
+ node.body.body.items
684
+ if isinstance(node.body, ast.ArchDef)
685
+ else node.body.items if node.body else []
686
+ ):
687
+ if isinstance(i, ast.Ability):
688
+ self.method_sigs.append(i.signature)
689
+ if isinstance(node.body, ast.AstImplOnlyNode):
690
+ self.traverse(node.body)
691
+
661
692
  def exit_architype(self, node: ast.Architype) -> None:
662
693
  """Sub objects.
663
694
 
@@ -821,6 +852,19 @@ class PyastGenPass(Pass):
821
852
  decorators: Optional[SubNodeList[ExprType]],
822
853
  """
823
854
 
855
+ def enter_enum(self, node: ast.Enum) -> None:
856
+ """Sub objects.
857
+
858
+ name: Name,
859
+ access: Optional[SubTag[Token]],
860
+ base_classes: Optional[SubNodeList[AtomType]],
861
+ body: Optional[SubNodeList[EnumBlockStmt] | EnumDef],
862
+ doc: Optional[String],
863
+ decorators: Optional[SubNodeList[ExprType]],
864
+ """
865
+ if isinstance(node.body, ast.AstImplOnlyNode):
866
+ self.traverse(node.body)
867
+
824
868
  def exit_enum(self, node: ast.Enum) -> None:
825
869
  """Sub objects.
826
870
 
@@ -870,6 +914,23 @@ class PyastGenPass(Pass):
870
914
  decorators: Optional[SubNodeList[ExprType]],
871
915
  """
872
916
 
917
+ def enter_ability(self, node: ast.Ability) -> None:
918
+ """Sub objects.
919
+
920
+ name_ref: NameType,
921
+ is_func: bool,
922
+ is_async: bool,
923
+ is_static: bool,
924
+ is_abstract: bool,
925
+ access: Optional[SubTag[Token]],
926
+ signature: Optional[FuncSignature | ExprType | EventSignature],
927
+ body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef | FuncCall],
928
+ doc: Optional[String],
929
+ decorators: Optional[SubNodeList[ExprType]],
930
+ """
931
+ if isinstance(node.body, ast.AstImplOnlyNode):
932
+ self.traverse(node.body)
933
+
873
934
  def exit_ability(self, node: ast.Ability) -> None:
874
935
  """Sub objects.
875
936
 
@@ -1043,7 +1104,7 @@ class PyastGenPass(Pass):
1043
1104
  action = (
1044
1105
  node.semstr.gen.py_ast[0]
1045
1106
  if node.semstr
1046
- else self.sync(ast3.Constant(value=None))
1107
+ else self.sync(ast3.Constant(value=node.name_ref.sym_name))
1047
1108
  )
1048
1109
  return [
1049
1110
  self.sync(
@@ -1272,7 +1333,7 @@ class PyastGenPass(Pass):
1272
1333
  """
1273
1334
  params = (
1274
1335
  [self.sync(ast3.arg(arg="self", annotation=None))]
1275
- if node.is_method and not node.is_static
1336
+ if node in self.method_sigs and not node.is_static
1276
1337
  else []
1277
1338
  )
1278
1339
  vararg = None
@@ -1330,7 +1391,7 @@ class PyastGenPass(Pass):
1330
1391
  posonlyargs=[],
1331
1392
  args=(
1332
1393
  [self.sync(ast3.arg(arg="self", annotation=None)), here]
1333
- if node.is_method
1394
+ if node in self.method_sigs
1334
1395
  else [here]
1335
1396
  ),
1336
1397
  kwonlyargs=[],