jaclang 0.5.17__py3-none-any.whl → 0.6.0__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 +2 -6
- jaclang/cli/cli.py +4 -2
- jaclang/compiler/__init__.py +12 -5
- jaclang/compiler/absyntree.py +23 -23
- jaclang/compiler/generated/jac_parser.py +2 -2
- jaclang/compiler/jac.lark +9 -9
- jaclang/compiler/parser.py +76 -21
- jaclang/compiler/passes/ir_pass.py +10 -8
- jaclang/compiler/passes/main/__init__.py +3 -2
- jaclang/compiler/passes/main/access_modifier_pass.py +173 -0
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +3 -2
- jaclang/compiler/passes/main/import_pass.py +33 -21
- jaclang/compiler/passes/main/pyast_gen_pass.py +99 -44
- jaclang/compiler/passes/main/pyast_load_pass.py +141 -77
- jaclang/compiler/passes/main/pyout_pass.py +14 -13
- jaclang/compiler/passes/main/registry_pass.py +8 -3
- jaclang/compiler/passes/main/schedules.py +5 -3
- jaclang/compiler/passes/main/sym_tab_build_pass.py +47 -37
- jaclang/compiler/passes/main/tests/test_import_pass.py +2 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +85 -23
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -4
- jaclang/compiler/passes/transform.py +2 -0
- jaclang/compiler/symtable.py +10 -3
- jaclang/compiler/tests/test_importer.py +9 -0
- jaclang/compiler/workspace.py +19 -11
- jaclang/core/aott.py +34 -63
- jaclang/core/importer.py +73 -65
- jaclang/core/llms/__init__.py +20 -0
- jaclang/core/llms/anthropic.py +61 -0
- jaclang/core/llms/base.py +206 -0
- jaclang/core/llms/groq.py +67 -0
- jaclang/core/llms/huggingface.py +73 -0
- jaclang/core/llms/ollama.py +78 -0
- jaclang/core/llms/openai.py +61 -0
- jaclang/core/llms/togetherai.py +60 -0
- jaclang/core/llms/utils.py +9 -0
- jaclang/core/utils.py +16 -1
- jaclang/plugin/default.py +47 -16
- jaclang/plugin/feature.py +9 -6
- jaclang/plugin/spec.py +8 -1
- jaclang/settings.py +95 -0
- jaclang/utils/helpers.py +6 -2
- jaclang/utils/treeprinter.py +9 -6
- jaclang/vendor/mypy/checker.py +2 -3
- jaclang-0.6.0.dist-info/METADATA +17 -0
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/RECORD +49 -39
- jaclang/core/llms.py +0 -29
- jaclang-0.5.17.dist-info/METADATA +0 -7
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/WHEEL +0 -0
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/entry_points.txt +0 -0
- {jaclang-0.5.17.dist-info → jaclang-0.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Huggingface client for MTLLM."""
|
|
2
|
+
|
|
3
|
+
from .base import BaseLLM
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
REASON_SUFFIX = """
|
|
7
|
+
Reason and return the output results(s) only such that <Output> should be eval(<Output>) Compatible and reflects the
|
|
8
|
+
expected output type, Follow the format below to provide the reasoning for the output result(s).
|
|
9
|
+
|
|
10
|
+
[Reasoning] <Reasoning>
|
|
11
|
+
[Output] <Output>
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
NORMAL_SUFFIX = """Return the output result(s) only such that <Output> should be eval(<Output>) Compatible and
|
|
15
|
+
reflects the expected output type, Follow the format below to provide the output result(s).
|
|
16
|
+
|
|
17
|
+
[Output] <Output>
|
|
18
|
+
""" # noqa E501
|
|
19
|
+
|
|
20
|
+
CHAIN_OF_THOUGHT_SUFFIX = """
|
|
21
|
+
Generate and return the output result(s) only, adhering to the provided Type in the following format. Perform the operation in a chain of thoughts.(Think Step by Step)
|
|
22
|
+
|
|
23
|
+
[Chain of Thoughts] <Chain of Thoughts>
|
|
24
|
+
[Output] <Result>
|
|
25
|
+
""" # noqa E501
|
|
26
|
+
|
|
27
|
+
REACT_SUFFIX = """
|
|
28
|
+
""" # noqa E501
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Huggingface(BaseLLM):
|
|
32
|
+
"""Huggingface API client for Large Language Models (LLMs)."""
|
|
33
|
+
|
|
34
|
+
MTLLM_METHOD_PROMPTS: dict[str, str] = {
|
|
35
|
+
"Normal": NORMAL_SUFFIX,
|
|
36
|
+
"Reason": REASON_SUFFIX,
|
|
37
|
+
"Chain-of-Thoughts": CHAIN_OF_THOUGHT_SUFFIX,
|
|
38
|
+
"ReAct": REACT_SUFFIX,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self, verbose: bool = False, max_tries: int = 10, **kwargs: dict
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Initialize the Huggingface API client."""
|
|
45
|
+
import torch # type: ignore
|
|
46
|
+
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline # type: ignore
|
|
47
|
+
|
|
48
|
+
torch.random.manual_seed(0)
|
|
49
|
+
model = AutoModelForCausalLM.from_pretrained(
|
|
50
|
+
kwargs.get("model_name", "microsoft/Phi-3-mini-128k-instruct"),
|
|
51
|
+
device_map=kwargs.get("device_map", "cuda"),
|
|
52
|
+
torch_dtype="auto",
|
|
53
|
+
trust_remote_code=True,
|
|
54
|
+
)
|
|
55
|
+
tokenizer = AutoTokenizer.from_pretrained(
|
|
56
|
+
kwargs.get("model_name", "microsoft/Phi-3-mini-128k-instruct")
|
|
57
|
+
)
|
|
58
|
+
self.verbose = verbose
|
|
59
|
+
self.max_tries = max_tries
|
|
60
|
+
self.pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
|
|
61
|
+
self.temperature = kwargs.get("temperature", 0.7)
|
|
62
|
+
self.max_tokens = kwargs.get("max_new_tokens", 1024)
|
|
63
|
+
|
|
64
|
+
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
65
|
+
"""Infer a response from the input meaning."""
|
|
66
|
+
messages = [{"role": "user", "content": meaning_in}]
|
|
67
|
+
output = self.pipe(
|
|
68
|
+
messages,
|
|
69
|
+
temperature=kwargs.get("temperature", self.temperature),
|
|
70
|
+
max_length=kwargs.get("max_new_tokens", self.max_tokens),
|
|
71
|
+
**kwargs,
|
|
72
|
+
)
|
|
73
|
+
return output[0]["generated_text"][-1]["content"]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Ollama client for MTLLM."""
|
|
2
|
+
|
|
3
|
+
from .base import BaseLLM
|
|
4
|
+
|
|
5
|
+
REASON_SUFFIX = """
|
|
6
|
+
Reason and return the output results(s) only such that <Output> should be eval(<Output>) Compatible and reflects the
|
|
7
|
+
expected output type, Follow the format below to provide the reasoning for the output result(s).
|
|
8
|
+
|
|
9
|
+
[Reasoning] <Reasoning>
|
|
10
|
+
[Output] <Output>
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
NORMAL_SUFFIX = """Return the output result(s) only such that <Output> should be eval(<Output>) Compatible and
|
|
14
|
+
reflects the expected output type, Follow the format below to provide the output result(s).
|
|
15
|
+
|
|
16
|
+
[Output] <Output>
|
|
17
|
+
""" # noqa E501
|
|
18
|
+
|
|
19
|
+
CHAIN_OF_THOUGHT_SUFFIX = """
|
|
20
|
+
Generate and return the output result(s) only, adhering to the provided Type in the following format. Perform the operation in a chain of thoughts.(Think Step by Step)
|
|
21
|
+
|
|
22
|
+
[Chain of Thoughts] <Chain of Thoughts>
|
|
23
|
+
[Output] <Result>
|
|
24
|
+
""" # noqa E501
|
|
25
|
+
|
|
26
|
+
REACT_SUFFIX = """
|
|
27
|
+
""" # noqa E501
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Ollama(BaseLLM):
|
|
31
|
+
"""Ollama API client for Large Language Models (LLMs)."""
|
|
32
|
+
|
|
33
|
+
MTLLM_METHOD_PROMPTS: dict[str, str] = {
|
|
34
|
+
"Normal": NORMAL_SUFFIX,
|
|
35
|
+
"Reason": REASON_SUFFIX,
|
|
36
|
+
"Chain-of-Thoughts": CHAIN_OF_THOUGHT_SUFFIX,
|
|
37
|
+
"ReAct": REACT_SUFFIX,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self, verbose: bool = False, max_tries: int = 10, **kwargs: dict
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Initialize the Ollama API client."""
|
|
44
|
+
import ollama # type: ignore
|
|
45
|
+
|
|
46
|
+
self.client = ollama.Client(host=kwargs.get("host", "http://localhost:11434"))
|
|
47
|
+
self.verbose = verbose
|
|
48
|
+
self.max_tries = max_tries
|
|
49
|
+
self.model_name = kwargs.get("model_name", "phi3")
|
|
50
|
+
self.default_model_params = {
|
|
51
|
+
k: v for k, v in kwargs.items() if k not in ["model_name", "host"]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
55
|
+
"""Infer a response from the input meaning."""
|
|
56
|
+
model = str(kwargs.get("model_name", self.model_name))
|
|
57
|
+
if not self.check_model(model):
|
|
58
|
+
self.download_model(model)
|
|
59
|
+
model_params = {k: v for k, v in kwargs.items() if k not in ["model_name"]}
|
|
60
|
+
messages = [{"role": "user", "content": meaning_in}]
|
|
61
|
+
output = self.client.chat(
|
|
62
|
+
model=model,
|
|
63
|
+
messages=messages,
|
|
64
|
+
options={**self.default_model_params, **model_params},
|
|
65
|
+
)
|
|
66
|
+
return output["message"]["content"]
|
|
67
|
+
|
|
68
|
+
def check_model(self, model_name: str) -> bool:
|
|
69
|
+
"""Check if the model is available."""
|
|
70
|
+
try:
|
|
71
|
+
self.client.show(model_name)
|
|
72
|
+
return True
|
|
73
|
+
except Exception:
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
def download_model(self, model_name: str) -> None:
|
|
77
|
+
"""Download the model."""
|
|
78
|
+
self.client.pull(model_name)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Anthropic API client for MTLLM."""
|
|
2
|
+
|
|
3
|
+
from .base import BaseLLM
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
REASON_SUFFIX = """
|
|
7
|
+
Reason and return the output result(s) only, adhering to the provided Type in the following format
|
|
8
|
+
|
|
9
|
+
[Reasoning] <Reason>
|
|
10
|
+
[Output] <Result>
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
NORMAL_SUFFIX = """Generate and return the output result(s) only, adhering to the provided Type in the following format
|
|
14
|
+
|
|
15
|
+
[Output] <result>
|
|
16
|
+
""" # noqa E501
|
|
17
|
+
|
|
18
|
+
CHAIN_OF_THOUGHT_SUFFIX = """
|
|
19
|
+
Generate and return the output result(s) only, adhering to the provided Type in the following format. Perform the operation in a chain of thoughts.(Think Step by Step)
|
|
20
|
+
|
|
21
|
+
[Chain of Thoughts] <Chain of Thoughts>
|
|
22
|
+
[Output] <Result>
|
|
23
|
+
""" # noqa E501
|
|
24
|
+
|
|
25
|
+
REACT_SUFFIX = """
|
|
26
|
+
""" # noqa E501
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OpenAI(BaseLLM):
|
|
30
|
+
"""Anthropic API client for MTLLM."""
|
|
31
|
+
|
|
32
|
+
MTLLM_METHOD_PROMPTS: dict[str, str] = {
|
|
33
|
+
"Normal": NORMAL_SUFFIX,
|
|
34
|
+
"Reason": REASON_SUFFIX,
|
|
35
|
+
"Chain-of-Thoughts": CHAIN_OF_THOUGHT_SUFFIX,
|
|
36
|
+
"ReAct": REACT_SUFFIX,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self, verbose: bool = False, max_tries: int = 10, **kwargs: dict
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Initialize the Anthropic API client."""
|
|
43
|
+
import openai # type: ignore
|
|
44
|
+
|
|
45
|
+
self.client = openai.OpenAI()
|
|
46
|
+
self.verbose = verbose
|
|
47
|
+
self.max_tries = max_tries
|
|
48
|
+
self.model_name = kwargs.get("model_name", "gpt-3.5-turbo")
|
|
49
|
+
self.temperature = kwargs.get("temperature", 0.7)
|
|
50
|
+
self.max_tokens = kwargs.get("max_tokens", 1024)
|
|
51
|
+
|
|
52
|
+
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
53
|
+
"""Infer a response from the input meaning."""
|
|
54
|
+
messages = [{"role": "user", "content": meaning_in}]
|
|
55
|
+
output = self.client.chat.completions.create(
|
|
56
|
+
model=kwargs.get("model_name", self.model_name),
|
|
57
|
+
temperature=kwargs.get("temperature", self.temperature),
|
|
58
|
+
max_tokens=kwargs.get("max_tokens", self.max_tokens),
|
|
59
|
+
messages=messages,
|
|
60
|
+
)
|
|
61
|
+
return output.choices[0].message.content
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Anthropic API client for MTLLM."""
|
|
2
|
+
|
|
3
|
+
from .base import BaseLLM
|
|
4
|
+
|
|
5
|
+
REASON_SUFFIX = """
|
|
6
|
+
Reason and return the output result(s) only, adhering to the provided Type in the following format
|
|
7
|
+
|
|
8
|
+
[Reasoning] <Reason>
|
|
9
|
+
[Output] <Result>
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
NORMAL_SUFFIX = """Generate and return the output result(s) only, adhering to the provided Type in the following format
|
|
13
|
+
|
|
14
|
+
[Output] <result>
|
|
15
|
+
""" # noqa E501
|
|
16
|
+
|
|
17
|
+
CHAIN_OF_THOUGHT_SUFFIX = """
|
|
18
|
+
Generate and return the output result(s) only, adhering to the provided Type in the following format. Perform the operation in a chain of thoughts.(Think Step by Step)
|
|
19
|
+
|
|
20
|
+
[Chain of Thoughts] <Chain of Thoughts>
|
|
21
|
+
[Output] <Result>
|
|
22
|
+
""" # noqa E501
|
|
23
|
+
|
|
24
|
+
REACT_SUFFIX = """
|
|
25
|
+
""" # noqa E501
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TogetherAI(BaseLLM):
|
|
29
|
+
"""Anthropic API client for MTLLM."""
|
|
30
|
+
|
|
31
|
+
MTLLM_METHOD_PROMPTS: dict[str, str] = {
|
|
32
|
+
"Normal": NORMAL_SUFFIX,
|
|
33
|
+
"Reason": REASON_SUFFIX,
|
|
34
|
+
"Chain-of-Thoughts": CHAIN_OF_THOUGHT_SUFFIX,
|
|
35
|
+
"ReAct": REACT_SUFFIX,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self, verbose: bool = False, max_tries: int = 10, **kwargs: dict
|
|
40
|
+
) -> None:
|
|
41
|
+
"""Initialize the Anthropic API client."""
|
|
42
|
+
import together # type: ignore
|
|
43
|
+
|
|
44
|
+
self.client = together.Together()
|
|
45
|
+
self.verbose = verbose
|
|
46
|
+
self.max_tries = max_tries
|
|
47
|
+
self.model_name = kwargs.get("model_name", "mistralai/Mistral-7B-Instruct-v0.3")
|
|
48
|
+
self.temperature = kwargs.get("temperature", 0.7)
|
|
49
|
+
self.max_tokens = kwargs.get("max_tokens", 1024)
|
|
50
|
+
|
|
51
|
+
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
52
|
+
"""Infer a response from the input meaning."""
|
|
53
|
+
messages = [{"role": "user", "content": meaning_in}]
|
|
54
|
+
output = self.client.chat.completions.create(
|
|
55
|
+
model=kwargs.get("model_name", self.model_name),
|
|
56
|
+
temperature=kwargs.get("temperature", self.temperature),
|
|
57
|
+
max_tokens=kwargs.get("max_tokens", self.max_tokens),
|
|
58
|
+
messages=messages,
|
|
59
|
+
)
|
|
60
|
+
return output.choices[0].message.content
|
jaclang/core/utils.py
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import ast as ast3
|
|
6
|
-
|
|
6
|
+
import sys
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
from typing import Callable, Iterator, TYPE_CHECKING
|
|
7
9
|
|
|
8
10
|
import jaclang.compiler.absyntree as ast
|
|
9
11
|
from jaclang.core.registry import SemScope
|
|
@@ -12,6 +14,19 @@ if TYPE_CHECKING:
|
|
|
12
14
|
from jaclang.core.construct import NodeAnchor, NodeArchitype
|
|
13
15
|
|
|
14
16
|
|
|
17
|
+
@contextmanager
|
|
18
|
+
def sys_path_context(path: str) -> Iterator[None]:
|
|
19
|
+
"""Add a path to sys.path temporarily."""
|
|
20
|
+
novel_path = path not in sys.path
|
|
21
|
+
try:
|
|
22
|
+
if novel_path:
|
|
23
|
+
sys.path.append(path)
|
|
24
|
+
yield
|
|
25
|
+
finally:
|
|
26
|
+
if novel_path:
|
|
27
|
+
sys.path.remove(path)
|
|
28
|
+
|
|
29
|
+
|
|
15
30
|
def collect_node_connections(
|
|
16
31
|
current_node: NodeAnchor,
|
|
17
32
|
visited_nodes: set,
|
jaclang/plugin/default.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import fnmatch
|
|
6
|
+
import html
|
|
6
7
|
import os
|
|
7
8
|
import pickle
|
|
8
9
|
import types
|
|
@@ -18,7 +19,6 @@ from jaclang.core.aott import (
|
|
|
18
19
|
get_all_type_explanations,
|
|
19
20
|
get_info_types,
|
|
20
21
|
get_object_string,
|
|
21
|
-
get_reasoning_output,
|
|
22
22
|
get_type_annotation,
|
|
23
23
|
)
|
|
24
24
|
from jaclang.core.construct import (
|
|
@@ -85,7 +85,11 @@ class JacFeatureDefaults:
|
|
|
85
85
|
for i in on_entry + on_exit:
|
|
86
86
|
i.resolve(cls)
|
|
87
87
|
if not issubclass(cls, arch_base):
|
|
88
|
+
# Saving the module path and reassign it after creating cls
|
|
89
|
+
# So the jac modules are part of the correct module
|
|
90
|
+
cur_module = cls.__module__
|
|
88
91
|
cls = type(cls.__name__, (cls, arch_base), {})
|
|
92
|
+
cls.__module__ = cur_module
|
|
89
93
|
cls._jac_entry_funcs_ = on_entry # type: ignore
|
|
90
94
|
cls._jac_exit_funcs_ = on_exit # type: ignore
|
|
91
95
|
else:
|
|
@@ -423,10 +427,16 @@ class JacFeatureDefaults:
|
|
|
423
427
|
|
|
424
428
|
@staticmethod
|
|
425
429
|
@hookimpl
|
|
426
|
-
def get_root() ->
|
|
430
|
+
def get_root() -> Root:
|
|
427
431
|
"""Jac's assign comprehension feature."""
|
|
428
432
|
return root
|
|
429
433
|
|
|
434
|
+
@staticmethod
|
|
435
|
+
@hookimpl
|
|
436
|
+
def get_root_type() -> Type[Root]:
|
|
437
|
+
"""Jac's root getter."""
|
|
438
|
+
return Root
|
|
439
|
+
|
|
430
440
|
@staticmethod
|
|
431
441
|
@hookimpl
|
|
432
442
|
def build_edge(
|
|
@@ -582,9 +592,15 @@ class JacFeatureDefaults:
|
|
|
582
592
|
_scope = SemScope.get_scope_from_str(scope)
|
|
583
593
|
assert _scope is not None
|
|
584
594
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
595
|
+
method = model_params.pop("method") if "method" in model_params else "Normal"
|
|
596
|
+
available_methods = model.MTLLM_METHOD_PROMPTS.keys()
|
|
597
|
+
assert (
|
|
598
|
+
method in available_methods
|
|
599
|
+
), f"Invalid method: {method}. Select from {available_methods}"
|
|
600
|
+
|
|
601
|
+
context = (
|
|
602
|
+
"\n".join(model_params.pop("context")) if "context" in model_params else ""
|
|
603
|
+
)
|
|
588
604
|
|
|
589
605
|
type_collector: list = []
|
|
590
606
|
information, collected_types = get_info_types(_scope, mod_registry, incl_info)
|
|
@@ -600,22 +616,34 @@ class JacFeatureDefaults:
|
|
|
600
616
|
|
|
601
617
|
output_information = f"{outputs[0]} ({outputs[1]})"
|
|
602
618
|
type_collector.extend(extract_non_primary_type(outputs[1]))
|
|
619
|
+
output_type_explanations = "\n".join(
|
|
620
|
+
list(
|
|
621
|
+
get_all_type_explanations(
|
|
622
|
+
extract_non_primary_type(outputs[1]), mod_registry
|
|
623
|
+
).values()
|
|
624
|
+
)
|
|
625
|
+
)
|
|
603
626
|
|
|
604
627
|
type_explanations_list = list(
|
|
605
628
|
get_all_type_explanations(type_collector, mod_registry).values()
|
|
606
629
|
)
|
|
607
630
|
type_explanations = "\n".join(type_explanations_list)
|
|
608
631
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
632
|
+
meaning_out = aott_raise(
|
|
633
|
+
model=model,
|
|
634
|
+
information=information,
|
|
635
|
+
inputs_information=inputs_information,
|
|
636
|
+
output_information=output_information,
|
|
637
|
+
type_explanations=type_explanations,
|
|
638
|
+
action=action,
|
|
639
|
+
context=context,
|
|
640
|
+
method=method,
|
|
641
|
+
tools=[],
|
|
642
|
+
model_params=model_params,
|
|
643
|
+
)
|
|
644
|
+
output = model.resolve_output(
|
|
645
|
+
meaning_out, outputs[0], outputs[1], output_type_explanations
|
|
616
646
|
)
|
|
617
|
-
meaning_out = model.__infer__(meaning_in, **model_params)
|
|
618
|
-
reasoning, output = get_reasoning_output(meaning_out)
|
|
619
647
|
return output
|
|
620
648
|
|
|
621
649
|
|
|
@@ -691,13 +719,16 @@ class JacBuiltin:
|
|
|
691
719
|
for source, target, edge in connections:
|
|
692
720
|
dot_content += (
|
|
693
721
|
f"{visited_nodes.index(source)} -> {visited_nodes.index(target)} "
|
|
694
|
-
f' [label="{edge._jac_.obj.__class__.__name__} "];\n'
|
|
722
|
+
f' [label="{html.escape(str(edge._jac_.obj.__class__.__name__))} "];\n'
|
|
695
723
|
)
|
|
696
724
|
for node_ in visited_nodes:
|
|
697
725
|
color = (
|
|
698
726
|
colors[node_depths[node_]] if node_depths[node_] < 25 else colors[24]
|
|
699
727
|
)
|
|
700
|
-
dot_content +=
|
|
728
|
+
dot_content += (
|
|
729
|
+
f'{visited_nodes.index(node_)} [label="{html.escape(str(node_._jac_.obj))}"'
|
|
730
|
+
f'fillcolor="{color}"];\n'
|
|
731
|
+
)
|
|
701
732
|
if dot_file:
|
|
702
733
|
with open(dot_file, "w") as f:
|
|
703
734
|
f.write(dot_content + "}")
|
jaclang/plugin/feature.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import types
|
|
6
|
-
from typing import Any, Callable, Optional, Type,
|
|
6
|
+
from typing import Any, Callable, Optional, Type, Union
|
|
7
7
|
|
|
8
8
|
from jaclang.compiler.absyntree import Module
|
|
9
9
|
from jaclang.core.construct import (
|
|
@@ -31,8 +31,6 @@ class JacFeature:
|
|
|
31
31
|
from jaclang.plugin.spec import DSFunc
|
|
32
32
|
from jaclang.compiler.constant import EdgeDir
|
|
33
33
|
|
|
34
|
-
RootType: TypeAlias = Root
|
|
35
|
-
|
|
36
34
|
@staticmethod
|
|
37
35
|
def make_architype(
|
|
38
36
|
cls: type,
|
|
@@ -82,7 +80,7 @@ class JacFeature:
|
|
|
82
80
|
mdl_alias: Optional[str] = None,
|
|
83
81
|
override_name: Optional[str] = None,
|
|
84
82
|
mod_bundle: Optional[Module] = None,
|
|
85
|
-
lng: Optional[str] =
|
|
83
|
+
lng: Optional[str] = "jac",
|
|
86
84
|
items: Optional[dict[str, Union[str, bool]]] = None,
|
|
87
85
|
) -> Optional[types.ModuleType]:
|
|
88
86
|
"""Core Import Process."""
|
|
@@ -218,10 +216,15 @@ class JacFeature:
|
|
|
218
216
|
return pm.hook.assign_compr(target=target, attr_val=attr_val)
|
|
219
217
|
|
|
220
218
|
@staticmethod
|
|
221
|
-
def get_root() ->
|
|
222
|
-
"""Jac's
|
|
219
|
+
def get_root() -> Root:
|
|
220
|
+
"""Jac's root getter."""
|
|
223
221
|
return pm.hook.get_root()
|
|
224
222
|
|
|
223
|
+
@staticmethod
|
|
224
|
+
def get_root_type() -> Type[Root]:
|
|
225
|
+
"""Jac's root type getter."""
|
|
226
|
+
return pm.hook.get_root_type()
|
|
227
|
+
|
|
225
228
|
@staticmethod
|
|
226
229
|
def build_edge(
|
|
227
230
|
is_undirected: bool,
|
jaclang/plugin/spec.py
CHANGED
|
@@ -12,6 +12,7 @@ from jaclang.plugin.default import (
|
|
|
12
12
|
EdgeArchitype,
|
|
13
13
|
EdgeDir,
|
|
14
14
|
NodeArchitype,
|
|
15
|
+
Root,
|
|
15
16
|
WalkerArchitype,
|
|
16
17
|
)
|
|
17
18
|
|
|
@@ -198,7 +199,13 @@ class JacFeatureSpec:
|
|
|
198
199
|
|
|
199
200
|
@staticmethod
|
|
200
201
|
@hookspec(firstresult=True)
|
|
201
|
-
def get_root() ->
|
|
202
|
+
def get_root() -> Root:
|
|
203
|
+
"""Jac's root getter."""
|
|
204
|
+
raise NotImplementedError
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
@hookspec(firstresult=True)
|
|
208
|
+
def get_root_type() -> Type[Root]:
|
|
202
209
|
"""Jac's root getter."""
|
|
203
210
|
raise NotImplementedError
|
|
204
211
|
|
jaclang/settings.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Main settings of Jac lang."""
|
|
2
|
+
|
|
3
|
+
import configparser
|
|
4
|
+
import os
|
|
5
|
+
from dataclasses import dataclass, fields
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class Settings:
|
|
10
|
+
"""Main settings of Jac lang."""
|
|
11
|
+
|
|
12
|
+
fuse_type_info_debug: bool = False
|
|
13
|
+
py_raise: bool = False
|
|
14
|
+
|
|
15
|
+
def __post_init__(self) -> None:
|
|
16
|
+
"""Initialize settings."""
|
|
17
|
+
home_dir = os.path.expanduser("~")
|
|
18
|
+
config_dir = os.path.join(home_dir, ".jaclang")
|
|
19
|
+
self.config_file_path = os.path.join(config_dir, "config.ini")
|
|
20
|
+
os.makedirs(config_dir, exist_ok=True)
|
|
21
|
+
if not os.path.exists(self.config_file_path):
|
|
22
|
+
with open(self.config_file_path, "w") as f:
|
|
23
|
+
f.write("[settings]\n")
|
|
24
|
+
self.load_all()
|
|
25
|
+
|
|
26
|
+
def load_all(self) -> None:
|
|
27
|
+
"""Load settings from all available sources."""
|
|
28
|
+
self.load_config_file()
|
|
29
|
+
self.load_env_vars()
|
|
30
|
+
|
|
31
|
+
def load_config_file(self) -> None:
|
|
32
|
+
"""Load settings from a configuration file."""
|
|
33
|
+
config_parser = configparser.ConfigParser()
|
|
34
|
+
config_parser.read(self.config_file_path)
|
|
35
|
+
if "settings" in config_parser:
|
|
36
|
+
for key in config_parser["settings"]:
|
|
37
|
+
if key in [f.name for f in fields(self)]:
|
|
38
|
+
setattr(
|
|
39
|
+
self, key, self.convert_type(config_parser["settings"][key])
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def load_env_vars(self) -> None:
|
|
43
|
+
"""Override settings from environment variables if available."""
|
|
44
|
+
for key in [f.name for f in fields(self)]:
|
|
45
|
+
env_value = os.getenv("JACLANG_" + key.upper())
|
|
46
|
+
if env_value is not None:
|
|
47
|
+
setattr(self, key, self.convert_type(env_value))
|
|
48
|
+
|
|
49
|
+
# def load_command_line_arguments(self):
|
|
50
|
+
# """Override settings from command-line arguments if provided."""
|
|
51
|
+
# parser = argparse.ArgumentParser()
|
|
52
|
+
# parser.add_argument(
|
|
53
|
+
# "--debug",
|
|
54
|
+
# type=self.str_to_bool,
|
|
55
|
+
# nargs="?",
|
|
56
|
+
# const=True,
|
|
57
|
+
# default=self.config["debug"],
|
|
58
|
+
# )
|
|
59
|
+
# parser.add_argument("--port", type=int, default=self.config["port"])
|
|
60
|
+
# parser.add_argument("--host", default=self.config["host"])
|
|
61
|
+
# args = parser.parse_args()
|
|
62
|
+
|
|
63
|
+
def str_to_bool(self, value: str) -> bool:
|
|
64
|
+
"""Convert string to boolean."""
|
|
65
|
+
return value.lower() in ("yes", "y", "true", "t", "1")
|
|
66
|
+
|
|
67
|
+
def convert_type(self, value: str) -> bool | str | int:
|
|
68
|
+
"""Convert string values from the config to the appropriate type."""
|
|
69
|
+
if value.isdigit():
|
|
70
|
+
return int(value)
|
|
71
|
+
if value.lower() in (
|
|
72
|
+
"true",
|
|
73
|
+
"false",
|
|
74
|
+
"t",
|
|
75
|
+
"f",
|
|
76
|
+
"yes",
|
|
77
|
+
"no",
|
|
78
|
+
"y",
|
|
79
|
+
"n",
|
|
80
|
+
"1",
|
|
81
|
+
"0",
|
|
82
|
+
):
|
|
83
|
+
return self.str_to_bool(value)
|
|
84
|
+
return value
|
|
85
|
+
|
|
86
|
+
def __str__(self) -> str:
|
|
87
|
+
"""Return string representation of the settings."""
|
|
88
|
+
return "\n".join(
|
|
89
|
+
[f"{field.name}: {getattr(self, field.name)}" for field in fields(self)]
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
settings = Settings()
|
|
94
|
+
|
|
95
|
+
__all__ = ["settings"]
|
jaclang/utils/helpers.py
CHANGED
|
@@ -131,7 +131,6 @@ def import_target_to_relative_path(
|
|
|
131
131
|
import_level: int,
|
|
132
132
|
import_target: str,
|
|
133
133
|
base_path: Optional[str] = None,
|
|
134
|
-
file_extension: str = ".jac",
|
|
135
134
|
) -> str:
|
|
136
135
|
"""Convert an import target string into a relative file path."""
|
|
137
136
|
if not base_path:
|
|
@@ -141,7 +140,12 @@ def import_target_to_relative_path(
|
|
|
141
140
|
actual_parts = parts[traversal_levels:]
|
|
142
141
|
for _ in range(traversal_levels):
|
|
143
142
|
base_path = os.path.dirname(base_path)
|
|
144
|
-
relative_path = os.path.join(base_path, *actual_parts)
|
|
143
|
+
relative_path = os.path.join(base_path, *actual_parts)
|
|
144
|
+
relative_path = (
|
|
145
|
+
relative_path + ".jac"
|
|
146
|
+
if os.path.exists(relative_path + ".jac")
|
|
147
|
+
else relative_path
|
|
148
|
+
)
|
|
145
149
|
return relative_path
|
|
146
150
|
|
|
147
151
|
|
jaclang/utils/treeprinter.py
CHANGED
|
@@ -88,16 +88,19 @@ def print_ast_tree(
|
|
|
88
88
|
from jaclang.compiler.absyntree import AstSymbolNode, Token
|
|
89
89
|
|
|
90
90
|
def __node_repr_in_tree(node: AstNode) -> str:
|
|
91
|
+
access = (
|
|
92
|
+
f"Access: {node.access.tag.value}"
|
|
93
|
+
if isinstance(node, ast.AstAccessNode) and node.access is not None
|
|
94
|
+
else ""
|
|
95
|
+
)
|
|
91
96
|
if isinstance(node, Token) and isinstance(node, AstSymbolNode):
|
|
92
|
-
return
|
|
93
|
-
f"{node.__class__.__name__} - {node.value} - Type: {node.sym_info.typ}"
|
|
94
|
-
)
|
|
97
|
+
return f"{node.__class__.__name__} - {node.value} - Type: {node.sym_info.typ}, {access}"
|
|
95
98
|
elif isinstance(node, Token):
|
|
96
|
-
return f"{node.__class__.__name__} - {node.value}"
|
|
99
|
+
return f"{node.__class__.__name__} - {node.value}, {access}"
|
|
97
100
|
elif isinstance(node, AstSymbolNode):
|
|
98
|
-
return f"{node.__class__.__name__} - {node.sym_name} - Type: {node.sym_info.typ}"
|
|
101
|
+
return f"{node.__class__.__name__} - {node.sym_name} - Type: {node.sym_info.typ}, {access}"
|
|
99
102
|
else:
|
|
100
|
-
return f"{node.__class__.__name__}"
|
|
103
|
+
return f"{node.__class__.__name__}, {access}"
|
|
101
104
|
|
|
102
105
|
def __node_repr_in_py_tree(node: ast3.AST) -> str:
|
|
103
106
|
if isinstance(node, ast3.Constant):
|
jaclang/vendor/mypy/checker.py
CHANGED
|
@@ -3637,11 +3637,10 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
|
|
|
3637
3637
|
if (
|
|
3638
3638
|
lv.node.final_unset_in_class
|
|
3639
3639
|
and not lv.node.final_set_in_init
|
|
3640
|
-
and not self.is_stub
|
|
3641
|
-
and # It is OK to skip initializer in stub files.
|
|
3640
|
+
and not self.is_stub # It is OK to skip initializer in stub files.
|
|
3642
3641
|
# Avoid extra error messages, if there is no type in Final[...],
|
|
3643
3642
|
# then we already reported the error about missing r.h.s.
|
|
3644
|
-
isinstance(s, AssignmentStmt)
|
|
3643
|
+
and isinstance(s, AssignmentStmt)
|
|
3645
3644
|
and s.type is not None
|
|
3646
3645
|
):
|
|
3647
3646
|
self.msg.final_without_value(s)
|