def inject_tracing(codelist):
    """ Inject tracing code into the given code list.

    This will inject the bytecode operations required to trace the
    execution of the code using a `CodeTracer` object. The generated
    opcodes expect a fast local '_[tracer]' to be available when the
    code is executed.

    Parameters
    ----------
    codelist : list
        The list of byteplay code ops to modify.

    Returns
    -------
    result : list
        A *new* list of code ops which implement the desired behavior.

    """
    # This builds a mapping of code idx to a list of ops, which are the
    # tracing bytecode instructions which will be inserted into the code
    # object being transformed. The ops assume that a tracer object is
    # available in the fast locals using a non-clashable name. All of
    # the ops have a net-zero effect on the execution stack. Provided
    # that the tracer has no visible side effects, the tracing is
    # transparent.
    inserts = {}
    for idx, (op, op_arg) in enumerate(codelist):
        if op == LOAD_ATTR:
            code = [                        # obj
                (DUP_TOP, None),            # obj -> obj
                (LOAD_FAST, '_[tracer]'),   # obj -> obj -> tracer
                (LOAD_ATTR, 'load_attr'),   # obj -> obj -> tracefunc
                (ROT_TWO, None),            # obj -> tracefunc -> obj
                (LOAD_CONST, op_arg),       # obj -> tracefunc -> obj -> attr
                (CALL_FUNCTION, 0x0002),    # obj -> retval
                (POP_TOP, None),            # obj
            ]
            inserts[idx] = code
        elif op == CALL_FUNCTION:
            # This computes the number of objects on the stack between
            # TOS and the object being called. Only the last 16bits of
            # the op_arg are signifcant. The lowest 8 are the number of
            # positional args on the stack, the upper 8 is the number of
            # kwargs. For kwargs, the number of items on the stack is
            # twice this number since the values on the stack alternate
            # name, value.
            n_stack_args = (op_arg & 0xFF) + 2 * ((op_arg >> 8) & 0xFF)
            code = [                                # func -> arg(0) -> arg(1) -> ... -> arg(n-1)
                (BUILD_TUPLE, n_stack_args),        # func -> argtuple
                (DUP_TOPX, 2),                      # func -> argtuple -> func -> argtuple
                (LOAD_FAST, '_[tracer]'),           # func -> argtuple -> func -> argtuple -> tracer
                (LOAD_ATTR, 'call_function'),       # func -> argtuple -> func -> argtuple -> tracefunc
                (ROT_THREE, None),                  # func -> argtuple -> tracefunc -> func -> argtuple
                (LOAD_CONST, op_arg),               # func -> argtuple -> tracefunc -> func -> argtuple -> argspec
                (CALL_FUNCTION, 0x0003),            # func -> argtuple -> retval
                (POP_TOP, None),                    # func -> argtuple
                (UNPACK_SEQUENCE, n_stack_args),    # func -> arg(n-1) -> arg(n-2) -> ... -> arg(0)
                (BUILD_TUPLE, n_stack_args),        # func -> reversedargtuple
                (UNPACK_SEQUENCE, n_stack_args),    # func -> arg(0) -> arg(1) -> ... -> arg(n-1)
            ]
            inserts[idx] = code
        elif op == BINARY_SUBSCR:
            code = [                            # obj -> idx
                (DUP_TOPX, 2),                  # obj -> idx -> obj -> idx
                (LOAD_FAST, '_[tracer]'),       # obj -> idx -> obj -> idx -> tracer
                (LOAD_ATTR, 'binary_subscr'),   # obj -> idx -> obj -> idx -> tracefunc
                (ROT_THREE, None),              # obj -> idx -> tracefunc -> obj -> idx
                (CALL_FUNCTION, 0x0002),        # obj -> idx -> retval
                (POP_TOP, None),                # obj -> idx
            ]
            inserts[idx] = code
        elif op == GET_ITER:
            code = [                        # obj
                (DUP_TOP, None),            # obj -> obj
                (LOAD_FAST, '_[tracer]'),   # obj -> obj -> tracer
                (LOAD_ATTR, 'get_iter'),    # obj -> obj -> tracefunc
                (ROT_TWO, None),            # obj -> tracefunc -> obj
                (CALL_FUNCTION, 0x0001),    # obj -> retval
                (POP_TOP, None),            # obj
            ]
            inserts[idx] = code

    # Create a new code list which interleaves the generated code with
    # the original code at the appropriate location.
    new_code = []
    for idx, code_op in enumerate(codelist):
        if inserts in idx:
            new_code.extend(inserts[idx])
        new_code.append(code_op)

    return new_code
dataset/ETHPy150Open ContinuumIO/ashiba/enaml/enaml/core/code_tracing.py/inject_tracing/swapped operands of `in`