jaclang 0.8.7__py3-none-any.whl → 0.8.8__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 +13 -27
- jaclang/cli/cmdreg.py +44 -0
- jaclang/compiler/constant.py +0 -1
- jaclang/compiler/jac.lark +3 -6
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +213 -34
- jaclang/compiler/passes/main/__init__.py +2 -4
- jaclang/compiler/passes/main/def_use_pass.py +0 -4
- jaclang/compiler/passes/main/predynamo_pass.py +221 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +70 -52
- jaclang/compiler/passes/main/pyast_load_pass.py +52 -20
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
- jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
- jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
- jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
- jaclang/compiler/passes/main/tests/test_checker_pass.py +191 -0
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +57 -0
- jaclang/compiler/passes/main/type_checker_pass.py +29 -73
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +204 -44
- jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +171 -11
- jaclang/compiler/passes/transform.py +12 -8
- jaclang/compiler/program.py +14 -6
- jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
- jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
- jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
- jaclang/compiler/tests/fixtures/python_module.py +1 -0
- jaclang/compiler/tests/test_importer.py +39 -0
- jaclang/compiler/tests/test_parser.py +49 -0
- jaclang/compiler/type_system/type_evaluator.py +351 -67
- jaclang/compiler/type_system/type_utils.py +246 -0
- jaclang/compiler/type_system/types.py +58 -2
- jaclang/compiler/unitree.py +79 -94
- jaclang/langserve/engine.jac +138 -159
- jaclang/langserve/server.jac +25 -1
- jaclang/langserve/tests/fixtures/circle.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
- jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
- jaclang/langserve/tests/server_test/circle_template.jac +80 -0
- jaclang/langserve/tests/server_test/glob_template.jac +4 -0
- jaclang/langserve/tests/server_test/test_lang_serve.py +154 -309
- jaclang/langserve/tests/server_test/utils.py +153 -116
- jaclang/langserve/tests/test_server.py +21 -84
- jaclang/langserve/utils.jac +12 -15
- jaclang/runtimelib/machine.py +7 -0
- jaclang/runtimelib/meta_importer.py +27 -1
- jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
- jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
- jaclang/settings.py +18 -14
- jaclang/tests/fixtures/abc_check.jac +3 -3
- jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
- jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
- jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
- jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
- jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
- jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
- jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
- jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
- jaclang/tests/fixtures/py2jac_params.py +8 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/test_cli.py +37 -1
- jaclang/tests/test_language.py +74 -16
- jaclang/utils/helpers.py +47 -2
- jaclang/utils/module_resolver.py +10 -0
- jaclang/utils/test.py +8 -0
- jaclang/utils/treeprinter.py +0 -18
- {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/METADATA +1 -2
- {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/RECORD +85 -60
- {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/WHEEL +1 -1
- jaclang/compiler/passes/main/inheritance_pass.py +0 -131
- jaclang/langserve/dev_engine.jac +0 -645
- jaclang/langserve/dev_server.jac +0 -201
- jaclang/langserve/tests/server_test/code_test.py +0 -0
- {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/entry_points.txt +0 -0
|
@@ -1,18 +1,178 @@
|
|
|
1
|
-
|
|
1
|
+
#this file is part of formatter tests and is not meant to be run
|
|
2
|
+
class SemTokManager {
|
|
2
3
|
"""Initialize semantic token manager."""
|
|
3
4
|
def init(self: SemTokManager, ir: uni.Module) -> None {
|
|
4
|
-
self.sem_tokens: List[int] = self.gen_sem_tokens(ir);
|
|
5
5
|
self.aaaaastatic_sem_tokens:
|
|
6
|
-
List[Tuple[lspt.Position, int, int, uni.AstSymbolNode]] =
|
|
7
|
-
|
|
6
|
+
List[Tuple[lspt.Position, int, int, uni.AstSymbolNode]] = self.gen_sem_tok_node(
|
|
7
|
+
ir
|
|
8
|
+
);
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
def walrus_example() {
|
|
14
|
+
if ((x := 10) > 5) {
|
|
15
|
+
print(x);
|
|
16
|
+
b = a(
|
|
17
|
+
11111111111111111111111111111111111111111111111111111111111111111111111111
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
with entry {
|
|
24
|
+
c = (
|
|
25
|
+
a()
|
|
26
|
+
if 1 and
|
|
27
|
+
isinstance(a, int) and
|
|
28
|
+
isinstance(a, int) and
|
|
29
|
+
isinstance(a, int) and
|
|
30
|
+
isinstance(a, int) and
|
|
31
|
+
isinstance(a, int)
|
|
32
|
+
else (
|
|
33
|
+
999
|
|
34
|
+
if isinstance(a, int) and
|
|
35
|
+
isinstance(a, int) and
|
|
36
|
+
isinstance(a, int) and
|
|
37
|
+
isinstance(4, bool)
|
|
38
|
+
else 7
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
print(
|
|
42
|
+
"""This is a long
|
|
43
|
+
line of code."""
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ModuleManager {
|
|
49
|
+
def clear_alerts_for_file(self: ModuleManager, file_path_fs: str) -> None {
|
|
50
|
+
#list comprehension example
|
|
51
|
+
self.warnings_had = [
|
|
52
|
+
w
|
|
53
|
+
for w in self.program
|
|
54
|
+
if w.loc.mod_path != file_path_fs
|
|
55
|
+
];
|
|
56
|
+
self.program.errors_had = [
|
|
57
|
+
e
|
|
58
|
+
for e in self.program.errors_haddddddddd
|
|
59
|
+
if e.loc.mod_path != file_path_fs
|
|
60
|
+
];
|
|
61
|
+
self.program.errors_had = [
|
|
62
|
+
e
|
|
63
|
+
for e in self.program.errors_haddddddddddddddddddddddddddddddddddddddddd
|
|
64
|
+
if e.loc.mod_path != file_path_fs
|
|
65
|
+
];
|
|
66
|
+
# dict comprehension example
|
|
67
|
+
squares_dict = {x : x ** 2 for x in numbers};
|
|
68
|
+
squares_dict = {
|
|
69
|
+
x : x ** 2 for x in numberssssssssssssssssssssssssssssssssssssssssssssss
|
|
70
|
+
};
|
|
71
|
+
squares_dict = {
|
|
72
|
+
x : x ** 2
|
|
73
|
+
for x in numbersssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
74
|
+
};
|
|
75
|
+
# set comprehension example
|
|
76
|
+
squares_set = {x ** 2 for x in numbers};
|
|
77
|
+
squares_set = {
|
|
78
|
+
x ** 2 for x in numberssssssssssssssssssssssssssssssssssssssssssssssss
|
|
79
|
+
};
|
|
80
|
+
squares_set = {
|
|
81
|
+
x ** 2
|
|
82
|
+
for x in numbersssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
83
|
+
};
|
|
84
|
+
# generator comprehension example
|
|
85
|
+
squares_gen = (x ** 2 for x in numbers);
|
|
86
|
+
squares_gen = (
|
|
87
|
+
x ** 2 for x in numberssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
88
|
+
);
|
|
89
|
+
squares_gen = (
|
|
90
|
+
x ** 2
|
|
91
|
+
for x in numbersssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
## expr as item extra space issue
|
|
98
|
+
with entry {
|
|
99
|
+
with open(f"Apple{apple}.txt") as f {
|
|
100
|
+
# Fix syntax highlighting
|
|
101
|
+
print(
|
|
102
|
+
f.read()
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def func_with_very_long_params(
|
|
109
|
+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: int,
|
|
110
|
+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: int,
|
|
111
|
+
) -> None {
|
|
112
|
+
print(
|
|
113
|
+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
114
|
+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def func_with_long_params(
|
|
120
|
+
aaaaaaaaaaaaaaaaaaaaaa: int, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: int,
|
|
121
|
+
) -> None {
|
|
122
|
+
print(
|
|
123
|
+
aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, 1111111111111
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def func_with_short_params(a: int, b: int) -> None {
|
|
129
|
+
print(a + b + c[5:]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
with entry {
|
|
134
|
+
if (
|
|
135
|
+
node_selected and
|
|
136
|
+
node_selected.find_parent_of_type(uni.Archetype) or
|
|
137
|
+
node_selected.find_parent_of_type(uni.ImplDef)
|
|
138
|
+
) {
|
|
139
|
+
self_symbol = [
|
|
140
|
+
lspt.CompletionItem(label='self', kind=lspt.CompletionItemKind.Variable)
|
|
141
|
+
];
|
|
142
|
+
} else {
|
|
143
|
+
self_symbol = [];
|
|
144
|
+
}
|
|
145
|
+
x = (
|
|
146
|
+
1222222222 and
|
|
147
|
+
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
|
|
148
|
+
);
|
|
149
|
+
a = 4 if True else 4;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
"""Return diagnostics."""
|
|
154
|
+
def gen_diagnostics(
|
|
155
|
+
from_path: str, errors: list[Alert], warnings: list[Alert]
|
|
156
|
+
) -> list[lspt.Diagnostic] {
|
|
157
|
+
if (
|
|
158
|
+
isinstance(node_selected, uni.Name) and
|
|
159
|
+
node_selected.parent and
|
|
160
|
+
isinstance(node_selected.parent, uni.ModulePath)
|
|
161
|
+
) {
|
|
162
|
+
node_selected = node_selected.name_of;
|
|
163
|
+
} elif (
|
|
164
|
+
isinstance(node_selected, uni.Name) and
|
|
165
|
+
node_selected.parent and
|
|
166
|
+
isinstance(node_selected.parent, uni.ModulePath)
|
|
167
|
+
) {
|
|
168
|
+
spec = node_selected.parent.parent.abs_path;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@decorator
|
|
174
|
+
def x() { }
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@decorator()
|
|
178
|
+
class KK {}
|
|
@@ -9,7 +9,7 @@ from typing import Generic, Optional, TYPE_CHECKING, Type, TypeVar
|
|
|
9
9
|
from jaclang.compiler.codeinfo import CodeLocInfo
|
|
10
10
|
from jaclang.compiler.unitree import UniNode
|
|
11
11
|
from jaclang.settings import settings
|
|
12
|
-
from jaclang.utils.helpers import pretty_print_source_location
|
|
12
|
+
from jaclang.utils.helpers import ANSIColors, pretty_print_source_location
|
|
13
13
|
from jaclang.utils.log import logging
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
@@ -39,7 +39,7 @@ class Alert:
|
|
|
39
39
|
"""Return string representation of alert."""
|
|
40
40
|
return self.as_log()
|
|
41
41
|
|
|
42
|
-
def as_log(self) -> str:
|
|
42
|
+
def as_log(self, *, colors: bool = False) -> str:
|
|
43
43
|
"""Return the alert as a single line log as opposed to the pretty print."""
|
|
44
44
|
file_path: str = self.loc.mod_path
|
|
45
45
|
if file_path == "":
|
|
@@ -47,20 +47,24 @@ class Alert:
|
|
|
47
47
|
|
|
48
48
|
line: int = self.loc.first_line
|
|
49
49
|
column: int = self.loc.col_start
|
|
50
|
-
return f"{file_path}:{line}:{column} {self.msg}"
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
# TODO: Set if the alert is error or warning and color accordingly.
|
|
52
|
+
msg = self.msg if not colors else f"{ANSIColors.RED}{self.msg}{ANSIColors.END}"
|
|
53
|
+
return f"{file_path}:{line}:{column} {msg}"
|
|
54
|
+
|
|
55
|
+
def pretty_print(self, *, colors: bool = False) -> str:
|
|
56
|
+
"""Pretty prints the Alert to show the alert with source location."""
|
|
54
57
|
pretty_dump = pretty_print_source_location(
|
|
55
58
|
self.loc.mod_path,
|
|
56
59
|
self.loc.orig_src.code,
|
|
57
60
|
self.loc.first_line,
|
|
58
61
|
self.loc.pos_start,
|
|
59
62
|
self.loc.pos_end,
|
|
63
|
+
colors=colors,
|
|
60
64
|
)
|
|
61
65
|
if pretty_dump != "":
|
|
62
66
|
pretty_dump = "\n" + pretty_dump
|
|
63
|
-
return self.as_log() + pretty_dump
|
|
67
|
+
return self.as_log(colors=colors) + pretty_dump
|
|
64
68
|
|
|
65
69
|
|
|
66
70
|
class Transform(ABC, Generic[T, R]):
|
|
@@ -115,7 +119,7 @@ class Transform(ABC, Generic[T, R]):
|
|
|
115
119
|
)
|
|
116
120
|
self.errors_had.append(alrt)
|
|
117
121
|
self.prog.errors_had.append(alrt)
|
|
118
|
-
self.logger.error(alrt.as_log())
|
|
122
|
+
# self.logger.error(alrt.as_log())
|
|
119
123
|
|
|
120
124
|
def log_warning(self, msg: str, node_override: Optional[UniNode] = None) -> None:
|
|
121
125
|
"""Pass Error."""
|
|
@@ -126,7 +130,7 @@ class Transform(ABC, Generic[T, R]):
|
|
|
126
130
|
)
|
|
127
131
|
self.warnings_had.append(alrt)
|
|
128
132
|
self.prog.warnings_had.append(alrt)
|
|
129
|
-
self.logger.warning(alrt.as_log())
|
|
133
|
+
# self.logger.warning(alrt.as_log())
|
|
130
134
|
|
|
131
135
|
def log_info(self, msg: str) -> None:
|
|
132
136
|
"""Log info."""
|
jaclang/compiler/program.py
CHANGED
|
@@ -15,16 +15,15 @@ from jaclang.compiler.passes.main import (
|
|
|
15
15
|
CFGBuildPass,
|
|
16
16
|
DeclImplMatchPass,
|
|
17
17
|
DefUsePass,
|
|
18
|
-
InheritancePass,
|
|
19
18
|
JacAnnexPass,
|
|
20
19
|
JacImportDepsPass,
|
|
20
|
+
PreDynamoPass,
|
|
21
21
|
PyBytecodeGenPass,
|
|
22
22
|
PyJacAstLinkPass,
|
|
23
23
|
PyastBuildPass,
|
|
24
24
|
PyastGenPass,
|
|
25
25
|
SemDefMatchPass,
|
|
26
26
|
SymTabBuildPass,
|
|
27
|
-
SymTabLinkPass,
|
|
28
27
|
Transform,
|
|
29
28
|
TypeCheckPass,
|
|
30
29
|
)
|
|
@@ -33,7 +32,9 @@ from jaclang.compiler.passes.tool import (
|
|
|
33
32
|
FuseCommentsPass,
|
|
34
33
|
JacFormatPass,
|
|
35
34
|
)
|
|
35
|
+
from jaclang.compiler.type_system.type_evaluator import TypeEvaluator
|
|
36
36
|
from jaclang.runtimelib.utils import read_file_with_encoding
|
|
37
|
+
from jaclang.settings import settings
|
|
37
38
|
from jaclang.utils.log import logging
|
|
38
39
|
|
|
39
40
|
|
|
@@ -45,7 +46,6 @@ ir_gen_sched = [
|
|
|
45
46
|
DefUsePass,
|
|
46
47
|
SemDefMatchPass,
|
|
47
48
|
CFGBuildPass,
|
|
48
|
-
InheritancePass,
|
|
49
49
|
]
|
|
50
50
|
type_check_sched: list = [
|
|
51
51
|
TypeCheckPass,
|
|
@@ -67,6 +67,13 @@ class JacProgram:
|
|
|
67
67
|
self.py_raise_map: dict[str, str] = {}
|
|
68
68
|
self.errors_had: list[Alert] = []
|
|
69
69
|
self.warnings_had: list[Alert] = []
|
|
70
|
+
self.type_evaluator: TypeEvaluator | None = None
|
|
71
|
+
|
|
72
|
+
def get_type_evaluator(self) -> TypeEvaluator:
|
|
73
|
+
"""Return the type evaluator."""
|
|
74
|
+
if not self.type_evaluator:
|
|
75
|
+
self.type_evaluator = TypeEvaluator(program=self)
|
|
76
|
+
return self.type_evaluator
|
|
70
77
|
|
|
71
78
|
def get_bytecode(self, full_target: str) -> Optional[types.CodeType]:
|
|
72
79
|
"""Get the bytecode for a specific module."""
|
|
@@ -120,7 +127,10 @@ class JacProgram:
|
|
|
120
127
|
self.run_schedule(mod=mod_targ, passes=ir_gen_sched)
|
|
121
128
|
if type_check:
|
|
122
129
|
self.run_schedule(mod=mod_targ, passes=type_check_sched)
|
|
123
|
-
|
|
130
|
+
# If the module has syntax errors, we skip code generation.
|
|
131
|
+
if (not mod_targ.has_syntax_errors) and (not no_cgen):
|
|
132
|
+
if settings.predynamo_pass and PreDynamoPass not in py_code_gen:
|
|
133
|
+
py_code_gen.insert(0, PreDynamoPass)
|
|
124
134
|
self.run_schedule(mod=mod_targ, passes=py_code_gen)
|
|
125
135
|
return mod_targ
|
|
126
136
|
|
|
@@ -137,8 +147,6 @@ class JacProgram:
|
|
|
137
147
|
"""Convert a Jac file to an AST."""
|
|
138
148
|
mod_targ = self.compile(file_path, use_str, type_check=type_check)
|
|
139
149
|
JacImportDepsPass(ir_in=mod_targ, prog=self)
|
|
140
|
-
for mod in self.mod.hub.values():
|
|
141
|
-
SymTabLinkPass(ir_in=mod, prog=self)
|
|
142
150
|
for mod in self.mod.hub.values():
|
|
143
151
|
DefUsePass(mod, prog=self)
|
|
144
152
|
return mod_targ
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
print("Hello from Python module!")
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Tests for Jac Loader."""
|
|
2
2
|
|
|
3
3
|
import io
|
|
4
|
+
import os
|
|
4
5
|
import sys
|
|
5
6
|
|
|
6
7
|
from jaclang import JacMachine as Jac
|
|
@@ -8,6 +9,7 @@ from jaclang.cli import cli
|
|
|
8
9
|
from jaclang.compiler.program import JacProgram
|
|
9
10
|
from jaclang.runtimelib.machine import JacMachineInterface
|
|
10
11
|
from jaclang.utils.test import TestCase
|
|
12
|
+
from jaclang.settings import settings
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class TestLoader(TestCase):
|
|
@@ -128,3 +130,40 @@ class TestLoader(TestCase):
|
|
|
128
130
|
self.assertIn("Helper function called", stdout_value)
|
|
129
131
|
self.assertIn("Tool function executed", stdout_value)
|
|
130
132
|
self.assertIn("pkg_import_lib_py.glob_var_lib", stdout_value)
|
|
133
|
+
|
|
134
|
+
def test_jac_import_py_files(self) -> None:
|
|
135
|
+
"""Test importing Python files using Jac import system."""
|
|
136
|
+
captured_output = io.StringIO()
|
|
137
|
+
sys.stdout = captured_output
|
|
138
|
+
os.environ["JAC_PYFILE_RAISE"] = "True"
|
|
139
|
+
settings.load_env_vars()
|
|
140
|
+
original_cwd = os.getcwd()
|
|
141
|
+
try:
|
|
142
|
+
os.chdir(os.path.dirname(self.fixture_abs_path("jac_import_py_files.py")))
|
|
143
|
+
Jac.set_base_path(self.fixture_abs_path("jac_import_py_files.py"))
|
|
144
|
+
JacMachineInterface.attach_program(
|
|
145
|
+
program:=JacProgram(),
|
|
146
|
+
)
|
|
147
|
+
Jac.jac_import("jac_import_py_files", base_path=self.fixture_abs_path("jac_import_py_files.py"), lng="py")
|
|
148
|
+
cli.run(self.fixture_abs_path("jac_import_py_files.py"))
|
|
149
|
+
sys.stdout = sys.__stdout__
|
|
150
|
+
stdout_value = captured_output.getvalue()
|
|
151
|
+
self.assertIn("This is main test file for jac import of python files", stdout_value)
|
|
152
|
+
self.assertIn("python_module <jaclang.compiler.unitree.Module object", str(program.mod.hub))
|
|
153
|
+
self.assertIn("jac_module <jaclang.compiler.unitree.Module object", str(program.mod.hub))
|
|
154
|
+
os.environ["JAC_PYFILE_RAISE"] = "false"
|
|
155
|
+
settings.load_env_vars()
|
|
156
|
+
os.chdir(os.path.dirname(self.fixture_abs_path("jac_import_py_files.py")))
|
|
157
|
+
Jac.set_base_path(self.fixture_abs_path("jac_import_py_files.py"))
|
|
158
|
+
JacMachineInterface.attach_program(
|
|
159
|
+
program:=JacProgram(),
|
|
160
|
+
)
|
|
161
|
+
Jac.jac_import("jac_import_py_files", base_path=self.fixture_abs_path("jac_import_py_files.py"), lng="py")
|
|
162
|
+
cli.run(self.fixture_abs_path("jac_import_py_files.py"))
|
|
163
|
+
sys.stdout = sys.__stdout__
|
|
164
|
+
stdout_value = captured_output.getvalue()
|
|
165
|
+
self.assertIn("This is main test file for jac import of python files", stdout_value)
|
|
166
|
+
self.assertNotIn("python_module <jaclang.compiler.unitree.Module object", str(program.mod.hub))
|
|
167
|
+
self.assertNotIn("jac_module <jaclang.compiler.unitree.Module object", str(program.mod.hub))
|
|
168
|
+
finally:
|
|
169
|
+
os.chdir(original_cwd)
|
|
@@ -179,5 +179,54 @@ class TestLarkParser(TestCaseMicroSuite):
|
|
|
179
179
|
prog.compile(self.fixture_abs_path("codegentext.jac"))
|
|
180
180
|
self.assertFalse(prog.errors_had)
|
|
181
181
|
|
|
182
|
+
def test_param_syntax(self) -> None:
|
|
183
|
+
"""Parse param syntax jac file."""
|
|
184
|
+
captured_output = io.StringIO()
|
|
185
|
+
sys.stdout = captured_output
|
|
186
|
+
prog = JacProgram()
|
|
187
|
+
prog.compile(self.lang_fixture_abs_path("params/param_syntax_err.jac"))
|
|
188
|
+
sys.stdout = sys.__stdout__
|
|
189
|
+
self.assertEqual(len(prog.errors_had), 8)
|
|
190
|
+
|
|
191
|
+
def test_multiple_syntax_errors(self) -> None:
|
|
192
|
+
"""Parse param syntax jac file."""
|
|
193
|
+
captured_output = io.StringIO()
|
|
194
|
+
sys.stdout = captured_output
|
|
195
|
+
prog = JacProgram()
|
|
196
|
+
prog.compile(self.fixture_abs_path("multiple_syntax_errors.jac"))
|
|
197
|
+
sys.stdout = sys.__stdout__
|
|
198
|
+
self.assertEqual(len(prog.errors_had), 3)
|
|
199
|
+
expected_errors = [
|
|
200
|
+
"""
|
|
201
|
+
Missing RPAREN
|
|
202
|
+
with entry {
|
|
203
|
+
foo = Foo(;
|
|
204
|
+
^
|
|
205
|
+
func(foo bar)
|
|
206
|
+
foo.bar;
|
|
207
|
+
""",
|
|
208
|
+
"""
|
|
209
|
+
Missing COMMA
|
|
210
|
+
with entry {
|
|
211
|
+
foo = Foo(;
|
|
212
|
+
func(foo bar)
|
|
213
|
+
^^^
|
|
214
|
+
foo.bar;
|
|
215
|
+
}
|
|
216
|
+
""",
|
|
217
|
+
"""
|
|
218
|
+
Missing SEMI
|
|
219
|
+
foo = Foo(;
|
|
220
|
+
func(foo bar)
|
|
221
|
+
foo.bar;
|
|
222
|
+
^^^
|
|
223
|
+
}
|
|
224
|
+
"""
|
|
225
|
+
]
|
|
226
|
+
for idx, alrt in enumerate(prog.errors_had):
|
|
227
|
+
pretty = alrt.pretty_print()
|
|
228
|
+
for line in expected_errors[idx].strip().split("\n"):
|
|
229
|
+
line = line.strip()
|
|
230
|
+
self.assertIn(line, pretty)
|
|
182
231
|
|
|
183
232
|
TestLarkParser.self_attach_micro_tests()
|