mirror of https://github.com/lua/lua
concat TM can yield
This commit is contained in:
parent
84b3daebbd
commit
b472098493
32
ldo.c
32
ldo.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 2.49 2008/10/28 16:53:16 roberto Exp roberto $
|
** $Id: ldo.c,v 2.50 2008/10/30 15:39:30 roberto Exp roberto $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -390,7 +390,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
|
||||||
static void unroll (lua_State *L) {
|
static void unroll (lua_State *L) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Instruction inst;
|
Instruction inst;
|
||||||
luaV_execute(L); /* execute up to higher C 'boundary' */
|
luaV_execute(L); /* execute down to higher C 'boundary' */
|
||||||
if (L->ci == L->base_ci) { /* stack is empty? */
|
if (L->ci == L->base_ci) { /* stack is empty? */
|
||||||
lua_assert(L->baseCcalls == G(L)->nCcalls);
|
lua_assert(L->baseCcalls == G(L)->nCcalls);
|
||||||
return; /* coroutine finished normally */
|
return; /* coroutine finished normally */
|
||||||
|
@ -405,27 +405,38 @@ static void unroll (lua_State *L) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_LE: case OP_LT: case OP_EQ: {
|
case OP_LE: case OP_LT: case OP_EQ: {
|
||||||
int res;
|
int res = !l_isfalse(L->top - 1);
|
||||||
L->top--;
|
L->top--;
|
||||||
res = !l_isfalse(L->top);
|
/* metamethod should not be called when operand is K */
|
||||||
/* cannot call metamethod with K operand */
|
|
||||||
lua_assert(!ISK(GETARG_B(inst)));
|
lua_assert(!ISK(GETARG_B(inst)));
|
||||||
if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */
|
if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */
|
||||||
ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE)))
|
ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE)))
|
||||||
res = !res; /* invert result */
|
res = !res; /* invert result */
|
||||||
lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP);
|
lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP);
|
||||||
if (res == GETARG_A(inst))
|
if (res != GETARG_A(inst)) /* condition failed? */
|
||||||
L->savedpc += GETARG_sBx(*L->savedpc); /* jump */
|
L->savedpc++; /* skip jump instruction */
|
||||||
L->savedpc++; /* skip jump instruction */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_SETGLOBAL: case OP_SETTABLE:
|
case OP_CONCAT: {
|
||||||
break; /* nothing to be done */
|
StkId top = L->top - 1; /* top when __concat was called */
|
||||||
|
int last = cast_int(top - L->base) - 2; /* last element and ... */
|
||||||
|
int b = GETARG_B(inst); /* ... first element to concatenate */
|
||||||
|
int total = last - b + 1; /* number of elements to concatenate */
|
||||||
|
setobj2s(L, top - 2, top); /* put TM result in proper position */
|
||||||
|
L->top = L->ci->top; /* correct top */
|
||||||
|
if (total > 1) /* are there elements to concat? */
|
||||||
|
luaV_concat(L, total, last); /* concat them (may yield again) */
|
||||||
|
/* move final result to final position */
|
||||||
|
setobj2s(L, L->base + GETARG_A(inst), L->base + b);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
case OP_TFORCALL: {
|
case OP_TFORCALL: {
|
||||||
lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP);
|
lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP);
|
||||||
L->top = L->ci->top; /* correct top */
|
L->top = L->ci->top; /* correct top */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_SETGLOBAL: case OP_SETTABLE:
|
||||||
|
break; /* nothing to be done */
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,7 +511,6 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
|
||||||
LUA_API int lua_yield (lua_State *L, int nresults) {
|
LUA_API int lua_yield (lua_State *L, int nresults) {
|
||||||
luai_userstateyield(L, nresults);
|
luai_userstateyield(L, nresults);
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
/*printf("yield: %d - %d\n", G(L)->nCcalls, L->baseCcalls);*/
|
|
||||||
if (G(L)->nCcalls > L->baseCcalls)
|
if (G(L)->nCcalls > L->baseCcalls)
|
||||||
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
|
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
|
||||||
L->base = L->top - nresults; /* protect stack slots below */
|
L->base = L->top - nresults; /* protect stack slots below */
|
||||||
|
|
4
lvm.c
4
lvm.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.78 2008/10/28 16:53:16 roberto Exp roberto $
|
** $Id: lvm.c,v 2.79 2008/10/30 15:39:30 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -271,8 +271,10 @@ void luaV_concat (lua_State *L, int total, int last) {
|
||||||
StkId top = L->base + last + 1;
|
StkId top = L->base + last + 1;
|
||||||
int n = 2; /* number of elements handled in this pass (at least 2) */
|
int n = 2; /* number of elements handled in this pass (at least 2) */
|
||||||
if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
|
if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
|
||||||
|
L->top = top; /* set top to current position (in case of yield) */
|
||||||
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
|
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
|
||||||
luaG_concaterror(L, top-2, top-1);
|
luaG_concaterror(L, top-2, top-1);
|
||||||
|
L->top = L->ci->top; /* restore top */
|
||||||
}
|
}
|
||||||
else if (tsvalue(top-1)->len == 0) { /* second operand is empty? */
|
else if (tsvalue(top-1)->len == 0) { /* second operand is empty? */
|
||||||
(void)tostring(L, top - 2); /* result is first operand */ ;
|
(void)tostring(L, top - 2); /* result is first operand */ ;
|
||||||
|
|
Loading…
Reference in New Issue