summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lbaselib.c81
-rw-r--r--lcode.c3
-rw-r--r--ldebug.c15
-rw-r--r--ldo.c126
-rw-r--r--lopcodes.h19
-rw-r--r--lparser.c10
-rw-r--r--lstate.c1
-rw-r--r--lstate.h6
-rw-r--r--lua.h17
-rw-r--r--lvm.c86
-rw-r--r--lvm.h2
11 files changed, 229 insertions, 137 deletions
diff --git a/lbaselib.c b/lbaselib.c
index cb914f18..6cd97d95 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -148,30 +148,6 @@ static int luaB_eventtable (lua_State *L) {
}
-static int luaB_weakmode (lua_State *L) {
- const char *mode = luaL_check_string(L, 2);
- luaL_check_type(L, 1, LUA_TTABLE);
- if (*mode == '?') {
- char buff[3];
- char *s = buff;
- int imode = lua_getweakmode(L, 1);
- if (imode & LUA_WEAK_KEY) *s++ = 'k';
- if (imode & LUA_WEAK_VALUE) *s++ = 'v';
- *s = '\0';
- lua_pushstring(L, buff);
- return 1;
- }
- else {
- int imode = 0;
- if (strchr(mode, 'k')) imode |= LUA_WEAK_KEY;
- if (strchr(mode, 'v')) imode |= LUA_WEAK_VALUE;
- lua_pushvalue(L, 1); /* push table */
- lua_setweakmode(L, imode);
- return 1; /* return the table */
- }
-}
-
-
static int luaB_globals (lua_State *L) {
lua_getglobals(L); /* value to be returned */
if (!lua_isnone(L, 1)) {
@@ -287,6 +263,14 @@ static int luaB_loadfile (lua_State *L) {
}
+static int luaB_assert (lua_State *L) {
+ luaL_check_any(L, 1);
+ if (!lua_istrue(L, 1))
+ luaL_verror(L, "assertion failed! %.90s", luaL_opt_string(L, 2, ""));
+ lua_settop(L, 1);
+ return 1;
+}
+
#define LUA_PATH "LUA_PATH"
@@ -428,6 +412,40 @@ static int luaB_tostring (lua_State *L) {
}
+static int luaB_resume (lua_State *L) {
+ lua_State *co = (lua_State *)lua_touserdata(L, lua_upvalueindex(1));
+ lua_resume(L, co);
+ return 0;
+}
+
+
+static int luaB_coroutine (lua_State *L) {
+ lua_State *NL;
+ int ref;
+ luaL_check_type(L, 1, LUA_TFUNCTION);
+ NL = lua_newthread(L, 0);
+ if (NL == NULL) lua_error(L, "unable to create new thread");
+ /* move function from L to NL */
+ ref = lua_ref(L, 1);
+ lua_getref(NL, ref);
+ lua_unref(L, ref);
+ lua_cobegin(NL, 0);
+ lua_newuserdatabox(L, NL);
+ lua_pushcclosure(L, luaB_resume, 1);
+ return 1;
+}
+
+
+static int luaB_yield (lua_State *L) {
+ return lua_yield(L, 0);
+}
+
+
+/*
+** {======================================================
+** Auxiliar table-related functions
+*/
+
static int luaB_foreachi (lua_State *L) {
int n, i;
luaL_check_type(L, 1, LUA_TTABLE);
@@ -464,15 +482,6 @@ static int luaB_foreach (lua_State *L) {
}
-static int luaB_assert (lua_State *L) {
- luaL_check_any(L, 1);
- if (!lua_istrue(L, 1))
- luaL_verror(L, "assertion failed! %.90s", luaL_opt_string(L, 2, ""));
- lua_settop(L, 1);
- return 1;
-}
-
-
static int luaB_getn (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
lua_pushnumber(L, lua_getn(L, 1));
@@ -521,7 +530,6 @@ static int luaB_tremove (lua_State *L) {
-
/*
** {======================================================
** Quicksort
@@ -627,6 +635,8 @@ static int luaB_sort (lua_State *L) {
/* }====================================================== */
+/* }====================================================== */
+
static const luaL_reg base_funcs[] = {
@@ -634,6 +644,7 @@ static const luaL_reg base_funcs[] = {
{LUA_ERRORMESSAGE, luaB__ERRORMESSAGE},
{"call", luaB_call},
{"collectgarbage", luaB_collectgarbage},
+ {"coroutine", luaB_coroutine},
{"dofile", luaB_dofile},
{"dostring", luaB_dostring},
{"error", luaB_error},
@@ -659,7 +670,7 @@ static const luaL_reg base_funcs[] = {
{"tinsert", luaB_tinsert},
{"tremove", luaB_tremove},
{"unpack", luaB_unpack},
- {"weakmode", luaB_weakmode}
+ {"yield", luaB_yield}
};
diff --git a/lcode.c b/lcode.c
index 4e8d23c1..a93b52b9 100644
--- a/lcode.c
+++ b/lcode.c
@@ -264,8 +264,7 @@ static int nil_constant (FuncState *fs) {
void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) {
if (e->k == VCALL) { /* expression is an open function call? */
- if (nresults == LUA_MULTRET) nresults = NO_REG;
- SETARG_C(getcode(fs, e), nresults);
+ SETARG_C(getcode(fs, e), nresults+1);
if (nresults == 1) { /* `regular' expression? */
e->k = VNONRELOC;
e->u.i.info = GETARG_A(getcode(fs, e));
diff --git a/ldebug.c b/ldebug.c
index 16a3c5c5..17a0f11a 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
+** $Id: ldebug.c,v 1.96 2001/12/18 20:52:30 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
@@ -303,7 +303,7 @@ static int checkopenop (const Proto *pt, int pc) {
switch (GET_OPCODE(i)) {
case OP_CALL:
case OP_RETURN: {
- check(GETARG_B(i) == NO_REG);
+ check(GETARG_B(i) == 0);
return 1;
}
case OP_SETLISTO: return 1;
@@ -391,10 +391,11 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
break;
}
case OP_CALL: {
- if (b != NO_REG) {
- checkreg(pt, a+b);
+ if (b != 0) {
+ checkreg(pt, a+b-1);
}
- if (c == NO_REG) {
+ c--; /* c = num. returns */
+ if (c == LUA_MULTRET) {
check(checkopenop(pt, pc));
}
else if (c != 0)
@@ -403,8 +404,8 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
break;
}
case OP_RETURN: {
- if (b != NO_REG && b != 0)
- checkreg(pt, a+b-1);
+ b--; /* b = num. returns */
+ if (b > 0) checkreg(pt, a+b-1);
break;
}
case OP_FORPREP:
diff --git a/ldo.c b/ldo.c
index fedc0e35..c161cfe8 100644
--- a/ldo.c
+++ b/ldo.c
@@ -18,6 +18,7 @@
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
+#include "lopcodes.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
@@ -112,8 +113,6 @@ void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event) {
}
-#define newci(L) ((++L->ci == L->end_ci) ? growci(L) : L->ci)
-
static CallInfo *growci (lua_State *L) {
lua_assert(L->ci == L->end_ci);
luaM_reallocvector(L, L->base_ci, L->size_ci, 2*L->size_ci, CallInfo);
@@ -124,9 +123,32 @@ static CallInfo *growci (lua_State *L) {
}
+static void adjust_varargs (lua_State *L, StkId base, int nfixargs) {
+ int i;
+ Table *htab;
+ TObject n, nname;
+ StkId firstvar = base + nfixargs; /* position of first vararg */
+ if (L->top < firstvar) {
+ luaD_checkstack(L, firstvar - L->top);
+ while (L->top < firstvar)
+ setnilvalue(L->top++);
+ }
+ htab = luaH_new(L, 0, 0);
+ for (i=0; firstvar+i<L->top; i++)
+ luaH_setnum(L, htab, i+1, firstvar+i);
+ /* store counter in field `n' */
+ setnvalue(&n, i);
+ setsvalue(&nname, luaS_newliteral(L, "n"));
+ luaH_set(L, htab, &nname, &n);
+ L->top = firstvar; /* remove elements from the stack */
+ sethvalue(L->top, htab);
+ incr_top;
+}
+
+
StkId luaD_precall (lua_State *L, StkId func) {
CallInfo *ci;
- int n;
+ LClosure *cl;
if (ttype(func) != LUA_TFUNCTION) {
/* `func' is not a function; check the `function' tag method */
const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
@@ -135,21 +157,39 @@ StkId luaD_precall (lua_State *L, StkId func) {
luaD_openstack(L, func);
setobj(func, tm); /* tag method is the new function to be called */
}
- ci = newci(L);
+ ci = ++L->ci;
+ if (L->ci == L->end_ci) ci = growci(L);
ci->base = func+1;
- ci->savedpc = NULL;
if (L->callhook)
luaD_callHook(L, L->callhook, "call");
- if (!clvalue(func)->c.isC) return NULL;
- /* if is a C function, call it */
- luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
- lua_unlock(L);
+ cl = &clvalue(func)->l;
+ if (!cl->isC) { /* Lua function? prepare its call */
+ StkId base = func+1;
+ Proto *p = cl->p;
+ ci->linehook = L->linehook;
+ ci->savedpc = p->code; /* starting point */
+ if (p->is_vararg) /* varargs? */
+ adjust_varargs(L, base, p->numparams);
+ if (base > L->stack_last - p->maxstacksize)
+ luaD_stackerror(L);
+ ci->top = base + p->maxstacksize;
+ while (L->top < ci->top)
+ setnilvalue(L->top++);
+ L->top = ci->top;
+ return NULL;
+ }
+ else { /* if is a C function, call it */
+ int n;
+ ci->savedpc = NULL;
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ lua_unlock(L);
#if LUA_COMPATUPVALUES
- lua_pushupvalues(L);
+ lua_pushupvalues(L);
#endif
- n = (*clvalue(func)->c.f)(L); /* do the actual call */
- lua_lock(L);
- return L->top - n;
+ n = (*clvalue(func)->c.f)(L); /* do the actual call */
+ lua_lock(L);
+ return L->top - n;
+ }
}
@@ -179,12 +219,60 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
*/
void luaD_call (lua_State *L, StkId func, int nResults) {
StkId firstResult = luaD_precall(L, func);
- if (firstResult == NULL) /* is a Lua function? */
- firstResult = luaV_execute(L, &clvalue(func)->l, func+1); /* call it */
+ if (firstResult == NULL) { /* is a Lua function? */
+ firstResult = luaV_execute(L); /* call it */
+ if (firstResult == NULL) {
+ luaD_poscall(L, 0, L->top);
+ luaD_error(L, "attempt to `yield' across tag-method/C-call boundary");
+ }
+ }
luaD_poscall(L, nResults, firstResult);
}
+LUA_API void lua_cobegin (lua_State *L, int nargs) {
+ StkId func;
+ lua_lock(L);
+ func = L->top - (nargs+1); /* coroutine main function */
+ if (luaD_precall(L, func) != NULL)
+ luaD_error(L, "coroutine started with a C function");
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_resume (lua_State *L, lua_State *co) {
+ StkId firstResult;
+ lua_lock(L);
+ if (co->ci->savedpc == NULL) /* no activation record? */
+ luaD_error(L, "thread is dead - cannot be resumed");
+ lua_assert(co->errorJmp == NULL);
+ co->errorJmp = L->errorJmp;
+ firstResult = luaV_execute(co);
+ if (firstResult != NULL) /* `return'? */
+ luaD_poscall(co, LUA_MULTRET, firstResult); /* ends this coroutine */
+ else { /* `yield' */
+ int nresults = GETARG_C(*((co->ci-1)->savedpc - 1)) - 1;
+ luaD_poscall(co, nresults, co->top); /* complete it */
+ if (nresults >= 0) co->top = co->ci->top;
+ }
+ co->errorJmp = NULL;
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_yield (lua_State *L, int nresults) {
+ CallInfo *ci;
+ int ibase;
+ lua_lock(L);
+ ci = L->ci - 1; /* call info of calling function */
+ if (ci->pc == NULL)
+ luaD_error(L, "cannot `yield' a C function");
+ ibase = L->top - ci->base;
+ lua_unlock(L);
+ return ibase;
+}
+
+
/*
** Execute a protected call.
*/
@@ -330,7 +418,13 @@ static void message (lua_State *L, const char *s) {
** Reports an error, and jumps up to the available recovery label
*/
void luaD_error (lua_State *L, const char *s) {
- if (s) message(L, s);
+ if (s) {
+ if (L->ci->savedpc) { /* error in Lua function preamble? */
+ L->ci->savedpc = NULL; /* pretend function was already running */
+ L->ci->pc = NULL;
+ }
+ message(L, s);
+ }
luaD_breakrun(L, LUA_ERRRUN);
}
diff --git a/lopcodes.h b/lopcodes.h
index b9539a9a..722e3d6a 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -168,8 +168,8 @@ OP_TESTGE,/* A C test := (R(A) >= R/K(C)) */
OP_TESTT,/* A B test := R(B); if (test) R(A) := R(B) */
OP_TESTF,/* A B test := not R(B); if (test) R(A) := R(B) */
-OP_CALL,/* A B C R(A), ... ,R(A+C-1) := R(A)(R(A+1), ... ,R(A+B))*/
-OP_RETURN,/* A B return R(A), ... ,R(A+B-1) (see (3)) */
+OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))*/
+OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see (3)) */
OP_FORPREP,/* A sBc */
OP_FORLOOP,/* A sBc */
@@ -182,6 +182,9 @@ OP_SETLISTO,/* A Bc */
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */
+/*----------------------------------------------------------------------
+pseudo-instructions (interruptions): cannot occur in regular code
+------------------------------------------------------------------------*/
} OpCode;
@@ -194,11 +197,11 @@ OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */
(1) In the current implementation there is no `test' variable;
instructions OP_TEST* and OP_CJMP must always occur together.
- (2) In OP_CALL, if (B == NO_REG) then B = top. C is the number of returns,
- and can be NO_REG. OP_CALL can set `top' to last_result+1, so
+ (2) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
+ and can be 0: OP_CALL then sets `top' to last_result+1, so
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
- (3) In OP_RETURN, if (B == NO_REG) then return up to `top'
+ (3) In OP_RETURN, if (B == 0) then return up to `top'
===========================================================================*/
@@ -221,6 +224,12 @@ extern const lu_byte luaP_opmodes[NUM_OPCODES];
/*
+** constant instructions
+*/
+
+extern const Instruction luaP_yieldop;
+
+/*
** opcode names (only included when compiled with LUA_OPNAMES)
*/
extern const char *const luaP_opnames[];
diff --git a/lparser.c b/lparser.c
index 2a11fef6..0e43b2ba 100644
--- a/lparser.c
+++ b/lparser.c
@@ -335,7 +335,7 @@ static void close_func (LexState *ls) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
removelocalvars(ls, fs->nactloc, 0);
- luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */
+ luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */
luaK_getlabel(fs); /* close eventual list of pending jumps */
lua_assert(G(L)->roottable == fs->h);
G(L)->roottable = fs->h->next;
@@ -449,13 +449,13 @@ static void funcargs (LexState *ls, expdesc *f) {
lua_assert(f->k == VNONRELOC);
base = f->u.i.info; /* base register for call */
if (args.k == VCALL)
- nparams = NO_REG; /* open call */
+ nparams = LUA_MULTRET; /* open call */
else {
if (args.k != VVOID)
luaK_exp2nextreg(fs, &args); /* close last argument */
nparams = fs->freereg - (base+1);
}
- init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams, 1));
+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
fs->freereg = base+1; /* call remove function and arguments and leaves
(unless changed) one result */
}
@@ -1136,7 +1136,7 @@ static void retstat (LexState *ls) {
if (e.k == VCALL) {
luaK_setcallreturns(fs, &e, LUA_MULTRET);
first = fs->nactloc;
- nret = NO_REG; /* return all values */
+ nret = LUA_MULTRET; /* return all values */
}
else {
luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
@@ -1144,7 +1144,7 @@ static void retstat (LexState *ls) {
nret = fs->freereg - first; /* return all `active' values */
}
}
- luaK_codeABC(fs, OP_RETURN, first, nret, 0);
+ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
fs->freereg = fs->nactloc; /* removes all temp values */
}
diff --git a/lstate.c b/lstate.c
index 504313d6..bf669bec 100644
--- a/lstate.c
+++ b/lstate.c
@@ -104,6 +104,7 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) {
}
}
if (OL) lua_unlock(OL);
+ lua_userstateopen(L);
return L;
}
diff --git a/lstate.h b/lstate.h
index db7c7b86..b7d69af6 100644
--- a/lstate.h
+++ b/lstate.h
@@ -39,6 +39,10 @@
#define LUA_USERSTATE
#endif
+#ifndef lua_userstateopen
+#define lua_userstateopen(l)
+#endif
+
struct lua_longjmp; /* defined in ldo.c */
@@ -77,8 +81,8 @@ typedef struct CallInfo {
const Instruction *savedpc;
lua_Hook linehook;
StkId top; /* top for this function (when it's a Lua function) */
- /* extra information for debugging */
const Instruction **pc;
+ /* extra information for line tracing */
int lastpc; /* last pc traced */
int line; /* current line */
int refi; /* current index in `lineinfo' */
diff --git a/lua.h b/lua.h
index ed779771..0a2f5b10 100644
--- a/lua.h
+++ b/lua.h
@@ -45,10 +45,6 @@
#define LUA_ERRMEM 4
#define LUA_ERRERR 5
-/* weak-table modes */
-#define LUA_WEAK_KEY 1
-#define LUA_WEAK_VALUE 2
-
typedef struct lua_State lua_State;
@@ -182,6 +178,14 @@ LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size,
LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
const char *name);
+
+/*
+** coroutine functions
+*/
+LUA_API void lua_cobegin (lua_State *L, int nargs);
+LUA_API int lua_yield (lua_State *L, int nresults);
+LUA_API void lua_resume (lua_State *L, lua_State *co);
+
/*
** Garbage-collection functions
*/
@@ -203,9 +207,6 @@ LUA_API void lua_concat (lua_State *L, int n);
LUA_API void *lua_newuserdata (lua_State *L, size_t size);
LUA_API void lua_newuserdatabox (lua_State *L, void *u);
-LUA_API void lua_setweakmode (lua_State *L, int mode);
-LUA_API int lua_getweakmode (lua_State *L, int index);
-
/*
@@ -242,7 +243,7 @@ LUA_API int lua_getweakmode (lua_State *L, int index);
** compatibility macros and functions
*/
-LUA_API void lua_pushupvalues (lua_State *L);
+LUA_API int lua_pushupvalues (lua_State *L);
#define lua_isnull lua_isnone
diff --git a/lvm.c b/lvm.c
index a073d39d..bec488f1 100644
--- a/lvm.c
+++ b/lvm.c
@@ -254,29 +254,6 @@ void luaV_strconc (lua_State *L, int total, StkId top) {
}
-static void adjust_varargs (lua_State *L, StkId base, int nfixargs) {
- int i;
- Table *htab;
- TObject n, nname;
- StkId firstvar = base + nfixargs; /* position of first vararg */
- if (L->top < firstvar) {
- luaD_checkstack(L, firstvar - L->top);
- while (L->top < firstvar)
- setnilvalue(L->top++);
- }
- htab = luaH_new(L, 0, 0);
- for (i=0; firstvar+i<L->top; i++)
- luaH_setnum(L, htab, i+1, firstvar+i);
- /* store counter in field `n' */
- setnvalue(&n, i);
- setsvalue(&nname, luaS_newliteral(L, "n"));
- luaH_set(L, htab, &nname, &n);
- L->top = firstvar; /* remove elements from the stack */
- sethvalue(L->top, htab);
- incr_top;
-}
-
-
static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) {
const TObject *b = rb;
const TObject *c = rc;
@@ -307,8 +284,8 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) {
#define RC(i) (base+GETARG_C(i))
#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? \
base+GETARG_C(i) : \
- cl->p->k+GETARG_C(i)-MAXSTACK)
-#define KBc(i) (cl->p->k+GETARG_Bc(i))
+ k+GETARG_C(i)-MAXSTACK)
+#define KBc(i) (k+GETARG_Bc(i))
#define Arith(op, optm) { \
const TObject *b = RB(i); const TObject *c = RKC(i); \
@@ -321,38 +298,26 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) {
}
-#define luaV_poscall(L,c,f,ci) \
- if (c != NO_REG) { \
- luaD_poscall(L, c, f); \
- L->top = ci->top; \
- } \
- else { \
- luaD_poscall(L, LUA_MULTRET, f); \
- }
-
-
#define dojump(pc, i) ((pc) += GETARG_sBc(i))
/*
-** Executes the given Lua function. Parameters are between [base,top).
+** Executes current Lua function. Parameters are between [base,top).
** Returns n such that the results are between [n,top).
*/
-StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
+StkId luaV_execute (lua_State *L) {
+ StkId base;
+ LClosure *cl;
+ TObject *k;
const Instruction *pc;
lua_Hook linehook;
reinit:
- lua_assert(L->ci->savedpc == NULL);
+ base = L->ci->base;
+ cl = &clvalue(base - 1)->l;
+ k = cl->p->k;
+ linehook = L->ci->linehook;
L->ci->pc = &pc;
- L->ci->top = base + cl->p->maxstacksize;
- if (cl->p->is_vararg) /* varargs? */
- adjust_varargs(L, base, cl->p->numparams);
- if (base > L->stack_last - cl->p->maxstacksize)
- luaD_stackerror(L);
- while (L->top < L->ci->top)
- setnilvalue(L->top++);
- L->top = L->ci->top;
- linehook = L->ci->linehook = L->linehook;
- pc = cl->p->code;
+ pc = L->ci->savedpc;
+ L->ci->savedpc = NULL;
/* main loop of interpreter */
for (;;) {
const Instruction i = *pc++;
@@ -535,18 +500,21 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
case OP_CALL: {
StkId firstResult;
int b = GETARG_B(i);
- if (b != NO_REG) L->top = ra+b+1;
- /* else previous instruction set top */
+ int nresults;
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ nresults = GETARG_C(i) - 1;
firstResult = luaD_precall(L, ra);
if (firstResult) {
+ if (firstResult == base) { /* yield?? */
+ (L->ci-1)->savedpc = pc;
+ return NULL;
+ }
/* it was a C function (`precall' called it); adjust results */
- luaV_poscall(L, GETARG_C(i), firstResult, L->ci);
+ luaD_poscall(L, nresults, firstResult);
+ if (nresults >= 0) L->top = L->ci->top;
}
else { /* it is a Lua function: `call' it */
- CallInfo *ci = L->ci;
- (ci-1)->savedpc = pc;
- base = ci->base;
- cl = &clvalue(base - 1)->l;
+ (L->ci-1)->savedpc = pc;
goto reinit;
}
break;
@@ -556,19 +524,23 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
int b;
if (L->openupval) luaF_close(L, base);
b = GETARG_B(i);
- if (b != NO_REG) L->top = ra+b;
+ if (b != 0) L->top = ra+b-1;
ci = L->ci - 1;
if (ci->savedpc == NULL)
return ra;
else { /* previous function is Lua: continue its execution */
+ int nresults;
lua_assert(ttype(ci->base-1) == LUA_TFUNCTION);
base = ci->base; /* restore previous values */
linehook = ci->linehook;
cl = &clvalue(base - 1)->l;
+ k = cl->p->k;
pc = ci->savedpc;
ci->savedpc = NULL;
lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL);
- luaV_poscall(L, GETARG_C(*(pc-1)), ra, ci);
+ nresults = GETARG_C(*(pc-1)) - 1;
+ luaD_poscall(L, nresults, ra);
+ if (nresults >= 0) L->top = L->ci->top;
}
break;
}
diff --git a/lvm.h b/lvm.h
index 1e0369fc..ebe15e65 100644
--- a/lvm.h
+++ b/lvm.h
@@ -20,7 +20,7 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n);
int luaV_tostring (lua_State *L, TObject *obj);
void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res);
void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val);
-StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base);
+StkId luaV_execute (lua_State *L);
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
void luaV_strconc (lua_State *L, int total, StkId top);