-
-
Save zahlman/18a4492018ebf43dbc33ecd2c322650d to your computer and use it in GitHub Desktop.
Initial prototype: hack recursive functions to look themselves up in the function's pre-bound consts, instead of doing a global namespace lookup
This file contains hidden or 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 dis | |
| def filter_code(func, replacement): | |
| name = func.__name__ | |
| code = func.__code__.co_code | |
| begin, do_fix = None, None | |
| for i in dis.get_instructions(func): | |
| if begin is not None: # every time except the first | |
| end = i.offset | |
| yield replacement if do_fix else code[begin:end] | |
| begin, do_fix = i.offset, (i.opname == 'LOAD_GLOBAL' and i.argval == name) | |
| # handle the last | |
| yield replacement if do_fix else code[begin:] | |
| def rewrite(func): | |
| consts = func.__code__.co_consts + (func,) | |
| load_opcode = bytes([dis.opmap['LOAD_CONST'], len(consts) - 1]) | |
| fixed_code = b''.join(filter_code(func, load_opcode)) | |
| func.__code__ = func.__code__.replace(co_consts=consts, co_code=fixed_code) | |
| return func # for decorator usage |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment