/** {@inheritDoc} */
  @Override
  public List<Mutation> apply(
      MethodNode mn,
      String className,
      String methodName,
      BytecodeInstruction instruction,
      Frame frame) {
    List<Mutation> mutations = new LinkedList<Mutation>();

    FieldInsnNode node = (FieldInsnNode) instruction.getASMNode();
    Type fieldType = Type.getType(node.desc);

    // insert mutation into bytecode with conditional
    InsnList mutation = new InsnList();
    logger.debug("Mutation deletefield for statement " + node.name + node.desc);
    if (node.getOpcode() == Opcodes.GETFIELD) {
      logger.debug("Deleting source of type " + node.owner);
      mutation.add(new InsnNode(Opcodes.POP));
    }
    mutation.add(getDefault(fieldType));
    // insert mutation into pool
    Mutation mutationObject =
        MutationPool.addMutation(
            className,
            methodName,
            NAME + " " + node.name + node.desc,
            instruction,
            mutation,
            getInfectionDistance(node, mutation));

    mutations.add(mutationObject);
    return mutations;
  }
  /** {@inheritDoc} */
  @Override
  public List<Mutation> apply(
      MethodNode mn,
      String className,
      String methodName,
      BytecodeInstruction instruction,
      Frame frame) {

    List<Mutation> mutations = new LinkedList<Mutation>();
    Object value = getValue(instruction.getASMNode());

    for (Object replacement : getReplacement(value)) {
      // insert mutation into bytecode with conditional
      LdcInsnNode mutation = new LdcInsnNode(replacement);
      // insert mutation into pool
      String summary = NAME + " - " + value + " -> " + replacement;
      if (replacement instanceof String) {
        summary = summary.replace("*/", "*_/");
      }
      Mutation mutationObject =
          MutationPool.addMutation(
              className,
              methodName,
              summary,
              instruction,
              mutation,
              Mutation.getDefaultInfectionDistance());
      mutations.add(mutationObject);
    }

    return mutations;
  }
  /** {@inheritDoc} */
  @Override
  public List<Mutation> apply(
      MethodNode mn,
      String className,
      String methodName,
      BytecodeInstruction instruction,
      Frame frame) {
    JumpInsnNode node = (JumpInsnNode) instruction.getASMNode();
    List<Mutation> mutations = new LinkedList<Mutation>();
    LabelNode target = node.label;

    boolean isBoolean =
        frame.getStack(frame.getStackSize() - 1) == BooleanValueInterpreter.BOOLEAN_VALUE;

    for (Integer op : getOperators(node.getOpcode(), isBoolean)) {
      logger.debug("Adding replacement " + op);
      if (op >= 0) {
        // insert mutation into bytecode with conditional
        JumpInsnNode mutation = new JumpInsnNode(op, target);
        // insert mutation into pool
        Mutation mutationObject =
            MutationPool.addMutation(
                className,
                methodName,
                "ReplaceComparisonOperator " + getOp(node.getOpcode()) + " -> " + getOp(op),
                instruction,
                mutation,
                getInfectionDistance(node.getOpcode(), op));
        mutations.add(mutationObject);
      } else {
        // Replace relational operator with TRUE/FALSE

        InsnList mutation = new InsnList();
        if (opcodesInt.contains(node.getOpcode())) mutation.add(new InsnNode(Opcodes.POP));
        else mutation.add(new InsnNode(Opcodes.POP2));
        if (op == TRUE) {
          mutation.add(new LdcInsnNode(1));
        } else {
          mutation.add(new LdcInsnNode(0));
        }
        mutation.add(new JumpInsnNode(Opcodes.IFNE, target));
        Mutation mutationObject =
            MutationPool.addMutation(
                className,
                methodName,
                "ReplaceComparisonOperator " + getOp(node.getOpcode()) + " -> " + op,
                instruction,
                mutation,
                getInfectionDistance(node.getOpcode(), op));
        mutations.add(mutationObject);
      }
    }

    return mutations;
  }
 /** {@inheritDoc} */
 @Override
 public boolean isApplicable(BytecodeInstruction instruction) {
   return instruction.getASMNode().getOpcode() == Opcodes.GETFIELD
       || instruction.getASMNode().getOpcode() == Opcodes.GETSTATIC;
 }
 /** {@inheritDoc} */
 @Override
 public boolean isApplicable(BytecodeInstruction instruction) {
   return instruction.isConstant();
 }