jaclang 0.7.23__py3-none-any.whl → 0.7.26__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.
- jaclang/cli/cli.py +46 -29
- jaclang/compiler/__init__.py +2 -2
- jaclang/compiler/absyntree.py +114 -66
- jaclang/compiler/codeloc.py +7 -2
- jaclang/compiler/compile.py +10 -3
- jaclang/compiler/jac.lark +4 -1
- jaclang/compiler/parser.py +63 -43
- jaclang/compiler/passes/ir_pass.py +2 -2
- jaclang/compiler/passes/main/def_impl_match_pass.py +83 -0
- jaclang/compiler/passes/main/def_use_pass.py +1 -2
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +146 -123
- jaclang/compiler/passes/main/import_pass.py +6 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +46 -20
- jaclang/compiler/passes/main/pyast_load_pass.py +56 -41
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -7
- jaclang/compiler/passes/main/registry_pass.py +3 -12
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -2
- jaclang/compiler/passes/main/tests/fixtures/defn_decl_mismatch.jac +19 -0
- jaclang/compiler/passes/main/tests/fixtures/fstrings.jac +2 -0
- jaclang/compiler/passes/main/tests/fixtures/uninitialized_hasvars.jac +26 -0
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +66 -0
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +3 -3
- jaclang/compiler/passes/main/tests/test_registry_pass.py +2 -10
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +3 -3
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
- jaclang/compiler/passes/transform.py +27 -3
- jaclang/compiler/passes/utils/mypy_ast_build.py +246 -26
- jaclang/compiler/symtable.py +6 -0
- jaclang/compiler/tests/test_importer.py +2 -2
- jaclang/compiler/tests/test_parser.py +7 -1
- jaclang/langserve/engine.py +14 -12
- jaclang/langserve/server.py +7 -2
- jaclang/langserve/tests/test_server.py +1 -1
- jaclang/langserve/utils.py +17 -3
- jaclang/plugin/default.py +80 -43
- jaclang/plugin/feature.py +12 -2
- jaclang/plugin/plugin.md +471 -0
- jaclang/plugin/spec.py +14 -1
- jaclang/plugin/tests/fixtures/graph_purger.jac +101 -0
- jaclang/plugin/tests/fixtures/other_root_access.jac +9 -0
- jaclang/plugin/tests/test_jaseci.py +126 -6
- jaclang/runtimelib/architype.py +12 -1
- jaclang/runtimelib/context.py +2 -0
- jaclang/runtimelib/importer.py +7 -2
- jaclang/runtimelib/machine.py +21 -6
- jaclang/runtimelib/memory.py +5 -1
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/architype_def_bug.jac +17 -0
- jaclang/tests/fixtures/builtin_dotgen.jac +6 -6
- jaclang/tests/fixtures/decl_defn_param_name.jac +19 -0
- jaclang/tests/fixtures/enum_inside_archtype.jac +16 -11
- jaclang/tests/fixtures/expr_type.jac +54 -0
- jaclang/tests/fixtures/glob_multivar_statement.jac +15 -0
- jaclang/tests/fixtures/multi_dim_array_split.jac +19 -0
- jaclang/tests/fixtures/registry.jac +20 -8
- jaclang/tests/foo/__init__.jac +0 -0
- jaclang/tests/main.jac +2 -0
- jaclang/tests/test_cli.py +86 -4
- jaclang/tests/test_language.py +104 -27
- jaclang/utils/helpers.py +92 -14
- jaclang/utils/lang_tools.py +6 -2
- jaclang/utils/treeprinter.py +4 -2
- {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/METADATA +2 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/RECORD +68 -57
- {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/WHEEL +1 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/entry_points.txt +0 -0
jaclang/tests/test_cli.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Test Jac cli module."""
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
import inspect
|
|
4
5
|
import io
|
|
5
6
|
import os
|
|
@@ -55,10 +56,8 @@ class JacCliTests(TestCase):
|
|
|
55
56
|
sys.stdout = captured_output
|
|
56
57
|
sys.stderr = captured_output
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
with contextlib.suppress(Exception):
|
|
59
60
|
cli.run(self.fixture_abs_path("err_runtime.jac"))
|
|
60
|
-
except Exception as e:
|
|
61
|
-
print(f"Error: {e}")
|
|
62
61
|
|
|
63
62
|
sys.stdout = sys.__stdout__
|
|
64
63
|
sys.stderr = sys.__stderr__
|
|
@@ -71,7 +70,6 @@ class JacCliTests(TestCase):
|
|
|
71
70
|
" at foo() ",
|
|
72
71
|
" at <module> ",
|
|
73
72
|
)
|
|
74
|
-
|
|
75
73
|
logger_capture = "\n".join([rec.message for rec in self.caplog.records])
|
|
76
74
|
for exp in expected_stdout_values:
|
|
77
75
|
self.assertIn(exp, logger_capture)
|
|
@@ -96,6 +94,24 @@ class JacCliTests(TestCase):
|
|
|
96
94
|
path_to_file = self.fixture_abs_path("err.impl.jac")
|
|
97
95
|
self.assertIn(f'"{path_to_file}", line 2', stdout_value)
|
|
98
96
|
|
|
97
|
+
def test_param_name_diff(self) -> None:
|
|
98
|
+
"""Test when parameter name from definitinon and declaration are mismatched."""
|
|
99
|
+
captured_output = io.StringIO()
|
|
100
|
+
sys.stdout = captured_output
|
|
101
|
+
sys.stderr = captured_output
|
|
102
|
+
with contextlib.suppress(Exception):
|
|
103
|
+
cli.run(self.fixture_abs_path("decl_defn_param_name.jac"))
|
|
104
|
+
sys.stdout = sys.__stdout__
|
|
105
|
+
sys.stderr = sys.__stderr__
|
|
106
|
+
|
|
107
|
+
expected_stdout_values = (
|
|
108
|
+
"short_name = 42",
|
|
109
|
+
"p1 = 64 , p2 = foobar",
|
|
110
|
+
)
|
|
111
|
+
output = captured_output.getvalue()
|
|
112
|
+
for exp in expected_stdout_values:
|
|
113
|
+
self.assertIn(exp, output)
|
|
114
|
+
|
|
99
115
|
def test_jac_test_err(self) -> None:
|
|
100
116
|
"""Basic test for pass."""
|
|
101
117
|
captured_output = io.StringIO()
|
|
@@ -217,6 +233,42 @@ class JacCliTests(TestCase):
|
|
|
217
233
|
r"13\:12 \- 13\:18.*Name - append - .*SymbolPath: builtins_test.builtins.list.append",
|
|
218
234
|
)
|
|
219
235
|
|
|
236
|
+
def test_expr_types(self) -> None:
|
|
237
|
+
"""Testing for print AstTool."""
|
|
238
|
+
captured_output = io.StringIO()
|
|
239
|
+
sys.stdout = captured_output
|
|
240
|
+
|
|
241
|
+
cli.tool("ir", ["ast", f"{self.fixture_abs_path('expr_type.jac')}"])
|
|
242
|
+
|
|
243
|
+
sys.stdout = sys.__stdout__
|
|
244
|
+
stdout_value = captured_output.getvalue()
|
|
245
|
+
|
|
246
|
+
self.assertRegex(
|
|
247
|
+
stdout_value, r"4\:9 \- 4\:14.*BinaryExpr \- Type\: builtins.int"
|
|
248
|
+
)
|
|
249
|
+
self.assertRegex(
|
|
250
|
+
stdout_value, r"7\:9 \- 7\:17.*FuncCall \- Type\: builtins.float"
|
|
251
|
+
)
|
|
252
|
+
self.assertRegex(
|
|
253
|
+
stdout_value, r"9\:6 \- 9\:11.*CompareExpr \- Type\: builtins.bool"
|
|
254
|
+
)
|
|
255
|
+
self.assertRegex(
|
|
256
|
+
stdout_value, r"10\:6 - 10\:15.*BinaryExpr \- Type\: builtins.str"
|
|
257
|
+
)
|
|
258
|
+
self.assertRegex(
|
|
259
|
+
stdout_value, r"11\:5 \- 11\:13.*AtomTrailer \- Type\: builtins.int"
|
|
260
|
+
)
|
|
261
|
+
self.assertRegex(
|
|
262
|
+
stdout_value, r"12\:5 \- 12\:14.*UnaryExpr \- Type\: builtins.bool"
|
|
263
|
+
)
|
|
264
|
+
self.assertRegex(
|
|
265
|
+
stdout_value, r"13\:5 \- 13\:25.*IfElseExpr \- Type\: Literal\['a']\?"
|
|
266
|
+
)
|
|
267
|
+
self.assertRegex(
|
|
268
|
+
stdout_value,
|
|
269
|
+
r"14\:5 \- 14\:27.*ListCompr - \[ListCompr] \- Type\: builtins.list\[builtins.int]",
|
|
270
|
+
)
|
|
271
|
+
|
|
220
272
|
def test_ast_dotgen(self) -> None:
|
|
221
273
|
"""Testing for print AstTool."""
|
|
222
274
|
captured_output = io.StringIO()
|
|
@@ -247,6 +299,8 @@ class JacCliTests(TestCase):
|
|
|
247
299
|
self.assertEqual(stdout_value.count("type_info.ServerWrapper"), 7)
|
|
248
300
|
self.assertEqual(stdout_value.count("builtins.int"), 3)
|
|
249
301
|
self.assertEqual(stdout_value.count("builtins.str"), 10)
|
|
302
|
+
self.assertIn("Literal['test_server']", stdout_value)
|
|
303
|
+
self.assertIn("Literal['1']", stdout_value)
|
|
250
304
|
|
|
251
305
|
def test_build_and_run(self) -> None:
|
|
252
306
|
"""Testing for print AstTool."""
|
|
@@ -368,3 +422,31 @@ class JacCliTests(TestCase):
|
|
|
368
422
|
sys.stdout = sys.__stdout__
|
|
369
423
|
stdout_value = captured_output.getvalue()
|
|
370
424
|
self.assertIn("can my_print(x: object) -> None", stdout_value)
|
|
425
|
+
|
|
426
|
+
def test_caching_issue(self) -> None:
|
|
427
|
+
"""Test for Caching Issue."""
|
|
428
|
+
test_file = self.fixture_abs_path("test_caching_issue.jac")
|
|
429
|
+
test_cases = [(10, True), (11, False)]
|
|
430
|
+
for x, is_passed in test_cases:
|
|
431
|
+
with open(test_file, "w") as f:
|
|
432
|
+
f.write(
|
|
433
|
+
f"""
|
|
434
|
+
test mytest{{
|
|
435
|
+
check 10 == {x};
|
|
436
|
+
}}
|
|
437
|
+
"""
|
|
438
|
+
)
|
|
439
|
+
process = subprocess.Popen(
|
|
440
|
+
["jac", "test", test_file],
|
|
441
|
+
stdout=subprocess.PIPE,
|
|
442
|
+
stderr=subprocess.PIPE,
|
|
443
|
+
text=True,
|
|
444
|
+
)
|
|
445
|
+
stdout, stderr = process.communicate()
|
|
446
|
+
if is_passed:
|
|
447
|
+
self.assertIn("Passed successfully.", stdout)
|
|
448
|
+
self.assertIn(".", stderr)
|
|
449
|
+
else:
|
|
450
|
+
self.assertNotIn("Passed successfully.", stdout)
|
|
451
|
+
self.assertIn("F", stderr)
|
|
452
|
+
os.remove(test_file)
|
jaclang/tests/test_language.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import io
|
|
4
4
|
import os
|
|
5
|
-
import pickle
|
|
6
5
|
import sys
|
|
7
6
|
import sysconfig
|
|
8
7
|
|
|
@@ -24,7 +23,7 @@ class JacLanguageTests(TestCase):
|
|
|
24
23
|
"""Set up test."""
|
|
25
24
|
SUPER_ROOT_ANCHOR.edges.clear()
|
|
26
25
|
JacMachine(self.fixture_abs_path("./")).attach_program(
|
|
27
|
-
JacProgram(mod_bundle=None, bytecode=None)
|
|
26
|
+
JacProgram(mod_bundle=None, bytecode=None, sem_ir=None)
|
|
28
27
|
)
|
|
29
28
|
return super().setUp()
|
|
30
29
|
|
|
@@ -104,6 +103,40 @@ class JacLanguageTests(TestCase):
|
|
|
104
103
|
"Too high!\nToo low!\nToo high!\nCongratulations! You guessed correctly.\n",
|
|
105
104
|
)
|
|
106
105
|
|
|
106
|
+
def test_multi_dim_arr_slice(self) -> None:
|
|
107
|
+
"""Parse micro jac file."""
|
|
108
|
+
captured_output = io.StringIO()
|
|
109
|
+
sys.stdout = captured_output
|
|
110
|
+
cli.tool(
|
|
111
|
+
"ir",
|
|
112
|
+
[
|
|
113
|
+
"ast",
|
|
114
|
+
self.fixture_abs_path("multi_dim_array_split.jac"),
|
|
115
|
+
],
|
|
116
|
+
)
|
|
117
|
+
sys.stdout = sys.__stdout__
|
|
118
|
+
stdout_value = captured_output.getvalue()
|
|
119
|
+
|
|
120
|
+
# print(arr[1:3, 1::2]);
|
|
121
|
+
expected_outputs = [
|
|
122
|
+
"+-- AtomTrailer - Type: Any",
|
|
123
|
+
" +-- Name - arr - Type: Any, SymbolTable: None",
|
|
124
|
+
" +-- IndexSlice - [IndexSlice] - Type: builtins.slice, SymbolTable: None",
|
|
125
|
+
" +-- Token - [,",
|
|
126
|
+
" +-- Int - 1 - Type: Literal[1]?, SymbolTable: None",
|
|
127
|
+
" +-- Token - :,",
|
|
128
|
+
" +-- Int - 3 - Type: Literal[3]?, SymbolTable: None",
|
|
129
|
+
" +-- Token - ,,",
|
|
130
|
+
" +-- Int - 1 - Type: Literal[1]?, SymbolTable: None",
|
|
131
|
+
" +-- Token - :,",
|
|
132
|
+
" +-- Token - :,",
|
|
133
|
+
" +-- Int - 2 - Type: Literal[2]?, SymbolTable: None",
|
|
134
|
+
" +-- Token - ],",
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
for expected in expected_outputs:
|
|
138
|
+
self.assertIn(expected, stdout_value)
|
|
139
|
+
|
|
107
140
|
def test_chandra_bugs(self) -> None:
|
|
108
141
|
"""Parse micro jac file."""
|
|
109
142
|
captured_output = io.StringIO()
|
|
@@ -209,8 +242,10 @@ class JacLanguageTests(TestCase):
|
|
|
209
242
|
"""Test semstring."""
|
|
210
243
|
captured_output = io.StringIO()
|
|
211
244
|
sys.stdout = captured_output
|
|
245
|
+
sys.stderr = captured_output
|
|
212
246
|
jac_import("semstr", base_path=self.fixture_abs_path("./"))
|
|
213
247
|
sys.stdout = sys.__stdout__
|
|
248
|
+
sys.stderr = sys.__stderr__
|
|
214
249
|
stdout_value = captured_output.getvalue()
|
|
215
250
|
self.assertNotIn("Error", stdout_value)
|
|
216
251
|
|
|
@@ -237,6 +272,7 @@ class JacLanguageTests(TestCase):
|
|
|
237
272
|
self.assertEqual(stdout_value.split("\n")[0], "11 13 12 12 11 12 12")
|
|
238
273
|
self.assertEqual(stdout_value.split("\n")[1], '12 12 """hello""" 18 18')
|
|
239
274
|
self.assertEqual(stdout_value.split("\n")[2], "11 12 11 12 11 18 23")
|
|
275
|
+
self.assertEqual(stdout_value.split("\n")[3], 'hello klkl"""')
|
|
240
276
|
|
|
241
277
|
def test_deep_imports(self) -> None:
|
|
242
278
|
"""Parse micro jac file."""
|
|
@@ -465,24 +501,22 @@ class JacLanguageTests(TestCase):
|
|
|
465
501
|
"""Test Jac registry feature."""
|
|
466
502
|
captured_output = io.StringIO()
|
|
467
503
|
sys.stdout = captured_output
|
|
504
|
+
sys.stderr = captured_output
|
|
468
505
|
jac_import("registry", base_path=self.fixture_abs_path("./"))
|
|
469
506
|
sys.stdout = sys.__stdout__
|
|
507
|
+
sys.stderr = sys.__stderr__
|
|
470
508
|
stdout_value = captured_output.getvalue()
|
|
471
509
|
self.assertNotIn("Error", stdout_value)
|
|
472
510
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
"rb",
|
|
478
|
-
) as f:
|
|
479
|
-
registry = pickle.load(f)
|
|
511
|
+
output_lines = stdout_value.strip().split("\n")
|
|
512
|
+
outputs = [
|
|
513
|
+
int(output_lines[i]) if i != 2 else output_lines[i] for i in range(4)
|
|
514
|
+
]
|
|
480
515
|
|
|
481
|
-
self.assertEqual(
|
|
482
|
-
self.assertEqual(
|
|
483
|
-
self.assertEqual(
|
|
484
|
-
|
|
485
|
-
self.assertEqual(len(sem_info.get_children(registry)), 2)
|
|
516
|
+
self.assertEqual(outputs[0], 9)
|
|
517
|
+
self.assertEqual(outputs[1], 2)
|
|
518
|
+
self.assertEqual(outputs[2], "Person")
|
|
519
|
+
self.assertEqual(outputs[3], 2)
|
|
486
520
|
|
|
487
521
|
def test_enum_inside_arch(self) -> None:
|
|
488
522
|
"""Test Enum as member stmt."""
|
|
@@ -491,7 +525,7 @@ class JacLanguageTests(TestCase):
|
|
|
491
525
|
jac_import("enum_inside_archtype", base_path=self.fixture_abs_path("./"))
|
|
492
526
|
sys.stdout = sys.__stdout__
|
|
493
527
|
stdout_value = captured_output.getvalue()
|
|
494
|
-
self.
|
|
528
|
+
self.assertIn("2 Accessing privileged Data", stdout_value)
|
|
495
529
|
|
|
496
530
|
def test_needs_import_1(self) -> None:
|
|
497
531
|
"""Test py ast to Jac ast conversion output."""
|
|
@@ -503,10 +537,13 @@ class JacLanguageTests(TestCase):
|
|
|
503
537
|
import jaclang.compiler.absyntree as ast
|
|
504
538
|
|
|
505
539
|
with open(file_name, "r") as f:
|
|
506
|
-
|
|
540
|
+
file_source = f.read()
|
|
541
|
+
parsed_ast = py_ast.parse(file_source)
|
|
507
542
|
try:
|
|
508
543
|
py_ast_build_pass = PyastBuildPass(
|
|
509
|
-
input_ir=ast.PythonModuleAst(
|
|
544
|
+
input_ir=ast.PythonModuleAst(
|
|
545
|
+
parsed_ast, orig_src=ast.JacSource(file_source, file_name)
|
|
546
|
+
),
|
|
510
547
|
)
|
|
511
548
|
except Exception as e:
|
|
512
549
|
return f"Error While Jac to Py AST conversion: {e}"
|
|
@@ -528,9 +565,11 @@ class JacLanguageTests(TestCase):
|
|
|
528
565
|
|
|
529
566
|
py_out_path = os.path.join(self.fixture_abs_path("./"), "pyfunc_1.py")
|
|
530
567
|
with open(py_out_path) as f:
|
|
568
|
+
file_source = f.read()
|
|
531
569
|
output = PyastBuildPass(
|
|
532
570
|
input_ir=ast.PythonModuleAst(
|
|
533
|
-
py_ast.parse(
|
|
571
|
+
py_ast.parse(file_source),
|
|
572
|
+
orig_src=ast.JacSource(file_source, py_out_path),
|
|
534
573
|
),
|
|
535
574
|
).ir.unparse()
|
|
536
575
|
# print(output)
|
|
@@ -559,10 +598,14 @@ class JacLanguageTests(TestCase):
|
|
|
559
598
|
import jaclang.compiler.absyntree as ast
|
|
560
599
|
|
|
561
600
|
with open(file_name, "r") as f:
|
|
562
|
-
|
|
601
|
+
file_source = f.read()
|
|
602
|
+
parsed_ast = py_ast.parse(file_source)
|
|
563
603
|
try:
|
|
564
604
|
py_ast_build_pass = PyastBuildPass(
|
|
565
|
-
input_ir=ast.PythonModuleAst(
|
|
605
|
+
input_ir=ast.PythonModuleAst(
|
|
606
|
+
parsed_ast,
|
|
607
|
+
orig_src=ast.JacSource(file_source, file_name),
|
|
608
|
+
),
|
|
566
609
|
)
|
|
567
610
|
except Exception as e:
|
|
568
611
|
return f"Error While Jac to Py AST conversion: {e}"
|
|
@@ -587,9 +630,11 @@ class JacLanguageTests(TestCase):
|
|
|
587
630
|
|
|
588
631
|
py_out_path = os.path.join(self.fixture_abs_path("./"), "pyfunc_2.py")
|
|
589
632
|
with open(py_out_path) as f:
|
|
633
|
+
file_source = f.read()
|
|
590
634
|
output = PyastBuildPass(
|
|
591
635
|
input_ir=ast.PythonModuleAst(
|
|
592
|
-
py_ast.parse(
|
|
636
|
+
py_ast.parse(file_source),
|
|
637
|
+
orig_src=ast.JacSource(file_source, py_out_path),
|
|
593
638
|
),
|
|
594
639
|
).ir.unparse()
|
|
595
640
|
self.assertIn("class X {\n with entry {\n\n a_b = 67;", output)
|
|
@@ -607,10 +652,14 @@ class JacLanguageTests(TestCase):
|
|
|
607
652
|
import jaclang.compiler.absyntree as ast
|
|
608
653
|
|
|
609
654
|
with open(file_name, "r") as f:
|
|
610
|
-
|
|
655
|
+
file_source = f.read()
|
|
656
|
+
parsed_ast = py_ast.parse(file_source)
|
|
611
657
|
try:
|
|
612
658
|
py_ast_build_pass = PyastBuildPass(
|
|
613
|
-
input_ir=ast.PythonModuleAst(
|
|
659
|
+
input_ir=ast.PythonModuleAst(
|
|
660
|
+
parsed_ast,
|
|
661
|
+
orig_src=ast.JacSource(file_source, file_name),
|
|
662
|
+
),
|
|
614
663
|
)
|
|
615
664
|
except Exception as e:
|
|
616
665
|
return f"Error While Jac to Py AST conversion: {e}"
|
|
@@ -634,9 +683,11 @@ class JacLanguageTests(TestCase):
|
|
|
634
683
|
|
|
635
684
|
py_out_path = os.path.join(self.fixture_abs_path("./"), "pyfunc_3.py")
|
|
636
685
|
with open(py_out_path) as f:
|
|
686
|
+
file_source = f.read()
|
|
637
687
|
output = PyastBuildPass(
|
|
638
688
|
input_ir=ast.PythonModuleAst(
|
|
639
|
-
py_ast.parse(
|
|
689
|
+
py_ast.parse(file_source),
|
|
690
|
+
orig_src=ast.JacSource(file_source, py_out_path),
|
|
640
691
|
),
|
|
641
692
|
).ir.unparse()
|
|
642
693
|
self.assertIn("if 0 <= x<= 5 {", output)
|
|
@@ -761,9 +812,11 @@ class JacLanguageTests(TestCase):
|
|
|
761
812
|
module_path + ".py",
|
|
762
813
|
)
|
|
763
814
|
with open(file_path) as f:
|
|
815
|
+
file_source = f.read()
|
|
764
816
|
jac_ast = PyastBuildPass(
|
|
765
817
|
input_ir=ast.PythonModuleAst(
|
|
766
|
-
py_ast.parse(
|
|
818
|
+
py_ast.parse(file_source),
|
|
819
|
+
orig_src=ast.JacSource(file_source, file_path),
|
|
767
820
|
)
|
|
768
821
|
)
|
|
769
822
|
settings.print_py_raised_ast = True
|
|
@@ -786,11 +839,13 @@ class JacLanguageTests(TestCase):
|
|
|
786
839
|
"""Test for access tags working."""
|
|
787
840
|
captured_output = io.StringIO()
|
|
788
841
|
sys.stdout = captured_output
|
|
842
|
+
sys.stderr = captured_output
|
|
789
843
|
cli.check(
|
|
790
844
|
self.fixture_abs_path("../../tests/fixtures/access_modifier.jac"),
|
|
791
845
|
print_errs=True,
|
|
792
846
|
)
|
|
793
847
|
sys.stdout = sys.__stdout__
|
|
848
|
+
sys.stderr = sys.__stderr__
|
|
794
849
|
stdout_value = captured_output.getvalue()
|
|
795
850
|
self.assertEqual(stdout_value.count("Invalid access"), 18)
|
|
796
851
|
|
|
@@ -808,10 +863,12 @@ class JacLanguageTests(TestCase):
|
|
|
808
863
|
parsed_ast = py_ast.parse(f.read())
|
|
809
864
|
try:
|
|
810
865
|
py_ast_build_pass = PyastBuildPass(
|
|
811
|
-
input_ir=ast.PythonModuleAst(
|
|
866
|
+
input_ir=ast.PythonModuleAst(
|
|
867
|
+
parsed_ast, orig_src=ast.JacSource(f.read(), file_name)
|
|
868
|
+
)
|
|
812
869
|
)
|
|
813
870
|
except Exception as e:
|
|
814
|
-
|
|
871
|
+
raise Exception(f"Error While Jac to Py AST conversion: {e}")
|
|
815
872
|
|
|
816
873
|
settings.print_py_raised_ast = True
|
|
817
874
|
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
@@ -1156,3 +1213,23 @@ class JacLanguageTests(TestCase):
|
|
|
1156
1213
|
sys.stdout = sys.__stdout__
|
|
1157
1214
|
stdout_value = captured_output.getvalue()
|
|
1158
1215
|
self.assertEqual("[MyNode(Name='End'), MyNode(Name='Middle')]\n", stdout_value)
|
|
1216
|
+
|
|
1217
|
+
def test_global_multivar(self) -> None:
|
|
1218
|
+
"""Test supporting multiple global variable in a statement."""
|
|
1219
|
+
captured_output = io.StringIO()
|
|
1220
|
+
sys.stdout = captured_output
|
|
1221
|
+
jac_import("glob_multivar_statement", base_path=self.fixture_abs_path("./"))
|
|
1222
|
+
sys.stdout = sys.__stdout__
|
|
1223
|
+
stdout_value = captured_output.getvalue().split("\n")
|
|
1224
|
+
self.assertIn("Hello World !", stdout_value[0])
|
|
1225
|
+
self.assertIn("Welcome to Jaseci!", stdout_value[1])
|
|
1226
|
+
|
|
1227
|
+
def test_architype_def(self) -> None:
|
|
1228
|
+
"""Test architype definition bug."""
|
|
1229
|
+
captured_output = io.StringIO()
|
|
1230
|
+
sys.stdout = captured_output
|
|
1231
|
+
jac_import("architype_def_bug", base_path=self.fixture_abs_path("./"))
|
|
1232
|
+
sys.stdout = sys.__stdout__
|
|
1233
|
+
stdout_value = captured_output.getvalue().split("\n")
|
|
1234
|
+
self.assertIn("MyNode", stdout_value[0])
|
|
1235
|
+
self.assertIn("MyWalker", stdout_value[1])
|
jaclang/utils/helpers.py
CHANGED
|
@@ -147,7 +147,7 @@ def dump_traceback(e: Exception) -> str:
|
|
|
147
147
|
return len(string.encode("utf-8")[:offset].decode("utf-8", errors="replace"))
|
|
148
148
|
|
|
149
149
|
tb = TracebackException(type(e), e, e.__traceback__, limit=None, compact=True)
|
|
150
|
-
trace_dump += f"Error: {str(e)}"
|
|
150
|
+
trace_dump += f"Error: {str(e)}\n"
|
|
151
151
|
|
|
152
152
|
# The first frame is the call the to the above `exec` function, not usefull to the enduser,
|
|
153
153
|
# and Make the most recent call first.
|
|
@@ -155,33 +155,111 @@ def dump_traceback(e: Exception) -> str:
|
|
|
155
155
|
tb.stack.reverse()
|
|
156
156
|
|
|
157
157
|
# FIXME: should be some settings, we should replace to ensure the anchors length match.
|
|
158
|
-
dump_tab_width =
|
|
158
|
+
dump_tab_width = 2
|
|
159
159
|
|
|
160
160
|
for idx, frame in enumerate(tb.stack):
|
|
161
161
|
func_signature = frame.name + ("()" if frame.name.isidentifier() else "")
|
|
162
162
|
|
|
163
163
|
# Pretty print the most recent call's location.
|
|
164
|
-
if idx == 0 and (
|
|
164
|
+
if idx == 0 and (
|
|
165
|
+
(frame.lineno is not None) and frame.line and frame.line.strip() != ""
|
|
166
|
+
):
|
|
167
|
+
|
|
165
168
|
line_o = frame._original_line.rstrip() # type: ignore [attr-defined]
|
|
166
|
-
line_s = frame.line.rstrip() if frame.line else ""
|
|
167
|
-
stripped_chars = len(line_o) - len(line_s)
|
|
168
|
-
trace_dump += f'\n{" " * (dump_tab_width * 2)}{line_s}'
|
|
169
169
|
if frame.colno is not None and frame.end_colno is not None:
|
|
170
|
-
off_start = byte_offset_to_char_offset(line_o, frame.colno)
|
|
171
|
-
off_end = byte_offset_to_char_offset(line_o, frame.end_colno)
|
|
172
|
-
|
|
173
|
-
#
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
off_start = byte_offset_to_char_offset(line_o, frame.colno) - 1
|
|
171
|
+
off_end = byte_offset_to_char_offset(line_o, frame.end_colno) - 1
|
|
172
|
+
|
|
173
|
+
# Get the source.
|
|
174
|
+
file_source = None
|
|
175
|
+
with open(frame.filename, "r") as file:
|
|
176
|
+
file_source = file.read()
|
|
177
|
+
|
|
178
|
+
# Get the source offset.
|
|
179
|
+
lines = file_source.split("\n")
|
|
180
|
+
for i in range(frame.lineno - 1):
|
|
181
|
+
off_start += len(lines[i]) + 1
|
|
182
|
+
off_end += len(lines[i]) + 1
|
|
183
|
+
|
|
184
|
+
trace_dump += pretty_print_source_location(
|
|
185
|
+
frame.filename, file_source, frame.lineno, off_start, off_end
|
|
176
186
|
)
|
|
177
187
|
|
|
178
|
-
trace_dump += f'\n{" " * (dump_tab_width * 2)}{anchors}'
|
|
179
|
-
|
|
180
188
|
trace_dump += f'\n{" " * dump_tab_width}at {func_signature} {frame.filename}:{frame.lineno}'
|
|
181
189
|
|
|
182
190
|
return trace_dump
|
|
183
191
|
|
|
184
192
|
|
|
193
|
+
# TODO: After implementing the TextRange (or simillar named) class to mark a text range
|
|
194
|
+
# refactor the parameter to accept an instace of that text range object.
|
|
195
|
+
def pretty_print_source_location(
|
|
196
|
+
file_path: str,
|
|
197
|
+
file_source: str,
|
|
198
|
+
error_line: int,
|
|
199
|
+
pos_start: int,
|
|
200
|
+
pos_end: int,
|
|
201
|
+
) -> str:
|
|
202
|
+
"""Pretty print internal method for the pretty_print method."""
|
|
203
|
+
# NOTE: The Line numbers and the column numbers are starts with 1.
|
|
204
|
+
# We print totally 5 lines (error line and above 2 and bellow 2).
|
|
205
|
+
|
|
206
|
+
# The width of the line number we'll be printing (more of a settings).
|
|
207
|
+
line_num_width: int = 5
|
|
208
|
+
|
|
209
|
+
idx: int = pos_start # Pointer for the current character.
|
|
210
|
+
|
|
211
|
+
if file_source == "" or file_path == "":
|
|
212
|
+
return ""
|
|
213
|
+
|
|
214
|
+
start_line: int = error_line - 2
|
|
215
|
+
if start_line < 1:
|
|
216
|
+
start_line = 1
|
|
217
|
+
end_line: int = start_line + 5 # Index is exclusive.
|
|
218
|
+
|
|
219
|
+
# Get the first character of the [start_line].
|
|
220
|
+
file_source.splitlines(True)[start_line - 1]
|
|
221
|
+
curr_line: int = error_line
|
|
222
|
+
while idx >= 0 and curr_line >= start_line:
|
|
223
|
+
idx -= 1
|
|
224
|
+
if idx < 0:
|
|
225
|
+
break
|
|
226
|
+
if file_source[idx] == "\n":
|
|
227
|
+
curr_line -= 1
|
|
228
|
+
|
|
229
|
+
idx += 1 # Enter the line.
|
|
230
|
+
assert idx == 0 or file_source[idx - 1] == "\n"
|
|
231
|
+
|
|
232
|
+
pretty_dump = ""
|
|
233
|
+
|
|
234
|
+
# Print each lines.
|
|
235
|
+
curr_line = start_line
|
|
236
|
+
while curr_line < end_line:
|
|
237
|
+
pretty_dump += f"%{line_num_width}d | " % curr_line
|
|
238
|
+
|
|
239
|
+
idx_line_start = idx
|
|
240
|
+
while idx < len(file_source) and file_source[idx] != "\n":
|
|
241
|
+
idx += 1 # Run to the line end.
|
|
242
|
+
pretty_dump += file_source[idx_line_start:idx]
|
|
243
|
+
pretty_dump += "\n"
|
|
244
|
+
|
|
245
|
+
if curr_line == error_line: # Print the current line with indicator.
|
|
246
|
+
pretty_dump += f"%{line_num_width}s | " % " "
|
|
247
|
+
|
|
248
|
+
spaces = ""
|
|
249
|
+
for idx_pre in range(idx_line_start, pos_start):
|
|
250
|
+
spaces += "\t" if file_source[idx_pre] == "\t" else " "
|
|
251
|
+
|
|
252
|
+
err_token_len = pos_end - pos_start
|
|
253
|
+
pretty_dump += spaces + ("^" * err_token_len) + "\n"
|
|
254
|
+
|
|
255
|
+
if idx == len(file_source):
|
|
256
|
+
break
|
|
257
|
+
curr_line += 1
|
|
258
|
+
idx += 1
|
|
259
|
+
|
|
260
|
+
return pretty_dump[:-1] # Get rid of the last newline (of the last line).
|
|
261
|
+
|
|
262
|
+
|
|
185
263
|
class Jdb(pdb.Pdb):
|
|
186
264
|
"""Jac debugger."""
|
|
187
265
|
|
jaclang/utils/lang_tools.py
CHANGED
|
@@ -215,12 +215,16 @@ class AstTool:
|
|
|
215
215
|
|
|
216
216
|
if file_name.endswith(".py"):
|
|
217
217
|
with open(file_name, "r") as f:
|
|
218
|
-
|
|
218
|
+
file_source = f.read()
|
|
219
|
+
parsed_ast = py_ast.parse(file_source)
|
|
219
220
|
if output == "pyast":
|
|
220
221
|
return f"\n{py_ast.dump(parsed_ast, indent=2)}"
|
|
221
222
|
try:
|
|
222
223
|
rep = PyastBuildPass(
|
|
223
|
-
input_ir=ast.PythonModuleAst(
|
|
224
|
+
input_ir=ast.PythonModuleAst(
|
|
225
|
+
parsed_ast,
|
|
226
|
+
orig_src=ast.JacSource(file_source, file_name),
|
|
227
|
+
),
|
|
224
228
|
).ir
|
|
225
229
|
|
|
226
230
|
schedule = py_code_gen_typed
|
jaclang/utils/treeprinter.py
CHANGED
|
@@ -105,7 +105,7 @@ def print_ast_tree(
|
|
|
105
105
|
if isinstance(node, Token) and isinstance(node, AstSymbolNode):
|
|
106
106
|
out = (
|
|
107
107
|
f"{node.__class__.__name__} - {node.value} - "
|
|
108
|
-
f"Type: {node.
|
|
108
|
+
f"Type: {node.expr_type}, {access} {sym_table_link}"
|
|
109
109
|
)
|
|
110
110
|
if settings.ast_symbol_info_detailed:
|
|
111
111
|
symbol = (
|
|
@@ -133,7 +133,7 @@ def print_ast_tree(
|
|
|
133
133
|
elif isinstance(node, AstSymbolNode):
|
|
134
134
|
out = (
|
|
135
135
|
f"{node.__class__.__name__} - {node.sym_name} - "
|
|
136
|
-
f"Type: {node.
|
|
136
|
+
f"Type: {node.expr_type}, {access} {sym_table_link}"
|
|
137
137
|
)
|
|
138
138
|
if settings.ast_symbol_info_detailed:
|
|
139
139
|
symbol = (
|
|
@@ -143,6 +143,8 @@ def print_ast_tree(
|
|
|
143
143
|
)
|
|
144
144
|
out += f" SymbolPath: {symbol}"
|
|
145
145
|
return out
|
|
146
|
+
elif isinstance(node, ast.Expr):
|
|
147
|
+
return f"{node.__class__.__name__} - Type: {node.expr_type}"
|
|
146
148
|
else:
|
|
147
149
|
return f"{node.__class__.__name__}, {access}"
|
|
148
150
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jaclang
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.26
|
|
4
4
|
Summary: Jac is a unique and powerful programming language that runs on top of Python, offering an unprecedented level of intelligence and intuitive understanding.
|
|
5
5
|
Home-page: https://jaseci.org
|
|
6
6
|
License: MIT
|
|
@@ -14,6 +14,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
18
|
Provides-Extra: all
|
|
18
19
|
Provides-Extra: llm
|
|
19
20
|
Provides-Extra: streamlit
|