import dis


def instructions_are_the_same(instr: dis.Instruction, target_instr: dis.Instruction,
                              frame=None):
    """Check if the disassembled instructions *instr* and *target_instr* are (basically) the same.

    Mainly this checks if the *opname* and *argval* of the two instructions are the same,
    additionally accounting for some subtleties involving code object - argvals and LOAD-operators.

    :param instr: Candidate instruction that should be matched to the target.
    :param target_instr: Target instruction.
    :param frame: Frame the target instruction came from.
    """
    # for the LOAD_FAST operator, get the argval from the frame's locals
    if (frame is not None and target_instr.opname == 'LOAD_FAST'
            and target_instr.argval in frame.f_locals
            and target_instr.argval in frame.f_code.co_varnames):
        argval = frame.f_locals[target_instr.argval]
    else:
        argval = target_instr.argval
    # if the instruction's argval contains code objects, compare the code
    instr_argval = getattr(instr.argval, 'co_code', instr.argval)
    target_argval = getattr(target_instr.argval, 'co_code', target_instr.argval)

    if instr_argval not in (target_argval, argval):
        return False

    if instr.opname == target_instr.opname:
        return True

    # load operations can have many different name, accept if both are load ops regardless
    # of which kind exactly
    load_ops = ('LOAD_NAME', 'LOAD_FAST', 'LOAD_GLOBAL', 'LOAD_CONST', 'LOAD_DEREF')
    return instr.opname in load_ops and target_instr.opname in load_ops