@@ -77,6 +77,10 @@ def edge(i: int, j: int) -> KCFG.Edge:
7777 return KCFG .Edge (node (i ), node (j ), 1 , ())
7878
7979
80+ def merged_edge (i : int , j : int , edges : Iterable [KCFG .Edge ]) -> KCFG .MergedEdge :
81+ return KCFG .MergedEdge (node (i ), node (j ), tuple (edges ))
82+
83+
8084def cover (i : int , j : int ) -> KCFG .Cover :
8185 csubst = term (j ).match_with_constraint (term (i ))
8286 assert csubst is not None
@@ -107,6 +111,14 @@ def _make_edge_dict(i: int, j: int, depth: int = 1, rules: tuple[str, ...] = ())
107111 return [_make_edge_dict (* edge ) for edge in edges ]
108112
109113
114+ def merged_edge_dicts (* merged_edges : Iterable ) -> list [dict [str , Any ]]:
115+
116+ def _make_merged_edge_dict (s : int , t : int , * edges : Iterable ) -> dict [str , Any ]:
117+ return {'source' : s , 'target' : t , 'edges' : edge_dicts (* edges )}
118+
119+ return [_make_merged_edge_dict (* merged_edge ) for merged_edge in merged_edges ]
120+
121+
110122def cover_dicts (* edges : tuple [int , int ]) -> list [dict [str , Any ]]:
111123 covers = []
112124 for i , j in edges :
@@ -310,6 +322,7 @@ def test_get_successors() -> None:
310322 'next' : 19 ,
311323 'nodes' : node_dicts (18 ),
312324 'edges' : edge_dicts ((11 , 12 )),
325+ 'merged_edges' : merged_edge_dicts ((17 , 18 , (14 , 15 ))),
313326 'splits' : split_dicts ((12 , [(13 , mlTop ()), (14 , mlTop ())])),
314327 'covers' : cover_dicts ((14 , 11 )),
315328 'ndbranches' : ndbranch_dicts ((13 , [(16 , False ), (17 , False )])),
@@ -318,12 +331,14 @@ def test_get_successors() -> None:
318331
319332 # When
320333 edges = set (cfg .edges (source_id = 11 ))
334+ merged_edges = set (cfg .merged_edges (source_id = 17 ))
321335 covers = set (cfg .covers (source_id = 14 ))
322336 splits = sorted (cfg .splits (source_id = 12 ))
323337 ndbranches = set (cfg .ndbranches (source_id = 13 ))
324338
325339 # Then
326340 assert edges == {edge (11 , 12 )}
341+ assert merged_edges == {merged_edge (17 , 18 , [edge (14 , 15 )])}
327342 assert covers == {cover (14 , 11 )}
328343 assert splits == [split (12 , [13 , 14 ])]
329344 assert ndbranches == {ndbranch (13 , [16 , 17 ])}
@@ -344,8 +359,9 @@ def test_get_predecessors() -> None:
344359def test_reachable_nodes () -> None :
345360 # Given
346361 d = {
347- 'nodes' : node_dicts (20 ),
362+ 'nodes' : node_dicts (21 ),
348363 'edges' : edge_dicts ((13 , 15 ), (14 , 15 ), (15 , 12 )),
364+ 'merged_edges' : merged_edge_dicts ((20 , 21 , (12 , 13 ))),
349365 'covers' : cover_dicts ((12 , 13 )),
350366 'splits' : split_dicts (
351367 (16 , [(12 , mlTop ()), (13 , mlTop ()), (17 , mlTop ())]), (17 , [(12 , mlTop ()), (18 , mlTop ())])
@@ -362,16 +378,17 @@ def test_reachable_nodes() -> None:
362378
363379 # Then
364380 assert nodes_2 == {node (12 ), node (13 ), node (15 )}
365- assert nodes_3 == {node (16 ), node (12 ), node (13 ), node (17 ), node (18 ), node (15 ), node (19 ), node (20 )}
381+ assert nodes_3 == {node (16 ), node (12 ), node (13 ), node (17 ), node (18 ), node (15 ), node (19 ), node (20 ), node ( 21 ) }
366382 assert nodes_4 == {node (13 ), node (16 ), node (12 ), node (15 ), node (17 ), node (14 )}
367383 assert nodes_5 == {node (19 ), node (18 ), node (17 ), node (16 )}
368384
369385
370386def test_paths_between () -> None :
371387 # Given
372388 d = {
373- 'nodes' : node_dicts (20 ),
389+ 'nodes' : node_dicts (21 ),
374390 'edges' : edge_dicts ((13 , 15 ), (14 , 15 ), (15 , 12 )),
391+ 'merged_edges' : merged_edge_dicts ((20 , 21 , (12 , 13 ))),
375392 'covers' : cover_dicts ((12 , 13 )),
376393 'splits' : split_dicts (
377394 (16 , [(12 , mlTop ()), (13 , mlTop ()), (17 , mlTop ())]), (17 , [(12 , mlTop ()), (18 , mlTop ())])
@@ -391,11 +408,11 @@ def test_paths_between() -> None:
391408 ]
392409
393410 # When
394- paths = sorted (cfg .paths_between (17 , 20 ))
411+ paths = sorted (cfg .paths_between (17 , 21 ))
395412
396413 # Then
397414 assert paths == [
398- (split (17 , [18 ]), ndbranch (18 , [20 ])),
415+ (split (17 , [18 ]), ndbranch (18 , [20 ]), merged_edge ( 20 , 21 , [ edge ( 12 , 13 )]) ),
399416 ]
400417
401418
@@ -914,7 +931,8 @@ def test_pretty_print() -> None:
914931 d = {
915932 'nodes' : nodes ,
916933 'aliases' : {'foo' : 14 , 'bar' : 14 },
917- 'edges' : edge_dicts ((21 , 12 ), (12 , 13 , 5 ), (13 , 14 ), (15 , 16 ), (16 , 13 ), (18 , 17 ), (22 , 19 )),
934+ 'edges' : edge_dicts ((12 , 13 , 5 ), (13 , 14 ), (15 , 16 ), (16 , 13 ), (18 , 17 ), (22 , 19 )),
935+ 'merged_edges' : merged_edge_dicts ((21 , 12 , (21 , 12 ), (21 , 13 ))),
918936 'covers' : cover_dicts ((19 , 22 )),
919937 'splits' : split_dicts (
920938 (
@@ -940,7 +958,7 @@ def test_pretty_print() -> None:
940958 '\n '
941959 '┌─ 21 (root)\n '
942960 '│\n '
943- '│ (1 step )\n '
961+ '│ (1|1 steps )\n '
944962 '├─ 12\n '
945963 '│\n '
946964 '│ (5 steps)\n '
@@ -1026,7 +1044,7 @@ def test_pretty_print() -> None:
10261044 '│ V21\n '
10271045 '│ </top>\n '
10281046 '│\n '
1029- '│ (1 step )\n '
1047+ '│ (1|1 steps )\n '
10301048 '├─ 12\n '
10311049 '│ <top>\n '
10321050 '│ V12\n '
0 commit comments