jaclang 0.8.0__py3-none-any.whl → 0.8.1__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 (77) hide show
  1. jaclang/cli/cli.py +11 -9
  2. jaclang/compiler/jac.lark +2 -12
  3. jaclang/compiler/larkparse/jac_parser.py +1 -1
  4. jaclang/compiler/parser.py +360 -521
  5. jaclang/compiler/passes/main/cfg_build_pass.py +2 -2
  6. jaclang/compiler/passes/main/def_impl_match_pass.py +14 -13
  7. jaclang/compiler/passes/main/def_use_pass.py +4 -7
  8. jaclang/compiler/passes/main/import_pass.py +3 -3
  9. jaclang/compiler/passes/main/inheritance_pass.py +2 -2
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +196 -218
  11. jaclang/compiler/passes/main/pyast_load_pass.py +115 -311
  12. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +8 -7
  13. jaclang/compiler/passes/main/sym_tab_build_pass.py +3 -3
  14. jaclang/compiler/passes/main/sym_tab_link_pass.py +4 -4
  15. jaclang/compiler/passes/main/tests/fixtures/symtab_link_tests/action/actions.jac +1 -5
  16. jaclang/compiler/passes/main/tests/fixtures/symtab_link_tests/main.jac +1 -8
  17. jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +4 -2
  18. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +197 -120
  19. jaclang/compiler/program.py +2 -7
  20. jaclang/compiler/tests/fixtures/fam.jac +2 -2
  21. jaclang/compiler/tests/fixtures/pkg_import_lib/__init__.jac +1 -0
  22. jaclang/compiler/tests/fixtures/pkg_import_lib/sub/__init__.jac +1 -0
  23. jaclang/compiler/tests/fixtures/pkg_import_lib/sub/helper.jac +3 -0
  24. jaclang/compiler/tests/fixtures/pkg_import_lib/tools.jac +3 -0
  25. jaclang/compiler/tests/fixtures/pkg_import_lib_py/__init__.py +11 -0
  26. jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/__init__.py +7 -0
  27. jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/helper.jac +3 -0
  28. jaclang/compiler/tests/fixtures/pkg_import_lib_py/tools.jac +3 -0
  29. jaclang/compiler/tests/fixtures/pkg_import_main.jac +10 -0
  30. jaclang/compiler/tests/fixtures/pkg_import_main_py.jac +11 -0
  31. jaclang/compiler/tests/test_importer.py +20 -0
  32. jaclang/compiler/tests/test_parser.py +1 -0
  33. jaclang/compiler/unitree.py +456 -304
  34. jaclang/langserve/engine.jac +498 -0
  35. jaclang/langserve/sem_manager.jac +309 -0
  36. jaclang/langserve/server.jac +186 -0
  37. jaclang/langserve/tests/server_test/test_lang_serve.py +6 -7
  38. jaclang/langserve/tests/server_test/utils.py +4 -1
  39. jaclang/langserve/tests/session.jac +294 -0
  40. jaclang/langserve/tests/test_sem_tokens.py +2 -2
  41. jaclang/langserve/tests/test_server.py +12 -7
  42. jaclang/langserve/utils.jac +51 -30
  43. jaclang/runtimelib/archetype.py +1 -1
  44. jaclang/runtimelib/builtin.py +17 -14
  45. jaclang/runtimelib/importer.py +26 -8
  46. jaclang/runtimelib/machine.py +96 -55
  47. jaclang/runtimelib/tests/fixtures/traversing_save.jac +7 -5
  48. jaclang/runtimelib/utils.py +3 -3
  49. jaclang/tests/fixtures/backward_edge_visit.jac +31 -0
  50. jaclang/tests/fixtures/builtin_printgraph.jac +85 -0
  51. jaclang/tests/fixtures/builtin_printgraph_json.jac +21 -0
  52. jaclang/tests/fixtures/builtin_printgraph_mermaid.jac +16 -0
  53. jaclang/tests/fixtures/chandra_bugs2.jac +20 -13
  54. jaclang/tests/fixtures/concurrency.jac +1 -1
  55. jaclang/tests/fixtures/edge_ability.jac +49 -0
  56. jaclang/tests/fixtures/guess_game.jac +1 -1
  57. jaclang/tests/fixtures/here_usage_error.jac +21 -0
  58. jaclang/tests/fixtures/here_visitor_usage.jac +21 -0
  59. jaclang/tests/fixtures/node_del.jac +30 -36
  60. jaclang/tests/fixtures/visit_traversal.jac +47 -0
  61. jaclang/tests/test_cli.py +12 -7
  62. jaclang/tests/test_language.py +91 -16
  63. jaclang/utils/helpers.py +14 -6
  64. jaclang/utils/lang_tools.py +2 -3
  65. jaclang/utils/tests/test_lang_tools.py +2 -1
  66. jaclang/utils/treeprinter.py +3 -4
  67. {jaclang-0.8.0.dist-info → jaclang-0.8.1.dist-info}/METADATA +4 -3
  68. {jaclang-0.8.0.dist-info → jaclang-0.8.1.dist-info}/RECORD +71 -55
  69. {jaclang-0.8.0.dist-info → jaclang-0.8.1.dist-info}/WHEEL +1 -1
  70. jaclang/langserve/engine.py +0 -553
  71. jaclang/langserve/sem_manager.py +0 -383
  72. jaclang/langserve/server.py +0 -167
  73. jaclang/langserve/tests/session.py +0 -255
  74. jaclang/tests/fixtures/builtin_dotgen.jac +0 -42
  75. jaclang/tests/fixtures/builtin_dotgen_json.jac +0 -21
  76. /jaclang/langserve/{__init__.py → __init__.jac} +0 -0
  77. {jaclang-0.8.0.dist-info → jaclang-0.8.1.dist-info}/entry_points.txt +0 -0
@@ -329,23 +329,27 @@ class JacWalker:
329
329
  | NodeArchetype
330
330
  | EdgeArchetype
331
331
  ),
332
+ insert_loc: int = -1,
332
333
  ) -> bool: # noqa: ANN401
333
334
  """Jac's visit stmt feature."""
334
335
  if isinstance(walker, WalkerArchetype):
335
336
  """Walker visits node."""
336
337
  wanch = walker.__jac__
337
338
  before_len = len(wanch.next)
339
+ next = []
338
340
  for anchor in (
339
341
  (i.__jac__ for i in expr) if isinstance(expr, list) else [expr.__jac__]
340
342
  ):
341
343
  if anchor not in wanch.ignores:
342
- if isinstance(anchor, NodeAnchor):
343
- wanch.next.append(anchor)
344
- elif isinstance(anchor, EdgeAnchor):
345
- if target := anchor.target:
346
- wanch.next.append(target)
347
- else:
348
- raise ValueError("Edge has no target.")
344
+ if isinstance(anchor, (NodeAnchor, EdgeAnchor)):
345
+ next.append(anchor)
346
+ else:
347
+ raise ValueError("Anchor should be NodeAnchor or EdgeAnchor.")
348
+ if insert_loc < -len(wanch.next): # for out of index selection
349
+ insert_loc = 0
350
+ elif insert_loc < 0:
351
+ insert_loc += len(wanch.next) + 1
352
+ wanch.next = wanch.next[:insert_loc] + next + wanch.next[insert_loc:]
349
353
  return len(wanch.next) > before_len
350
354
  else:
351
355
  raise TypeError("Invalid walker object")
@@ -381,83 +385,91 @@ class JacWalker:
381
385
  raise TypeError("Invalid walker object")
382
386
 
383
387
  @staticmethod
384
- def spawn_call(walker: WalkerAnchor, node: NodeAnchor) -> WalkerArchetype:
388
+ def spawn_call(
389
+ walker: WalkerAnchor,
390
+ node: NodeAnchor | EdgeAnchor,
391
+ ) -> WalkerArchetype:
385
392
  """Jac's spawn operator feature."""
386
393
  warch = walker.archetype
387
394
  walker.path = []
388
- walker.next = [node]
389
- current_node = node.archetype
395
+ current_loc = node.archetype
390
396
 
391
- # walker entry
397
+ # walker ability on any entry
392
398
  for i in warch._jac_entry_funcs_:
393
399
  if not i.trigger:
394
- i.func(warch, current_node)
400
+ i.func(warch, current_loc)
395
401
  if walker.disengaged:
396
402
  return warch
397
403
 
398
404
  while len(walker.next):
399
- if current_node := walker.next.pop(0).archetype:
400
- # walker entry with
405
+ if current_loc := walker.next.pop(0).archetype:
406
+ # walker ability with loc entry
401
407
  for i in warch._jac_entry_funcs_:
402
408
  if (
403
409
  i.trigger
404
- and all_issubclass(i.trigger, NodeArchetype)
405
- and isinstance(current_node, i.trigger)
410
+ and (
411
+ all_issubclass(i.trigger, NodeArchetype)
412
+ or all_issubclass(i.trigger, EdgeArchetype)
413
+ )
414
+ and isinstance(current_loc, i.trigger)
406
415
  ):
407
- i.func(warch, current_node)
416
+ i.func(warch, current_loc)
408
417
  if walker.disengaged:
409
418
  return warch
410
419
 
411
- # node entry
412
- for i in current_node._jac_entry_funcs_:
420
+ # loc ability with any entry
421
+ for i in current_loc._jac_entry_funcs_:
413
422
  if not i.trigger:
414
- i.func(current_node, warch)
423
+ i.func(current_loc, warch)
415
424
  if walker.disengaged:
416
425
  return warch
417
426
 
418
- # node entry with
419
- for i in current_node._jac_entry_funcs_:
427
+ # loc ability with walker entry
428
+ for i in current_loc._jac_entry_funcs_:
420
429
  if (
421
430
  i.trigger
422
431
  and all_issubclass(i.trigger, WalkerArchetype)
423
432
  and isinstance(warch, i.trigger)
424
433
  ):
425
- i.func(current_node, warch)
434
+ i.func(current_loc, warch)
426
435
  if walker.disengaged:
427
436
  return warch
428
437
 
429
- # node exit with
430
- for i in current_node._jac_exit_funcs_:
438
+ # loc ability with walker exit
439
+ for i in current_loc._jac_exit_funcs_:
431
440
  if (
432
441
  i.trigger
433
442
  and all_issubclass(i.trigger, WalkerArchetype)
434
443
  and isinstance(warch, i.trigger)
435
444
  ):
436
- i.func(current_node, warch)
445
+ i.func(current_loc, warch)
437
446
  if walker.disengaged:
438
447
  return warch
439
448
 
440
- # node exit
441
- for i in current_node._jac_exit_funcs_:
449
+ # loc ability with any exit
450
+ for i in current_loc._jac_exit_funcs_:
442
451
  if not i.trigger:
443
- i.func(current_node, warch)
452
+ i.func(current_loc, warch)
444
453
  if walker.disengaged:
445
454
  return warch
446
455
 
447
- # walker exit with
456
+ # walker ability with loc exit
448
457
  for i in warch._jac_exit_funcs_:
449
458
  if (
450
459
  i.trigger
451
- and all_issubclass(i.trigger, NodeArchetype)
452
- and isinstance(current_node, i.trigger)
460
+ and (
461
+ all_issubclass(i.trigger, NodeArchetype)
462
+ or all_issubclass(i.trigger, EdgeArchetype)
463
+ )
464
+ and isinstance(current_loc, i.trigger)
453
465
  ):
454
- i.func(warch, current_node)
466
+ i.func(warch, current_loc)
455
467
  if walker.disengaged:
456
468
  return warch
457
- # walker exit
469
+ # walker ability with any exit
458
470
  for i in warch._jac_exit_funcs_:
459
471
  if not i.trigger:
460
- i.func(warch, current_node)
472
+ i.func(warch, current_loc)
461
473
  if walker.disengaged:
462
474
  return warch
463
475
 
@@ -467,12 +479,14 @@ class JacWalker:
467
479
  @staticmethod
468
480
  def spawn(op1: Archetype, op2: Archetype) -> WalkerArchetype | asyncio.Future:
469
481
  """Jac's spawn operator feature."""
482
+ edge: EdgeAnchor | None = None
470
483
  if isinstance(op1, WalkerArchetype):
471
484
  warch = op1
472
485
  walker = op1.__jac__
473
486
  if isinstance(op2, NodeArchetype):
474
487
  node = op2.__jac__
475
488
  elif isinstance(op2, EdgeArchetype):
489
+ edge = op2.__jac__
476
490
  node = op2.__jac__.target
477
491
  else:
478
492
  raise TypeError("Invalid target object")
@@ -482,21 +496,29 @@ class JacWalker:
482
496
  if isinstance(op1, NodeArchetype):
483
497
  node = op1.__jac__
484
498
  elif isinstance(op1, EdgeArchetype):
499
+ edge = op1.__jac__
485
500
  node = op1.__jac__.target
486
501
  else:
487
502
  raise TypeError("Invalid target object")
488
503
  else:
489
504
  raise TypeError("Invalid walker object")
490
505
 
506
+ if edge is not None:
507
+ loc: EdgeAnchor | NodeAnchor = edge
508
+ walker.next = [edge, node]
509
+ else:
510
+ loc = node
511
+ walker.next = [node]
512
+
491
513
  if warch.__jac_async__:
492
514
  machine = JacMachineInterface.py_get_jac_machine()
493
515
  _event_loop = machine._event_loop
494
- func = partial(JacMachineInterface.spawn_call, *(walker, node))
516
+ func = partial(JacMachineInterface.spawn_call, *(walker, loc))
495
517
  return asyncio.ensure_future(
496
518
  _event_loop.run_in_executor(None, func), loop=_event_loop
497
519
  )
498
520
  else:
499
- return JacMachineInterface.spawn_call(walker=walker, node=node)
521
+ return JacMachineInterface.spawn_call(walker=walker, node=loc)
500
522
 
501
523
  @staticmethod
502
524
  def disengage(walker: WalkerArchetype) -> bool:
@@ -525,7 +547,7 @@ class JacBuiltin:
525
547
  """Jac Builtins."""
526
548
 
527
549
  @staticmethod
528
- def dotgen(
550
+ def printgraph(
529
551
  node: NodeArchetype,
530
552
  depth: int,
531
553
  traverse: bool,
@@ -533,9 +555,10 @@ class JacBuiltin:
533
555
  bfs: bool,
534
556
  edge_limit: int,
535
557
  node_limit: int,
536
- dot_file: Optional[str],
558
+ file: Optional[str],
559
+ format: str,
537
560
  ) -> str:
538
- """Generate Dot file for visualizing nodes and edges."""
561
+ """Generate graph for visualizing nodes and edges."""
539
562
  edge_type = edge_type if edge_type else []
540
563
  visited_nodes: list[NodeArchetype] = []
541
564
  node_depths: dict[NodeArchetype, int] = {node: 0}
@@ -589,24 +612,32 @@ class JacBuiltin:
589
612
  'digraph {\nnode [style="filled", shape="ellipse", '
590
613
  'fillcolor="invis", fontcolor="black"];\n'
591
614
  )
615
+ mermaid_content = "flowchart LR\n"
592
616
  for source, target, edge in connections:
593
617
  edge_label = html.escape(str(edge.__jac__.archetype))
594
618
  dot_content += (
595
619
  f"{visited_nodes.index(source)} -> {visited_nodes.index(target)} "
596
620
  f' [label="{edge_label if "GenericEdge" not in edge_label else ""}"];\n'
597
621
  )
622
+ mermaid_content += (
623
+ f"{visited_nodes.index(source)} -->"
624
+ f"|{edge_label if 'GenericEdge' not in edge_label else ''}| {visited_nodes.index(target)}\n"
625
+ )
598
626
  for node_ in visited_nodes:
599
627
  color = (
600
628
  colors[node_depths[node_]] if node_depths[node_] < 25 else colors[24]
601
629
  )
630
+ label = html.escape(str(node_.__jac__.archetype))
602
631
  dot_content += (
603
- f'{visited_nodes.index(node_)} [label="{html.escape(str(node_.__jac__.archetype))}"'
632
+ f'{visited_nodes.index(node_)} [label="{label}"'
604
633
  f'fillcolor="{color}"];\n'
605
634
  )
606
- if dot_file:
607
- with open(dot_file, "w") as f:
608
- f.write(dot_content + "}")
609
- return dot_content + "}"
635
+ mermaid_content += f'{visited_nodes.index(node_)}["{label}"]\n'
636
+ output = dot_content + "}" if format == "dot" else mermaid_content
637
+ if file:
638
+ with open(file, "w") as f:
639
+ f.write(output)
640
+ return output
610
641
 
611
642
 
612
643
  class JacCmd:
@@ -803,7 +834,7 @@ class JacBasics:
803
834
  items,
804
835
  )
805
836
 
806
- if not mach.jac_program:
837
+ if not mach.program:
807
838
  JacMachineInterface.attach_program(mach, JacProgram())
808
839
 
809
840
  if lng == "py":
@@ -924,7 +955,10 @@ class JacBasics:
924
955
  dir: EdgeDir = EdgeDir.OUT,
925
956
  filter: Callable[[EdgeArchetype], bool] | None = None,
926
957
  edges_only: bool = False,
927
- ) -> list[NodeArchetype] | list[EdgeArchetype]:
958
+ from_visit: bool = False,
959
+ ) -> (
960
+ list[NodeArchetype] | list[EdgeArchetype] | list[NodeArchetype | EdgeArchetype]
961
+ ):
928
962
  """Jac's apply_dir stmt feature."""
929
963
  if isinstance(sources, NodeArchetype):
930
964
  sources = [sources]
@@ -934,14 +968,23 @@ class JacBasics:
934
968
  else targets if targets else None
935
969
  )
936
970
  if edges_only:
937
- connected_edges: list[EdgeArchetype] = []
971
+ connected_edges: list[EdgeArchetype | NodeArchetype] = []
938
972
  for node in sources:
939
973
  edges = JacMachineInterface.get_edges(
940
974
  node.__jac__, dir, filter, target_obj=targ_obj_set
941
975
  )
942
- connected_edges.extend(
943
- edge for edge in edges if edge not in connected_edges
944
- )
976
+ for edge in edges:
977
+ assert isinstance(edge, EdgeArchetype)
978
+ if edge in connected_edges:
979
+ continue
980
+ if from_visit:
981
+ connected_edges.append(edge)
982
+ if dir == EdgeDir.IN:
983
+ connected_edges.append(edge.__jac__.source.archetype)
984
+ else:
985
+ connected_edges.append(edge.__jac__.target.archetype)
986
+ else:
987
+ connected_edges.append(edge)
945
988
  return connected_edges
946
989
  else:
947
990
  connected_nodes: list[NodeArchetype] = []
@@ -1310,7 +1353,7 @@ class JacUtils:
1310
1353
  @staticmethod
1311
1354
  def attach_program(mach: JacMachine, jac_program: JacProgram) -> None:
1312
1355
  """Attach a JacProgram to the machine."""
1313
- mach.jac_program = jac_program
1356
+ mach.program = jac_program
1314
1357
 
1315
1358
  @staticmethod
1316
1359
  def load_module(
@@ -1545,7 +1588,6 @@ class JacMachine(JacMachineInterface):
1545
1588
  base_path: str = "",
1546
1589
  session: Optional[str] = None,
1547
1590
  root: Optional[str] = None,
1548
- interp_mode: bool = False,
1549
1591
  ) -> None:
1550
1592
  """Initialize JacMachine."""
1551
1593
  self.loaded_modules: dict[str, types.ModuleType] = {}
@@ -1558,8 +1600,7 @@ class JacMachine(JacMachineInterface):
1558
1600
  if not os.path.isdir(base_path)
1559
1601
  else os.path.abspath(base_path)
1560
1602
  )
1561
- self.jac_program: JacProgram = JacProgram()
1562
- self.interp_mode = interp_mode
1603
+ self.program: JacProgram = JacProgram()
1563
1604
  self.pool = ThreadPoolExecutor()
1564
1605
  self._event_loop = asyncio.new_event_loop()
1565
1606
  self.mem: Memory = ShelfStorage(session)
@@ -1,17 +1,19 @@
1
1
  node A {}
2
2
  node B {}
3
3
 
4
+
4
5
  walker build {
5
6
  can run with `root entry {
6
7
  a = A();
7
- a ++> B(); # connecting two non persistent nodes
8
-
9
- here ++> a;
8
+ a ++> B();
9
+ # connecting two non persistent nodes
10
+ here ++> a;
10
11
  }
11
12
  }
12
13
 
14
+
13
15
  walker view {
14
16
  can run with `root entry {
15
- print(dotgen(here));
17
+ print(printgraph(here));
16
18
  }
17
- }
19
+ }
@@ -133,7 +133,7 @@ def extract_params(
133
133
  include_info = []
134
134
  exclude_info = []
135
135
  if body.params:
136
- for param in body.params.items:
136
+ for param in body.params:
137
137
  if isinstance(param, uni.KWPair) and isinstance(param.key, uni.Name):
138
138
  key = param.key.value
139
139
  value = param.value
@@ -153,7 +153,7 @@ def extract_params(
153
153
  )
154
154
  include_info.append((var_name, value.gen.py_ast[0]))
155
155
  elif isinstance(value, uni.TupleVal) and value.values:
156
- for i in value.values.items:
156
+ for i in value.values:
157
157
  var_name = (
158
158
  i.right.value
159
159
  if isinstance(i, uni.AtomTrailer)
@@ -175,7 +175,7 @@ def extract_params(
175
175
  )
176
176
  exclude_info.append((var_name, value.gen.py_ast[0]))
177
177
  elif isinstance(value, uni.TupleVal) and value.values:
178
- for i in value.values.items:
178
+ for i in value.values:
179
179
  var_name = (
180
180
  i.right.value
181
181
  if isinstance(i, uni.AtomTrailer)
@@ -0,0 +1,31 @@
1
+ node MyNode{
2
+ has val:int;
3
+
4
+ can do with MyWalker entry {
5
+ print( visitor,"from node", self);
6
+ }
7
+ }
8
+
9
+ edge MyEdge {
10
+ has path:int;
11
+
12
+ can do with MyWalker entry {
13
+ print(visitor,"from edge",self);
14
+ }
15
+ }
16
+
17
+ walker MyWalker {
18
+ can does with MyNode entry {
19
+ visit [edge <--];
20
+ }
21
+ }
22
+
23
+ with entry {
24
+ n0 = MyNode(0);
25
+ n1 = MyNode(10);
26
+ root +>:MyEdge(0):+> n0 <+:MyEdge(1):<+ n1;
27
+ n1 <+:MyEdge(2):<+ MyNode(20);
28
+ n1 <+:MyEdge(3):<+ MyNode(30);
29
+ n1 <+:MyEdge(4):<+ MyNode(40);
30
+ MyWalker() spawn n0;
31
+ }
@@ -0,0 +1,85 @@
1
+ node a {
2
+ has val: int;
3
+ }
4
+
5
+
6
+ edge Edge1 {
7
+ has val: int = 5;
8
+ }
9
+
10
+
11
+ with entry {
12
+ end = root;
13
+ for i in range(0, 4) {
14
+ end ++> (end := [ a(val=i) for i in range(0, 3) ]);
15
+ }
16
+ x = [ a(val=i) for i in range(0, 3) ];
17
+ end = x[1];
18
+ for i in range(0, 8) {
19
+ locals()[chr(ord('b') + i)] = (values := [ a(val=j * i + 5.2 * i + 6) for j in range(0, 3) ]);
20
+ end ++> (end := values);
21
+ }
22
+ p = b[1];
23
+ for k in range(0, 10) {
24
+ p +>: Edge1 : val=6 :+> (p := a(val=k));
25
+ }
26
+ # b++>c;
27
+ # c++>b;
28
+ d1 = printgraph();
29
+ l1 = d1 |> len;
30
+ #generate dot for all connected with root
31
+ # d2=printgraph(b[1],Traverse=True,depth=20,bfs=False,node_limit=12);l2=d2|>len; #generate dot for all connected with root
32
+ d2 = printgraph(
33
+ b[1],
34
+ edge_type=["Edge1"],
35
+ depth=20,
36
+ traverse=True,
37
+ bfs=False,
38
+ node_limit=19
39
+ );
40
+ l2 = d2 |> len;
41
+ #generate dot for all connected with root
42
+ d3 = printgraph(b[2], edge_limit=5, depth=5);
43
+ l3 = d3 |> len;
44
+ #generate dot for all connected with b[1] node
45
+ d4 = printgraph(
46
+ b[1],
47
+ bfs=True,
48
+ edge_type=["Edge1"],
49
+ node_limit=100,
50
+ edge_limit=900,
51
+ depth=300
52
+ );
53
+ l4 = d4 |> len;
54
+ #generate dot from nodes with depth 3 connected with b[1] node
55
+ d5 = printgraph(b[1], node_limit=10, edge_limit=90);
56
+ l5 := d5 |> len;
57
+ #generate dot from nodes with depth 3 connected with b[1] node
58
+ print(
59
+ d1.count('a(val') == 12,
60
+ d1.count('#FFFFE0') == 3,
61
+ 'Root' in d1,
62
+ d1.count('label=""') == 30
63
+ );
64
+ print(
65
+ d2.count('a(val') == 19,
66
+ d2.count('#F5E5FF') == 2,
67
+ 'Edge1' not in d2,
68
+ d2.count('label=""') == 42
69
+ );
70
+ print(d3.count('a(val') == 6, d3.count('label=""') == 5, d3.count('#F5E5FF') == 1);
71
+ print(d4.count("a(val") == 25, d4.count('label=""') == 66, d4.count('#FFF0F') == 3);
72
+ print(d5.count("Edge1(val=6)") == 2, d5.count('label=""') == 24);
73
+ # print(l3<l2);
74
+
75
+ # print(d1);
76
+
77
+ # print(d2);
78
+
79
+ # print(d3);
80
+
81
+ # print(d4);
82
+
83
+ # print(printgraph(node=b[2],bfs=True,depth=3.96,edge_limit=12,node_limit=12.96));
84
+
85
+ }
@@ -0,0 +1,21 @@
1
+ import json;
2
+
3
+
4
+ node N {
5
+ has val: int;
6
+ }
7
+
8
+
9
+ edge E {
10
+ has val: int = 0;
11
+ }
12
+
13
+
14
+ with entry {
15
+ end = root;
16
+ for i in range(0, 2) {
17
+ end +>: E : val=i :+> (end := [ N(val=i) for i in range(0, 2) ]);
18
+ }
19
+ data = printgraph(node=root, format="json");
20
+ print(data);
21
+ }
@@ -0,0 +1,16 @@
1
+ node N {
2
+ has val: int;
3
+ }
4
+
5
+ edge E {
6
+ has val: int = 0;
7
+ }
8
+
9
+ with entry {
10
+ end = root;
11
+ for i in range(0, 2) {
12
+ end +>: E : val=i :+> (end := [ N(val=i) for i in range(0, 2) ]);
13
+ }
14
+ data = printgraph(node=root, format="mermaid");
15
+ print(data);
16
+ }
@@ -1,27 +1,34 @@
1
1
  import re;
2
2
 
3
- glob a: int = 5;
3
+
4
+ glob a : int = 5;
5
+
4
6
 
5
7
  with entry {
6
- arguments = {x: None for x in re.findall(
7
- r'\{([A-Za-z0-9_]+)\}',
8
- "Apple {apple} pineapple {pineapple}"
9
- )};
10
- a: int = 5;
8
+ arguments = { x : None for x in re.findall(r'\{([A-Za-z0-9_]+)\}', "Apple {apple} pineapple {pineapple}") };
9
+ a : int = 5;
11
10
  if False {
12
- with open(f"Apple{apple}.txt") as f { # Fix syntax highlighting
13
-
14
- print(f.read());
11
+ with open(f"Apple{apple}.txt") as f {
12
+ # Fix syntax highlighting
13
+ print(
14
+ f.read()
15
+ );
15
16
  }
16
17
  }
17
18
  print(arguments);
18
- print("""This is a long
19
- line of code.""");
19
+ print(
20
+ """This is a long
21
+ line of code."""
22
+ );
20
23
  }
21
24
 
25
+
22
26
  with entry {
23
- a = {"a": "apple", "b": "ball", "c": "cat"};
24
- y = {**a, "d": "dog", "e": "elephant"};
27
+ a = {"a" : "apple" , "b" : "ball" , "c" : "cat" };
28
+ y = {** a , "d" : "dog" , "e" : "elephant" };
25
29
  print(y);
26
30
  }
31
+
32
+
27
33
  # Use before def error would be nice
34
+
@@ -6,7 +6,7 @@ node A {
6
6
  can do with entry {
7
7
  print("Started");
8
8
  sleep(2);
9
- print(here);
9
+ print(visitor);
10
10
 
11
11
  }
12
12
  }
@@ -0,0 +1,49 @@
1
+ node MyNode {
2
+ has val:int;
3
+
4
+ can ability1 with MyWalker entry {
5
+ print("MyWalker from node",visitor);
6
+ }
7
+
8
+ can ability2 with MyWalker exit {
9
+ print("MyWalker from node",visitor);
10
+ }
11
+ }
12
+
13
+ edge MyEdge {
14
+ has path:int;
15
+
16
+ can ability3 with MyWalker entry {
17
+ print("MyWalker from edge",visitor);
18
+ }
19
+
20
+ can ability4 with MyWalker exit {
21
+ print("MyWalker from edge",visitor);
22
+ }
23
+ }
24
+
25
+ walker MyWalker {
26
+ can ability5 with MyEdge entry {
27
+ print("MyEdge from walker",here);
28
+ }
29
+
30
+ can ability6 with MyEdge exit {
31
+ print("MyEdge from walker",here);
32
+ }
33
+
34
+ can ability7 with MyNode entry {
35
+ print("MyNode from walker",here);
36
+ visit [edge -->];
37
+ }
38
+
39
+ can ability8 with MyNode exit {
40
+ print("MyNode from walker",here);
41
+ visit [edge -->];
42
+ }
43
+ }
44
+
45
+ with entry {
46
+ e1 = MyEdge(1);
47
+ root +>:e1:+> MyNode(10) +>:MyEdge(2):+> MyNode(20);
48
+ MyWalker() spawn e1;
49
+ }
@@ -17,7 +17,7 @@ node turn {
17
17
 
18
18
  impl turn.check {
19
19
  guess = guesses.pop(0);
20
- guess |> here.process_guess;
20
+ guess |> visitor.process_guess;
21
21
  visit [-->];
22
22
  }
23
23
 
@@ -0,0 +1,21 @@
1
+ node MyNode{
2
+ has val:int;
3
+
4
+ can ability1 with MyWalker entry {
5
+ print("Visitor name is ",here.name);
6
+ }
7
+ }
8
+
9
+ walker MyWalker{
10
+ has name:str;
11
+
12
+ can ability2 with MyNode entry {
13
+ print("Here value is ",here.val);
14
+ }
15
+ }
16
+
17
+ with entry {
18
+ Node1 = MyNode(10);
19
+ Walker1 = MyWalker("Walker 1");
20
+ Walker1 spawn Node1;
21
+ }