I think here we should be consistent with the table.unpack()
behaviour, i.e. throw an error.
When handling huge tables in a program, special considerations
are unavoidable.
Just like with table.unpack() one could unpack values from a huge
table in chunks to avoid stack overflow, same can be applied to
the proposed table.remove().
Here's an updated version that checks for the stack space.
static int tremove (lua_State *L) {
lua_Integer i;
lua_Integer size = aux_getn(L, 1, TAB_RW);
lua_Integer pos = luaL_optinteger(L, 2, size);
lua_Integer count = luaL_optinteger(L, 3, 1);
if(count < 0) { /* if 'count' is negative, convert the call to 'table.remove(t, pos + count + 1, -count)' */
lua_pop(L, 2);
lua_pushinteger(L, pos + count + 1);
lua_pushinteger(L, -count);
return tremove(L);
} /* 'count' from now on is strictly non-negative */
/* check whether 'pos' is in [1, size + 1] */
luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2,
"position out of bounds");
if (l_unlikely(count >= (unsigned int)INT_MAX ||
!lua_checkstack(L, (int)(count + 1))))
return luaL_error(L, "too many results to remove");
for(i = 0; i < count; i++) /* push 'count' elements onto the stack starting from 'pos' */
lua_geti(L, 1, pos + i);
for (i = pos ; i <= size; i++) { /* shift the rest */
lua_geti(L, 1, i + count);
lua_seti(L, 1, i); /* t[pos] = t[pos + count] */
}
if(pos + count - 1 <= size) { /* remove the tail (if present) */
for(i = size - count + 1; i <= size; i++) {
lua_pushnil(L);
lua_seti(L, 1, i);
}
}
return count;
}