jaclang 0.7.26__py3-none-any.whl → 0.7.28__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 +3 -0
- jaclang/compiler/absyntree.py +18 -3
- jaclang/compiler/passes/main/__init__.py +1 -1
- jaclang/compiler/passes/main/access_modifier_pass.py +1 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +62 -33
- jaclang/compiler/passes/main/import_pass.py +284 -63
- jaclang/compiler/passes/main/inheritance_pass.py +103 -0
- jaclang/compiler/passes/main/py_collect_dep_pass.py +5 -5
- jaclang/compiler/passes/main/pyast_load_pass.py +1 -1
- jaclang/compiler/passes/main/schedules.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +17 -0
- jaclang/compiler/passes/main/tests/fixtures/data_spatial_types.jac +130 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -3
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.pyi +3 -3
- jaclang/compiler/passes/main/tests/test_import_pass.py +13 -17
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +24 -0
- jaclang/compiler/passes/main/type_check_pass.py +3 -2
- jaclang/compiler/py_info.py +22 -0
- jaclang/compiler/symtable.py +9 -2
- jaclang/langserve/tests/test_server.py +2 -2
- jaclang/plugin/default.py +28 -11
- jaclang/plugin/feature.py +8 -1
- jaclang/plugin/spec.py +3 -2
- jaclang/plugin/tests/fixtures/other_root_access.jac +10 -0
- jaclang/plugin/tests/fixtures/savable_object.jac +84 -0
- jaclang/plugin/tests/test_jaseci.py +88 -0
- jaclang/runtimelib/architype.py +17 -0
- jaclang/runtimelib/memory.py +22 -7
- jaclang/runtimelib/test.py +59 -4
- jaclang/runtimelib/utils.py +16 -0
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/base_class1.jac +11 -0
- jaclang/tests/fixtures/base_class2.jac +11 -0
- jaclang/tests/fixtures/import_all.jac +7 -0
- jaclang/tests/fixtures/import_all_py.py +8 -0
- jaclang/tests/fixtures/jactest_imported.jac +6 -0
- jaclang/tests/fixtures/jactest_main.jac +22 -0
- jaclang/tests/fixtures/multi_dim_array_split.jac +2 -6
- jaclang/tests/fixtures/test_py.py +12 -0
- jaclang/tests/test_cli.py +82 -0
- jaclang/tests/test_language.py +7 -8
- jaclang/utils/helpers.py +9 -1
- jaclang/utils/treeprinter.py +6 -3
- {jaclang-0.7.26.dist-info → jaclang-0.7.28.dist-info}/METADATA +2 -2
- {jaclang-0.7.26.dist-info → jaclang-0.7.28.dist-info}/RECORD +47 -36
- {jaclang-0.7.26.dist-info → jaclang-0.7.28.dist-info}/WHEEL +1 -1
- {jaclang-0.7.26.dist-info → jaclang-0.7.28.dist-info}/entry_points.txt +0 -0
|
@@ -23,6 +23,16 @@ walker update_node {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
walker update_target_node {
|
|
27
|
+
has val: int;
|
|
28
|
+
has node_id: str;
|
|
29
|
+
|
|
30
|
+
can enter with `root entry {
|
|
31
|
+
target_node = &(self.node_id);
|
|
32
|
+
target_node.val = self.val;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
walker update_node_forced {
|
|
27
37
|
has val: int;
|
|
28
38
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
enum Enum {
|
|
2
|
+
A = "a",
|
|
3
|
+
B = "b",
|
|
4
|
+
C = "c"
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
obj Child {
|
|
8
|
+
has val: int, arr: list[int], json: dict[str, int], enum_field: Enum;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
obj Parent:Child: {
|
|
12
|
+
has child: Child;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
obj SavableObject {
|
|
16
|
+
has val: int, arr: list[int], json: dict[str, int], parent: Parent, enum_field: Enum;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
walker create_custom_object {
|
|
20
|
+
can enter1 with `root entry {
|
|
21
|
+
o = SavableObject(
|
|
22
|
+
val=0,
|
|
23
|
+
arr=[],
|
|
24
|
+
json={},
|
|
25
|
+
parent=Parent(
|
|
26
|
+
val=1,
|
|
27
|
+
arr=[1],
|
|
28
|
+
json={"a": 1},
|
|
29
|
+
child=Child(
|
|
30
|
+
val=2,
|
|
31
|
+
arr=[1, 2],
|
|
32
|
+
json={"a": 1, "b": 2},
|
|
33
|
+
enum_field = Enum.C
|
|
34
|
+
),
|
|
35
|
+
enum_field = Enum.B
|
|
36
|
+
),
|
|
37
|
+
enum_field = Enum.A
|
|
38
|
+
);
|
|
39
|
+
Jac.save(o);
|
|
40
|
+
print(jid(o));
|
|
41
|
+
print(o);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
walker get_custom_object {
|
|
46
|
+
has object_id: str;
|
|
47
|
+
|
|
48
|
+
can enter1 with `root entry {
|
|
49
|
+
try {
|
|
50
|
+
print(&(self.object_id));
|
|
51
|
+
} except Exception as e {
|
|
52
|
+
print(None);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
walker update_custom_object {
|
|
58
|
+
has object_id: str;
|
|
59
|
+
|
|
60
|
+
can enter1 with `root entry {
|
|
61
|
+
savable_object = &(self.object_id);
|
|
62
|
+
savable_object.parent.child.json["c"] = 3;
|
|
63
|
+
savable_object.parent.child.arr.append(3);
|
|
64
|
+
savable_object.parent.child.val = 3;
|
|
65
|
+
savable_object.parent.child.enum_field = Enum.A;
|
|
66
|
+
savable_object.parent.json["b"] = 2;
|
|
67
|
+
savable_object.parent.arr.append(2);
|
|
68
|
+
savable_object.parent.val = 2;
|
|
69
|
+
savable_object.parent.enum_field = Enum.C;
|
|
70
|
+
savable_object.json["a"] = 1;
|
|
71
|
+
savable_object.arr.append(1);
|
|
72
|
+
savable_object.val = 1;
|
|
73
|
+
savable_object.enum_field = Enum.B;
|
|
74
|
+
print(savable_object);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
walker delete_custom_object {
|
|
79
|
+
has object_id: str;
|
|
80
|
+
|
|
81
|
+
can enter1 with `root entry {
|
|
82
|
+
Jac.destroy(&(self.object_id));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -385,6 +385,22 @@ class TestJaseciPlugin(TestCase):
|
|
|
385
385
|
node=self.nodes[0],
|
|
386
386
|
)
|
|
387
387
|
|
|
388
|
+
cli.enter(
|
|
389
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
390
|
+
entrypoint="update_target_node",
|
|
391
|
+
args=[20, self.nodes[1]],
|
|
392
|
+
session=session,
|
|
393
|
+
root=self.roots[0],
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
cli.enter(
|
|
397
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
398
|
+
entrypoint="update_target_node",
|
|
399
|
+
args=[10, self.nodes[0]],
|
|
400
|
+
session=session,
|
|
401
|
+
root=self.roots[1],
|
|
402
|
+
)
|
|
403
|
+
|
|
388
404
|
cli.enter(
|
|
389
405
|
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
390
406
|
entrypoint="check_node",
|
|
@@ -728,3 +744,75 @@ class TestJaseciPlugin(TestCase):
|
|
|
728
744
|
)
|
|
729
745
|
|
|
730
746
|
self._del_session(session)
|
|
747
|
+
|
|
748
|
+
def test_savable_object(self) -> None:
|
|
749
|
+
"""Test ObjectAnchor save."""
|
|
750
|
+
global session
|
|
751
|
+
session = self.fixture_abs_path("other_root_access.session")
|
|
752
|
+
|
|
753
|
+
self._output2buffer()
|
|
754
|
+
|
|
755
|
+
cli.enter(
|
|
756
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
757
|
+
entrypoint="create_custom_object",
|
|
758
|
+
args=[],
|
|
759
|
+
session=session,
|
|
760
|
+
)
|
|
761
|
+
|
|
762
|
+
prints = self.capturedOutput.getvalue().strip().split("\n")
|
|
763
|
+
id = prints[0]
|
|
764
|
+
|
|
765
|
+
self.assertEqual(
|
|
766
|
+
"SavableObject(val=0, arr=[], json={}, parent=Parent(val=1, arr=[1], json"
|
|
767
|
+
"={'a': 1}, enum_field=<Enum.B: 'b'>, child=Child(val=2, arr=[1, 2], json"
|
|
768
|
+
"={'a': 1, 'b': 2}, enum_field=<Enum.C: 'c'>)), enum_field=<Enum.A: 'a'>)",
|
|
769
|
+
prints[1],
|
|
770
|
+
)
|
|
771
|
+
|
|
772
|
+
self._output2buffer()
|
|
773
|
+
|
|
774
|
+
cli.enter(
|
|
775
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
776
|
+
entrypoint="get_custom_object",
|
|
777
|
+
args=[id],
|
|
778
|
+
session=session,
|
|
779
|
+
)
|
|
780
|
+
self.assertEqual(
|
|
781
|
+
"SavableObject(val=0, arr=[], json={}, parent=Parent(val=1, arr=[1], json"
|
|
782
|
+
"={'a': 1}, enum_field=<Enum.B: 'b'>, child=Child(val=2, arr=[1, 2], json"
|
|
783
|
+
"={'a': 1, 'b': 2}, enum_field=<Enum.C: 'c'>)), enum_field=<Enum.A: 'a'>)",
|
|
784
|
+
self.capturedOutput.getvalue().strip(),
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
self._output2buffer()
|
|
788
|
+
|
|
789
|
+
cli.enter(
|
|
790
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
791
|
+
entrypoint="update_custom_object",
|
|
792
|
+
args=[id],
|
|
793
|
+
session=session,
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
self.assertEqual(
|
|
797
|
+
"SavableObject(val=1, arr=[1], json={'a': 1}, parent=Parent(val=2, arr=[1, 2], json"
|
|
798
|
+
"={'a': 1, 'b': 2}, enum_field=<Enum.C: 'c'>, child=Child(val=3, arr=[1, 2, 3], json"
|
|
799
|
+
"={'a': 1, 'b': 2, 'c': 3}, enum_field=<Enum.A: 'a'>)), enum_field=<Enum.B: 'b'>)",
|
|
800
|
+
self.capturedOutput.getvalue().strip(),
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
self._output2buffer()
|
|
804
|
+
|
|
805
|
+
cli.enter(
|
|
806
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
807
|
+
entrypoint="delete_custom_object",
|
|
808
|
+
args=[id],
|
|
809
|
+
session=session,
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
cli.enter(
|
|
813
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
814
|
+
entrypoint="get_custom_object",
|
|
815
|
+
args=[id],
|
|
816
|
+
session=session,
|
|
817
|
+
)
|
|
818
|
+
self.assertEqual("None", self.capturedOutput.getvalue().strip())
|
jaclang/runtimelib/architype.py
CHANGED
|
@@ -226,6 +226,13 @@ class WalkerAnchor(Anchor):
|
|
|
226
226
|
disengaged: bool = False
|
|
227
227
|
|
|
228
228
|
|
|
229
|
+
@dataclass(eq=False, repr=False, kw_only=True)
|
|
230
|
+
class ObjectAnchor(Anchor):
|
|
231
|
+
"""Edge Anchor."""
|
|
232
|
+
|
|
233
|
+
architype: ObjectArchitype
|
|
234
|
+
|
|
235
|
+
|
|
229
236
|
class Architype:
|
|
230
237
|
"""Architype Protocol."""
|
|
231
238
|
|
|
@@ -267,6 +274,16 @@ class WalkerArchitype(Architype):
|
|
|
267
274
|
self.__jac__ = WalkerAnchor(architype=self)
|
|
268
275
|
|
|
269
276
|
|
|
277
|
+
class ObjectArchitype(Architype):
|
|
278
|
+
"""Walker Architype Protocol."""
|
|
279
|
+
|
|
280
|
+
__jac__: ObjectAnchor
|
|
281
|
+
|
|
282
|
+
def __init__(self) -> None:
|
|
283
|
+
"""Create walker architype."""
|
|
284
|
+
self.__jac__ = ObjectAnchor(architype=self)
|
|
285
|
+
|
|
286
|
+
|
|
270
287
|
@dataclass(eq=False)
|
|
271
288
|
class GenericEdge(EdgeArchitype):
|
|
272
289
|
"""Generic Root Node."""
|
jaclang/runtimelib/memory.py
CHANGED
|
@@ -84,14 +84,32 @@ class ShelfStorage(Memory[UUID, Anchor]):
|
|
|
84
84
|
def close(self) -> None:
|
|
85
85
|
"""Close memory handler."""
|
|
86
86
|
if isinstance(self.__shelf__, Shelf):
|
|
87
|
-
from jaclang.plugin.feature import JacFeature as Jac
|
|
88
|
-
|
|
89
87
|
for anchor in self.__gc__:
|
|
90
88
|
self.__shelf__.pop(str(anchor.id), None)
|
|
91
89
|
self.__mem__.pop(anchor.id, None)
|
|
92
90
|
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
keys = set(self.__mem__.keys())
|
|
92
|
+
|
|
93
|
+
# current memory
|
|
94
|
+
self.sync_mem_to_db(keys)
|
|
95
|
+
|
|
96
|
+
# additional after memory sync
|
|
97
|
+
self.sync_mem_to_db(set(self.__mem__.keys() - keys))
|
|
98
|
+
|
|
99
|
+
self.__shelf__.close()
|
|
100
|
+
super().close()
|
|
101
|
+
|
|
102
|
+
def sync_mem_to_db(self, keys: Iterable[UUID]) -> None:
|
|
103
|
+
"""Manually sync memory to db."""
|
|
104
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
105
|
+
|
|
106
|
+
if isinstance(self.__shelf__, Shelf):
|
|
107
|
+
for key in keys:
|
|
108
|
+
if (
|
|
109
|
+
(d := self.__mem__.get(key))
|
|
110
|
+
and d.persistent
|
|
111
|
+
and d.hash != hash(dumps(d))
|
|
112
|
+
):
|
|
95
113
|
_id = str(d.id)
|
|
96
114
|
if p_d := self.__shelf__.get(_id):
|
|
97
115
|
if (
|
|
@@ -119,9 +137,6 @@ class ShelfStorage(Memory[UUID, Anchor]):
|
|
|
119
137
|
):
|
|
120
138
|
self.__shelf__[_id] = d
|
|
121
139
|
|
|
122
|
-
self.__shelf__.close()
|
|
123
|
-
super().close()
|
|
124
|
-
|
|
125
140
|
def find(
|
|
126
141
|
self,
|
|
127
142
|
ids: UUID | Iterable[UUID],
|
jaclang/runtimelib/test.py
CHANGED
|
@@ -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(
|
|
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(
|
|
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(
|
|
127
|
+
def add_test(filepath: str, func_name: str, test_func: Callable) -> None:
|
|
85
128
|
"""Create a new test."""
|
|
86
|
-
|
|
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."""
|
jaclang/runtimelib/utils.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import ast as ast3
|
|
6
6
|
import sys
|
|
7
7
|
from contextlib import contextmanager
|
|
8
|
+
from types import UnionType
|
|
8
9
|
from typing import Callable, Iterator, TYPE_CHECKING
|
|
9
10
|
|
|
10
11
|
import jaclang.compiler.absyntree as ast
|
|
@@ -215,3 +216,18 @@ def extract_params(
|
|
|
215
216
|
)
|
|
216
217
|
exclude_info.append((var_name, i.gen.py_ast[0]))
|
|
217
218
|
return model_params, include_info, exclude_info
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def is_instance(
|
|
222
|
+
obj: object, target: type | UnionType | tuple[type | UnionType, ...]
|
|
223
|
+
) -> bool:
|
|
224
|
+
"""Check if object is instance of target type."""
|
|
225
|
+
match target:
|
|
226
|
+
case UnionType():
|
|
227
|
+
return any((is_instance(obj, trg) for trg in target.__args__))
|
|
228
|
+
case tuple():
|
|
229
|
+
return any((is_instance(obj, trg) for trg in target))
|
|
230
|
+
case type():
|
|
231
|
+
return isinstance(obj, target)
|
|
232
|
+
case _:
|
|
233
|
+
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,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 =
|
|
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);
|
jaclang/tests/test_cli.py
CHANGED
|
@@ -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())
|
jaclang/tests/test_language.py
CHANGED
|
@@ -117,11 +117,10 @@ class JacLanguageTests(TestCase):
|
|
|
117
117
|
sys.stdout = sys.__stdout__
|
|
118
118
|
stdout_value = captured_output.getvalue()
|
|
119
119
|
|
|
120
|
-
# print(arr[1:3, 1::2]);
|
|
121
120
|
expected_outputs = [
|
|
122
|
-
"+-- AtomTrailer - Type:
|
|
123
|
-
" +-- Name - arr - Type:
|
|
124
|
-
" +-- IndexSlice - [IndexSlice] - Type: builtins.
|
|
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",
|
|
125
124
|
" +-- Token - [,",
|
|
126
125
|
" +-- Int - 1 - Type: Literal[1]?, SymbolTable: None",
|
|
127
126
|
" +-- Token - :,",
|
|
@@ -549,7 +548,7 @@ class JacLanguageTests(TestCase):
|
|
|
549
548
|
return f"Error While Jac to Py AST conversion: {e}"
|
|
550
549
|
|
|
551
550
|
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
552
|
-
self.assertEqual(len(ir.get_all_sub_nodes(ast.Architype)),
|
|
551
|
+
self.assertEqual(len(ir.get_all_sub_nodes(ast.Architype)), 21)
|
|
553
552
|
captured_output = io.StringIO()
|
|
554
553
|
sys.stdout = captured_output
|
|
555
554
|
jac_import("needs_import_1", base_path=self.fixture_abs_path("./"))
|
|
@@ -612,7 +611,7 @@ class JacLanguageTests(TestCase):
|
|
|
612
611
|
|
|
613
612
|
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
614
613
|
self.assertEqual(
|
|
615
|
-
len(ir.get_all_sub_nodes(ast.Architype)),
|
|
614
|
+
len(ir.get_all_sub_nodes(ast.Architype)), 27
|
|
616
615
|
) # Because of the Architype from math
|
|
617
616
|
captured_output = io.StringIO()
|
|
618
617
|
sys.stdout = captured_output
|
|
@@ -666,7 +665,7 @@ class JacLanguageTests(TestCase):
|
|
|
666
665
|
|
|
667
666
|
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
668
667
|
self.assertEqual(
|
|
669
|
-
len(ir.get_all_sub_nodes(ast.Architype)),
|
|
668
|
+
len(ir.get_all_sub_nodes(ast.Architype)), 75
|
|
670
669
|
) # Because of the Architype from other imports
|
|
671
670
|
captured_output = io.StringIO()
|
|
672
671
|
sys.stdout = captured_output
|
|
@@ -874,7 +873,7 @@ class JacLanguageTests(TestCase):
|
|
|
874
873
|
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
875
874
|
jac_ast = ir.pp()
|
|
876
875
|
self.assertIn(" | +-- String - 'Loop completed normally{}'", jac_ast)
|
|
877
|
-
self.assertEqual(len(ir.get_all_sub_nodes(ast.SubNodeList)),
|
|
876
|
+
self.assertEqual(len(ir.get_all_sub_nodes(ast.SubNodeList)), 586)
|
|
878
877
|
captured_output = io.StringIO()
|
|
879
878
|
sys.stdout = captured_output
|
|
880
879
|
jac_import("deep_convert", base_path=self.fixture_abs_path("./"))
|
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
|
-
|
|
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
|