我正在为 Python 程序绘制控制流图,并希望影响哪种边缘不应交叉。有没有办法做到这一点?
考虑这个简单的 Python 程序:
try:
a += 1
except:
a += 2
else:
a = 3
以及一个点程序来表示通过生成的控制流https://github.com/rocky/python-control-flow/ 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];
}
The image that dot produces for the above is
注意一条线如何蜿蜒并与向下的直箭头交叉。相反,我更希望没有一个直接向下的箭头会被交叉。带花键的边缘可以提供更好的交叉位置。
如果你看一下这个点,我有两个看不见的向下边缘,我用它们来对齐。 (在字节码中,它们遵循指令的线性序列)。
因此,如果需要跨越向下的直线(这里不需要),则不可见的边缘将优于可见的边缘。
想法?
Edit
到目前为止,一个很好的答案建议更改边缘定义的顺序,并在某些情况下指定应进行边缘附件的位置。
在此应用程序中,我确实拥有来自支配树的分层嵌套信息,并且可以对边进行分类:循环的边、跳转到复合结构末尾的边、打破循环的边等。
所以现在问题就变成了how人们使用此信息来避免那些蜿蜒的箭头,并确保跳出循环优先于跨越“if”/“else”跳转边缘。
这感觉就像 VLSI 设计:提出一组适用于每种(控制流)结构的模式,然后这些模式将正确嵌套和排序。
我已经尝试过边缘排序和放置,但我只是没有直觉地知道何时提前或推迟放置某些内容。
对于结构化控制流边缘的指导,或者更好的设计规则,我们将不胜感激。