jaclang 0.8.7__py3-none-any.whl → 0.8.8__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (89) hide show
  1. jaclang/cli/cli.py +13 -27
  2. jaclang/cli/cmdreg.py +44 -0
  3. jaclang/compiler/constant.py +0 -1
  4. jaclang/compiler/jac.lark +3 -6
  5. jaclang/compiler/larkparse/jac_parser.py +2 -2
  6. jaclang/compiler/parser.py +213 -34
  7. jaclang/compiler/passes/main/__init__.py +2 -4
  8. jaclang/compiler/passes/main/def_use_pass.py +0 -4
  9. jaclang/compiler/passes/main/predynamo_pass.py +221 -0
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +70 -52
  11. jaclang/compiler/passes/main/pyast_load_pass.py +52 -20
  12. jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
  13. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
  14. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
  15. jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
  16. jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
  17. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
  18. jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
  19. jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
  20. jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
  21. jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
  22. jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
  23. jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
  24. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
  25. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
  26. jaclang/compiler/passes/main/tests/test_checker_pass.py +191 -0
  27. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +57 -0
  28. jaclang/compiler/passes/main/type_checker_pass.py +29 -73
  29. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +204 -44
  30. jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
  31. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
  32. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
  33. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +171 -11
  34. jaclang/compiler/passes/transform.py +12 -8
  35. jaclang/compiler/program.py +14 -6
  36. jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
  37. jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
  38. jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
  39. jaclang/compiler/tests/fixtures/python_module.py +1 -0
  40. jaclang/compiler/tests/test_importer.py +39 -0
  41. jaclang/compiler/tests/test_parser.py +49 -0
  42. jaclang/compiler/type_system/type_evaluator.py +351 -67
  43. jaclang/compiler/type_system/type_utils.py +246 -0
  44. jaclang/compiler/type_system/types.py +58 -2
  45. jaclang/compiler/unitree.py +79 -94
  46. jaclang/langserve/engine.jac +138 -159
  47. jaclang/langserve/server.jac +25 -1
  48. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  49. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  50. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  51. jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
  52. jaclang/langserve/tests/server_test/circle_template.jac +80 -0
  53. jaclang/langserve/tests/server_test/glob_template.jac +4 -0
  54. jaclang/langserve/tests/server_test/test_lang_serve.py +154 -309
  55. jaclang/langserve/tests/server_test/utils.py +153 -116
  56. jaclang/langserve/tests/test_server.py +21 -84
  57. jaclang/langserve/utils.jac +12 -15
  58. jaclang/runtimelib/machine.py +7 -0
  59. jaclang/runtimelib/meta_importer.py +27 -1
  60. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  61. jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
  62. jaclang/settings.py +18 -14
  63. jaclang/tests/fixtures/abc_check.jac +3 -3
  64. jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
  65. jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
  66. jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
  67. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  68. jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
  69. jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
  70. jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
  71. jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
  72. jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
  73. jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
  74. jaclang/tests/fixtures/py2jac_params.py +8 -0
  75. jaclang/tests/fixtures/run_test.jac +4 -4
  76. jaclang/tests/test_cli.py +37 -1
  77. jaclang/tests/test_language.py +74 -16
  78. jaclang/utils/helpers.py +47 -2
  79. jaclang/utils/module_resolver.py +10 -0
  80. jaclang/utils/test.py +8 -0
  81. jaclang/utils/treeprinter.py +0 -18
  82. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/METADATA +1 -2
  83. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/RECORD +85 -60
  84. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/WHEEL +1 -1
  85. jaclang/compiler/passes/main/inheritance_pass.py +0 -131
  86. jaclang/langserve/dev_engine.jac +0 -645
  87. jaclang/langserve/dev_server.jac +0 -201
  88. jaclang/langserve/tests/server_test/code_test.py +0 -0
  89. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/entry_points.txt +0 -0
@@ -28,6 +28,18 @@ class TypeCheckerPassTests(TestCase):
28
28
  ^^^^^^^^^^^^^^^^^^^^^^
29
29
  """, program.errors_had[1].pretty_print())
30
30
 
31
+ def test_float_types(self) -> None:
32
+ program = JacProgram()
33
+ mod = program.compile(self.fixture_abs_path("checker_float.jac"))
34
+ TypeCheckPass(ir_in=mod, prog=program)
35
+ self.assertEqual(len(program.errors_had), 1)
36
+ self._assert_error_pretty_found("""
37
+ f: float = pi; # <-- OK
38
+ s: str = pi; # <-- Error
39
+ ^^^^^^^^^^^
40
+ """, program.errors_had[0].pretty_print())
41
+
42
+
31
43
  def test_infer_type_of_assignment(self) -> None:
32
44
  program = JacProgram()
33
45
  mod = program.compile(self.fixture_abs_path("infer_type_assignment.jac"))
@@ -49,6 +61,17 @@ class TypeCheckerPassTests(TestCase):
49
61
  ^^^^^^^^^^^^^^^^^^^
50
62
  """, program.errors_had[0].pretty_print())
51
63
 
64
+ def test_imported_sym(self) -> None:
65
+ program = JacProgram()
66
+ mod = program.compile(self.fixture_abs_path("checker/import_sym_test.jac"))
67
+ TypeCheckPass(ir_in=mod, prog=program)
68
+ self.assertEqual(len(program.errors_had), 1)
69
+ self._assert_error_pretty_found("""
70
+ a: str = foo(); # <-- Ok
71
+ b: int = foo(); # <-- Error
72
+ ^^^^^^^^^^^^^^
73
+ """, program.errors_had[0].pretty_print())
74
+
52
75
  def test_member_access_type_infered(self) -> None:
53
76
  program = JacProgram()
54
77
  mod = program.compile(self.fixture_abs_path("member_access_type_inferred.jac"))
@@ -59,6 +82,22 @@ class TypeCheckerPassTests(TestCase):
59
82
  ^^^^^^^^^
60
83
  """, program.errors_had[0].pretty_print())
61
84
 
85
+ def test_inherited_symbol(self) -> None:
86
+ program = JacProgram()
87
+ mod = program.compile(self.fixture_abs_path("checker_sym_inherit.jac"))
88
+ TypeCheckPass(ir_in=mod, prog=program)
89
+ self.assertEqual(len(program.errors_had), 2)
90
+ self._assert_error_pretty_found("""
91
+ c.val = 42; # <-- Ok
92
+ c.val = "str"; # <-- Error
93
+ ^^^^^^^^^^^^^
94
+ """, program.errors_had[0].pretty_print())
95
+ self._assert_error_pretty_found("""
96
+ l.name = "Simba"; # <-- Ok
97
+ l.name = 42; # <-- Error
98
+ ^^^^^^^^^^^
99
+ """, program.errors_had[1].pretty_print())
100
+
62
101
  def test_import_symbol_type_infer(self) -> None:
63
102
  program = JacProgram()
64
103
  mod = program.compile(self.fixture_abs_path("import_symbol_type_infer.jac"))
@@ -104,6 +143,145 @@ class TypeCheckerPassTests(TestCase):
104
143
  ^^^^^^^^^^^^^^^^
105
144
  """, program.errors_had[0].pretty_print())
106
145
 
146
+ def test_arity(self) -> None:
147
+ path = self.fixture_abs_path("checker_arity.jac")
148
+ program = JacProgram()
149
+ mod = program.compile(path)
150
+ TypeCheckPass(ir_in=mod, prog=program)
151
+ self.assertEqual(len(program.errors_had), 3)
152
+ self._assert_error_pretty_found("""
153
+ f.first_is_self(f); # <-- Error
154
+ ^
155
+ """, program.errors_had[0].pretty_print())
156
+ self._assert_error_pretty_found("""
157
+ f.with_default_args(1, 2, 3); # <-- Error
158
+ ^
159
+ """, program.errors_had[1].pretty_print())
160
+ self._assert_error_pretty_found("""
161
+ f.with_default_args(); # <-- Error
162
+ ^^^^^^^^^^^^^^^^^^^^^
163
+ """, program.errors_had[2].pretty_print())
164
+
165
+ def test_param_types(self) -> None:
166
+ path = self.fixture_abs_path("checker_param_types.jac")
167
+ program = JacProgram()
168
+ mod = program.compile(path)
169
+ TypeCheckPass(ir_in=mod, prog=program)
170
+ self.assertEqual(len(program.errors_had), 1)
171
+ self._assert_error_pretty_found("""
172
+ foo(A()); # <-- Ok
173
+ foo(B()); # <-- Error
174
+ ^^^
175
+ """, program.errors_had[0].pretty_print())
176
+
177
+ def test_param_arg_match(self) -> None:
178
+ path = self.fixture_abs_path("checker_param_types.jac")
179
+ program = JacProgram()
180
+ path = self.fixture_abs_path("checker_arg_param_match.jac")
181
+ mod = program.compile(path)
182
+ TypeCheckPass(ir_in=mod, prog=program)
183
+ self.assertEqual(len(program.errors_had), 13)
184
+
185
+ expected_errors = [
186
+ """
187
+ Not all required parameters were provided in the function call: 'a'
188
+ f = Foo();
189
+ f.bar();
190
+ ^^^^^^^
191
+ """,
192
+ """
193
+ Too many positional arguments
194
+ f.bar();
195
+ f.bar(1);
196
+ f.bar(1, 2);
197
+ ^
198
+ """,
199
+ """
200
+ Not all required parameters were provided in the function call: 'self', 'a'
201
+ f.bar(1, 2);
202
+ f.baz();
203
+ ^^^^^^^
204
+ """,
205
+ """
206
+ Not all required parameters were provided in the function call: 'a'
207
+ f.baz();
208
+ f.baz(1);
209
+ ^^^^^^^^
210
+ """,
211
+ """
212
+ Not all required parameters were provided in the function call: 'f'
213
+ foo(1, 2, d=3, e=4, f=5, c=4); # order does not matter for named
214
+ foo(1, 2, 3, d=4, e=5, g=7, h=8); # missing argument 'f'
215
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
216
+ """,
217
+ """
218
+ Positional only parameter 'b' cannot be matched with a named argument
219
+ foo(1, 2, 3, d=4, e=5, g=7, h=8); # missing argument 'f'
220
+ foo(1, b=2, c=3, d=4, e=5, f=6); # b is positional only
221
+ ^^^
222
+ """,
223
+ """
224
+ Too many positional arguments
225
+ bar(1, 2, 3, 4, 5, f=6);
226
+ bar(1, 2, 3, 4, 5, 6, 7, 8, 9); # too many args
227
+ ^
228
+ """,
229
+ """
230
+ Too many positional arguments
231
+ bar(1, 2, 3, 4, 5, f=6);
232
+ bar(1, 2, 3, 4, 5, 6, 7, 8, 9); # too many args
233
+ ^
234
+ """,
235
+ """
236
+ Too many positional arguments
237
+ bar(1, 2, 3, 4, 5, f=6);
238
+ bar(1, 2, 3, 4, 5, 6, 7, 8, 9); # too many args
239
+ ^
240
+ """,
241
+ """
242
+ Parameter 'c' already matched
243
+ bar(1, 2, 3, 4, 5, f=6);
244
+ bar(1, 2, 3, 4, 5, 6, 7, 8, 9); # too many args
245
+ bar(1, 2, 3, 4, 5, 6, c=3); # already matched
246
+ ^^^
247
+ """,
248
+ """
249
+ Named argument 'h' does not match any parameter
250
+ bar(1, 2, 3, 4, 5, 6, 7, 8, 9); # too many args
251
+ bar(1, 2, 3, 4, 5, 6, c=3); # already matched
252
+ bar(1, 2, 3, 4, 5, 6, h=1); # h is not matched
253
+ ^^^
254
+ """,
255
+ """
256
+ Too many positional arguments
257
+ baz(a=1, b=2);
258
+ baz(1, b=2); # a can be both positional and keyword
259
+ baz(1, 2); # 'b' can only be keyword arg
260
+ ^
261
+ """,
262
+ """
263
+ Not all required parameters were provided in the function call: 'b'
264
+ baz(a=1, b=2);
265
+ baz(1, b=2); # a can be both positional and keyword
266
+ baz(1, 2); # 'b' can only be keyword arg
267
+ ^^^^^^^^^
268
+ """,
269
+ ]
270
+
271
+ for i, expected in enumerate(expected_errors):
272
+ self._assert_error_pretty_found(expected, program.errors_had[i].pretty_print())
273
+
274
+ def test_self_type_inference(self) -> None:
275
+ path = self.fixture_abs_path("checker_self_type.jac")
276
+ program = JacProgram()
277
+ mod = program.compile(path)
278
+ TypeCheckPass(ir_in=mod, prog=program)
279
+ self.assertEqual(len(program.errors_had), 1)
280
+ self._assert_error_pretty_found("""
281
+ x: str = self.i; # <-- Error
282
+ ^^^^^^^^^^^^^^^
283
+ """, program.errors_had[0].pretty_print())
284
+
107
285
  def test_binary_op(self) -> None:
108
286
  program = JacProgram()
109
287
  mod = program.compile(self.fixture_abs_path("checker_binary_op.jac"))
@@ -140,6 +318,19 @@ class TypeCheckerPassTests(TestCase):
140
318
  ^^^^^^^^^^^^^^
141
319
  """, program.errors_had[0].pretty_print())
142
320
 
321
+ def test_checker_cat_is_animal(self) -> None:
322
+ path = self.fixture_abs_path("checker_cat_is_animal.jac")
323
+ program = JacProgram()
324
+ mod = program.compile(path)
325
+ TypeCheckPass(ir_in=mod, prog=program)
326
+ self.assertEqual(len(program.errors_had), 1)
327
+ self._assert_error_pretty_found("""
328
+ animal_func(cat); # <-- Ok
329
+ animal_func(lion); # <-- Ok
330
+ animal_func(not_animal); # <-- Error
331
+ ^^^^^^^^^^
332
+ """, program.errors_had[0].pretty_print())
333
+
143
334
  def test_checker_import_missing_module(self) -> None:
144
335
  path = self.fixture_abs_path("checker_import_missing_module.jac")
145
336
  program = JacProgram()
@@ -0,0 +1,57 @@
1
+ """Test ast build pass module."""
2
+
3
+ import io
4
+ import os
5
+ import sys
6
+
7
+ from jaclang.compiler.program import JacProgram
8
+ from jaclang.utils.test import TestCase
9
+ from jaclang.settings import settings
10
+ from jaclang.compiler.passes.main import PreDynamoPass
11
+
12
+ class PreDynamoPassTests(TestCase):
13
+ """Test pass module."""
14
+
15
+ TargetPass = PreDynamoPass
16
+
17
+ def setUp(self) -> None:
18
+ """Set up test."""
19
+ return super().setUp()
20
+
21
+ def test_predynamo_where_assign(self) -> None:
22
+ """Test torch.where transformation."""
23
+ captured_output = io.StringIO()
24
+ sys.stdout = captured_output
25
+ os.environ["JAC_PREDYNAMO_PASS"] = "True"
26
+ settings.load_env_vars()
27
+ code_gen = JacProgram().compile(self.fixture_abs_path("predynamo_where_assign.jac"))
28
+ sys.stdout = sys.__stdout__
29
+ self.assertIn("torch.where", code_gen.unparse())
30
+ os.environ["JAC_PREDYNAMO_PASS"] = "false"
31
+ settings.load_env_vars()
32
+
33
+ def test_predynamo_where_return(self) -> None:
34
+ """Test torch.where transformation."""
35
+ captured_output = io.StringIO()
36
+ sys.stdout = captured_output
37
+ os.environ["JAC_PREDYNAMO_PASS"] = "True"
38
+ settings.load_env_vars()
39
+ code_gen = JacProgram().compile(self.fixture_abs_path("predynamo_where_return.jac"))
40
+ sys.stdout = sys.__stdout__
41
+ self.assertIn("torch.where", code_gen.unparse())
42
+ os.environ["JAC_PREDYNAMO_PASS"] = "false"
43
+ settings.load_env_vars()
44
+
45
+ def test_predynamo_fix3(self) -> None:
46
+ """Test torch.where transformation."""
47
+ captured_output = io.StringIO()
48
+ sys.stdout = captured_output
49
+ os.environ["JAC_PREDYNAMO_PASS"] = "True"
50
+ settings.load_env_vars()
51
+ code_gen = JacProgram().compile(self.fixture_abs_path("predynamo_fix3.jac"))
52
+ sys.stdout = sys.__stdout__
53
+ unparsed_code = code_gen.unparse()
54
+ self.assertIn("__inv_freq = torch.where(", unparsed_code)
55
+ self.assertIn("self.register_buffer('inv_freq', __inv_freq, persistent=False);", unparsed_code)
56
+ os.environ["JAC_PREDYNAMO_PASS"] = "false"
57
+ settings.load_env_vars()
@@ -9,92 +9,34 @@ Reference:
9
9
  craizy_type_expr branch: type_checker_pass.py
10
10
  """
11
11
 
12
- import ast as py_ast
13
- import os
14
-
15
12
  import jaclang.compiler.unitree as uni
16
13
  from jaclang.compiler.passes import UniPass
17
- from jaclang.compiler.type_system.type_evaluator import TypeEvaluator
18
- from jaclang.runtimelib.utils import read_file_with_encoding
19
-
20
- from .pyast_load_pass import PyastBuildPass
21
- from .sym_tab_build_pass import SymTabBuildPass
14
+ from jaclang.compiler.type_system import types as jtypes
22
15
 
23
16
 
24
17
  class TypeCheckPass(UniPass):
25
18
  """Type checker pass for JacLang."""
26
19
 
27
- # NOTE: This is done in the binder pass of pyright, however I'm doing this
28
- # here, cause this will be the entry point of the type checker and we're not
29
- # relying on the binder pass at the moment and we can go back to binder pass
30
- # in the future if we needed it.
31
- _BUILTINS_STUB_FILE_PATH = os.path.join(
32
- os.path.dirname(__file__),
33
- "../../../vendor/typeshed/stdlib/builtins.pyi",
34
- )
35
-
36
- # Cache the builtins module once it parsed.
37
- _BUILTINS_MODULE: uni.Module | None = None
38
-
39
- # REVIEW: Making the evaluator a static (singleton) variable to make sure only one
40
- # instance is used across mulitple compilation units. This can also be attached to an
41
- # attribute of JacProgram, however the evaluator is a temproary object that we dont
42
- # want bound to the program for long term, Also the program is the one that will be
43
- # dumped in the compiled bundle.
44
- _EVALUATOR: TypeEvaluator | None = None
45
-
46
20
  def before_pass(self) -> None:
47
21
  """Initialize the checker pass."""
48
- self._load_builtins_stub_module()
22
+ self.evaluator = self.prog.get_type_evaluator()
23
+ self.evaluator.diagnostic_callback = self._add_diagnostic
49
24
  self._insert_builtin_symbols()
50
25
 
51
- @property
52
- def evaluator(self) -> TypeEvaluator:
53
- """Return the type evaluator."""
54
- if TypeCheckPass._EVALUATOR is None:
55
- assert TypeCheckPass._BUILTINS_MODULE is not None
56
- TypeCheckPass._EVALUATOR = TypeEvaluator(
57
- builtins_module=TypeCheckPass._BUILTINS_MODULE,
58
- program=self.prog,
59
- )
60
- return TypeCheckPass._EVALUATOR
26
+ def _add_diagnostic(self, node: uni.UniNode, message: str, warning: bool) -> None:
27
+ """Add a diagnostic message to the pass."""
28
+ if warning:
29
+ self.log_warning(message, node)
30
+ else:
31
+ self.log_error(message, node)
61
32
 
62
33
  # --------------------------------------------------------------------------
63
34
  # Internal helper functions
64
35
  # --------------------------------------------------------------------------
65
36
 
66
- def _binding_builtins(self) -> bool:
67
- """Return true if we're binding the builtins stub file."""
68
- return self.ir_in == TypeCheckPass._BUILTINS_MODULE
69
-
70
- def _load_builtins_stub_module(self) -> None:
71
- """Return the builtins stub module.
72
-
73
- This will parse and cache the stub file and return the cached module on
74
- subsequent calls.
75
- """
76
- if self._binding_builtins() or TypeCheckPass._BUILTINS_MODULE is not None:
77
- return
78
-
79
- if not os.path.exists(TypeCheckPass._BUILTINS_STUB_FILE_PATH):
80
- raise FileNotFoundError(
81
- f"Builtins stub file not found at {TypeCheckPass._BUILTINS_STUB_FILE_PATH}"
82
- )
83
-
84
- file_content = read_file_with_encoding(TypeCheckPass._BUILTINS_STUB_FILE_PATH)
85
- uni_source = uni.Source(file_content, TypeCheckPass._BUILTINS_STUB_FILE_PATH)
86
- mod = PyastBuildPass(
87
- ir_in=uni.PythonModuleAst(
88
- py_ast.parse(file_content),
89
- orig_src=uni_source,
90
- ),
91
- prog=self.prog,
92
- ).ir_out
93
- SymTabBuildPass(ir_in=mod, prog=self.prog)
94
- TypeCheckPass._BUILTINS_MODULE = mod
95
-
96
37
  def _insert_builtin_symbols(self) -> None:
97
- if self._binding_builtins():
38
+ # Don't insert builtin symbols into the builtin module itself.
39
+ if self.ir_in == self.evaluator.builtins_module:
98
40
  return
99
41
 
100
42
  # TODO: Insert these symbols.
@@ -104,20 +46,34 @@ class TypeCheckPass(UniPass):
104
46
  # '__name__', '__loader__', '__package__', '__spec__', '__path__',
105
47
  # '__file__', '__cached__', '__dict__', '__annotations__',
106
48
  # '__builtins__', '__doc__',
107
- assert (
108
- TypeCheckPass._BUILTINS_MODULE is not None
109
- ), "Builtins module is not loaded"
110
49
  if self.ir_in.parent_scope is not None:
111
50
  self.log_info("Builtins module is already bound, skipping.")
112
51
  return
113
52
  # Review: If we ever assume a module cannot have a parent scope, this will
114
53
  # break that contract.
115
- self.ir_in.parent_scope = TypeCheckPass._BUILTINS_MODULE
54
+ self.ir_in.parent_scope = self.evaluator.builtins_module
116
55
 
117
56
  # --------------------------------------------------------------------------
118
57
  # Ast walker hooks
119
58
  # --------------------------------------------------------------------------
120
59
 
60
+ def enter_ability(self, node: uni.Ability) -> None:
61
+ """Enter an ability node."""
62
+ # If the node has @staticmethod decorator, mark it as static method.
63
+ # this is needed since ast raised from python does not have this info.
64
+ for decor in node.decorators or []:
65
+ ty = self.evaluator.get_type_of_expression(decor)
66
+ if isinstance(ty, jtypes.ClassType) and ty.is_builtin("staticmethod"):
67
+ node.is_static = True
68
+ break
69
+
70
+ def exit_import(self, node: uni.Import) -> None:
71
+ """Exit an import node."""
72
+ if node.from_loc:
73
+ for item in node.items:
74
+ if isinstance(item, uni.ModuleItem):
75
+ self.evaluator.get_type_of_module_item(item)
76
+
121
77
  def exit_assignment(self, node: uni.Assignment) -> None:
122
78
  """Pyright: Checker.visitAssignment(node: AssignmentNode): boolean."""
123
79
  # TODO: In pyright this logic is present at evaluateTypesForAssignmentStatement