Is there a way to mechanically translate goto
statements to if
, switch
, while
, break
, and continue
statements, etc, or with function calls, objects, anything?
views:
629answers:
7Considering the complexity that goto
's can create based on where its jumping between, it's very doubtful.
The Java language doesn't support the features necessary to simulate gotos to arbitrary position (not even within the same method). You can implement a few simple uses of goto
using the constructs you mentioned, but can't implement all possible goto
uses this way. (*)
On the byte code level you could probably implement goto
(at least within a method), but that byte code could not be mapped back to valid Java code in this case.
As for goto
s that cross method or object boundaries: That's definitely a big no-no on the JVM level. The entire Java security model depends on the fact that code is verifyable and thus has only defined entry points (also known as "methods").
(*) Disclaimer: this assumes that you don't want to completely restructure the method to implement the effect of goto, which could also invoke code duplication and obfuscating the "normal" flow of the method. Since you can implement a turing machine in a Java method you can definitely implement "goto" in a Java method ;-)
Yes, using a combination of the methods you mentioned...it is possible (anything is possible really, just figuring out how to do it properly is a pain in the ass).
Keep in mind that goto
's can result in extremely complex execution paths...and therefore may result in unsightly large amounts of duplicate code in whatever is generated.
In practice, I imagine any given example goto
can be translated to something else, particularly if method extraction is an allowed transformation. Is this an abstract question or do you actually have so many goto's that you really need an actual tool? Perhaps the java code itself was machine-translated from something?
I used to put one actual goto
into every program I wrote just to annoy the purists.
While it is not a good idea, it is possible using loops and swith-case. In the following example the goto variable decides what label (0, 1, 2 or default) to goto when you get to a continue.
int goTo=0;
while(true){
switch(goTo){
case 0:
doSomething();
goTo = 1;
continue;
case 1:
doSomethingElse();
goTo = 2;
continue;
case 2:
doSOmethingDifferent();
goTo = 0;
continue;
default:
return;
}
}
I thought this would be worth sharing here. I saw this on Reddit one day, it's an implementation of goto to an arbitrary line number (in the same .java file) via a custom class loader. It's a fun piece of code. http://steike.com/tmp/goto.zip . I take no credit for it.
Edit: For those who are curious but don't want to download the zip and run it, for the following file:
public class GotoDemo {
public static void main(String[] args) {
int i = 5;
System.out.println(i);
i = i - 1;
if (i >= 0) {
GotoFactory.getSharedInstance().getGoto().go(4);
}
try {
System.out.print("Hell");
if (Math.random() < 2) throw new Exception();
System.out.println("World!");
} catch (Exception e) {
System.out.print("o ");
GotoFactory.getSharedInstance().getGoto().go(13);
}
}
}
It will print:
3 2 1 0 Hello World!
Sure: (abbreviating slightly for clarity)
int goTo = 0; boolean done = false;
while (!done) {
switch (goTo) {
default:
case 1: System.out.println("We're at line 1!"); goTo = 2; break;
case 2: System.out.println("We're going to line 4!"); goTo = 4; break;
case 3: System.out.println("We're at line 3 and we're done!"); done = true; break;
case 4: System.out.println("We're at 4, going to 2! Screw you, line 3!"); goTo = 2; break;
}
}
Why you would want to do such a thing is beyond me, but hey, you can...