util.py 849 B

123456789101112131415161718192021
  1. import dis
  2. import inspect
  3. def iterate_instructions(code_object):
  4. """Delivers the byte-code instructions as a continuous stream.
  5. Yields `dis.Instruction`. After each code-block (`co_code`), `None` is
  6. yielded to mark the end of the block and to interrupt the steam.
  7. """
  8. # The arg extension the EXTENDED_ARG opcode represents is automatically handled by get_instructions() but the
  9. # instruction is left in. Get rid of it to make subsequent parsing easier/safer.
  10. yield from (i for i in dis.get_instructions(code_object) if i.opname != "EXTENDED_ARG")
  11. yield None
  12. # For each constant in this code object that is itself a code object,
  13. # parse this constant in the same manner.
  14. for constant in code_object.co_consts:
  15. if inspect.iscode(constant):
  16. yield from iterate_instructions(constant)