jaclang 0.8.9__py3-none-any.whl → 0.8.10__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 +147 -25
- jaclang/cli/cmdreg.py +144 -8
- jaclang/compiler/__init__.py +6 -1
- jaclang/compiler/codeinfo.py +16 -1
- jaclang/compiler/constant.py +33 -13
- jaclang/compiler/jac.lark +130 -31
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +567 -176
- jaclang/compiler/passes/__init__.py +2 -1
- jaclang/compiler/passes/ast_gen/__init__.py +5 -0
- jaclang/compiler/passes/ast_gen/base_ast_gen_pass.py +54 -0
- jaclang/compiler/passes/ast_gen/jsx_processor.py +344 -0
- jaclang/compiler/passes/ecmascript/__init__.py +25 -0
- jaclang/compiler/passes/ecmascript/es_unparse.py +576 -0
- jaclang/compiler/passes/ecmascript/esast_gen_pass.py +2068 -0
- jaclang/compiler/passes/ecmascript/estree.py +972 -0
- jaclang/compiler/passes/ecmascript/tests/__init__.py +1 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/advanced_language_features.jac +170 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.impl.jac +30 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.jac +14 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/client_jsx.jac +89 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/core_language_features.jac +195 -0
- jaclang/compiler/passes/ecmascript/tests/test_esast_gen_pass.py +167 -0
- jaclang/compiler/passes/ecmascript/tests/test_js_generation.py +239 -0
- jaclang/compiler/passes/main/__init__.py +0 -3
- jaclang/compiler/passes/main/annex_pass.py +23 -1
- jaclang/compiler/passes/main/pyast_gen_pass.py +324 -234
- jaclang/compiler/passes/main/pyast_load_pass.py +46 -11
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +18 -1
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.cl.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +3 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_class_construct.jac +33 -0
- jaclang/compiler/passes/main/tests/fixtures/defuse_modpath.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +2 -1
- jaclang/compiler/passes/main/tests/test_checker_pass.py +31 -2
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +12 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +23 -4
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +25 -0
- jaclang/compiler/passes/main/type_checker_pass.py +7 -0
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +115 -0
- jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -1
- jaclang/compiler/passes/transform.py +9 -1
- jaclang/compiler/passes/uni_pass.py +5 -7
- jaclang/compiler/program.py +22 -25
- jaclang/compiler/tests/test_client_codegen.py +113 -0
- jaclang/compiler/tests/test_importer.py +12 -10
- jaclang/compiler/tests/test_parser.py +249 -3
- jaclang/compiler/type_system/type_evaluator.jac +169 -50
- jaclang/compiler/type_system/type_utils.py +1 -1
- jaclang/compiler/type_system/types.py +6 -0
- jaclang/compiler/unitree.py +430 -84
- jaclang/langserve/engine.jac +224 -288
- jaclang/langserve/sem_manager.jac +12 -8
- jaclang/langserve/server.jac +48 -48
- jaclang/langserve/tests/fixtures/greet.py +17 -0
- jaclang/langserve/tests/fixtures/md_path.jac +22 -0
- jaclang/langserve/tests/fixtures/user.jac +15 -0
- jaclang/langserve/tests/test_server.py +66 -371
- jaclang/lib.py +1 -1
- jaclang/runtimelib/client_bundle.py +169 -0
- jaclang/runtimelib/client_runtime.jac +586 -0
- jaclang/runtimelib/constructs.py +2 -0
- jaclang/runtimelib/machine.py +259 -100
- jaclang/runtimelib/meta_importer.py +111 -22
- jaclang/runtimelib/mtp.py +15 -0
- jaclang/runtimelib/server.py +1089 -0
- jaclang/runtimelib/tests/fixtures/client_app.jac +18 -0
- jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
- jaclang/runtimelib/tests/fixtures/savable_object.jac +4 -5
- jaclang/runtimelib/tests/fixtures/serve_api.jac +75 -0
- jaclang/runtimelib/tests/test_client_bundle.py +55 -0
- jaclang/runtimelib/tests/test_client_render.py +63 -0
- jaclang/runtimelib/tests/test_serve.py +1069 -0
- jaclang/settings.py +0 -2
- jaclang/tests/fixtures/iife_functions.jac +142 -0
- jaclang/tests/fixtures/iife_functions_client.jac +143 -0
- jaclang/tests/fixtures/multistatement_lambda.jac +116 -0
- jaclang/tests/fixtures/multistatement_lambda_client.jac +113 -0
- jaclang/tests/fixtures/needs_import_dup.jac +6 -4
- jaclang/tests/fixtures/py_run.py +7 -5
- jaclang/tests/fixtures/pyfunc_fstr.py +2 -2
- jaclang/tests/fixtures/simple_lambda_test.jac +12 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +10 -39
- jaclang/tests/test_reference.py +17 -2
- jaclang/utils/NonGPT.py +375 -0
- jaclang/utils/helpers.py +44 -16
- jaclang/utils/lang_tools.py +31 -4
- jaclang/utils/tests/test_lang_tools.py +1 -1
- jaclang/utils/treeprinter.py +8 -3
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/RECORD +96 -66
- jaclang/compiler/passes/main/binder_pass.py +0 -594
- jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +0 -47
- jaclang/compiler/passes/main/tests/test_binder_pass.py +0 -111
- jaclang/langserve/tests/session.jac +0 -294
- jaclang/langserve/tests/test_dev_server.py +0 -80
- jaclang/runtimelib/importer.py +0 -351
- jaclang/tests/test_typecheck.py +0 -542
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/entry_points.txt +0 -0
jaclang/runtimelib/machine.py
CHANGED
|
@@ -10,6 +10,7 @@ import sys
|
|
|
10
10
|
import tempfile
|
|
11
11
|
import types
|
|
12
12
|
from collections import OrderedDict
|
|
13
|
+
from collections.abc import Mapping, Sequence
|
|
13
14
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
14
15
|
from dataclasses import MISSING, dataclass, field
|
|
15
16
|
from functools import wraps
|
|
@@ -27,6 +28,7 @@ from typing import (
|
|
|
27
28
|
TypeVar,
|
|
28
29
|
Union,
|
|
29
30
|
cast,
|
|
31
|
+
get_type_hints,
|
|
30
32
|
)
|
|
31
33
|
from uuid import UUID
|
|
32
34
|
|
|
@@ -55,6 +57,7 @@ from jaclang.runtimelib.constructs import (
|
|
|
55
57
|
WalkerArchetype,
|
|
56
58
|
)
|
|
57
59
|
from jaclang.runtimelib.memory import Memory, Shelf, ShelfStorage
|
|
60
|
+
from jaclang.runtimelib.mtp import MTIR
|
|
58
61
|
from jaclang.runtimelib.utils import (
|
|
59
62
|
all_issubclass,
|
|
60
63
|
traverse_graph,
|
|
@@ -85,37 +88,31 @@ class ExecutionContext:
|
|
|
85
88
|
self.mem: Memory = ShelfStorage(session)
|
|
86
89
|
self.reports: list[Any] = []
|
|
87
90
|
self.custom: Any = MISSING
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
system_root =
|
|
92
|
-
system_root.id
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
self.entry_node = self.root_state = self.init_anchor(root, self.system_root)
|
|
91
|
+
self.system_root = self.mem.find_by_id(UUID(Con.SUPER_ROOT_UUID))
|
|
92
|
+
if not isinstance(self.system_root, NodeAnchor):
|
|
93
|
+
self.system_root = cast(NodeAnchor, Root().__jac__)
|
|
94
|
+
self.system_root.id = UUID(Con.SUPER_ROOT_UUID)
|
|
95
|
+
self.mem.set(self.system_root.id, self.system_root)
|
|
96
|
+
self.entry_node = self.root_state = (
|
|
97
|
+
self._get_anchor(root) if root else self.system_root
|
|
98
|
+
)
|
|
98
99
|
|
|
99
|
-
def
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
) -> NodeAnchor:
|
|
104
|
-
"""Load initial anchors."""
|
|
105
|
-
if anchor_id:
|
|
106
|
-
if isinstance(anchor := self.mem.find_by_id(UUID(anchor_id)), NodeAnchor):
|
|
107
|
-
return anchor
|
|
100
|
+
def _get_anchor(self, anchor_id: str) -> NodeAnchor:
|
|
101
|
+
"""Get anchor by ID or raise error."""
|
|
102
|
+
anchor = self.mem.find_by_id(UUID(anchor_id))
|
|
103
|
+
if not isinstance(anchor, NodeAnchor):
|
|
108
104
|
raise ValueError(f"Invalid anchor id {anchor_id} !")
|
|
109
|
-
return
|
|
105
|
+
return anchor
|
|
110
106
|
|
|
111
107
|
def set_entry_node(self, entry_node: str | None) -> None:
|
|
112
|
-
"""Override entry."""
|
|
113
|
-
self.entry_node =
|
|
108
|
+
"""Override entry node."""
|
|
109
|
+
self.entry_node = (
|
|
110
|
+
self._get_anchor(entry_node) if entry_node else self.root_state
|
|
111
|
+
)
|
|
114
112
|
|
|
115
113
|
def close(self) -> None:
|
|
116
114
|
"""Close current ExecutionContext."""
|
|
117
115
|
self.mem.close()
|
|
118
|
-
JacMachine.reset_machine()
|
|
119
116
|
|
|
120
117
|
def get_root(self) -> Root:
|
|
121
118
|
"""Get current root."""
|
|
@@ -698,7 +695,7 @@ class JacClassReferences:
|
|
|
698
695
|
Root: TypeAlias = _Root
|
|
699
696
|
GenericEdge: TypeAlias = _GenericEdge
|
|
700
697
|
|
|
701
|
-
|
|
698
|
+
OPath: TypeAlias = ObjectSpatialPath
|
|
702
699
|
|
|
703
700
|
|
|
704
701
|
class JacBuiltin:
|
|
@@ -937,45 +934,163 @@ class JacBasics:
|
|
|
937
934
|
target: str,
|
|
938
935
|
base_path: str,
|
|
939
936
|
absorb: bool = False,
|
|
940
|
-
mdl_alias: Optional[str] = None,
|
|
941
937
|
override_name: Optional[str] = None,
|
|
942
938
|
items: Optional[dict[str, Union[str, Optional[str]]]] = None,
|
|
943
939
|
reload_module: Optional[bool] = False,
|
|
944
940
|
lng: Optional[str] = None,
|
|
945
941
|
) -> tuple[types.ModuleType, ...]:
|
|
946
|
-
"""
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
942
|
+
"""Import a Jac or Python module using Python's standard import machinery.
|
|
943
|
+
|
|
944
|
+
This function bridges Jac's import semantics with Python's import system,
|
|
945
|
+
leveraging importlib.import_module() which automatically invokes our
|
|
946
|
+
JacMetaImporter (registered in sys.meta_path).
|
|
947
|
+
|
|
948
|
+
Args:
|
|
949
|
+
target: Module name to import (e.g., "foo.bar" or ".relative")
|
|
950
|
+
base_path: Base directory for resolving the module
|
|
951
|
+
absorb: If True with items, return module instead of items
|
|
952
|
+
override_name: Special handling for "__main__" execution context
|
|
953
|
+
items: Specific items to import from module (like "from X import Y")
|
|
954
|
+
reload_module: Force reload even if already in sys.modules
|
|
955
|
+
lng: Language hint ("jac", "py", etc.) - auto-detected if None
|
|
956
|
+
|
|
957
|
+
Returns:
|
|
958
|
+
Tuple of imported module(s) or item(s)
|
|
959
|
+
|
|
960
|
+
Examples:
|
|
961
|
+
# Import entire module
|
|
962
|
+
(mod,) = jac_import("mymod", "/path/to/base")
|
|
963
|
+
|
|
964
|
+
# Import specific items
|
|
965
|
+
(func, cls) = jac_import("mymod", "/path", items={"myfunc": None, "MyClass": None})
|
|
966
|
+
|
|
967
|
+
# Run as __main__
|
|
968
|
+
jac_import("mymod", "/path", override_name="__main__")
|
|
969
|
+
"""
|
|
970
|
+
import importlib
|
|
971
|
+
import importlib.util
|
|
952
972
|
|
|
953
973
|
if lng is None:
|
|
954
974
|
lng = infer_language(target, base_path)
|
|
955
975
|
|
|
956
|
-
spec = ImportPathSpec(
|
|
957
|
-
target,
|
|
958
|
-
base_path,
|
|
959
|
-
absorb,
|
|
960
|
-
mdl_alias,
|
|
961
|
-
override_name,
|
|
962
|
-
lng,
|
|
963
|
-
items,
|
|
964
|
-
)
|
|
965
|
-
|
|
966
976
|
if not JacMachine.program:
|
|
967
977
|
JacMachineInterface.attach_program(JacProgram())
|
|
968
978
|
|
|
969
|
-
|
|
970
|
-
|
|
979
|
+
# Compute the module name
|
|
980
|
+
# Convert relative imports (e.g., ".foo") to absolute
|
|
981
|
+
if target.startswith("."):
|
|
982
|
+
# Relative import - need to resolve against base_path
|
|
983
|
+
caller_dir = (
|
|
984
|
+
base_path if os.path.isdir(base_path) else os.path.dirname(base_path)
|
|
985
|
+
)
|
|
986
|
+
chomp_target = target
|
|
987
|
+
while chomp_target.startswith("."):
|
|
988
|
+
if len(chomp_target) > 1 and chomp_target[1] == ".":
|
|
989
|
+
caller_dir = os.path.dirname(caller_dir)
|
|
990
|
+
chomp_target = chomp_target[1:]
|
|
991
|
+
else:
|
|
992
|
+
chomp_target = chomp_target[1:]
|
|
993
|
+
break
|
|
994
|
+
module_name = chomp_target
|
|
971
995
|
else:
|
|
972
|
-
|
|
996
|
+
module_name = target
|
|
973
997
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
else
|
|
998
|
+
# Add base_path to sys.path for import resolution
|
|
999
|
+
# The meta importer uses this for finding modules
|
|
1000
|
+
caller_dir = (
|
|
1001
|
+
base_path if os.path.isdir(base_path) else os.path.dirname(base_path)
|
|
978
1002
|
)
|
|
1003
|
+
original_path = None
|
|
1004
|
+
|
|
1005
|
+
# Only modify sys.path if the directory isn't already there
|
|
1006
|
+
if caller_dir and caller_dir not in sys.path:
|
|
1007
|
+
original_path = sys.path.copy()
|
|
1008
|
+
sys.path.insert(0, caller_dir)
|
|
1009
|
+
|
|
1010
|
+
try:
|
|
1011
|
+
# Handle special case: override_name="__main__" means run as script
|
|
1012
|
+
if override_name == "__main__":
|
|
1013
|
+
# For __main__ execution, we use spec_from_file_location
|
|
1014
|
+
from jaclang.runtimelib.meta_importer import JacMetaImporter
|
|
1015
|
+
|
|
1016
|
+
finder = JacMetaImporter()
|
|
1017
|
+
# Pass None as path for top-level imports (e.g., "micro.simple_walk")
|
|
1018
|
+
# This ensures the meta importer searches sys.path correctly
|
|
1019
|
+
spec = finder.find_spec(module_name, None)
|
|
1020
|
+
if (
|
|
1021
|
+
spec
|
|
1022
|
+
and spec.origin
|
|
1023
|
+
and spec.origin.endswith(".jac")
|
|
1024
|
+
and lng == "py"
|
|
1025
|
+
):
|
|
1026
|
+
spec = None
|
|
1027
|
+
|
|
1028
|
+
if (not spec or not spec.origin) and lng == "py":
|
|
1029
|
+
file_path = os.path.join(caller_dir, f"{module_name}.py")
|
|
1030
|
+
if os.path.isfile(file_path):
|
|
1031
|
+
spec_name = (
|
|
1032
|
+
"__main__" if override_name == "__main__" else module_name
|
|
1033
|
+
)
|
|
1034
|
+
spec = importlib.util.spec_from_file_location(
|
|
1035
|
+
spec_name, file_path
|
|
1036
|
+
)
|
|
1037
|
+
|
|
1038
|
+
if not spec or not spec.origin:
|
|
1039
|
+
raise ImportError(f"Cannot find module {module_name}")
|
|
1040
|
+
|
|
1041
|
+
# Create or get __main__ module
|
|
1042
|
+
if "__main__" in sys.modules and not reload_module:
|
|
1043
|
+
module = sys.modules["__main__"]
|
|
1044
|
+
# Clear the module's dict except for special attributes
|
|
1045
|
+
to_keep = {
|
|
1046
|
+
k: v for k, v in module.__dict__.items() if k.startswith("__")
|
|
1047
|
+
}
|
|
1048
|
+
# module.__dict__.clear()
|
|
1049
|
+
module.__dict__.update(to_keep)
|
|
1050
|
+
else:
|
|
1051
|
+
module = types.ModuleType("__main__")
|
|
1052
|
+
sys.modules["__main__"] = module
|
|
1053
|
+
|
|
1054
|
+
# Set module attributes
|
|
1055
|
+
module.__file__ = spec.origin
|
|
1056
|
+
module.__name__ = "__main__"
|
|
1057
|
+
module.__spec__ = spec
|
|
1058
|
+
if spec.submodule_search_locations:
|
|
1059
|
+
module.__path__ = spec.submodule_search_locations
|
|
1060
|
+
|
|
1061
|
+
# Register in JacMachine
|
|
1062
|
+
JacMachineInterface.load_module("__main__", module)
|
|
1063
|
+
|
|
1064
|
+
# Execute the module
|
|
1065
|
+
if spec.loader:
|
|
1066
|
+
spec.loader.exec_module(module)
|
|
1067
|
+
elif reload_module and module_name in sys.modules:
|
|
1068
|
+
# Handle reload case
|
|
1069
|
+
module = importlib.reload(sys.modules[module_name])
|
|
1070
|
+
else:
|
|
1071
|
+
# Use Python's standard import machinery
|
|
1072
|
+
# This will invoke JacMetaImporter.find_spec() and exec_module()
|
|
1073
|
+
module = importlib.import_module(module_name)
|
|
1074
|
+
|
|
1075
|
+
# Handle selective item imports
|
|
1076
|
+
if items:
|
|
1077
|
+
imported_items = []
|
|
1078
|
+
for item_name, _ in items.items():
|
|
1079
|
+
if hasattr(module, item_name):
|
|
1080
|
+
item = getattr(module, item_name)
|
|
1081
|
+
imported_items.append(item)
|
|
1082
|
+
else:
|
|
1083
|
+
raise ImportError(
|
|
1084
|
+
f"Cannot import name '{item_name}' from '{module_name}'"
|
|
1085
|
+
)
|
|
1086
|
+
return tuple(imported_items) if not absorb else (module,)
|
|
1087
|
+
|
|
1088
|
+
return (module,)
|
|
1089
|
+
|
|
1090
|
+
finally:
|
|
1091
|
+
# Restore original sys.path if we modified it
|
|
1092
|
+
if original_path is not None:
|
|
1093
|
+
sys.path[:] = original_path
|
|
979
1094
|
|
|
980
1095
|
@staticmethod
|
|
981
1096
|
def jac_test(test_fun: Callable) -> Callable:
|
|
@@ -991,6 +1106,30 @@ class JacBasics:
|
|
|
991
1106
|
|
|
992
1107
|
return test_deco
|
|
993
1108
|
|
|
1109
|
+
@staticmethod
|
|
1110
|
+
def jsx(
|
|
1111
|
+
tag: object,
|
|
1112
|
+
attributes: Mapping[str, object] | None = None,
|
|
1113
|
+
children: Sequence[object] | None = None,
|
|
1114
|
+
) -> dict[str, object]:
|
|
1115
|
+
"""JSX interface for creating elements.
|
|
1116
|
+
|
|
1117
|
+
Args:
|
|
1118
|
+
tag: Element tag (string for HTML elements, callable for components)
|
|
1119
|
+
attributes: Element attributes/props
|
|
1120
|
+
children: Child elements
|
|
1121
|
+
|
|
1122
|
+
Returns:
|
|
1123
|
+
JSX element representation (implementation-defined)
|
|
1124
|
+
"""
|
|
1125
|
+
props: dict[str, object] = dict(attributes) if attributes else {}
|
|
1126
|
+
child_list = list(children) if children else []
|
|
1127
|
+
return {
|
|
1128
|
+
"tag": tag,
|
|
1129
|
+
"props": props,
|
|
1130
|
+
"children": child_list,
|
|
1131
|
+
}
|
|
1132
|
+
|
|
994
1133
|
@staticmethod
|
|
995
1134
|
def run_test(
|
|
996
1135
|
filepath: str,
|
|
@@ -1066,7 +1205,7 @@ class JacBasics:
|
|
|
1066
1205
|
return field(init=init)
|
|
1067
1206
|
|
|
1068
1207
|
@staticmethod
|
|
1069
|
-
def
|
|
1208
|
+
def log_report(expr: Any, custom: bool = False) -> None: # noqa: ANN401
|
|
1070
1209
|
"""Jac's report stmt feature."""
|
|
1071
1210
|
ctx = JacMachineInterface.get_context()
|
|
1072
1211
|
if custom:
|
|
@@ -1315,9 +1454,11 @@ class JacByLLM:
|
|
|
1315
1454
|
"""Jac byLLM integration."""
|
|
1316
1455
|
|
|
1317
1456
|
@staticmethod
|
|
1318
|
-
def get_mtir(
|
|
1457
|
+
def get_mtir(
|
|
1458
|
+
caller: Callable, args: dict[int | str, object], call_params: dict[str, object]
|
|
1459
|
+
) -> MTIR:
|
|
1319
1460
|
"""Get byLLM library."""
|
|
1320
|
-
return
|
|
1461
|
+
return MTIR(caller=caller, args=args, call_params=call_params)
|
|
1321
1462
|
|
|
1322
1463
|
@staticmethod
|
|
1323
1464
|
def sem(semstr: str, inner_semstr: dict[str, str]) -> Callable:
|
|
@@ -1331,15 +1472,23 @@ class JacByLLM:
|
|
|
1331
1472
|
return decorator
|
|
1332
1473
|
|
|
1333
1474
|
@staticmethod
|
|
1334
|
-
def call_llm(model: object, mtir:
|
|
1335
|
-
"""Call the LLM model.
|
|
1475
|
+
def call_llm(model: object, mtir: MTIR) -> Any: # noqa: ANN401
|
|
1476
|
+
"""Call the LLM model."""
|
|
1477
|
+
from jaclang.utils.NonGPT import random_value_for_type
|
|
1336
1478
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1479
|
+
try:
|
|
1480
|
+
type_hints = get_type_hints(
|
|
1481
|
+
mtir.caller,
|
|
1482
|
+
globalns=getattr(mtir.caller, "__globals__", {}),
|
|
1483
|
+
localns=None,
|
|
1484
|
+
include_extras=True,
|
|
1485
|
+
)
|
|
1486
|
+
except Exception:
|
|
1487
|
+
type_hints = getattr(mtir.caller, "__annotations__", {})
|
|
1488
|
+
return_type = type_hints.get("return", Any)
|
|
1489
|
+
|
|
1490
|
+
# Generate and return a random value matching the return type
|
|
1491
|
+
return random_value_for_type(return_type)
|
|
1343
1492
|
|
|
1344
1493
|
@staticmethod
|
|
1345
1494
|
def by(model: object) -> Callable:
|
|
@@ -1395,7 +1544,11 @@ class JacUtils:
|
|
|
1395
1544
|
if module:
|
|
1396
1545
|
walkers = []
|
|
1397
1546
|
for name, obj in inspect.getmembers(module):
|
|
1398
|
-
if
|
|
1547
|
+
if (
|
|
1548
|
+
isinstance(obj, type)
|
|
1549
|
+
and issubclass(obj, WalkerArchetype)
|
|
1550
|
+
and obj.__module__ == module_name
|
|
1551
|
+
):
|
|
1399
1552
|
walkers.append(name)
|
|
1400
1553
|
return walkers
|
|
1401
1554
|
return []
|
|
@@ -1407,7 +1560,11 @@ class JacUtils:
|
|
|
1407
1560
|
if module:
|
|
1408
1561
|
nodes = []
|
|
1409
1562
|
for name, obj in inspect.getmembers(module):
|
|
1410
|
-
if
|
|
1563
|
+
if (
|
|
1564
|
+
isinstance(obj, type)
|
|
1565
|
+
and issubclass(obj, NodeArchetype)
|
|
1566
|
+
and obj.__module__ == module_name
|
|
1567
|
+
):
|
|
1411
1568
|
nodes.append(name)
|
|
1412
1569
|
return nodes
|
|
1413
1570
|
return []
|
|
@@ -1417,11 +1574,15 @@ class JacUtils:
|
|
|
1417
1574
|
"""List all edges in a specific module."""
|
|
1418
1575
|
module = JacMachine.loaded_modules.get(module_name)
|
|
1419
1576
|
if module:
|
|
1420
|
-
|
|
1577
|
+
edges = []
|
|
1421
1578
|
for name, obj in inspect.getmembers(module):
|
|
1422
|
-
if
|
|
1423
|
-
|
|
1424
|
-
|
|
1579
|
+
if (
|
|
1580
|
+
isinstance(obj, type)
|
|
1581
|
+
and issubclass(obj, EdgeArchetype)
|
|
1582
|
+
and obj.__module__ == module_name
|
|
1583
|
+
):
|
|
1584
|
+
edges.append(name)
|
|
1585
|
+
return edges
|
|
1425
1586
|
return []
|
|
1426
1587
|
|
|
1427
1588
|
@staticmethod
|
|
@@ -1432,9 +1593,11 @@ class JacUtils:
|
|
|
1432
1593
|
cachable: bool = False,
|
|
1433
1594
|
keep_temporary_files: bool = False,
|
|
1434
1595
|
) -> Optional[types.ModuleType]:
|
|
1435
|
-
"""Dynamically creates archetypes (nodes, walkers, etc.) from Jac source code.
|
|
1436
|
-
from jaclang.runtimelib.importer import JacImporter, ImportPathSpec
|
|
1596
|
+
"""Dynamically creates archetypes (nodes, walkers, etc.) from Jac source code.
|
|
1437
1597
|
|
|
1598
|
+
This leverages Python's standard import machinery via jac_import(),
|
|
1599
|
+
which will automatically invoke JacMetaImporter.
|
|
1600
|
+
"""
|
|
1438
1601
|
if not base_path:
|
|
1439
1602
|
base_path = JacMachine.base_path_dir or os.getcwd()
|
|
1440
1603
|
|
|
@@ -1442,6 +1605,7 @@ class JacUtils:
|
|
|
1442
1605
|
os.makedirs(base_path)
|
|
1443
1606
|
if not module_name:
|
|
1444
1607
|
module_name = f"_dynamic_module_{len(JacMachine.loaded_modules)}"
|
|
1608
|
+
|
|
1445
1609
|
with tempfile.NamedTemporaryFile(
|
|
1446
1610
|
mode="w",
|
|
1447
1611
|
suffix=".jac",
|
|
@@ -1453,24 +1617,20 @@ class JacUtils:
|
|
|
1453
1617
|
tmp_file.write(source_code)
|
|
1454
1618
|
|
|
1455
1619
|
try:
|
|
1456
|
-
importer = JacImporter()
|
|
1457
1620
|
tmp_file_basename = os.path.basename(tmp_file_path)
|
|
1458
1621
|
tmp_module_name, _ = os.path.splitext(tmp_file_basename)
|
|
1459
1622
|
|
|
1460
|
-
|
|
1623
|
+
# Use simplified jac_import which delegates to importlib
|
|
1624
|
+
result = JacMachineInterface.jac_import(
|
|
1461
1625
|
target=tmp_module_name,
|
|
1462
1626
|
base_path=base_path,
|
|
1463
|
-
absorb=False,
|
|
1464
|
-
mdl_alias=None,
|
|
1465
1627
|
override_name=module_name,
|
|
1466
1628
|
lng="jac",
|
|
1467
|
-
items=None,
|
|
1468
1629
|
)
|
|
1630
|
+
module = result[0] if result else None
|
|
1469
1631
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
JacMachine.loaded_modules[module_name] = module
|
|
1632
|
+
if module:
|
|
1633
|
+
JacMachine.loaded_modules[module_name] = module
|
|
1474
1634
|
return module
|
|
1475
1635
|
except Exception as e:
|
|
1476
1636
|
logger.error(f"Error importing dynamic module '{module_name}': {e}")
|
|
@@ -1484,36 +1644,31 @@ class JacUtils:
|
|
|
1484
1644
|
module_name: str,
|
|
1485
1645
|
items: Optional[dict[str, Union[str, Optional[str]]]],
|
|
1486
1646
|
) -> tuple[types.ModuleType, ...]:
|
|
1487
|
-
"""Reimport the module."""
|
|
1488
|
-
from .importer import JacImporter, ImportPathSpec
|
|
1489
|
-
|
|
1647
|
+
"""Reimport the module using Python's reload mechanism."""
|
|
1490
1648
|
if module_name in JacMachine.loaded_modules:
|
|
1491
1649
|
try:
|
|
1492
1650
|
old_module = JacMachine.loaded_modules[module_name]
|
|
1493
|
-
|
|
1494
|
-
|
|
1651
|
+
|
|
1652
|
+
# Use jac_import with reload flag
|
|
1653
|
+
result = JacMachineInterface.jac_import(
|
|
1495
1654
|
target=module_name,
|
|
1496
1655
|
base_path=JacMachine.base_path_dir,
|
|
1497
|
-
absorb=False,
|
|
1498
|
-
mdl_alias=None,
|
|
1499
|
-
override_name=None,
|
|
1500
|
-
lng="jac",
|
|
1501
1656
|
items=items,
|
|
1657
|
+
reload_module=True,
|
|
1658
|
+
lng="jac",
|
|
1502
1659
|
)
|
|
1503
|
-
|
|
1504
|
-
|
|
1660
|
+
|
|
1661
|
+
# Update the old module's attributes if specific items were requested
|
|
1505
1662
|
if items:
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
)
|
|
1516
|
-
return (old_module,) if not items else tuple(ret_items)
|
|
1663
|
+
ret_items = []
|
|
1664
|
+
for idx, item_name in enumerate(items.keys()):
|
|
1665
|
+
if hasattr(old_module, item_name) and idx < len(result):
|
|
1666
|
+
new_attr = result[idx]
|
|
1667
|
+
ret_items.append(new_attr)
|
|
1668
|
+
setattr(old_module, item_name, new_attr)
|
|
1669
|
+
return tuple(ret_items)
|
|
1670
|
+
|
|
1671
|
+
return (old_module,)
|
|
1517
1672
|
except Exception as e:
|
|
1518
1673
|
logger.error(f"Failed to update module {module_name}: {e}")
|
|
1519
1674
|
else:
|
|
@@ -1719,8 +1874,12 @@ class JacMachine(JacMachineInterface):
|
|
|
1719
1874
|
@staticmethod
|
|
1720
1875
|
def reset_machine() -> None:
|
|
1721
1876
|
"""Reset the machine."""
|
|
1722
|
-
#
|
|
1723
|
-
#
|
|
1877
|
+
# Remove Jac modules from sys.modules, but skip special module names
|
|
1878
|
+
# that Python relies on (like __main__, __mp_main__, etc.)
|
|
1879
|
+
special_modules = {"__main__", "__mp_main__", "builtins"}
|
|
1880
|
+
for i in JacMachine.loaded_modules.values():
|
|
1881
|
+
if i.__name__ not in special_modules:
|
|
1882
|
+
sys.modules.pop(i.__name__, None)
|
|
1724
1883
|
JacMachine.loaded_modules.clear()
|
|
1725
1884
|
JacMachine.base_path_dir = os.getcwd()
|
|
1726
1885
|
JacMachine.program = JacProgram()
|