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)