python-goto
python-goto copied to clipboard
Add support for goto into blocks.
This adds support for goto-ing into blocks! Based on pull requests #21 and #22
While/Try/Except/Finally blocks can be goto-ed into normally.
For/With blocks cannot be goto-ed into normally but require a new syntax:
goto.param .target = obj
Or:
goto.params .target = obj1, obj2, obj3[, ...]
Here, the objects passed to the right of the equals sign are:
- If entering a for loop, an iterator or iterable must be passed.
- If entering a with block, a context manager must be passed.
- If entering multiple for/with blocks, the corresponding objects for each block must be passed left to right (outermost to innermost block).
This syntax was not chosen arbitrarily:
-
The "equals sign" syntax was chosen for implementation simplicity, since the stuff to the right of equals is evaluated before "goto.param(s) .target". (Function calls and the like would've been evaluated afterwards and would've made implementation considerably more complicated)
-
The ".param"/".params" suffix fulfills two purposes:
-
A) It allows distinguishing between the "enter one block" and the "enter several blocks" case (since the object "passed" to that one block may be a tuple), and the alternative of only supporting the "params" syntax is ugly and error-prone in python.
-
B) It pads out the size of the line in the bytecode to 6 bytes in python 3.x, which is also the size used for "goto .target". Doing "goto .target = whatever" would've taken 4 bytes (not including the evaluation of 'whatever', of course) and would not be enough to replace with an absolute jump in huge functions.
However, I'm still not too happy with this syntax. Do you have any ideas?
Another possibility (do you like it better?):
goto .target .param=obj
All locally tested on Python 2.6/2.7/3.4/3.8 & pypy2.7&3.6 (As usual, the pull request checks fail due to existing tooling issues unrelated to my changes)
By the way, async anything (and especially async with) has not been tested, and I imagine hasn't been in the past either.