jaclang 0.7.23__py3-none-any.whl → 0.7.25__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 +46 -29
- jaclang/compiler/__init__.py +2 -2
- jaclang/compiler/absyntree.py +87 -48
- jaclang/compiler/codeloc.py +7 -2
- jaclang/compiler/compile.py +10 -3
- jaclang/compiler/parser.py +26 -23
- jaclang/compiler/passes/ir_pass.py +2 -2
- jaclang/compiler/passes/main/def_impl_match_pass.py +46 -0
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +146 -123
- jaclang/compiler/passes/main/import_pass.py +6 -2
- jaclang/compiler/passes/main/pyast_load_pass.py +36 -35
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -7
- jaclang/compiler/passes/main/registry_pass.py +3 -12
- jaclang/compiler/passes/main/tests/fixtures/defn_decl_mismatch.jac +19 -0
- jaclang/compiler/passes/main/tests/fixtures/fstrings.jac +2 -0
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +59 -0
- jaclang/compiler/passes/main/tests/test_registry_pass.py +2 -10
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/transform.py +27 -3
- jaclang/compiler/passes/utils/mypy_ast_build.py +246 -26
- jaclang/compiler/symtable.py +6 -0
- jaclang/compiler/tests/test_importer.py +2 -2
- jaclang/langserve/engine.py +14 -12
- jaclang/langserve/server.py +7 -2
- jaclang/langserve/tests/test_server.py +1 -1
- jaclang/langserve/utils.py +17 -3
- jaclang/plugin/default.py +32 -32
- jaclang/plugin/feature.py +2 -2
- jaclang/plugin/plugin.md +471 -0
- jaclang/plugin/spec.py +2 -1
- jaclang/runtimelib/context.py +2 -0
- jaclang/runtimelib/importer.py +7 -2
- jaclang/runtimelib/machine.py +21 -6
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/builtin_dotgen.jac +6 -6
- jaclang/tests/fixtures/enum_inside_archtype.jac +16 -11
- jaclang/tests/fixtures/expr_type.jac +54 -0
- jaclang/tests/fixtures/glob_multivar_statement.jac +15 -0
- jaclang/tests/fixtures/registry.jac +20 -8
- jaclang/tests/foo/__init__.jac +0 -0
- jaclang/tests/main.jac +2 -0
- jaclang/tests/test_cli.py +68 -4
- jaclang/tests/test_language.py +60 -27
- jaclang/utils/helpers.py +92 -14
- jaclang/utils/lang_tools.py +6 -2
- jaclang/utils/treeprinter.py +4 -2
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/METADATA +2 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/RECORD +50 -44
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/WHEEL +1 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/entry_points.txt +0 -0
|
@@ -16,6 +16,7 @@ import mypy.build as myb
|
|
|
16
16
|
import mypy.checkexpr as mycke
|
|
17
17
|
import mypy.errors as mye
|
|
18
18
|
import mypy.fastparse as myfp
|
|
19
|
+
import mypy.nodes as mypy_nodes
|
|
19
20
|
from mypy.build import BuildSource
|
|
20
21
|
from mypy.build import BuildSourceSet
|
|
21
22
|
from mypy.build import FileSystemCache
|
|
@@ -36,6 +37,55 @@ if TYPE_CHECKING:
|
|
|
36
37
|
from mypy.report import Reports # Avoid unconditional slow import
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
# All the expression nodes of mypy.
|
|
41
|
+
EXPRESSION_NODES = (
|
|
42
|
+
mypy_nodes.AssertTypeExpr,
|
|
43
|
+
mypy_nodes.AssignmentExpr,
|
|
44
|
+
mypy_nodes.AwaitExpr,
|
|
45
|
+
mypy_nodes.BytesExpr,
|
|
46
|
+
mypy_nodes.CallExpr,
|
|
47
|
+
mypy_nodes.CastExpr,
|
|
48
|
+
mypy_nodes.ComparisonExpr,
|
|
49
|
+
mypy_nodes.ComplexExpr,
|
|
50
|
+
mypy_nodes.ConditionalExpr,
|
|
51
|
+
mypy_nodes.DictionaryComprehension,
|
|
52
|
+
mypy_nodes.DictExpr,
|
|
53
|
+
mypy_nodes.EllipsisExpr,
|
|
54
|
+
mypy_nodes.EnumCallExpr,
|
|
55
|
+
mypy_nodes.Expression,
|
|
56
|
+
mypy_nodes.FloatExpr,
|
|
57
|
+
mypy_nodes.GeneratorExpr,
|
|
58
|
+
mypy_nodes.IndexExpr,
|
|
59
|
+
mypy_nodes.IntExpr,
|
|
60
|
+
mypy_nodes.LambdaExpr,
|
|
61
|
+
mypy_nodes.ListComprehension,
|
|
62
|
+
mypy_nodes.ListExpr,
|
|
63
|
+
mypy_nodes.MemberExpr,
|
|
64
|
+
mypy_nodes.NamedTupleExpr,
|
|
65
|
+
mypy_nodes.NameExpr,
|
|
66
|
+
mypy_nodes.NewTypeExpr,
|
|
67
|
+
mypy_nodes.OpExpr,
|
|
68
|
+
mypy_nodes.ParamSpecExpr,
|
|
69
|
+
mypy_nodes.PromoteExpr,
|
|
70
|
+
mypy_nodes.RefExpr,
|
|
71
|
+
mypy_nodes.RevealExpr,
|
|
72
|
+
mypy_nodes.SetComprehension,
|
|
73
|
+
mypy_nodes.SetExpr,
|
|
74
|
+
mypy_nodes.SliceExpr,
|
|
75
|
+
mypy_nodes.StarExpr,
|
|
76
|
+
mypy_nodes.StrExpr,
|
|
77
|
+
mypy_nodes.SuperExpr,
|
|
78
|
+
mypy_nodes.TupleExpr,
|
|
79
|
+
mypy_nodes.TypeAliasExpr,
|
|
80
|
+
mypy_nodes.TypedDictExpr,
|
|
81
|
+
mypy_nodes.TypeVarExpr,
|
|
82
|
+
mypy_nodes.TypeVarTupleExpr,
|
|
83
|
+
mypy_nodes.UnaryExpr,
|
|
84
|
+
mypy_nodes.YieldExpr,
|
|
85
|
+
mypy_nodes.YieldFromExpr,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
39
89
|
mypy_to_jac_node_map: dict[
|
|
40
90
|
tuple[int, int | None, int | None, int | None], list[AstNode]
|
|
41
91
|
] = {}
|
|
@@ -131,61 +181,231 @@ class ExpressionChecker(mycke.ExpressionChecker):
|
|
|
131
181
|
"""Override to mypy expression checker for direct AST pass through."""
|
|
132
182
|
super().__init__(tc, msg, plugin, per_line_checking_time_ns)
|
|
133
183
|
|
|
184
|
+
def visit_assert_type_expr(self, e: mycke.AssertTypeExpr) -> mycke.Type:
|
|
185
|
+
"""Type check AssertTypeExpr expression."""
|
|
186
|
+
out = super().visit_assert_type_expr(e)
|
|
187
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
188
|
+
return out
|
|
189
|
+
|
|
190
|
+
def visit_assignment_expr(self, e: mycke.AssignmentExpr) -> mycke.Type:
|
|
191
|
+
"""Type check AssignmentExpr expression."""
|
|
192
|
+
out = super().visit_assignment_expr(e)
|
|
193
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
194
|
+
return out
|
|
195
|
+
|
|
196
|
+
def visit_await_expr(
|
|
197
|
+
self, e: mycke.AwaitExpr, allow_none_return: bool = False
|
|
198
|
+
) -> mycke.Type:
|
|
199
|
+
"""Type check AwaitExpr expression."""
|
|
200
|
+
out = super().visit_await_expr(e, allow_none_return)
|
|
201
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
202
|
+
return out
|
|
203
|
+
|
|
204
|
+
def visit_bytes_expr(self, e: mycke.BytesExpr) -> mycke.Type:
|
|
205
|
+
"""Type check BytesExpr expression."""
|
|
206
|
+
out = super().visit_bytes_expr(e)
|
|
207
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
208
|
+
return out
|
|
209
|
+
|
|
210
|
+
def visit_call_expr(
|
|
211
|
+
self, e: mycke.CallExpr, allow_none_return: bool = False
|
|
212
|
+
) -> mycke.Type:
|
|
213
|
+
"""Type check CallExpr expression."""
|
|
214
|
+
out = super().visit_call_expr(e, allow_none_return)
|
|
215
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
216
|
+
return out
|
|
217
|
+
|
|
218
|
+
def visit_cast_expr(self, e: mycke.CastExpr) -> mycke.Type:
|
|
219
|
+
"""Type check CastExpr expression."""
|
|
220
|
+
out = super().visit_cast_expr(e)
|
|
221
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
222
|
+
return out
|
|
223
|
+
|
|
224
|
+
def visit_comparison_expr(self, e: mycke.ComparisonExpr) -> mycke.Type:
|
|
225
|
+
"""Type check ComparisonExpr expression."""
|
|
226
|
+
out = super().visit_comparison_expr(e)
|
|
227
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
228
|
+
return out
|
|
229
|
+
|
|
230
|
+
def visit_complex_expr(self, e: mycke.ComplexExpr) -> mycke.Type:
|
|
231
|
+
"""Type check ComplexExpr expression."""
|
|
232
|
+
out = super().visit_complex_expr(e)
|
|
233
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
234
|
+
return out
|
|
235
|
+
|
|
236
|
+
def visit_conditional_expr(
|
|
237
|
+
self, e: mycke.ConditionalExpr, allow_none_return: bool = False
|
|
238
|
+
) -> mycke.Type:
|
|
239
|
+
"""Type check ConditionalExpr expression."""
|
|
240
|
+
out = super().visit_conditional_expr(e, allow_none_return)
|
|
241
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
242
|
+
return out
|
|
243
|
+
|
|
244
|
+
def visit_dictionary_comprehension(
|
|
245
|
+
self, e: mycke.DictionaryComprehension
|
|
246
|
+
) -> mycke.Type:
|
|
247
|
+
"""Type check DictionaryComprehension expression."""
|
|
248
|
+
out = super().visit_dictionary_comprehension(e)
|
|
249
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
250
|
+
return out
|
|
251
|
+
|
|
252
|
+
def visit_dict_expr(self, e: mycke.DictExpr) -> mycke.Type:
|
|
253
|
+
"""Type check DictExpr expression."""
|
|
254
|
+
out = super().visit_dict_expr(e)
|
|
255
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
256
|
+
return out
|
|
257
|
+
|
|
258
|
+
def visit_enum_call_expr(self, e: mycke.EnumCallExpr) -> mycke.Type:
|
|
259
|
+
"""Type check EnumCallExpr expression."""
|
|
260
|
+
out = super().visit_enum_call_expr(e)
|
|
261
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
262
|
+
return out
|
|
263
|
+
|
|
264
|
+
def visit_float_expr(self, e: mycke.FloatExpr) -> mycke.Type:
|
|
265
|
+
"""Type check FloatExpr expression."""
|
|
266
|
+
out = super().visit_float_expr(e)
|
|
267
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
268
|
+
return out
|
|
269
|
+
|
|
270
|
+
def visit_generator_expr(self, e: mycke.GeneratorExpr) -> mycke.Type:
|
|
271
|
+
"""Type check GeneratorExpr expression."""
|
|
272
|
+
out = super().visit_generator_expr(e)
|
|
273
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
274
|
+
return out
|
|
275
|
+
|
|
276
|
+
def visit_index_expr(self, e: mycke.IndexExpr) -> mycke.Type:
|
|
277
|
+
"""Type check IndexExpr expression."""
|
|
278
|
+
out = super().visit_index_expr(e)
|
|
279
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
280
|
+
return out
|
|
281
|
+
|
|
282
|
+
def visit_int_expr(self, e: mycke.IntExpr) -> mycke.Type:
|
|
283
|
+
"""Type check IntExpr expression."""
|
|
284
|
+
out = super().visit_int_expr(e)
|
|
285
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
286
|
+
return out
|
|
287
|
+
|
|
288
|
+
def visit_lambda_expr(self, e: mycke.LambdaExpr) -> mycke.Type:
|
|
289
|
+
"""Type check LambdaExpr expression."""
|
|
290
|
+
out = super().visit_lambda_expr(e)
|
|
291
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
292
|
+
return out
|
|
293
|
+
|
|
294
|
+
def visit_list_comprehension(self, e: mycke.ListComprehension) -> mycke.Type:
|
|
295
|
+
"""Type check ListComprehension expression."""
|
|
296
|
+
out = super().visit_list_comprehension(e)
|
|
297
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
298
|
+
return out
|
|
299
|
+
|
|
134
300
|
def visit_list_expr(self, e: mycke.ListExpr) -> mycke.Type:
|
|
135
|
-
"""Type check
|
|
301
|
+
"""Type check ListExpr expression."""
|
|
136
302
|
out = super().visit_list_expr(e)
|
|
137
303
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
138
304
|
return out
|
|
139
305
|
|
|
306
|
+
def visit_member_expr(
|
|
307
|
+
self, e: mycke.MemberExpr, is_lvalue: bool = False
|
|
308
|
+
) -> mycke.Type:
|
|
309
|
+
"""Type check MemberExpr expression."""
|
|
310
|
+
out = super().visit_member_expr(e, is_lvalue)
|
|
311
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
312
|
+
return out
|
|
313
|
+
|
|
314
|
+
def visit_name_expr(self, e: mycke.NameExpr) -> mycke.Type:
|
|
315
|
+
"""Type check NameExpr expression."""
|
|
316
|
+
out = super().visit_name_expr(e)
|
|
317
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
318
|
+
return out
|
|
319
|
+
|
|
320
|
+
def visit_op_expr(self, e: mycke.OpExpr) -> mycke.Type:
|
|
321
|
+
"""Type check OpExpr expression."""
|
|
322
|
+
out = super().visit_op_expr(e)
|
|
323
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
324
|
+
return out
|
|
325
|
+
|
|
326
|
+
def visit_reveal_expr(self, e: mycke.RevealExpr) -> mycke.Type:
|
|
327
|
+
"""Type check RevealExpr expression."""
|
|
328
|
+
out = super().visit_reveal_expr(e)
|
|
329
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
330
|
+
return out
|
|
331
|
+
|
|
332
|
+
def visit_set_comprehension(self, e: mycke.SetComprehension) -> mycke.Type:
|
|
333
|
+
"""Type check SetComprehension expression."""
|
|
334
|
+
out = super().visit_set_comprehension(e)
|
|
335
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
336
|
+
return out
|
|
337
|
+
|
|
140
338
|
def visit_set_expr(self, e: mycke.SetExpr) -> mycke.Type:
|
|
141
|
-
"""Type check
|
|
339
|
+
"""Type check SetExpr expression."""
|
|
142
340
|
out = super().visit_set_expr(e)
|
|
143
341
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
144
342
|
return out
|
|
145
343
|
|
|
146
|
-
def
|
|
147
|
-
"""Type check
|
|
344
|
+
def visit_slice_expr(self, e: mycke.SliceExpr) -> mycke.Type:
|
|
345
|
+
"""Type check SliceExpr expression."""
|
|
346
|
+
out = super().visit_slice_expr(e)
|
|
347
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
348
|
+
return out
|
|
349
|
+
|
|
350
|
+
def visit_star_expr(self, e: mycke.StarExpr) -> mycke.Type:
|
|
351
|
+
"""Type check StarExpr expression."""
|
|
352
|
+
out = super().visit_star_expr(e)
|
|
353
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
354
|
+
return out
|
|
355
|
+
|
|
356
|
+
def visit_str_expr(self, e: mycke.StrExpr) -> mycke.Type:
|
|
357
|
+
"""Type check StrExpr expression."""
|
|
358
|
+
out = super().visit_str_expr(e)
|
|
359
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
360
|
+
return out
|
|
361
|
+
|
|
362
|
+
def visit_super_expr(self, e: mycke.SuperExpr) -> mycke.Type:
|
|
363
|
+
"""Type check SuperExpr expression."""
|
|
364
|
+
out = super().visit_super_expr(e)
|
|
365
|
+
FuseTypeInfoPass.node_type_hash[e] = out
|
|
366
|
+
return out
|
|
367
|
+
|
|
368
|
+
def visit_tuple_expr(self, e: mycke.TupleExpr) -> mycke.Type:
|
|
369
|
+
"""Type check TupleExpr expression."""
|
|
148
370
|
out = super().visit_tuple_expr(e)
|
|
149
371
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
150
372
|
return out
|
|
151
373
|
|
|
152
|
-
def
|
|
153
|
-
"""Type check
|
|
154
|
-
out = super().
|
|
374
|
+
def visit_type_alias_expr(self, e: mycke.TypeAliasExpr) -> mycke.Type:
|
|
375
|
+
"""Type check TypeAliasExpr expression."""
|
|
376
|
+
out = super().visit_type_alias_expr(e)
|
|
155
377
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
156
378
|
return out
|
|
157
379
|
|
|
158
|
-
def
|
|
159
|
-
"""Type check
|
|
160
|
-
out = super().
|
|
380
|
+
def visit_type_var_expr(self, e: mycke.TypeVarExpr) -> mycke.Type:
|
|
381
|
+
"""Type check TypeVarExpr expression."""
|
|
382
|
+
out = super().visit_type_var_expr(e)
|
|
161
383
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
162
384
|
return out
|
|
163
385
|
|
|
164
|
-
def
|
|
165
|
-
"""Type check
|
|
166
|
-
out = super().
|
|
386
|
+
def visit_type_var_tuple_expr(self, e: mycke.TypeVarTupleExpr) -> mycke.Type:
|
|
387
|
+
"""Type check TypeVarTupleExpr expression."""
|
|
388
|
+
out = super().visit_type_var_tuple_expr(e)
|
|
167
389
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
168
390
|
return out
|
|
169
391
|
|
|
170
|
-
def
|
|
171
|
-
"""Type check
|
|
172
|
-
out = super().
|
|
392
|
+
def visit_unary_expr(self, e: mycke.UnaryExpr) -> mycke.Type:
|
|
393
|
+
"""Type check UnaryExpr expression."""
|
|
394
|
+
out = super().visit_unary_expr(e)
|
|
173
395
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
174
396
|
return out
|
|
175
397
|
|
|
176
|
-
def
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
"""Type check a dict comprehension."""
|
|
180
|
-
out = super().visit_dictionary_comprehension(e)
|
|
398
|
+
def visit_yield_expr(self, e: mycke.YieldExpr) -> mycke.Type:
|
|
399
|
+
"""Type check YieldExpr expression."""
|
|
400
|
+
out = super().visit_yield_expr(e)
|
|
181
401
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
182
402
|
return out
|
|
183
403
|
|
|
184
|
-
def
|
|
185
|
-
self, e:
|
|
186
|
-
) ->
|
|
187
|
-
"""Type check
|
|
188
|
-
out = super().
|
|
404
|
+
def visit_yield_from_expr(
|
|
405
|
+
self, e: mycke.YieldFromExpr, allow_none_return: bool = False
|
|
406
|
+
) -> mycke.Type:
|
|
407
|
+
"""Type check YieldFromExpr expression."""
|
|
408
|
+
out = super().visit_yield_from_expr(e, allow_none_return)
|
|
189
409
|
FuseTypeInfoPass.node_type_hash[e] = out
|
|
190
410
|
return out
|
|
191
411
|
|
jaclang/compiler/symtable.py
CHANGED
|
@@ -88,6 +88,12 @@ class SymbolTable:
|
|
|
88
88
|
self.tab: dict[str, Symbol] = {}
|
|
89
89
|
self.inherit: list[SymbolTable] = []
|
|
90
90
|
|
|
91
|
+
def get_type(self) -> SymbolType:
|
|
92
|
+
"""Get type."""
|
|
93
|
+
if isinstance(self.owner, ast.AstSymbolNode):
|
|
94
|
+
return self.owner.sym_category
|
|
95
|
+
return SymbolType.VAR
|
|
96
|
+
|
|
91
97
|
def get_parent(self) -> Optional[SymbolTable]:
|
|
92
98
|
"""Get parent."""
|
|
93
99
|
return self.parent
|
|
@@ -15,7 +15,7 @@ class TestLoader(TestCase):
|
|
|
15
15
|
def test_import_basic_python(self) -> None:
|
|
16
16
|
"""Test basic self loading."""
|
|
17
17
|
JacMachine(self.fixture_abs_path(__file__)).attach_program(
|
|
18
|
-
JacProgram(mod_bundle=None, bytecode=None)
|
|
18
|
+
JacProgram(mod_bundle=None, bytecode=None, sem_ir=None)
|
|
19
19
|
)
|
|
20
20
|
(h,) = jac_import("fixtures.hello_world", base_path=__file__)
|
|
21
21
|
self.assertEqual(h.hello(), "Hello World!") # type: ignore
|
|
@@ -24,7 +24,7 @@ class TestLoader(TestCase):
|
|
|
24
24
|
def test_modules_correct(self) -> None:
|
|
25
25
|
"""Test basic self loading."""
|
|
26
26
|
JacMachine(self.fixture_abs_path(__file__)).attach_program(
|
|
27
|
-
JacProgram(mod_bundle=None, bytecode=None)
|
|
27
|
+
JacProgram(mod_bundle=None, bytecode=None, sem_ir=None)
|
|
28
28
|
)
|
|
29
29
|
jac_import("fixtures.hello_world", base_path=__file__)
|
|
30
30
|
self.assertIn(
|
jaclang/langserve/engine.py
CHANGED
|
@@ -18,6 +18,7 @@ from jaclang.langserve.sem_manager import SemTokManager
|
|
|
18
18
|
from jaclang.langserve.utils import (
|
|
19
19
|
add_unique_text_edit,
|
|
20
20
|
collect_all_symbols_in_scope,
|
|
21
|
+
collect_child_tabs,
|
|
21
22
|
create_range,
|
|
22
23
|
find_deepest_symbol_node_at_pos,
|
|
23
24
|
find_index,
|
|
@@ -44,6 +45,7 @@ class ModuleInfo:
|
|
|
44
45
|
self.ir = ir
|
|
45
46
|
self.impl_parent: Optional[ModuleInfo] = impl_parent
|
|
46
47
|
self.sem_manager = SemTokManager(ir=ir)
|
|
48
|
+
self.is_modified: bool = False
|
|
47
49
|
|
|
48
50
|
@property
|
|
49
51
|
def uri(self) -> str:
|
|
@@ -171,22 +173,20 @@ class JacLangServer(LanguageServer):
|
|
|
171
173
|
self, file_path: str, position: lspt.Position, completion_trigger: Optional[str]
|
|
172
174
|
) -> lspt.CompletionList:
|
|
173
175
|
"""Return completion for a file."""
|
|
174
|
-
completion_items = []
|
|
175
176
|
document = self.workspace.get_text_document(file_path)
|
|
177
|
+
mod_ir = self.modules[file_path].ir
|
|
176
178
|
current_line = document.lines[position.line]
|
|
177
179
|
current_pos = position.character
|
|
178
180
|
current_symbol_path = parse_symbol_path(current_line, current_pos)
|
|
181
|
+
builtin_tab = mod_ir.sym_tab.kid[-1]
|
|
182
|
+
completion_items = []
|
|
179
183
|
|
|
180
184
|
node_selected = find_deepest_symbol_node_at_pos(
|
|
181
|
-
|
|
185
|
+
mod_ir,
|
|
182
186
|
position.line,
|
|
183
187
|
position.character - 2,
|
|
184
188
|
)
|
|
185
|
-
mod_tab =
|
|
186
|
-
self.modules[file_path].ir.sym_tab
|
|
187
|
-
if not node_selected
|
|
188
|
-
else node_selected.sym_tab
|
|
189
|
-
)
|
|
189
|
+
mod_tab = mod_ir.sym_tab if not node_selected else node_selected.sym_tab
|
|
190
190
|
current_symbol_table = mod_tab
|
|
191
191
|
|
|
192
192
|
if completion_trigger == ".":
|
|
@@ -238,7 +238,9 @@ class JacLangServer(LanguageServer):
|
|
|
238
238
|
)
|
|
239
239
|
else:
|
|
240
240
|
break
|
|
241
|
-
completion_items
|
|
241
|
+
completion_items += collect_all_symbols_in_scope(
|
|
242
|
+
temp_tab, up_tree=False
|
|
243
|
+
)
|
|
242
244
|
if (
|
|
243
245
|
isinstance(temp_tab.owner, ast.Architype)
|
|
244
246
|
and temp_tab.owner.base_classes
|
|
@@ -254,8 +256,6 @@ class JacLangServer(LanguageServer):
|
|
|
254
256
|
up_tree=False,
|
|
255
257
|
)
|
|
256
258
|
|
|
257
|
-
else:
|
|
258
|
-
completion_items = []
|
|
259
259
|
else:
|
|
260
260
|
if node_selected and (
|
|
261
261
|
node_selected.find_parent_of_type(ast.Architype)
|
|
@@ -269,8 +269,10 @@ class JacLangServer(LanguageServer):
|
|
|
269
269
|
else:
|
|
270
270
|
self_symbol = []
|
|
271
271
|
|
|
272
|
-
completion_items
|
|
273
|
-
collect_all_symbols_in_scope(current_symbol_table)
|
|
272
|
+
completion_items += (
|
|
273
|
+
collect_all_symbols_in_scope(current_symbol_table)
|
|
274
|
+
+ self_symbol
|
|
275
|
+
+ collect_child_tabs(builtin_tab)
|
|
274
276
|
)
|
|
275
277
|
return lspt.CompletionList(is_incomplete=False, items=completion_items)
|
|
276
278
|
|
jaclang/langserve/server.py
CHANGED
|
@@ -26,8 +26,11 @@ async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) ->
|
|
|
26
26
|
@server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
|
|
27
27
|
async def did_save(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
|
|
28
28
|
"""Check syntax on change."""
|
|
29
|
-
|
|
30
|
-
ls.
|
|
29
|
+
file_path = params.text_document.uri
|
|
30
|
+
if ls.modules[file_path].is_modified:
|
|
31
|
+
await ls.launch_deep_check(file_path)
|
|
32
|
+
ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH)
|
|
33
|
+
ls.modules[file_path].is_modified = False
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
@server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
|
|
@@ -35,6 +38,8 @@ async def did_change(
|
|
|
35
38
|
ls: JacLangServer, params: lspt.DidChangeTextDocumentParams
|
|
36
39
|
) -> None:
|
|
37
40
|
"""Check syntax on change."""
|
|
41
|
+
module = ls.modules[params.text_document.uri]
|
|
42
|
+
module.is_modified = True
|
|
38
43
|
await ls.launch_quick_check(file_path := params.text_document.uri)
|
|
39
44
|
if file_path in ls.modules:
|
|
40
45
|
document = ls.workspace.get_text_document(file_path)
|
jaclang/langserve/utils.py
CHANGED
|
@@ -133,9 +133,12 @@ def find_index(
|
|
|
133
133
|
) -> Optional[int]:
|
|
134
134
|
"""Find index."""
|
|
135
135
|
index = None
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
|
|
137
|
+
# A list contains all the token start positions.
|
|
138
|
+
token_start_list = [
|
|
139
|
+
get_token_start(i, sem_tokens) for i in range(0, len(sem_tokens), 5)
|
|
140
|
+
]
|
|
141
|
+
for i, j in enumerate(token_start_list):
|
|
139
142
|
if j[0] == line and j[1] <= char <= j[2]:
|
|
140
143
|
return i
|
|
141
144
|
|
|
@@ -302,6 +305,17 @@ def collect_all_symbols_in_scope(
|
|
|
302
305
|
return symbols
|
|
303
306
|
|
|
304
307
|
|
|
308
|
+
def collect_child_tabs(sym_tab: SymbolTable) -> list[lspt.CompletionItem]:
|
|
309
|
+
"""Return all child tab's as completion items."""
|
|
310
|
+
symbols: list[lspt.CompletionItem] = []
|
|
311
|
+
for tab in sym_tab.kid:
|
|
312
|
+
if tab.name not in [i.label for i in symbols]:
|
|
313
|
+
symbols.append(
|
|
314
|
+
lspt.CompletionItem(label=tab.name, kind=label_map(tab.get_type()))
|
|
315
|
+
)
|
|
316
|
+
return symbols
|
|
317
|
+
|
|
318
|
+
|
|
305
319
|
def parse_symbol_path(text: str, dot_position: int) -> list[str]:
|
|
306
320
|
"""Parse text and return a list of symbols."""
|
|
307
321
|
text = text[:dot_position][:-1].strip()
|
jaclang/plugin/default.py
CHANGED
|
@@ -6,7 +6,6 @@ import ast as ast3
|
|
|
6
6
|
import fnmatch
|
|
7
7
|
import html
|
|
8
8
|
import os
|
|
9
|
-
import pickle
|
|
10
9
|
import types
|
|
11
10
|
from collections import OrderedDict
|
|
12
11
|
from dataclasses import field
|
|
@@ -510,9 +509,10 @@ class JacBuiltinImpl:
|
|
|
510
509
|
'fillcolor="invis", fontcolor="black"];\n'
|
|
511
510
|
)
|
|
512
511
|
for source, target, edge in connections:
|
|
512
|
+
edge_label = html.escape(str(edge.__jac__.architype))
|
|
513
513
|
dot_content += (
|
|
514
514
|
f"{visited_nodes.index(source)} -> {visited_nodes.index(target)} "
|
|
515
|
-
f' [label="{
|
|
515
|
+
f' [label="{edge_label if "GenericEdge" not in edge_label else ""}"];\n'
|
|
516
516
|
)
|
|
517
517
|
for node_ in visited_nodes:
|
|
518
518
|
color = (
|
|
@@ -751,7 +751,9 @@ class JacFeatureImpl(
|
|
|
751
751
|
|
|
752
752
|
jac_machine = JacMachine.get(base_path)
|
|
753
753
|
if not jac_machine.jac_program:
|
|
754
|
-
jac_machine.attach_program(
|
|
754
|
+
jac_machine.attach_program(
|
|
755
|
+
JacProgram(mod_bundle=None, bytecode=None, sem_ir=None)
|
|
756
|
+
)
|
|
755
757
|
|
|
756
758
|
if lng == "py":
|
|
757
759
|
import_result = PythonImporter(JacMachine.get()).run_import(spec)
|
|
@@ -800,7 +802,7 @@ class JacFeatureImpl(
|
|
|
800
802
|
if mod_name.endswith(".test"):
|
|
801
803
|
mod_name = mod_name[:-5]
|
|
802
804
|
JacTestCheck.reset()
|
|
803
|
-
Jac.jac_import(target=mod_name, base_path=base)
|
|
805
|
+
Jac.jac_import(target=mod_name, base_path=base, cachable=False)
|
|
804
806
|
JacTestCheck.run_test(xit, maxfail, verbose)
|
|
805
807
|
ret_count = JacTestCheck.failcount
|
|
806
808
|
else:
|
|
@@ -854,8 +856,13 @@ class JacFeatureImpl(
|
|
|
854
856
|
|
|
855
857
|
@staticmethod
|
|
856
858
|
@hookimpl
|
|
857
|
-
def report(expr: Any) ->
|
|
859
|
+
def report(expr: Any, custom: bool) -> None: # noqa: ANN401
|
|
858
860
|
"""Jac's report stmt feature."""
|
|
861
|
+
ctx = Jac.get_context()
|
|
862
|
+
if custom:
|
|
863
|
+
ctx.custom = expr
|
|
864
|
+
else:
|
|
865
|
+
ctx.reports.append(expr)
|
|
859
866
|
|
|
860
867
|
@staticmethod
|
|
861
868
|
@hookimpl
|
|
@@ -1059,16 +1066,14 @@ class JacFeatureImpl(
|
|
|
1059
1066
|
file_loc: str, scope: str, attr: str, return_semstr: bool
|
|
1060
1067
|
) -> Optional[str]:
|
|
1061
1068
|
"""Jac's get_semstr_type feature."""
|
|
1069
|
+
from jaclang.compiler.semtable import SemInfo, SemScope, SemRegistry
|
|
1070
|
+
from jaclang.runtimelib.machine import JacMachine
|
|
1071
|
+
|
|
1062
1072
|
_scope = SemScope.get_scope_from_str(scope)
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
os.path.basename(file_loc).replace(".jac", ".registry.pkl"),
|
|
1068
|
-
),
|
|
1069
|
-
"rb",
|
|
1070
|
-
) as f:
|
|
1071
|
-
mod_registry: SemRegistry = pickle.load(f)
|
|
1073
|
+
jac_program = JacMachine.get().jac_program
|
|
1074
|
+
mod_registry: SemRegistry = (
|
|
1075
|
+
jac_program.sem_ir if jac_program is not None else SemRegistry()
|
|
1076
|
+
)
|
|
1072
1077
|
_, attr_seminfo = mod_registry.lookup(_scope, attr)
|
|
1073
1078
|
if attr_seminfo and isinstance(attr_seminfo, SemInfo):
|
|
1074
1079
|
return attr_seminfo.semstr if return_semstr else attr_seminfo.type
|
|
@@ -1078,15 +1083,12 @@ class JacFeatureImpl(
|
|
|
1078
1083
|
@hookimpl
|
|
1079
1084
|
def obj_scope(file_loc: str, attr: str) -> str:
|
|
1080
1085
|
"""Jac's gather_scope feature."""
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
"rb",
|
|
1088
|
-
) as f:
|
|
1089
|
-
mod_registry: SemRegistry = pickle.load(f)
|
|
1086
|
+
from jaclang.runtimelib.machine import JacMachine
|
|
1087
|
+
|
|
1088
|
+
jac_program = JacMachine.get().jac_program
|
|
1089
|
+
mod_registry: SemRegistry = (
|
|
1090
|
+
jac_program.sem_ir if jac_program is not None else SemRegistry()
|
|
1091
|
+
)
|
|
1090
1092
|
|
|
1091
1093
|
attr_scope = None
|
|
1092
1094
|
for x in attr.split("."):
|
|
@@ -1119,15 +1121,13 @@ class JacFeatureImpl(
|
|
|
1119
1121
|
@hookimpl
|
|
1120
1122
|
def get_sem_type(file_loc: str, attr: str) -> tuple[str | None, str | None]:
|
|
1121
1123
|
"""Jac's get_semstr_type implementation."""
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
)
|
|
1128
|
-
|
|
1129
|
-
) as f:
|
|
1130
|
-
mod_registry: SemRegistry = pickle.load(f)
|
|
1124
|
+
from jaclang.runtimelib.machine import JacMachine
|
|
1125
|
+
from jaclang.compiler.semtable import SemInfo, SemScope
|
|
1126
|
+
|
|
1127
|
+
jac_program = JacMachine.get().jac_program
|
|
1128
|
+
mod_registry: SemRegistry = (
|
|
1129
|
+
jac_program.sem_ir if jac_program is not None else SemRegistry()
|
|
1130
|
+
)
|
|
1131
1131
|
|
|
1132
1132
|
attr_scope = None
|
|
1133
1133
|
for x in attr.split("."):
|
jaclang/plugin/feature.py
CHANGED
|
@@ -371,9 +371,9 @@ class JacFeature(
|
|
|
371
371
|
return plugin_manager.hook.has_instance_default(gen_func=gen_func)
|
|
372
372
|
|
|
373
373
|
@staticmethod
|
|
374
|
-
def report(expr: Any) ->
|
|
374
|
+
def report(expr: Any, custom: bool = False) -> None: # noqa: ANN401
|
|
375
375
|
"""Jac's report stmt feature."""
|
|
376
|
-
|
|
376
|
+
plugin_manager.hook.report(expr=expr, custom=custom)
|
|
377
377
|
|
|
378
378
|
@staticmethod
|
|
379
379
|
def edge_ref(
|