new way to use vararg' parameters (with ...')
This commit is contained in:
28
lcode.c
28
lcode.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lcode.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
** $Id: lcode.c,v 2.2 2004/04/30 20:13:38 roberto Exp roberto $
|
||||||
** Code generator for Lua
|
** Code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -252,13 +252,26 @@ static int nil_constant (FuncState *fs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) {
|
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
|
||||||
if (e->k == VCALL) { /* expression is an open function call? */
|
if (e->k == VCALL) { /* expression is an open function call? */
|
||||||
SETARG_C(getcode(fs, e), nresults+1);
|
SETARG_C(getcode(fs, e), nresults+1);
|
||||||
if (nresults == 1) { /* `regular' expression? */
|
}
|
||||||
e->k = VNONRELOC;
|
else if (e->k == VVARARG) {
|
||||||
e->info = GETARG_A(getcode(fs, e));
|
SETARG_B(getcode(fs, e), nresults+1);
|
||||||
}
|
SETARG_A(getcode(fs, e), fs->freereg);
|
||||||
|
luaK_reserveregs(fs, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void luaK_setoneret (FuncState *fs, expdesc *e) {
|
||||||
|
if (e->k == VCALL) { /* expression is an open function call? */
|
||||||
|
e->k = VNONRELOC;
|
||||||
|
e->info = GETARG_A(getcode(fs, e));
|
||||||
|
}
|
||||||
|
else if (e->k == VVARARG) {
|
||||||
|
SETARG_B(getcode(fs, e), 2);
|
||||||
|
e->k = VRELOCABLE; /* can relocate its simple result */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,8 +299,9 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
|||||||
e->k = VRELOCABLE;
|
e->k = VRELOCABLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VVARARG:
|
||||||
case VCALL: {
|
case VCALL: {
|
||||||
luaK_setcallreturns(fs, e, 1);
|
luaK_setoneret(fs, e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break; /* there is one value available (somewhere) */
|
default: break; /* there is one value available (somewhere) */
|
||||||
|
|||||||
7
lcode.h
7
lcode.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lcode.h,v 1.37 2002/06/12 19:16:00 roberto Exp roberto $
|
** $Id: lcode.h,v 1.38 2002/12/11 12:34:22 roberto Exp roberto $
|
||||||
** Code generator for Lua
|
** Code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -41,6 +41,8 @@ typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr;
|
|||||||
|
|
||||||
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
|
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
|
||||||
|
|
||||||
|
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
|
||||||
|
|
||||||
int luaK_code (FuncState *fs, Instruction i, int line);
|
int luaK_code (FuncState *fs, Instruction i, int line);
|
||||||
int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
||||||
int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
|
int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
|
||||||
@@ -60,7 +62,8 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
|
|||||||
void luaK_goiftrue (FuncState *fs, expdesc *e);
|
void luaK_goiftrue (FuncState *fs, expdesc *e);
|
||||||
void luaK_goiffalse (FuncState *fs, expdesc *e);
|
void luaK_goiffalse (FuncState *fs, expdesc *e);
|
||||||
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
||||||
void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
|
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
|
||||||
|
void luaK_setoneret (FuncState *fs, expdesc *e);
|
||||||
int luaK_jump (FuncState *fs);
|
int luaK_jump (FuncState *fs);
|
||||||
void luaK_patchlist (FuncState *fs, int list, int target);
|
void luaK_patchlist (FuncState *fs, int list, int target);
|
||||||
void luaK_patchtohere (FuncState *fs, int list);
|
void luaK_patchtohere (FuncState *fs, int list);
|
||||||
|
|||||||
13
ldebug.c
13
ldebug.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldebug.c,v 2.3 2004/03/23 13:10:16 roberto Exp roberto $
|
** $Id: ldebug.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $
|
||||||
** Debug Interface
|
** Debug Interface
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -221,8 +221,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
|||||||
}
|
}
|
||||||
else if (ar->i_ci != 0) { /* no tail call? */
|
else if (ar->i_ci != 0) { /* no tail call? */
|
||||||
CallInfo *ci = L->base_ci + ar->i_ci;
|
CallInfo *ci = L->base_ci + ar->i_ci;
|
||||||
lua_assert(ttisfunction(ci->base - 1));
|
lua_assert(ttisfunction(ci->func));
|
||||||
status = auxgetinfo(L, what, ar, ci->base - 1, ci);
|
status = auxgetinfo(L, what, ar, ci->func, ci);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
info_tailcall(L, ar);
|
info_tailcall(L, ar);
|
||||||
@@ -405,6 +405,13 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_VARARG: {
|
||||||
|
check(pt->is_vararg & NEWSTYLEVARARG);
|
||||||
|
b--;
|
||||||
|
if (b == LUA_MULTRET) check(checkopenop(pt, pc));
|
||||||
|
checkreg(pt, a+b-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
ldo.c
66
ldo.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 2.4 2004/05/10 17:50:51 roberto Exp roberto $
|
** $Id: ldo.c,v 2.5 2004/05/14 19:25:09 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
|
||||||
*/
|
*/
|
||||||
@@ -113,6 +113,7 @@ static void correctstack (lua_State *L, TValue *oldstack) {
|
|||||||
for (ci = L->base_ci; ci <= L->ci; ci++) {
|
for (ci = L->base_ci; ci <= L->ci; ci++) {
|
||||||
ci->top = (ci->top - oldstack) + L->stack;
|
ci->top = (ci->top - oldstack) + L->stack;
|
||||||
ci->base = (ci->base - oldstack) + L->stack;
|
ci->base = (ci->base - oldstack) + L->stack;
|
||||||
|
ci->func = (ci->func - oldstack) + L->stack;
|
||||||
}
|
}
|
||||||
L->base = L->ci->base;
|
L->base = L->ci->base;
|
||||||
}
|
}
|
||||||
@@ -181,26 +182,37 @@ void luaD_callhook (lua_State *L, int event, int line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
|
static StkId adjust_varargs (lua_State *L, int nfixargs, int actual,
|
||||||
|
int style) {
|
||||||
int i;
|
int i;
|
||||||
Table *htab;
|
Table *htab = NULL;
|
||||||
int actual = L->top - base; /* actual number of arguments */
|
StkId base, fixed;
|
||||||
if (actual < nfixargs) {
|
if (actual < nfixargs) {
|
||||||
luaD_checkstack(L, nfixargs - actual);
|
|
||||||
for (; actual < nfixargs; ++actual)
|
for (; actual < nfixargs; ++actual)
|
||||||
setnilvalue(L->top++);
|
setnilvalue(L->top++);
|
||||||
}
|
}
|
||||||
actual -= nfixargs; /* number of extra arguments */
|
if (style != NEWSTYLEVARARG) { /* compatibility with old-style vararg */
|
||||||
htab = luaH_new(L, actual, 1); /* create `arg' table */
|
int nvar = actual - nfixargs; /* number of extra arguments */
|
||||||
for (i=0; i<actual; i++) /* put extra arguments into `arg' table */
|
htab = luaH_new(L, nvar, 1); /* create `arg' table */
|
||||||
setobj2n(L, luaH_setnum(L, htab, i+LUA_FIRSTINDEX), L->top - actual + i);
|
for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
|
||||||
/* store counter in field `n' */
|
setobj2n(L, luaH_setnum(L, htab, i+LUA_FIRSTINDEX), L->top - nvar + i);
|
||||||
setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")),
|
/* store counter in field `n' */
|
||||||
cast(lua_Number, actual));
|
setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")),
|
||||||
L->top -= actual; /* remove extra elements from the stack */
|
cast(lua_Number, nvar));
|
||||||
sethvalue(L, L->top, htab);
|
}
|
||||||
lua_assert(iswhite(obj2gco(htab)));
|
/* move fixed parameters to final position */
|
||||||
incr_top(L);
|
fixed = L->top - actual; /* first fixed argument */
|
||||||
|
base = L->top; /* final position of first argument */
|
||||||
|
for (i=0; i<nfixargs; i++) {
|
||||||
|
setobjs2s(L, L->top++, fixed+i);
|
||||||
|
setnilvalue(fixed+i);
|
||||||
|
}
|
||||||
|
/* add `arg' parameter */
|
||||||
|
if (htab) {
|
||||||
|
sethvalue(L, L->top++, htab);
|
||||||
|
lua_assert(iswhite(obj2gco(htab)));
|
||||||
|
}
|
||||||
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -221,21 +233,28 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
|
|||||||
|
|
||||||
int luaD_precall (lua_State *L, StkId func, int nresults) {
|
int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
LClosure *cl;
|
LClosure *cl;
|
||||||
ptrdiff_t funcr = savestack(L, func);
|
ptrdiff_t funcr;
|
||||||
if (!ttisfunction(func)) /* `func' is not a function? */
|
if (!ttisfunction(func)) /* `func' is not a function? */
|
||||||
func = tryfuncTM(L, func); /* check the `function' tag method */
|
func = tryfuncTM(L, func); /* check the `function' tag method */
|
||||||
|
funcr = savestack(L, func);
|
||||||
if (L->ci + 1 == L->end_ci) luaD_growCI(L);
|
if (L->ci + 1 == L->end_ci) luaD_growCI(L);
|
||||||
else condhardstacktests(luaD_reallocCI(L, L->size_ci));
|
else condhardstacktests(luaD_reallocCI(L, L->size_ci));
|
||||||
cl = &clvalue(func)->l;
|
cl = &clvalue(func)->l;
|
||||||
if (!cl->isC) { /* Lua function? prepare its call */
|
if (!cl->isC) { /* Lua function? prepare its call */
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
StkId st;
|
StkId st, base;
|
||||||
Proto *p = cl->p;
|
Proto *p = cl->p;
|
||||||
if (p->is_vararg) /* varargs? */
|
|
||||||
adjust_varargs(L, p->numparams, func+1);
|
|
||||||
luaD_checkstack(L, p->maxstacksize);
|
luaD_checkstack(L, p->maxstacksize);
|
||||||
|
func = restorestack(L, funcr);
|
||||||
|
if (p->is_vararg) { /* varargs? */
|
||||||
|
int nargs = L->top - func - 1;
|
||||||
|
base = adjust_varargs(L, p->numparams, nargs, p->is_vararg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
base = func + 1;
|
||||||
ci = ++L->ci; /* now `enter' new function */
|
ci = ++L->ci; /* now `enter' new function */
|
||||||
L->base = L->ci->base = restorestack(L, funcr) + 1;
|
ci->func = func;
|
||||||
|
L->base = ci->base = base;
|
||||||
ci->top = L->base + p->maxstacksize;
|
ci->top = L->base + p->maxstacksize;
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
ci->u.l.tailcalls = 0;
|
ci->u.l.tailcalls = 0;
|
||||||
@@ -250,7 +269,8 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
int n;
|
int n;
|
||||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
||||||
ci = ++L->ci; /* now `enter' new function */
|
ci = ++L->ci; /* now `enter' new function */
|
||||||
L->base = L->ci->base = restorestack(L, funcr) + 1;
|
ci->func = restorestack(L, funcr);
|
||||||
|
L->base = ci->base = ci->func + 1;
|
||||||
ci->top = L->top + LUA_MINSTACK;
|
ci->top = L->top + LUA_MINSTACK;
|
||||||
if (L->hookmask & LUA_MASKCALL)
|
if (L->hookmask & LUA_MASKCALL)
|
||||||
luaD_callhook(L, LUA_HOOKCALL, -1);
|
luaD_callhook(L, LUA_HOOKCALL, -1);
|
||||||
@@ -284,7 +304,7 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
|
|||||||
StkId res;
|
StkId res;
|
||||||
if (L->hookmask & LUA_MASKRET)
|
if (L->hookmask & LUA_MASKRET)
|
||||||
firstResult = callrethooks(L, firstResult);
|
firstResult = callrethooks(L, firstResult);
|
||||||
res = L->base - 1; /* res == final position of 1st result */
|
res = L->ci->func; /* res == final position of 1st result */
|
||||||
L->ci--;
|
L->ci--;
|
||||||
L->base = L->ci->base; /* restore base */
|
L->base = L->ci->base; /* restore base */
|
||||||
/* move results to correct place */
|
/* move results to correct place */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lobject.h,v 2.3 2004/02/20 16:01:05 roberto Exp roberto $
|
** $Id: lobject.h,v 2.4 2004/03/15 21:04:33 roberto Exp roberto $
|
||||||
** Type definitions for Lua objects
|
** Type definitions for Lua objects
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -249,6 +249,10 @@ typedef struct Proto {
|
|||||||
} Proto;
|
} Proto;
|
||||||
|
|
||||||
|
|
||||||
|
/* mask for new-style vararg */
|
||||||
|
#define NEWSTYLEVARARG 2
|
||||||
|
|
||||||
|
|
||||||
typedef struct LocVar {
|
typedef struct LocVar {
|
||||||
TString *varname;
|
TString *varname;
|
||||||
int startpc; /* first point where variable is active */
|
int startpc; /* first point where variable is active */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lopcodes.c,v 1.25 2003/05/14 21:09:53 roberto Exp roberto $
|
** $Id: lopcodes.c,v 1.26 2004/04/30 20:13:38 roberto Exp roberto $
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -53,7 +53,8 @@ const char *const luaP_opnames[NUM_OPCODES] = {
|
|||||||
"SETLIST",
|
"SETLIST",
|
||||||
"SETLISTO",
|
"SETLISTO",
|
||||||
"CLOSE",
|
"CLOSE",
|
||||||
"CLOSURE"
|
"CLOSURE",
|
||||||
|
"VARARG"
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -98,5 +99,6 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
|||||||
,opmode(0, 0, OpArgU, OpArgN, iABx) /* OP_SETLISTO */
|
,opmode(0, 0, OpArgU, OpArgN, iABx) /* OP_SETLISTO */
|
||||||
,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
|
,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
|
||||||
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
|
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
|
||||||
|
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
21
lopcodes.h
21
lopcodes.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lopcodes.h,v 1.107 2004/04/30 20:13:38 roberto Exp roberto $
|
** $Id: lopcodes.h,v 1.108 2004/05/17 12:34:00 roberto Exp roberto $
|
||||||
** Opcodes for Lua virtual machine
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -79,7 +79,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
|
|||||||
#define GET_OPCODE(i) (cast(OpCode, (i)&MASK1(SIZE_OP,0)))
|
#define GET_OPCODE(i) (cast(OpCode, (i)&MASK1(SIZE_OP,0)))
|
||||||
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | cast(Instruction, o)))
|
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | cast(Instruction, o)))
|
||||||
|
|
||||||
#define GETARG_A(i) (cast(int, (i)>>POS_A) & MASK1(SIZE_A,0))
|
#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
|
||||||
#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
|
#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
|
||||||
((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
|
((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
|
||||||
|
|
||||||
@@ -183,25 +183,30 @@ OP_SETLIST,/* A Bx R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1 */
|
|||||||
OP_SETLISTO,/* A Bx */
|
OP_SETLISTO,/* A Bx */
|
||||||
|
|
||||||
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
|
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
|
||||||
OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
||||||
|
|
||||||
|
OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
|
||||||
} OpCode;
|
} OpCode;
|
||||||
|
|
||||||
|
|
||||||
#define NUM_OPCODES (cast(int, OP_CLOSURE+1))
|
#define NUM_OPCODES (cast(int, OP_VARARG+1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
Notes:
|
Notes:
|
||||||
(1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
|
(*) 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
|
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'.
|
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
|
||||||
|
|
||||||
(2) In OP_RETURN, if (B == 0) then return up to `top'
|
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
|
||||||
|
set top (like in OP_CALL).
|
||||||
|
|
||||||
(3) For comparisons, B specifies what conditions the test should accept.
|
(*) In OP_RETURN, if (B == 0) then return up to `top'
|
||||||
|
|
||||||
(4) All `skips' (pc++) assume that next instruction is a jump
|
(*) For comparisons, B specifies what conditions the test should accept.
|
||||||
|
|
||||||
|
(*) All `skips' (pc++) assume that next instruction is a jump
|
||||||
===========================================================================*/
|
===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
60
lparser.c
60
lparser.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lparser.c,v 2.3 2004/03/26 14:02:41 roberto Exp roberto $
|
** $Id: lparser.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $
|
||||||
** Lua Parser
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
|
||||||
|
|
||||||
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
|
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
|
||||||
|
|
||||||
#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m)
|
#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m)
|
||||||
@@ -272,11 +274,11 @@ static TString *singlevar (LexState *ls, expdesc *var, int base) {
|
|||||||
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
|
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int extra = nvars - nexps;
|
int extra = nvars - nexps;
|
||||||
if (e->k == VCALL) {
|
if (hasmultret(e->k)) {
|
||||||
extra++; /* includes call itself */
|
extra++; /* includes call itself */
|
||||||
if (extra <= 0) extra = 0;
|
if (extra < 0) extra = 0;
|
||||||
else luaK_reserveregs(fs, extra-1);
|
luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
|
||||||
luaK_setcallreturns(fs, e, extra); /* call provides the difference */
|
if (extra > 1) luaK_reserveregs(fs, extra-1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
|
if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
|
||||||
@@ -392,6 +394,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
|
|||||||
lexstate.nestlevel = 0;
|
lexstate.nestlevel = 0;
|
||||||
luaX_setinput(L, &lexstate, z, luaS_new(L, name));
|
luaX_setinput(L, &lexstate, z, luaS_new(L, name));
|
||||||
open_func(&lexstate, &funcstate);
|
open_func(&lexstate, &funcstate);
|
||||||
|
funcstate.f->is_vararg = NEWSTYLEVARARG;
|
||||||
next(&lexstate); /* read first token */
|
next(&lexstate); /* read first token */
|
||||||
chunk(&lexstate);
|
chunk(&lexstate);
|
||||||
check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
|
check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
|
||||||
@@ -481,8 +484,8 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) {
|
|||||||
|
|
||||||
static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
|
static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
|
||||||
if (cc->tostore == 0) return;
|
if (cc->tostore == 0) return;
|
||||||
if (cc->v.k == VCALL) {
|
if (hasmultret(cc->v.k)) {
|
||||||
luaK_setcallreturns(fs, &cc->v, LUA_MULTRET);
|
luaK_setmultret(fs, &cc->v);
|
||||||
luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1);
|
luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1);
|
||||||
cc->na--; /* do not count last expression (unknown number of elements) */
|
cc->na--; /* do not count last expression (unknown number of elements) */
|
||||||
}
|
}
|
||||||
@@ -558,12 +561,8 @@ static void parlist (LexState *ls) {
|
|||||||
if (ls->t.token != ')') { /* is `parlist' not empty? */
|
if (ls->t.token != ')') { /* is `parlist' not empty? */
|
||||||
do {
|
do {
|
||||||
switch (ls->t.token) {
|
switch (ls->t.token) {
|
||||||
case TK_NAME: { /* param -> NAME [ `=' `...' ] */
|
case TK_NAME: { /* param -> NAME */
|
||||||
new_localvar(ls, str_checkname(ls), nparams++);
|
new_localvar(ls, str_checkname(ls), nparams++);
|
||||||
if (testnext(ls, '=')) {
|
|
||||||
check(ls, TK_DOTS);
|
|
||||||
f->is_vararg = 1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_DOTS: { /* param -> `...' */
|
case TK_DOTS: { /* param -> `...' */
|
||||||
@@ -629,7 +628,7 @@ static void funcargs (LexState *ls, expdesc *f) {
|
|||||||
args.k = VVOID;
|
args.k = VVOID;
|
||||||
else {
|
else {
|
||||||
explist1(ls, &args);
|
explist1(ls, &args);
|
||||||
luaK_setcallreturns(fs, &args, LUA_MULTRET);
|
luaK_setmultret(fs, &args);
|
||||||
}
|
}
|
||||||
check_match(ls, ')', '(', line);
|
check_match(ls, ')', '(', line);
|
||||||
break;
|
break;
|
||||||
@@ -650,7 +649,7 @@ static void funcargs (LexState *ls, expdesc *f) {
|
|||||||
}
|
}
|
||||||
lua_assert(f->k == VNONRELOC);
|
lua_assert(f->k == VNONRELOC);
|
||||||
base = f->info; /* base register for call */
|
base = f->info; /* base register for call */
|
||||||
if (args.k == VCALL)
|
if (hasmultret(args.k))
|
||||||
nparams = LUA_MULTRET; /* open call */
|
nparams = LUA_MULTRET; /* open call */
|
||||||
else {
|
else {
|
||||||
if (args.k != VVOID)
|
if (args.k != VVOID)
|
||||||
@@ -739,43 +738,47 @@ static void simpleexp (LexState *ls, expdesc *v) {
|
|||||||
switch (ls->t.token) {
|
switch (ls->t.token) {
|
||||||
case TK_NUMBER: {
|
case TK_NUMBER: {
|
||||||
init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r));
|
init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r));
|
||||||
next(ls); /* must use `seminfo' before `next' */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_STRING: {
|
case TK_STRING: {
|
||||||
codestring(ls, v, ls->t.seminfo.ts);
|
codestring(ls, v, ls->t.seminfo.ts);
|
||||||
next(ls); /* must use `seminfo' before `next' */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_NIL: {
|
case TK_NIL: {
|
||||||
init_exp(v, VNIL, 0);
|
init_exp(v, VNIL, 0);
|
||||||
next(ls);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_TRUE: {
|
case TK_TRUE: {
|
||||||
init_exp(v, VTRUE, 0);
|
init_exp(v, VTRUE, 0);
|
||||||
next(ls);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_FALSE: {
|
case TK_FALSE: {
|
||||||
init_exp(v, VFALSE, 0);
|
init_exp(v, VFALSE, 0);
|
||||||
next(ls);
|
break;
|
||||||
|
}
|
||||||
|
case TK_DOTS: { /* vararg */
|
||||||
|
FuncState *fs = ls->fs;
|
||||||
|
check_condition(ls, fs->f->is_vararg,
|
||||||
|
"cannot use `...' outside a vararg function");
|
||||||
|
fs->f->is_vararg = NEWSTYLEVARARG;
|
||||||
|
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '{': { /* constructor */
|
case '{': { /* constructor */
|
||||||
constructor(ls, v);
|
constructor(ls, v);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case TK_FUNCTION: {
|
case TK_FUNCTION: {
|
||||||
next(ls);
|
next(ls);
|
||||||
body(ls, v, 0, ls->linenumber);
|
body(ls, v, 0, ls->linenumber);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
primaryexp(ls, v);
|
primaryexp(ls, v);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
next(ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -952,7 +955,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
|
|||||||
ls->fs->freereg -= nexps - nvars; /* remove extra values */
|
ls->fs->freereg -= nexps - nvars; /* remove extra values */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */
|
luaK_setoneret(ls->fs, &e); /* close last expression */
|
||||||
luaK_storevar(ls->fs, &lh->v, &e);
|
luaK_storevar(ls->fs, &lh->v, &e);
|
||||||
return; /* avoid default */
|
return; /* avoid default */
|
||||||
}
|
}
|
||||||
@@ -1236,9 +1239,8 @@ static void exprstat (LexState *ls) {
|
|||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
struct LHS_assign v;
|
struct LHS_assign v;
|
||||||
primaryexp(ls, &v.v);
|
primaryexp(ls, &v.v);
|
||||||
if (v.v.k == VCALL) { /* stat -> func */
|
if (v.v.k == VCALL) /* stat -> func */
|
||||||
luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */
|
SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
|
||||||
}
|
|
||||||
else { /* stat -> assignment */
|
else { /* stat -> assignment */
|
||||||
v.prev = NULL;
|
v.prev = NULL;
|
||||||
assignment(ls, &v, 1);
|
assignment(ls, &v, 1);
|
||||||
@@ -1256,9 +1258,9 @@ static void retstat (LexState *ls) {
|
|||||||
first = nret = 0; /* return no values */
|
first = nret = 0; /* return no values */
|
||||||
else {
|
else {
|
||||||
nret = explist1(ls, &e); /* optional return values */
|
nret = explist1(ls, &e); /* optional return values */
|
||||||
if (e.k == VCALL) {
|
if (hasmultret(e.k)) {
|
||||||
luaK_setcallreturns(fs, &e, LUA_MULTRET);
|
luaK_setmultret(fs, &e);
|
||||||
if (nret == 1) { /* tail call? */
|
if (e.k == VCALL && nret == 1) { /* tail call? */
|
||||||
SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
|
SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
|
||||||
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
|
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lparser.h,v 1.49 2003/07/09 20:11:30 roberto Exp roberto $
|
** $Id: lparser.h,v 1.50 2003/08/25 19:51:54 roberto Exp roberto $
|
||||||
** Lua Parser
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -30,7 +30,8 @@ typedef enum {
|
|||||||
VJMP, /* info = instruction pc */
|
VJMP, /* info = instruction pc */
|
||||||
VRELOCABLE, /* info = instruction pc */
|
VRELOCABLE, /* info = instruction pc */
|
||||||
VNONRELOC, /* info = result register */
|
VNONRELOC, /* info = result register */
|
||||||
VCALL /* info = result register */
|
VCALL, /* info = instruction pc */
|
||||||
|
VVARARG /* info = instruction pc */
|
||||||
} expkind;
|
} expkind;
|
||||||
|
|
||||||
typedef struct expdesc {
|
typedef struct expdesc {
|
||||||
|
|||||||
3
lstate.c
3
lstate.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.c,v 2.5 2004/03/23 12:57:12 roberto Exp roberto $
|
** $Id: lstate.c,v 2.6 2004/04/30 20:13:38 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -57,6 +57,7 @@ static void stack_init (lua_State *L1, lua_State *L) {
|
|||||||
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
|
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
|
||||||
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
|
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
|
||||||
L1->ci = L1->base_ci;
|
L1->ci = L1->base_ci;
|
||||||
|
L1->ci->func = L1->top;
|
||||||
setnilvalue(L1->top++); /* `function' entry for this `ci' */
|
setnilvalue(L1->top++); /* `function' entry for this `ci' */
|
||||||
L1->base = L1->ci->base = L1->top;
|
L1->base = L1->ci->base = L1->top;
|
||||||
L1->ci->top = L1->top + LUA_MINSTACK;
|
L1->ci->top = L1->top + LUA_MINSTACK;
|
||||||
|
|||||||
9
lstate.h
9
lstate.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.h,v 2.2 2004/03/23 17:02:58 roberto Exp roberto $
|
** $Id: lstate.h,v 2.3 2004/05/14 19:25:09 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -71,6 +71,7 @@ typedef struct stringtable {
|
|||||||
*/
|
*/
|
||||||
typedef struct CallInfo {
|
typedef struct CallInfo {
|
||||||
StkId base; /* base for this function */
|
StkId base; /* base for this function */
|
||||||
|
StkId func; /* function index in the stack */
|
||||||
StkId top; /* top for this function */
|
StkId top; /* top for this function */
|
||||||
int nresults; /* expected number of results from this function */
|
int nresults; /* expected number of results from this function */
|
||||||
union {
|
union {
|
||||||
@@ -86,10 +87,10 @@ typedef struct CallInfo {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define curr_func(L) (clvalue(L->base - 1))
|
#define curr_func(L) (clvalue(L->ci->func))
|
||||||
#define ci_func(ci) (clvalue((ci)->base - 1))
|
#define ci_func(ci) (clvalue((ci)->func))
|
||||||
#define f_isLua(ci) (!ci_func(ci)->c.isC)
|
#define f_isLua(ci) (!ci_func(ci)->c.isC)
|
||||||
#define isLua(ci) (ttisfunction((ci)->base - 1) && f_isLua(ci))
|
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
37
lua.c
37
lua.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lua.c,v 1.124 2003/10/23 18:06:22 roberto Exp roberto $
|
** $Id: lua.c,v 1.125 2004/04/30 20:13:38 roberto Exp roberto $
|
||||||
** Lua stand-alone interpreter
|
** Lua stand-alone interpreter
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -113,30 +113,32 @@ static void print_version (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void getargs (char *argv[], int n) {
|
static int getargs (char *argv[], int n) {
|
||||||
int i;
|
int i, narg;
|
||||||
|
for (i=n+1; argv[i]; i++) {
|
||||||
|
luaL_checkstack(L, 1, "too many arguments to script");
|
||||||
|
lua_pushstring(L, argv[i]);
|
||||||
|
}
|
||||||
|
narg = i-(n+1); /* number of arguments to the script (not to `lua.c') */
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
for (i=0; argv[i]; i++) {
|
for (i=0; argv[i]; i++) {
|
||||||
lua_pushnumber(L, i - n);
|
lua_pushnumber(L, i - n);
|
||||||
lua_pushstring(L, argv[i]);
|
lua_pushstring(L, argv[i]);
|
||||||
lua_rawset(L, -3);
|
lua_rawset(L, -3);
|
||||||
}
|
}
|
||||||
}
|
return narg;
|
||||||
|
|
||||||
|
|
||||||
static int docall (int status) {
|
|
||||||
if (status == 0) status = lcall(0, 1);
|
|
||||||
return report(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int file_input (const char *name) {
|
static int file_input (const char *name) {
|
||||||
return docall(luaL_loadfile(L, name));
|
int status = luaL_loadfile(L, name) || lcall(0, 1);
|
||||||
|
return report(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int dostring (const char *s, const char *name) {
|
static int dostring (const char *s, const char *name) {
|
||||||
return docall(luaL_loadbuffer(L, s, strlen(s), name));
|
int status = luaL_loadbuffer(L, s, strlen(s), name) || lcall(0, 1);
|
||||||
|
return report(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -329,10 +331,17 @@ static int handle_argv (char *argv[], int *interactive) {
|
|||||||
} endloop:
|
} endloop:
|
||||||
if (argv[i] != NULL) {
|
if (argv[i] != NULL) {
|
||||||
const char *filename = argv[i];
|
const char *filename = argv[i];
|
||||||
getargs(argv, i); /* collect arguments */
|
int narg = getargs(argv, i); /* collect arguments */
|
||||||
clearinteractive(interactive);
|
int status;
|
||||||
lua_setglobal(L, "arg");
|
lua_setglobal(L, "arg");
|
||||||
return file_input(filename); /* stop scanning arguments */
|
clearinteractive(interactive);
|
||||||
|
status = luaL_loadfile(L, filename);
|
||||||
|
lua_insert(L, -(narg+1));
|
||||||
|
if (status == 0)
|
||||||
|
status = lcall(narg, 0);
|
||||||
|
else
|
||||||
|
lua_pop(L, narg);
|
||||||
|
return report(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
37
lvm.c
37
lvm.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.5 2004/05/10 17:50:51 roberto Exp roberto $
|
** $Id: lvm.c,v 2.6 2004/05/14 19:25:09 roberto Exp $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -387,8 +387,8 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
|
|||||||
luaD_callhook(L, LUA_HOOKCALL, -1);
|
luaD_callhook(L, LUA_HOOKCALL, -1);
|
||||||
retentry: /* entry point when returning to old functions */
|
retentry: /* entry point when returning to old functions */
|
||||||
pc = L->ci->u.l.savedpc;
|
pc = L->ci->u.l.savedpc;
|
||||||
|
cl = &clvalue(L->ci->func)->l;
|
||||||
base = L->base;
|
base = L->base;
|
||||||
cl = &clvalue(base - 1)->l;
|
|
||||||
k = cl->p->k;
|
k = cl->p->k;
|
||||||
/* main loop of interpreter */
|
/* main loop of interpreter */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -615,17 +615,19 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
|
|||||||
pcr = luaD_precall(L, ra, LUA_MULTRET);
|
pcr = luaD_precall(L, ra, LUA_MULTRET);
|
||||||
if (pcr == PCRLUA) {
|
if (pcr == PCRLUA) {
|
||||||
/* tail call: put new frame in place of previous one */
|
/* tail call: put new frame in place of previous one */
|
||||||
|
CallInfo *ci = L->ci - 1; /* previous frame */
|
||||||
int aux;
|
int aux;
|
||||||
base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */
|
StkId func = ci->func;
|
||||||
ra = RA(i);
|
StkId pfunc = (ci+1)->func; /* previous function index */
|
||||||
|
base = ci->base = ci->func + ((ci+1)->base - pfunc);
|
||||||
|
L->base = base;
|
||||||
if (L->openupval) luaF_close(L, base);
|
if (L->openupval) luaF_close(L, base);
|
||||||
for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
|
for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
|
||||||
setobjs2s(L, base+aux-1, ra+aux);
|
setobjs2s(L, func+aux, pfunc+aux);
|
||||||
(L->ci - 1)->top = L->top = base+aux; /* correct top */
|
ci->top = L->top = base+aux; /* correct top */
|
||||||
(L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
|
ci->u.l.savedpc = L->ci->u.l.savedpc;
|
||||||
(L->ci - 1)->u.l.tailcalls++; /* one more call lost */
|
ci->u.l.tailcalls++; /* one more call lost */
|
||||||
L->ci--; /* remove new frame */
|
L->ci--; /* remove new frame */
|
||||||
L->base = L->ci->base;
|
|
||||||
goto callentry;
|
goto callentry;
|
||||||
}
|
}
|
||||||
else if (pcr == PCRC) {
|
else if (pcr == PCRC) {
|
||||||
@@ -758,6 +760,21 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
|
|||||||
base = L->base;
|
base = L->base;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_VARARG: {
|
||||||
|
int b = GETARG_B(i) - 1;
|
||||||
|
int j;
|
||||||
|
CallInfo *ci = L->ci;
|
||||||
|
int n = ci->base - ci->func - cl->p->numparams - 1;
|
||||||
|
if (b == LUA_MULTRET) {
|
||||||
|
b = n;
|
||||||
|
L->top = ra + n;
|
||||||
|
}
|
||||||
|
for (j=0; j<b && j<n; j++)
|
||||||
|
setobjs2s(L, ra+j, ci->base - n + j);
|
||||||
|
for (; j<b; j++)
|
||||||
|
setnilvalue(ra+j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user