jaclang 0.7.30__py3-none-any.whl → 0.7.31__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/__init__.py +419 -3
- jaclang/compiler/absyntree.py +3 -3
- jaclang/compiler/constant.py +4 -4
- jaclang/compiler/jac.lark +226 -175
- jaclang/compiler/parser.py +1336 -1819
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +2 -2
- jaclang/compiler/passes/main/import_pass.py +2 -1
- jaclang/compiler/passes/main/pyast_gen_pass.py +565 -723
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +6 -3
- jaclang/compiler/tests/test_parser.py +13 -5
- jaclang/plugin/builtin.py +11 -0
- jaclang/plugin/default.py +51 -8
- jaclang/plugin/feature.py +14 -0
- jaclang/plugin/spec.py +16 -0
- jaclang/plugin/tests/fixtures/graph_purger.jac +2 -0
- jaclang/plugin/tests/fixtures/other_root_access.jac +1 -0
- jaclang/plugin/tests/fixtures/savable_object.jac +2 -0
- jaclang/plugin/tests/test_jaseci.py +1 -1
- jaclang/runtimelib/architype.py +9 -19
- jaclang/runtimelib/context.py +25 -9
- jaclang/settings.py +2 -0
- jaclang/tests/fixtures/create_dynamic_architype.jac +1 -1
- jaclang/tests/fixtures/nested_impls.jac +55 -0
- jaclang/tests/test_language.py +27 -13
- jaclang/tests/test_reference.py +2 -2
- jaclang/utils/helpers.py +4 -3
- {jaclang-0.7.30.dist-info → jaclang-0.7.31.dist-info}/METADATA +1 -1
- {jaclang-0.7.30.dist-info → jaclang-0.7.31.dist-info}/RECORD +30 -29
- {jaclang-0.7.30.dist-info → jaclang-0.7.31.dist-info}/WHEEL +1 -1
- {jaclang-0.7.30.dist-info → jaclang-0.7.31.dist-info}/entry_points.txt +0 -0
|
@@ -70,19 +70,22 @@ class MypyTypeCheckPassTests(TestCase):
|
|
|
70
70
|
)
|
|
71
71
|
self.assertRegex(
|
|
72
72
|
out,
|
|
73
|
-
r"129:24 - 129:28.*SpecialVarRef -
|
|
73
|
+
r"129:24 - 129:28.*SpecialVarRef - Jac.get_root\(\) \- Type\: jaclang.Root",
|
|
74
74
|
)
|
|
75
|
+
|
|
75
76
|
self.assertRegex(out, r"129:11 - 129:29.*FuncCall \- Type\: builtins\.str")
|
|
76
77
|
self.assertRegex(
|
|
77
78
|
out,
|
|
78
79
|
r"129:15 - 129:23.*Name \- node_dot \- Type\: builtins.str, SymbolTable\: str",
|
|
79
80
|
)
|
|
81
|
+
|
|
80
82
|
self.assertRegex(
|
|
81
83
|
out,
|
|
82
|
-
r"128:5 - 128:25.*BinaryExpr \- Type\: jaclang.
|
|
84
|
+
r"128:5 - 128:25.*BinaryExpr \- Type\: jaclang.Walker",
|
|
83
85
|
)
|
|
84
86
|
self.assertRegex(
|
|
85
87
|
out,
|
|
86
|
-
r"48:11 - 48:28.*EdgeRefTrailer \- Type\:
|
|
88
|
+
r"48:11 - 48:28.*EdgeRefTrailer \- Type\: jaclang.JacList\[data_spatial_types.A\]",
|
|
87
89
|
)
|
|
90
|
+
|
|
88
91
|
self.assertRegex(out, r"24:5 - 24:25.*BinaryExpr \- Type\: builtins.bool", out)
|
|
@@ -89,12 +89,20 @@ class TestLarkParser(TestCaseMicroSuite):
|
|
|
89
89
|
JacParser.TreeToAST.__base__, value.__name__, False
|
|
90
90
|
):
|
|
91
91
|
parse_funcs.append(name)
|
|
92
|
-
for
|
|
93
|
-
self.assertIn(
|
|
94
|
-
for
|
|
95
|
-
if
|
|
92
|
+
for rule in rules:
|
|
93
|
+
self.assertIn(rule, parse_funcs)
|
|
94
|
+
for fn in parse_funcs:
|
|
95
|
+
if fn.startswith("_") or fn in [
|
|
96
|
+
"ice",
|
|
97
|
+
"match",
|
|
98
|
+
"consume",
|
|
99
|
+
"match_token",
|
|
100
|
+
"consume_token",
|
|
101
|
+
"match_many",
|
|
102
|
+
"consume_many",
|
|
103
|
+
]:
|
|
96
104
|
continue
|
|
97
|
-
self.assertIn(
|
|
105
|
+
self.assertIn(fn, rules)
|
|
98
106
|
|
|
99
107
|
def test_all_ast_has_normalize(self) -> None:
|
|
100
108
|
"""Test for enter/exit name diffs with parser."""
|
jaclang/plugin/builtin.py
CHANGED
|
@@ -7,6 +7,12 @@ from typing import Optional
|
|
|
7
7
|
from jaclang.plugin.feature import JacFeature as Jac
|
|
8
8
|
from jaclang.runtimelib.constructs import Architype, NodeArchitype
|
|
9
9
|
|
|
10
|
+
__all__ = [
|
|
11
|
+
"dotgen",
|
|
12
|
+
"jid",
|
|
13
|
+
"jobj",
|
|
14
|
+
]
|
|
15
|
+
|
|
10
16
|
|
|
11
17
|
def dotgen(
|
|
12
18
|
node: Optional[NodeArchitype] = None,
|
|
@@ -44,3 +50,8 @@ def dotgen(
|
|
|
44
50
|
def jid(obj: Architype) -> str:
|
|
45
51
|
"""Get the id of the object."""
|
|
46
52
|
return Jac.object_ref(obj)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def jobj(id: str) -> Architype | None:
|
|
56
|
+
"""Get the object from the id."""
|
|
57
|
+
return Jac.get_object(id)
|
jaclang/plugin/default.py
CHANGED
|
@@ -660,11 +660,15 @@ class JacFeatureImpl(
|
|
|
660
660
|
if not hasattr(cls, "_jac_entry_funcs_") or not hasattr(
|
|
661
661
|
cls, "_jac_exit_funcs_"
|
|
662
662
|
):
|
|
663
|
-
#
|
|
664
|
-
#
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
663
|
+
# If a class only inherit from object (ie. Doesn't inherit from a class), we cannot modify
|
|
664
|
+
# the __bases__ property of it, so it's necessary to make sure the class is not a direct child of object.
|
|
665
|
+
assert cls.__bases__ != (object,)
|
|
666
|
+
bases = (
|
|
667
|
+
(cls.__bases__ + (arch_base,))
|
|
668
|
+
if arch_base not in cls.__bases__
|
|
669
|
+
else cls.__bases__
|
|
670
|
+
)
|
|
671
|
+
cls.__bases__ = bases
|
|
668
672
|
cls._jac_entry_funcs_ = on_entry # type: ignore
|
|
669
673
|
cls._jac_exit_funcs_ = on_exit # type: ignore
|
|
670
674
|
else:
|
|
@@ -724,6 +728,22 @@ class JacFeatureImpl(
|
|
|
724
728
|
|
|
725
729
|
return decorator
|
|
726
730
|
|
|
731
|
+
@staticmethod
|
|
732
|
+
@hookimpl
|
|
733
|
+
def make_root(
|
|
734
|
+
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
|
735
|
+
) -> Callable[[type], type]:
|
|
736
|
+
"""Create a obj architype."""
|
|
737
|
+
|
|
738
|
+
def decorator(cls: Type[Architype]) -> Type[Architype]:
|
|
739
|
+
"""Decorate class."""
|
|
740
|
+
cls = Jac.make_architype(
|
|
741
|
+
cls=cls, arch_base=Root, on_entry=on_entry, on_exit=on_exit
|
|
742
|
+
)
|
|
743
|
+
return cls
|
|
744
|
+
|
|
745
|
+
return decorator
|
|
746
|
+
|
|
727
747
|
@staticmethod
|
|
728
748
|
@hookimpl
|
|
729
749
|
def make_edge(
|
|
@@ -740,6 +760,25 @@ class JacFeatureImpl(
|
|
|
740
760
|
|
|
741
761
|
return decorator
|
|
742
762
|
|
|
763
|
+
@staticmethod
|
|
764
|
+
@hookimpl
|
|
765
|
+
def make_generic_edge(
|
|
766
|
+
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
|
767
|
+
) -> Callable[[type], type]:
|
|
768
|
+
"""Create a edge architype."""
|
|
769
|
+
|
|
770
|
+
def decorator(cls: Type[Architype]) -> Type[Architype]:
|
|
771
|
+
"""Decorate class."""
|
|
772
|
+
cls = Jac.make_architype(
|
|
773
|
+
cls=cls,
|
|
774
|
+
arch_base=GenericEdge,
|
|
775
|
+
on_entry=on_entry,
|
|
776
|
+
on_exit=on_exit,
|
|
777
|
+
)
|
|
778
|
+
return cls
|
|
779
|
+
|
|
780
|
+
return decorator
|
|
781
|
+
|
|
743
782
|
@staticmethod
|
|
744
783
|
@hookimpl
|
|
745
784
|
def make_walker(
|
|
@@ -1061,7 +1100,9 @@ class JacFeatureImpl(
|
|
|
1061
1100
|
@hookimpl
|
|
1062
1101
|
def get_root_type() -> Type[Root]:
|
|
1063
1102
|
"""Jac's root getter."""
|
|
1064
|
-
|
|
1103
|
+
from jaclang import Root as JRoot
|
|
1104
|
+
|
|
1105
|
+
return cast(Type[Root], JRoot)
|
|
1065
1106
|
|
|
1066
1107
|
@staticmethod
|
|
1067
1108
|
@hookimpl
|
|
@@ -1071,10 +1112,12 @@ class JacFeatureImpl(
|
|
|
1071
1112
|
conn_assign: Optional[tuple[tuple, tuple]],
|
|
1072
1113
|
) -> Callable[[NodeAnchor, NodeAnchor], EdgeArchitype]:
|
|
1073
1114
|
"""Jac's root getter."""
|
|
1074
|
-
|
|
1115
|
+
from jaclang import GenericEdge
|
|
1116
|
+
|
|
1117
|
+
ct = conn_type if conn_type else GenericEdge
|
|
1075
1118
|
|
|
1076
1119
|
def builder(source: NodeAnchor, target: NodeAnchor) -> EdgeArchitype:
|
|
1077
|
-
edge =
|
|
1120
|
+
edge = ct() if isinstance(ct, type) else ct
|
|
1078
1121
|
|
|
1079
1122
|
eanch = edge.__jac__ = EdgeAnchor(
|
|
1080
1123
|
architype=edge,
|
jaclang/plugin/feature.py
CHANGED
|
@@ -305,6 +305,13 @@ class JacFeature(
|
|
|
305
305
|
"""Create a node architype."""
|
|
306
306
|
return plugin_manager.hook.make_node(on_entry=on_entry, on_exit=on_exit)
|
|
307
307
|
|
|
308
|
+
@staticmethod
|
|
309
|
+
def make_root(
|
|
310
|
+
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
|
311
|
+
) -> Callable[[type], type]:
|
|
312
|
+
"""Create a root node architype."""
|
|
313
|
+
return plugin_manager.hook.make_root(on_entry=on_entry, on_exit=on_exit)
|
|
314
|
+
|
|
308
315
|
@staticmethod
|
|
309
316
|
def make_edge(
|
|
310
317
|
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
|
@@ -312,6 +319,13 @@ class JacFeature(
|
|
|
312
319
|
"""Create a edge architype."""
|
|
313
320
|
return plugin_manager.hook.make_edge(on_entry=on_entry, on_exit=on_exit)
|
|
314
321
|
|
|
322
|
+
@staticmethod
|
|
323
|
+
def make_generic_edge(
|
|
324
|
+
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
|
325
|
+
) -> Callable[[type], type]:
|
|
326
|
+
"""Create a edge architype."""
|
|
327
|
+
return plugin_manager.hook.make_generic_edge(on_entry=on_entry, on_exit=on_exit)
|
|
328
|
+
|
|
315
329
|
@staticmethod
|
|
316
330
|
def make_walker(
|
|
317
331
|
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
jaclang/plugin/spec.py
CHANGED
|
@@ -295,6 +295,14 @@ class JacFeatureSpec(
|
|
|
295
295
|
"""Create a node architype."""
|
|
296
296
|
raise NotImplementedError
|
|
297
297
|
|
|
298
|
+
@staticmethod
|
|
299
|
+
@hookspec(firstresult=True)
|
|
300
|
+
def make_root(
|
|
301
|
+
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
|
302
|
+
) -> Callable[[type], type]:
|
|
303
|
+
"""Create a root node architype."""
|
|
304
|
+
raise NotImplementedError
|
|
305
|
+
|
|
298
306
|
@staticmethod
|
|
299
307
|
@hookspec(firstresult=True)
|
|
300
308
|
def make_edge(
|
|
@@ -303,6 +311,14 @@ class JacFeatureSpec(
|
|
|
303
311
|
"""Create a edge architype."""
|
|
304
312
|
raise NotImplementedError
|
|
305
313
|
|
|
314
|
+
@staticmethod
|
|
315
|
+
@hookspec(firstresult=True)
|
|
316
|
+
def make_generic_edge(
|
|
317
|
+
on_entry: list[DSFunc], on_exit: list[DSFunc]
|
|
318
|
+
) -> Callable[[type], type]:
|
|
319
|
+
"""Create a generic edge architype."""
|
|
320
|
+
raise NotImplementedError
|
|
321
|
+
|
|
306
322
|
@staticmethod
|
|
307
323
|
@hookspec(firstresult=True)
|
|
308
324
|
def make_walker(
|
|
@@ -748,7 +748,7 @@ class TestJaseciPlugin(TestCase):
|
|
|
748
748
|
def test_savable_object(self) -> None:
|
|
749
749
|
"""Test ObjectAnchor save."""
|
|
750
750
|
global session
|
|
751
|
-
session = self.fixture_abs_path("
|
|
751
|
+
session = self.fixture_abs_path("savable_object.session")
|
|
752
752
|
|
|
753
753
|
self._output2buffer()
|
|
754
754
|
|
jaclang/runtimelib/architype.py
CHANGED
|
@@ -12,6 +12,7 @@ from types import UnionType
|
|
|
12
12
|
from typing import Any, Callable, ClassVar, Optional, TypeVar
|
|
13
13
|
from uuid import UUID, uuid4
|
|
14
14
|
|
|
15
|
+
|
|
15
16
|
logger = getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
TARCH = TypeVar("TARCH", bound="Architype")
|
|
@@ -285,21 +286,13 @@ class ObjectArchitype(Architype):
|
|
|
285
286
|
self.__jac__ = ObjectAnchor(architype=self)
|
|
286
287
|
|
|
287
288
|
|
|
288
|
-
@dataclass(eq=False)
|
|
289
289
|
class GenericEdge(EdgeArchitype):
|
|
290
|
-
"""Generic
|
|
291
|
-
|
|
292
|
-
_jac_entry_funcs_: ClassVar[list[DSFunc]] = []
|
|
293
|
-
_jac_exit_funcs_: ClassVar[list[DSFunc]] = []
|
|
290
|
+
"""Generic Edge."""
|
|
294
291
|
|
|
295
292
|
|
|
296
|
-
@dataclass(eq=False)
|
|
297
293
|
class Root(NodeArchitype):
|
|
298
294
|
"""Generic Root Node."""
|
|
299
295
|
|
|
300
|
-
_jac_entry_funcs_: ClassVar[list[DSFunc]] = []
|
|
301
|
-
_jac_exit_funcs_: ClassVar[list[DSFunc]] = []
|
|
302
|
-
|
|
303
296
|
def __init__(self) -> None:
|
|
304
297
|
"""Create root node."""
|
|
305
298
|
self.__jac__ = NodeAnchor(architype=self, persistent=True, edges=[])
|
|
@@ -315,16 +308,13 @@ class DSFunc:
|
|
|
315
308
|
@cached_property
|
|
316
309
|
def trigger(self) -> type | UnionType | tuple[type | UnionType, ...] | None:
|
|
317
310
|
"""Get function parameter annotations."""
|
|
318
|
-
|
|
319
|
-
(
|
|
320
|
-
|
|
321
|
-
.
|
|
322
|
-
.annotation
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
else None
|
|
326
|
-
)
|
|
327
|
-
return None if t is inspect._empty else t
|
|
311
|
+
if self.func:
|
|
312
|
+
parameters = inspect.signature(self.func, eval_str=True).parameters
|
|
313
|
+
if len(parameters) >= 2:
|
|
314
|
+
second_param = list(parameters.values())[1]
|
|
315
|
+
ty = second_param.annotation
|
|
316
|
+
return ty if ty != inspect._empty else None
|
|
317
|
+
return None
|
|
328
318
|
|
|
329
319
|
def resolve(self, cls: type) -> None:
|
|
330
320
|
"""Resolve the function."""
|
jaclang/runtimelib/context.py
CHANGED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import unittest
|
|
6
6
|
from contextvars import ContextVar
|
|
7
7
|
from dataclasses import MISSING
|
|
8
|
-
from typing import Any, Callable, Optional, cast
|
|
8
|
+
from typing import Any, Callable, ClassVar, Optional, cast
|
|
9
9
|
from uuid import UUID
|
|
10
10
|
|
|
11
11
|
from .architype import NodeAnchor, Root
|
|
@@ -13,13 +13,7 @@ from .memory import Memory, ShelfStorage
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
EXECUTION_CONTEXT = ContextVar[Optional["ExecutionContext"]]("ExecutionContext")
|
|
16
|
-
|
|
17
16
|
SUPER_ROOT_UUID = UUID("00000000-0000-0000-0000-000000000000")
|
|
18
|
-
SUPER_ROOT_ARCHITYPE = object.__new__(Root)
|
|
19
|
-
SUPER_ROOT_ANCHOR = NodeAnchor(
|
|
20
|
-
id=SUPER_ROOT_UUID, architype=SUPER_ROOT_ARCHITYPE, persistent=False, edges=[]
|
|
21
|
-
)
|
|
22
|
-
SUPER_ROOT_ARCHITYPE.__jac__ = SUPER_ROOT_ANCHOR
|
|
23
17
|
|
|
24
18
|
|
|
25
19
|
class ExecutionContext:
|
|
@@ -32,6 +26,9 @@ class ExecutionContext:
|
|
|
32
26
|
root: NodeAnchor
|
|
33
27
|
entry_node: NodeAnchor
|
|
34
28
|
|
|
29
|
+
# A context change event subscription list, those who want to listen ctx change will register here.
|
|
30
|
+
on_ctx_change: ClassVar[list[Callable[[ExecutionContext | None], None]]] = []
|
|
31
|
+
|
|
35
32
|
def init_anchor(
|
|
36
33
|
self,
|
|
37
34
|
anchor_id: str | None,
|
|
@@ -52,6 +49,8 @@ class ExecutionContext:
|
|
|
52
49
|
"""Close current ExecutionContext."""
|
|
53
50
|
self.mem.close()
|
|
54
51
|
EXECUTION_CONTEXT.set(None)
|
|
52
|
+
for func in ExecutionContext.on_ctx_change:
|
|
53
|
+
func(EXECUTION_CONTEXT.get(None))
|
|
55
54
|
|
|
56
55
|
@staticmethod
|
|
57
56
|
def create(
|
|
@@ -60,6 +59,8 @@ class ExecutionContext:
|
|
|
60
59
|
auto_close: bool = True,
|
|
61
60
|
) -> ExecutionContext:
|
|
62
61
|
"""Create ExecutionContext."""
|
|
62
|
+
from jaclang import Root
|
|
63
|
+
|
|
63
64
|
ctx = ExecutionContext()
|
|
64
65
|
ctx.mem = ShelfStorage(session)
|
|
65
66
|
ctx.reports = []
|
|
@@ -67,7 +68,7 @@ class ExecutionContext:
|
|
|
67
68
|
if not isinstance(
|
|
68
69
|
system_root := ctx.mem.find_by_id(SUPER_ROOT_UUID), NodeAnchor
|
|
69
70
|
):
|
|
70
|
-
system_root = Root().__jac__
|
|
71
|
+
system_root = cast(NodeAnchor, Root().__jac__) # type: ignore[attr-defined]
|
|
71
72
|
system_root.id = SUPER_ROOT_UUID
|
|
72
73
|
ctx.mem.set(system_root.id, system_root)
|
|
73
74
|
|
|
@@ -79,6 +80,8 @@ class ExecutionContext:
|
|
|
79
80
|
old_ctx.close()
|
|
80
81
|
|
|
81
82
|
EXECUTION_CONTEXT.set(ctx)
|
|
83
|
+
for func in ExecutionContext.on_ctx_change:
|
|
84
|
+
func(EXECUTION_CONTEXT.get(None))
|
|
82
85
|
|
|
83
86
|
return ctx
|
|
84
87
|
|
|
@@ -95,7 +98,20 @@ class ExecutionContext:
|
|
|
95
98
|
if ctx := EXECUTION_CONTEXT.get(None):
|
|
96
99
|
return cast(Root, ctx.root.architype)
|
|
97
100
|
|
|
98
|
-
return
|
|
101
|
+
return cast(Root, ExecutionContext.global_system_root().architype)
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def global_system_root() -> NodeAnchor:
|
|
105
|
+
"""Get global system root."""
|
|
106
|
+
from jaclang import Root
|
|
107
|
+
|
|
108
|
+
if not (sr_anch := getattr(ExecutionContext, "system_root", None)):
|
|
109
|
+
sr_arch = Root()
|
|
110
|
+
sr_anch = sr_arch.__jac__ # type: ignore[attr-defined]
|
|
111
|
+
sr_anch.id = SUPER_ROOT_UUID
|
|
112
|
+
sr_anch.persistent = False
|
|
113
|
+
ExecutionContext.system_root = sr_anch
|
|
114
|
+
return sr_anch
|
|
99
115
|
|
|
100
116
|
|
|
101
117
|
class JacTestResult(unittest.TextTestResult):
|
jaclang/settings.py
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
obj mainObject;
|
|
2
|
+
|
|
3
|
+
:obj:mainObject{
|
|
4
|
+
can greet;
|
|
5
|
+
obj subObject;
|
|
6
|
+
}
|
|
7
|
+
can foo{
|
|
8
|
+
obj ObjInsideFunction;
|
|
9
|
+
return ObjInsideFunction();
|
|
10
|
+
}
|
|
11
|
+
:can:foo:obj:ObjInsideFunction{
|
|
12
|
+
can bar{
|
|
13
|
+
print("Hello,from bar in kk");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
with entry{
|
|
18
|
+
foo().bar();
|
|
19
|
+
}
|
|
20
|
+
:obj:mainObject:can:greet{
|
|
21
|
+
print("Greeting: Hello, World!");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:obj:mainObject:obj:subObject{
|
|
25
|
+
can displayMessage;
|
|
26
|
+
can shortMessage{
|
|
27
|
+
print("Hello, World!");
|
|
28
|
+
}
|
|
29
|
+
obj nestedObject;
|
|
30
|
+
}
|
|
31
|
+
:obj:mainObject:obj:subObject:can:displayMessage{
|
|
32
|
+
print("Repeated: Hello!");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:obj:mainObject:obj:subObject:obj:nestedObject{
|
|
36
|
+
can lastMessage;
|
|
37
|
+
can finalMessage{
|
|
38
|
+
print("Final message:!");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:obj:mainObject:obj:subObject:obj:nestedObject:can:lastMessage{
|
|
43
|
+
# impl mainObject.subObject.nestedObject{ # TODO
|
|
44
|
+
print("Last message:!");
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
with entry{
|
|
50
|
+
mainObject().greet();
|
|
51
|
+
mainObject().subObject().displayMessage();
|
|
52
|
+
mainObject().subObject().shortMessage();
|
|
53
|
+
mainObject().subObject().nestedObject().lastMessage();
|
|
54
|
+
mainObject().subObject().nestedObject().finalMessage();
|
|
55
|
+
}
|
jaclang/tests/test_language.py
CHANGED
|
@@ -11,7 +11,7 @@ from jaclang import jac_import
|
|
|
11
11
|
from jaclang.cli import cli
|
|
12
12
|
from jaclang.compiler.compile import jac_file_to_pass, jac_pass_to_pass, jac_str_to_pass
|
|
13
13
|
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
14
|
-
from jaclang.runtimelib.context import
|
|
14
|
+
from jaclang.runtimelib.context import ExecutionContext
|
|
15
15
|
from jaclang.runtimelib.machine import JacMachine, JacProgram
|
|
16
16
|
from jaclang.utils.test import TestCase
|
|
17
17
|
|
|
@@ -21,7 +21,7 @@ class JacLanguageTests(TestCase):
|
|
|
21
21
|
|
|
22
22
|
def setUp(self) -> None:
|
|
23
23
|
"""Set up test."""
|
|
24
|
-
|
|
24
|
+
ExecutionContext.global_system_root().edges.clear()
|
|
25
25
|
JacMachine(self.fixture_abs_path("./")).attach_program(
|
|
26
26
|
JacProgram(mod_bundle=None, bytecode=None, sem_ir=None)
|
|
27
27
|
)
|
|
@@ -118,19 +118,19 @@ class JacLanguageTests(TestCase):
|
|
|
118
118
|
stdout_value = captured_output.getvalue()
|
|
119
119
|
|
|
120
120
|
expected_outputs = [
|
|
121
|
-
"+-- AtomTrailer - Type:
|
|
122
|
-
" +-- Name - arr - Type:
|
|
123
|
-
"
|
|
124
|
-
" +-- Token - [,",
|
|
121
|
+
"+-- AtomTrailer - Type: jaclang.JacList[builtins.int]",
|
|
122
|
+
" +-- Name - arr - Type: jaclang.JacList[jaclang.JacList[builtins.int]], SymbolTable: None",
|
|
123
|
+
"+-- IndexSlice - [IndexSlice] - Type: jaclang.JacList[jaclang.JacList[builtins.int]], SymbolTable: None",
|
|
124
|
+
" +-- Token - [, ",
|
|
125
125
|
" +-- Int - 1 - Type: Literal[1]?, SymbolTable: None",
|
|
126
|
-
" +-- Token - :,",
|
|
126
|
+
" +-- Token - :, ",
|
|
127
127
|
" +-- Int - 3 - Type: Literal[3]?, SymbolTable: None",
|
|
128
|
-
" +-- Token - ,,",
|
|
128
|
+
" +-- Token - ,, ",
|
|
129
129
|
" +-- Int - 1 - Type: Literal[1]?, SymbolTable: None",
|
|
130
|
-
" +-- Token - :,",
|
|
131
|
-
" +-- Token - :,",
|
|
130
|
+
" +-- Token - :, ",
|
|
131
|
+
" +-- Token - :, ",
|
|
132
132
|
" +-- Int - 2 - Type: Literal[2]?, SymbolTable: None",
|
|
133
|
-
" +-- Token - ],",
|
|
133
|
+
" +-- Token - ], ",
|
|
134
134
|
]
|
|
135
135
|
|
|
136
136
|
for expected in expected_outputs:
|
|
@@ -1033,11 +1033,11 @@ class JacLanguageTests(TestCase):
|
|
|
1033
1033
|
stdout_value,
|
|
1034
1034
|
)
|
|
1035
1035
|
self.assertIn(
|
|
1036
|
-
"Walkers in bar:\n - Walker: bar_walk",
|
|
1036
|
+
"Walkers in bar:\n - Walker: Walker\n - Walker: bar_walk",
|
|
1037
1037
|
stdout_value,
|
|
1038
1038
|
)
|
|
1039
1039
|
self.assertIn("Nodes in bar:\n - Node: Item", stdout_value)
|
|
1040
|
-
self.assertIn("Edges in bar:\n - Edge: Link", stdout_value)
|
|
1040
|
+
self.assertIn("Edges in bar:\n - Edge: Edge\n - Edge: Link", stdout_value)
|
|
1041
1041
|
self.assertIn("Item value: 0", stdout_value)
|
|
1042
1042
|
self.assertIn("Created 5 items.", stdout_value)
|
|
1043
1043
|
|
|
@@ -1247,3 +1247,17 @@ class JacLanguageTests(TestCase):
|
|
|
1247
1247
|
"walker exit\n",
|
|
1248
1248
|
captured_output.getvalue(),
|
|
1249
1249
|
)
|
|
1250
|
+
|
|
1251
|
+
def test_nested_impls(self) -> None:
|
|
1252
|
+
"""Test complex nested impls."""
|
|
1253
|
+
captured_output = io.StringIO()
|
|
1254
|
+
sys.stdout = captured_output
|
|
1255
|
+
jac_import("nested_impls", base_path=self.fixture_abs_path("./"))
|
|
1256
|
+
sys.stdout = sys.__stdout__
|
|
1257
|
+
stdout_value = captured_output.getvalue().split("\n")
|
|
1258
|
+
self.assertIn("Hello,from bar in kk", stdout_value[0])
|
|
1259
|
+
self.assertIn("Greeting: Hello, World!", stdout_value[1])
|
|
1260
|
+
self.assertIn("Repeated: Hello", stdout_value[2])
|
|
1261
|
+
self.assertIn("Hello, World!", stdout_value[3])
|
|
1262
|
+
self.assertIn("Last message:!", stdout_value[4])
|
|
1263
|
+
self.assertIn("Final message:!", stdout_value[5])
|
jaclang/tests/test_reference.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Callable, Optional
|
|
|
7
7
|
|
|
8
8
|
import jaclang
|
|
9
9
|
from jaclang.compiler.compile import jac_file_to_pass
|
|
10
|
-
from jaclang.runtimelib.context import
|
|
10
|
+
from jaclang.runtimelib.context import ExecutionContext
|
|
11
11
|
from jaclang.utils.test import TestCase
|
|
12
12
|
|
|
13
13
|
|
|
@@ -52,7 +52,7 @@ class JacReferenceTests(TestCase):
|
|
|
52
52
|
"""Test file."""
|
|
53
53
|
|
|
54
54
|
def execute_and_capture_output(code: str | bytes, filename: str = "") -> str:
|
|
55
|
-
|
|
55
|
+
ExecutionContext.global_system_root().edges.clear()
|
|
56
56
|
f = io.StringIO()
|
|
57
57
|
with redirect_stdout(f):
|
|
58
58
|
exec(
|
jaclang/utils/helpers.py
CHANGED
|
@@ -73,13 +73,14 @@ def extract_headings(file_path: str) -> dict[str, tuple[int, int]]:
|
|
|
73
73
|
current_heading = None
|
|
74
74
|
start_line = 0
|
|
75
75
|
for idx, line in enumerate(lines, start=1):
|
|
76
|
-
|
|
76
|
+
line = line.strip().removesuffix(".")
|
|
77
|
+
if line.startswith("// [Heading]:"):
|
|
77
78
|
if current_heading is not None:
|
|
78
79
|
headings[current_heading] = (
|
|
79
80
|
start_line,
|
|
80
81
|
idx - 2,
|
|
81
82
|
) # Subtract 1 to get the correct end line
|
|
82
|
-
current_heading = line.
|
|
83
|
+
current_heading = line.removeprefix("// [Heading]:")
|
|
83
84
|
start_line = idx + 1
|
|
84
85
|
# Add the last heading
|
|
85
86
|
if current_heading is not None:
|
|
@@ -95,7 +96,7 @@ def auto_generate_refs() -> None:
|
|
|
95
96
|
result = extract_headings(file_path)
|
|
96
97
|
created_file_path = os.path.join(
|
|
97
98
|
os.path.split(os.path.dirname(__file__))[0],
|
|
98
|
-
"../support/jac-lang.org/docs/
|
|
99
|
+
"../support/jac-lang.org/docs/lang_ref/jac_ref.md",
|
|
99
100
|
)
|
|
100
101
|
destination_folder = os.path.join(
|
|
101
102
|
os.path.split(os.path.dirname(__file__))[0], "../examples/reference/"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: jaclang
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.31
|
|
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
|
License: MIT
|
|
6
6
|
Keywords: jac,jaclang,jaseci,python,programming-language,machine-learning,artificial-intelligence
|