return 0;
}
-LJLIB_CF(table_remove) LJLIB_REC(.)
-{
- GCtab *t = lj_lib_checktab(L, 1);
- int32_t e = (int32_t)lj_tab_len(t);
- int32_t pos = lj_lib_optint(L, 2, e);
- if (!(1 <= pos && pos <= e)) /* Nothing to remove? */
- return 0;
- lua_rawgeti(L, 1, pos); /* Get previous value. */
- /* NOBARRIER: This just moves existing elements around. */
- for (; pos < e; pos++) {
- cTValue *src = lj_tab_getint(t, pos+1);
- TValue *dst = lj_tab_setint(L, t, pos);
- if (src) {
- copyTV(L, dst, src);
- } else {
- setnilV(dst);
- }
- }
- setnilV(lj_tab_setint(L, t, e)); /* Remove (last) value. */
- return 1; /* Return previous value. */
-}
+LJLIB_LUA(table_remove) /*
+ function(t, pos)
+ CHECK_tab(t)
+ local len = #t
+ if pos == nil then
+ if len ~= 0 then
+ local old = t[len]
+ t[len] = nil
+ return old
+ end
+ else
+ CHECK_int(pos)
+ if pos >= 1 and pos <= len then
+ local old = t[pos]
+ for i=pos+1,len do
+ t[i-1] = t[i]
+ end
+ t[len] = nil
+ return old
+ end
+ end
+ end
+*/
-LJLIB_CF(table_concat)
+LJLIB_CF(table_concat) LJLIB_REC(.)
{
- luaL_Buffer b;
GCtab *t = lj_lib_checktab(L, 1);
GCstr *sep = lj_lib_optstr(L, 2);
- MSize seplen = sep ? sep->len : 0;
int32_t i = lj_lib_optint(L, 3, 1);
- int32_t e = L->base+3 < L->top ? lj_lib_checkint(L, 4) :
- (int32_t)lj_tab_len(t);
+ int32_t e = (L->base+3 < L->top && !tvisnil(L->base+3)) ?
+ lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t);
- luaL_buffinit(L, &b);
- if (i <= e) {
- for (;;) {
- cTValue *o;
- lua_rawgeti(L, 1, i);
- o = L->top-1;
- if (!(tvisstr(o) || tvisnumber(o)))
- lj_err_callerv(L, LJ_ERR_TABCAT, lj_typename(o), i);
- luaL_addvalue(&b);
- if (i++ == e) break;
- if (seplen)
- luaL_addlstring(&b, strdata(sep), seplen);
- }
+ SBuf *sb = lj_buf_tmp_(L);
+ SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e);
+ if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */
+ int32_t idx = (int32_t)(intptr_t)sbufP(sb);
+ cTValue *o = lj_tab_getint(t, idx);
+ lj_err_callerv(L, LJ_ERR_TABCAT,
+ lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx);
}
- luaL_pushresult(&b);
+ setstrV(L, L->top-1, lj_buf_str(L, sbx));
+ lj_gc_check(L);
return 1;
}
} /* else: Interpreter will throw. */
}
- TRef sep = 0, tri = 0, tre = 0;
- TRef hdr, tr;
- if (J->base[1]) {
- sep = lj_ir_tostr(J, J->base[1]);
- if (J->base[2]) {
- tri = lj_opt_narrow_toint(J, J->base[2]);
- if (J->base[3])
- tre = lj_opt_narrow_toint(J, J->base[3]);
- }
- } else {
- sep = lj_ir_knull(J, IRT_STR);
- }
- if (!tri) tri = lj_ir_kint(J, 1);
- if (!tre) tre = lj_ir_call(J, IRCALL_lj_tab_len, tab);
- hdr = emitir(IRT(IR_BUFHDR, IRT_P32),
- lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET);
- tr = lj_ir_call(J, IRCALL_lj_buf_puttab, hdr, tab, sep, tri, tre);
+static void LJ_FASTCALL recff_table_concat(jit_State *J, RecordFFData *rd)
+{
+ TRef tab = J->base[0];
+ if (tref_istab(tab)) {
++ TRef sep = !tref_isnil(J->base[1]) ?
++ lj_ir_tostr(J, J->base[1]) : lj_ir_knull(J, IRT_STR);
++ TRef tri = (J->base[1] && !tref_isnil(J->base[2])) ?
++ lj_opt_narrow_toint(J, J->base[2]) : lj_ir_kint(J, 1);
++ TRef tre = (J->base[1] && J->base[2] && !tref_isnil(J->base[3])) ?
++ lj_opt_narrow_toint(J, J->base[3]) :
++ lj_ir_call(J, IRCALL_lj_tab_len, tab);
++ TRef hdr = emitir(IRT(IR_BUFHDR, IRT_P32),
++ lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET);
++ TRef tr = lj_ir_call(J, IRCALL_lj_buf_puttab, hdr, tab, sep, tri, tre);
+ emitir(IRTG(IR_NE, IRT_PTR), tr, lj_ir_kptr(J, NULL));
+ J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
+ } /* else: Interpreter will throw. */
+ UNUSED(rd);
+}
+
/* -- I/O library fast functions ------------------------------------------ */
/* Get FILE* for I/O function. Any I/O error aborts recording, so there's