@Override
  public BasicValue naryOperation(AbstractInsnNode insn, List<? extends BasicValue> values) throws AnalyzerException {
    int opCode = insn.getOpcode();
    int shift = opCode == INVOKESTATIC ? 0 : 1;

    switch (opCode) {
      case INVOKESPECIAL, INVOKEINTERFACE, INVOKEVIRTUAL -> {
        if (nullAnalysis && values.get(0) instanceof ParamValue) {
          deReferenced = true;
          return super.naryOperation(insn, values);
        }
      }
    }

    boolean propagate = resultOrigins[insns.indexOf(insn)];
    if (propagate || isThrowAnalysis()) {
      switch (opCode) {
        case INVOKESTATIC, INVOKESPECIAL, INVOKEVIRTUAL, INVOKEINTERFACE -> {
          boolean stable = opCode == INVOKESTATIC || opCode == INVOKESPECIAL;
          MethodInsnNode mNode = (MethodInsnNode)insn;
          Member method = new Member(mNode.owner, mNode.name, mNode.desc);
          Type retType = Type.getReturnType(mNode.desc);
          boolean isRefRetType = retType.getSort() == Type.OBJECT || retType.getSort() == Type.ARRAY;
          if (propagate && !Type.VOID_TYPE.equals(retType) || isThrowAnalysis()) {
            if (direction != null) {
              List<EKey> keys = new ArrayList<>();
              for (int i = shift; i < values.size(); i++) {
                Direction direction = null;
                BasicValue value = values.get(i);
                if (value instanceof ParamValue) {
                  direction = this.direction.withIndex(i - shift);
                }
                else {
                  Value constant = Value.fromBasicValue(value);
                  if (constant != null) {
                    direction = this.direction.withValue(i - shift, constant);
                  }
                }
                if (direction != null) {
                  keys.add(new EKey(method, direction, stable));
                }
              }
              if (isRefRetType) {
                keys.add(new EKey(method, isThrowAnalysis() ? Throw : Out, stable));
              }
              if (!keys.isEmpty()) {
                if (isThrowAnalysis()) {
                  throwKeys = keys;
                }
                return new CallResultValue(retType, keys);
              }
            }
            else if (isRefRetType) {
              return new CallResultValue(retType, List.of(new EKey(method, Out, stable)));
            }
          }
        }
        case INVOKEDYNAMIC -> {
          InvokeDynamicInsnNode indy = (InvokeDynamicInsnNode)insn;
          if (LambdaIndy.from(indy) != null || ClassDataIndexer.STRING_CONCAT_FACTORY.equals(indy.bsm.getOwner())) {
            // indy producing lambda or string concatenation is never null
            return new NotNullValue(Type.getReturnType(indy.desc));
          }
        }
        case MULTIANEWARRAY -> {
          return new NotNullValue(super.naryOperation(insn, values).getType());
        }
        default -> {
        }
      }
    }
    return super.naryOperation(insn, values);
  }
@Override
  public BasicValue naryOperation(AbstractInsnNode insn, List<? extends BasicValue> values)