jaclang 0.7.14__py3-none-any.whl → 0.7.17__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 (131) hide show
  1. jaclang/cli/cli.py +147 -77
  2. jaclang/cli/cmdreg.py +9 -12
  3. jaclang/compiler/__init__.py +19 -53
  4. jaclang/compiler/absyntree.py +94 -16
  5. jaclang/compiler/constant.py +8 -8
  6. jaclang/compiler/jac.lark +4 -3
  7. jaclang/compiler/parser.py +41 -25
  8. jaclang/compiler/passes/ir_pass.py +4 -13
  9. jaclang/compiler/passes/main/__init__.py +1 -1
  10. jaclang/compiler/passes/main/access_modifier_pass.py +96 -147
  11. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +155 -54
  12. jaclang/compiler/passes/main/import_pass.py +99 -75
  13. jaclang/compiler/passes/main/py_collect_dep_pass.py +70 -0
  14. jaclang/compiler/passes/main/pyast_gen_pass.py +328 -565
  15. jaclang/compiler/passes/main/pyast_load_pass.py +33 -6
  16. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -0
  17. jaclang/compiler/passes/main/registry_pass.py +37 -3
  18. jaclang/compiler/passes/main/schedules.py +9 -2
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +10 -6
  20. jaclang/compiler/passes/main/tests/__init__.py +1 -1
  21. jaclang/compiler/passes/main/tests/fixtures/autoimpl.empty.impl.jac +0 -0
  22. jaclang/compiler/passes/main/tests/fixtures/autoimpl.jac +1 -1
  23. jaclang/compiler/passes/main/tests/fixtures/py_imp_test.jac +29 -0
  24. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -0
  25. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/color.py +3 -0
  26. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/constants.py +5 -0
  27. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/display.py +2 -0
  28. jaclang/compiler/passes/main/tests/test_import_pass.py +72 -13
  29. jaclang/compiler/passes/main/type_check_pass.py +22 -5
  30. jaclang/compiler/passes/tool/jac_formatter_pass.py +135 -89
  31. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +37 -41
  32. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +37 -42
  33. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/access_mod_check.jac +27 -0
  34. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
  35. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
  36. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
  37. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
  38. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
  39. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
  40. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
  41. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
  42. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
  43. jaclang/compiler/passes/transform.py +4 -0
  44. jaclang/compiler/passes/utils/mypy_ast_build.py +45 -0
  45. jaclang/compiler/semtable.py +31 -7
  46. jaclang/compiler/symtable.py +16 -11
  47. jaclang/compiler/tests/test_importer.py +25 -10
  48. jaclang/langserve/engine.py +104 -118
  49. jaclang/langserve/sem_manager.py +379 -0
  50. jaclang/langserve/server.py +24 -11
  51. jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
  52. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  53. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  54. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  55. jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
  56. jaclang/langserve/tests/fixtures/rename.jac +30 -0
  57. jaclang/langserve/tests/test_sem_tokens.py +277 -0
  58. jaclang/langserve/tests/test_server.py +287 -17
  59. jaclang/langserve/utils.py +184 -98
  60. jaclang/plugin/builtin.py +1 -1
  61. jaclang/plugin/default.py +288 -92
  62. jaclang/plugin/feature.py +65 -27
  63. jaclang/plugin/spec.py +62 -23
  64. jaclang/plugin/tests/fixtures/other_root_access.jac +82 -0
  65. jaclang/plugin/tests/test_jaseci.py +414 -42
  66. jaclang/runtimelib/architype.py +650 -0
  67. jaclang/{core → runtimelib}/constructs.py +5 -8
  68. jaclang/{core → runtimelib}/context.py +86 -59
  69. jaclang/runtimelib/importer.py +361 -0
  70. jaclang/runtimelib/machine.py +158 -0
  71. jaclang/runtimelib/memory.py +158 -0
  72. jaclang/{core → runtimelib}/utils.py +30 -15
  73. jaclang/settings.py +5 -4
  74. jaclang/tests/fixtures/abc.jac +3 -3
  75. jaclang/tests/fixtures/access_checker.jac +12 -17
  76. jaclang/tests/fixtures/access_modifier.jac +88 -33
  77. jaclang/tests/fixtures/baddy.jac +3 -0
  78. jaclang/tests/fixtures/baddy.test.jac +3 -0
  79. jaclang/tests/fixtures/bar.jac +34 -0
  80. jaclang/tests/fixtures/byllmissue.jac +1 -5
  81. jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
  82. jaclang/tests/fixtures/cls_method.jac +41 -0
  83. jaclang/tests/fixtures/dblhello.jac +6 -0
  84. jaclang/tests/fixtures/deep/one_lev.jac +3 -3
  85. jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
  86. jaclang/tests/fixtures/deep_import_mods.jac +13 -0
  87. jaclang/tests/fixtures/edge_node_walk.jac +1 -1
  88. jaclang/tests/fixtures/edge_ops.jac +1 -1
  89. jaclang/tests/fixtures/edges_walk.jac +1 -1
  90. jaclang/tests/fixtures/err.impl.jac +3 -0
  91. jaclang/tests/fixtures/err.jac +4 -2
  92. jaclang/tests/fixtures/err_runtime.jac +15 -0
  93. jaclang/tests/fixtures/foo.jac +43 -0
  94. jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
  95. jaclang/tests/fixtures/hello.jac +4 -0
  96. jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
  97. jaclang/tests/fixtures/impl_grab.jac +4 -1
  98. jaclang/tests/fixtures/import.jac +9 -0
  99. jaclang/tests/fixtures/index_slice.jac +30 -0
  100. jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
  101. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  102. jaclang/tests/fixtures/needs_import.jac +2 -2
  103. jaclang/tests/fixtures/pyfunc_1.py +1 -1
  104. jaclang/tests/fixtures/pyfunc_2.py +5 -2
  105. jaclang/tests/fixtures/pygame_mock/__init__.py +3 -0
  106. jaclang/tests/fixtures/pygame_mock/color.py +3 -0
  107. jaclang/tests/fixtures/pygame_mock/constants.py +5 -0
  108. jaclang/tests/fixtures/pygame_mock/display.py +2 -0
  109. jaclang/tests/fixtures/pygame_mock/inner/__init__.py +0 -0
  110. jaclang/tests/fixtures/pygame_mock/inner/iner_mod.py +2 -0
  111. jaclang/tests/fixtures/registry.jac +9 -0
  112. jaclang/tests/fixtures/run_test.jac +4 -4
  113. jaclang/tests/fixtures/semstr.jac +1 -4
  114. jaclang/tests/fixtures/simple_archs.jac +1 -1
  115. jaclang/tests/test_cli.py +109 -3
  116. jaclang/tests/test_language.py +170 -68
  117. jaclang/tests/test_reference.py +2 -3
  118. jaclang/utils/helpers.py +45 -21
  119. jaclang/utils/test.py +9 -0
  120. jaclang/utils/treeprinter.py +30 -7
  121. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/METADATA +3 -2
  122. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/RECORD +126 -90
  123. jaclang/core/architype.py +0 -502
  124. jaclang/core/importer.py +0 -344
  125. jaclang/core/memory.py +0 -99
  126. jaclang/tests/fixtures/aott_raise.jac +0 -25
  127. jaclang/tests/fixtures/package_import.jac +0 -6
  128. /jaclang/{core → runtimelib}/__init__.py +0 -0
  129. /jaclang/{core → runtimelib}/test.py +0 -0
  130. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/WHEEL +0 -0
  131. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/entry_points.txt +0 -0
@@ -128,6 +128,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
128
128
  is_imported=False,
129
129
  kid=valid,
130
130
  )
131
+ ret.is_raised_from_py = True
131
132
  return self.nu(ret)
132
133
 
133
134
  def proc_function_def(
@@ -144,12 +145,15 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
144
145
  if sys.version_info >= (3, 12):
145
146
  type_params: list[type_param]
146
147
  """
148
+ from jaclang.compiler import TOKEN_MAP
149
+
150
+ reserved_keywords = [v for _, v in TOKEN_MAP.items()]
151
+
152
+ value = node.name if node.name not in reserved_keywords else f"<>{node.name}"
147
153
  name = ast.Name(
148
154
  file_path=self.mod_path,
149
155
  name=Tok.NAME,
150
- value=(
151
- node.name if node.name != "root" else "root_"
152
- ), # root is a reserved keyword
156
+ value=value,
153
157
  line=node.lineno,
154
158
  end_line=node.end_lineno if node.end_lineno else node.lineno,
155
159
  col_start=node.col_offset,
@@ -1875,10 +1879,19 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1875
1879
  id: _Identifier
1876
1880
  ctx: expr_context
1877
1881
  """
1882
+ from jaclang.compiler import TOKEN_MAP
1883
+
1884
+ reserved_keywords = [
1885
+ v
1886
+ for _, v in TOKEN_MAP.items()
1887
+ if v not in ["float", "int", "str", "bool", "self"]
1888
+ ]
1889
+
1890
+ value = node.id if node.id not in reserved_keywords else f"<>{node.id}"
1878
1891
  ret = ast.Name(
1879
1892
  file_path=self.mod_path,
1880
1893
  name=Tok.NAME,
1881
- value=node.id if node.id != "root" else "root_", # reserved word
1894
+ value=value,
1882
1895
  line=node.lineno,
1883
1896
  end_line=node.end_lineno if node.end_lineno else node.lineno,
1884
1897
  col_start=node.col_offset,
@@ -1913,13 +1926,18 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
1913
1926
  class Nonlocal(stmt):
1914
1927
  names: list[_Identifier]
1915
1928
  """
1929
+ from jaclang.compiler import TOKEN_MAP
1930
+
1931
+ reserved_keywords = [v for _, v in TOKEN_MAP.items()]
1932
+
1916
1933
  names: list[ast.NameAtom] = []
1917
1934
  for name in node.names:
1935
+ value = name if name not in reserved_keywords else f"<>{name}"
1918
1936
  names.append(
1919
1937
  ast.Name(
1920
1938
  file_path=self.mod_path,
1921
1939
  name=Tok.NAME,
1922
- value=name if name != "root" else "root_",
1940
+ value=value,
1923
1941
  line=node.lineno,
1924
1942
  end_line=node.end_lineno if node.end_lineno else node.lineno,
1925
1943
  col_start=node.col_offset,
@@ -2238,10 +2256,19 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
2238
2256
  arg: _Identifier
2239
2257
  annotation: expr | None
2240
2258
  """
2259
+ from jaclang.compiler import TOKEN_MAP
2260
+
2261
+ reserved_keywords = [
2262
+ v
2263
+ for _, v in TOKEN_MAP.items()
2264
+ if v not in ["float", "int", "str", "bool", "self"]
2265
+ ]
2266
+
2267
+ value = node.arg if node.arg not in reserved_keywords else f"<>{node.arg}"
2241
2268
  name = ast.Name(
2242
2269
  file_path=self.mod_path,
2243
2270
  name=Tok.NAME,
2244
- value=node.arg if node.arg != "root" else "root_", # reserved word
2271
+ value=value,
2245
2272
  line=node.lineno,
2246
2273
  end_line=node.end_lineno if node.end_lineno else node.lineno,
2247
2274
  col_start=node.col_offset,
@@ -162,6 +162,13 @@ class PyJacAstLinkPass(Pass):
162
162
  py_nodes=node.parent.signature.return_type.gen.py_ast,
163
163
  )
164
164
 
165
+ if isinstance(node.decl_link, ast.Ability) and isinstance(
166
+ node.target, ast.ArchRefChain
167
+ ):
168
+ for arch in node.target.archs:
169
+ if arch.arch_name.sym:
170
+ arch.arch_name.sym.add_use(arch.arch_name)
171
+
165
172
  def exit_param_var(self, node: ast.ParamVar) -> None:
166
173
  """Sub objects.
167
174
 
@@ -13,7 +13,7 @@ import jaclang.compiler.absyntree as ast
13
13
  from jaclang.compiler.constant import Constants as Con
14
14
  from jaclang.compiler.passes import Pass
15
15
  from jaclang.compiler.semtable import SemInfo, SemRegistry
16
- from jaclang.core.utils import get_sem_scope
16
+ from jaclang.runtimelib.utils import get_sem_scope
17
17
 
18
18
 
19
19
  class RegistryPass(Pass):
@@ -46,6 +46,7 @@ class RegistryPass(Pass):
46
46
  """Save architype information."""
47
47
  scope = get_sem_scope(node)
48
48
  seminfo = SemInfo(
49
+ node,
49
50
  node.name.value,
50
51
  node.arch_type.value,
51
52
  node.semstr.lit_value if node.semstr else "",
@@ -61,7 +62,7 @@ class RegistryPass(Pass):
61
62
  """Save enum information."""
62
63
  scope = get_sem_scope(node)
63
64
  seminfo = SemInfo(
64
- node.name.value, "Enum", node.semstr.lit_value if node.semstr else ""
65
+ node, node.name.value, "Enum", node.semstr.lit_value if node.semstr else ""
65
66
  )
66
67
  if (
67
68
  len(self.modules_visited)
@@ -77,6 +78,38 @@ class RegistryPass(Pass):
77
78
  )
78
79
  scope = get_sem_scope(node)
79
80
  seminfo = SemInfo(
81
+ node,
82
+ node.name.value,
83
+ extracted_type,
84
+ node.semstr.lit_value if node.semstr else "",
85
+ )
86
+ if len(self.modules_visited) and self.modules_visited[-1].registry:
87
+ self.modules_visited[-1].registry.add(scope, seminfo)
88
+
89
+ def exit_ability(self, node: ast.Ability) -> None:
90
+ """Save ability information."""
91
+ scope = get_sem_scope(node)
92
+ seminfo = SemInfo(
93
+ node,
94
+ node.name_ref.sym_name,
95
+ "Ability",
96
+ node.semstr.lit_value if node.semstr else "",
97
+ )
98
+ if len(self.modules_visited) and self.modules_visited[-1].registry:
99
+ (
100
+ self.modules_visited[-1].registry.add(scope.parent, seminfo)
101
+ if scope.parent
102
+ else None
103
+ )
104
+
105
+ def exit_param_var(self, node: ast.ParamVar) -> None:
106
+ """Save param information."""
107
+ scope = get_sem_scope(node)
108
+ extracted_type = (
109
+ "".join(self.extract_type(node.type_tag.tag)) if node.type_tag else None
110
+ )
111
+ seminfo = SemInfo(
112
+ node,
80
113
  node.name.value,
81
114
  extracted_type,
82
115
  node.semstr.lit_value if node.semstr else "",
@@ -94,6 +127,7 @@ class RegistryPass(Pass):
94
127
  )
95
128
  scope = get_sem_scope(node)
96
129
  seminfo = SemInfo(
130
+ node,
97
131
  (
98
132
  node.target.items[0].value
99
133
  if isinstance(node.target.items[0], ast.Name)
@@ -113,7 +147,7 @@ class RegistryPass(Pass):
113
147
  and node.parent.parent.__class__.__name__ == "Enum"
114
148
  ):
115
149
  scope = get_sem_scope(node)
116
- seminfo = SemInfo(node.value, None, "")
150
+ seminfo = SemInfo(node, node.value, None, "")
117
151
  if len(self.modules_visited) and self.modules_visited[-1].registry:
118
152
  self.modules_visited[-1].registry.add(scope, seminfo)
119
153
 
@@ -19,11 +19,11 @@ from .type_check_pass import JacTypeCheckPass # noqa: I100
19
19
  from .fuse_typeinfo_pass import FuseTypeInfoPass # noqa: I100
20
20
  from .registry_pass import RegistryPass # noqa: I100
21
21
  from .access_modifier_pass import AccessCheckPass # noqa: I100
22
+ from .py_collect_dep_pass import PyCollectDepsPass # noqa: I100
22
23
 
23
24
  py_code_gen = [
24
25
  SubNodeTabPass,
25
26
  JacImportPass,
26
- PyImportPass,
27
27
  SymTabBuildPass,
28
28
  DeclImplMatchPass,
29
29
  DefUsePass,
@@ -33,6 +33,13 @@ py_code_gen = [
33
33
  PyBytecodeGenPass,
34
34
  ]
35
35
 
36
- type_checker_sched = [JacTypeCheckPass, FuseTypeInfoPass, AccessCheckPass]
36
+ type_checker_sched = [
37
+ JacTypeCheckPass,
38
+ PyCollectDepsPass,
39
+ PyImportPass,
40
+ DefUsePass,
41
+ FuseTypeInfoPass,
42
+ AccessCheckPass,
43
+ ]
37
44
  py_code_gen_typed = [*py_code_gen, *type_checker_sched]
38
45
  py_compiler = [*py_code_gen, PyOutPass]
@@ -19,12 +19,16 @@ class SymTabBuildPass(Pass):
19
19
  """Before pass."""
20
20
  self.cur_sym_tab: list[SymbolTable] = []
21
21
 
22
- def push_scope(self, name: str, key_node: ast.AstNode, fresh: bool = False) -> None:
22
+ def push_scope(self, name: str, key_node: ast.AstNode) -> None:
23
23
  """Push scope."""
24
- if fresh:
24
+ inherit = key_node.parent
25
+ if not len(self.cur_sym_tab) and not inherit:
25
26
  self.cur_sym_tab.append(SymbolTable(name, key_node))
27
+ elif not len(self.cur_sym_tab) and inherit:
28
+ self.cur_sym_tab.append(inherit.sym_tab)
29
+ self.cur_sym_tab.append(self.cur_scope.push_kid_scope(name, key_node))
26
30
  else:
27
- self.cur_sym_tab.append(self.cur_scope.push_scope(name, key_node))
31
+ self.cur_sym_tab.append(self.cur_scope.push_kid_scope(name, key_node))
28
32
 
29
33
  def pop_scope(self) -> SymbolTable:
30
34
  """Pop scope."""
@@ -48,7 +52,7 @@ class SymTabBuildPass(Pass):
48
52
  mod_path: str,
49
53
  is_imported: bool,
50
54
  """
51
- self.push_scope(node.name, node, fresh=(node == self.ir))
55
+ self.push_scope(node.name, node)
52
56
  self.sync_node_to_scope(node)
53
57
  for obj in dir(builtins):
54
58
  builtin = ast.Name(
@@ -193,11 +197,11 @@ class SymTabBuildPass(Pass):
193
197
  if not node.is_absorb:
194
198
  for i in node.items.items:
195
199
  i.sym_tab.def_insert(i, single_decl="import item")
196
- elif node.is_absorb and node.hint.tag.value == "jac":
200
+ elif node.is_absorb and node.is_jac:
197
201
  source = node.items.items[0]
198
202
  if not isinstance(source, ast.ModulePath) or not source.sub_module:
199
203
  self.error(
200
- f"Module {node.from_loc.path_str if node.from_loc else 'from location'}"
204
+ f"Module {node.from_loc.dot_path_str if node.from_loc else 'from location'}"
201
205
  f" not found to include *, or ICE occurred!"
202
206
  )
203
207
  else:
@@ -1 +1 @@
1
- """Tests for Jac passes."""
1
+ """Various tests for Jac passes."""
@@ -6,4 +6,4 @@ with entry {
6
6
  foo();
7
7
  bar();
8
8
  baz();
9
- }
9
+ }
@@ -0,0 +1,29 @@
1
+ import:py math;
2
+ import:py argparse;
3
+ import:py from pygame_mock { color, display }
4
+ import:py pygame_mock;
5
+ import:py os;
6
+
7
+ can fool_me -> `Type[pygame_mock.constants.CL] {
8
+ return pygame_mock.constants.CL;
9
+ }
10
+
11
+ obj kk {
12
+ can fool_me -> `Type[pygame_mock.constants.CL] {
13
+ return pygame_mock.constants.CL;
14
+ }
15
+ }
16
+
17
+ with entry {
18
+ b = math.floor(1.7);
19
+ c: color.Color = color.Color(pygame_mock.constants.CONST_VALUE);
20
+ c2: pygame_mock.color.Color = color.Color(pygame_mock.constants.CL.CONST_VALUE2);
21
+ c3: pygame_mock.color.Color = color.Color(fool_me().CONST_VALUE2);
22
+ c4: pygame_mock.color.Color = color.Color(kk().fool_me().CONST_VALUE2);
23
+ g = fool_me();
24
+ c4: pygame_mock.color.Color = color.Color(g.CONST_VALUE2);
25
+ a: argparse.ArgumentParser = argparse.ArgumentParser();
26
+ print("Hello", 1, b);
27
+ pygame_mock.display.set_mode(WIN_WIDTH, WIN_HEIGHT);
28
+ print(os.path.isfile("/jj"));
29
+ }
@@ -0,0 +1,3 @@
1
+ from .display import *
2
+ from .color import *
3
+ from .constants import *
@@ -0,0 +1,3 @@
1
+ class Color:
2
+ def __init__(self, value: int | str) -> None:
3
+ pass
@@ -0,0 +1,5 @@
1
+ CONST_VALUE: int = 0
2
+
3
+
4
+ class CL:
5
+ CONST_VALUE2: str = "h"
@@ -0,0 +1,2 @@
1
+ def set_mode(a, b):
2
+ pass
@@ -1,8 +1,15 @@
1
1
  """Test pass module."""
2
2
 
3
+ import io
4
+ import re
5
+ import sys
6
+
3
7
  import jaclang.compiler.absyntree as ast
8
+ from jaclang.cli import cli
4
9
  from jaclang.compiler.compile import jac_file_to_pass
5
10
  from jaclang.compiler.passes.main import JacImportPass
11
+ from jaclang.compiler.passes.main.fuse_typeinfo_pass import FuseTypeInfoPass
12
+ from jaclang.compiler.passes.main.schedules import py_code_gen_typed
6
13
  from jaclang.utils.test import TestCase
7
14
 
8
15
 
@@ -24,7 +31,7 @@ class ImportPassPassTests(TestCase):
24
31
  state = jac_file_to_pass(self.fixture_abs_path("autoimpl.jac"), JacImportPass)
25
32
  num_modules = len(state.ir.get_all_sub_nodes(ast.Module))
26
33
  mod_names = [i.name for i in state.ir.get_all_sub_nodes(ast.Module)]
27
- self.assertEqual(num_modules, 3)
34
+ self.assertEqual(num_modules, 4)
28
35
  self.assertIn("getme.impl", mod_names)
29
36
  self.assertIn("autoimpl.impl", mod_names)
30
37
  self.assertIn("autoimpl.something.else.impl", mod_names)
@@ -36,7 +43,7 @@ class ImportPassPassTests(TestCase):
36
43
  )
37
44
  num_modules = len(state.ir.get_all_sub_nodes(ast.Module))
38
45
  mod_names = [i.name for i in state.ir.get_all_sub_nodes(ast.Module)]
39
- self.assertEqual(num_modules, 4)
46
+ self.assertEqual(num_modules, 5)
40
47
  self.assertIn("getme.impl", mod_names)
41
48
  self.assertIn("autoimpl", mod_names)
42
49
  self.assertIn("autoimpl.impl", mod_names)
@@ -52,17 +59,69 @@ class ImportPassPassTests(TestCase):
52
59
  if i.name != "autoimpl":
53
60
  count += 1
54
61
  self.assertEqual(i.annexable_by, self.fixture_abs_path("autoimpl.jac"))
55
- self.assertEqual(count, 3)
62
+ self.assertEqual(count, 4)
63
+
64
+ def test_py_raise_map(self) -> None:
65
+ """Basic test for pass."""
66
+ build = jac_file_to_pass(
67
+ self.fixture_abs_path("py_imp_test.jac"),
68
+ FuseTypeInfoPass,
69
+ schedule=py_code_gen_typed,
70
+ )
71
+ assert isinstance(build.ir, ast.Module)
72
+ p = {
73
+ "math": "jaclang/jaclang/vendor/mypy/typeshed/stdlib/math.pyi",
74
+ "pygame_mock": "pygame_mock/__init__.py",
75
+ "pygame_mock.color": "pygame_mock/color.py",
76
+ "pygame_mock.constants": "pygame_mock/constants.py",
77
+ "argparse": "jaclang/vendor/mypy/typeshed/stdlib/argparse.pyi",
78
+ "builtins": "jaclang/vendor/mypy/typeshed/stdlib/builtins.pyi",
79
+ "pygame_mock.display": "pygame_mock/display.py",
80
+ "os": "jaclang/vendor/mypy/typeshed/stdlib/os/__init__.pyi",
81
+ "genericpath": "jaclang/vendor/mypy/typeshed/stdlib/genericpath.pyi",
82
+ }
83
+ for i in p:
84
+ self.assertIn(i, build.ir.py_raise_map)
85
+ self.assertIn(p[i], re.sub(r".*fixtures/", "", build.ir.py_raise_map[i]))
56
86
 
57
- def test_py_resolve_list(self) -> None:
87
+ def test_py_raised_mods(self) -> None:
58
88
  """Basic test for pass."""
59
- state: JacImportPass = jac_file_to_pass(
60
- self.examples_abs_path("rpg_game/jac_impl/jac_impl_5/main.jac"),
61
- JacImportPass,
89
+ state = jac_file_to_pass(
90
+ self.fixture_abs_path("py_imp_test.jac"), schedule=py_code_gen_typed
91
+ )
92
+ self.assertEqual(
93
+ len(
94
+ list(
95
+ filter(
96
+ lambda x: x.is_raised_from_py,
97
+ state.ir.get_all_sub_nodes(ast.Module),
98
+ )
99
+ )
100
+ ),
101
+ 7,
62
102
  )
63
- self.assertGreater(len(state.py_resolve_list), 20)
64
- self.assertIn("pygame.sprite.Sprite.__init__", state.py_resolve_list)
65
- self.assertIn("pygame.mouse.get_pressed", state.py_resolve_list)
66
- self.assertIn("pygame.K_SPACE", state.py_resolve_list)
67
- self.assertIn("random.randint", state.py_resolve_list)
68
- self.assertIn("pygame.font.Font", state.py_resolve_list)
103
+
104
+ # def test_py_resolve_list(self) -> None:
105
+ # """Basic test for pass."""
106
+ # state: JacImportPass = jac_file_to_pass(
107
+ # self.examples_abs_path("rpg_game/jac_impl/jac_impl_5/main.jac"),
108
+ # JacImportPass,
109
+ # )
110
+ # self.assertGreater(len(state.py_resolve_list), 20)
111
+ # self.assertIn("pygame.sprite.Sprite.__init__", state.py_resolve_list)
112
+ # self.assertIn("pygame.mouse.get_pressed", state.py_resolve_list)
113
+ # self.assertIn("pygame.K_SPACE", state.py_resolve_list)
114
+ # self.assertIn("random.randint", state.py_resolve_list)
115
+ # self.assertIn("pygame.font.Font", state.py_resolve_list)
116
+
117
+ def test_double_empty_anx(self) -> None:
118
+ """Test importing python."""
119
+ captured_output = io.StringIO()
120
+ sys.stdout = captured_output
121
+ cli.run(self.fixture_abs_path("autoimpl.jac"))
122
+ cli.run(self.fixture_abs_path("autoimpl.jac"))
123
+ sys.stdout = sys.__stdout__
124
+ stdout_value = captured_output.getvalue()
125
+ self.assertIn("foo", stdout_value)
126
+ self.assertIn("bar", stdout_value)
127
+ self.assertIn("baz", stdout_value)
@@ -8,7 +8,6 @@ import os
8
8
  import pathlib
9
9
  import sys
10
10
 
11
- # import jaclang
12
11
  import jaclang.compiler.absyntree as ast
13
12
  import jaclang.compiler.passes.utils.mypy_ast_build as myab
14
13
  from jaclang.compiler.constant import Constants as Con
@@ -35,7 +34,7 @@ class JacTypeCheckPass(Pass):
35
34
  def after_pass(self) -> None:
36
35
  """Call mypy api after traversing all the modules."""
37
36
  try:
38
- self.api()
37
+ self.api(os.path.dirname(self.ir.loc.mod_path))
39
38
  except Exception as e:
40
39
  self.error(f"Unable to run type checking: {e}")
41
40
  return super().after_pass()
@@ -45,11 +44,21 @@ class JacTypeCheckPass(Pass):
45
44
  ) -> None:
46
45
  """Mypy errors reporter."""
47
46
 
48
- def api(self) -> None:
47
+ def api(self, top_module_path: str = "") -> None:
49
48
  """Call mypy APIs to implement type checking in Jac."""
50
49
  # Creating mypy api objects
51
50
  options = myab.myb.Options()
51
+ options.ignore_missing_imports = True
52
52
  options.cache_dir = Con.JAC_MYPY_CACHE
53
+ options.mypy_path = [
54
+ str(
55
+ pathlib.Path(os.path.dirname(__file__)).parent.parent.parent.parent
56
+ / "stubs"
57
+ )
58
+ ]
59
+ if top_module_path != "":
60
+ options.mypy_path.append(top_module_path)
61
+
53
62
  errors = myab.Errors(self, options)
54
63
  fs_cache = myab.FileSystemCache()
55
64
  search_paths = myab.compute_search_paths([], options, str(self.__path))
@@ -94,7 +103,9 @@ class JacTypeCheckPass(Pass):
94
103
  mypy_graph[module.name] = st
95
104
  new_modules.append(st)
96
105
 
97
- graph = myab.load_graph(
106
+ if not isinstance(self.ir, ast.Module):
107
+ raise self.ice("Expected module node. Impossible")
108
+ mypy_graph = myab.load_graph(
98
109
  [
99
110
  myab.BuildSource(
100
111
  path=str(self.__path / "typeshed" / "stdlib" / "builtins.pyi"),
@@ -105,4 +116,10 @@ class JacTypeCheckPass(Pass):
105
116
  old_graph=mypy_graph,
106
117
  new_modules=new_modules, # To parse the dependancies of modules
107
118
  )
108
- myab.process_graph(graph, manager)
119
+ for i in mypy_graph:
120
+ self.ir.py_mod_dep_map[i] = mypy_graph[i].xpath
121
+ for j in mypy_graph[i].dependencies:
122
+ self.ir.py_mod_dep_map[j] = str(
123
+ myab.find_module_with_reason(j, manager)
124
+ )
125
+ myab.process_graph(mypy_graph, manager)