結果はきれいではないかもしれませんが、原則として、これを行うことは常に可能です。
goto を常に排除する 1 つの方法は、次のようにプログラムを変換することです。元のプログラムのすべての命令に番号を付けることから始めます。たとえば、次のプログラムがあるとします。
start:
while (true) {
if (x < 5) goto start;
x++
}
次のようにステートメントに番号を付けることができます。
0 start:
1 while (x < 3) {
2 if (x < 5) goto start;
3 x++
}
すべての goto を排除するために、while ループ、プログラム カウンターを保持する明示的な変数、および一連の if ステートメントを使用して、この関数を介した制御の流れをシミュレートできます。たとえば、上記のコードを次のように変換できます。
int PC = 0;
while (PC <= 3) {
if (PC == 0) {
PC = 1; // Label has no effect
} else if (PC == 1) {
if (x < 3) PC = 4; // Skip loop, which ends this function.
else PC = 2; // Enter loop.
} else if (PC == 2) {
if (x < 5) PC = 0; // Simulate goto
else PC = 3; // Simulate if-statement fall-through
} else if (PC == 3) {
x++;
PC = 1; // Simulate jump back up to the top of the loop.
}
}
これは、翻訳を行うには本当に悪い方法ですが、理論上は常に可能であることを示しています。これを実際に実装するのは非常に面倒です。おそらく、関数の基本ブロックに番号を付けてから、基本ブロックをループに入れるコードを生成し、現在実行中の基本ブロックを追跡し、基本ブロックの実行の効果をシミュレートし、その基本ブロックから適切な次の基本ブロックへの移行。
お役に立てれば!