jaclang 0.8.4__py3-none-any.whl → 0.8.6__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.md +1 -0
- jaclang/cli/cli.py +109 -37
- jaclang/compiler/jac.lark +3 -3
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +14 -21
- jaclang/compiler/passes/main/__init__.py +5 -1
- jaclang/compiler/passes/main/binder_pass.py +594 -0
- jaclang/compiler/passes/main/cfg_build_pass.py +21 -1
- jaclang/compiler/passes/main/import_pass.py +8 -256
- jaclang/compiler/passes/main/inheritance_pass.py +10 -3
- jaclang/compiler/passes/main/pyast_gen_pass.py +92 -77
- jaclang/compiler/passes/main/pyast_load_pass.py +24 -13
- jaclang/compiler/passes/main/sem_def_match_pass.py +1 -1
- jaclang/compiler/passes/main/sym_tab_build_pass.py +4 -0
- jaclang/compiler/passes/main/tests/fixtures/M1.jac +3 -0
- jaclang/compiler/passes/main/tests/fixtures/cfg_has_var.jac +12 -0
- jaclang/compiler/passes/main/tests/fixtures/cfg_if_no_else.jac +11 -0
- jaclang/compiler/passes/main/tests/fixtures/cfg_return.jac +9 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_imported.jac +2 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_importer.jac +6 -0
- jaclang/compiler/passes/main/tests/fixtures/data_spatial_types.jac +1 -1
- jaclang/compiler/passes/main/tests/fixtures/import_symbol_type_infer.jac +11 -0
- jaclang/compiler/passes/main/tests/fixtures/infer_type_assignment.jac +5 -0
- jaclang/compiler/passes/main/tests/fixtures/member_access_type_inferred.jac +13 -0
- jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +11 -0
- jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +47 -0
- jaclang/compiler/passes/main/tests/fixtures/type_annotation_assignment.jac +8 -0
- jaclang/compiler/passes/main/tests/test_binder_pass.py +111 -0
- jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +62 -24
- jaclang/compiler/passes/main/tests/test_checker_pass.py +87 -0
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +13 -13
- jaclang/compiler/passes/main/tests/test_sem_def_match_pass.py +6 -6
- jaclang/compiler/passes/main/type_checker_pass.py +128 -0
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +2 -0
- jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +3 -0
- jaclang/compiler/program.py +32 -11
- jaclang/compiler/tests/test_sr_errors.py +32 -0
- jaclang/compiler/type_system/__init__.py +1 -0
- jaclang/compiler/type_system/type_evaluator.py +421 -0
- jaclang/compiler/type_system/type_utils.py +41 -0
- jaclang/compiler/type_system/types.py +240 -0
- jaclang/compiler/unitree.py +36 -24
- jaclang/langserve/dev_engine.jac +645 -0
- jaclang/langserve/dev_server.jac +201 -0
- jaclang/langserve/engine.jac +24 -5
- jaclang/langserve/tests/server_test/test_lang_serve.py +2 -2
- jaclang/langserve/tests/test_dev_server.py +80 -0
- jaclang/langserve/tests/test_server.py +13 -0
- jaclang/runtimelib/builtin.py +28 -39
- jaclang/runtimelib/importer.py +34 -63
- jaclang/runtimelib/machine.py +48 -64
- jaclang/runtimelib/memory.py +23 -5
- jaclang/runtimelib/tests/fixtures/savable_object.jac +10 -2
- jaclang/runtimelib/utils.py +42 -6
- jaclang/tests/fixtures/edge_node_walk.jac +1 -1
- jaclang/tests/fixtures/edges_walk.jac +1 -1
- jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
- jaclang/tests/fixtures/py_run.jac +8 -0
- jaclang/tests/fixtures/py_run.py +23 -0
- jaclang/tests/fixtures/pyfunc.py +2 -0
- jaclang/tests/fixtures/pyfunc_fmt.py +60 -0
- jaclang/tests/fixtures/pyfunc_fstr.py +25 -0
- jaclang/tests/fixtures/pyfunc_kwesc.py +33 -0
- jaclang/tests/fixtures/python_run_test.py +19 -0
- jaclang/tests/test_cli.py +107 -0
- jaclang/tests/test_language.py +106 -5
- jaclang/utils/lang_tools.py +6 -3
- jaclang/utils/module_resolver.py +90 -0
- jaclang/utils/symtable_test_helpers.py +125 -0
- jaclang/utils/test.py +3 -4
- jaclang/vendor/interegular/__init__.py +34 -0
- jaclang/vendor/interegular/comparator.py +163 -0
- jaclang/vendor/interegular/fsm.py +1015 -0
- jaclang/vendor/interegular/patterns.py +732 -0
- jaclang/vendor/interegular/py.typed +0 -0
- jaclang/vendor/interegular/utils/__init__.py +15 -0
- jaclang/vendor/interegular/utils/simple_parser.py +165 -0
- jaclang/vendor/interegular-0.3.3.dist-info/INSTALLER +1 -0
- jaclang/vendor/interegular-0.3.3.dist-info/LICENSE.txt +21 -0
- jaclang/vendor/interegular-0.3.3.dist-info/METADATA +64 -0
- jaclang/vendor/interegular-0.3.3.dist-info/RECORD +20 -0
- jaclang/vendor/interegular-0.3.3.dist-info/REQUESTED +0 -0
- jaclang/vendor/interegular-0.3.3.dist-info/WHEEL +5 -0
- jaclang/vendor/interegular-0.3.3.dist-info/top_level.txt +1 -0
- {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/METADATA +2 -1
- {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/RECORD +88 -43
- {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/WHEEL +0 -0
- {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/entry_points.txt +0 -0
jaclang/runtimelib/machine.py
CHANGED
|
@@ -57,7 +57,6 @@ from jaclang.runtimelib.constructs import (
|
|
|
57
57
|
from jaclang.runtimelib.memory import Memory, Shelf, ShelfStorage
|
|
58
58
|
from jaclang.runtimelib.utils import (
|
|
59
59
|
all_issubclass,
|
|
60
|
-
collect_node_connections,
|
|
61
60
|
traverse_graph,
|
|
62
61
|
)
|
|
63
62
|
from jaclang.utils import infer_language
|
|
@@ -266,30 +265,6 @@ class JacAccessValidation:
|
|
|
266
265
|
class JacNode:
|
|
267
266
|
"""Jac Node Operations."""
|
|
268
267
|
|
|
269
|
-
@staticmethod
|
|
270
|
-
def node_dot(node: NodeArchetype, dot_file: Optional[str] = None) -> str:
|
|
271
|
-
"""Generate Dot file for visualizing nodes and edges."""
|
|
272
|
-
visited_nodes: set[NodeAnchor] = set()
|
|
273
|
-
connections: set[tuple[NodeArchetype, NodeArchetype, str]] = set()
|
|
274
|
-
unique_node_id_dict = {}
|
|
275
|
-
|
|
276
|
-
collect_node_connections(node.__jac__, visited_nodes, connections)
|
|
277
|
-
dot_content = 'digraph {\nnode [style="filled", shape="ellipse", fillcolor="invis", fontcolor="black"];\n'
|
|
278
|
-
for idx, i in enumerate([nodes_.archetype for nodes_ in visited_nodes]):
|
|
279
|
-
unique_node_id_dict[i] = (i.__class__.__name__, str(idx))
|
|
280
|
-
dot_content += f'{idx} [label="{i}"];\n'
|
|
281
|
-
dot_content += 'edge [color="gray", style="solid"];\n'
|
|
282
|
-
|
|
283
|
-
for pair in list(set(connections)):
|
|
284
|
-
dot_content += (
|
|
285
|
-
f"{unique_node_id_dict[pair[0]][1]} -> {unique_node_id_dict[pair[1]][1]}"
|
|
286
|
-
f' [label="{pair[2]}"];\n'
|
|
287
|
-
)
|
|
288
|
-
if dot_file:
|
|
289
|
-
with open(dot_file, "w") as f:
|
|
290
|
-
f.write(dot_content + "}")
|
|
291
|
-
return dot_content + "}"
|
|
292
|
-
|
|
293
268
|
@staticmethod
|
|
294
269
|
def get_edges(
|
|
295
270
|
origin: list[NodeArchetype], destination: DataSpatialDestination
|
|
@@ -879,6 +854,15 @@ class JacBasics:
|
|
|
879
854
|
"""Get current execution context."""
|
|
880
855
|
return JacMachine.exec_ctx
|
|
881
856
|
|
|
857
|
+
@staticmethod
|
|
858
|
+
def commit(anchor: Anchor | Archetype | None = None) -> None:
|
|
859
|
+
"""Commit all data from memory to datasource."""
|
|
860
|
+
if isinstance(anchor, Archetype):
|
|
861
|
+
anchor = anchor.__jac__
|
|
862
|
+
|
|
863
|
+
mem = JacMachineInterface.get_context().mem
|
|
864
|
+
mem.commit(anchor)
|
|
865
|
+
|
|
882
866
|
@staticmethod
|
|
883
867
|
def reset_graph(root: Optional[Root] = None) -> int:
|
|
884
868
|
"""Purge current or target graph."""
|
|
@@ -987,6 +971,7 @@ class JacBasics:
|
|
|
987
971
|
override_name: Optional[str] = None,
|
|
988
972
|
items: Optional[dict[str, Union[str, Optional[str]]]] = None,
|
|
989
973
|
reload_module: Optional[bool] = False,
|
|
974
|
+
lng: Optional[str] = None,
|
|
990
975
|
) -> tuple[types.ModuleType, ...]:
|
|
991
976
|
"""Core Import Process."""
|
|
992
977
|
from jaclang.runtimelib.importer import (
|
|
@@ -995,7 +980,8 @@ class JacBasics:
|
|
|
995
980
|
PythonImporter,
|
|
996
981
|
)
|
|
997
982
|
|
|
998
|
-
lng
|
|
983
|
+
if lng is None:
|
|
984
|
+
lng = infer_language(target, base_path)
|
|
999
985
|
|
|
1000
986
|
spec = ImportPathSpec(
|
|
1001
987
|
target,
|
|
@@ -1358,12 +1344,10 @@ class JacBasics:
|
|
|
1358
1344
|
return decorator
|
|
1359
1345
|
|
|
1360
1346
|
@staticmethod
|
|
1361
|
-
def call_llm(
|
|
1362
|
-
model: object, caller: Callable, args: dict[str | int, object]
|
|
1363
|
-
) -> Any: # noqa: ANN401
|
|
1347
|
+
def call_llm(model: object, mtir: object) -> Any: # noqa: ANN401
|
|
1364
1348
|
"""Call the LLM model."""
|
|
1365
1349
|
raise ImportError(
|
|
1366
|
-
"
|
|
1350
|
+
"byLLM is not installed. Please install it with `pip install byllm` and run `jac clean`."
|
|
1367
1351
|
)
|
|
1368
1352
|
|
|
1369
1353
|
|
|
@@ -1587,40 +1571,6 @@ class JacMachineInterface(
|
|
|
1587
1571
|
"""Jac Feature."""
|
|
1588
1572
|
|
|
1589
1573
|
|
|
1590
|
-
class JacMachine(JacMachineInterface):
|
|
1591
|
-
"""Jac Machine State."""
|
|
1592
|
-
|
|
1593
|
-
loaded_modules: dict[str, types.ModuleType] = {}
|
|
1594
|
-
base_path_dir: str = os.getcwd()
|
|
1595
|
-
program: JacProgram = JacProgram()
|
|
1596
|
-
pool: ThreadPoolExecutor = ThreadPoolExecutor()
|
|
1597
|
-
exec_ctx: ExecutionContext = ExecutionContext()
|
|
1598
|
-
|
|
1599
|
-
@staticmethod
|
|
1600
|
-
def set_base_path(base_path: str) -> None:
|
|
1601
|
-
"""Set the base path for the machine."""
|
|
1602
|
-
JacMachine.reset_machine()
|
|
1603
|
-
JacMachine.base_path_dir = (
|
|
1604
|
-
base_path if os.path.isdir(base_path) else os.path.dirname(base_path)
|
|
1605
|
-
)
|
|
1606
|
-
|
|
1607
|
-
@staticmethod
|
|
1608
|
-
def set_context(context: ExecutionContext) -> None:
|
|
1609
|
-
"""Set the context for the machine."""
|
|
1610
|
-
JacMachine.exec_ctx = context
|
|
1611
|
-
|
|
1612
|
-
@staticmethod
|
|
1613
|
-
def reset_machine() -> None:
|
|
1614
|
-
"""Reset the machine."""
|
|
1615
|
-
# for i in JacMachine.loaded_modules.values():
|
|
1616
|
-
# sys.modules.pop(i.__name__, None)
|
|
1617
|
-
JacMachine.loaded_modules.clear()
|
|
1618
|
-
JacMachine.base_path_dir = os.getcwd()
|
|
1619
|
-
JacMachine.program = JacProgram()
|
|
1620
|
-
JacMachine.pool = ThreadPoolExecutor()
|
|
1621
|
-
JacMachine.exec_ctx = ExecutionContext()
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
1574
|
def generate_plugin_helpers(
|
|
1625
1575
|
plugin_class: Type[Any],
|
|
1626
1576
|
) -> tuple[Type[Any], Type[Any], Type[Any]]:
|
|
@@ -1726,3 +1676,37 @@ def generate_plugin_helpers(
|
|
|
1726
1676
|
|
|
1727
1677
|
JacMachineSpec, JacMachineImpl, JacMachineInterface = generate_plugin_helpers(JacMachineInterface) # type: ignore[misc]
|
|
1728
1678
|
plugin_manager.add_hookspecs(JacMachineSpec)
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
class JacMachine(JacMachineInterface):
|
|
1682
|
+
"""Jac Machine State."""
|
|
1683
|
+
|
|
1684
|
+
loaded_modules: dict[str, types.ModuleType] = {}
|
|
1685
|
+
base_path_dir: str = os.getcwd()
|
|
1686
|
+
program: JacProgram = JacProgram()
|
|
1687
|
+
pool: ThreadPoolExecutor = ThreadPoolExecutor()
|
|
1688
|
+
exec_ctx: ExecutionContext = ExecutionContext()
|
|
1689
|
+
|
|
1690
|
+
@staticmethod
|
|
1691
|
+
def set_base_path(base_path: str) -> None:
|
|
1692
|
+
"""Set the base path for the machine."""
|
|
1693
|
+
JacMachine.reset_machine()
|
|
1694
|
+
JacMachine.base_path_dir = (
|
|
1695
|
+
base_path if os.path.isdir(base_path) else os.path.dirname(base_path)
|
|
1696
|
+
)
|
|
1697
|
+
|
|
1698
|
+
@staticmethod
|
|
1699
|
+
def set_context(context: ExecutionContext) -> None:
|
|
1700
|
+
"""Set the context for the machine."""
|
|
1701
|
+
JacMachine.exec_ctx = context
|
|
1702
|
+
|
|
1703
|
+
@staticmethod
|
|
1704
|
+
def reset_machine() -> None:
|
|
1705
|
+
"""Reset the machine."""
|
|
1706
|
+
# for i in JacMachine.loaded_modules.values():
|
|
1707
|
+
# sys.modules.pop(i.__name__, None)
|
|
1708
|
+
JacMachine.loaded_modules.clear()
|
|
1709
|
+
JacMachine.base_path_dir = os.getcwd()
|
|
1710
|
+
JacMachine.program = JacProgram()
|
|
1711
|
+
JacMachine.pool = ThreadPoolExecutor()
|
|
1712
|
+
JacMachine.exec_ctx = ExecutionContext()
|
jaclang/runtimelib/memory.py
CHANGED
|
@@ -82,6 +82,9 @@ class Memory(Generic[ID, TANCH]):
|
|
|
82
82
|
if anchor := self.__mem__.pop(id, None):
|
|
83
83
|
self.__gc__.add(anchor)
|
|
84
84
|
|
|
85
|
+
def commit(self, anchor: TANCH | None = None) -> None:
|
|
86
|
+
"""Commit all data from memory to datasource."""
|
|
87
|
+
|
|
85
88
|
|
|
86
89
|
@dataclass
|
|
87
90
|
class ShelfStorage(Memory[UUID, Anchor]):
|
|
@@ -94,12 +97,21 @@ class ShelfStorage(Memory[UUID, Anchor]):
|
|
|
94
97
|
super().__init__()
|
|
95
98
|
self.__shelf__ = open(session) if session else None # noqa: SIM115
|
|
96
99
|
|
|
97
|
-
def
|
|
98
|
-
"""
|
|
100
|
+
def commit(self, anchor: Anchor | None = None) -> None:
|
|
101
|
+
"""Commit all data from memory to datasource."""
|
|
99
102
|
if isinstance(self.__shelf__, Shelf):
|
|
100
|
-
|
|
101
|
-
self.
|
|
102
|
-
|
|
103
|
+
if anchor:
|
|
104
|
+
if anchor in self.__gc__:
|
|
105
|
+
self.__shelf__.pop(str(anchor.id), None)
|
|
106
|
+
self.__mem__.pop(anchor.id, None)
|
|
107
|
+
self.__gc__.remove(anchor)
|
|
108
|
+
else:
|
|
109
|
+
self.sync_mem_to_db([anchor.id])
|
|
110
|
+
return
|
|
111
|
+
|
|
112
|
+
for anc in self.__gc__:
|
|
113
|
+
self.__shelf__.pop(str(anc.id), None)
|
|
114
|
+
self.__mem__.pop(anc.id, None)
|
|
103
115
|
|
|
104
116
|
keys = set(self.__mem__.keys())
|
|
105
117
|
|
|
@@ -109,7 +121,13 @@ class ShelfStorage(Memory[UUID, Anchor]):
|
|
|
109
121
|
# additional after memory sync
|
|
110
122
|
self.sync_mem_to_db(set(self.__mem__.keys() - keys))
|
|
111
123
|
|
|
124
|
+
def close(self) -> None:
|
|
125
|
+
"""Close memory handler."""
|
|
126
|
+
self.commit()
|
|
127
|
+
|
|
128
|
+
if isinstance(self.__shelf__, Shelf):
|
|
112
129
|
self.__shelf__.close()
|
|
130
|
+
|
|
113
131
|
super().close()
|
|
114
132
|
|
|
115
133
|
def sync_mem_to_db(self, keys: Iterable[UUID]) -> None:
|
|
@@ -18,7 +18,7 @@ obj SavableObject {
|
|
|
18
18
|
|
|
19
19
|
walker create_custom_object {
|
|
20
20
|
can enter1 with `root entry {
|
|
21
|
-
|
|
21
|
+
self.obj = SavableObject(
|
|
22
22
|
val=0,
|
|
23
23
|
arr=[],
|
|
24
24
|
json={},
|
|
@@ -36,7 +36,15 @@ walker create_custom_object {
|
|
|
36
36
|
),
|
|
37
37
|
enum_field = Enum.A
|
|
38
38
|
);
|
|
39
|
-
|
|
39
|
+
save(self.obj);
|
|
40
|
+
|
|
41
|
+
# commit the object to db
|
|
42
|
+
commit(self.obj);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
can exit1 with `root exit {
|
|
46
|
+
# get directly from shelf
|
|
47
|
+
o = _.get_context().mem.__shelf__.get(str(self.obj.__jac__.id)).archetype;
|
|
40
48
|
print(jid(o));
|
|
41
49
|
print(o);
|
|
42
50
|
}
|
jaclang/runtimelib/utils.py
CHANGED
|
@@ -11,7 +11,36 @@ from typing import Callable, Iterator, TYPE_CHECKING
|
|
|
11
11
|
import jaclang.compiler.unitree as uni
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from jaclang.runtimelib.constructs import
|
|
14
|
+
from jaclang.runtimelib.constructs import NodeArchetype
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def read_file_with_encoding(file_path: str) -> str:
|
|
18
|
+
"""Read file with proper encoding detection."""
|
|
19
|
+
encodings_to_try = [
|
|
20
|
+
"utf-8-sig",
|
|
21
|
+
"utf-8",
|
|
22
|
+
"utf-16",
|
|
23
|
+
"utf-16le",
|
|
24
|
+
"utf-16be",
|
|
25
|
+
# "latin-1", # TODO: Support reading files with Latin-1 encoding
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
for encoding in encodings_to_try:
|
|
29
|
+
try:
|
|
30
|
+
with open(file_path, "r", encoding=encoding) as f:
|
|
31
|
+
return f.read()
|
|
32
|
+
except UnicodeError:
|
|
33
|
+
continue
|
|
34
|
+
except Exception as e:
|
|
35
|
+
raise IOError(
|
|
36
|
+
f"Could not read file {file_path}: {e}. "
|
|
37
|
+
f"Report this issue: https://github.com/jaseci-labs/jaseci/issues"
|
|
38
|
+
) from e
|
|
39
|
+
|
|
40
|
+
raise IOError(
|
|
41
|
+
f"Could not read file {file_path} with any encoding. "
|
|
42
|
+
f"Report this issue: https://github.com/jaseci-labs/jaseci/issues"
|
|
43
|
+
)
|
|
15
44
|
|
|
16
45
|
|
|
17
46
|
@contextmanager
|
|
@@ -28,25 +57,32 @@ def sys_path_context(path: str) -> Iterator[None]:
|
|
|
28
57
|
|
|
29
58
|
|
|
30
59
|
def collect_node_connections(
|
|
31
|
-
current_node:
|
|
60
|
+
current_node: NodeArchetype,
|
|
32
61
|
visited_nodes: set,
|
|
33
62
|
connections: set,
|
|
63
|
+
edge_ids: set,
|
|
34
64
|
) -> None:
|
|
35
65
|
"""Nodes and edges representing the graph are collected in visited_nodes and connections."""
|
|
36
66
|
if current_node not in visited_nodes:
|
|
37
67
|
visited_nodes.add(current_node)
|
|
38
|
-
edges = current_node.edges
|
|
68
|
+
edges = current_node.__jac__.edges
|
|
39
69
|
for edge_ in edges:
|
|
70
|
+
if edge_.id in edge_ids:
|
|
71
|
+
continue
|
|
72
|
+
edge_ids.add(edge_.id)
|
|
40
73
|
target = edge_.target
|
|
41
74
|
if target:
|
|
42
75
|
connections.add(
|
|
43
76
|
(
|
|
44
|
-
|
|
77
|
+
edge_.id,
|
|
78
|
+
edge_.source.archetype,
|
|
45
79
|
target.archetype,
|
|
46
|
-
edge_.
|
|
80
|
+
edge_.archetype,
|
|
47
81
|
)
|
|
48
82
|
)
|
|
49
|
-
collect_node_connections(
|
|
83
|
+
collect_node_connections(
|
|
84
|
+
target.archetype, visited_nodes, connections, edge_ids
|
|
85
|
+
)
|
|
50
86
|
|
|
51
87
|
|
|
52
88
|
def traverse_graph(
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Print Hello, World!
|
|
2
|
+
print("Hello, World!")
|
|
3
|
+
|
|
4
|
+
a = 5
|
|
5
|
+
b = 3
|
|
6
|
+
sum_ab = a + b
|
|
7
|
+
print("Sum:", sum_ab)
|
|
8
|
+
|
|
9
|
+
num = 7
|
|
10
|
+
if num % 2 == 0:
|
|
11
|
+
print(num, "is even")
|
|
12
|
+
else:
|
|
13
|
+
print(num, "is odd")
|
|
14
|
+
|
|
15
|
+
# Loop through a list
|
|
16
|
+
fruits = ["apple", "banana", "cherry"]
|
|
17
|
+
for fruit in fruits:
|
|
18
|
+
print(fruit)
|
|
19
|
+
|
|
20
|
+
def greet(name):
|
|
21
|
+
return f"Hello, {name}!"
|
|
22
|
+
|
|
23
|
+
print(greet("Alice"))
|
jaclang/tests/fixtures/pyfunc.py
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
if __name__ == "__main__":
|
|
6
|
+
|
|
7
|
+
def foo():
|
|
8
|
+
print("One")
|
|
9
|
+
return "foo"
|
|
10
|
+
foo()
|
|
11
|
+
|
|
12
|
+
condition = True
|
|
13
|
+
|
|
14
|
+
if condition:
|
|
15
|
+
|
|
16
|
+
print("Two")
|
|
17
|
+
|
|
18
|
+
def bar():
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
main_mod = None
|
|
22
|
+
bar()
|
|
23
|
+
|
|
24
|
+
def baz():
|
|
25
|
+
print("Three")
|
|
26
|
+
return "baz"
|
|
27
|
+
|
|
28
|
+
print(baz())
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
a = 90
|
|
33
|
+
except FileNotFoundError:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
condition = 10
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
while condition:
|
|
41
|
+
print("Processing...")
|
|
42
|
+
|
|
43
|
+
while condition:
|
|
44
|
+
print("Four")
|
|
45
|
+
condition -= 10
|
|
46
|
+
break
|
|
47
|
+
|
|
48
|
+
if condition:
|
|
49
|
+
|
|
50
|
+
def foo():
|
|
51
|
+
return
|
|
52
|
+
foo()
|
|
53
|
+
print("Exiting the loop.")
|
|
54
|
+
|
|
55
|
+
if condition:
|
|
56
|
+
print("still +")
|
|
57
|
+
def foo():
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
print("The End.")
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
name = 'Peter'
|
|
7
|
+
relation = 'mother'
|
|
8
|
+
mom_name = 'Mary'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
print(f"Hello {name}")
|
|
12
|
+
print(f"Hello {name} {name}")
|
|
13
|
+
print(f"{name} squared is {name} {name}")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
print(f"{name.upper()}! wrong poem.")
|
|
17
|
+
print(f"Hello {name} , yoo {relation} is {mom_name}. Myself, I am {name}.")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
item = "Apple"
|
|
22
|
+
price = 1.23
|
|
23
|
+
|
|
24
|
+
print(f"Left aligned: {item:<10} | Price: {price:.2f}")
|
|
25
|
+
print(f"{name = } 🤔")
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def foo(type= 90):
|
|
5
|
+
"""This is a function with a docstring."""
|
|
6
|
+
return type
|
|
7
|
+
|
|
8
|
+
print(foo(type=89))
|
|
9
|
+
|
|
10
|
+
def bar(node= 12, *args,**kwargs):
|
|
11
|
+
"""This is another function with a docstring."""
|
|
12
|
+
return node, args, kwargs
|
|
13
|
+
|
|
14
|
+
print(str(bar(node=13, a=1, b=2)))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
functions = [
|
|
18
|
+
|
|
19
|
+
dict(
|
|
20
|
+
name="replace_lines",
|
|
21
|
+
args=[
|
|
22
|
+
dict(name="text", type="str", default=None),
|
|
23
|
+
dict(name="old", type="str", default=None),
|
|
24
|
+
dict(name="new", type="str", default=None),
|
|
25
|
+
],
|
|
26
|
+
returns=dict(type="str", default=None),
|
|
27
|
+
),
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
print(f"Functions: {functions}")
|
|
31
|
+
|
|
32
|
+
dict = 90
|
|
33
|
+
print(f"Dict: {dict}")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Simple Python test file for jac run command."""
|
|
2
|
+
|
|
3
|
+
print("Hello from Python!")
|
|
4
|
+
print("This is a test Python file.")
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
"""Main function to demonstrate execution."""
|
|
8
|
+
result = 42
|
|
9
|
+
print(f"Result: {result}")
|
|
10
|
+
return result
|
|
11
|
+
|
|
12
|
+
if __name__ == "__main__":
|
|
13
|
+
main()
|
|
14
|
+
print("Python execution completed.")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from jaclang.tests.fixtures import py_namedexpr
|
|
18
|
+
|
|
19
|
+
py_namedexpr.walrus_example()
|
jaclang/tests/test_cli.py
CHANGED
|
@@ -35,6 +35,73 @@ class JacCliTests(TestCase):
|
|
|
35
35
|
|
|
36
36
|
self.assertIn("Hello World!", stdout_value)
|
|
37
37
|
|
|
38
|
+
def test_jac_cli_run_python_file(self) -> None:
|
|
39
|
+
"""Test running Python files with jac run command."""
|
|
40
|
+
captured_output = io.StringIO()
|
|
41
|
+
sys.stdout = captured_output
|
|
42
|
+
|
|
43
|
+
cli.run(self.fixture_abs_path("python_run_test.py"))
|
|
44
|
+
|
|
45
|
+
sys.stdout = sys.__stdout__
|
|
46
|
+
stdout_value = captured_output.getvalue()
|
|
47
|
+
|
|
48
|
+
self.assertIn("Hello from Python!", stdout_value)
|
|
49
|
+
self.assertIn("This is a test Python file.", stdout_value)
|
|
50
|
+
self.assertIn("Result: 42", stdout_value)
|
|
51
|
+
self.assertIn("Python execution completed.", stdout_value)
|
|
52
|
+
self.assertIn("10", stdout_value)
|
|
53
|
+
|
|
54
|
+
def test_jac_run_py_fstr(self) -> None:
|
|
55
|
+
"""Test running Python files with jac run command."""
|
|
56
|
+
captured_output = io.StringIO()
|
|
57
|
+
sys.stdout = captured_output
|
|
58
|
+
|
|
59
|
+
cli.run(self.fixture_abs_path("pyfunc_fstr.py"))
|
|
60
|
+
|
|
61
|
+
sys.stdout = sys.__stdout__
|
|
62
|
+
stdout_value = captured_output.getvalue()
|
|
63
|
+
|
|
64
|
+
self.assertIn("Hello Peter", stdout_value)
|
|
65
|
+
self.assertIn("Hello Peter Peter", stdout_value)
|
|
66
|
+
self.assertIn("Peter squared is Peter Peter", stdout_value)
|
|
67
|
+
self.assertIn("PETER! wrong poem", stdout_value)
|
|
68
|
+
self.assertIn("Hello Peter , yoo mother is Mary. Myself, I am Peter.", stdout_value)
|
|
69
|
+
self.assertIn("Left aligned: Apple | Price: 1.23", stdout_value)
|
|
70
|
+
self.assertIn("name = Peter 🤔", stdout_value)
|
|
71
|
+
|
|
72
|
+
def test_jac_run_py_fmt(self) -> None:
|
|
73
|
+
"""Test running Python files with jac run command."""
|
|
74
|
+
captured_output = io.StringIO()
|
|
75
|
+
sys.stdout = captured_output
|
|
76
|
+
|
|
77
|
+
cli.run(self.fixture_abs_path("pyfunc_fmt.py"))
|
|
78
|
+
|
|
79
|
+
sys.stdout = sys.__stdout__
|
|
80
|
+
stdout_value = captured_output.getvalue()
|
|
81
|
+
|
|
82
|
+
self.assertIn("One", stdout_value)
|
|
83
|
+
self.assertIn("Two", stdout_value)
|
|
84
|
+
self.assertIn("Three", stdout_value)
|
|
85
|
+
self.assertIn("baz", stdout_value)
|
|
86
|
+
self.assertIn("Processing...", stdout_value)
|
|
87
|
+
self.assertIn("Four", stdout_value)
|
|
88
|
+
self.assertIn("The End.", stdout_value)
|
|
89
|
+
|
|
90
|
+
def test_jac_run_pyfunc_kwesc(self) -> None:
|
|
91
|
+
"""Test running Python files with jac run command."""
|
|
92
|
+
captured_output = io.StringIO()
|
|
93
|
+
sys.stdout = captured_output
|
|
94
|
+
|
|
95
|
+
cli.run(self.fixture_abs_path("pyfunc_kwesc.py"))
|
|
96
|
+
|
|
97
|
+
sys.stdout = sys.__stdout__
|
|
98
|
+
stdout_value = captured_output.getvalue()
|
|
99
|
+
out = stdout_value.split("\n")
|
|
100
|
+
self.assertIn("89", out[0])
|
|
101
|
+
self.assertIn("(13, (), {'a': 1, 'b': 2})", out[1])
|
|
102
|
+
self.assertIn("Functions: [{'name': 'replace_lines'", out[2])
|
|
103
|
+
self.assertIn("Dict: 90", out[3])
|
|
104
|
+
|
|
38
105
|
def test_jac_cli_alert_based_err(self) -> None:
|
|
39
106
|
"""Basic test for pass."""
|
|
40
107
|
captured_output = io.StringIO()
|
|
@@ -203,6 +270,27 @@ class JacCliTests(TestCase):
|
|
|
203
270
|
'[label="MultiString" shape="oval" style="filled" fillcolor="#fccca4"]',
|
|
204
271
|
stdout_value,
|
|
205
272
|
)
|
|
273
|
+
|
|
274
|
+
def test_cfg_printgraph(self) -> None:
|
|
275
|
+
"""Testing for print CFG."""
|
|
276
|
+
captured_output = io.StringIO()
|
|
277
|
+
sys.stdout = captured_output
|
|
278
|
+
|
|
279
|
+
cli.tool("ir", ["cfg.", f"{self.fixture_abs_path('hello.jac')}"])
|
|
280
|
+
|
|
281
|
+
sys.stdout = sys.__stdout__
|
|
282
|
+
stdout_value = captured_output.getvalue()
|
|
283
|
+
correct_graph = (
|
|
284
|
+
"digraph G {\n"
|
|
285
|
+
' 0 [label="BB0\\n\\nprint ( \\"im still here\\" ) ;\", shape=box];\n'
|
|
286
|
+
' 1 [label="BB1\\n\\"Hello World!\\" |> print ;\", shape=box];\n'
|
|
287
|
+
"}\n\n"
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
self.assertEqual(
|
|
291
|
+
correct_graph,
|
|
292
|
+
stdout_value,
|
|
293
|
+
)
|
|
206
294
|
|
|
207
295
|
def test_del_clean(self) -> None:
|
|
208
296
|
"""Testing for print AstTool."""
|
|
@@ -324,6 +412,8 @@ class JacCliTests(TestCase):
|
|
|
324
412
|
sys.stdout = sys.__stdout__
|
|
325
413
|
stdout_value = captured_output.getvalue()
|
|
326
414
|
self.assertIn("def my_print(x: object) -> None", stdout_value)
|
|
415
|
+
self.assertIn("class MyClass {", stdout_value)
|
|
416
|
+
self.assertIn('"""Print function."""', stdout_value)
|
|
327
417
|
|
|
328
418
|
def test_caching_issue(self) -> None:
|
|
329
419
|
"""Test for Caching Issue."""
|
|
@@ -453,3 +543,20 @@ class JacCliTests(TestCase):
|
|
|
453
543
|
description_pattern,
|
|
454
544
|
f"Parameter description for '{param_name}' not found in help text for '{cmd_name}'",
|
|
455
545
|
)
|
|
546
|
+
|
|
547
|
+
def test_run_jac_name_py(self) -> None:
|
|
548
|
+
"""Test a specific test case."""
|
|
549
|
+
process = subprocess.Popen(
|
|
550
|
+
[
|
|
551
|
+
"jac",
|
|
552
|
+
"run",
|
|
553
|
+
self.fixture_abs_path("py_run.py"),
|
|
554
|
+
],
|
|
555
|
+
stdin=subprocess.PIPE,
|
|
556
|
+
stdout=subprocess.PIPE,
|
|
557
|
+
stderr=subprocess.PIPE,
|
|
558
|
+
text=True,
|
|
559
|
+
)
|
|
560
|
+
stdout, stderr = process.communicate()
|
|
561
|
+
self.assertIn("Hello, World!", stdout)
|
|
562
|
+
self.assertIn("Sum: 8", stdout)
|