tags:

views:

629

answers:

7

Is there a way to mechanically translate goto statements to if, switch, while, break, and continue statements, etc, or with function calls, objects, anything?

+2  A: 

Considering the complexity that goto's can create based on where its jumping between, it's very doubtful.

Will Eddins
I took the original question to mean: "There's an application I'm maintaining that uses goto's all over the place. I want to make an application that will go through the code and replace the goto's with if's, for loops, functions, etc. to get rid of them." While I was trying to answer that question, others seem to be trying to answer "How can I make a switch that simulates using a goto?" which I saw as less useful.
Will Eddins
+1 I understand what you meant
Kip
+1 You read the question the same way I did, and I more or less agree with your answer. There may be specific uses of GOTO that can be automatically detected and replaced - but to do so in the general case might not be possible.
slim
I understood what you mean, but I think you're wrong. The switch 'solution' could be used to mechanically transform source code containing gotos; unless I'm missing something you could write a script to take arbitrary code and convert it. It's not a good solution, but it works.
Alex Feinman
In my mind, I'm thinking of a goto in the middle of one function jumping to the middle of another function, thus skipping code at the end of the first, and the beginning of the second. I see a switch useful only in cases where they're using a goto to jump between choices, in which case a switch would just do the exact same thing. I'm assuming this is legal use of a goto in Java, since I'm fairly sure it is in other languages. You may be thinking best-case, i'm thinking worst-case.
Will Eddins
@Guard Java has no goto, so by definition there is no "legal use of goto"!In C, a label has function scope, so you can't goto another function.However, I, like you, was thinking of the worst case where a goto sends you to different function. BBC BASIC allowed you to do this, as I'm sure many other languages do.
slim
+4  A: 

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 gotos 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 ;-)

Joachim Sauer
A: 

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.

Justin Niessner
It doesn't *require* duplication, necessarily, just lots and lots of boilerplate. See below.
Alex Feinman
A: 

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.

DigitalRoss
+5  A: 

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;
  }
}
Marius
Actually there's nothing that's inherently a bad idea about that code block (though I don't know if I'd use it as a way to get around not having a goto) That's just a basic implementation of a finite state machine which has lots of legitimate purposes.
Falaina
You can't have an integer condition for a while loop in Java. `while(true)`
pjp
Thanks pjp. Being able to pass 1 as true and 0 as false is one of the things I really wish they would add to Java. The rest of it is wonderful.
Marius
Great minds think alike.
Alex Feinman
@Marius: in my opinion and the fact that `0` and `1` are *not* equivalent to `false` and `true` respectively is one of the best decisions in Java ;-)
Joachim Sauer
+5  A: 

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!
Falaina
That's interesting ... in a horrible way.
Joachim Sauer
my brain is crying
Kip
A: 

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...

Alex Feinman
This is almost exactly identical to Marius's answer. As pointed out there, this is a finite state machine (i.e. change "goTo" to "state"). Nothing wrong with FSMs, but using it as a goto workaround would be weird.
Kip
Yeah, he posted while I had the edit window up...the perils of multi-threading...It's weird. But it answers the OP's request.
Alex Feinman