jaclang 0.7.1__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 +378 -277
- 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 +29 -11
- jaclang/compiler/passes/main/def_use_pass.py +48 -17
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +49 -30
- jaclang/compiler/passes/main/import_pass.py +12 -7
- jaclang/compiler/passes/main/pyast_gen_pass.py +110 -47
- jaclang/compiler/passes/main/pyast_load_pass.py +49 -13
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +25 -11
- jaclang/compiler/passes/main/pyout_pass.py +3 -1
- 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/tests/test_import_pass.py +8 -0
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/main/type_check_pass.py +2 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +44 -11
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
- jaclang/compiler/passes/transform.py +2 -4
- jaclang/{core/registry.py → compiler/semtable.py} +1 -3
- jaclang/compiler/symtable.py +39 -31
- jaclang/compiler/tests/test_parser.py +2 -2
- jaclang/core/aott.py +112 -16
- jaclang/core/{construct.py → architype.py} +44 -93
- jaclang/core/constructs.py +44 -0
- jaclang/core/context.py +157 -0
- jaclang/core/importer.py +18 -9
- jaclang/core/llms/anthropic.py +31 -2
- jaclang/core/llms/base.py +3 -3
- jaclang/core/llms/groq.py +4 -1
- jaclang/core/llms/huggingface.py +4 -1
- jaclang/core/llms/ollama.py +4 -1
- jaclang/core/llms/openai.py +6 -2
- jaclang/core/llms/togetherai.py +4 -1
- jaclang/core/memory.py +53 -2
- jaclang/core/test.py +90 -0
- jaclang/core/utils.py +2 -2
- jaclang/langserve/engine.py +119 -122
- jaclang/langserve/server.py +27 -5
- jaclang/langserve/tests/fixtures/circle.jac +16 -12
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.impl.jac +8 -4
- jaclang/langserve/tests/fixtures/circle_pure.jac +2 -2
- jaclang/langserve/tests/test_server.py +114 -0
- jaclang/langserve/utils.py +104 -10
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +46 -90
- jaclang/plugin/feature.py +32 -16
- jaclang/plugin/spec.py +17 -19
- jaclang/plugin/tests/test_features.py +0 -33
- jaclang/settings.py +4 -0
- jaclang/tests/fixtures/abc.jac +16 -12
- jaclang/tests/fixtures/byllmissue.jac +12 -0
- jaclang/tests/fixtures/edgetypetest.jac +16 -0
- jaclang/tests/fixtures/hash_init_check.jac +17 -0
- jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
- jaclang/tests/fixtures/impl_match_confused.jac +5 -0
- jaclang/tests/fixtures/math_question.jpg +0 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
- jaclang/tests/fixtures/nosigself.jac +19 -0
- jaclang/tests/fixtures/run_test.jac +17 -5
- jaclang/tests/fixtures/walker_override.jac +21 -0
- jaclang/tests/fixtures/with_llm_vision.jac +25 -0
- jaclang/tests/test_bugs.py +19 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +116 -11
- jaclang/tests/test_reference.py +1 -1
- jaclang/utils/lang_tools.py +5 -4
- jaclang/utils/test.py +2 -1
- jaclang/utils/treeprinter.py +35 -4
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/METADATA +3 -2
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/RECORD +84 -71
- jaclang/core/shelve_storage.py +0 -55
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/WHEEL +0 -0
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/entry_points.txt +0 -0
|
@@ -22,7 +22,7 @@ class Alert:
|
|
|
22
22
|
def __str__(self) -> str:
|
|
23
23
|
"""Return string representation of alert."""
|
|
24
24
|
return (
|
|
25
|
-
f"{self.loc.mod_path}, line {self.loc.first_line},"
|
|
25
|
+
f" {self.loc.mod_path}, line {self.loc.first_line},"
|
|
26
26
|
f" col {self.loc.col_start}: {self.msg}"
|
|
27
27
|
)
|
|
28
28
|
|
|
@@ -40,7 +40,7 @@ class Transform(ABC, Generic[T]):
|
|
|
40
40
|
prior: Optional[Transform] = None,
|
|
41
41
|
) -> None:
|
|
42
42
|
"""Initialize pass."""
|
|
43
|
-
self.logger = logging.getLogger(self.__class__.
|
|
43
|
+
self.logger = logging.getLogger(self.__class__.__name__)
|
|
44
44
|
self.errors_had: list[Alert] = [] if not prior else prior.errors_had
|
|
45
45
|
self.warnings_had: list[Alert] = [] if not prior else prior.warnings_had
|
|
46
46
|
self.cur_node: AstNode = input_ir # tracks current node during traversal
|
|
@@ -59,7 +59,6 @@ class Transform(ABC, Generic[T]):
|
|
|
59
59
|
self.__class__,
|
|
60
60
|
)
|
|
61
61
|
self.errors_had.append(alrt)
|
|
62
|
-
# print("Error:", str(alrt))
|
|
63
62
|
self.logger.error(str(alrt))
|
|
64
63
|
|
|
65
64
|
def log_warning(self, msg: str, node_override: Optional[AstNode] = None) -> None:
|
|
@@ -70,5 +69,4 @@ class Transform(ABC, Generic[T]):
|
|
|
70
69
|
self.__class__,
|
|
71
70
|
)
|
|
72
71
|
self.warnings_had.append(alrt)
|
|
73
|
-
# print("Warning:", str(alrt))
|
|
74
72
|
self.logger.warning(str(alrt))
|
|
@@ -12,9 +12,7 @@ from typing import Optional
|
|
|
12
12
|
class SemInfo:
|
|
13
13
|
"""Semantic information class."""
|
|
14
14
|
|
|
15
|
-
def __init__(
|
|
16
|
-
self, name: str, type: Optional[str] = None, semstr: Optional[str] = None
|
|
17
|
-
) -> None:
|
|
15
|
+
def __init__(self, name: str, type: Optional[str] = None, semstr: str = "") -> None:
|
|
18
16
|
"""Initialize the class."""
|
|
19
17
|
self.name = name
|
|
20
18
|
self.type = type
|
jaclang/compiler/symtable.py
CHANGED
|
@@ -17,7 +17,7 @@ class SymbolType(Enum):
|
|
|
17
17
|
|
|
18
18
|
MODULE = "module" # LSP: Module
|
|
19
19
|
MOD_VAR = "mod_var" # LSP: Variable
|
|
20
|
-
VAR = "
|
|
20
|
+
VAR = "variable" # LSP: Variable
|
|
21
21
|
IMM_VAR = "immutable" # LSP: Constant
|
|
22
22
|
ABILITY = "ability" # LSP: Function
|
|
23
23
|
OBJECT_ARCH = "object" # LSP: Class
|
|
@@ -37,24 +37,13 @@ class SymbolType(Enum):
|
|
|
37
37
|
BOOL = "bool" # LSP: Boolean
|
|
38
38
|
SEQUENCE = "sequence" # LSP: Array
|
|
39
39
|
NULL = "null" # LSP: Null
|
|
40
|
+
UNKNOWN = "unknown" # LSP: Unknown
|
|
40
41
|
|
|
41
42
|
def __str__(self) -> str:
|
|
42
43
|
"""Stringify."""
|
|
43
44
|
return self.value
|
|
44
45
|
|
|
45
46
|
|
|
46
|
-
class SymbolInfo:
|
|
47
|
-
"""Symbol Info."""
|
|
48
|
-
|
|
49
|
-
def __init__(
|
|
50
|
-
self, typ: str = "NoType", acc_tag: Optional[SymbolAccess] = None
|
|
51
|
-
) -> None: # noqa: ANN401
|
|
52
|
-
"""Initialize."""
|
|
53
|
-
self.typ = typ
|
|
54
|
-
self.acc_tag: Optional[SymbolAccess] = acc_tag
|
|
55
|
-
self.typ_sym_table: Optional[SymbolTable] = None
|
|
56
|
-
|
|
57
|
-
|
|
58
47
|
class SymbolAccess(Enum):
|
|
59
48
|
"""Symbol types."""
|
|
60
49
|
|
|
@@ -74,20 +63,19 @@ class Symbol:
|
|
|
74
63
|
|
|
75
64
|
def __init__(
|
|
76
65
|
self,
|
|
77
|
-
defn: ast.
|
|
66
|
+
defn: ast.NameAtom,
|
|
78
67
|
access: SymbolAccess,
|
|
79
68
|
parent_tab: SymbolTable,
|
|
80
|
-
typ: Optional[type] = None,
|
|
81
69
|
) -> None:
|
|
82
70
|
"""Initialize."""
|
|
83
|
-
self.
|
|
84
|
-
self.
|
|
85
|
-
defn.
|
|
86
|
-
self.access = access
|
|
71
|
+
self.defn: list[ast.NameAtom] = [defn]
|
|
72
|
+
self.uses: list[ast.NameAtom] = []
|
|
73
|
+
defn.sym = self
|
|
74
|
+
self.access: SymbolAccess = access
|
|
87
75
|
self.parent_tab = parent_tab
|
|
88
76
|
|
|
89
77
|
@property
|
|
90
|
-
def decl(self) -> ast.
|
|
78
|
+
def decl(self) -> ast.NameAtom:
|
|
91
79
|
"""Get decl."""
|
|
92
80
|
return self.defn[0]
|
|
93
81
|
|
|
@@ -99,19 +87,35 @@ class Symbol:
|
|
|
99
87
|
@property
|
|
100
88
|
def sym_type(self) -> SymbolType:
|
|
101
89
|
"""Get sym_type."""
|
|
102
|
-
return self.decl.
|
|
90
|
+
return self.decl.sym_category
|
|
103
91
|
|
|
104
|
-
|
|
92
|
+
@property
|
|
93
|
+
def sym_dotted_name(self) -> str:
|
|
94
|
+
"""Return a full path of the symbol."""
|
|
95
|
+
out = [self.defn[0].sym_name]
|
|
96
|
+
current_tab = self.parent_tab
|
|
97
|
+
while current_tab is not None:
|
|
98
|
+
out.append(current_tab.name)
|
|
99
|
+
if current_tab.has_parent():
|
|
100
|
+
current_tab = current_tab.parent
|
|
101
|
+
else:
|
|
102
|
+
break
|
|
103
|
+
out.reverse()
|
|
104
|
+
return ".".join(out)
|
|
105
|
+
|
|
106
|
+
def add_defn(self, node: ast.NameAtom) -> None:
|
|
105
107
|
"""Add defn."""
|
|
106
108
|
self.defn.append(node)
|
|
107
|
-
node.
|
|
109
|
+
node.sym = self
|
|
110
|
+
|
|
111
|
+
def add_use(self, node: ast.NameAtom) -> None:
|
|
112
|
+
"""Add use."""
|
|
113
|
+
self.uses.append(node)
|
|
114
|
+
node.sym = self
|
|
108
115
|
|
|
109
116
|
def __repr__(self) -> str:
|
|
110
117
|
"""Repr."""
|
|
111
|
-
return (
|
|
112
|
-
f"Symbol({self.sym_name}, {self.sym_type}, {self.access}, "
|
|
113
|
-
f"{self.typ}, {self.defn})"
|
|
114
|
-
)
|
|
118
|
+
return f"Symbol({self.sym_name}, {self.sym_type}, {self.access}, {self.defn})"
|
|
115
119
|
|
|
116
120
|
|
|
117
121
|
class SymbolTable:
|
|
@@ -126,7 +130,7 @@ class SymbolTable:
|
|
|
126
130
|
self.parent = parent if parent else self
|
|
127
131
|
self.kid: list[SymbolTable] = []
|
|
128
132
|
self.tab: dict[str, Symbol] = {}
|
|
129
|
-
self.
|
|
133
|
+
self.inherit: list[SymbolTable] = []
|
|
130
134
|
|
|
131
135
|
def has_parent(self) -> bool:
|
|
132
136
|
"""Check if has parent."""
|
|
@@ -142,6 +146,10 @@ class SymbolTable:
|
|
|
142
146
|
"""Lookup a variable in the symbol table."""
|
|
143
147
|
if name in self.tab:
|
|
144
148
|
return self.tab[name]
|
|
149
|
+
for i in self.inherit:
|
|
150
|
+
found = i.lookup(name, deep=False)
|
|
151
|
+
if found:
|
|
152
|
+
return found
|
|
145
153
|
if deep and self.has_parent():
|
|
146
154
|
return self.get_parent().lookup(name, deep)
|
|
147
155
|
return None
|
|
@@ -164,7 +172,7 @@ class SymbolTable:
|
|
|
164
172
|
)
|
|
165
173
|
if node.sym_name not in self.tab:
|
|
166
174
|
self.tab[node.sym_name] = Symbol(
|
|
167
|
-
defn=node,
|
|
175
|
+
defn=node.name_spec,
|
|
168
176
|
access=(
|
|
169
177
|
access_spec
|
|
170
178
|
if isinstance(access_spec, SymbolAccess)
|
|
@@ -173,8 +181,8 @@ class SymbolTable:
|
|
|
173
181
|
parent_tab=self,
|
|
174
182
|
)
|
|
175
183
|
else:
|
|
176
|
-
self.tab[node.sym_name].add_defn(node)
|
|
177
|
-
node.
|
|
184
|
+
self.tab[node.sym_name].add_defn(node.name_spec)
|
|
185
|
+
node.name_spec.sym = self.tab[node.sym_name]
|
|
178
186
|
return collision
|
|
179
187
|
|
|
180
188
|
def find_scope(self, name: str) -> Optional[SymbolTable]:
|
|
@@ -102,9 +102,9 @@ class TestLarkParser(TestCaseMicroSuite):
|
|
|
102
102
|
"JacSource",
|
|
103
103
|
"EmptyToken",
|
|
104
104
|
"AstSymbolNode",
|
|
105
|
+
"AstSymbolStubNode",
|
|
105
106
|
"AstImplNeedingNode",
|
|
106
107
|
"AstAccessNode",
|
|
107
|
-
"TokenSymbol",
|
|
108
108
|
"Literal",
|
|
109
109
|
"AstDocNode",
|
|
110
110
|
"AstSemStrNode",
|
|
@@ -119,7 +119,7 @@ class TestLarkParser(TestCaseMicroSuite):
|
|
|
119
119
|
"ArchBlockStmt",
|
|
120
120
|
"EnumBlockStmt",
|
|
121
121
|
"CodeBlockStmt",
|
|
122
|
-
"
|
|
122
|
+
"NameAtom",
|
|
123
123
|
"ArchSpec",
|
|
124
124
|
"MatchPattern",
|
|
125
125
|
]
|
jaclang/core/aott.py
CHANGED
|
@@ -4,18 +4,30 @@ AOTT: Automated Operational Type Transformation.
|
|
|
4
4
|
This has all the necessary functions to perform the AOTT operations.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import base64
|
|
8
|
+
import logging
|
|
7
9
|
import re
|
|
8
10
|
from enum import Enum
|
|
11
|
+
from io import BytesIO
|
|
9
12
|
from typing import Any
|
|
10
13
|
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
from PIL import Image
|
|
17
|
+
except ImportError:
|
|
18
|
+
Image = None
|
|
19
|
+
|
|
20
|
+
from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
|
|
11
21
|
from jaclang.core.llms.base import BaseLLM
|
|
12
|
-
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
IMG_FORMATS = ["PngImageFile", "JpegImageFile"]
|
|
13
25
|
|
|
14
26
|
|
|
15
27
|
def aott_raise(
|
|
16
28
|
model: BaseLLM,
|
|
17
29
|
information: str,
|
|
18
|
-
inputs_information: str,
|
|
30
|
+
inputs_information: str | list[dict],
|
|
19
31
|
output_information: str,
|
|
20
32
|
type_explanations: str,
|
|
21
33
|
action: str,
|
|
@@ -25,18 +37,43 @@ def aott_raise(
|
|
|
25
37
|
model_params: dict,
|
|
26
38
|
) -> str:
|
|
27
39
|
"""AOTT Raise uses the information (Meanings types values) provided to generate a prompt(meaning in)."""
|
|
40
|
+
system_prompt = model.MTLLM_SYSTEM_PROMPT
|
|
41
|
+
meaning_in: str | list[dict]
|
|
28
42
|
if method != "ReAct":
|
|
29
|
-
system_prompt = model.MTLLM_SYSTEM_PROMPT
|
|
30
|
-
mtllm_prompt = model.MTLLM_PROMPT.format(
|
|
31
|
-
information=information,
|
|
32
|
-
inputs_information=inputs_information,
|
|
33
|
-
output_information=output_information,
|
|
34
|
-
type_explanations=type_explanations,
|
|
35
|
-
action=action,
|
|
36
|
-
context=context,
|
|
37
|
-
)
|
|
38
43
|
method_prompt = model.MTLLM_METHOD_PROMPTS[method]
|
|
39
|
-
|
|
44
|
+
if isinstance(inputs_information, str):
|
|
45
|
+
mtllm_prompt = model.MTLLM_PROMPT.format(
|
|
46
|
+
information=information,
|
|
47
|
+
inputs_information=inputs_information,
|
|
48
|
+
output_information=output_information,
|
|
49
|
+
type_explanations=type_explanations,
|
|
50
|
+
action=action,
|
|
51
|
+
context=context,
|
|
52
|
+
).strip()
|
|
53
|
+
meaning_in = f"{system_prompt}\n{mtllm_prompt}\n{method_prompt}".strip()
|
|
54
|
+
else:
|
|
55
|
+
upper_half = model.MTLLM_PROMPT.split("{inputs_information}")[0]
|
|
56
|
+
lower_half = model.MTLLM_PROMPT.split("{inputs_information}")[1]
|
|
57
|
+
upper_half = upper_half.format(
|
|
58
|
+
information=information,
|
|
59
|
+
context=context,
|
|
60
|
+
)
|
|
61
|
+
lower_half = lower_half.format(
|
|
62
|
+
output_information=output_information,
|
|
63
|
+
type_explanations=type_explanations,
|
|
64
|
+
action=action,
|
|
65
|
+
)
|
|
66
|
+
meaning_in = (
|
|
67
|
+
[
|
|
68
|
+
{"type": "text", "text": system_prompt},
|
|
69
|
+
{"type": "text", "text": upper_half},
|
|
70
|
+
]
|
|
71
|
+
+ inputs_information
|
|
72
|
+
+ [
|
|
73
|
+
{"type": "text", "text": lower_half},
|
|
74
|
+
{"type": "text", "text": method_prompt},
|
|
75
|
+
]
|
|
76
|
+
)
|
|
40
77
|
return model(meaning_in, **model_params)
|
|
41
78
|
else:
|
|
42
79
|
assert tools, "Tools must be provided for the ReAct method."
|
|
@@ -71,7 +108,7 @@ def get_info_types(
|
|
|
71
108
|
else None
|
|
72
109
|
)
|
|
73
110
|
info_str.append(
|
|
74
|
-
f"{sem_info.semstr} ({sem_info.name}) ({sem_info.type}) = {get_object_string(incl[1])}"
|
|
111
|
+
f"{sem_info.semstr} ({sem_info.name}) ({sem_info.type}) = {get_object_string(incl[1])}".strip()
|
|
75
112
|
)
|
|
76
113
|
return ("\n".join(info_str), collected_types)
|
|
77
114
|
|
|
@@ -142,7 +179,7 @@ def get_type_explanation(
|
|
|
142
179
|
if sem_info.type == "Enum" and isinstance(type_info, list):
|
|
143
180
|
for enum_item in type_info:
|
|
144
181
|
type_info_str.append(
|
|
145
|
-
f"{enum_item.semstr} ({enum_item.name}) (EnumItem)"
|
|
182
|
+
f"{enum_item.semstr} ({enum_item.name}) (EnumItem)".strip()
|
|
146
183
|
)
|
|
147
184
|
type_example[0] = type_example[0].replace("(", f".{enum_item.name}")
|
|
148
185
|
elif sem_info.type in ["obj", "class", "node", "edge"] and isinstance(
|
|
@@ -152,7 +189,7 @@ def get_type_explanation(
|
|
|
152
189
|
if arch_item.type in ["obj", "class", "node", "edge"]:
|
|
153
190
|
continue
|
|
154
191
|
type_info_str.append(
|
|
155
|
-
f"{arch_item.semstr} ({arch_item.name}) ({arch_item.type})"
|
|
192
|
+
f"{arch_item.semstr} ({arch_item.name}) ({arch_item.type})".strip()
|
|
156
193
|
)
|
|
157
194
|
type_example.append(f"{arch_item.name}={arch_item.type}, ")
|
|
158
195
|
if arch_item.type and extract_non_primary_type(arch_item.type):
|
|
@@ -162,7 +199,7 @@ def get_type_explanation(
|
|
|
162
199
|
else:
|
|
163
200
|
type_example.append(")")
|
|
164
201
|
return (
|
|
165
|
-
f"{sem_info.semstr} ({sem_info.name}) ({sem_info.type}) eg:- {''.join(type_example)} -> {', '.join(type_info_str)}", # noqa: E501
|
|
202
|
+
f"{sem_info.semstr} ({sem_info.name}) ({sem_info.type}) eg:- {''.join(type_example)} -> {', '.join(type_info_str)}".strip(), # noqa: E501
|
|
166
203
|
set(type_info_types),
|
|
167
204
|
)
|
|
168
205
|
return None, None
|
|
@@ -212,3 +249,62 @@ class Tool:
|
|
|
212
249
|
"""Initialize the Tool class."""
|
|
213
250
|
# TODO: Implement the Tool class
|
|
214
251
|
pass
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def get_input_information(
|
|
255
|
+
inputs: list[tuple[str, str, str, Any]], type_collector: list
|
|
256
|
+
) -> str | list[dict]:
|
|
257
|
+
"""
|
|
258
|
+
Get the input information for the AOTT operation.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
str | list[dict]: If the input does not contain images, returns a string with the input information.
|
|
262
|
+
If the input contains images, returns a list of dictionaries representing the input information,
|
|
263
|
+
where each dictionary contains either text or image_url.
|
|
264
|
+
|
|
265
|
+
"""
|
|
266
|
+
contains_imgs = any(get_type_annotation(i[3]) in IMG_FORMATS for i in inputs)
|
|
267
|
+
if not contains_imgs:
|
|
268
|
+
inputs_information_list = []
|
|
269
|
+
for i in inputs:
|
|
270
|
+
typ_anno = get_type_annotation(i[3])
|
|
271
|
+
type_collector.extend(extract_non_primary_type(typ_anno))
|
|
272
|
+
inputs_information_list.append(
|
|
273
|
+
f"{i[0] if i[0] else ''} ({i[2]}) ({typ_anno}) = {get_object_string(i[3])}".strip()
|
|
274
|
+
)
|
|
275
|
+
return "\n".join(inputs_information_list)
|
|
276
|
+
else:
|
|
277
|
+
inputs_information_dict_list: list[dict] = []
|
|
278
|
+
for i in inputs:
|
|
279
|
+
if get_type_annotation(i[3]) in IMG_FORMATS:
|
|
280
|
+
img_base64 = image_to_base64(i[3])
|
|
281
|
+
image_repr: list[dict] = [
|
|
282
|
+
{
|
|
283
|
+
"type": "text",
|
|
284
|
+
"text": f"{i[0] if i[0] else ''} ({i[2]}) (Image) = ".strip(),
|
|
285
|
+
},
|
|
286
|
+
{"type": "image_url", "image_url": {"url": img_base64}},
|
|
287
|
+
]
|
|
288
|
+
inputs_information_dict_list.extend(image_repr)
|
|
289
|
+
continue
|
|
290
|
+
typ_anno = get_type_annotation(i[3])
|
|
291
|
+
type_collector.extend(extract_non_primary_type(typ_anno))
|
|
292
|
+
inputs_information_dict_list.append(
|
|
293
|
+
{
|
|
294
|
+
"type": "text",
|
|
295
|
+
"text": f"{i[0] if i[0] else ''} ({i[2]}) ({typ_anno}) = {get_object_string(i[3])}".strip(),
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
return inputs_information_dict_list
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def image_to_base64(image: Image) -> str:
|
|
302
|
+
"""Convert an image to base64 expected by OpenAI."""
|
|
303
|
+
if not Image:
|
|
304
|
+
log = logging.getLogger(__name__)
|
|
305
|
+
log.error("Pillow is not installed. Please install Pillow to use images.")
|
|
306
|
+
return ""
|
|
307
|
+
img_format = image.format
|
|
308
|
+
with BytesIO() as buffer:
|
|
309
|
+
image.save(buffer, format=img_format, quality=100)
|
|
310
|
+
return f"data:image/{img_format.lower()};base64,{base64.b64encode(buffer.getvalue()).decode()}"
|
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import types
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
|
-
from typing import Callable, Optional
|
|
7
|
+
from typing import Any, Callable, Optional
|
|
8
8
|
from uuid import UUID, uuid4
|
|
9
9
|
|
|
10
10
|
from jaclang.compiler.constant import EdgeDir
|
|
11
11
|
from jaclang.core.utils import collect_node_connections
|
|
12
|
-
from jaclang.plugin.feature import JacFeature as Jac
|
|
13
|
-
from jaclang.plugin.spec import DSFunc
|
|
14
12
|
|
|
15
13
|
|
|
16
14
|
@dataclass(eq=False)
|
|
@@ -57,6 +55,8 @@ class NodeAnchor(ObjectAnchor):
|
|
|
57
55
|
|
|
58
56
|
def populate_edges(self) -> None:
|
|
59
57
|
"""Populate edges from edge ids."""
|
|
58
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
59
|
+
|
|
60
60
|
if len(self.edges) == 0 and len(self.edge_ids) > 0:
|
|
61
61
|
for e_id in self.edge_ids:
|
|
62
62
|
edge = Jac.context().get_obj(e_id)
|
|
@@ -229,7 +229,13 @@ class WalkerAnchor(ObjectAnchor):
|
|
|
229
229
|
|
|
230
230
|
def visit_node(
|
|
231
231
|
self,
|
|
232
|
-
nds:
|
|
232
|
+
nds: (
|
|
233
|
+
list[NodeArchitype | EdgeArchitype]
|
|
234
|
+
| list[NodeArchitype]
|
|
235
|
+
| list[EdgeArchitype]
|
|
236
|
+
| NodeArchitype
|
|
237
|
+
| EdgeArchitype
|
|
238
|
+
),
|
|
233
239
|
) -> bool:
|
|
234
240
|
"""Walker visits node."""
|
|
235
241
|
nd_list: list[NodeArchitype | EdgeArchitype]
|
|
@@ -251,7 +257,13 @@ class WalkerAnchor(ObjectAnchor):
|
|
|
251
257
|
|
|
252
258
|
def ignore_node(
|
|
253
259
|
self,
|
|
254
|
-
nds:
|
|
260
|
+
nds: (
|
|
261
|
+
list[NodeArchitype | EdgeArchitype]
|
|
262
|
+
| list[NodeArchitype]
|
|
263
|
+
| list[EdgeArchitype]
|
|
264
|
+
| NodeArchitype
|
|
265
|
+
| EdgeArchitype
|
|
266
|
+
),
|
|
255
267
|
) -> bool:
|
|
256
268
|
"""Walker ignores node."""
|
|
257
269
|
nd_list: list[NodeArchitype | EdgeArchitype]
|
|
@@ -354,11 +366,15 @@ class NodeArchitype(Architype):
|
|
|
354
366
|
|
|
355
367
|
def __init__(self) -> None:
|
|
356
368
|
"""Create node architype."""
|
|
369
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
370
|
+
|
|
357
371
|
self._jac_: NodeAnchor = NodeAnchor(obj=self)
|
|
358
372
|
Jac.context().save_obj(self, persistent=self._jac_.persistent)
|
|
359
373
|
|
|
360
374
|
def save(self) -> None:
|
|
361
375
|
"""Save the node to the memory/storage hierarchy."""
|
|
376
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
377
|
+
|
|
362
378
|
self._jac_.persistent = True
|
|
363
379
|
Jac.context().save_obj(self, persistent=True)
|
|
364
380
|
|
|
@@ -383,11 +399,15 @@ class EdgeArchitype(Architype):
|
|
|
383
399
|
|
|
384
400
|
def __init__(self) -> None:
|
|
385
401
|
"""Create edge architype."""
|
|
402
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
403
|
+
|
|
386
404
|
self._jac_: EdgeAnchor = EdgeAnchor(obj=self)
|
|
387
405
|
Jac.context().save_obj(self, persistent=self.persistent)
|
|
388
406
|
|
|
389
407
|
def save(self) -> None:
|
|
390
408
|
"""Save the edge to the memory/storage hierarchy."""
|
|
409
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
410
|
+
|
|
391
411
|
self.persistent = True
|
|
392
412
|
Jac.context().save_obj(self, persistent=True)
|
|
393
413
|
|
|
@@ -405,6 +425,8 @@ class EdgeArchitype(Architype):
|
|
|
405
425
|
|
|
406
426
|
def populate_nodes(self) -> None:
|
|
407
427
|
"""Populate nodes for the edges from node ids."""
|
|
428
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
429
|
+
|
|
408
430
|
if self._jac_.source_id:
|
|
409
431
|
obj = Jac.context().get_obj(self._jac_.source_id)
|
|
410
432
|
if obj is None:
|
|
@@ -439,6 +461,13 @@ class WalkerArchitype(Architype):
|
|
|
439
461
|
self._jac_: WalkerAnchor = WalkerAnchor(obj=self)
|
|
440
462
|
|
|
441
463
|
|
|
464
|
+
class GenericEdge(EdgeArchitype):
|
|
465
|
+
"""Generic Root Node."""
|
|
466
|
+
|
|
467
|
+
_jac_entry_funcs_ = []
|
|
468
|
+
_jac_exit_funcs_ = []
|
|
469
|
+
|
|
470
|
+
|
|
442
471
|
class Root(NodeArchitype):
|
|
443
472
|
"""Generic Root Node."""
|
|
444
473
|
|
|
@@ -460,92 +489,14 @@ class Root(NodeArchitype):
|
|
|
460
489
|
self._jac_.edges = []
|
|
461
490
|
|
|
462
491
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
_jac_entry_funcs_ = []
|
|
467
|
-
_jac_exit_funcs_ = []
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
class JacTestResult(unittest.TextTestResult):
|
|
471
|
-
"""Jac test result class."""
|
|
472
|
-
|
|
473
|
-
def __init__(
|
|
474
|
-
self,
|
|
475
|
-
stream, # noqa
|
|
476
|
-
descriptions, # noqa
|
|
477
|
-
verbosity: int,
|
|
478
|
-
max_failures: Optional[int] = None,
|
|
479
|
-
) -> None:
|
|
480
|
-
"""Initialize FailFastTestResult object."""
|
|
481
|
-
super().__init__(stream, descriptions, verbosity) # noqa
|
|
482
|
-
self.failures_count = JacTestCheck.failcount
|
|
483
|
-
self.max_failures = max_failures
|
|
484
|
-
|
|
485
|
-
def addFailure(self, test, err) -> None: # noqa
|
|
486
|
-
"""Count failures and stop."""
|
|
487
|
-
super().addFailure(test, err)
|
|
488
|
-
self.failures_count += 1
|
|
489
|
-
if self.max_failures is not None and self.failures_count >= self.max_failures:
|
|
490
|
-
self.stop()
|
|
491
|
-
|
|
492
|
-
def stop(self) -> None:
|
|
493
|
-
"""Stop the test execution."""
|
|
494
|
-
self.shouldStop = True
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
class JacTextTestRunner(unittest.TextTestRunner):
|
|
498
|
-
"""Jac test runner class."""
|
|
499
|
-
|
|
500
|
-
def __init__(self, max_failures: Optional[int] = None, **kwargs) -> None: # noqa
|
|
501
|
-
"""Initialize JacTextTestRunner object."""
|
|
502
|
-
self.max_failures = max_failures
|
|
503
|
-
super().__init__(**kwargs)
|
|
504
|
-
|
|
505
|
-
def _makeResult(self) -> JacTestResult: # noqa
|
|
506
|
-
"""Override the method to return an instance of JacTestResult."""
|
|
507
|
-
return JacTestResult(
|
|
508
|
-
self.stream,
|
|
509
|
-
self.descriptions,
|
|
510
|
-
self.verbosity,
|
|
511
|
-
max_failures=self.max_failures,
|
|
512
|
-
)
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
class JacTestCheck:
|
|
516
|
-
"""Jac Testing and Checking."""
|
|
517
|
-
|
|
518
|
-
test_case = unittest.TestCase()
|
|
519
|
-
test_suite = unittest.TestSuite()
|
|
520
|
-
breaker = False
|
|
521
|
-
failcount = 0
|
|
522
|
-
|
|
523
|
-
@staticmethod
|
|
524
|
-
def reset() -> None:
|
|
525
|
-
"""Clear the test suite."""
|
|
526
|
-
JacTestCheck.test_case = unittest.TestCase()
|
|
527
|
-
JacTestCheck.test_suite = unittest.TestSuite()
|
|
528
|
-
|
|
529
|
-
@staticmethod
|
|
530
|
-
def run_test(xit: bool, maxfail: int | None, verbose: bool) -> None:
|
|
531
|
-
"""Run the test suite."""
|
|
532
|
-
verb = 2 if verbose else 1
|
|
533
|
-
runner = JacTextTestRunner(max_failures=maxfail, failfast=xit, verbosity=verb)
|
|
534
|
-
result = runner.run(JacTestCheck.test_suite)
|
|
535
|
-
if result.wasSuccessful():
|
|
536
|
-
print("Passed successfully.")
|
|
537
|
-
else:
|
|
538
|
-
fails = len(result.failures)
|
|
539
|
-
JacTestCheck.failcount += fails
|
|
540
|
-
JacTestCheck.breaker = (
|
|
541
|
-
(JacTestCheck.failcount >= maxfail) if maxfail else True
|
|
542
|
-
)
|
|
492
|
+
@dataclass(eq=False)
|
|
493
|
+
class DSFunc:
|
|
494
|
+
"""Data Spatial Function."""
|
|
543
495
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
JacTestCheck.test_suite.addTest(unittest.FunctionTestCase(test_fun))
|
|
496
|
+
name: str
|
|
497
|
+
trigger: type | types.UnionType | tuple[type | types.UnionType, ...] | None
|
|
498
|
+
func: Callable[[Any, Any], Any] | None = None
|
|
548
499
|
|
|
549
|
-
def
|
|
550
|
-
"""
|
|
551
|
-
|
|
500
|
+
def resolve(self, cls: type) -> None:
|
|
501
|
+
"""Resolve the function."""
|
|
502
|
+
self.func = getattr(cls, self.name)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Core constructs for Jac Language."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from .architype import (
|
|
7
|
+
Architype,
|
|
8
|
+
DSFunc,
|
|
9
|
+
EdgeAnchor,
|
|
10
|
+
EdgeArchitype,
|
|
11
|
+
ElementAnchor,
|
|
12
|
+
GenericEdge,
|
|
13
|
+
NodeAnchor,
|
|
14
|
+
NodeArchitype,
|
|
15
|
+
ObjectAnchor,
|
|
16
|
+
Root,
|
|
17
|
+
WalkerAnchor,
|
|
18
|
+
WalkerArchitype,
|
|
19
|
+
)
|
|
20
|
+
from .context import ExecutionContext, exec_context
|
|
21
|
+
from .memory import Memory, ShelveStorage
|
|
22
|
+
from .test import JacTestCheck, JacTestResult, JacTextTestRunner
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"ElementAnchor",
|
|
26
|
+
"ObjectAnchor",
|
|
27
|
+
"NodeAnchor",
|
|
28
|
+
"EdgeAnchor",
|
|
29
|
+
"WalkerAnchor",
|
|
30
|
+
"Architype",
|
|
31
|
+
"NodeArchitype",
|
|
32
|
+
"EdgeArchitype",
|
|
33
|
+
"WalkerArchitype",
|
|
34
|
+
"GenericEdge",
|
|
35
|
+
"Root",
|
|
36
|
+
"DSFunc",
|
|
37
|
+
"Memory",
|
|
38
|
+
"ShelveStorage",
|
|
39
|
+
"ExecutionContext",
|
|
40
|
+
"exec_context",
|
|
41
|
+
"JacTestResult",
|
|
42
|
+
"JacTextTestRunner",
|
|
43
|
+
"JacTestCheck",
|
|
44
|
+
]
|