forked from nat/natalieee.net
47 lines
1.3 KiB
Python
47 lines
1.3 KiB
Python
import sys, inspect
|
|
|
|
label = lambda lineno: type(
|
|
'label',
|
|
(object,),
|
|
dict(line=lineno)
|
|
)
|
|
|
|
def prepare_labels(fp, scope):
|
|
with open(fp, 'r') as f:
|
|
lines = f.readlines()
|
|
|
|
for lineno, line in enumerate(lines):
|
|
if line.startswith('#LABEL'):
|
|
# 1 + 1, first to account for 0 index then to account for comment line
|
|
scope.__setitem__(line.split(' ')[1].strip(), label(lineno+2))
|
|
|
|
_goto = type('goto', (object,), dict(__and__=lambda _, other: (_goto(other.line))))
|
|
|
|
goto = _goto()
|
|
|
|
def _goto(lineno):
|
|
frame = sys._getframe().f_back.f_back
|
|
called_from = frame
|
|
|
|
def hook(frame, event, _):
|
|
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
|
|
|
|
# it doesn't think we actually need to set the hook for each frame
|
|
# while frame:
|
|
# frame.f_trace = hook
|
|
# frame = frame.f_back
|
|
|
|
called_from.f_trace = hook
|
|
sys.settrace(hook)
|
|
|
|
prepare_labels(inspect.stack()[-1].frame.f_code.co_filename, inspect.stack()[-1].frame.f_globals)
|