allocateMemSpace :: a -> MemSpace a -> ExceptT GrLang.Error LuaGrLang Lua.LuaInteger
allocateMemSpace value memSpace = do
  idx <- getFreeIndex memSpace
  liftIO $ do
    writeArray (cells memSpace) idx (Just value)
    freeVals <- readIORef (numFreeValues memSpace)
    let freeVals' = freeVals - 1
    writeIORef (numFreeValues memSpace) freeVals'
    writeIORef (nextFreeIndex memSpace) =<<
      if freeVals' < 1
        then return Nothing
        else Just <$> findNextFreeIndex (idx+1)
    return (fromIntegral idx)
  where
    getFreeIndex memSpace = do
      freeIdx <- liftIO $ readIORef (nextFreeIndex memSpace)
      case freeIdx of
        Just idx -> return idx
        Nothing -> do
          liftLua $ Lua.gc Lua.GCCOLLECT 0
          freeIdx <- liftIO $ readIORef (nextFreeIndex memSpace)
          case freeIdx of
            Just idx -> return idx
            Nothing -> GrLang.throwError Nothing "Out of GrLang memory"

    findNextFreeIndex idx = do
      val <- readArray (cells memSpace) idx
      case val of
        Nothing -> return idx
        Just _ -> findNextFreeIndex (idx+1)
allocateMemSpace :: a -> MemSpace a -> ExceptT GrLang.Error LuaGrLang Lua.LuaInteger
allocateMemSpace value memSpace = do
  idx <- getFreeIndex memSpace
  liftIO $ do
    writeArray (cells memSpace) idx (Just value)
    freeVals <- readIORef (numFreeValues memSpace)
    let freeVals' = freeVals - 1
    writeIORef (numFreeValues memSpace) freeVals'
    writeIORef (nextFreeIndex memSpace) =<<
      if freeVals' < 1
        then return Nothing
        else Just <$> findNextFreeIndex (idx+1)
    return (fromIntegral idx)
  where
    getFreeIndex memSpace = do
      freeIdx <- liftIO $ readIORef (nextFreeIndex memSpace)
      case freeIdx of
        Just idx -> return idx
        Nothing -> do
          liftLua $ Lua.gc Lua.GCCOLLECT 0
          freeIdx <- liftIO $ readIORef (nextFreeIndex memSpace)
          case freeIdx of
            Just idx -> return idx
            Nothing -> GrLang.throwError Nothing "Out of GrLang memory"

    findNextFreeIndex idx = do
      val <- readArray (cells memSpace) idx
      case val of
        Nothing -> return idx
        Just _ -> findNextFreeIndex (idx+1)
allocateMemSpace value memSpace = do
  idx <- getFreeIndex memSpace
  liftIO $ do
    writeArray (cells memSpace) idx (Just value)
    freeVals <- readIORef (numFreeValues memSpace)
    let freeVals' = freeVals - 1
    writeIORef (numFreeValues memSpace) freeVals'
    writeIORef (nextFreeIndex memSpace) =<<
      if freeVals' < 1
        then return Nothing
        else Just <$> findNextFreeIndex (idx+1)
    return (fromIntegral idx)
  where
    getFreeIndex memSpace = do
      freeIdx <- liftIO $ readIORef (nextFreeIndex memSpace)
      case freeIdx of
        Just idx -> return idx
        Nothing -> do
          liftLua $ Lua.gc Lua.GCCOLLECT 0
          freeIdx <- liftIO $ readIORef (nextFreeIndex memSpace)
          case freeIdx of
            Just idx -> return idx
            Nothing -> GrLang.throwError Nothing "Out of GrLang memory"

    findNextFreeIndex idx = do
      val <- readArray (cells memSpace) idx
      case val of
        Nothing -> return idx
        Just _ -> findNextFreeIndex (idx+1)