@@ -75,6 +75,10 @@ def edge(i: int, j: int) -> KCFG.Edge:
7575 return KCFG .Edge (node (i ), node (j ), 1 , ())
7676
7777
78+ def merged_edge (i : int , j : int , edges : Iterable [KCFG .Edge ]) -> KCFG .MergedEdge :
79+ return KCFG .MergedEdge (node (i ), node (j ), tuple (edges ))
80+
81+
7882def cover (i : int , j : int ) -> KCFG .Cover :
7983 csubst = term (j ).match_with_constraint (term (i ))
8084 assert csubst is not None
@@ -105,6 +109,14 @@ def _make_edge_dict(i: int, j: int, depth: int = 1, rules: tuple[str, ...] = ())
105109 return [_make_edge_dict (* edge ) for edge in edges ]
106110
107111
112+ def merged_edge_dicts (* merged_edges : Iterable ) -> list [dict [str , Any ]]:
113+
114+ def _make_merged_edge_dict (s : int , t : int , * edges : Iterable ) -> dict [str , Any ]:
115+ return {'source' : s , 'target' : t , 'edges' : edge_dicts (* edges )}
116+
117+ return [_make_merged_edge_dict (* merged_edge ) for merged_edge in merged_edges ]
118+
119+
108120def cover_dicts (* edges : tuple [int , int ]) -> list [dict [str , Any ]]:
109121 covers = []
110122 for i , j in edges :
@@ -308,6 +320,7 @@ def test_get_successors() -> None:
308320 'next' : 19 ,
309321 'nodes' : node_dicts (18 ),
310322 'edges' : edge_dicts ((11 , 12 )),
323+ 'merged_edges' : merged_edge_dicts ((17 , 18 , (14 , 15 ))),
311324 'splits' : split_dicts ((12 , [(13 , mlTop ()), (14 , mlTop ())])),
312325 'covers' : cover_dicts ((14 , 11 )),
313326 'ndbranches' : ndbranch_dicts ((13 , [(16 , False ), (17 , False )])),
@@ -316,12 +329,14 @@ def test_get_successors() -> None:
316329
317330 # When
318331 edges = set (cfg .edges (source_id = 11 ))
332+ merged_edges = set (cfg .merged_edges (source_id = 17 ))
319333 covers = set (cfg .covers (source_id = 14 ))
320334 splits = sorted (cfg .splits (source_id = 12 ))
321335 ndbranches = set (cfg .ndbranches (source_id = 13 ))
322336
323337 # Then
324338 assert edges == {edge (11 , 12 )}
339+ assert merged_edges == {merged_edge (17 , 18 , [edge (14 , 15 )])}
325340 assert covers == {cover (14 , 11 )}
326341 assert splits == [split (12 , [13 , 14 ])]
327342 assert ndbranches == {ndbranch (13 , [16 , 17 ])}
@@ -342,8 +357,9 @@ def test_get_predecessors() -> None:
342357def test_reachable_nodes () -> None :
343358 # Given
344359 d = {
345- 'nodes' : node_dicts (20 ),
360+ 'nodes' : node_dicts (21 ),
346361 'edges' : edge_dicts ((13 , 15 ), (14 , 15 ), (15 , 12 )),
362+ 'merged_edges' : merged_edge_dicts ((20 , 21 , (12 , 13 ))),
347363 'covers' : cover_dicts ((12 , 13 )),
348364 'splits' : split_dicts (
349365 (16 , [(12 , mlTop ()), (13 , mlTop ()), (17 , mlTop ())]), (17 , [(12 , mlTop ()), (18 , mlTop ())])
@@ -360,16 +376,17 @@ def test_reachable_nodes() -> None:
360376
361377 # Then
362378 assert nodes_2 == {node (12 ), node (13 ), node (15 )}
363- assert nodes_3 == {node (16 ), node (12 ), node (13 ), node (17 ), node (18 ), node (15 ), node (19 ), node (20 )}
379+ assert nodes_3 == {node (16 ), node (12 ), node (13 ), node (17 ), node (18 ), node (15 ), node (19 ), node (20 ), node ( 21 ) }
364380 assert nodes_4 == {node (13 ), node (16 ), node (12 ), node (15 ), node (17 ), node (14 )}
365381 assert nodes_5 == {node (19 ), node (18 ), node (17 ), node (16 )}
366382
367383
368384def test_paths_between () -> None :
369385 # Given
370386 d = {
371- 'nodes' : node_dicts (20 ),
387+ 'nodes' : node_dicts (21 ),
372388 'edges' : edge_dicts ((13 , 15 ), (14 , 15 ), (15 , 12 )),
389+ 'merged_edges' : merged_edge_dicts ((20 , 21 , (12 , 13 ))),
373390 'covers' : cover_dicts ((12 , 13 )),
374391 'splits' : split_dicts (
375392 (16 , [(12 , mlTop ()), (13 , mlTop ()), (17 , mlTop ())]), (17 , [(12 , mlTop ()), (18 , mlTop ())])
@@ -389,11 +406,11 @@ def test_paths_between() -> None:
389406 ]
390407
391408 # When
392- paths = sorted (cfg .paths_between (17 , 20 ))
409+ paths = sorted (cfg .paths_between (17 , 21 ))
393410
394411 # Then
395412 assert paths == [
396- (split (17 , [18 ]), ndbranch (18 , [20 ])),
413+ (split (17 , [18 ]), ndbranch (18 , [20 ]), merged_edge ( 20 , 21 , [ edge ( 12 , 13 )]) ),
397414 ]
398415
399416
@@ -536,7 +553,8 @@ def test_pretty_print() -> None:
536553 d = {
537554 'nodes' : nodes ,
538555 'aliases' : {'foo' : 14 , 'bar' : 14 },
539- 'edges' : edge_dicts ((21 , 12 ), (12 , 13 , 5 ), (13 , 14 ), (15 , 16 ), (16 , 13 ), (18 , 17 ), (22 , 19 )),
556+ 'edges' : edge_dicts ((12 , 13 , 5 ), (13 , 14 ), (15 , 16 ), (16 , 13 ), (18 , 17 ), (22 , 19 )),
557+ 'merged_edges' : merged_edge_dicts ((21 , 12 , (21 , 12 ), (21 , 13 ))),
540558 'covers' : cover_dicts ((19 , 22 )),
541559 'splits' : split_dicts (
542560 (
@@ -562,7 +580,7 @@ def test_pretty_print() -> None:
562580 '\n '
563581 '┌─ 21 (root)\n '
564582 '│\n '
565- '│ (1 step )\n '
583+ '│ (1|1 steps )\n '
566584 '├─ 12\n '
567585 '│\n '
568586 '│ (5 steps)\n '
@@ -648,7 +666,7 @@ def test_pretty_print() -> None:
648666 '│ V21\n '
649667 '│ </top>\n '
650668 '│\n '
651- '│ (1 step )\n '
669+ '│ (1|1 steps )\n '
652670 '├─ 12\n '
653671 '│ <top>\n '
654672 '│ V12\n '
0 commit comments