jaclang 0.5.17__py3-none-any.whl → 0.6.0__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 (51) hide show
  1. jaclang/__init__.py +2 -6
  2. jaclang/cli/cli.py +4 -2
  3. jaclang/compiler/__init__.py +12 -5
  4. jaclang/compiler/absyntree.py +23 -23
  5. jaclang/compiler/generated/jac_parser.py +2 -2
  6. jaclang/compiler/jac.lark +9 -9
  7. jaclang/compiler/parser.py +76 -21
  8. jaclang/compiler/passes/ir_pass.py +10 -8
  9. jaclang/compiler/passes/main/__init__.py +3 -2
  10. jaclang/compiler/passes/main/access_modifier_pass.py +173 -0
  11. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +3 -2
  12. jaclang/compiler/passes/main/import_pass.py +33 -21
  13. jaclang/compiler/passes/main/pyast_gen_pass.py +99 -44
  14. jaclang/compiler/passes/main/pyast_load_pass.py +141 -77
  15. jaclang/compiler/passes/main/pyout_pass.py +14 -13
  16. jaclang/compiler/passes/main/registry_pass.py +8 -3
  17. jaclang/compiler/passes/main/schedules.py +5 -3
  18. jaclang/compiler/passes/main/sym_tab_build_pass.py +47 -37
  19. jaclang/compiler/passes/main/tests/test_import_pass.py +2 -2
  20. jaclang/compiler/passes/tool/jac_formatter_pass.py +85 -23
  21. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -4
  22. jaclang/compiler/passes/transform.py +2 -0
  23. jaclang/compiler/symtable.py +10 -3
  24. jaclang/compiler/tests/test_importer.py +9 -0
  25. jaclang/compiler/workspace.py +19 -11
  26. jaclang/core/aott.py +34 -63
  27. jaclang/core/importer.py +73 -65
  28. jaclang/core/llms/__init__.py +20 -0
  29. jaclang/core/llms/anthropic.py +61 -0
  30. jaclang/core/llms/base.py +206 -0
  31. jaclang/core/llms/groq.py +67 -0
  32. jaclang/core/llms/huggingface.py +73 -0
  33. jaclang/core/llms/ollama.py +78 -0
  34. jaclang/core/llms/openai.py +61 -0
  35. jaclang/core/llms/togetherai.py +60 -0
  36. jaclang/core/llms/utils.py +9 -0
  37. jaclang/core/utils.py +16 -1
  38. jaclang/plugin/default.py +47 -16
  39. jaclang/plugin/feature.py +9 -6
  40. jaclang/plugin/spec.py +8 -1
  41. jaclang/settings.py +95 -0
  42. jaclang/utils/helpers.py +6 -2
  43. jaclang/utils/treeprinter.py +9 -6
  44. jaclang/vendor/mypy/checker.py +2 -3
  45. jaclang-0.6.0.dist-info/METADATA +17 -0
  46. {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/RECORD +49 -39
  47. jaclang/core/llms.py +0 -29
  48. jaclang-0.5.17.dist-info/METADATA +0 -7
  49. {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/WHEEL +0 -0
  50. {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/entry_points.txt +0 -0
  51. {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/top_level.txt +0 -0
jaclang/compiler/jac.lark CHANGED
@@ -195,8 +195,8 @@ list_inner_pattern: (pattern_seq | STAR_MUL NAME)
195
195
  dict_inner_pattern: (literal_pattern COLON pattern_seq | STAR_POW NAME)
196
196
 
197
197
  // Match class patterns
198
- class_pattern: NAME LPAREN kw_pattern_list? RPAREN
199
- | NAME LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
198
+ class_pattern: NAME (DOT NAME)* LPAREN kw_pattern_list? RPAREN
199
+ | NAME (DOT NAME)* LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
200
200
 
201
201
  pattern_list: (pattern_list COMMA)? pattern_seq
202
202
  kw_pattern_list: (kw_pattern_list COMMA)? named_ref EQ pattern_seq
@@ -317,9 +317,9 @@ cmp_op: KW_ISN
317
317
 
318
318
  // Arithmetic expressions
319
319
  arithmetic: (arithmetic (MINUS | PLUS))? term
320
- term: (term (MOD | DIV | FLOOR_DIV | STAR_MUL | DECOR_OP))? factor
321
- factor: (BW_NOT | MINUS | PLUS) factor | power
322
- power: (power STAR_POW)? connect
320
+ term: (term (MOD | DIV | FLOOR_DIV | STAR_MUL | DECOR_OP))? power
321
+ power: (power STAR_POW)? factor
322
+ factor: (BW_NOT | MINUS | PLUS) factor | connect
323
323
 
324
324
  // Connect expressions
325
325
  connect: (connect (connect_op | disconnect_op))? atomic_pipe
@@ -539,16 +539,16 @@ KW_POST_INIT: "postinit"
539
539
  KW_SUPER: "super"
540
540
  KW_ROOT: "root"
541
541
 
542
- FLOAT: /(\d+(\.\d*)|\.\d+)([eE][+-]?\d+)?/
542
+ FLOAT: /(\d+(\.\d*)|\.\d+)([eE][+-]?\d+)?|\d+([eE][-+]?\d+)/
543
543
  DOC_STRING.1: /"""(.|\n|\r)*?"""|'''(.|\n|\r)*?'''/
544
544
  PYNLINE: /::py::(.|\n|\r)*?::py::/
545
545
  STRING: /(r?b?|b?r?)"[^"\r\n]*"|(r?b?|b?r?)'[^'\r\n]*'/
546
546
  BOOL.1: /True|False/
547
547
  KW_NIN.1: /\bnot\s+in\b/
548
548
  KW_ISN.1: /\bis\s+not\b/
549
- HEX: /0[xX][0-9a-fA-F_]+/
550
- BIN: /0[bB][01_]+/
551
- OCT: /0[oO][0-7_]+/
549
+ HEX.1: /0[xX][0-9a-fA-F_]+/
550
+ BIN.1: /0[bB][01_]+/
551
+ OCT.1: /0[oO][0-7_]+/
552
552
  INT: /[0-9][0-9_]*/
553
553
  NULL.1: /None/
554
554
  KWESC_NAME: /<>[a-zA-Z_][a-zA-Z0-9_]*/
@@ -287,17 +287,22 @@ class JacParser(Pass):
287
287
  if len(kid) == 1 and isinstance(kid[0], ast.Import):
288
288
  return self.nu(kid[0])
289
289
  lang = kid[1]
290
- paths = [i for i in kid if isinstance(i, ast.ModulePath)]
290
+ from_path = kid[3] if isinstance(kid[3], ast.ModulePath) else None
291
+ if from_path:
292
+ items = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
293
+ else:
294
+ paths = [i for i in kid if isinstance(i, ast.ModulePath)]
295
+ items = ast.SubNodeList[ast.ModulePath](
296
+ items=paths, delim=Tok.COMMA, kid=kid[2:-1]
297
+ )
298
+ kid = kid[:2] + [items] + kid[-1:]
291
299
 
292
- items = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
293
300
  is_absorb = False
294
- if isinstance(lang, ast.SubTag) and (
295
- isinstance(items, ast.SubNodeList) or items is None
296
- ):
301
+ if isinstance(lang, ast.SubTag) and (isinstance(items, ast.SubNodeList)):
297
302
  return self.nu(
298
303
  ast.Import(
299
304
  hint=lang,
300
- paths=paths,
305
+ from_loc=from_path,
301
306
  items=items,
302
307
  is_absorb=is_absorb,
303
308
  kid=kid,
@@ -342,14 +347,20 @@ class JacParser(Pass):
342
347
  include_stmt: KW_INCLUDE sub_name import_path SEMI
343
348
  """
344
349
  lang = kid[1]
345
- paths = [i for i in kid if isinstance(i, ast.ModulePath)]
350
+ from_path = kid[2]
351
+ if not isinstance(from_path, ast.ModulePath):
352
+ raise self.ice()
353
+ items = ast.SubNodeList[ast.ModulePath](
354
+ items=[from_path], delim=Tok.COMMA, kid=[from_path]
355
+ )
356
+ kid = kid[:2] + [items] + kid[3:]
346
357
  is_absorb = True
347
358
  if isinstance(lang, ast.SubTag):
348
359
  return self.nu(
349
360
  ast.Import(
350
361
  hint=lang,
351
- paths=paths,
352
- items=None,
362
+ from_loc=None,
363
+ items=items,
353
364
  is_absorb=is_absorb,
354
365
  kid=kid,
355
366
  )
@@ -1919,13 +1930,17 @@ class JacParser(Pass):
1919
1930
  sig_kid.append(params)
1920
1931
  if return_type:
1921
1932
  sig_kid.append(return_type)
1922
- signature = ast.FuncSignature(
1923
- params=params,
1924
- return_type=return_type,
1925
- kid=sig_kid,
1933
+ signature = (
1934
+ ast.FuncSignature(
1935
+ params=params,
1936
+ return_type=return_type,
1937
+ kid=sig_kid,
1938
+ )
1939
+ if params or return_type
1940
+ else None
1926
1941
  )
1927
1942
  new_kid = [i for i in kid if i != params and i != return_type]
1928
- new_kid.insert(1, signature)
1943
+ new_kid.insert(1, signature) if signature else None
1929
1944
  if isinstance(chomp[0], ast.Expr):
1930
1945
  return self.nu(
1931
1946
  ast.LambdaExpr(
@@ -3724,12 +3739,43 @@ class JacParser(Pass):
3724
3739
  def class_pattern(self, kid: list[ast.AstNode]) -> ast.MatchArch:
3725
3740
  """Grammar rule.
3726
3741
 
3727
- class_pattern: NAME LPAREN kw_pattern_list? RPAREN
3728
- | NAME LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
3742
+ class_pattern: NAME (DOT NAME)* LPAREN kw_pattern_list? RPAREN
3743
+ | NAME (DOT NAME)* LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
3729
3744
  """
3730
- name = kid[0]
3731
- first = kid[2]
3732
- second = kid[4] if len(kid) > 4 else None
3745
+ chomp = [*kid]
3746
+ cur_element = chomp[0]
3747
+ chomp = chomp[1:]
3748
+ while not (isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.LPAREN):
3749
+ if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.DOT:
3750
+ target_ = cur_element
3751
+ right_ = chomp[1]
3752
+ if isinstance(right_, (ast.Expr, ast.AtomExpr)) and isinstance(
3753
+ target_, ast.Expr
3754
+ ):
3755
+ cur_element = ast.AtomTrailer(
3756
+ target=target_,
3757
+ right=right_,
3758
+ is_attr=True,
3759
+ is_null_ok=False,
3760
+ kid=[target_, chomp[0], right_],
3761
+ )
3762
+ chomp = chomp[2:]
3763
+ else:
3764
+ raise self.ice()
3765
+ elif isinstance(cur_element, ast.NameSpec):
3766
+ chomp = chomp[1:]
3767
+ else:
3768
+ break
3769
+ name = cur_element
3770
+ lparen = chomp[0]
3771
+ rapren = chomp[-1]
3772
+ first = chomp[1]
3773
+ if len(chomp) > 4:
3774
+ second = chomp[3]
3775
+ comma = chomp[2]
3776
+ else:
3777
+ second = None
3778
+ comma = None
3733
3779
  arg = (
3734
3780
  first
3735
3781
  if isinstance(first, ast.SubNodeList)
@@ -3747,13 +3793,22 @@ class JacParser(Pass):
3747
3793
  else None
3748
3794
  )
3749
3795
  )
3750
- if isinstance(name, ast.NameSpec):
3796
+ if isinstance(name, (ast.NameSpec, ast.AtomTrailer)):
3797
+ kid_nodes = [name, lparen]
3798
+ if arg:
3799
+ kid_nodes.append(arg)
3800
+ if kw:
3801
+ kid_nodes.extend([comma, kw]) if comma else kid_nodes.append(kw)
3802
+ elif kw:
3803
+ kid_nodes.append(kw)
3804
+ kid_nodes.append(rapren)
3805
+
3751
3806
  return self.nu(
3752
3807
  ast.MatchArch(
3753
3808
  name=name,
3754
3809
  arg_patterns=arg,
3755
3810
  kw_patterns=kw,
3756
- kid=kid,
3811
+ kid=kid_nodes,
3757
3812
  )
3758
3813
  )
3759
3814
  else:
@@ -1,16 +1,18 @@
1
1
  """Abstract class for IR Passes for Jac."""
2
2
 
3
- from typing import Optional, Type
3
+ from typing import Optional, Type, TypeVar
4
4
 
5
5
  import jaclang.compiler.absyntree as ast
6
6
  from jaclang.compiler.passes.transform import Transform
7
7
  from jaclang.utils.helpers import pascal_to_snake
8
8
 
9
+ T = TypeVar("T", bound=ast.AstNode)
9
10
 
10
- class Pass(Transform[ast.T]):
11
+
12
+ class Pass(Transform[T]):
11
13
  """Abstract class for IR passes."""
12
14
 
13
- def __init__(self, input_ir: ast.T, prior: Optional[Transform]) -> None:
15
+ def __init__(self, input_ir: T, prior: Optional[Transform]) -> None:
14
16
  """Initialize parser."""
15
17
  self.term_signal = False
16
18
  self.prune_signal = False
@@ -45,10 +47,10 @@ class Pass(Transform[ast.T]):
45
47
 
46
48
  @staticmethod
47
49
  def get_all_sub_nodes(
48
- node: ast.AstNode, typ: Type[ast.T], brute_force: bool = False
49
- ) -> list[ast.T]:
50
+ node: ast.AstNode, typ: Type[T], brute_force: bool = False
51
+ ) -> list[T]:
50
52
  """Get all sub nodes of type."""
51
- result: list[ast.T] = []
53
+ result: list[T] = []
52
54
  # Assumes pass built the sub node table
53
55
  if not node:
54
56
  return result
@@ -69,7 +71,7 @@ class Pass(Transform[ast.T]):
69
71
  return result
70
72
 
71
73
  @staticmethod
72
- def has_parent_of_type(node: ast.AstNode, typ: Type[ast.T]) -> Optional[ast.T]:
74
+ def has_parent_of_type(node: ast.AstNode, typ: Type[T]) -> Optional[T]:
73
75
  """Check if node has parent of type."""
74
76
  while node.parent:
75
77
  if isinstance(node.parent, typ):
@@ -97,7 +99,7 @@ class Pass(Transform[ast.T]):
97
99
 
98
100
  # Transform Implementations
99
101
  # -------------------------
100
- def transform(self, ir: ast.T) -> ast.AstNode:
102
+ def transform(self, ir: T) -> ast.AstNode:
101
103
  """Run pass."""
102
104
  # Only performs passes on proper ASTs
103
105
  if not isinstance(ir, ast.AstNode):
@@ -1,7 +1,7 @@
1
1
  """Collection of passes for Jac IR."""
2
2
 
3
3
  from .sub_node_tab_pass import SubNodeTabPass
4
- from .import_pass import ImportPass # noqa: I100
4
+ from .import_pass import JacImportPass, PyImportPass # noqa: I100
5
5
  from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
6
6
  from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
7
7
  from .def_use_pass import DefUsePass # noqa: I100
@@ -17,7 +17,8 @@ pass_schedule = py_code_gen
17
17
 
18
18
  __all__ = [
19
19
  "SubNodeTabPass",
20
- "ImportPass",
20
+ "JacImportPass",
21
+ "PyImportPass",
21
22
  "SymTabBuildPass",
22
23
  "DeclDefMatchPass",
23
24
  "DefUsePass",
@@ -0,0 +1,173 @@
1
+ """Access check pass for the Jac compiler.
2
+
3
+ This pass checks for access to attributes in the Jac language.
4
+ """
5
+
6
+ import os
7
+ from typing import Optional
8
+
9
+ import jaclang.compiler.absyntree as ast
10
+ from jaclang.compiler.passes.main.sym_tab_build_pass import SymTabPass, SymbolAccess
11
+
12
+
13
+ class AccessCheckPass(SymTabPass):
14
+ """Jac Ast Access Check pass."""
15
+
16
+ def after_pass(self) -> None:
17
+ """After pass."""
18
+ pass
19
+
20
+ def access_check(self, node: ast.Name) -> None:
21
+ """Access check."""
22
+ node_info = (
23
+ node.sym_tab.lookup(node.sym_name)
24
+ if isinstance(node.sym_tab, ast.SymbolTable)
25
+ else None
26
+ )
27
+
28
+ if node.sym_link:
29
+ decl_package_path = os.path.dirname(
30
+ os.path.abspath(node.sym_link.defn[-1].loc.mod_path)
31
+ )
32
+ use_package_path = os.path.dirname(os.path.abspath(node.loc.mod_path))
33
+ else:
34
+ decl_package_path = use_package_path = ""
35
+
36
+ if (
37
+ node_info
38
+ and node.sym_link
39
+ and node_info.access == SymbolAccess.PROTECTED
40
+ and decl_package_path != use_package_path
41
+ ):
42
+ return self.error(
43
+ f'Can not access protected variable "{node.sym_name}" from {decl_package_path}'
44
+ f" to {use_package_path}."
45
+ )
46
+
47
+ if (
48
+ node_info
49
+ and node.sym_link
50
+ and node_info.access == SymbolAccess.PRIVATE
51
+ and node.sym_link.defn[-1].loc.mod_path != node.loc.mod_path
52
+ ):
53
+ return self.error(
54
+ f'Can not access private variable "{node.sym_name}" from {node.sym_link.defn[-1].loc.mod_path}'
55
+ f" to {node.loc.mod_path}."
56
+ )
57
+
58
+ def access_register(
59
+ self, node: ast.AstSymbolNode, acc_tag: Optional[SymbolAccess] = None
60
+ ) -> None:
61
+ """Access register."""
62
+ node.sym_info.acc_tag = acc_tag
63
+
64
+ def enter_global_vars(self, node: ast.GlobalVars) -> None:
65
+ """Sub objects.
66
+
67
+ access: Optional[SubTag[Token]],
68
+ assignments: SubNodeList[Assignment],
69
+ is_frozen: bool,
70
+ """
71
+ pass
72
+
73
+ def enter_module(self, node: ast.Module) -> None:
74
+ """Sub objects.
75
+
76
+ name: str,
77
+ doc: Token,
78
+ body: Optional['Elements'],
79
+ mod_path: str,
80
+ is_imported: bool,
81
+ """
82
+
83
+ def enter_architype(self, node: ast.Architype) -> None:
84
+ """Sub objects.
85
+
86
+ name: Name,
87
+ arch_type: Token,
88
+ access: Optional[SubTag[Token]],
89
+ base_classes: Optional[SubNodeList[Expr]],
90
+ body: Optional[SubNodeList[ArchBlockStmt] | ArchDef],
91
+ decorators: Optional[SubNodeList[Expr]] = None,
92
+ """
93
+ pass
94
+
95
+ def enter_enum(self, node: ast.Enum) -> None:
96
+ """Sub objects.
97
+
98
+ name: Name,
99
+ access: Optional[SubTag[Token]],
100
+ base_classes: Optional[SubNodeList[Expr]],
101
+ body: Optional[SubNodeList[EnumBlockStmt] | EnumDef],
102
+ decorators: Optional[SubNodeList[Expr]] = None,
103
+ """
104
+ pass
105
+
106
+ def enter_ability(self, node: ast.Ability) -> None:
107
+ """Sub objects.
108
+
109
+ name_ref: NameSpec,
110
+ is_func: bool,
111
+ is_async: bool,
112
+ is_override: bool,
113
+ is_static: bool,
114
+ is_abstract: bool,
115
+ access: Optional[SubTag[Token]],
116
+ signature: Optional[FuncSignature | EventSignature],
117
+ body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef],
118
+ decorators: Optional[SubNodeList[Expr]] = None,
119
+ """
120
+ pass
121
+
122
+ def enter_sub_node_list(self, node: ast.SubNodeList) -> None:
123
+ """Sub objects.
124
+
125
+ items: list[T]
126
+ """
127
+
128
+ def enter_arch_has(self, node: ast.ArchHas) -> None:
129
+ """Sub objects.
130
+
131
+ is_static: bool,
132
+ access: Optional[SubTag[Token]],
133
+ vars: SubNodeList[HasVar],
134
+ is_frozen: bool,
135
+ """
136
+ pass
137
+
138
+ def enter_atom_trailer(self, node: ast.AtomTrailer) -> None:
139
+ """Sub objects.
140
+
141
+ access: Optional[SubTag[Token]],
142
+ """
143
+ pass
144
+
145
+ def enter_func_call(self, node: ast.FuncCall) -> None:
146
+ """Sub objects.
147
+
148
+ target: Expr,
149
+ params: Optional[SubNodeList[Expr | KWPair]],
150
+ genai_call: Optional[FuncCall],
151
+ kid: Sequence[AstNode],
152
+ """
153
+ pass
154
+
155
+ def enter_name(self, node: ast.Name) -> None:
156
+ """Sub objects.
157
+
158
+ name: str,
159
+ value: str,
160
+ col_start: int,
161
+ col_end: int,
162
+ pos_start: int,
163
+ pos_end: int,
164
+ """
165
+ from jaclang.compiler.passes import Pass
166
+
167
+ if isinstance(node.parent, ast.FuncCall):
168
+ self.access_check(node)
169
+
170
+ if node.sym_link and Pass.has_parent_of_type(
171
+ node=node.sym_link.defn[-1], typ=ast.GlobalVars
172
+ ):
173
+ self.access_check(node)
@@ -6,15 +6,16 @@ mypy apis into Jac and use jac py ast in it.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- import os
10
9
  import traceback
11
10
  from typing import Callable, TypeVar
12
11
 
13
12
  import jaclang.compiler.absyntree as ast
14
13
  from jaclang.compiler.passes import Pass
14
+ from jaclang.settings import settings
15
15
  from jaclang.utils.helpers import pascal_to_snake
16
16
  from jaclang.vendor.mypy.nodes import Node as VNode # bit of a hack
17
17
 
18
+
18
19
  import mypy.nodes as MypyNodes # noqa N812
19
20
  import mypy.types as MypyTypes # noqa N812
20
21
  from mypy.checkexpr import Type as MyType
@@ -29,7 +30,7 @@ class FuseTypeInfoPass(Pass):
29
30
  node_type_hash: dict[MypyNodes.Node | VNode, MyType] = {}
30
31
 
31
32
  def __debug_print(self, *argv: object) -> None:
32
- if "FuseTypeInfoDebug" in os.environ:
33
+ if settings.fuse_type_info_debug:
33
34
  print("FuseTypeInfo::", *argv)
34
35
 
35
36
  def __call_type_handler(
@@ -7,7 +7,6 @@ symbols are available for matching.
7
7
 
8
8
  import ast as py_ast
9
9
  import importlib.util
10
- import os
11
10
  import sys
12
11
  from os import path
13
12
  from typing import Optional
@@ -16,11 +15,12 @@ from typing import Optional
16
15
  import jaclang.compiler.absyntree as ast
17
16
  from jaclang.compiler.passes import Pass
18
17
  from jaclang.compiler.passes.main import SubNodeTabPass
18
+ from jaclang.settings import settings
19
19
  from jaclang.utils.helpers import import_target_to_relative_path
20
20
 
21
21
 
22
- class ImportPass(Pass):
23
- """Jac statically imports all modules."""
22
+ class JacImportPass(Pass):
23
+ """Jac statically imports Jac modules."""
24
24
 
25
25
  def before_pass(self) -> None:
26
26
  """Run once before pass."""
@@ -29,6 +29,7 @@ class ImportPass(Pass):
29
29
  def enter_module(self, node: ast.Module) -> None:
30
30
  """Run Importer."""
31
31
  self.cur_node = node
32
+ self.import_table[node.loc.mod_path] = node
32
33
  self.annex_impl(node)
33
34
  self.terminate() # Turns off auto traversal for deliberate traversal
34
35
  self.run_again = True
@@ -36,29 +37,26 @@ class ImportPass(Pass):
36
37
  self.run_again = False
37
38
  all_imports = self.get_all_sub_nodes(node, ast.ModulePath)
38
39
  for i in all_imports:
39
- if i.parent.hint.tag.value == "jac" and not i.sub_module:
40
- self.run_again = True
41
- mod = self.import_module(
42
- node=i,
43
- mod_path=node.loc.mod_path,
44
- )
45
- if not mod:
46
- self.run_again = False
47
- continue
48
- self.annex_impl(mod)
49
- i.sub_module = mod
50
- i.add_kids_right([mod], pos_update=False)
51
- elif i.parent.hint.tag.value == "py" and os.environ.get(
52
- "JAC_PROC_DEBUG", False
53
- ):
54
- mod = self.import_py_module(node=i, mod_path=node.loc.mod_path)
55
- i.sub_module = mod
56
- i.add_kids_right([mod], pos_update=False)
40
+ self.process_import(node, i)
57
41
  self.enter_module_path(i)
58
42
  SubNodeTabPass(prior=self, input_ir=node)
59
43
  self.annex_impl(node)
60
44
  node.mod_deps = self.import_table
61
45
 
46
+ def process_import(self, node: ast.Module, i: ast.ModulePath) -> None:
47
+ """Process an import."""
48
+ lang = i.parent_of_type(ast.Import).hint.tag.value
49
+ if lang == "jac" and not i.sub_module:
50
+ mod = self.import_module(
51
+ node=i,
52
+ mod_path=node.loc.mod_path,
53
+ )
54
+ if mod:
55
+ self.run_again = True
56
+ self.annex_impl(mod)
57
+ i.sub_module = mod
58
+ i.add_kids_right([mod], pos_update=False)
59
+
62
60
  def annex_impl(self, node: ast.Module) -> None:
63
61
  """Annex impl and test modules."""
64
62
  if not node.loc.mod_path:
@@ -166,3 +164,17 @@ class ImportPass(Pass):
166
164
  )
167
165
  raise e
168
166
  return None
167
+
168
+
169
+ class PyImportPass(JacImportPass):
170
+ """Jac statically imports Python modules."""
171
+
172
+ def process_import(self, node: ast.Module, i: ast.ModulePath) -> None:
173
+ """Process an import."""
174
+ lang = i.parent_of_type(ast.Import).hint.tag.value
175
+ if lang == "py" and not i.sub_module and settings.py_raise:
176
+ mod = self.import_py_module(node=i, mod_path=node.loc.mod_path)
177
+ if mod:
178
+ # self.run_again = True
179
+ i.sub_module = mod
180
+ i.add_kids_right([mod], pos_update=False)