private static int checkParameterizedType(
     String subroutineName,
     ParameterizedType expectedType,
     ArgumentsList arguments,
     List<LispObject> args,
     int argsCounter,
     int i) {
   Type rawType = expectedType.getRawType();
   Type expectedTypeArguments = expectedType.getActualTypeArguments()[0];
   try {
     if (((Class) rawType).isInstance(args.get(argsCounter))) {
       Type actualTypeArguments =
           ((ParameterizedType) (Type) args.get(argsCounter).getClass())
               .getActualTypeArguments()[0];
       if (!expectedTypeArguments.equals(actualTypeArguments)) {
         throw new WrongTypeArgumentException(
             ((Class) rawType).getSimpleName()
                 + "<"
                 + ((Class) expectedTypeArguments).getSimpleName()
                 + ">",
             args.get(argsCounter));
       }
       arguments.setValue(i, args.get(argsCounter));
       return argsCounter + 1;
     } else {
       if (arguments.isOptional(i)) return -1;
       throw new WrongTypeArgumentException(expectedType.toString(), args.get(argsCounter));
     }
   } catch (IndexOutOfBoundsException e) {
     if (arguments.isOptional(i)) return -1;
     throw new WrongNumberOfArgumentsException(subroutineName, i);
   }
 }
 private static void checkArguments(
     String subroutineName, ArgumentsList arguments, List<LispObject> args) {
   int argsCounter = 0;
   for (int i = 0; i != arguments.getSize(); ++i) {
     Type expectedType = arguments.getType(i);
     if (i == 0 && expectedType.equals(Environment.class)) continue;
     if (ParameterizedType.class.isInstance(expectedType)) {
       argsCounter =
           checkParameterizedType(
               subroutineName, (ParameterizedType) expectedType, arguments, args, argsCounter, i);
     } else if (((Class) expectedType).isArray()) {
       argsCounter = checkArray((Class) expectedType, arguments, args, argsCounter, i);
     } else {
       argsCounter =
           checkSingleArgument(
               subroutineName, (Class) expectedType, arguments, args, argsCounter, i);
     }
     if (argsCounter == -1) break;
   }
 }