code: def index(self, val, start=None, stop=None):
          
          _len = self._len
  
          if not _len:
              raise ValueError('{0!r} is not in list'.format(val))
  
          if start is None:
              start = 0
          if start < 0:
              start += _len
          if start < 0:
              start = 0
  
          if stop is None:
              stop = _len
          if stop < 0:
              stop += _len
          if stop > _len:
              stop = _len
  
          if stop <= start:
              raise ValueError('{0!r} is not in list'.format(val))
  
          _maxes = self._maxes
          key = self._key(val)
          pos = bisect_left(_maxes, key)
  
          if pos == len(_maxes):
              raise ValueError('{0!r} is not in list'.format(val))
  
          stop -= 1
          _lists = self._lists
          _keys = self._keys
          idx = bisect_left(_keys[pos], key)
          len_keys = len(_keys)
          len_sublist = len(_keys[pos])
  
          while True:
              if _keys[pos][idx] != key:
                  raise ValueError('{0!r} is not in list'.format(val))
              if _lists[pos][idx] == val:
                  loc = self._loc(pos, idx)
                  if start <= loc <= stop:
                      return loc
                  elif loc > stop:
                      break
              idx += 1
              if idx == len_sublist:
                  pos += 1
                  if pos == len_keys:
                      raise ValueError('{0!r} is not in list'.format(val))
                  len_sublist = len(_keys[pos])
                  idx = 0
  
          raise ValueError('{0!r} is not in list'.format(val))
docs: Return the smallest *k* such that L[k] == val and i <= k < j`.  Raises
          ValueError if *val* is not present.  *stop* defaults to the end of the
          list. *start* defaults to the beginning. Negative indices are supported,
          as for slice indices.