I must use goto
in Python. I found entrians goto
but my Python implementation (CPython 2.7.1 on Mac) does not have this module, so it doesn't seem to be portable. It should at least work in all Python implementations which support CPython bytecode (esp. I care about CPython and PyPy). Then there is this related question, and cdjc's goto
. And the ones given by answers below.
I could go and build up the bytecode manually (i.e. write my own Python compiler) because there is such an instruction (JUMP_ABSOLUTE
and friends). But I wonder if there is an easier way. Is it possible via inspect
or so to call a single bytecode instruction? I also thought about compiling via Python and then automatically patching the generated Python bytecode.
Of course, people will ask why and will not give me any helpful answer if I don't explain why I really really need this. So in short my use case: I am translating a C AST to Python AST and compiling this. I can map every logical flow (all the loops and other stuff) in some way to equivalent Python code. Everything except goto
. Related projects: PyCParser (see interpreter.py
), PyCPython, PyLua.
There are going to be some common patterns that code using
goto
is likely to follow.In most cases, I suspect that all goto statements will jump to a location that's both later, and in a more enclosing block; If a function body follows this pattern perfectly, transform the goto's into exceptions, with the labels as the except blocks.
Other cases of goto jumping from the one place to another in the same block, as would be used in a state machine. This can probably be translated into a dispatch loop; each region between a label and the next becomes a function; goto's are replaced by
next_state = 'labelname'; return
The last case, which is neither of the above and possibly non-trivial, are when the jump is into a loop body. I don't have an answer for that yet.
You may have the only valid use case I have ever seen for needing
goto
in Python. :-)The most straightforward way to emulate forward
goto
in Python is using exceptions, as these can jump out of any depth of nested control structures.This gets hairy if you need to support more than one destination, but I think it could be done using nested
try/except
structures and multiple classes of exception, one for each destination. Since C limitsgoto
to the scope of a single function, at least you won't have to worry about how to make this work across functions. :-) Of course, it doesn't work for reversegoto
s.Another thing to note is that exceptions in Python, while fast compared to some languages, are still slower than normal flow control structures such as
while
andfor
.This could be a lot of work (though perhaps not more than you're already in for), but if you could generate Python bytecode rather than Python source, you would have no problem implementing
goto
, because Python bytecode (like most psuedo-machine-languages) has a perfectly cromulentJUMP_ABSOLUTE
opcode.I know what everybody is thinking:
However, there might be some didactic cases where you actually need a
goto
.This python recipe provides the
goto
command as a function decorator.The goto decorator (Python recipe by Carl Cerecke)
Usage
Update
Here're two additional implementations compatible with Python 3:
This is not exactly what you're looking for but hear me out.
Many years ago, my son and I wrote an "Adventure" game in BASIC. Each location in the underground game was a line number. When you left one location through the tunnel going north, for instance, you arrived at another location.
The coding was something like
if response == 'N' GOTO 2400
. So players ended up going all over the place using GOTOs.I wondered how this might be done in Python and came up with this.
Maybe such a technique could be used for other applications where something like a GOTO is needed. If you split up your program into chunks which are functions, the following "a bit silly" coding would do the trick.
A working version has been made: http://entrian.com/goto/.
Note: It was offered as an April Fool's joke. (working though)
Needless to say. Yes its funny, but DONT use it.
I've updated my python goto decorator for Python 3. You can get it at https://github.com/cdjc/goto. Using goto instead of functions can make a state machine about 5 times faster.
The version for python 2 is still available at http://code.activestate.com/recipes/576944-the-goto-decorator/ but it has a number of bugs that are fixed in the python 3 version.