jaclang 0.7.2__py3-none-any.whl → 0.7.5__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 +2 -2
- jaclang/compiler/absyntree.py +337 -273
- jaclang/compiler/codeloc.py +2 -2
- jaclang/compiler/constant.py +2 -0
- jaclang/compiler/jac.lark +25 -19
- jaclang/compiler/parser.py +115 -92
- jaclang/compiler/passes/main/access_modifier_pass.py +15 -9
- jaclang/compiler/passes/main/def_impl_match_pass.py +25 -13
- jaclang/compiler/passes/main/def_use_pass.py +48 -17
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +34 -34
- jaclang/compiler/passes/main/import_pass.py +8 -6
- jaclang/compiler/passes/main/pyast_gen_pass.py +97 -42
- jaclang/compiler/passes/main/pyast_load_pass.py +47 -12
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +19 -10
- jaclang/compiler/passes/main/registry_pass.py +6 -6
- jaclang/compiler/passes/main/sym_tab_build_pass.py +30 -72
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +21 -4
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +5 -10
- jaclang/compiler/passes/main/type_check_pass.py +2 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +30 -9
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
- jaclang/compiler/passes/transform.py +2 -4
- jaclang/{core/registry.py → compiler/semtable.py} +1 -3
- jaclang/compiler/symtable.py +25 -37
- jaclang/compiler/tests/test_parser.py +2 -2
- jaclang/core/aott.py +8 -8
- jaclang/core/{construct.py → architype.py} +25 -240
- jaclang/core/constructs.py +44 -0
- jaclang/core/context.py +157 -0
- jaclang/core/importer.py +18 -9
- jaclang/core/memory.py +99 -0
- jaclang/core/test.py +90 -0
- jaclang/core/utils.py +2 -2
- jaclang/langserve/engine.py +32 -19
- jaclang/langserve/tests/fixtures/circle.jac +16 -12
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/test_server.py +3 -12
- jaclang/langserve/utils.py +10 -6
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +21 -7
- jaclang/plugin/feature.py +24 -6
- jaclang/plugin/spec.py +17 -19
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/abc.jac +16 -12
- jaclang/tests/fixtures/byllmissue.jac +9 -0
- jaclang/tests/fixtures/edgetypetest.jac +16 -0
- jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
- jaclang/tests/fixtures/impl_match_confused.jac +5 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
- jaclang/tests/fixtures/run_test.jac +17 -5
- jaclang/tests/test_bugs.py +19 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +56 -1
- jaclang/tests/test_reference.py +1 -1
- jaclang/utils/lang_tools.py +5 -4
- jaclang/utils/test.py +2 -1
- jaclang/utils/treeprinter.py +22 -8
- {jaclang-0.7.2.dist-info → jaclang-0.7.5.dist-info}/METADATA +1 -1
- {jaclang-0.7.2.dist-info → jaclang-0.7.5.dist-info}/RECORD +62 -54
- {jaclang-0.7.2.dist-info → jaclang-0.7.5.dist-info}/WHEEL +0 -0
- {jaclang-0.7.2.dist-info → jaclang-0.7.5.dist-info}/entry_points.txt +0 -0
jaclang/core/test.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Core constructs for Jac Language."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
from typing import Callable, Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class JacTestResult(unittest.TextTestResult):
|
|
10
|
+
"""Jac test result class."""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
stream, # noqa
|
|
15
|
+
descriptions, # noqa
|
|
16
|
+
verbosity: int,
|
|
17
|
+
max_failures: Optional[int] = None,
|
|
18
|
+
) -> None:
|
|
19
|
+
"""Initialize FailFastTestResult object."""
|
|
20
|
+
super().__init__(stream, descriptions, verbosity) # noqa
|
|
21
|
+
self.failures_count = JacTestCheck.failcount
|
|
22
|
+
self.max_failures = max_failures
|
|
23
|
+
|
|
24
|
+
def addFailure(self, test, err) -> None: # noqa
|
|
25
|
+
"""Count failures and stop."""
|
|
26
|
+
super().addFailure(test, err)
|
|
27
|
+
self.failures_count += 1
|
|
28
|
+
if self.max_failures is not None and self.failures_count >= self.max_failures:
|
|
29
|
+
self.stop()
|
|
30
|
+
|
|
31
|
+
def stop(self) -> None:
|
|
32
|
+
"""Stop the test execution."""
|
|
33
|
+
self.shouldStop = True
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class JacTextTestRunner(unittest.TextTestRunner):
|
|
37
|
+
"""Jac test runner class."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, max_failures: Optional[int] = None, **kwargs) -> None: # noqa
|
|
40
|
+
"""Initialize JacTextTestRunner object."""
|
|
41
|
+
self.max_failures = max_failures
|
|
42
|
+
super().__init__(**kwargs)
|
|
43
|
+
|
|
44
|
+
def _makeResult(self) -> JacTestResult: # noqa
|
|
45
|
+
"""Override the method to return an instance of JacTestResult."""
|
|
46
|
+
return JacTestResult(
|
|
47
|
+
self.stream,
|
|
48
|
+
self.descriptions,
|
|
49
|
+
self.verbosity,
|
|
50
|
+
max_failures=self.max_failures,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class JacTestCheck:
|
|
55
|
+
"""Jac Testing and Checking."""
|
|
56
|
+
|
|
57
|
+
test_case = unittest.TestCase()
|
|
58
|
+
test_suite = unittest.TestSuite()
|
|
59
|
+
breaker = False
|
|
60
|
+
failcount = 0
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def reset() -> None:
|
|
64
|
+
"""Clear the test suite."""
|
|
65
|
+
JacTestCheck.test_case = unittest.TestCase()
|
|
66
|
+
JacTestCheck.test_suite = unittest.TestSuite()
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def run_test(xit: bool, maxfail: int | None, verbose: bool) -> None:
|
|
70
|
+
"""Run the test suite."""
|
|
71
|
+
verb = 2 if verbose else 1
|
|
72
|
+
runner = JacTextTestRunner(max_failures=maxfail, failfast=xit, verbosity=verb)
|
|
73
|
+
result = runner.run(JacTestCheck.test_suite)
|
|
74
|
+
if result.wasSuccessful():
|
|
75
|
+
print("Passed successfully.")
|
|
76
|
+
else:
|
|
77
|
+
fails = len(result.failures)
|
|
78
|
+
JacTestCheck.failcount += fails
|
|
79
|
+
JacTestCheck.breaker = (
|
|
80
|
+
(JacTestCheck.failcount >= maxfail) if maxfail else True
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def add_test(test_fun: Callable) -> None:
|
|
85
|
+
"""Create a new test."""
|
|
86
|
+
JacTestCheck.test_suite.addTest(unittest.FunctionTestCase(test_fun))
|
|
87
|
+
|
|
88
|
+
def __getattr__(self, name: str) -> object:
|
|
89
|
+
"""Make convenient check.Equal(...) etc."""
|
|
90
|
+
return getattr(JacTestCheck.test_case, name)
|
jaclang/core/utils.py
CHANGED
|
@@ -8,10 +8,10 @@ from contextlib import contextmanager
|
|
|
8
8
|
from typing import Callable, Iterator, TYPE_CHECKING
|
|
9
9
|
|
|
10
10
|
import jaclang.compiler.absyntree as ast
|
|
11
|
-
from jaclang.
|
|
11
|
+
from jaclang.compiler.semtable import SemScope
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from jaclang.core.
|
|
14
|
+
from jaclang.core.constructs import NodeAnchor, NodeArchitype
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@contextmanager
|
jaclang/langserve/engine.py
CHANGED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
from enum import IntEnum
|
|
7
7
|
from hashlib import md5
|
|
8
|
-
from typing import Optional
|
|
8
|
+
from typing import Optional
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import jaclang.compiler.absyntree as ast
|
|
@@ -40,8 +40,8 @@ class ModuleInfo:
|
|
|
40
40
|
def __init__(
|
|
41
41
|
self,
|
|
42
42
|
ir: ast.Module,
|
|
43
|
-
errors:
|
|
44
|
-
warnings:
|
|
43
|
+
errors: list[Alert],
|
|
44
|
+
warnings: list[Alert],
|
|
45
45
|
alev: ALev,
|
|
46
46
|
parent: Optional[ModuleInfo] = None,
|
|
47
47
|
) -> None:
|
|
@@ -63,6 +63,14 @@ class ModuleInfo:
|
|
|
63
63
|
"""Return if there are syntax errors."""
|
|
64
64
|
return len(self.errors) > 0 and self.alev == ALev.QUICK
|
|
65
65
|
|
|
66
|
+
def update_with(self, new_info: ModuleInfo) -> None:
|
|
67
|
+
"""Update module info."""
|
|
68
|
+
self.ir = new_info.ir
|
|
69
|
+
self.errors += [i for i in new_info.errors if i not in self.errors]
|
|
70
|
+
self.warnings += [i for i in new_info.warnings if i not in self.warnings]
|
|
71
|
+
self.alev = new_info.alev
|
|
72
|
+
self.diagnostics = self.gen_diagnostics()
|
|
73
|
+
|
|
66
74
|
def gen_diagnostics(self) -> list[lspt.Diagnostic]:
|
|
67
75
|
"""Return diagnostics."""
|
|
68
76
|
return [
|
|
@@ -124,15 +132,14 @@ class JacLangServer(LanguageServer):
|
|
|
124
132
|
self.quick_check(file_path)
|
|
125
133
|
return file_path
|
|
126
134
|
|
|
127
|
-
def update_modules(
|
|
135
|
+
def update_modules(
|
|
136
|
+
self, file_path: str, build: Pass, alev: ALev, refresh: bool = False
|
|
137
|
+
) -> None:
|
|
128
138
|
"""Update modules."""
|
|
129
139
|
if not isinstance(build.ir, ast.Module):
|
|
130
140
|
self.log_error("Error with module build.")
|
|
131
141
|
return
|
|
132
|
-
|
|
133
|
-
self.modules[file_path].parent if file_path in self.modules else None
|
|
134
|
-
)
|
|
135
|
-
self.modules[file_path] = ModuleInfo(
|
|
142
|
+
new_mod = ModuleInfo(
|
|
136
143
|
ir=build.ir,
|
|
137
144
|
errors=[
|
|
138
145
|
i
|
|
@@ -146,15 +153,22 @@ class JacLangServer(LanguageServer):
|
|
|
146
153
|
],
|
|
147
154
|
alev=alev,
|
|
148
155
|
)
|
|
149
|
-
self.modules
|
|
156
|
+
if not refresh and file_path in self.modules:
|
|
157
|
+
self.modules[file_path].update_with(new_mod)
|
|
158
|
+
else:
|
|
159
|
+
self.modules[file_path] = new_mod
|
|
150
160
|
for p in build.ir.mod_deps.keys():
|
|
151
161
|
uri = uris.from_fs_path(p)
|
|
152
|
-
|
|
162
|
+
new_mod = ModuleInfo(
|
|
153
163
|
ir=build.ir.mod_deps[p],
|
|
154
164
|
errors=[i for i in build.errors_had if i.loc.mod_path == p],
|
|
155
165
|
warnings=[i for i in build.warnings_had if i.loc.mod_path == p],
|
|
156
166
|
alev=alev,
|
|
157
167
|
)
|
|
168
|
+
if not refresh and uri in self.modules:
|
|
169
|
+
self.modules[uri].update_with(new_mod)
|
|
170
|
+
else:
|
|
171
|
+
self.modules[uri] = new_mod
|
|
158
172
|
self.modules[uri].parent = (
|
|
159
173
|
self.modules[file_path] if file_path != uri else None
|
|
160
174
|
)
|
|
@@ -170,7 +184,7 @@ class JacLangServer(LanguageServer):
|
|
|
170
184
|
)
|
|
171
185
|
except Exception as e:
|
|
172
186
|
self.log_error(f"Error during syntax check: {e}")
|
|
173
|
-
self.update_modules(file_path, build, ALev.QUICK)
|
|
187
|
+
self.update_modules(file_path, build, ALev.QUICK, refresh=True)
|
|
174
188
|
|
|
175
189
|
def deep_check(self, file_path: str, force: bool = False) -> None:
|
|
176
190
|
"""Rebuild a file and its dependencies."""
|
|
@@ -275,21 +289,20 @@ class JacLangServer(LanguageServer):
|
|
|
275
289
|
def get_node_info(self, node: ast.AstSymbolNode) -> Optional[str]:
|
|
276
290
|
"""Extract meaningful information from the AST node."""
|
|
277
291
|
try:
|
|
278
|
-
if isinstance(node, ast.
|
|
292
|
+
if isinstance(node, ast.NameAtom):
|
|
279
293
|
node = node.name_of
|
|
280
|
-
access = node.
|
|
294
|
+
access = node.sym.access.value + " " if node.sym else None
|
|
281
295
|
node_info = (
|
|
282
|
-
f"({access if access else ''}{node.
|
|
296
|
+
f"({access if access else ''}{node.sym_category.value}) {node.sym_name}"
|
|
283
297
|
)
|
|
284
|
-
if node.
|
|
285
|
-
node_info += f": {node.
|
|
298
|
+
if node.name_spec.clean_type:
|
|
299
|
+
node_info += f": {node.name_spec.clean_type}"
|
|
286
300
|
if isinstance(node, ast.AstSemStrNode) and node.semstr:
|
|
287
301
|
node_info += f"\n{node.semstr.value}"
|
|
288
302
|
if isinstance(node, ast.AstDocNode) and node.doc:
|
|
289
303
|
node_info += f"\n{node.doc.value}"
|
|
290
304
|
if isinstance(node, ast.Ability) and node.signature:
|
|
291
305
|
node_info += f"\n{node.signature.unparse()}"
|
|
292
|
-
self.log_py(node.pp())
|
|
293
306
|
self.log_py(f"mypy_node: {node.gen.mypy_ast}")
|
|
294
307
|
except AttributeError as e:
|
|
295
308
|
self.log_warning(f"Attribute error when accessing node attributes: {e}")
|
|
@@ -318,8 +331,8 @@ class JacLangServer(LanguageServer):
|
|
|
318
331
|
and isinstance(node_selected.parent, ast.AstImplNeedingNode)
|
|
319
332
|
and isinstance(node_selected.parent.body, ast.AstImplOnlyNode)
|
|
320
333
|
else (
|
|
321
|
-
node_selected.
|
|
322
|
-
if (node_selected.
|
|
334
|
+
node_selected.sym.decl
|
|
335
|
+
if (node_selected.sym and node_selected.sym.decl)
|
|
323
336
|
else node_selected
|
|
324
337
|
)
|
|
325
338
|
)
|
|
@@ -18,9 +18,9 @@ Below we have the demonstration of a class to calculate the area of a circle.
|
|
|
18
18
|
*#
|
|
19
19
|
|
|
20
20
|
"""Enum for shape types"""
|
|
21
|
-
enum ShapeType
|
|
22
|
-
CIRCLE="Circle",
|
|
23
|
-
UNKNOWN="Unknown"
|
|
21
|
+
enum ShapeType {
|
|
22
|
+
CIRCLE = "Circle",
|
|
23
|
+
UNKNOWN = "Unknown"
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
"""Base class for a shape."""
|
|
@@ -50,24 +50,28 @@ with entry {
|
|
|
50
50
|
# Global also works here
|
|
51
51
|
|
|
52
52
|
with entry:__main__ {
|
|
53
|
-
# To run the program functionality
|
|
54
|
-
print(
|
|
55
|
-
|
|
53
|
+
# To run the program functionality
|
|
54
|
+
print(
|
|
55
|
+
f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}"
|
|
56
|
+
);
|
|
57
|
+
print(
|
|
58
|
+
f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}"
|
|
59
|
+
);
|
|
56
60
|
}
|
|
57
61
|
# Unit Tests!
|
|
58
62
|
|
|
59
63
|
glob expected_area = 78.53981633974483;
|
|
60
64
|
|
|
61
|
-
test calc_area
|
|
62
|
-
check
|
|
65
|
+
test calc_area {
|
|
66
|
+
check assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
test circle_area
|
|
69
|
+
test circle_area {
|
|
66
70
|
c = Circle(RAD);
|
|
67
|
-
check
|
|
71
|
+
check assertAlmostEqual(c.area(), expected_area);
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
test circle_type
|
|
74
|
+
test circle_type {
|
|
71
75
|
c = Circle(RAD);
|
|
72
|
-
check
|
|
76
|
+
check assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
73
77
|
}
|
|
@@ -59,15 +59,15 @@ print(f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}
|
|
|
59
59
|
glob expected_area = 78.53981633974483;
|
|
60
60
|
|
|
61
61
|
test calc_area {
|
|
62
|
-
check
|
|
62
|
+
check assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
test circle_area {
|
|
66
66
|
c = Circle(RAD);
|
|
67
|
-
check
|
|
67
|
+
check assertAlmostEqual(c.area(), expected_area);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
test circle_type {
|
|
71
71
|
c = Circle(RAD);
|
|
72
|
-
check
|
|
72
|
+
check assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
73
73
|
}
|
|
@@ -143,16 +143,7 @@ class TestJacLangServer(TestCase):
|
|
|
143
143
|
lsp.quick_check(circle_file)
|
|
144
144
|
lsp.deep_check(circle_file)
|
|
145
145
|
lsp.type_check(circle_file)
|
|
146
|
-
|
|
147
|
-
"DocumentSymbol(name='calculate_area', kind=<SymbolKind.Function: 12>, range=9:0-9:43, "
|
|
148
|
-
"selection_range=9:0-9:43, detail=None, tags=None, deprecated=None, children=["
|
|
149
|
-
"DocumentSymbol(name='radius', kind=<SymbolKind.Variable: 13>, range=9:1-9:14, "
|
|
150
|
-
"selection_range=9:1-9:14, detail=None, tags=None, deprecated=None, children=[])])"
|
|
151
|
-
)
|
|
152
|
-
self.assertEqual(
|
|
153
|
-
expected_string, str((lsp.get_document_symbols(circle_file))[6])
|
|
154
|
-
)
|
|
155
|
-
self.assertEqual(10, len(lsp.get_document_symbols(circle_file)))
|
|
146
|
+
self.assertEqual(8, len(lsp.get_document_symbols(circle_file)))
|
|
156
147
|
|
|
157
148
|
def test_go_to_definition(self) -> None:
|
|
158
149
|
"""Test that the go to definition is correct."""
|
|
@@ -169,7 +160,7 @@ class TestJacLangServer(TestCase):
|
|
|
169
160
|
str(lsp.get_definition(circle_file, lspt.Position(9, 16))),
|
|
170
161
|
)
|
|
171
162
|
self.assertIn(
|
|
172
|
-
"fixtures/circle_pure.jac:
|
|
163
|
+
"fixtures/circle_pure.jac:13:11-13:16",
|
|
173
164
|
str(lsp.get_definition(circle_file, lspt.Position(20, 17))),
|
|
174
165
|
)
|
|
175
166
|
|
|
@@ -186,6 +177,6 @@ class TestJacLangServer(TestCase):
|
|
|
186
177
|
lsp.deep_check(guess_game_file)
|
|
187
178
|
lsp.type_check(guess_game_file)
|
|
188
179
|
self.assertIn(
|
|
189
|
-
"guess_game4.jac:27:
|
|
180
|
+
"guess_game4.jac:27:8-27:21",
|
|
190
181
|
str(lsp.get_definition(guess_game_file, lspt.Position(46, 45))),
|
|
191
182
|
)
|
jaclang/langserve/utils.py
CHANGED
|
@@ -106,23 +106,27 @@ def collect_symbols(node: SymbolTable) -> list[lspt.DocumentSymbol]:
|
|
|
106
106
|
return symbols
|
|
107
107
|
|
|
108
108
|
for key, item in node.tab.items():
|
|
109
|
-
if
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
if (
|
|
110
|
+
key in dir(builtins)
|
|
111
|
+
or item in [owner_sym(tab) for tab in node.kid]
|
|
112
|
+
or item.decl.loc.mod_path != node.owner.loc.mod_path
|
|
113
|
+
):
|
|
112
114
|
continue
|
|
113
115
|
else:
|
|
114
116
|
|
|
115
|
-
pos = create_range(item.
|
|
117
|
+
pos = create_range(item.decl.loc)
|
|
116
118
|
symbol = lspt.DocumentSymbol(
|
|
117
119
|
name=key,
|
|
118
|
-
kind=kind_map(item.
|
|
120
|
+
kind=kind_map(item.decl),
|
|
119
121
|
range=pos,
|
|
120
122
|
selection_range=pos,
|
|
121
123
|
children=[],
|
|
122
124
|
)
|
|
123
125
|
symbols.append(symbol)
|
|
124
126
|
|
|
125
|
-
for sub_tab in
|
|
127
|
+
for sub_tab in [
|
|
128
|
+
i for i in node.kid if i.owner.loc.mod_path == node.owner.loc.mod_path
|
|
129
|
+
]:
|
|
126
130
|
sub_symbols = collect_symbols(sub_tab)
|
|
127
131
|
|
|
128
132
|
if isinstance(
|
jaclang/plugin/builtin.py
CHANGED
jaclang/plugin/default.py
CHANGED
|
@@ -14,6 +14,7 @@ from typing import Any, Callable, Optional, Type, Union
|
|
|
14
14
|
|
|
15
15
|
from jaclang.compiler.absyntree import Module
|
|
16
16
|
from jaclang.compiler.constant import EdgeDir, colors
|
|
17
|
+
from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
|
|
17
18
|
from jaclang.core.aott import (
|
|
18
19
|
aott_raise,
|
|
19
20
|
extract_non_primary_type,
|
|
@@ -21,7 +22,7 @@ from jaclang.core.aott import (
|
|
|
21
22
|
get_info_types,
|
|
22
23
|
get_input_information,
|
|
23
24
|
)
|
|
24
|
-
from jaclang.core.
|
|
25
|
+
from jaclang.core.constructs import (
|
|
25
26
|
Architype,
|
|
26
27
|
DSFunc,
|
|
27
28
|
EdgeAnchor,
|
|
@@ -39,7 +40,6 @@ from jaclang.core.construct import (
|
|
|
39
40
|
exec_context,
|
|
40
41
|
)
|
|
41
42
|
from jaclang.core.importer import jac_importer
|
|
42
|
-
from jaclang.core.registry import SemInfo, SemRegistry, SemScope
|
|
43
43
|
from jaclang.core.utils import traverse_graph
|
|
44
44
|
from jaclang.plugin.feature import JacFeature as Jac
|
|
45
45
|
from jaclang.plugin.spec import T
|
|
@@ -110,7 +110,9 @@ class JacFeatureDefaults:
|
|
|
110
110
|
"""Create a new architype."""
|
|
111
111
|
for i in on_entry + on_exit:
|
|
112
112
|
i.resolve(cls)
|
|
113
|
-
if not
|
|
113
|
+
if not hasattr(cls, "_jac_entry_funcs_") or not hasattr(
|
|
114
|
+
cls, "_jac_exit_funcs_"
|
|
115
|
+
):
|
|
114
116
|
# Saving the module path and reassign it after creating cls
|
|
115
117
|
# So the jac modules are part of the correct module
|
|
116
118
|
cur_module = cls.__module__
|
|
@@ -216,7 +218,7 @@ class JacFeatureDefaults:
|
|
|
216
218
|
cachable: bool,
|
|
217
219
|
mdl_alias: Optional[str],
|
|
218
220
|
override_name: Optional[str],
|
|
219
|
-
mod_bundle: Optional[Module],
|
|
221
|
+
mod_bundle: Optional[Module | str],
|
|
220
222
|
lng: Optional[str],
|
|
221
223
|
items: Optional[dict[str, Union[str, bool]]],
|
|
222
224
|
) -> Optional[types.ModuleType]:
|
|
@@ -335,7 +337,13 @@ class JacFeatureDefaults:
|
|
|
335
337
|
@hookimpl
|
|
336
338
|
def ignore(
|
|
337
339
|
walker: WalkerArchitype,
|
|
338
|
-
expr:
|
|
340
|
+
expr: (
|
|
341
|
+
list[NodeArchitype | EdgeArchitype]
|
|
342
|
+
| list[NodeArchitype]
|
|
343
|
+
| list[EdgeArchitype]
|
|
344
|
+
| NodeArchitype
|
|
345
|
+
| EdgeArchitype
|
|
346
|
+
),
|
|
339
347
|
) -> bool:
|
|
340
348
|
"""Jac's ignore stmt feature."""
|
|
341
349
|
return walker._jac_.ignore_node(expr)
|
|
@@ -344,7 +352,13 @@ class JacFeatureDefaults:
|
|
|
344
352
|
@hookimpl
|
|
345
353
|
def visit_node(
|
|
346
354
|
walker: WalkerArchitype,
|
|
347
|
-
expr:
|
|
355
|
+
expr: (
|
|
356
|
+
list[NodeArchitype | EdgeArchitype]
|
|
357
|
+
| list[NodeArchitype]
|
|
358
|
+
| list[EdgeArchitype]
|
|
359
|
+
| NodeArchitype
|
|
360
|
+
| EdgeArchitype
|
|
361
|
+
),
|
|
348
362
|
) -> bool:
|
|
349
363
|
"""Jac's visit stmt feature."""
|
|
350
364
|
if isinstance(walker, WalkerArchitype):
|
|
@@ -649,7 +663,7 @@ class JacFeatureDefaults:
|
|
|
649
663
|
|
|
650
664
|
inputs_information = get_input_information(inputs, type_collector)
|
|
651
665
|
|
|
652
|
-
output_information = f"{outputs[0]} ({outputs[1]})"
|
|
666
|
+
output_information = f"{outputs[0]} ({outputs[1]})".strip()
|
|
653
667
|
type_collector.extend(extract_non_primary_type(outputs[1]))
|
|
654
668
|
output_type_explanations = "\n".join(
|
|
655
669
|
list(
|
jaclang/plugin/feature.py
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import types
|
|
6
|
-
from typing import Any, Callable, Optional, Type, Union
|
|
6
|
+
from typing import Any, Callable, Optional, Type, TypeAlias, Union
|
|
7
7
|
|
|
8
8
|
from jaclang.compiler.absyntree import Module
|
|
9
|
-
from jaclang.core.
|
|
9
|
+
from jaclang.core.constructs import (
|
|
10
10
|
Architype,
|
|
11
11
|
EdgeArchitype,
|
|
12
12
|
Memory,
|
|
@@ -31,7 +31,13 @@ class JacFeature:
|
|
|
31
31
|
|
|
32
32
|
import abc
|
|
33
33
|
from jaclang.compiler.constant import EdgeDir
|
|
34
|
-
from jaclang.
|
|
34
|
+
from jaclang.core.constructs import DSFunc
|
|
35
|
+
|
|
36
|
+
RootType: TypeAlias = Root
|
|
37
|
+
Obj: TypeAlias = Architype
|
|
38
|
+
Node: TypeAlias = NodeArchitype
|
|
39
|
+
Edge: TypeAlias = EdgeArchitype
|
|
40
|
+
Walker: TypeAlias = WalkerArchitype
|
|
35
41
|
|
|
36
42
|
@staticmethod
|
|
37
43
|
def context(session: str = "") -> ExecutionContext:
|
|
@@ -96,7 +102,7 @@ class JacFeature:
|
|
|
96
102
|
cachable: bool = True,
|
|
97
103
|
mdl_alias: Optional[str] = None,
|
|
98
104
|
override_name: Optional[str] = None,
|
|
99
|
-
mod_bundle: Optional[Module] = None,
|
|
105
|
+
mod_bundle: Optional[Module | str] = None,
|
|
100
106
|
lng: Optional[str] = "jac",
|
|
101
107
|
items: Optional[dict[str, Union[str, bool]]] = None,
|
|
102
108
|
) -> Optional[types.ModuleType]:
|
|
@@ -160,7 +166,13 @@ class JacFeature:
|
|
|
160
166
|
@staticmethod
|
|
161
167
|
def ignore(
|
|
162
168
|
walker: WalkerArchitype,
|
|
163
|
-
expr:
|
|
169
|
+
expr: (
|
|
170
|
+
list[NodeArchitype | EdgeArchitype]
|
|
171
|
+
| list[NodeArchitype]
|
|
172
|
+
| list[EdgeArchitype]
|
|
173
|
+
| NodeArchitype
|
|
174
|
+
| EdgeArchitype
|
|
175
|
+
),
|
|
164
176
|
) -> bool: # noqa: ANN401
|
|
165
177
|
"""Jac's ignore stmt feature."""
|
|
166
178
|
return pm.hook.ignore(walker=walker, expr=expr)
|
|
@@ -168,7 +180,13 @@ class JacFeature:
|
|
|
168
180
|
@staticmethod
|
|
169
181
|
def visit_node(
|
|
170
182
|
walker: WalkerArchitype,
|
|
171
|
-
expr:
|
|
183
|
+
expr: (
|
|
184
|
+
list[NodeArchitype | EdgeArchitype]
|
|
185
|
+
| list[NodeArchitype]
|
|
186
|
+
| list[EdgeArchitype]
|
|
187
|
+
| NodeArchitype
|
|
188
|
+
| EdgeArchitype
|
|
189
|
+
),
|
|
172
190
|
) -> bool: # noqa: ANN401
|
|
173
191
|
"""Jac's visit stmt feature."""
|
|
174
192
|
return pm.hook.visit_node(walker=walker, expr=expr)
|
jaclang/plugin/spec.py
CHANGED
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import types
|
|
6
|
-
from dataclasses import dataclass
|
|
7
6
|
from typing import Any, Callable, Optional, TYPE_CHECKING, Type, TypeVar, Union
|
|
8
7
|
|
|
9
8
|
from jaclang.compiler.absyntree import Module
|
|
10
9
|
|
|
11
10
|
if TYPE_CHECKING:
|
|
12
|
-
from jaclang.core.
|
|
11
|
+
from jaclang.core.constructs import EdgeArchitype, NodeArchitype
|
|
13
12
|
from jaclang.plugin.default import (
|
|
14
13
|
Architype,
|
|
15
14
|
EdgeDir,
|
|
16
15
|
ExecutionContext,
|
|
17
16
|
WalkerArchitype,
|
|
18
17
|
Root,
|
|
18
|
+
DSFunc,
|
|
19
19
|
)
|
|
20
20
|
from jaclang.core.memory import Memory
|
|
21
21
|
|
|
@@ -26,20 +26,6 @@ hookspec = pluggy.HookspecMarker("jac")
|
|
|
26
26
|
T = TypeVar("T")
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
# TODO: DSFunc should be moved into jaclang/core
|
|
30
|
-
@dataclass(eq=False)
|
|
31
|
-
class DSFunc:
|
|
32
|
-
"""Data Spatial Function."""
|
|
33
|
-
|
|
34
|
-
name: str
|
|
35
|
-
trigger: type | types.UnionType | tuple[type | types.UnionType, ...] | None
|
|
36
|
-
func: Callable[[Any, Any], Any] | None = None
|
|
37
|
-
|
|
38
|
-
def resolve(self, cls: type) -> None:
|
|
39
|
-
"""Resolve the function."""
|
|
40
|
-
self.func = getattr(cls, self.name)
|
|
41
|
-
|
|
42
|
-
|
|
43
29
|
class JacFeatureSpec:
|
|
44
30
|
"""Jac Feature."""
|
|
45
31
|
|
|
@@ -113,7 +99,7 @@ class JacFeatureSpec:
|
|
|
113
99
|
cachable: bool,
|
|
114
100
|
mdl_alias: Optional[str],
|
|
115
101
|
override_name: Optional[str],
|
|
116
|
-
mod_bundle: Optional[Module],
|
|
102
|
+
mod_bundle: Optional[Module | str],
|
|
117
103
|
lng: Optional[str],
|
|
118
104
|
items: Optional[dict[str, Union[str, bool]]],
|
|
119
105
|
) -> Optional[types.ModuleType]:
|
|
@@ -167,7 +153,13 @@ class JacFeatureSpec:
|
|
|
167
153
|
@hookspec(firstresult=True)
|
|
168
154
|
def ignore(
|
|
169
155
|
walker: WalkerArchitype,
|
|
170
|
-
expr:
|
|
156
|
+
expr: (
|
|
157
|
+
list[NodeArchitype | EdgeArchitype]
|
|
158
|
+
| list[NodeArchitype]
|
|
159
|
+
| list[EdgeArchitype]
|
|
160
|
+
| NodeArchitype
|
|
161
|
+
| EdgeArchitype
|
|
162
|
+
),
|
|
171
163
|
) -> bool:
|
|
172
164
|
"""Jac's ignore stmt feature."""
|
|
173
165
|
raise NotImplementedError
|
|
@@ -176,7 +168,13 @@ class JacFeatureSpec:
|
|
|
176
168
|
@hookspec(firstresult=True)
|
|
177
169
|
def visit_node(
|
|
178
170
|
walker: WalkerArchitype,
|
|
179
|
-
expr:
|
|
171
|
+
expr: (
|
|
172
|
+
list[NodeArchitype | EdgeArchitype]
|
|
173
|
+
| list[NodeArchitype]
|
|
174
|
+
| list[EdgeArchitype]
|
|
175
|
+
| NodeArchitype
|
|
176
|
+
| EdgeArchitype
|
|
177
|
+
),
|
|
180
178
|
) -> bool: # noqa: ANN401
|
|
181
179
|
"""Jac's visit stmt feature."""
|
|
182
180
|
raise NotImplementedError
|
jaclang/settings.py
CHANGED
jaclang/tests/fixtures/abc.jac
CHANGED
|
@@ -18,9 +18,9 @@ Below we have the demonstration of a class to calculate the area of a circle.
|
|
|
18
18
|
*#
|
|
19
19
|
|
|
20
20
|
"""Enum for shape types"""
|
|
21
|
-
enum ShapeType
|
|
22
|
-
CIRCLE="Circle",
|
|
23
|
-
UNKNOWN="Unknown"
|
|
21
|
+
enum ShapeType {
|
|
22
|
+
CIRCLE = "Circle",
|
|
23
|
+
UNKNOWN = "Unknown"
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
"""Base class for a shape."""
|
|
@@ -50,24 +50,28 @@ with entry {
|
|
|
50
50
|
# Global also works here
|
|
51
51
|
|
|
52
52
|
with entry:__main__ {
|
|
53
|
-
# To run the program functionality
|
|
54
|
-
print(
|
|
55
|
-
|
|
53
|
+
# To run the program functionality
|
|
54
|
+
print(
|
|
55
|
+
f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}"
|
|
56
|
+
);
|
|
57
|
+
print(
|
|
58
|
+
f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}"
|
|
59
|
+
);
|
|
56
60
|
}
|
|
57
61
|
# Unit Tests!
|
|
58
62
|
|
|
59
63
|
glob expected_area = 78.53981633974483;
|
|
60
64
|
|
|
61
|
-
test calc_area
|
|
62
|
-
check
|
|
65
|
+
test calc_area {
|
|
66
|
+
check assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
test circle_area
|
|
69
|
+
test circle_area {
|
|
66
70
|
c = Circle(RAD);
|
|
67
|
-
check
|
|
71
|
+
check assertAlmostEqual(c.area(), expected_area);
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
test circle_type
|
|
74
|
+
test circle_type {
|
|
71
75
|
c = Circle(RAD);
|
|
72
|
-
check
|
|
76
|
+
check assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
73
77
|
}
|