Created
September 18, 2017 07:47
-
-
Save georgexsh/ede5163a294ced53c3e2369ccaa392cc to your computer and use it in GitHub Desktop.
python goto with system trace function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
def j(lineno): | |
frame = sys._getframe().f_back | |
called_from = frame | |
def hook(frame, event, arg): | |
if event == 'line' and frame == called_from: | |
try: | |
frame.f_lineno = lineno | |
except ValueError as e: | |
print "jump failed:", e | |
while frame: | |
frame.f_trace = None | |
frame = frame.f_back | |
return None | |
return hook | |
while frame: | |
frame.f_trace = hook | |
frame = frame.f_back | |
sys.settrace(hook) | |
def foo(): | |
a = 1 | |
j(30) | |
a = 2 | |
print 1 | |
print 2 | |
if a == 1: | |
j(28) | |
print 4 | |
foo() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 | |
1 | |
2 | |
4 |
The "goto" on pypi follows the same idea, and was made for an April first a couple years ago. It is actually "production quality" and implements labels and a comefrom
statement as well as the goto
.
Can this at GOSUB too ?
How about making a BASIC interpreter, and then a transpiler to convert Python code into BASIC?
Yo DAWG! Now you can throw up in your mouth while you die a little inside!
I made a py3 port. This one uses relative line numbers though.
Here's a reworking of the version above that adds labels, that uses the bytecode dissassembler rather than re-parsing a file that may have changed:
import sys
import dis
def label(name):
pass
def j(lineno):
frame = sys._getframe().f_back
called_from = frame
if isinstance(lineno, str):
# Dissassemble our byte code to find and create our labels:
bc = dis.Bytecode(called_from.f_code)
labels = {}
SET_LABEL = False
LABEL_LINE = None
for idx, instr in enumerate(bc):
if instr.opname == 'LOAD_GLOBAL':
if instr.argval == 'label':
SET_LABEL = True
LABEL_LINE = instr.starts_line
if instr.opname == 'LOAD_CONST' and SET_LABEL:
label_name = instr.argval
labels[label_name] = LABEL_LINE
SET_LABEL = False
LABEL_LINE = None
try:
lineno = labels[lineno]
except KeyError:
raise RuntimeError("Unknown Label: {}".format(lineno))
def hook(frame, event, arg):
if event == 'line' and frame == called_from:
try:
frame.f_lineno = lineno
except ValueError as e:
print("jump failed:", e)
while frame:
frame.f_trace = None
frame = frame.f_back
return None
return hook
while frame:
frame.f_trace = hook
frame = frame.f_back
sys.settrace(hook)
def foo():
a = 1
j('l1')
label('l2')
a = 2
print(1)
label('l1')
print(2)
if a == 1:
j('l2')
print(4)
foo()
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Meh... "goto" is already taken on PyPI... :(