karl3ļ¼ writeme.com wrote: > > GPT-4 > > User > > Come up with an analog to "goto" in python that engages the raw > > interpreter and/or bytecode systems of python to function. > > i want to try! > > omigod this sounds really hard. options: > - is there a way to halt interpretation during a function? > - alternatively, we could use ctypes to modify whatever python uses as an > instruction pointer > > hmmmmmmmmmmmmmmmmm 1304 > > so, yes, there is a way to halt interpretation during a function, it's called > 'yield'. > there's also access to the call stack but i think the access is read-only. > the problem with 'yield' is: > - (a) i think it turns the function into a generator upon use > - (b) if it's bundled into a goto() function it will interrupt the goto() > body rather than the surrounding code > > here's a third option: > - mutate the source code live using runtime preprocessing like old javascript > second language interpreters did > > options again: > - find an in-python way to halt function executation midway > - use ctypes to modify the runtime at runtime > - post-process the running sourcecode, say in a nonreturning function with > injects controlflow to hide its nonreturn > > but i'm guessing what i originally meant was more along the lines of: > - instrument the calling function to behave as if there were a goto statement > where your function is called > > ok so the idea is maybe along the lines of, let's make a goto() function in > python that emulates goto in C. > the approaches of interest (despite there being many other interesting ones!) > are either: > (a) validate that callers are decorated with a recompiler > or > (b) identify the caller and mutate them mid-call to change their behavior > > although (b) is preferred because it doesn't require a decorator, it might be > unreasonable hard i'm not sure. for example it's likely not possible to > mutate code mid-call (although it could be); it likely only affects the next > call. > > let's see! this sounds hard :s > 1308 > > def a(): > > ... b = 1 > > ... b += 1 > > ... return b > > ... > > import dis > > dis.dis(a) > > 1 0 RESUME 0 > > 2 2 LOAD_CONST 1 (1) > 4 STORE_FAST 0 (b) > > 3 6 LOAD_FAST 0 (b) > 8 LOAD_CONST 1 (1) > 10 BINARY_OP 13 (+=) > 14 STORE_FAST 0 (b) > > 4 16 LOAD_FAST 0 (b) > 18 RETURN_VALUE > > let's see what happens if i remove line 3 from the function and try to inject > it using a caller-modifier or something? :s :s :s this won't work > > list(a.__code__.co_code) > > [151, 0, 100, 1, 125, 0, 124, 0, 100, 1, 122, 13, 0, 0, 125, 0, 124, 0, 83, > > 0] > > looks like maybe > 151=RESUME_1 > 100=LOAD_CONST_1 > 125=STORE_FAST_1 > 124=LOAD_FAST_1 > 122=BINARY_OP_3 > 83=RETURN_VALUE_1 > and it uses an indexable stack or something > > 1313 > > 1317 > here's a cool thing you can do. this function disassembles itself. it shows a > call to the function to get the stack frame and pass it to the disassembler: > > import sys > > def disassemble_self(): > > ... dis.dis(sys._getframe().f_code.co_code) > > ... > > disassemble_self() > > 0 RESUME 0 > > 2 LOAD_GLOBAL 0 > > 14 LOAD_METHOD 0 > > 36 LOAD_GLOBAL 2 > > 48 LOAD_METHOD 2 > > 70 PRECALL 0 > > 74 CALL 0 > > 84 LOAD_ATTR 3 > > 94 LOAD_ATTR 4 > > 104 PRECALL 1 > > 108 CALL 1 > > 118 POP_TOP > > 120 LOAD_CONST 0 > > 122 RETURN_VALUE > >
oops: >>> exec(disassemble_self.__code__.replace(co_code=a.__code__.co_code)) Segmentation fault