jaclang 0.7.18__py3-none-any.whl → 0.7.22__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 (47) hide show
  1. jaclang/cli/cli.py +2 -2
  2. jaclang/compiler/absyntree.py +29 -4
  3. jaclang/compiler/jac.lark +14 -14
  4. jaclang/compiler/parser.py +71 -59
  5. jaclang/compiler/passes/ir_pass.py +2 -0
  6. jaclang/compiler/passes/main/__init__.py +1 -1
  7. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +50 -13
  8. jaclang/compiler/passes/main/import_pass.py +29 -1
  9. jaclang/compiler/passes/main/py_collect_dep_pass.py +8 -0
  10. jaclang/compiler/passes/main/pyast_load_pass.py +8 -6
  11. jaclang/compiler/passes/main/registry_pass.py +4 -0
  12. jaclang/compiler/passes/main/sym_tab_build_pass.py +0 -18
  13. jaclang/compiler/passes/main/tests/fixtures/fstrings.jac +44 -1
  14. jaclang/compiler/passes/main/tests/fixtures/mod_type_assign.jac +7 -0
  15. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.pyi +3 -0
  16. jaclang/compiler/passes/main/tests/test_import_pass.py +10 -10
  17. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  18. jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +23 -1
  19. jaclang/compiler/passes/main/type_check_pass.py +4 -4
  20. jaclang/compiler/passes/tool/jac_formatter_pass.py +61 -31
  21. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/line_spacing.jac +57 -0
  22. jaclang/compiler/semtable.py +4 -4
  23. jaclang/compiler/symtable.py +5 -0
  24. jaclang/langserve/engine.py +68 -7
  25. jaclang/langserve/tests/test_server.py +3 -3
  26. jaclang/langserve/utils.py +0 -113
  27. jaclang/plugin/tests/test_jaseci.py +23 -4
  28. jaclang/runtimelib/architype.py +20 -2
  29. jaclang/runtimelib/importer.py +3 -0
  30. jaclang/runtimelib/machine.py +92 -4
  31. jaclang/runtimelib/memory.py +1 -1
  32. jaclang/settings.py +4 -0
  33. jaclang/tests/fixtures/bar.jac +1 -1
  34. jaclang/tests/fixtures/builtins_test.jac +16 -0
  35. jaclang/tests/fixtures/dynamic_architype.jac +34 -0
  36. jaclang/tests/fixtures/entry_exit.jac +36 -0
  37. jaclang/tests/fixtures/foo.jac +0 -1
  38. jaclang/tests/fixtures/match_multi_ex.jac +12 -0
  39. jaclang/tests/fixtures/trailing_comma.jac +88 -0
  40. jaclang/tests/fixtures/walker_update.jac +19 -0
  41. jaclang/tests/test_cli.py +29 -2
  42. jaclang/tests/test_language.py +150 -9
  43. jaclang/utils/treeprinter.py +1 -1
  44. {jaclang-0.7.18.dist-info → jaclang-0.7.22.dist-info}/METADATA +4 -2
  45. {jaclang-0.7.18.dist-info → jaclang-0.7.22.dist-info}/RECORD +47 -38
  46. {jaclang-0.7.18.dist-info → jaclang-0.7.22.dist-info}/WHEEL +0 -0
  47. {jaclang-0.7.18.dist-info → jaclang-0.7.22.dist-info}/entry_points.txt +0 -0
@@ -332,119 +332,6 @@ def parse_symbol_path(text: str, dot_position: int) -> list[str]:
332
332
  return all_words
333
333
 
334
334
 
335
- def resolve_symbol_path(sym_name: str, node_tab: SymbolTable) -> str:
336
- """Resolve symbol path."""
337
- visited = set()
338
- current_tab: Optional[SymbolTable] = node_tab
339
-
340
- while current_tab is not None and current_tab not in visited:
341
- visited.add(current_tab)
342
- for name, symbol in current_tab.tab.items():
343
- if name not in dir(builtins) and name == sym_name:
344
- path = symbol.defn[0]._sym_type
345
- if symbol.sym_type == SymbolType.ENUM_ARCH:
346
- if isinstance(current_tab.owner, ast.Module):
347
- return current_tab.owner.name + "." + sym_name
348
- elif isinstance(current_tab.owner, ast.AstSymbolNode):
349
- return current_tab.owner.name_spec._sym_type + "." + sym_name
350
- return path
351
- current_tab = current_tab.parent if current_tab.parent != current_tab else None
352
- return ""
353
-
354
-
355
- def find_symbol_table(path: str, current_tab: Optional[SymbolTable]) -> SymbolTable:
356
- """Find symbol table."""
357
- path = path.lstrip(".")
358
- current_table = current_tab
359
- if current_table:
360
- for segment in path.split("."):
361
- current_table = next(
362
- (
363
- child_table
364
- for child_table in current_table.kid
365
- if child_table.name == segment
366
- ),
367
- current_table,
368
- )
369
- if current_table:
370
- return current_table
371
- raise ValueError(f"Symbol table not found for path {path}")
372
-
373
-
374
- def resolve_completion_symbol_table(
375
- mod_tab: SymbolTable,
376
- current_symbol_path: list[str],
377
- current_tab: Optional[SymbolTable],
378
- ) -> list[lspt.CompletionItem]:
379
- """Resolve symbol table for completion items."""
380
- current_symbol_table = mod_tab
381
- for obj in current_symbol_path:
382
- if obj == "self":
383
- try:
384
- try:
385
- is_abilitydef = (
386
- mod_tab.owner
387
- if isinstance(mod_tab.owner, ast.AbilityDef)
388
- else mod_tab.owner.parent_of_type(ast.AbilityDef)
389
- )
390
- archi_owner = (
391
- (is_abilitydef.decl_link.parent_of_type(ast.Architype))
392
- if is_abilitydef.decl_link
393
- else None
394
- )
395
- current_symbol_table = (
396
- archi_owner._sym_tab
397
- if archi_owner and archi_owner._sym_tab
398
- else mod_tab
399
- )
400
- continue
401
-
402
- except ValueError:
403
- pass
404
- archi_owner = mod_tab.owner.parent_of_type(ast.Architype)
405
- current_symbol_table = (
406
- archi_owner._sym_tab
407
- if archi_owner and archi_owner._sym_tab
408
- else mod_tab
409
- )
410
- except ValueError:
411
- pass
412
- else:
413
- path: str = resolve_symbol_path(obj, current_symbol_table)
414
- if path:
415
- current_symbol_table = find_symbol_table(path, current_tab)
416
- else:
417
- if (
418
- isinstance(current_symbol_table.owner, ast.Architype)
419
- and current_symbol_table.owner.base_classes
420
- ):
421
- for base_name in current_symbol_table.owner.base_classes.items:
422
- if isinstance(base_name, ast.Name) and base_name.sym:
423
- path = base_name.sym.sym_dotted_name + "." + obj
424
- current_symbol_table = find_symbol_table(path, current_tab)
425
- if (
426
- isinstance(current_symbol_table.owner, ast.Architype)
427
- and current_symbol_table.owner.base_classes
428
- ):
429
- base = []
430
- for base_name in current_symbol_table.owner.base_classes.items:
431
- if isinstance(base_name, ast.Name) and base_name.sym:
432
- base.append(base_name.sym.sym_dotted_name)
433
- for base_ in base:
434
- completion_items = collect_all_symbols_in_scope(
435
- find_symbol_table(base_, current_tab),
436
- up_tree=False,
437
- )
438
- else:
439
- completion_items = []
440
- if isinstance(current_symbol_table.owner, (ast.Ability, ast.AbilityDef)):
441
- return completion_items
442
- completion_items.extend(
443
- collect_all_symbols_in_scope(current_symbol_table, up_tree=False)
444
- )
445
- return completion_items
446
-
447
-
448
335
  def get_token_start(
449
336
  token_index: int | None, sem_tokens: list[int]
450
337
  ) -> tuple[int, int, int]:
@@ -337,8 +337,8 @@ class TestJaseciPlugin(TestCase):
337
337
 
338
338
  # --------- NO UPDATE SHOULD HAPPEN -------- #
339
339
 
340
- self.assertTrue(archs[0], "A(val=2)")
341
- self.assertTrue(archs[1], "A(val=1)")
340
+ self.assertEqual(archs[0], "A(val=2)")
341
+ self.assertEqual(archs[1], "A(val=1)")
342
342
 
343
343
  self._output2buffer()
344
344
  cli.enter(
@@ -435,8 +435,8 @@ class TestJaseciPlugin(TestCase):
435
435
 
436
436
  # --------- UPDATE SHOULD HAPPEN -------- #
437
437
 
438
- self.assertTrue(archs[0], "A(val=20)")
439
- self.assertTrue(archs[1], "A(val=10)")
438
+ self.assertEqual(archs[0], "A(val=20)")
439
+ self.assertEqual(archs[1], "A(val=10)")
440
440
 
441
441
  self._output2buffer()
442
442
  cli.enter(
@@ -474,6 +474,25 @@ class TestJaseciPlugin(TestCase):
474
474
  )
475
475
  self.assertFalse(self.capturedOutput.getvalue().strip())
476
476
 
477
+ # --------- ROOTS RESET OWN NODE -------- #
478
+
479
+ cli.enter(
480
+ filename=self.fixture_abs_path("other_root_access.jac"),
481
+ entrypoint="update_node",
482
+ args=[1],
483
+ session=session,
484
+ root=self.roots[0],
485
+ node=self.nodes[0],
486
+ )
487
+ cli.enter(
488
+ filename=self.fixture_abs_path("other_root_access.jac"),
489
+ entrypoint="update_node",
490
+ args=[2],
491
+ session=session,
492
+ root=self.roots[1],
493
+ node=self.nodes[1],
494
+ )
495
+
477
496
  def test_other_root_access(self) -> None:
478
497
  """Test filtering on node, then visit."""
479
498
  global session
@@ -526,6 +526,14 @@ class WalkerAnchor(Anchor):
526
526
  if walker := self.architype:
527
527
  self.path = []
528
528
  self.next = [node]
529
+ if self.next:
530
+ current_node = self.next[-1].architype
531
+ for i in walker._jac_entry_funcs_:
532
+ if not i.trigger:
533
+ if i.func:
534
+ i.func(walker, current_node)
535
+ else:
536
+ raise ValueError(f"No function {i.name} to call.")
529
537
  while len(self.next):
530
538
  if current_node := self.next.pop(0).architype:
531
539
  for i in current_node._jac_entry_funcs_:
@@ -538,16 +546,20 @@ class WalkerAnchor(Anchor):
538
546
  return walker
539
547
  for i in walker._jac_entry_funcs_:
540
548
  if not i.trigger or isinstance(current_node, i.trigger):
541
- if i.func:
549
+ if i.func and i.trigger:
542
550
  i.func(walker, current_node)
551
+ elif not i.trigger:
552
+ continue
543
553
  else:
544
554
  raise ValueError(f"No function {i.name} to call.")
545
555
  if self.disengaged:
546
556
  return walker
547
557
  for i in walker._jac_exit_funcs_:
548
558
  if not i.trigger or isinstance(current_node, i.trigger):
549
- if i.func:
559
+ if i.func and i.trigger:
550
560
  i.func(walker, current_node)
561
+ elif not i.trigger:
562
+ continue
551
563
  else:
552
564
  raise ValueError(f"No function {i.name} to call.")
553
565
  if self.disengaged:
@@ -560,6 +572,12 @@ class WalkerAnchor(Anchor):
560
572
  raise ValueError(f"No function {i.name} to call.")
561
573
  if self.disengaged:
562
574
  return walker
575
+ for i in walker._jac_exit_funcs_:
576
+ if not i.trigger:
577
+ if i.func:
578
+ i.func(walker, current_node)
579
+ else:
580
+ raise ValueError(f"No function {i.name} to call.")
563
581
  self.ignores = []
564
582
  return walker
565
583
  raise Exception(f"Invalid Reference {self.id}")
@@ -195,6 +195,8 @@ class PythonImporter(Importer):
195
195
  loaded_items: list = []
196
196
  if spec.target.startswith("."):
197
197
  spec.target = spec.target.lstrip(".")
198
+ if len(spec.target.split(".")) > 1:
199
+ spec.target = spec.target.split(".")[-1]
198
200
  full_target = path.normpath(path.join(spec.caller_dir, spec.target))
199
201
  imp_spec = importlib.util.spec_from_file_location(
200
202
  spec.target, full_target + ".py"
@@ -340,6 +342,7 @@ class JacImporter(Importer):
340
342
  spec.full_target,
341
343
  caller_dir=spec.caller_dir,
342
344
  cachable=spec.cachable,
345
+ reload=reload if reload else False,
343
346
  )
344
347
  try:
345
348
  if not codeobj:
@@ -6,12 +6,17 @@ import os
6
6
  import sys
7
7
  import types
8
8
  from contextvars import ContextVar
9
- from typing import Optional
9
+ from typing import Optional, Union
10
10
 
11
11
  from jaclang.compiler.absyntree import Module
12
12
  from jaclang.compiler.compile import compile_jac
13
13
  from jaclang.compiler.constant import Constants as Con
14
- from jaclang.runtimelib.architype import EdgeArchitype, NodeArchitype, WalkerArchitype
14
+ from jaclang.runtimelib.architype import (
15
+ Architype,
16
+ EdgeArchitype,
17
+ NodeArchitype,
18
+ WalkerArchitype,
19
+ )
15
20
  from jaclang.utils.log import logging
16
21
 
17
22
 
@@ -55,11 +60,12 @@ class JacMachine:
55
60
  full_target: str,
56
61
  caller_dir: str,
57
62
  cachable: bool = True,
63
+ reload: bool = False,
58
64
  ) -> Optional[types.CodeType]:
59
65
  """Retrieve bytecode from the attached JacProgram."""
60
66
  if self.jac_program:
61
67
  return self.jac_program.get_bytecode(
62
- module_name, full_target, caller_dir, cachable
68
+ module_name, full_target, caller_dir, cachable, reload=reload
63
69
  )
64
70
  return None
65
71
 
@@ -105,6 +111,87 @@ class JacMachine:
105
111
  return nodes
106
112
  return []
107
113
 
114
+ def update_walker(
115
+ self, module_name: str, items: Optional[dict[str, Union[str, Optional[str]]]]
116
+ ) -> tuple[types.ModuleType, ...]:
117
+ """Reimport the module."""
118
+ from .importer import JacImporter, ImportPathSpec
119
+
120
+ if module_name in self.loaded_modules:
121
+ try:
122
+ old_module = self.loaded_modules[module_name]
123
+ importer = JacImporter(self)
124
+ spec = ImportPathSpec(
125
+ target=module_name,
126
+ base_path=self.base_path,
127
+ absorb=False,
128
+ cachable=True,
129
+ mdl_alias=None,
130
+ override_name=None,
131
+ lng="jac",
132
+ items=items,
133
+ )
134
+ import_result = importer.run_import(spec, reload=True)
135
+ ret_items = []
136
+ if items:
137
+ for item_name in items:
138
+ if hasattr(old_module, item_name):
139
+ new_attr = getattr(import_result.ret_mod, item_name, None)
140
+ if new_attr:
141
+ ret_items.append(new_attr)
142
+ setattr(
143
+ old_module,
144
+ item_name,
145
+ new_attr,
146
+ )
147
+ return (old_module,) if not items else tuple(ret_items)
148
+ except Exception as e:
149
+ logger.error(f"Failed to update module {module_name}: {e}")
150
+ else:
151
+ logger.warning(f"Module {module_name} not found in loaded modules.")
152
+ return ()
153
+
154
+ def spawn_node(
155
+ self,
156
+ node_name: str,
157
+ attributes: Optional[dict] = None,
158
+ module_name: str = "__main__",
159
+ ) -> NodeArchitype:
160
+ """Spawn a node instance of the given node_name with attributes."""
161
+ node_class = self.get_architype(module_name, node_name)
162
+ if isinstance(node_class, type) and issubclass(node_class, NodeArchitype):
163
+ if attributes is None:
164
+ attributes = {}
165
+ node_instance = node_class(**attributes)
166
+ return node_instance
167
+ else:
168
+ raise ValueError(f"Node {node_name} not found.")
169
+
170
+ def spawn_walker(
171
+ self,
172
+ walker_name: str,
173
+ attributes: Optional[dict] = None,
174
+ module_name: str = "__main__",
175
+ ) -> WalkerArchitype:
176
+ """Spawn a walker instance of the given walker_name."""
177
+ walker_class = self.get_architype(module_name, walker_name)
178
+ if isinstance(walker_class, type) and issubclass(walker_class, WalkerArchitype):
179
+ if attributes is None:
180
+ attributes = {}
181
+ walker_instance = walker_class(**attributes)
182
+ return walker_instance
183
+ else:
184
+ raise ValueError(f"Walker {walker_name} not found.")
185
+
186
+ def get_architype(
187
+ self, module_name: str, architype_name: str
188
+ ) -> Optional[Architype]:
189
+ """Retrieve an architype class from a module."""
190
+ module = self.loaded_modules.get(module_name)
191
+ if module:
192
+ return getattr(module, architype_name, None)
193
+ return None
194
+
108
195
  @staticmethod
109
196
  def get(base_path: str = "") -> "JacMachine":
110
197
  """Get current jac machine."""
@@ -134,6 +221,7 @@ class JacProgram:
134
221
  full_target: str,
135
222
  caller_dir: str,
136
223
  cachable: bool = True,
224
+ reload: bool = False,
137
225
  ) -> Optional[types.CodeType]:
138
226
  """Get the bytecode for a specific module."""
139
227
  if self.mod_bundle and isinstance(self.mod_bundle, Module):
@@ -141,7 +229,7 @@ class JacProgram:
141
229
  return marshal.loads(codeobj) if isinstance(codeobj, bytes) else None
142
230
  gen_dir = os.path.join(caller_dir, Con.JAC_GEN_DIR)
143
231
  pyc_file_path = os.path.join(gen_dir, module_name + ".jbc")
144
- if cachable and os.path.exists(pyc_file_path):
232
+ if cachable and os.path.exists(pyc_file_path) and not reload:
145
233
  with open(pyc_file_path, "rb") as f:
146
234
  return marshal.load(f)
147
235
 
@@ -106,7 +106,7 @@ class ShelfStorage(Memory[UUID, Anchor]):
106
106
  if root.has_write_access(d):
107
107
  if hash(dumps(p_d.access)) != hash(dumps(d.access)):
108
108
  p_d.access = d.access
109
- if hash(dumps(d.architype)) != hash(dumps(d.architype)):
109
+ if hash(dumps(p_d.architype)) != hash(dumps(d.architype)):
110
110
  p_d.architype = d.architype
111
111
 
112
112
  self.__shelf__[_id] = p_d
jaclang/settings.py CHANGED
@@ -17,6 +17,10 @@ class Settings:
17
17
  collect_py_dep_debug: bool = False
18
18
  print_py_raised_ast: bool = False
19
19
 
20
+ # Compiler configuration
21
+ disable_mtllm: bool = False
22
+ ignore_test_annex: bool = False
23
+
20
24
  # Formatter configuration
21
25
  max_line_length: int = 88
22
26
 
@@ -31,4 +31,4 @@ walker bar_walk {
31
31
  disengage;
32
32
  }
33
33
  }
34
- }
34
+ }
@@ -0,0 +1,16 @@
1
+ with entry {
2
+ a: list[str] = [];
3
+ a.append("str1");
4
+ a.append("str2");
5
+ a.pop();
6
+ a.pop();
7
+
8
+ str(6).count("6");
9
+ int("5");
10
+
11
+ b: dict[str, list[int]] = {"a": [2, 3, 4]};
12
+ b.keys();
13
+ b["a"].append(9);
14
+
15
+ dir(a);
16
+ }
@@ -0,0 +1,34 @@
1
+ import:py from jaclang.runtimelib.machine {JacMachine}
2
+ import:jac from bar {Item}
3
+
4
+ node test_node {
5
+ has value:int;
6
+ }
7
+
8
+ walker test_walker {
9
+ can visit_nodes with `root entry {
10
+ visit [-->];
11
+ }
12
+
13
+ can print_value with test_node | Item entry {
14
+ print("Value:", f'{here.value}');
15
+ }
16
+ }
17
+
18
+ walker child_walker :test_walker: {}
19
+
20
+ with entry {
21
+ for value in range(1, 4) {
22
+ root ++> test_node(value=value);
23
+ root ++> Item(value=value);
24
+ }
25
+ node_obj = JacMachine.get().spawn_node(node_name='test_node', attributes={'value': 0}, module_name='__main__');
26
+ walker_obj = JacMachine.get().spawn_walker(walker_name='child_walker', module_name='__main__');
27
+ external_node = JacMachine.get().spawn_node(node_name='Item', attributes={'value': 0}, module_name='bar');
28
+ root ++> external_node;
29
+ root ++> node_obj;
30
+ print("Spawned Node:", node_obj);
31
+ print("Spawned Walker:", walker_obj);
32
+ print("Spawned External node:", external_node);
33
+ root spawn walker_obj;
34
+ }
@@ -0,0 +1,36 @@
1
+ node test_node {
2
+ has value: int;
3
+ }
4
+
5
+ walker test_walker {
6
+ has visited_nodes: list = [];
7
+ has entry_count: int = 0;
8
+ has exit_count: int = 0;
9
+
10
+ can traverse with `root entry {
11
+ visit [-->](`?test_node);
12
+ }
13
+
14
+ can log_entry with entry {
15
+ print("Entering at the beginning of walker: ",here);
16
+ self.entry_count += 1;
17
+ }
18
+
19
+ can log_visit with test_node exit {
20
+ print("Visiting node : ", here);
21
+ self.visited_nodes.append(here);
22
+ }
23
+
24
+ can log_exit with exit {
25
+ print("Exiting at the end of walker: ",here);
26
+ self.exit_count += 1;
27
+ }
28
+ }
29
+
30
+ with entry {
31
+ for i in range(10) {
32
+ root ++> (next:=test_node(value=i));
33
+ }
34
+ wlk_obj = root spawn test_walker();
35
+ print(wlk_obj);
36
+ }
@@ -1,4 +1,3 @@
1
- import:py from jaclang.plugin.feature, JacFeature as Jac;
2
1
  import:py from jaclang.runtimelib.machine, JacMachine;
3
2
  import:jac from bar, bar_walk;
4
3
  # Test runner to initialize the walker
@@ -0,0 +1,12 @@
1
+ with entry{
2
+ Num =10;
3
+ match Num{
4
+ case 2:
5
+ print("Two");
6
+ case 10:
7
+ print("Ten");
8
+ print("ten");
9
+ case _:
10
+ print("nothing");
11
+ }
12
+ }
@@ -0,0 +1,88 @@
1
+ """
2
+ This test file is to ensure the valid syntax of jac lang.
3
+ Add new jac syntax here to test if it compile without any issue.
4
+ """
5
+
6
+
7
+ # Import statement without trailing comma.
8
+ import:py from time { sleep, timezone, tzname }
9
+ # Import statement with trailing comma.
10
+ import:py from os { path, getenv, getpid, }
11
+
12
+ enum WithoutTrailComma {
13
+ FOO = "FOO",
14
+ BAR = "BAR"
15
+ }
16
+
17
+ enum WithTrailComma {
18
+ FOO = "FOO",
19
+ BAR = "BAR",
20
+ }
21
+
22
+ can without_trail_comma(a: int, b: int) {}
23
+
24
+ can with_trail_comma(a: int, b: int, c: int, ) {}
25
+
26
+ with entry {
27
+
28
+ dict_without_trail_comma = {"key": "value"};
29
+ dict_with_trail_comma = {"key": "val",};
30
+
31
+ list_without_trail_comma = ["foo", "bar"];
32
+ list_with_trail_comma = ["foo", "bar",];
33
+
34
+ set_without_trail_comma = {"foo", "bar"};
35
+ set_with_trail_comma = {"foo", "bar"};
36
+ obj foo11 {
37
+ has val: int,
38
+ val2: int = 9,
39
+ val3: int = 8,
40
+ val4: int = 8,
41
+ val5: int = 8;
42
+ }
43
+ empty_tuple = ();
44
+ single_tuple = ('single', );
45
+
46
+ tuple_without_trail_comma = ("foo", "bar");
47
+ tuple_with_trail_comma = ("foo", "bar", );
48
+
49
+ mixed_tuple = (1, 'two', 3.0, False);
50
+ mixed_tuple_with_trail_comma = (1, 'two', 3.0, False, );
51
+
52
+ nested_tuple = (1, (2, 3), 'four');
53
+ nested_tuple_with_trail_comma = (1, (2, 3), 'four', );
54
+
55
+ deeply_nested_tuple = (1, (2, (3, (4, 5))));
56
+ deeply_nested_tuple_with_trail_comma = (1, (2, (3, (4, 5))), );
57
+
58
+ tuple1 = ("foo", );
59
+ tuple1_2 = ("foo", "bar", "baz");
60
+ tuple_2_2 = ("foo", "bar", "baz", );
61
+
62
+ foo_instance1 = foo11(val=90);
63
+ foo_instance1_2 = foo11(val=90, );
64
+
65
+ foo_instance3 = foo11(2, 34, val3=90);
66
+ foo_instance3_2 = foo11(2, 34, val3=90, );
67
+
68
+ foo_instance4 = foo11(2, 34, val3=90, val4=90);
69
+ foo_instance4_2 = foo11(2, 34, val3=90, val4=90, );
70
+
71
+ func_tuple = (foo_instance1, foo_instance3_2, len(tuple1_2));
72
+ func_tuple_with_trail_comma = (foo_instance1, foo_instance3_2, len(tuple1_2), );
73
+
74
+ unpack_tuple = (1, 2, 3);
75
+ (a, b, c, ) = unpack_tuple;
76
+ values = (a, b, c);
77
+
78
+ (1, 2);
79
+ (1, 2, );
80
+ (1, 2, 3, 4);
81
+ (1, 2, 3, 4, );
82
+
83
+ val_f = (foo_instance3_2.val, foo_instance3_2.val2, foo_instance3_2.val3);
84
+ expression_tuple = (1 + 2, len("abc"), foo_instance1.val * 2);
85
+ tuple_with_list = (1, [2, 3], 4);
86
+ print("Code compiled and ran successfully!");
87
+
88
+ }
@@ -0,0 +1,19 @@
1
+ import:jac from bar { bar_walk }
2
+ import:py from jaclang.runtimelib.machine { JacMachine }
3
+ import:py os;
4
+
5
+ can update_bar_walker {
6
+ "Updating bar.jac with new behavior." |> print;
7
+ (bar_walk_new, ) = JacMachine.get().update_walker(
8
+ "bar",
9
+ items={'bar_walk': None}
10
+ );
11
+ "Running bar_walk after update..." |> print;
12
+ root spawn bar_walk_new();
13
+ print(f"bar_walk: {bar_walk_new.__dict__}");
14
+ }
15
+
16
+
17
+ with entry {
18
+ update_bar_walker();
19
+ }
jaclang/tests/test_cli.py CHANGED
@@ -190,6 +190,33 @@ class JacCliTests(TestCase):
190
190
  r"8\:37 \- 8:44.*ModuleItem - display - abs_path\:.*fixtures/pygame_mock/display.py",
191
191
  )
192
192
 
193
+ def test_builtins_loading(self) -> None:
194
+ """Testing for print AstTool."""
195
+ from jaclang.settings import settings
196
+
197
+ settings.ast_symbol_info_detailed = True
198
+ captured_output = io.StringIO()
199
+ sys.stdout = captured_output
200
+
201
+ cli.tool("ir", ["ast", f"{self.fixture_abs_path('builtins_test.jac')}"])
202
+
203
+ sys.stdout = sys.__stdout__
204
+ stdout_value = captured_output.getvalue()
205
+ settings.ast_symbol_info_detailed = False
206
+
207
+ self.assertRegex(
208
+ stdout_value,
209
+ r"2\:8 \- 2\:12.*BuiltinType - list - .*SymbolPath: builtins_test.builtins.list",
210
+ )
211
+ self.assertRegex(
212
+ stdout_value,
213
+ r"15\:5 \- 15\:8.*Name - dir - .*SymbolPath: builtins_test.builtins.dir",
214
+ )
215
+ self.assertRegex(
216
+ stdout_value,
217
+ r"13\:12 \- 13\:18.*Name - append - .*SymbolPath: builtins_test.builtins.list.append",
218
+ )
219
+
193
220
  def test_ast_dotgen(self) -> None:
194
221
  """Testing for print AstTool."""
195
222
  captured_output = io.StringIO()
@@ -218,8 +245,8 @@ class JacCliTests(TestCase):
218
245
  sys.stdout = sys.__stdout__
219
246
  stdout_value = captured_output.getvalue()
220
247
  self.assertEqual(stdout_value.count("type_info.ServerWrapper"), 7)
221
- self.assertEqual(stdout_value.count("builtins.int"), 2)
222
- self.assertEqual(stdout_value.count("builtins.str"), 7)
248
+ self.assertEqual(stdout_value.count("builtins.int"), 3)
249
+ self.assertEqual(stdout_value.count("builtins.str"), 10)
223
250
 
224
251
  def test_build_and_run(self) -> None:
225
252
  """Testing for print AstTool."""