jaclang 0.8.7__py3-none-any.whl → 0.8.9__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 +77 -29
- jaclang/cli/cmdreg.py +44 -0
- jaclang/compiler/constant.py +6 -2
- jaclang/compiler/jac.lark +37 -47
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +356 -61
- jaclang/compiler/passes/main/__init__.py +2 -4
- jaclang/compiler/passes/main/def_use_pass.py +1 -4
- jaclang/compiler/passes/main/predynamo_pass.py +221 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +221 -135
- jaclang/compiler/passes/main/pyast_load_pass.py +54 -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 +190 -0
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +56 -0
- jaclang/compiler/passes/main/type_checker_pass.py +29 -73
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +302 -58
- 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/import_fmt.jac +7 -1
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +276 -10
- jaclang/compiler/passes/transform.py +12 -8
- jaclang/compiler/program.py +19 -7
- 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.jac +959 -0
- jaclang/compiler/type_system/type_utils.py +246 -0
- jaclang/compiler/type_system/types.py +58 -2
- jaclang/compiler/unitree.py +102 -107
- 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/lib.py +17 -0
- jaclang/runtimelib/archetype.py +25 -25
- jaclang/runtimelib/constructs.py +2 -2
- jaclang/runtimelib/machine.py +63 -46
- 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 +19 -16
- jaclang/tests/fixtures/abc_check.jac +3 -3
- jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
- jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
- jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
- jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
- jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
- jaclang/tests/fixtures/funccall_genexpr.py +5 -0
- 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 +159 -7
- jaclang/tests/test_language.py +213 -38
- jaclang/tests/test_reference.py +3 -1
- jaclang/utils/helpers.py +67 -6
- jaclang/utils/module_resolver.py +10 -0
- jaclang/utils/test.py +8 -0
- jaclang/utils/tests/test_lang_tools.py +4 -15
- jaclang/utils/treeprinter.py +0 -18
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -2
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/RECORD +95 -65
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/WHEEL +1 -1
- jaclang/compiler/passes/main/inheritance_pass.py +0 -131
- jaclang/compiler/type_system/type_evaluator.py +0 -560
- jaclang/langserve/dev_engine.jac +0 -645
- jaclang/langserve/dev_server.jac +0 -201
- /jaclang/{langserve/tests/server_test/code_test.py → tests/fixtures/py2jac_empty.py} +0 -0
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
This is a pass for formatting Jac code.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from collections import deque
|
|
7
|
+
from typing import Deque, Optional, Tuple
|
|
7
8
|
|
|
8
9
|
import jaclang.compiler.passes.tool.doc_ir as doc
|
|
9
10
|
import jaclang.compiler.unitree as uni
|
|
@@ -19,6 +20,83 @@ class JacFormatPass(Transform[uni.Module, uni.Module]):
|
|
|
19
20
|
self.indent_size = 4
|
|
20
21
|
self.MAX_LINE_LENGTH = settings.max_line_length
|
|
21
22
|
|
|
23
|
+
def _probe_fits(
|
|
24
|
+
self,
|
|
25
|
+
node: doc.DocType,
|
|
26
|
+
indent_level: int,
|
|
27
|
+
width_remaining: int,
|
|
28
|
+
*,
|
|
29
|
+
max_steps: int = 2000,
|
|
30
|
+
) -> bool:
|
|
31
|
+
"""
|
|
32
|
+
Check if flat can be used early.
|
|
33
|
+
|
|
34
|
+
returns True if `node` could be printed *flat* on the current line within
|
|
35
|
+
`width_remaining` columns at `indent_level`.
|
|
36
|
+
Stops early on overflow or hard/literal lines.
|
|
37
|
+
"""
|
|
38
|
+
# Worklist holds (node, indent_level). We only ever push FLAT in a probe.
|
|
39
|
+
work: Deque[Tuple[object, int]] = deque()
|
|
40
|
+
work.append((node, indent_level))
|
|
41
|
+
steps = 0
|
|
42
|
+
remaining = width_remaining
|
|
43
|
+
|
|
44
|
+
while work:
|
|
45
|
+
if steps >= max_steps:
|
|
46
|
+
# Safety cutoff: if it's *that* complex, assume it doesn't fit.
|
|
47
|
+
return False
|
|
48
|
+
steps += 1
|
|
49
|
+
|
|
50
|
+
cur, lvl = work.pop()
|
|
51
|
+
|
|
52
|
+
if isinstance(cur, doc.Text):
|
|
53
|
+
remaining -= len(cur.text)
|
|
54
|
+
if remaining <= 0:
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
elif isinstance(cur, doc.Line):
|
|
58
|
+
if cur.hard or cur.literal:
|
|
59
|
+
# Any *real* newline (hard or literal) in FLAT means "doesn't fit"
|
|
60
|
+
return False
|
|
61
|
+
if cur.tight:
|
|
62
|
+
# tight softline disappears in flat mode
|
|
63
|
+
continue
|
|
64
|
+
# regular soft line becomes a single space in flat mode
|
|
65
|
+
remaining -= 1
|
|
66
|
+
if remaining <= 0:
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
# --- Structural nodes (walk children in LIFO) ---
|
|
70
|
+
elif isinstance(cur, doc.Concat):
|
|
71
|
+
# push reversed so we process left-to-right as work is a stack
|
|
72
|
+
for p in reversed(cur.parts):
|
|
73
|
+
work.append((p, lvl))
|
|
74
|
+
|
|
75
|
+
elif isinstance(cur, doc.Group):
|
|
76
|
+
# Probe is always FLAT for groups.
|
|
77
|
+
work.append((cur.contents, lvl))
|
|
78
|
+
|
|
79
|
+
elif isinstance(cur, doc.Indent):
|
|
80
|
+
# In flat mode, indentation has no effect until a newline; keep lvl in case
|
|
81
|
+
# children contain Lines (which would have already returned False).
|
|
82
|
+
work.append((cur.contents, lvl + 1))
|
|
83
|
+
|
|
84
|
+
elif isinstance(cur, doc.Align):
|
|
85
|
+
# In flat mode, alignment doesn’t change width immediately (no newline),
|
|
86
|
+
# but we carry its virtual indent so nested (illegal) Line would be caught.
|
|
87
|
+
align_spaces = cur.n if cur.n is not None else self.indent_size
|
|
88
|
+
extra_levels = align_spaces // self.indent_size
|
|
89
|
+
work.append((cur.contents, lvl + extra_levels))
|
|
90
|
+
|
|
91
|
+
elif isinstance(cur, doc.IfBreak):
|
|
92
|
+
# Flat branch while probing
|
|
93
|
+
work.append((cur.flat_contents, lvl))
|
|
94
|
+
|
|
95
|
+
else:
|
|
96
|
+
raise ValueError(f"Unknown DocType in probe: {type(cur)}")
|
|
97
|
+
|
|
98
|
+
return True
|
|
99
|
+
|
|
22
100
|
def transform(self, ir_in: uni.Module) -> uni.Module:
|
|
23
101
|
"""After pass."""
|
|
24
102
|
ir_in.gen.jac = self.format_doc_ir()
|
|
@@ -52,106 +130,78 @@ class JacFormatPass(Transform[uni.Module, uni.Module]):
|
|
|
52
130
|
return " "
|
|
53
131
|
|
|
54
132
|
elif isinstance(doc_node, doc.Group):
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
133
|
+
fits_flat = self._probe_fits(
|
|
134
|
+
doc_node.contents,
|
|
135
|
+
indent_level=indent_level,
|
|
136
|
+
width_remaining=width_remaining,
|
|
137
|
+
)
|
|
138
|
+
return self.format_doc_ir(
|
|
139
|
+
doc_node.contents,
|
|
140
|
+
indent_level,
|
|
141
|
+
width_remaining,
|
|
142
|
+
is_broken=not fits_flat,
|
|
58
143
|
)
|
|
59
|
-
if (
|
|
60
|
-
"\n" not in flat_contents_str
|
|
61
|
-
and len(flat_contents_str) <= width_remaining
|
|
62
|
-
):
|
|
63
|
-
return flat_contents_str
|
|
64
|
-
else:
|
|
65
|
-
full_width_for_broken_content = self.MAX_LINE_LENGTH - (
|
|
66
|
-
indent_level * self.indent_size
|
|
67
|
-
)
|
|
68
|
-
return self.format_doc_ir(
|
|
69
|
-
doc_node.contents,
|
|
70
|
-
indent_level,
|
|
71
|
-
full_width_for_broken_content,
|
|
72
|
-
is_broken=True,
|
|
73
|
-
)
|
|
74
144
|
|
|
75
145
|
elif isinstance(doc_node, doc.Indent):
|
|
76
146
|
new_indent_level = indent_level + 1
|
|
77
|
-
|
|
78
|
-
width_for_indented_content = self.MAX_LINE_LENGTH - (
|
|
79
|
-
new_indent_level * self.indent_size
|
|
80
|
-
)
|
|
81
147
|
return self.format_doc_ir(
|
|
82
148
|
doc_node.contents,
|
|
83
149
|
new_indent_level,
|
|
84
|
-
|
|
150
|
+
width_remaining, # width_for_indented_content # Budget for lines within indent
|
|
85
151
|
is_broken, # is_broken state propagates
|
|
86
152
|
)
|
|
87
153
|
|
|
88
154
|
elif isinstance(doc_node, doc.Concat):
|
|
89
|
-
result =
|
|
90
|
-
# current_line_budget is the space left on the current line for the current part.
|
|
155
|
+
result: list[str] = []
|
|
91
156
|
current_line_budget = width_remaining
|
|
92
157
|
|
|
93
158
|
for part in doc_node.parts:
|
|
94
159
|
part_str = self.format_doc_ir(
|
|
95
160
|
part, indent_level, current_line_budget, is_broken
|
|
96
161
|
)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
result
|
|
162
|
+
|
|
163
|
+
# Trim trailing spaces when a newline begins next
|
|
164
|
+
if part_str.startswith("\n") and result and result[-1].endswith(" "):
|
|
165
|
+
result[-1] = result[-1].rstrip(" ")
|
|
166
|
+
|
|
167
|
+
result.append(part_str)
|
|
100
168
|
|
|
101
169
|
if "\n" in part_str:
|
|
102
|
-
#
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
indent_level * self.indent_size
|
|
170
|
+
# After a newline, reset budget to full width at this indent.
|
|
171
|
+
last_line = part_str.splitlines()[-1]
|
|
172
|
+
full_budget = max(
|
|
173
|
+
0, self.MAX_LINE_LENGTH - indent_level * self.indent_size
|
|
106
174
|
)
|
|
107
|
-
#
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
content_on_last_line = len(last_line_of_part) - indent_str_len
|
|
115
|
-
else: # It was a line not starting with the full indent (e.g. literal \n)
|
|
116
|
-
content_on_last_line = len(last_line_of_part)
|
|
117
|
-
|
|
118
|
-
current_line_budget -= content_on_last_line
|
|
175
|
+
# Compute how many chars are already on the last line (after indent).
|
|
176
|
+
indent_spaces = " " * (indent_level * self.indent_size)
|
|
177
|
+
if last_line.startswith(indent_spaces):
|
|
178
|
+
used = len(last_line) - len(indent_spaces)
|
|
179
|
+
else:
|
|
180
|
+
used = len(last_line)
|
|
181
|
+
current_line_budget = max(0, full_budget - used)
|
|
119
182
|
else:
|
|
120
|
-
|
|
121
|
-
current_line_budget -= len(part_str)
|
|
183
|
+
current_line_budget = max(0, current_line_budget - len(part_str))
|
|
122
184
|
|
|
123
|
-
|
|
124
|
-
current_line_budget = 0
|
|
125
|
-
return result
|
|
185
|
+
return "".join(result)
|
|
126
186
|
|
|
127
187
|
elif isinstance(doc_node, doc.IfBreak):
|
|
128
|
-
if is_broken
|
|
129
|
-
|
|
130
|
-
doc_node.break_contents, indent_level, width_remaining, is_broken
|
|
131
|
-
)
|
|
132
|
-
else:
|
|
133
|
-
return self.format_doc_ir(
|
|
134
|
-
doc_node.flat_contents, indent_level, width_remaining, is_broken
|
|
135
|
-
)
|
|
188
|
+
branch = doc_node.break_contents if is_broken else doc_node.flat_contents
|
|
189
|
+
return self.format_doc_ir(branch, indent_level, width_remaining, is_broken)
|
|
136
190
|
|
|
137
191
|
elif isinstance(doc_node, doc.Align):
|
|
138
192
|
align_spaces = doc_node.n if doc_node.n is not None else self.indent_size
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
# ) + align_spaces
|
|
142
|
-
child_indent_level_for_align = indent_level + (
|
|
143
|
-
align_spaces // self.indent_size
|
|
144
|
-
)
|
|
193
|
+
extra_levels = align_spaces // self.indent_size
|
|
194
|
+
child_indent_level = indent_level + extra_levels
|
|
145
195
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
child_width_budget = 0
|
|
196
|
+
# On the same line, alignment "consumes" part of the current budget.
|
|
197
|
+
child_width_budget = max(0, width_remaining - align_spaces)
|
|
149
198
|
|
|
150
199
|
return self.format_doc_ir(
|
|
151
200
|
doc_node.contents,
|
|
152
|
-
|
|
153
|
-
child_width_budget,
|
|
201
|
+
child_indent_level,
|
|
202
|
+
child_width_budget,
|
|
154
203
|
is_broken,
|
|
155
204
|
)
|
|
205
|
+
|
|
156
206
|
else:
|
|
157
207
|
raise ValueError(f"Unknown DocType: {type(doc_node)}")
|
|
@@ -474,15 +474,15 @@ impl JacPlugin.visit_node
|
|
|
474
474
|
glob expected_area = 78.53981633974483;
|
|
475
475
|
|
|
476
476
|
test a1 {
|
|
477
|
-
|
|
477
|
+
assert assertAlmostEqual(calculate_area(RAD), expected_area);
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
test a2 {
|
|
481
481
|
c = Circle(RAD);
|
|
482
|
-
|
|
482
|
+
assert assertAlmostEqual(c.area(), expected_area);
|
|
483
483
|
}
|
|
484
484
|
|
|
485
485
|
test a3 {
|
|
486
486
|
c = Circle(RAD);
|
|
487
|
-
|
|
487
|
+
assert assertEqual(c.shape_type, ShapeType.CIRCLE);
|
|
488
488
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
with entry {
|
|
2
|
-
triple_quoted_string =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
""";
|
|
2
|
+
triple_quoted_string = """This is a triple quoted string.
|
|
3
|
+
It can span multiple lines.
|
|
4
|
+
It can contain any number of quotes or apostrophes.
|
|
5
|
+
""";
|
|
7
6
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import from datetime { datetime }
|
|
2
2
|
import from uuid { UUID, uuid4 }
|
|
3
3
|
import from jaclang.compiler.constant { EdgeDir }
|
|
4
|
-
import from jaclang.plugin {
|
|
4
|
+
import from jaclang.plugin {
|
|
5
|
+
Archetype,
|
|
6
|
+
ArchetypeProtocol,
|
|
7
|
+
DSFunc,
|
|
8
|
+
AbsRootHook,
|
|
9
|
+
hookimpl
|
|
10
|
+
}
|
|
5
11
|
import math;
|
|
6
12
|
import numpy as np;
|
|
@@ -1,18 +1,284 @@
|
|
|
1
|
+
#this file is part of formatter tests and is not meant to be run
|
|
1
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
|
|
27
|
+
and isinstance(a, int)
|
|
28
|
+
and isinstance(a, int)
|
|
29
|
+
and isinstance(a, int)
|
|
30
|
+
and isinstance(a, int)
|
|
31
|
+
and isinstance(a, int)
|
|
32
|
+
else (
|
|
33
|
+
999
|
|
34
|
+
if isinstance(a, int)
|
|
35
|
+
and isinstance(a, int)
|
|
36
|
+
and isinstance(a, int)
|
|
37
|
+
and isinstance(4, bool)
|
|
38
|
+
else 7
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
print("""This is a long
|
|
42
|
+
line of code.""");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ModuleManager {
|
|
47
|
+
def clear_alerts_for_file(self: ModuleManager, file_path_fs: str) -> None {
|
|
48
|
+
#list comprehension example
|
|
49
|
+
self.warnings_had = [
|
|
50
|
+
w
|
|
51
|
+
for w in self.program
|
|
52
|
+
if w.loc.mod_path != file_path_fs
|
|
53
|
+
];
|
|
54
|
+
self.program.errors_had = [
|
|
55
|
+
e
|
|
56
|
+
for e in self.program.errors_haddddddddd
|
|
57
|
+
if e.loc.mod_path != file_path_fs
|
|
58
|
+
];
|
|
59
|
+
self.program.errors_had = [
|
|
60
|
+
e
|
|
61
|
+
for e in self.program.errors_haddddddddddddddddddddddddddddddddddddddddd
|
|
62
|
+
if e.loc.mod_path != file_path_fs
|
|
63
|
+
];
|
|
64
|
+
# dict comprehension example
|
|
65
|
+
squares_dict = {x : x ** 2 for x in numbers};
|
|
66
|
+
squares_dict = {
|
|
67
|
+
x : x ** 2 for x in numberssssssssssssssssssssssssssssssssssssssssssssss
|
|
68
|
+
};
|
|
69
|
+
squares_dict = {
|
|
70
|
+
x : x ** 2
|
|
71
|
+
for x in numbersssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
72
|
+
};
|
|
73
|
+
# set comprehension example
|
|
74
|
+
squares_set = {x ** 2 for x in numbers};
|
|
75
|
+
squares_set = {
|
|
76
|
+
x ** 2 for x in numberssssssssssssssssssssssssssssssssssssssssssssssss
|
|
77
|
+
};
|
|
78
|
+
squares_set = {
|
|
79
|
+
x ** 2
|
|
80
|
+
for x in numbersssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
81
|
+
};
|
|
82
|
+
# generator comprehension example
|
|
83
|
+
squares_gen = (x ** 2 for x in numbers);
|
|
84
|
+
squares_gen = (
|
|
85
|
+
x ** 2 for x in numberssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
86
|
+
);
|
|
87
|
+
squares_gen = (
|
|
88
|
+
x ** 2
|
|
89
|
+
for x in numbersssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
## expr as item extra space issue
|
|
96
|
+
with entry {
|
|
97
|
+
with open(f"Apple{apple}.txt") as f {
|
|
98
|
+
# Fix syntax highlighting
|
|
99
|
+
print(
|
|
100
|
+
f.read()
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def func_with_very_long_params(
|
|
107
|
+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: int,
|
|
108
|
+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: int,
|
|
109
|
+
) -> None {
|
|
110
|
+
print(
|
|
111
|
+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
112
|
+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def func_with_long_params(
|
|
118
|
+
aaaaaaaaaaaaaaaaaaaaaa: int, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: int,
|
|
119
|
+
) -> None {
|
|
120
|
+
print(
|
|
121
|
+
aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, 1111111111111
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def func_with_short_params(a: int, b: int) -> None {
|
|
127
|
+
print(a + b + c[5:]);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
with entry {
|
|
132
|
+
if (
|
|
133
|
+
node_selected
|
|
134
|
+
and node_selected.find_parent_of_type(uni.Archetype)
|
|
135
|
+
or node_selected.find_parent_of_type(uni.ImplDef)
|
|
136
|
+
) {
|
|
137
|
+
self_symbol = [
|
|
138
|
+
lspt.CompletionItem(label='self', kind=lspt.CompletionItemKind.Variable)
|
|
139
|
+
];
|
|
140
|
+
} else {
|
|
141
|
+
self_symbol = [];
|
|
142
|
+
}
|
|
143
|
+
x = (
|
|
144
|
+
1222222222
|
|
145
|
+
and 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
|
|
146
|
+
);
|
|
147
|
+
a = 4 if True else 4;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
import from typing { Any, Awaitable, Callable, Coroutine, Optional, ParamSpec, TypeVar }
|
|
152
|
+
|
|
153
|
+
import from jaclang.compiler.constant {
|
|
154
|
+
JacSemTokenModifier as SemTokMod,
|
|
155
|
+
JacSemTokenType as SemTokType,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
"""Return diagnostics."""
|
|
160
|
+
def gen_diagnostics(
|
|
161
|
+
from_path: str, errors: list[Alert], warnings: list[Alert]
|
|
162
|
+
) -> list[lspt.Diagnostic] {
|
|
163
|
+
if (
|
|
164
|
+
isinstance(node_selected, uni.Name)
|
|
165
|
+
and node_selected.parent
|
|
166
|
+
and isinstance(node_selected.parent, uni.ModulePath)
|
|
167
|
+
) {
|
|
168
|
+
node_selected = node_selected.name_of;
|
|
169
|
+
} elif (
|
|
170
|
+
isinstance(node_selected, uni.Name)
|
|
171
|
+
and node_selected.parent
|
|
172
|
+
and isinstance(node_selected.parent, uni.ModulePath)
|
|
173
|
+
) {
|
|
174
|
+
spec = node_selected.parent.parent.abs_path;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@decorator
|
|
180
|
+
def x() {
|
|
181
|
+
assert gg == 7;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@decorator()
|
|
186
|
+
class KK {}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# kkk
|
|
190
|
+
import pygame, random, math;
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
# fff
|
|
194
|
+
with entry {
|
|
195
|
+
# gg
|
|
196
|
+
a = 9;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# kkk
|
|
201
|
+
class X {}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# comment
|
|
205
|
+
@decorator
|
|
206
|
+
def xxx() { }
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# ddd
|
|
210
|
+
glob a = 7;
|
|
211
|
+
def get_node_info(self: JacLangServer, sym_node: uni.AstSymbolNode) -> Optional[str] {
|
|
212
|
+
try {
|
|
213
|
+
if isinstance(sym_node, uni.NameAtom) {
|
|
214
|
+
sym_node = sym_node.name_of;
|
|
215
|
+
}
|
|
216
|
+
access = (sym_node.sym.access.value + ' ') if sym_node.sym else None;
|
|
217
|
+
node_info = f"'('{(access if access else '')}{sym_node.sym_category.value}') '{sym_node.sym_name}";
|
|
218
|
+
if sym_node.name_spec.clean_type {
|
|
219
|
+
node_info += f"': '{sym_node.name_spec.clean_type}";
|
|
220
|
+
}
|
|
221
|
+
if (
|
|
222
|
+
isinstance(sym_node, uni.AstSymbolNode)
|
|
223
|
+
and isinstance(sym_node.name_spec.type, ClassType)
|
|
224
|
+
) {
|
|
225
|
+
node_info += f"': '{sym_node.name_spec.type.shared.class_name}";
|
|
226
|
+
}
|
|
227
|
+
if (isinstance(sym_node, uni.AstDocNode) and sym_node.doc) {
|
|
228
|
+
node_info += f"'\n'{sym_node.doc.value}";
|
|
229
|
+
}
|
|
230
|
+
if (isinstance(sym_node, uni.Ability) and sym_node.signature) {
|
|
231
|
+
node_info += f"'\n'{sym_node.signature.unparse()}";
|
|
232
|
+
}
|
|
233
|
+
} except AttributeError as e {
|
|
234
|
+
self.log_warning(f"'Attribute error when accessing node attributes: '{e}");
|
|
235
|
+
}
|
|
236
|
+
return node_info.strip();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class foo {
|
|
241
|
+
"""Get information about a node."""
|
|
242
|
+
def get_node_info(
|
|
243
|
+
self: JacLangServer, sym_node: uni.AstSymbolNode
|
|
244
|
+
) -> Optional[str] {
|
|
245
|
+
if isinstance(sym_node, uni.AstVarNode) {
|
|
246
|
+
var_name = sym_node.name;
|
|
247
|
+
var_type = sym_node.var_type if sym_node.var_type else 'unknown';
|
|
248
|
+
return f" 'Variable: ' {var_name} ', Type: ' {var_type} ";
|
|
249
|
+
} elif isinstance(sym_node, uni.AstFuncNode) {
|
|
250
|
+
func_name = sym_node.name;
|
|
251
|
+
params = ', '.join(
|
|
252
|
+
[f" {p.name} ': ' {p.param_type} " for p in sym_node.params]
|
|
253
|
+
);
|
|
254
|
+
return f" 'Function: ' {func_name} '(' {params} ')' ";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def x3() {
|
|
261
|
+
if dest_type.is_class_instance() and src_type.is_class_instance() {
|
|
262
|
+
print("x");
|
|
263
|
+
}
|
|
264
|
+
if (
|
|
265
|
+
dest_type.is_class_instance()
|
|
266
|
+
and src_type.is_class_instance()
|
|
267
|
+
and src_type.is_class_instance()
|
|
268
|
+
) {
|
|
269
|
+
print("x");
|
|
270
|
+
}
|
|
271
|
+
if (dest_type.is_class_instance() and src_type.is_class_instance()) {
|
|
272
|
+
print("x");
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class HH {
|
|
278
|
+
def test() -> Optional[str] {
|
|
279
|
+
a = """!
|
|
280
|
+
hello
|
|
281
|
+
hru
|
|
282
|
+
""";
|
|
283
|
+
}
|
|
284
|
+
}
|
|
@@ -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."""
|