jaclang 0.7.27__py3-none-any.whl → 0.7.30__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 (56) hide show
  1. jaclang/cli/cli.py +3 -0
  2. jaclang/compiler/__init__.py +1 -1
  3. jaclang/compiler/absyntree.py +30 -5
  4. jaclang/compiler/compile.py +1 -1
  5. jaclang/compiler/constant.py +0 -1
  6. jaclang/compiler/jac.lark +1 -5
  7. jaclang/compiler/parser.py +2 -10
  8. jaclang/compiler/passes/main/__init__.py +1 -1
  9. jaclang/compiler/passes/main/access_modifier_pass.py +1 -1
  10. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +62 -33
  11. jaclang/compiler/passes/main/import_pass.py +285 -64
  12. jaclang/compiler/passes/main/inheritance_pass.py +103 -0
  13. jaclang/compiler/passes/main/py_collect_dep_pass.py +5 -5
  14. jaclang/compiler/passes/main/pyast_gen_pass.py +0 -19
  15. jaclang/compiler/passes/main/pyast_load_pass.py +1 -1
  16. jaclang/compiler/passes/main/schedules.py +2 -0
  17. jaclang/compiler/passes/main/sym_tab_build_pass.py +17 -0
  18. jaclang/compiler/passes/main/tests/fixtures/data_spatial_types.jac +130 -0
  19. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -3
  20. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.pyi +3 -3
  21. jaclang/compiler/passes/main/tests/test_import_pass.py +16 -17
  22. jaclang/compiler/passes/main/tests/test_type_check_pass.py +24 -0
  23. jaclang/compiler/passes/main/type_check_pass.py +3 -2
  24. jaclang/compiler/passes/tool/jac_formatter_pass.py +0 -1
  25. jaclang/compiler/py_info.py +22 -0
  26. jaclang/compiler/symtable.py +9 -2
  27. jaclang/compiler/tests/test_importer.py +45 -1
  28. jaclang/langserve/tests/test_server.py +2 -2
  29. jaclang/plugin/default.py +86 -62
  30. jaclang/plugin/feature.py +2 -5
  31. jaclang/plugin/spec.py +1 -6
  32. jaclang/runtimelib/architype.py +20 -16
  33. jaclang/runtimelib/importer.py +26 -3
  34. jaclang/runtimelib/machine.py +2 -2
  35. jaclang/runtimelib/test.py +59 -4
  36. jaclang/runtimelib/utils.py +15 -0
  37. jaclang/settings.py +3 -0
  38. jaclang/tests/fixtures/base_class1.jac +11 -0
  39. jaclang/tests/fixtures/base_class2.jac +11 -0
  40. jaclang/tests/fixtures/import_all.jac +7 -0
  41. jaclang/tests/fixtures/import_all_py.py +8 -0
  42. jaclang/tests/fixtures/jactest_imported.jac +6 -0
  43. jaclang/tests/fixtures/jactest_main.jac +22 -0
  44. jaclang/tests/fixtures/multi_dim_array_split.jac +2 -6
  45. jaclang/tests/fixtures/test_py.py +12 -0
  46. jaclang/tests/fixtures/visit_sequence.jac +50 -0
  47. jaclang/tests/test_cli.py +83 -1
  48. jaclang/tests/test_language.py +24 -9
  49. jaclang/utils/helpers.py +9 -1
  50. jaclang/utils/test.py +2 -2
  51. jaclang/utils/tests/test_lang_tools.py +4 -2
  52. jaclang/utils/treeprinter.py +6 -3
  53. {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/METADATA +3 -3
  54. {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/RECORD +56 -45
  55. {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/WHEEL +1 -1
  56. {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/entry_points.txt +0 -0
jaclang/plugin/spec.py CHANGED
@@ -345,6 +345,7 @@ class JacFeatureSpec(
345
345
  @hookspec(firstresult=True)
346
346
  def run_test(
347
347
  filepath: str,
348
+ func_name: Optional[str],
348
349
  filter: Optional[str],
349
350
  xit: bool,
350
351
  maxfail: Optional[int],
@@ -354,12 +355,6 @@ class JacFeatureSpec(
354
355
  """Run the test suite in the specified .jac file."""
355
356
  raise NotImplementedError
356
357
 
357
- @staticmethod
358
- @hookspec(firstresult=True)
359
- def elvis(op1: Optional[T], op2: T) -> T:
360
- """Jac's elvis operator feature."""
361
- raise NotImplementedError
362
-
363
358
  @staticmethod
364
359
  @hookspec(firstresult=True)
365
360
  def has_instance_default(gen_func: Callable[[], T]) -> T:
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import inspect
6
6
  from dataclasses import asdict, dataclass, field, fields, is_dataclass
7
7
  from enum import IntEnum
8
+ from functools import cached_property
8
9
  from logging import getLogger
9
10
  from pickle import dumps
10
11
  from types import UnionType
@@ -43,9 +44,9 @@ class Access:
43
44
 
44
45
  anchors: dict[str, AccessLevel] = field(default_factory=dict)
45
46
 
46
- def check(self, anchor: str) -> AccessLevel:
47
+ def check(self, anchor: str) -> AccessLevel | None:
47
48
  """Validate access."""
48
- return self.anchors.get(anchor, AccessLevel.NO_ACCESS)
49
+ return self.anchors.get(anchor)
49
50
 
50
51
 
51
52
  @dataclass
@@ -220,9 +221,9 @@ class WalkerAnchor(Anchor):
220
221
  """Walker Anchor."""
221
222
 
222
223
  architype: WalkerArchitype
223
- path: list[Anchor] = field(default_factory=list)
224
- next: list[Anchor] = field(default_factory=list)
225
- ignores: list[Anchor] = field(default_factory=list)
224
+ path: list[NodeAnchor] = field(default_factory=list)
225
+ next: list[NodeAnchor] = field(default_factory=list)
226
+ ignores: list[NodeAnchor] = field(default_factory=list)
226
227
  disengaged: bool = False
227
228
 
228
229
 
@@ -311,17 +312,20 @@ class DSFunc:
311
312
  name: str
312
313
  func: Callable[[Any, Any], Any] | None = None
313
314
 
315
+ @cached_property
316
+ def trigger(self) -> type | UnionType | tuple[type | UnionType, ...] | None:
317
+ """Get function parameter annotations."""
318
+ t = (
319
+ (
320
+ inspect.signature(self.func, eval_str=True)
321
+ .parameters["_jac_here_"]
322
+ .annotation
323
+ )
324
+ if self.func
325
+ else None
326
+ )
327
+ return None if t is inspect._empty else t
328
+
314
329
  def resolve(self, cls: type) -> None:
315
330
  """Resolve the function."""
316
331
  self.func = getattr(cls, self.name)
317
-
318
- def get_funcparam_annotations(
319
- self, func: Callable[[Any, Any], Any] | None
320
- ) -> type | UnionType | tuple[type | UnionType, ...] | None:
321
- """Get function parameter annotations."""
322
- if not func:
323
- return None
324
- annotation = (
325
- inspect.signature(func, eval_str=True).parameters["_jac_here_"].annotation
326
- )
327
- return annotation if annotation != inspect._empty else None
@@ -158,9 +158,6 @@ class ImportReturn:
158
158
  return getattr(new_module, name, new_module)
159
159
  except ImportError as e:
160
160
  logger.error(dump_traceback(e))
161
- # logger.error(
162
- # f"Failed to load {name} from {jac_file_path} in {module.__name__}: {str(e)}"
163
- # )
164
161
  return None
165
162
 
166
163
 
@@ -319,6 +316,32 @@ class JacImporter(Importer):
319
316
  """Run the import process for Jac modules."""
320
317
  unique_loaded_items: list[types.ModuleType] = []
321
318
  module = None
319
+ # Gather all possible search paths
320
+ jacpaths = os.environ.get("JACPATH", "")
321
+ search_paths = [spec.caller_dir]
322
+ if jacpaths:
323
+ for p in jacpaths.split(os.pathsep):
324
+ p = p.strip()
325
+ if p and p not in search_paths:
326
+ search_paths.append(p)
327
+
328
+ # Attempt to locate the module file or directory
329
+ found_path = None
330
+ target_path_components = spec.target.split(".")
331
+ for search_path in search_paths:
332
+ candidate = os.path.join(search_path, "/".join(target_path_components))
333
+ # Check if the candidate is a directory or a .jac file
334
+ if (os.path.isdir(candidate)) or (os.path.isfile(candidate + ".jac")):
335
+ found_path = candidate
336
+ break
337
+
338
+ # If a suitable path was found, update spec.full_target; otherwise, raise an error
339
+ if found_path:
340
+ spec.full_target = os.path.abspath(found_path)
341
+ else:
342
+ raise ImportError(
343
+ f"Unable to locate module '{spec.target}' in {search_paths}"
344
+ )
322
345
  if os.path.isfile(spec.full_target + ".jac"):
323
346
  module_name = self.get_sys_mod_name(spec.full_target + ".jac")
324
347
  module_name = spec.override_name if spec.override_name else module_name
@@ -38,6 +38,7 @@ class JacMachine:
38
38
  self.loaded_modules: dict[str, types.ModuleType] = {}
39
39
  if not base_path:
40
40
  base_path = os.getcwd()
41
+ # Ensure the base_path is a list rather than a string
41
42
  self.base_path = base_path
42
43
  self.base_path_dir = (
43
44
  os.path.dirname(base_path)
@@ -306,12 +307,11 @@ class JacProgram:
306
307
  return marshal.load(f)
307
308
 
308
309
  result = compile_jac(full_target, cache_result=cachable)
309
- if result.errors_had or not result.ir.gen.py_bytecode:
310
+ if result.errors_had:
310
311
  for alrt in result.errors_had:
311
312
  # We're not logging here, it already gets logged as the errors were added to the errors_had list.
312
313
  # Regardless of the logging, this needs to be sent to the end user, so we'll printing it to stderr.
313
314
  logger.error(alrt.pretty_print())
314
- return None
315
315
  if result.ir.gen.py_bytecode is not None:
316
316
  return marshal.loads(result.ir.gen.py_bytecode)
317
317
  else:
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import unittest
6
+ from dataclasses import dataclass
6
7
  from typing import Callable, Optional
7
8
 
8
9
 
@@ -56,6 +57,16 @@ class JacTestCheck:
56
57
 
57
58
  test_case = unittest.TestCase()
58
59
  test_suite = unittest.TestSuite()
60
+
61
+ @dataclass
62
+ class TestSuite:
63
+ """Test Suite."""
64
+
65
+ test_case: unittest.FunctionTestCase
66
+ func_name: str
67
+
68
+ test_suite_path: dict[str, list[TestSuite]] = {}
69
+
59
70
  breaker = False
60
71
  failcount = 0
61
72
 
@@ -64,13 +75,45 @@ class JacTestCheck:
64
75
  """Clear the test suite."""
65
76
  JacTestCheck.test_case = unittest.TestCase()
66
77
  JacTestCheck.test_suite = unittest.TestSuite()
78
+ JacTestCheck.test_suite_path = {}
67
79
 
68
80
  @staticmethod
69
- def run_test(xit: bool, maxfail: int | None, verbose: bool) -> None:
81
+ def run_test(
82
+ xit: bool,
83
+ maxfail: int | None,
84
+ verbose: bool,
85
+ filepath: str | None,
86
+ func_name: str | None,
87
+ ) -> None:
70
88
  """Run the test suite."""
71
89
  verb = 2 if verbose else 1
90
+ test_suite = JacTestCheck.test_suite
91
+
92
+ if filepath and filepath.endswith(".test.jac"):
93
+ filepath = filepath[:-9]
94
+ elif filepath and filepath.endswith(".jac"):
95
+ filepath = filepath[:-4]
96
+
97
+ if filepath:
98
+ test_cases = JacTestCheck.test_suite_path.get(filepath)
99
+ if test_cases is not None:
100
+ test_suite = unittest.TestSuite()
101
+ for test_case in test_cases:
102
+ if func_name:
103
+ if test_case.func_name == func_name:
104
+ test_suite.addTest(test_case.test_case)
105
+ else:
106
+ test_suite.addTest(test_case.test_case)
107
+
108
+ elif func_name:
109
+ test_suite = unittest.TestSuite()
110
+ for test_cases in JacTestCheck.test_suite_path.values():
111
+ for test_case in test_cases:
112
+ if test_case.func_name == func_name:
113
+ test_suite.addTest(test_case.test_case)
114
+
72
115
  runner = JacTextTestRunner(max_failures=maxfail, failfast=xit, verbosity=verb)
73
- result = runner.run(JacTestCheck.test_suite)
116
+ result = runner.run(test_suite)
74
117
  if result.wasSuccessful():
75
118
  print("Passed successfully.")
76
119
  else:
@@ -81,9 +124,21 @@ class JacTestCheck:
81
124
  )
82
125
 
83
126
  @staticmethod
84
- def add_test(test_fun: Callable) -> None:
127
+ def add_test(filepath: str, func_name: str, test_func: Callable) -> None:
85
128
  """Create a new test."""
86
- JacTestCheck.test_suite.addTest(unittest.FunctionTestCase(test_fun))
129
+ if filepath and filepath.endswith(".test.jac"):
130
+ filepath = filepath[:-9]
131
+ elif filepath and filepath.endswith(".jac"):
132
+ filepath = filepath[:-4]
133
+
134
+ if filepath not in JacTestCheck.test_suite_path:
135
+ JacTestCheck.test_suite_path[filepath] = []
136
+
137
+ test_case = unittest.FunctionTestCase(test_func)
138
+ JacTestCheck.test_suite_path[filepath].append(
139
+ JacTestCheck.TestSuite(test_case=test_case, func_name=func_name)
140
+ )
141
+ JacTestCheck.test_suite.addTest(test_case)
87
142
 
88
143
  def __getattr__(self, name: str) -> object:
89
144
  """Make convenient check.Equal(...) etc."""
@@ -231,3 +231,18 @@ def is_instance(
231
231
  return isinstance(obj, target)
232
232
  case _:
233
233
  return False
234
+
235
+
236
+ def all_issubclass(
237
+ classes: type | UnionType | tuple[type | UnionType, ...], target: type
238
+ ) -> bool:
239
+ """Check if all classes is subclass of target type."""
240
+ match classes:
241
+ case type():
242
+ return issubclass(classes, target)
243
+ case UnionType():
244
+ return all((all_issubclass(cls, target) for cls in classes.__args__))
245
+ case tuple():
246
+ return all((all_issubclass(cls, target) for cls in classes))
247
+ case _:
248
+ return False
jaclang/settings.py CHANGED
@@ -16,10 +16,13 @@ class Settings:
16
16
  pass_timer: bool = False
17
17
  collect_py_dep_debug: bool = False
18
18
  print_py_raised_ast: bool = False
19
+ py_import_pass_debug: bool = False
20
+ inherit_pass_debug: bool = False
19
21
 
20
22
  # Compiler configuration
21
23
  disable_mtllm: bool = False
22
24
  ignore_test_annex: bool = False
25
+ allow_import_from: bool = False
23
26
 
24
27
  # Formatter configuration
25
28
  max_line_length: int = 88
@@ -0,0 +1,11 @@
1
+ import:py test_py;
2
+
3
+ class B :test_py.A: {}
4
+
5
+ with entry {
6
+ a = test_py.A();
7
+ b = B();
8
+
9
+ a.start();
10
+ b.start();
11
+ }
@@ -0,0 +1,11 @@
1
+ import:py from test_py { A }
2
+
3
+ class B :A: {}
4
+
5
+ with entry {
6
+ a = A();
7
+ b = B();
8
+
9
+ a.start();
10
+ b.start();
11
+ }
@@ -0,0 +1,7 @@
1
+ import:py import_all_py;
2
+
3
+ with entry {
4
+ print(import_all_py.custom_func(11));
5
+ print(import_all_py.pi);
6
+ print(import_all_py.floor(0.5));
7
+ }
@@ -0,0 +1,8 @@
1
+ """Module used for testing from x import * in jac."""
2
+
3
+ from math import * # noqa
4
+
5
+
6
+ def custom_func(x: int) -> str:
7
+ """Dummy custom function for testing purposes.""" # noqa
8
+ return str(x)
@@ -0,0 +1,6 @@
1
+
2
+
3
+ test this_should_not_run {
4
+ print("This test should not run after import.");
5
+ assert False;
6
+ }
@@ -0,0 +1,22 @@
1
+ import jactest_imported;
2
+
3
+ can fib(n: int) -> int {
4
+ if n <= 1 {
5
+ return n;
6
+ }
7
+ return fib(n - 1) + fib(n - 2);
8
+ }
9
+
10
+
11
+ test first_two {
12
+ print("Testing first 2 fibonacci numbers.");
13
+ assert fib(0) == 0;
14
+ assert fib(1) == 0;
15
+ }
16
+
17
+ test from_2_to_10 {
18
+ print("Testing fibonacci numbers from 2 to 10.");
19
+ for i in range(2, 10) {
20
+ assert fib(i) == fib(i - 1) + fib(i - 2);
21
+ }
22
+ }
@@ -1,13 +1,9 @@
1
- import:py numpy as np;
2
-
3
1
  with entry {
4
- arr = np.array(
5
- [[1, 2, 3, 4, 5],
2
+ arr = [[1, 2, 3, 4, 5],
6
3
  [6, 7, 8, 9, 10],
7
4
  [11, 12, 13, 14, 15],
8
5
  [16, 17, 18, 19, 20],
9
- [21, 22, 23, 24, 25]]
10
- );
6
+ [21, 22, 23, 24, 25]];
11
7
 
12
8
  print('Original Array:');
13
9
  print(arr);
@@ -0,0 +1,12 @@
1
+ """Test file for subclass issue."""
2
+
3
+ p = 5
4
+ g = 6
5
+
6
+
7
+ class A:
8
+ """Dummy class to test the base class issue."""
9
+
10
+ def start(self) -> int:
11
+ """Return 0."""
12
+ return 0
@@ -0,0 +1,50 @@
1
+ node Node {
2
+ has val: str;
3
+
4
+ can entry1 with entry {
5
+ print(f"{self.val}-2");
6
+ }
7
+
8
+ can entry2 with Walker entry {
9
+ print(f"{self.val}-3");
10
+ }
11
+
12
+ can exit1 with Walker exit {
13
+ print(f"{self.val}-4");
14
+ }
15
+
16
+ can exit2 with exit {
17
+ print(f"{self.val}-5");
18
+ }
19
+ }
20
+
21
+ walker Walker {
22
+ can entry1 with entry {
23
+ print("walker entry");
24
+ }
25
+
26
+ can entry2 with `root entry {
27
+ print("walker enter to root");
28
+ visit [-->];
29
+ }
30
+
31
+ can entry3 with Node entry {
32
+ print(f"{here.val}-1");
33
+ }
34
+
35
+ can exit1 with Node exit {
36
+ print(f"{here.val}-6");
37
+ }
38
+
39
+ can exit2 with exit {
40
+ print("walker exit");
41
+ }
42
+ }
43
+
44
+ with entry{
45
+ root ++> Node(val = "a");
46
+ root ++> Node(val = "b");
47
+ root ++> Node(val = "c");
48
+
49
+ Walker() spawn root;
50
+ }
jaclang/tests/test_cli.py CHANGED
@@ -168,7 +168,7 @@ class JacCliTests(TestCase):
168
168
  cli.tool("ir", ["ast", f"{self.fixture_abs_path('import.jac')}"])
169
169
 
170
170
  sys.stdout = sys.__stdout__
171
- stdout_value = captured_output.getvalue()
171
+ stdout_value = captured_output.getvalue().replace("\\", "/")
172
172
  self.assertRegex(
173
173
  stdout_value,
174
174
  r"1\:11 \- 1\:13.*ModulePath - os - abs_path\:.*typeshed/stdlib/os/__init__.pyi",
@@ -233,6 +233,67 @@ class JacCliTests(TestCase):
233
233
  r"13\:12 \- 13\:18.*Name - append - .*SymbolPath: builtins_test.builtins.list.append",
234
234
  )
235
235
 
236
+ def test_import_all(self) -> None:
237
+ """Testing for print AstTool."""
238
+ from jaclang.settings import settings
239
+
240
+ settings.ast_symbol_info_detailed = True
241
+ captured_output = io.StringIO()
242
+ sys.stdout = captured_output
243
+
244
+ cli.tool("ir", ["ast", f"{self.fixture_abs_path('import_all.jac')}"])
245
+
246
+ sys.stdout = sys.__stdout__
247
+ stdout_value = captured_output.getvalue()
248
+ settings.ast_symbol_info_detailed = False
249
+
250
+ self.assertRegex(
251
+ stdout_value,
252
+ r"6\:25 - 6\:30.*Name - floor -.*SymbolPath: import_all.import_all_py.floor",
253
+ )
254
+ self.assertRegex(
255
+ stdout_value,
256
+ r"5\:25 - 5\:27.*Name - pi -.*SymbolPath: import_all.import_all_py.pi",
257
+ )
258
+
259
+ def test_sub_class_symbol_table_fix_1(self) -> None:
260
+ """Testing for print AstTool."""
261
+ from jaclang.settings import settings
262
+
263
+ settings.ast_symbol_info_detailed = True
264
+ captured_output = io.StringIO()
265
+ sys.stdout = captured_output
266
+
267
+ cli.tool("ir", ["ast", f"{self.fixture_abs_path('base_class1.jac')}"])
268
+
269
+ sys.stdout = sys.__stdout__
270
+ stdout_value = captured_output.getvalue()
271
+ settings.ast_symbol_info_detailed = False
272
+
273
+ self.assertRegex(
274
+ stdout_value,
275
+ r"10:7 - 10:12.*Name - start - Type.*SymbolPath: base_class1.B.start",
276
+ )
277
+
278
+ def test_sub_class_symbol_table_fix_2(self) -> None:
279
+ """Testing for print AstTool."""
280
+ from jaclang.settings import settings
281
+
282
+ settings.ast_symbol_info_detailed = True
283
+ captured_output = io.StringIO()
284
+ sys.stdout = captured_output
285
+
286
+ cli.tool("ir", ["ast", f"{self.fixture_abs_path('base_class2.jac')}"])
287
+
288
+ sys.stdout = sys.__stdout__
289
+ stdout_value = captured_output.getvalue()
290
+ settings.ast_symbol_info_detailed = False
291
+
292
+ self.assertRegex(
293
+ stdout_value,
294
+ r"10:7 - 10:12.*Name - start - Type.*SymbolPath: base_class2.B.start",
295
+ )
296
+
236
297
  def test_expr_types(self) -> None:
237
298
  """Testing for print AstTool."""
238
299
  captured_output = io.StringIO()
@@ -393,6 +454,27 @@ class JacCliTests(TestCase):
393
454
  self.assertIn("...F", stderr)
394
455
  self.assertIn("F.F", stderr)
395
456
 
457
+ def test_run_specific_test_only(self) -> None:
458
+ """Test a specific test case."""
459
+ process = subprocess.Popen(
460
+ [
461
+ "jac",
462
+ "test",
463
+ "-t",
464
+ "from_2_to_10",
465
+ self.fixture_abs_path("jactest_main.jac"),
466
+ ],
467
+ stdin=subprocess.PIPE,
468
+ stdout=subprocess.PIPE,
469
+ stderr=subprocess.PIPE,
470
+ text=True,
471
+ )
472
+ stdout, stderr = process.communicate()
473
+ self.assertIn("Ran 1 test", stderr)
474
+ self.assertIn("Testing fibonacci numbers from 2 to 10.", stdout)
475
+ self.assertNotIn("Testing first 2 fibonacci numbers.", stdout)
476
+ self.assertNotIn("This test should not run after import.", stdout)
477
+
396
478
  def test_graph_coverage(self) -> None:
397
479
  """Test for coverage of graph cmd."""
398
480
  graph_params = set(inspect.signature(cli.dot).parameters.keys())
@@ -118,9 +118,9 @@ class JacLanguageTests(TestCase):
118
118
  stdout_value = captured_output.getvalue()
119
119
 
120
120
  expected_outputs = [
121
- "+-- AtomTrailer - Type: numpy.ndarray[Any, numpy.dtype[Any]]",
122
- " +-- Name - arr - Type: numpy.ndarray[Any, numpy.dtype[Any]], SymbolTable: None",
123
- " +-- IndexSlice - [IndexSlice] - Type: builtins.slice, SymbolTable: None",
121
+ "+-- AtomTrailer - Type: builtins.list[builtins.int]",
122
+ " +-- Name - arr - Type: builtins.list[builtins.list[builtins.int]], SymbolTable: list",
123
+ " +-- IndexSlice - [IndexSlice] - Type: builtins.list[builtins.list[builtins.int]], SymbolTable: None",
124
124
  " +-- Token - [,",
125
125
  " +-- Int - 1 - Type: Literal[1]?, SymbolTable: None",
126
126
  " +-- Token - :,",
@@ -548,7 +548,7 @@ class JacLanguageTests(TestCase):
548
548
  return f"Error While Jac to Py AST conversion: {e}"
549
549
 
550
550
  ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
551
- self.assertEqual(len(ir.get_all_sub_nodes(ast.Architype)), 7)
551
+ self.assertEqual(len(ir.get_all_sub_nodes(ast.Architype)), 21)
552
552
  captured_output = io.StringIO()
553
553
  sys.stdout = captured_output
554
554
  jac_import("needs_import_1", base_path=self.fixture_abs_path("./"))
@@ -611,7 +611,7 @@ class JacLanguageTests(TestCase):
611
611
 
612
612
  ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
613
613
  self.assertEqual(
614
- len(ir.get_all_sub_nodes(ast.Architype)), 8
614
+ len(ir.get_all_sub_nodes(ast.Architype)), 27
615
615
  ) # Because of the Architype from math
616
616
  captured_output = io.StringIO()
617
617
  sys.stdout = captured_output
@@ -665,7 +665,7 @@ class JacLanguageTests(TestCase):
665
665
 
666
666
  ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
667
667
  self.assertEqual(
668
- len(ir.get_all_sub_nodes(ast.Architype)), 38
668
+ len(ir.get_all_sub_nodes(ast.Architype)), 75
669
669
  ) # Because of the Architype from other imports
670
670
  captured_output = io.StringIO()
671
671
  sys.stdout = captured_output
@@ -873,7 +873,7 @@ class JacLanguageTests(TestCase):
873
873
  ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
874
874
  jac_ast = ir.pp()
875
875
  self.assertIn(" | +-- String - 'Loop completed normally{}'", jac_ast)
876
- self.assertEqual(len(ir.get_all_sub_nodes(ast.SubNodeList)), 269)
876
+ self.assertEqual(len(ir.get_all_sub_nodes(ast.SubNodeList)), 586)
877
877
  captured_output = io.StringIO()
878
878
  sys.stdout = captured_output
879
879
  jac_import("deep_convert", base_path=self.fixture_abs_path("./"))
@@ -1230,5 +1230,20 @@ class JacLanguageTests(TestCase):
1230
1230
  jac_import("architype_def_bug", base_path=self.fixture_abs_path("./"))
1231
1231
  sys.stdout = sys.__stdout__
1232
1232
  stdout_value = captured_output.getvalue().split("\n")
1233
- self.assertIn("MyNode", stdout_value[0])
1234
- self.assertIn("MyWalker", stdout_value[1])
1233
+ self.assertIn("MyWalker", stdout_value[0])
1234
+ self.assertIn("MyNode", stdout_value[1])
1235
+
1236
+ def test_visit_sequence(self) -> None:
1237
+ """Test conn assign on edges."""
1238
+ captured_output = io.StringIO()
1239
+ sys.stdout = captured_output
1240
+ jac_import("visit_sequence", base_path=self.fixture_abs_path("./"))
1241
+ sys.stdout = sys.__stdout__
1242
+ self.assertEqual(
1243
+ "walker entry\nwalker enter to root\n"
1244
+ "a-1\na-2\na-3\na-4\na-5\na-6\n"
1245
+ "b-1\nb-2\nb-3\nb-4\nb-5\nb-6\n"
1246
+ "c-1\nc-2\nc-3\nc-4\nc-5\nc-6\n"
1247
+ "walker exit\n",
1248
+ captured_output.getvalue(),
1249
+ )
jaclang/utils/helpers.py CHANGED
@@ -165,7 +165,15 @@ def dump_traceback(e: Exception) -> str:
165
165
  (frame.lineno is not None) and frame.line and frame.line.strip() != ""
166
166
  ):
167
167
 
168
- line_o = frame._original_line.rstrip() # type: ignore [attr-defined]
168
+ # Note: This is CPython internals we're trying to get since python doesn't provide
169
+ # the frames original line but the stripped version so we had to do this.
170
+ line_o = frame.line # Fallback line.
171
+ if hasattr(frame, "_original_line"):
172
+ line_o = frame._original_line.rstrip() # type: ignore [attr-defined]
173
+ elif hasattr(frame, "_original_lines"):
174
+ # https://github.com/python/cpython/issues/106922
175
+ line_o = frame._original_lines.split("\n")[0].rstrip() # type: ignore [attr-defined]
176
+
169
177
  if frame.colno is not None and frame.end_colno is not None:
170
178
  off_start = byte_offset_to_char_offset(line_o, frame.colno) - 1
171
179
  off_end = byte_offset_to_char_offset(line_o, frame.end_colno) - 1
jaclang/utils/test.py CHANGED
@@ -41,12 +41,12 @@ class TestCase(_TestCase):
41
41
  raise ValueError("Unable to determine the file of the module.")
42
42
  fixture_src = module.__file__
43
43
  fixture_path = os.path.join(os.path.dirname(fixture_src), "fixtures", fixture)
44
- with open(fixture_path, "r") as f:
44
+ with open(fixture_path, "r", encoding="utf-8") as f:
45
45
  return f.read()
46
46
 
47
47
  def file_to_str(self, file_path: str) -> str:
48
48
  """Load fixture from fixtures directory."""
49
- with open(file_path, "r") as f:
49
+ with open(file_path, "r", encoding="utf-8") as f:
50
50
  return f.read()
51
51
 
52
52
  def fixture_abs_path(self, fixture: str) -> str:
@@ -107,8 +107,10 @@ class JacFormatPassTests(TestCase):
107
107
 
108
108
  def test_sym_sym_dot(self) -> None:
109
109
  """Testing for sym, sym. AstTool."""
110
- jac_file = os.path.join(
111
- os.path.dirname(jaclang.__file__), "../examples/reference/atom.jac"
110
+ jac_file = os.path.normpath(
111
+ os.path.join(
112
+ os.path.dirname(jaclang.__file__), "../examples/reference/atom.jac"
113
+ )
112
114
  )
113
115
  out = AstTool().ir(["sym", jac_file])
114
116
  self.assertNotIn(