code: function splitFreeBlock(
    state: BlockMapType,
    addr: number,
    blockSize: number,
    splitAddr: number,
    splitSize: number
  ): BlockMapType {
    var bottomGap = splitAddr - addr;
    var topGap = endAddr(addr, blockSize) - endAddr(splitAddr, splitSize);
    if (bottomGap > 0 && topGap === 0) {
      return resizeFreeBlock(state, addr, blockSize, addr, bottomGap);
    }
    if (topGap > 0 && bottomGap === 0) {
      return resizeFreeBlock(
        state,
        addr,
        blockSize,
        endAddr(addr, blockSize) - topGap,
        topGap
      );
    }
    if (topGap > 0 && bottomGap > 0) {
      state = popFreeBlock(state, addr, blockSize);
      state = pushFreeBlock(state, addr, bottomGap);
      state = pushFreeBlock(state, endAddr(addr, blockSize) - topGap, topGap);
      return state;
    }
    return state;
  }
docs: Split a block into two or three parts.
  
  addr/blockSize is the original block that is currently in state.
  splitAddr/splitSize is being removed from it (its being allocated)
  and the original free block will be resized
  
  If splitAddr/splitSize is at the top or bottom edge then you get 2 parts.
  If in the middle then you get 3.
  
  @param {Immutable.Map} state
  @param {int} addr
  @param {int} blockSize
  @param {int} splitAddr
  @param {int} splitSize
  @returns {Immutable.Map} state