mirror of https://github.com/rusefi/lua.git
simpler implementation for `for' loops
This commit is contained in:
parent
addbe8c8b0
commit
38b0e6128d
11
lcode.c
11
lcode.c
|
@ -76,17 +76,6 @@ static void luaK_fixjump (FuncState *fs, int pc, int dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** prep-for instructions (OP_FORPREP & OP_TFORPREP) have a negated jump,
|
|
||||||
** as they simulate the real jump...
|
|
||||||
*/
|
|
||||||
void luaK_fixfor (FuncState *fs, int pc, int dest) {
|
|
||||||
Instruction *jmp = &fs->f->code[pc];
|
|
||||||
int offset = dest-(pc+1);
|
|
||||||
SETARG_sBc(*jmp, -offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** returns current `pc' and marks it as a jump target (to avoid wrong
|
** returns current `pc' and marks it as a jump target (to avoid wrong
|
||||||
** optimizations with consecutive instructions not in the same basic block).
|
** optimizations with consecutive instructions not in the same basic block).
|
||||||
|
|
1
lcode.h
1
lcode.h
|
@ -57,7 +57,6 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
||||||
void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
|
void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
|
||||||
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_fixfor (FuncState *fs, int pc, int dest);
|
|
||||||
void luaK_concat (FuncState *fs, int *l1, int l2);
|
void luaK_concat (FuncState *fs, int *l1, int l2);
|
||||||
int luaK_getlabel (FuncState *fs);
|
int luaK_getlabel (FuncState *fs);
|
||||||
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
|
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
|
||||||
|
|
40
ldebug.c
40
ldebug.c
|
@ -54,13 +54,6 @@ LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static CallInfo *ci_stack (lua_State *L, StkId obj) {
|
|
||||||
CallInfo *ci = L->ci;
|
|
||||||
while (ci->base > obj && ci > L->base_ci) ci--;
|
|
||||||
return ci;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
|
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
|
||||||
int status;
|
int status;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
|
@ -283,6 +276,7 @@ static int checklineinfo (const Proto *pt) {
|
||||||
int *lineinfo = pt->lineinfo;
|
int *lineinfo = pt->lineinfo;
|
||||||
if (lineinfo == NULL) return 1;
|
if (lineinfo == NULL) return 1;
|
||||||
check(pt->sizelineinfo >= 2 && lineinfo[pt->sizelineinfo-1] == MAX_INT);
|
check(pt->sizelineinfo >= 2 && lineinfo[pt->sizelineinfo-1] == MAX_INT);
|
||||||
|
lua_assert(luaG_getline(lineinfo, pt->sizecode-1, 1, NULL) < MAX_INT);
|
||||||
if (*lineinfo < 0) lineinfo++;
|
if (*lineinfo < 0) lineinfo++;
|
||||||
check(*lineinfo == 0);
|
check(*lineinfo == 0);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -292,7 +286,7 @@ static int checklineinfo (const Proto *pt) {
|
||||||
static int precheck (const Proto *pt) {
|
static int precheck (const Proto *pt) {
|
||||||
check(checklineinfo(pt));
|
check(checklineinfo(pt));
|
||||||
check(pt->maxstacksize <= MAXSTACK);
|
check(pt->maxstacksize <= MAXSTACK);
|
||||||
check(pt->numparams+pt->is_vararg <= pt->maxstacksize);
|
lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize);
|
||||||
check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
|
check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -381,7 +375,9 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||||
check(c < MAXSTACK && b < c);
|
check(c < MAXSTACK && b < c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_JMP: {
|
case OP_JMP:
|
||||||
|
case OP_FORLOOP:
|
||||||
|
case OP_TFORLOOP: {
|
||||||
int dest = pc+1+b;
|
int dest = pc+1+b;
|
||||||
check(0 <= dest && dest < pt->sizecode);
|
check(0 <= dest && dest < pt->sizecode);
|
||||||
/* not full check and jump is forward and do not skip `lastpc'? */
|
/* not full check and jump is forward and do not skip `lastpc'? */
|
||||||
|
@ -407,21 +403,6 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||||
if (b > 0) checkreg(pt, a+b-1);
|
if (b > 0) checkreg(pt, a+b-1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_FORPREP:
|
|
||||||
case OP_TFORPREP: {
|
|
||||||
int dest = pc-b; /* jump is negated here */
|
|
||||||
check(0 <= dest && dest < pt->sizecode &&
|
|
||||||
GET_OPCODE(pt->code[dest]) == op+1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_FORLOOP:
|
|
||||||
case OP_TFORLOOP: {
|
|
||||||
int dest = pc+b;
|
|
||||||
check(0 <= dest && dest < pt->sizecode &&
|
|
||||||
pt->code[dest] == SET_OPCODE(i, op-1));
|
|
||||||
checkreg(pt, a + ((op == OP_FORLOOP) ? 2 : 3));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_SETLIST: {
|
case OP_SETLIST: {
|
||||||
checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1);
|
checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1);
|
||||||
break;
|
break;
|
||||||
|
@ -445,12 +426,11 @@ int luaG_checkcode (const Proto *pt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *getobjname (lua_State *L, StkId obj, const char **name) {
|
static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
|
||||||
CallInfo *ci = ci_stack(L, obj);
|
const char **name) {
|
||||||
if (isLmark(ci)) { /* an active Lua function? */
|
if (isLmark(ci)) { /* an active Lua function? */
|
||||||
Proto *p = ci_func(ci)->l.p;
|
Proto *p = ci_func(ci)->l.p;
|
||||||
int pc = currentpc(L, ci);
|
int pc = currentpc(L, ci);
|
||||||
int stackpos = obj - ci->base;
|
|
||||||
Instruction i;
|
Instruction i;
|
||||||
*name = luaF_getlocalname(p, stackpos+1, pc);
|
*name = luaF_getlocalname(p, stackpos+1, pc);
|
||||||
if (*name) /* is a local? */
|
if (*name) /* is a local? */
|
||||||
|
@ -467,7 +447,7 @@ static const char *getobjname (lua_State *L, StkId obj, const char **name) {
|
||||||
int a = GETARG_A(i);
|
int a = GETARG_A(i);
|
||||||
int b = GETARG_B(i); /* move from `b' to `a' */
|
int b = GETARG_B(i); /* move from `b' to `a' */
|
||||||
if (b < a)
|
if (b < a)
|
||||||
return getobjname(L, ci->base+b, name); /* get name for `b' */
|
return getobjname(L, ci, b, name); /* get name for `b' */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_GETTABLE:
|
case OP_GETTABLE:
|
||||||
|
@ -496,7 +476,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||||
Instruction i;
|
Instruction i;
|
||||||
i = p->code[pc];
|
i = p->code[pc];
|
||||||
return (GET_OPCODE(i) == OP_CALL
|
return (GET_OPCODE(i) == OP_CALL
|
||||||
? getobjname(L, ci->base+GETARG_A(i), name)
|
? getobjname(L, ci, GETARG_A(i), name)
|
||||||
: NULL); /* no useful name found */
|
: NULL); /* no useful name found */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -504,7 +484,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||||
|
|
||||||
void luaG_typeerror (lua_State *L, StkId o, const char *op) {
|
void luaG_typeerror (lua_State *L, StkId o, const char *op) {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *kind = getobjname(L, o, &name);
|
const char *kind = getobjname(L, L->ci, o - L->ci->base, &name); /* ?? */
|
||||||
const char *t = luaT_typenames[ttype(o)];
|
const char *t = luaT_typenames[ttype(o)];
|
||||||
if (kind)
|
if (kind)
|
||||||
luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)",
|
luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)",
|
||||||
|
|
12
lopcodes.c
12
lopcodes.c
|
@ -46,9 +46,7 @@ const char *const luaP_opnames[] = {
|
||||||
"TESTF",
|
"TESTF",
|
||||||
"CALL",
|
"CALL",
|
||||||
"RETURN",
|
"RETURN",
|
||||||
"FORPREP",
|
|
||||||
"FORLOOP",
|
"FORLOOP",
|
||||||
"TFORPREP",
|
|
||||||
"TFORLOOP",
|
"TFORLOOP",
|
||||||
"SETLIST",
|
"SETLIST",
|
||||||
"SETLISTO",
|
"SETLISTO",
|
||||||
|
@ -60,10 +58,10 @@ const char *const luaP_opnames[] = {
|
||||||
|
|
||||||
#define opmode(t,x,b,c,sa,k,m) (((t)<<OpModeT) | \
|
#define opmode(t,x,b,c,sa,k,m) (((t)<<OpModeT) | \
|
||||||
((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \
|
((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \
|
||||||
((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
|
((sa)<<OpModesetA) | ((k)<<OpModeK) | (x)<<OpModeNoTrace | (m))
|
||||||
|
|
||||||
const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||||
/* T _ B C sA K mode opcode */
|
/* T n B C sA K mode opcode */
|
||||||
opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */
|
opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */
|
||||||
,opmode(0,0,0,0, 1,1,iABc) /* OP_LOADK */
|
,opmode(0,0,0,0, 1,1,iABc) /* OP_LOADK */
|
||||||
,opmode(0,0,0,0, 1,0,iABC) /* OP_LOADBOOL */
|
,opmode(0,0,0,0, 1,0,iABC) /* OP_LOADBOOL */
|
||||||
|
@ -95,10 +93,8 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||||
,opmode(1,0,1,0, 1,0,iABC) /* OP_TESTF */
|
,opmode(1,0,1,0, 1,0,iABC) /* OP_TESTF */
|
||||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */
|
,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */
|
||||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */
|
,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */
|
||||||
,opmode(0,0,0,0, 0,0,iAsBc) /* OP_FORPREP */
|
,opmode(0,1,0,0, 0,0,iAsBc) /* OP_FORLOOP */
|
||||||
,opmode(0,0,0,0, 0,0,iAsBc) /* OP_FORLOOP */
|
,opmode(0,1,0,0, 0,0,iAsBc) /* OP_TFORLOOP */
|
||||||
,opmode(0,0,0,0, 0,0,iAsBc) /* OP_TFORPREP */
|
|
||||||
,opmode(0,0,0,0, 0,0,iAsBc) /* OP_TFORLOOP */
|
|
||||||
,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */
|
,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */
|
||||||
,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */
|
,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */
|
||||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */
|
,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */
|
||||||
|
|
|
@ -169,10 +169,7 @@ OP_TESTF,/* A B if not (R(B)) then R(A) := R(B) else pc++ */
|
||||||
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))*/
|
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_RETURN,/* A B return R(A), ... ,R(A+B-2) (see (3)) */
|
||||||
|
|
||||||
OP_FORPREP,/* A sBc */
|
|
||||||
OP_FORLOOP,/* A sBc */
|
OP_FORLOOP,/* A sBc */
|
||||||
|
|
||||||
OP_TFORPREP,/* A sBc */
|
|
||||||
OP_TFORLOOP,/* A sBc */
|
OP_TFORLOOP,/* A sBc */
|
||||||
|
|
||||||
OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */
|
OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */
|
||||||
|
@ -206,7 +203,8 @@ enum OpModeMask {
|
||||||
OpModeCreg, /* C is a register/constant */
|
OpModeCreg, /* C is a register/constant */
|
||||||
OpModesetA, /* instruction set register A */
|
OpModesetA, /* instruction set register A */
|
||||||
OpModeK, /* Bc is a constant */
|
OpModeK, /* Bc is a constant */
|
||||||
OpModeT /* operator is a test */
|
OpModeT, /* operator is a test */
|
||||||
|
OpModeNoTrace /* operator should not be traced */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const lu_byte luaP_opmodes[NUM_OPCODES];
|
extern const lu_byte luaP_opmodes[NUM_OPCODES];
|
||||||
|
|
15
lparser.c
15
lparser.c
|
@ -955,17 +955,17 @@ static void exp1 (LexState *ls) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) {
|
static void forbody (LexState *ls, int nvar, OpCode loopfor) {
|
||||||
/* forbody -> DO block END */
|
/* forbody -> DO block END */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int basereg = fs->freereg - nvar;
|
int basereg = fs->freereg - nvar;
|
||||||
int prep = luaK_codeAsBc(fs, prepfor, basereg, NO_JUMP);
|
int prep = luaK_jump(fs);
|
||||||
int blockinit = luaK_getlabel(fs);
|
int blockinit = luaK_getlabel(fs);
|
||||||
check(ls, TK_DO);
|
check(ls, TK_DO);
|
||||||
adjustlocalvars(ls, nvar); /* scope for control variables */
|
adjustlocalvars(ls, nvar); /* scope for control variables */
|
||||||
block(ls);
|
block(ls);
|
||||||
|
luaK_patchlist(fs, prep, luaK_getlabel(fs));
|
||||||
luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit);
|
luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit);
|
||||||
luaK_fixfor(fs, prep, luaK_getlabel(fs));
|
|
||||||
removelocalvars(ls, nvar, 1);
|
removelocalvars(ls, nvar, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -986,13 +986,15 @@ static void fornum (LexState *ls, TString *varname) {
|
||||||
new_localvar(ls, varname, 0);
|
new_localvar(ls, varname, 0);
|
||||||
new_localvarstr(ls, "(limit)", 1);
|
new_localvarstr(ls, "(limit)", 1);
|
||||||
new_localvarstr(ls, "(step)", 2);
|
new_localvarstr(ls, "(step)", 2);
|
||||||
forbody(ls, 3, OP_FORPREP, OP_FORLOOP);
|
luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
|
||||||
|
forbody(ls, 3, OP_FORLOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void forlist (LexState *ls, TString *indexname) {
|
static void forlist (LexState *ls, TString *indexname) {
|
||||||
/* forlist -> NAME,NAME IN exp1 forbody */
|
/* forlist -> NAME,NAME IN exp1 forbody */
|
||||||
TString *valname;
|
TString *valname;
|
||||||
|
FuncState *fs = ls->fs;
|
||||||
check(ls, ',');
|
check(ls, ',');
|
||||||
valname = str_checkname(ls);
|
valname = str_checkname(ls);
|
||||||
next(ls); /* skip var name */
|
next(ls); /* skip var name */
|
||||||
|
@ -1002,8 +1004,9 @@ static void forlist (LexState *ls, TString *indexname) {
|
||||||
new_localvarstr(ls, "(index)", 1);
|
new_localvarstr(ls, "(index)", 1);
|
||||||
new_localvar(ls, indexname, 2);
|
new_localvar(ls, indexname, 2);
|
||||||
new_localvar(ls, valname, 3);
|
new_localvar(ls, valname, 3);
|
||||||
luaK_reserveregs(ls->fs, 3); /* registers for control, index and val */
|
luaK_reserveregs(fs, 3); /* registers for control, index and val */
|
||||||
forbody(ls, 4, OP_TFORPREP, OP_TFORLOOP);
|
luaK_codeABc(fs, OP_LOADK, fs->freereg - 3, luaK_numberK(fs, -1));
|
||||||
|
forbody(ls, 4, OP_TFORLOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
67
lvm.c
67
lvm.c
|
@ -26,6 +26,9 @@
|
||||||
#include "lvm.h"
|
#include "lvm.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* limit for table tag-method chains (to avoid loops) */
|
||||||
|
#define MAXTAGLOOP 10000
|
||||||
|
|
||||||
|
|
||||||
static void luaV_checkGC (lua_State *L, StkId top) {
|
static void luaV_checkGC (lua_State *L, StkId top) {
|
||||||
if (G(L)->nblocks >= G(L)->GCthreshold) {
|
if (G(L)->nblocks >= G(L)->GCthreshold) {
|
||||||
|
@ -65,6 +68,8 @@ static void traceexec (lua_State *L, lua_Hook linehook) {
|
||||||
int *lineinfo = ci_func(ci)->l.p->lineinfo;
|
int *lineinfo = ci_func(ci)->l.p->lineinfo;
|
||||||
int pc = cast(int, *ci->pc - ci_func(ci)->l.p->code) - 1;
|
int pc = cast(int, *ci->pc - ci_func(ci)->l.p->code) - 1;
|
||||||
int newline;
|
int newline;
|
||||||
|
if (testOpMode(GET_OPCODE(*(*ci->pc - 1)), OpModeNoTrace))
|
||||||
|
return;
|
||||||
if (ci->line == -1) return; /* no linehooks for this function */
|
if (ci->line == -1) return; /* no linehooks for this function */
|
||||||
else if (ci->line == 0) { /* first linehook? */
|
else if (ci->line == 0) { /* first linehook? */
|
||||||
if (pc == 0) { /* function is starting now? */
|
if (pc == 0) { /* function is starting now? */
|
||||||
|
@ -123,6 +128,7 @@ static void callTM (lua_State *L, const TObject *f,
|
||||||
*/
|
*/
|
||||||
void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
|
void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
|
||||||
const TObject *tm;
|
const TObject *tm;
|
||||||
|
int loop = 0;
|
||||||
init:
|
init:
|
||||||
if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
|
if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
|
||||||
Table *et = hvalue(t)->metatable;
|
Table *et = hvalue(t)->metatable;
|
||||||
|
@ -145,6 +151,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
|
||||||
if (ttype(tm) == LUA_TFUNCTION)
|
if (ttype(tm) == LUA_TFUNCTION)
|
||||||
callTMres(L, tm, t, key, res);
|
callTMres(L, tm, t, key, res);
|
||||||
else {
|
else {
|
||||||
|
if (++loop == MAXTAGLOOP) luaD_error(L, "loop in gettable");
|
||||||
t = (StkId)tm; /* ?? */
|
t = (StkId)tm; /* ?? */
|
||||||
goto init; /* return luaV_gettable(L, tm, key, res); */
|
goto init; /* return luaV_gettable(L, tm, key, res); */
|
||||||
}
|
}
|
||||||
|
@ -156,6 +163,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
|
||||||
*/
|
*/
|
||||||
void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) {
|
void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) {
|
||||||
const TObject *tm;
|
const TObject *tm;
|
||||||
|
int loop = 0;
|
||||||
init:
|
init:
|
||||||
if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
|
if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
|
||||||
Table *et = hvalue(t)->metatable;
|
Table *et = hvalue(t)->metatable;
|
||||||
|
@ -173,6 +181,7 @@ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) {
|
||||||
if (ttype(tm) == LUA_TFUNCTION)
|
if (ttype(tm) == LUA_TFUNCTION)
|
||||||
callTM(L, tm, t, key, val);
|
callTM(L, tm, t, key, val);
|
||||||
else {
|
else {
|
||||||
|
if (++loop == MAXTAGLOOP) luaD_error(L, "loop in settable");
|
||||||
t = (StkId)tm; /* ?? */
|
t = (StkId)tm; /* ?? */
|
||||||
goto init; /* luaV_settable(L, tm, key, val); */
|
goto init; /* luaV_settable(L, tm, key, val); */
|
||||||
}
|
}
|
||||||
|
@ -301,8 +310,8 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) {
|
||||||
#define Arith(op, optm) { \
|
#define Arith(op, optm) { \
|
||||||
const TObject *b = RB(i); const TObject *c = RKC(i); \
|
const TObject *b = RB(i); const TObject *c = RKC(i); \
|
||||||
TObject tempb, tempc; \
|
TObject tempb, tempc; \
|
||||||
if ((ttype(b) == LUA_TNUMBER || (b = luaV_tonumber(b, &tempb)) != NULL) && \
|
if ((b = luaV_tonumber(b, &tempb)) != NULL && \
|
||||||
(ttype(c) == LUA_TNUMBER || (c = luaV_tonumber(c, &tempc)) != NULL)) { \
|
(c = luaV_tonumber(c, &tempc)) != NULL) { \
|
||||||
setnvalue(ra, nvalue(b) op nvalue(c)); \
|
setnvalue(ra, nvalue(b) op nvalue(c)); \
|
||||||
} else \
|
} else \
|
||||||
call_arith(L, RB(i), RKC(i), ra, optm); \
|
call_arith(L, RB(i), RKC(i), ra, optm); \
|
||||||
|
@ -423,7 +432,7 @@ StkId luaV_execute (lua_State *L) {
|
||||||
}
|
}
|
||||||
case OP_UNM: {
|
case OP_UNM: {
|
||||||
const TObject *rb = RB(i);
|
const TObject *rb = RB(i);
|
||||||
if (ttype(rb) == LUA_TNUMBER || (rb=luaV_tonumber(rb, ra)) != NULL) {
|
if ((rb=luaV_tonumber(rb, ra)) != NULL) {
|
||||||
setnvalue(ra, -nvalue(rb));
|
setnvalue(ra, -nvalue(rb));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -441,7 +450,7 @@ StkId luaV_execute (lua_State *L) {
|
||||||
case OP_CONCAT: {
|
case OP_CONCAT: {
|
||||||
int b = GETARG_B(i);
|
int b = GETARG_B(i);
|
||||||
int c = GETARG_C(i);
|
int c = GETARG_C(i);
|
||||||
luaV_strconc(L, c-b+1, c); /* this call may change `base' (and `ra') */
|
luaV_strconc(L, c-b+1, c); /* may change `base' (and `ra') */
|
||||||
setobj(base+GETARG_A(i), base+b);
|
setobj(base+GETARG_A(i), base+b);
|
||||||
luaV_checkGC(L, base+c+1);
|
luaV_checkGC(L, base+c+1);
|
||||||
break;
|
break;
|
||||||
|
@ -532,53 +541,41 @@ StkId luaV_execute (lua_State *L) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_FORPREP: {
|
case OP_FORLOOP: {
|
||||||
if (luaV_tonumber(ra, ra) == NULL)
|
lua_Number step, index, limit;
|
||||||
|
int j = GETARG_sBc(i);
|
||||||
|
pc += j; /* jump back before tests (for error messages) */
|
||||||
|
if (ttype(ra) != LUA_TNUMBER)
|
||||||
luaD_error(L, "`for' initial value must be a number");
|
luaD_error(L, "`for' initial value must be a number");
|
||||||
if (luaV_tonumber(ra+1, ra+1) == NULL)
|
if (luaV_tonumber(ra+1, ra+1) == NULL)
|
||||||
luaD_error(L, "`for' limit must be a number");
|
luaD_error(L, "`for' limit must be a number");
|
||||||
if (luaV_tonumber(ra+2, ra+2) == NULL)
|
if (luaV_tonumber(ra+2, ra+2) == NULL)
|
||||||
luaD_error(L, "`for' step must be a number");
|
luaD_error(L, "`for' step must be a number");
|
||||||
/* decrement index (to be incremented) */
|
step = nvalue(ra+2);
|
||||||
chgnvalue(ra, nvalue(ra) - nvalue(ra+2));
|
index = nvalue(ra) + step; /* increment index */
|
||||||
pc += -GETARG_sBc(i); /* `jump' to loop end (delta is negated here) */
|
limit = nvalue(ra+1);
|
||||||
/* store in `ra+1' total number of repetitions */
|
if (step > 0 ? index <= limit : index >= limit)
|
||||||
chgnvalue(ra+1, (nvalue(ra+1)-nvalue(ra))/nvalue(ra+2));
|
chgnvalue(ra, index); /* update index */
|
||||||
/* go through */
|
else
|
||||||
}
|
pc -= j; /* undo jump */
|
||||||
case OP_FORLOOP: {
|
|
||||||
runtime_check(L, ttype(ra+1) == LUA_TNUMBER &&
|
|
||||||
ttype(ra+2) == LUA_TNUMBER);
|
|
||||||
if (ttype(ra) != LUA_TNUMBER)
|
|
||||||
luaD_error(L, "`for' index must be a number");
|
|
||||||
chgnvalue(ra+1, nvalue(ra+1) - 1); /* decrement counter */
|
|
||||||
if (nvalue(ra+1) >= 0) {
|
|
||||||
chgnvalue(ra, nvalue(ra) + nvalue(ra+2)); /* increment index */
|
|
||||||
dojump(pc, i); /* repeat loop */
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_TFORPREP: {
|
|
||||||
if (ttype(ra) != LUA_TTABLE)
|
|
||||||
luaD_error(L, "`for' table must be a table");
|
|
||||||
setnvalue(ra+1, -1); /* initial index */
|
|
||||||
setnilvalue(ra+2);
|
|
||||||
setnilvalue(ra+3);
|
|
||||||
pc += -GETARG_sBc(i); /* `jump' to loop end (delta is negated here) */
|
|
||||||
/* go through */
|
|
||||||
}
|
|
||||||
case OP_TFORLOOP: {
|
case OP_TFORLOOP: {
|
||||||
Table *t;
|
Table *t;
|
||||||
int n;
|
int n;
|
||||||
runtime_check(L, ttype(ra) == LUA_TTABLE &&
|
int j = GETARG_sBc(i);
|
||||||
ttype(ra+1) == LUA_TNUMBER);
|
pc += j; /* jump back before tests (for error messages) */
|
||||||
|
if (ttype(ra) != LUA_TTABLE)
|
||||||
|
luaD_error(L, "`for' table must be a table");
|
||||||
|
runtime_check(L, ttype(ra+1) == LUA_TNUMBER);
|
||||||
t = hvalue(ra);
|
t = hvalue(ra);
|
||||||
n = cast(int, nvalue(ra+1));
|
n = cast(int, nvalue(ra+1));
|
||||||
n = luaH_nexti(t, n, ra+2);
|
n = luaH_nexti(t, n, ra+2);
|
||||||
if (n != -1) { /* repeat loop? */
|
if (n != -1) { /* repeat loop? */
|
||||||
setnvalue(ra+1, n); /* index */
|
setnvalue(ra+1, n); /* index */
|
||||||
dojump(pc, i); /* repeat loop */
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
pc -= j; /* undo jump */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_SETLIST:
|
case OP_SETLIST:
|
||||||
|
|
Loading…
Reference in New Issue