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.

Files changed (99) hide show
  1. jaclang/cli/cli.py +77 -29
  2. jaclang/cli/cmdreg.py +44 -0
  3. jaclang/compiler/constant.py +6 -2
  4. jaclang/compiler/jac.lark +37 -47
  5. jaclang/compiler/larkparse/jac_parser.py +2 -2
  6. jaclang/compiler/parser.py +356 -61
  7. jaclang/compiler/passes/main/__init__.py +2 -4
  8. jaclang/compiler/passes/main/def_use_pass.py +1 -4
  9. jaclang/compiler/passes/main/predynamo_pass.py +221 -0
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +221 -135
  11. jaclang/compiler/passes/main/pyast_load_pass.py +54 -20
  12. jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
  13. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
  14. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
  15. jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
  16. jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
  17. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
  18. jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
  19. jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
  20. jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
  21. jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
  22. jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
  23. jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
  24. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
  25. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
  26. jaclang/compiler/passes/main/tests/test_checker_pass.py +190 -0
  27. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +56 -0
  28. jaclang/compiler/passes/main/type_checker_pass.py +29 -73
  29. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +302 -58
  30. jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
  31. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
  32. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
  33. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
  34. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +276 -10
  35. jaclang/compiler/passes/transform.py +12 -8
  36. jaclang/compiler/program.py +19 -7
  37. jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
  38. jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
  39. jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
  40. jaclang/compiler/tests/fixtures/python_module.py +1 -0
  41. jaclang/compiler/tests/test_importer.py +39 -0
  42. jaclang/compiler/tests/test_parser.py +49 -0
  43. jaclang/compiler/type_system/type_evaluator.jac +959 -0
  44. jaclang/compiler/type_system/type_utils.py +246 -0
  45. jaclang/compiler/type_system/types.py +58 -2
  46. jaclang/compiler/unitree.py +102 -107
  47. jaclang/langserve/engine.jac +138 -159
  48. jaclang/langserve/server.jac +25 -1
  49. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  50. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  51. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  52. jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
  53. jaclang/langserve/tests/server_test/circle_template.jac +80 -0
  54. jaclang/langserve/tests/server_test/glob_template.jac +4 -0
  55. jaclang/langserve/tests/server_test/test_lang_serve.py +154 -309
  56. jaclang/langserve/tests/server_test/utils.py +153 -116
  57. jaclang/langserve/tests/test_server.py +21 -84
  58. jaclang/langserve/utils.jac +12 -15
  59. jaclang/lib.py +17 -0
  60. jaclang/runtimelib/archetype.py +25 -25
  61. jaclang/runtimelib/constructs.py +2 -2
  62. jaclang/runtimelib/machine.py +63 -46
  63. jaclang/runtimelib/meta_importer.py +27 -1
  64. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  65. jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
  66. jaclang/settings.py +19 -16
  67. jaclang/tests/fixtures/abc_check.jac +3 -3
  68. jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
  69. jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
  70. jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
  71. jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
  72. jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
  73. jaclang/tests/fixtures/funccall_genexpr.py +5 -0
  74. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  75. jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
  76. jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
  77. jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
  78. jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
  79. jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
  80. jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
  81. jaclang/tests/fixtures/py2jac_params.py +8 -0
  82. jaclang/tests/fixtures/run_test.jac +4 -4
  83. jaclang/tests/test_cli.py +159 -7
  84. jaclang/tests/test_language.py +213 -38
  85. jaclang/tests/test_reference.py +3 -1
  86. jaclang/utils/helpers.py +67 -6
  87. jaclang/utils/module_resolver.py +10 -0
  88. jaclang/utils/test.py +8 -0
  89. jaclang/utils/tests/test_lang_tools.py +4 -15
  90. jaclang/utils/treeprinter.py +0 -18
  91. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -2
  92. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/RECORD +95 -65
  93. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/WHEEL +1 -1
  94. jaclang/compiler/passes/main/inheritance_pass.py +0 -131
  95. jaclang/compiler/type_system/type_evaluator.py +0 -560
  96. jaclang/langserve/dev_engine.jac +0 -645
  97. jaclang/langserve/dev_server.jac +0 -201
  98. /jaclang/{langserve/tests/server_test/code_test.py → tests/fixtures/py2jac_empty.py} +0 -0
  99. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
@@ -8,9 +8,10 @@ import from typing { Callable, Optional }
8
8
 
9
9
  import jaclang.compiler.unitree as uni;
10
10
  import from jaclang { JacMachineInterface as Jac }
11
- import from jaclang.compiler.constant {SymbolType}
11
+ import from jaclang.compiler.constant { SymbolType }
12
12
  import from jaclang.compiler.program { JacProgram }
13
- import from jaclang.compiler.type_system.types{ ClassType}
13
+ import from jaclang.compiler.type_system.type_utils { get_completion_items }
14
+ import from jaclang.compiler.type_system.types { ClassType, TypeBase }
14
15
  import from jaclang.compiler.unitree { UniScopeNode }
15
16
  import from sem_manager { SemTokManager }
16
17
  import from jaclang.vendor.pygls { uris }
@@ -201,121 +202,154 @@ class JacLangServer(JacProgram , LanguageServer) {
201
202
  }
202
203
  }
203
204
 
205
+ def get_token_at_position(self: JacLangServer, file_path: str, position: lspt.Position) -> Optional[uni.AstNode] {
206
+ fs_path = uris.to_fs_path(file_path);
207
+ if fs_path not in self.mod.hub {
208
+ return None;
209
+ }
210
+ sem_mgr = self.sem_managers.get(fs_path);
211
+ if not sem_mgr {
212
+ return None;
213
+ }
214
+ token_index =
215
+ utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
216
+ if token_index is None {
217
+ return None;
218
+ }
219
+ node_selected = sem_mgr.static_sem_tokens[token_index][3];
220
+ return node_selected;
221
+ }
222
+
223
+ def debug(self: JacLangServer, msg: str) -> None {
224
+ self.log_py("[DEBUG] " + ("-" * 80));
225
+ self.log_py(f"[DEBUG] {msg}");
226
+ self.log_py("[DEBUG] " + ("-" * 80));
227
+ }
228
+
204
229
  """Return completion for a file."""
205
230
  def get_completion(
206
231
  self: JacLangServer,
207
- file_path: str,
232
+ file_uri: str,
208
233
  position: lspt.Position,
209
234
  completion_trigger: Optional[str]
210
235
  ) -> lspt.CompletionList {
236
+ self.debug("getting completion for " + file_uri + " at " + str(position));
237
+
211
238
  try {
212
- document = self.workspace.get_text_document(file_path);
213
- mod_ir = self.get_ir(document.path);
214
- if not mod_ir {
215
- return lspt.CompletionList(is_incomplete=False, items=[]);
216
- }
217
- current_line = document.lines[position.line];
218
- current_pos = position.character;
219
- current_symbol_path = utils.parse_symbol_path(current_line, current_pos);
220
- builtin_mod =
221
- next(
222
- ( mod for (name, mod) in self.mod.hub.items() if 'builtins' in name )
223
- );
224
- builtin_tab = builtin_mod.sym_tab;
225
- assert isinstance(builtin_tab, UniScopeNode) ;
226
- completion_items = [];
227
- node_selected =
228
- utils.find_deepest_symbol_node_at_pos(
229
- mod_ir,
230
- position.line,
231
- (position.character - 2)
232
- );
233
- mod_tab = mod_ir.sym_tab if not node_selected else node_selected.sym_tab;
234
- current_symbol_table = mod_tab;
235
- if completion_trigger == '.' {
236
- if current_symbol_path {
237
- temp_tab = mod_tab;
238
- for symbol in current_symbol_path {
239
- if symbol == 'self' {
240
- is_ability_def =
241
- temp_tab
242
- if isinstance(temp_tab, uni.ImplDef)
243
- else temp_tab.find_parent_of_type(uni.ImplDef);
244
- if not is_ability_def {
245
- archi_owner =
246
- mod_tab.find_parent_of_type(uni.Archetype);
247
- temp_tab =
248
- archi_owner.sym_tab
249
- if archi_owner and archi_owner.sym_tab
250
- else mod_tab;
251
- continue;
252
- } else {
253
- archi_owner =
254
- is_ability_def.decl_link.find_parent_of_type(
255
- uni.Archetype
256
- )
257
- if is_ability_def.decl_link
258
- else None;
259
- temp_tab =
260
- archi_owner.sym_tab
261
- if archi_owner and archi_owner.sym_tab
262
- else temp_tab;
263
- continue;
264
- }
265
- }
266
- symb = temp_tab.lookup(symbol);
267
- if symb {
268
- fetc_tab = symb.symbol_table;
269
- if fetc_tab {
270
- temp_tab = fetc_tab;
271
- } else {
272
- temp_tab =
273
- symb.defn[0].type_sym_tab
274
- if symb.defn[0].type_sym_tab
275
- else temp_tab;
276
- }
277
- } else {
278
- break;
239
+ file_path = uris.to_fs_path(file_uri);
240
+
241
+ if (node_at_pos := self.get_node_at_position(file_path, position.line, position.character - 1)) {
242
+ self.debug("found the node at pos " + str(position) + " " + str(node_at_pos));
243
+
244
+ # For each trigger character we need to handle the completion differently
245
+ if isinstance(node_at_pos, uni.Token) {
246
+ if node_at_pos.name == "DOT" {
247
+ member_access = node_at_pos.parent;
248
+ self.debug("found dot " + str(member_access));
249
+ if isinstance(member_access, uni.AtomTrailer) {
250
+ self.debug("before returning the list");
251
+ return self.get_completion_of_node(member_access.target);
279
252
  }
280
- }
281
- completion_items += utils.collect_all_symbols_in_scope(
282
- temp_tab,
283
- up_tree=False
284
- );
285
- if isinstance(temp_tab, uni.Archetype) and temp_tab.base_classes {
286
- base = [];
287
- for base_name in temp_tab.base_classes {
288
- if isinstance(base_name, uni.Name) and base_name.sym {
289
- base.append(base_name.sym);
290
- }
253
+
254
+ # FIXME: This is wrong but imma do it anyways like this for now.
255
+ } elif node_at_pos.name == "NAME" {
256
+
257
+ # Name of atom trailer.
258
+ if node_at_pos.parent and isinstance(node_at_pos.parent, uni.AtomTrailer) {
259
+ self.debug("found name in atom trailer " + str(node_at_pos.parent));
260
+ return self.get_completion_of_node(node_at_pos.parent.target);
291
261
  }
292
- for base_class_symbol in base {
293
- if base_class_symbol.symbol_table {
294
- completion_items += utils.collect_all_symbols_in_scope(
295
- base_class_symbol.symbol_table,
296
- up_tree=False
297
- );
298
- }
262
+
263
+ # Just a name field.
264
+ if scope_node := node_at_pos.find_parent_of_type(uni.UniScopeNode) {
265
+ self.debug("found name in scope node " + str(scope_node));
266
+ return self.get_completion_of_node(scope_node);
299
267
  }
300
268
  }
301
269
  }
302
- } elif node_selected and node_selected.find_parent_of_type(uni.Archetype)
303
- or node_selected.find_parent_of_type(uni.ImplDef)
304
- {
305
- self_symbol =
306
-
307
- [lspt.CompletionItem(
308
- label='self',
309
- kind=lspt.CompletionItemKind.Variable
310
- )];
311
- } else {
312
- self_symbol = [];
313
270
  }
314
- return lspt.CompletionList(is_incomplete=False, items=completion_items);
271
+
272
+ return lspt.CompletionList(is_incomplete=False, items=[]);
273
+
315
274
  } except Exception as e {
316
275
  self.log_py(f"'Error during completion: '{e}");
317
276
  return lspt.CompletionList(is_incomplete=False, items=[]);
318
277
  }
278
+
279
+ self.debug("returning empty list");
280
+ }
281
+
282
+ def get_ast_of_file(self: JacLangServer, file_path: str) -> Optional[uni.AstNode] {
283
+ if file_path in self.mod.hub {
284
+ return self.mod.hub[file_path];
285
+ }
286
+ return None;
287
+ }
288
+
289
+ def get_node_at_position(self: JacLangServer, file_path: str, line:int, col: int) -> Optional[uni.AstNode] {
290
+ if (ast := self.get_ast_of_file(file_path)) {
291
+ for ast_node in ast._in_mod_nodes {
292
+ if not isinstance(ast_node, uni.Token) {
293
+ continue;
294
+ }
295
+ if (utils.position_within_node(ast_node, line + 1, col + 1)) {
296
+ return ast_node;
297
+ }
298
+ }
299
+ }
300
+ return None;
301
+ }
302
+
303
+ def get_completion_of_node(self: JacLangServer, node: uni.AstNode) -> lspt.CompletionList {
304
+ if (node_type := self.get_node_type(node)) {
305
+ self.debug("found type " + str(node_type));
306
+ return self.get_completion_items_of(node_type);
307
+ } elif isinstance(node, UniScopeNode) {
308
+ self.debug("found scope node " + str(node));
309
+ return self.get_completion_items_of(node);
310
+ }
311
+
312
+ self.debug("no type found for node " + str(node));
313
+ return lspt.CompletionList(is_incomplete=False, items=[]);
314
+ }
315
+
316
+ """Return the type of an AST node if it has one."""
317
+ def get_node_type(self: JacLangServer, n: uni.AstNode) -> Optional[TypeBase] {
318
+ if isinstance(n, uni.Expr) {
319
+ typ = self.get_type_evaluator().get_type_of_expression(n);
320
+ self.debug("found type " + str(typ) + " for expr " + str(n));
321
+ return typ;
322
+ }
323
+ self.debug("no type found for node " + str(n));
324
+ return None;
325
+ }
326
+
327
+ """Get type members for completion."""
328
+ def get_completion_items_of(self: JacLangServer, ty: TypeBase | uni.UniScopeNode) -> lspt.CompletionList {
329
+ evaluator = self.get_type_evaluator();
330
+ self.debug("getting completion of " + str(ty));
331
+ items = get_completion_items(ty);
332
+ self.debug("completion items are " + str(items));
333
+
334
+ items: list[lspt.CompletionItem] = [];
335
+ for item in get_completion_items(ty) {
336
+ detail: lspt.CompletionItemLabelDetails | None = None;
337
+ if item.detail {
338
+ detail = lspt.CompletionItemLabelDetails(detail=item.detail);
339
+ }
340
+ items.append(
341
+ lspt.CompletionItem(
342
+ label=item.label,
343
+ kind=item.kind,
344
+ label_details=detail,
345
+ )
346
+ );
347
+ }
348
+
349
+ return lspt.CompletionList(
350
+ is_incomplete=False,
351
+ items=items,
352
+ );
319
353
  }
320
354
 
321
355
  """Rename module."""
@@ -370,21 +404,7 @@ class JacLangServer(JacProgram , LanguageServer) {
370
404
  file_path: str,
371
405
  position: lspt.Position
372
406
  ) -> Optional[lspt.Hover] {
373
- fs_path = uris.to_fs_path(file_path);
374
-
375
- if fs_path not in self.mod.hub {
376
- return None;
377
- }
378
- sem_mgr = self.sem_managers.get(fs_path);
379
- if not sem_mgr {
380
- return None;
381
- }
382
- token_index =
383
- utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
384
- if token_index is None {
385
- return None;
386
- }
387
- node_selected = sem_mgr.static_sem_tokens[token_index][3];
407
+ node_selected = self.get_token_at_position(file_path, position);
388
408
  value = self.get_node_info(node_selected) if node_selected else None;
389
409
  if value {
390
410
  return lspt.Hover(
@@ -441,21 +461,7 @@ class JacLangServer(JacProgram , LanguageServer) {
441
461
  file_path: str,
442
462
  position: lspt.Position
443
463
  ) -> Optional[lspt.Location] {
444
- fs_path = uris.to_fs_path(file_path);
445
-
446
- if fs_path not in self.mod.hub {
447
- return None;
448
- }
449
- sem_mgr = self.sem_managers.get(fs_path);
450
- if not sem_mgr {
451
- return None;
452
- }
453
- token_index =
454
- utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
455
- if token_index is None {
456
- return None;
457
- }
458
- node_selected = sem_mgr.static_sem_tokens[token_index][3];
464
+ node_selected = self.get_token_at_position(file_path, position);
459
465
  if node_selected {
460
466
  if (node_selected.sym.sym_type == SymbolType.MODULE) {
461
467
  spec = node_selected.sym.decl.parent.resolve_relative_path();
@@ -554,21 +560,7 @@ class JacLangServer(JacProgram , LanguageServer) {
554
560
  file_path: str,
555
561
  position: lspt.Position
556
562
  ) -> list[lspt.Location] {
557
- fs_path = uris.to_fs_path(file_path);
558
-
559
- if fs_path not in self.mod.hub {
560
- return [];
561
- }
562
- sem_mgr = self.sem_managers.get(fs_path);
563
- if not sem_mgr {
564
- return [];
565
- }
566
- index1 =
567
- utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
568
- if index1 is None {
569
- return [];
570
- }
571
- node_selected = sem_mgr.static_sem_tokens[index1][3];
563
+ node_selected = self.get_token_at_position(file_path, position);
572
564
  if node_selected and node_selected.sym {
573
565
  list_of_references: list[lspt.Location] =
574
566
  [ lspt.Location(
@@ -587,20 +579,7 @@ class JacLangServer(JacProgram , LanguageServer) {
587
579
  position: lspt.Position,
588
580
  new_name: str
589
581
  ) -> Optional[lspt.WorkspaceEdit] {
590
- fs_path = uris.to_fs_path(file_path);
591
- if fs_path not in self.mod.hub {
592
- return None;
593
- }
594
- sem_mgr = self.sem_managers.get(fs_path);
595
- if not sem_mgr {
596
- return None;
597
- }
598
- index1 =
599
- utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
600
- if index1 is None {
601
- return None;
602
- }
603
- node_selected = sem_mgr.static_sem_tokens[index1][3];
582
+ node_selected = self.get_token_at_position(file_path, position);
604
583
  if node_selected and node_selected.sym {
605
584
  changes: dict[(str, list[lspt.TextEdit])] = {};
606
585
  for node in [*node_selected.sym.uses, node_selected.sym.defn[0]] {
@@ -1,5 +1,7 @@
1
1
  """Jaclang Language Server."""
2
2
 
3
+ import asyncio;
4
+
3
5
  import from typing { Optional }
4
6
 
5
7
  import from jaclang.compiler.constant {
@@ -17,6 +19,11 @@ with entry {
17
19
  server = JacLangServer();
18
20
  }
19
21
 
22
+ def debug(ls: JacLangServer, msg: str) -> None {
23
+ ls.log_py(f"[DEBUG] " + ("-" * 80));
24
+ ls.log_py(f"[DEBUG]' {msg} ");
25
+ ls.log_py(f"[DEBUG] " + ("-" * 80));
26
+ }
20
27
 
21
28
  """Check syntax on change."""
22
29
  @server.feature(lspt.TEXT_DOCUMENT_DID_OPEN)
@@ -38,6 +45,7 @@ async def did_save(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) ->
38
45
  ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
39
46
  }
40
47
 
48
+ glob still_compiling = False;
41
49
 
42
50
  """Check syntax on change with debouncing."""
43
51
  @ server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
@@ -45,6 +53,9 @@ async def did_change(
45
53
  ls: JacLangServer,
46
54
  params: lspt.DidChangeTextDocumentParams
47
55
  ) -> None {
56
+ global still_compiling;
57
+ still_compiling = True;
58
+
48
59
  file_path = params.text_document.uri;
49
60
  try {
50
61
  document = ls.workspace.get_text_document(file_path);
@@ -58,6 +69,8 @@ async def did_change(
58
69
  } except Exception as e {
59
70
  ls.log_py(f" 'Failed to update semantic tokens: ' {e} ");
60
71
  }
72
+
73
+ debug(ls, "Compilation started...");
61
74
  ls.log_py(f" 'Launching debounced quick check for ' {file_path} ");
62
75
  quick_check_passed = await ls.launch_quick_check(file_path, delay=0.5);
63
76
  if quick_check_passed {
@@ -65,8 +78,11 @@ async def did_change(
65
78
  f" 'Quick check passed, launching debounced deep check for ' {file_path} "
66
79
  );
67
80
  await ls.launch_deep_check(file_path, delay=1.0);
81
+
68
82
  ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
69
83
  }
84
+ still_compiling = False;
85
+ debug(ls, "Compilation finished...");
70
86
  }
71
87
 
72
88
  """Format the given document."""
@@ -124,7 +140,15 @@ def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None
124
140
  lspt.TEXT_DOCUMENT_COMPLETION,
125
141
  lspt.CompletionOptions(trigger_characters=['.', ':', 'a-zA-Z0-9'])
126
142
  )
127
- def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.CompletionList {
143
+ async def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.CompletionList {
144
+
145
+ debug(ls, "Waiting for compilation to finish...");
146
+ global still_compiling;
147
+ while still_compiling {
148
+ await asyncio.sleep(0.1);
149
+ }
150
+ debug(ls, "Compilation finished, providing completions...");
151
+
128
152
  return ls.get_completion(
129
153
  params.text_document.uri,
130
154
  params.position,
@@ -63,15 +63,15 @@ with entry:__main__ {
63
63
  glob expected_area = 78.53981633974483;
64
64
 
65
65
  test calc_area {
66
- check almostEqual(calculate_area(RAD), expected_area);
66
+ assert almostEqual(calculate_area(RAD), expected_area);
67
67
  }
68
68
 
69
69
  test circle_area {
70
70
  c = Circle(RAD);
71
- check almostEqual(c.area(), expected_area);
71
+ assert almostEqual(c.area(), expected_area);
72
72
  }
73
73
 
74
74
  test circle_type {
75
75
  c = Circle(RAD);
76
- check c.shape_type == ShapeType.CIRCLE;
76
+ assert c.shape_type == ShapeType.CIRCLE;
77
77
  }
@@ -59,15 +59,15 @@ print(f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}
59
59
  glob expected_area = 78.53981633974483;
60
60
 
61
61
  test calc_area {
62
- check almostEqual(calculate_area(RAD), expected_area);
62
+ assert almostEqual(calculate_area(RAD), expected_area);
63
63
  }
64
64
 
65
65
  test circle_area {
66
66
  c = Circle(RAD);
67
- check almostEqual(c.area(), expected_area);
67
+ assert almostEqual(c.area(), expected_area);
68
68
  }
69
69
 
70
70
  test circle_type {
71
71
  c = Circle(RAD);
72
- check c.shape_type == ShapeType.CIRCLE;
72
+ assert c.shape_type == ShapeType.CIRCLE;
73
73
  }
@@ -1,15 +1,15 @@
1
1
  glob expected_area = 78.53981633974483;
2
2
 
3
3
  test a1 {
4
- check almostEqual(calculate_area(RAD), expected_area);
4
+ assert almostEqual(calculate_area(RAD), expected_area);
5
5
  }
6
6
 
7
7
  test a2 {
8
8
  c = Circle(RAD);
9
- check almostEqual(c.area(), expected_area);
9
+ assert almostEqual(c.area(), expected_area);
10
10
  }
11
11
 
12
12
  test a3 {
13
13
  c = Circle(RAD);
14
- check c.shape_type == ShapeType.CIRCLE;
14
+ assert c.shape_type == ShapeType.CIRCLE;
15
15
  }
@@ -0,0 +1,10 @@
1
+
2
+ class Foo {
3
+ has bar: int;
4
+ has baz: int;
5
+ }
6
+
7
+ with entry {
8
+ foo = Foo();
9
+ foo.
10
+ }
@@ -0,0 +1,80 @@
1
+ """
2
+ This module demonstrates a simple circle class and a function to calculate
3
+ the area of a circle in all of Jac's glory.
4
+ """
5
+
6
+ import math;
7
+
8
+ # Module-level global variable
9
+ glob RAD = 5;
10
+
11
+ """Function to calculate the area of a circle."""
12
+ def calculate_area(radius: float) -> float {
13
+ return math.pi * radius * radius;
14
+ }
15
+
16
+ #* (This is a multiline comment in Jac)
17
+ Above we have the demonstration of a function to calculate the area of a circle.
18
+ Below we have the demonstration of a class to calculate the area of a circle.
19
+ *#
20
+
21
+ """Enum for shape types"""
22
+ enum ShapeType {
23
+ CIRCLE = "Circle",
24
+ UNKNOWN = "Unknown"
25
+ }
26
+
27
+ """Base class for a shape."""
28
+ obj Shape {
29
+ has shape_type: ShapeType;
30
+
31
+ """Abstract method to calculate the area of a shape."""
32
+ def area -> float abs;
33
+ }
34
+
35
+ """Circle class inherits from Shape."""
36
+ obj Circle(Shape) {
37
+ def init(radius: float) {
38
+ super.init(ShapeType.CIRCLE);
39
+ self.radius = radius;
40
+ }
41
+
42
+ """Overridden method to calculate the area of the circle."""
43
+ override def area -> float {
44
+ return math.pi * self.radius * self.radius;
45
+ }
46
+ }
47
+
48
+ with entry {
49
+ c = Circle(RAD);
50
+ }
51
+
52
+ # Global also works here
53
+
54
+ with entry:__main__ {
55
+ # To run the program functionality
56
+ print(
57
+ f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}"
58
+ );
59
+ print(
60
+ f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}"
61
+ );
62
+ }
63
+
64
+ # Unit Tests!
65
+ glob expected_area = 78.53981633974483;
66
+ #{{INJECT_CODE}}
67
+
68
+ test calc_area {
69
+ assert almostEqual(calculate_area(RAD), expected_area);
70
+ }
71
+
72
+ test circle_area {
73
+ c = Circle(RAD);
74
+ assert almostEqual(c.area(), expected_area);
75
+ }
76
+
77
+ test circle_type {
78
+ c = Circle(RAD);
79
+ assert c.shape_type == ShapeType.CIRCLE;
80
+ }
@@ -0,0 +1,4 @@
1
+ glob expected_area0 = 78.53981633974483;
2
+ glob expected_area1 = 78.53981633974483;
3
+ #{{INJECT_CODE}}
4
+ glob expected_area2 = 78.53981633974483;