> 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