Я рисую графы потока управления для программ Python и хотел бы повлиять на то, какие края не должны пересекаться. Есть ли способ сделать это?
Рассмотрим эту простую программу на Python:
try:
a += 1
except:
a += 2
else:
a = 3
И точечная программа для представления потока управления для сгенерированного через https://github.com/rocky/python-control-flow/
digraph G {
mclimit=1.5;
rankdir=TD; ordering=out;
graph[fontsize=10 fontname="Verdana"];
color="#efefef";
node[shape=box style=filled fontsize=8 fontname="Verdana" fillcolor="#efefef"];
edge[fontsize=8 fontname="Verdana"];
node_0 [shape = "oval"][label="Basic Block 0\loffsets: 0..12\lflags=entry, block, unconditional, try\ljumps=[34]\l"];
node_1 [label="Basic Block 1\loffsets: 14..30\lflags=except, unconditional\ljumps=[38]\l"];
node_2 [label="Basic Block 2\loffsets: 32..32\lflags=end finally\l"];
node_3 [label="Basic Block 3\loffsets: 34..36\l"];
node_4 [label="Basic Block 4\loffsets: 38..40\lflags=no fallthrough\l"];
node_0 -> node_2 [weight=1][color="red"];
node_3 -> node_4 [weight=10];
node_0 -> node_1 [weight=1][color="red"];
node_2 -> node_3 [weight=10];
node_0 -> node_1 [weight=10][style="invis"];
node_1 -> node_2 [weight=10][style="invis"];
node_1 -> node_4 [weight=1];
node_0 -> node_3 [weight=1];
}
Изображение, которое точка создает для приведенного выше, это
Обратите внимание, как одна линия извивается и пересекает прямую стрелку вниз. Вместо этого я бы предпочел, чтобы ни одна из прямых стрелок вниз не пересекалась. Шлицевые кромки улучшат места пересечения.
Если вы посмотрите на точку, у меня есть два невидимых нисходящих края, которые я использую для выравнивания. (В байт-коде они следуют линейной последовательности инструкций).
Таким образом, если необходимо пересечь прямую линию, направленную вниз (а здесь этого не происходит), невидимые ребра предпочтительнее видимых.
Мысли?
Изменить
Единственный отличный ответ на данный момент предлагает изменить порядок определения ребер и указать в определенных ситуациях, где следует выполнять присоединения ребер.
В этом приложении у меня есть иерархическая информация о вложенности из дерева доминаторов, и я могу классифицировать ребра: те, которые зацикливаются, те, которые переходят в конец составной структуры, те, которые разрывают петлю и так далее.
Итак, теперь проблема заключается именно в том, как использовать эту информацию, чтобы избежать этих извилистых стрелок, и гарантировать, что выходы из циклов предпочтительнее пересечения ребер, чем, скажем, ребер перехода «если»/«иначе».
Это похоже на дизайн СБИС: придумайте набор шаблонов, которые работают для каждого типа структуры (потока управления), и затем они будут правильно вложены друг в друга и упорядочены.
Я экспериментировал с порядком и размещением ребер, и у меня просто нет интуитивного понимания, когда что-то ставить раньше или позже.
Мы будем очень признательны за руководство или, что еще лучше, за правило проектирования для структурированных краев потока управления.