docs: def _insert_and_merge(self, address, size, sort, idx):
          """
          Determines whether the block specified by (address, size) should be merged with adjacent blocks.
  
          :param int address: Starting address of the block to be merged.
          :param int size: Size of the block to be merged.
          :param str sort: Type of the block.
          :param int idx: ID of the address.
          :return: None
          """
  
          # sanity check
          if idx > 0 and address + size <= self._list[idx - 1].start:
              # There is a bug, since _list[idx] must be the closest one that is less than the current segment
              l.warning("BUG FOUND: new segment should always be greater than _list[idx].")
              # Anyways, let's fix it.
              self._insert_and_merge(address, size, sort, idx - 1)
              return
  
          # Insert the block first
          # The new block might be overlapping with other blocks. _insert_and_merge_core will fix the overlapping.
          if idx == len(self._list):
              self._list.append(Segment(address, address + size, sort))
          else:
              self._list.insert(idx, Segment(address, address + size, sort))
          # Apparently _bytes_occupied will be wrong if the new block overlaps with any existing block. We will fix it
          # later
          self._bytes_occupied += size
  
          # Search forward to merge blocks if necessary
          pos = idx
          while pos < len(self._list):
              merged, pos, bytes_change = self._insert_and_merge_core(pos, "forward")
  
              if not merged:
                  break
  
              self._bytes_occupied += bytes_change
  
          # Search backward to merge blocks if necessary
          if pos >= len(self._list):
              pos = len(self._list) - 1
  
          while pos > 0:
              merged, pos, bytes_change = self._insert_and_merge_core(pos, "backward")
  
              if not merged:
                  break
  
              self._bytes_occupied += bytes_change