mirror of
https://github.com/lua/lua
synced 2024-11-22 12:51:30 +03:00
generic for (with any number of control variables)
This commit is contained in:
parent
4db04555f0
commit
bd8b9c94b3
27
lcode.c
27
lcode.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.c,v 1.89 2002/02/05 22:39:12 roberto Exp roberto $
|
||||
** $Id: lcode.c,v 1.90 2002/03/05 12:42:47 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -158,6 +158,11 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
|
||||
}
|
||||
|
||||
|
||||
void luaK_patchtohere (FuncState *fs, int list) {
|
||||
luaK_patchlist(fs, list, luaK_getlabel(fs));
|
||||
}
|
||||
|
||||
|
||||
void luaK_concat (FuncState *fs, int *l1, int l2) {
|
||||
if (*l1 == NO_JUMP)
|
||||
*l1 = l2;
|
||||
@ -171,16 +176,22 @@ void luaK_concat (FuncState *fs, int *l1, int l2) {
|
||||
}
|
||||
|
||||
|
||||
void luaK_reserveregs (FuncState *fs, int n) {
|
||||
fs->freereg += n;
|
||||
if (fs->freereg > fs->f->maxstacksize) {
|
||||
if (fs->freereg >= MAXSTACK)
|
||||
void luaK_checkstack (FuncState *fs, int n) {
|
||||
int newstack = fs->freereg + n;
|
||||
if (newstack > fs->f->maxstacksize) {
|
||||
if (newstack >= MAXSTACK)
|
||||
luaK_error(fs->ls, "function or expression too complex");
|
||||
fs->f->maxstacksize = cast(lu_byte, fs->freereg);
|
||||
fs->f->maxstacksize = cast(lu_byte, newstack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_reserveregs (FuncState *fs, int n) {
|
||||
luaK_checkstack(fs, n);
|
||||
fs->freereg += n;
|
||||
}
|
||||
|
||||
|
||||
static void freereg (FuncState *fs, int reg) {
|
||||
if (reg >= fs->nactloc && reg < MAXSTACK) {
|
||||
fs->freereg--;
|
||||
@ -533,7 +544,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
|
||||
}
|
||||
}
|
||||
luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
|
||||
luaK_patchlist(fs, e->t, luaK_getlabel(fs));
|
||||
luaK_patchtohere(fs, e->t);
|
||||
e->t = NO_JUMP;
|
||||
}
|
||||
|
||||
@ -560,7 +571,7 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) {
|
||||
}
|
||||
}
|
||||
luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
|
||||
luaK_patchlist(fs, e->f, luaK_getlabel(fs));
|
||||
luaK_patchtohere(fs, e->f);
|
||||
e->f = NO_JUMP;
|
||||
}
|
||||
|
||||
|
4
lcode.h
4
lcode.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
|
||||
** $Id: lcode.h,v 1.27 2002/02/05 22:39:12 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -42,6 +42,7 @@ void luaK_error (LexState *ls, const char *msg);
|
||||
int luaK_codeABc (FuncState *fs, OpCode o, int A, unsigned int Bc);
|
||||
int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
|
||||
void luaK_nil (FuncState *fs, int from, int n);
|
||||
void luaK_checkstack (FuncState *fs, int n);
|
||||
void luaK_reserveregs (FuncState *fs, int n);
|
||||
int luaK_stringK (FuncState *fs, TString *s);
|
||||
int luaK_numberK (FuncState *fs, lua_Number r);
|
||||
@ -57,6 +58,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
||||
void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
|
||||
int luaK_jump (FuncState *fs);
|
||||
void luaK_patchlist (FuncState *fs, int list, int target);
|
||||
void luaK_patchtohere (FuncState *fs, int list);
|
||||
void luaK_concat (FuncState *fs, int *l1, int l2);
|
||||
int luaK_getlabel (FuncState *fs);
|
||||
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
|
||||
|
21
ldebug.c
21
ldebug.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.c,v 1.97 2002/01/09 22:02:47 roberto Exp $
|
||||
** $Id: ldebug.c,v 1.100 2002/02/05 22:39:12 roberto Exp $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -375,9 +375,10 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
check(c < MAXSTACK && b < c);
|
||||
break;
|
||||
}
|
||||
case OP_JMP:
|
||||
case OP_FORLOOP:
|
||||
case OP_TFORLOOP: {
|
||||
checkreg(pt, a+2);
|
||||
/* go through */
|
||||
case OP_JMP: {
|
||||
int dest = pc+1+b;
|
||||
check(0 <= dest && dest < pt->sizecode);
|
||||
/* not full check and jump is forward and do not skip `lastpc'? */
|
||||
@ -385,6 +386,12 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
pc += b; /* do the jump */
|
||||
break;
|
||||
}
|
||||
case OP_TFORLOOP: {
|
||||
checkreg(pt, a+c);
|
||||
checkreg(pt, a+2); /* at least 2 for table generators */
|
||||
check(pc+2 < pt->sizecode); /* check skip */
|
||||
break;
|
||||
}
|
||||
case OP_CALL: {
|
||||
if (b != 0) {
|
||||
checkreg(pt, a+b-1);
|
||||
@ -408,8 +415,14 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
break;
|
||||
}
|
||||
case OP_CLOSURE: {
|
||||
int nup;
|
||||
check(b < pt->sizep);
|
||||
check(pc + pt->p[b]->nupvalues < pt->sizecode);
|
||||
nup = pt->p[b]->nupvalues;
|
||||
check(pc + nup < pt->sizecode);
|
||||
for (; nup>0; nup--) {
|
||||
OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
|
||||
check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.c,v 1.8 2001/12/11 22:48:44 roberto Exp $
|
||||
** $Id: lopcodes.c,v 1.11 2002/02/05 22:39:12 roberto Exp roberto $
|
||||
** extracted automatically from lopcodes.h by mkprint.lua
|
||||
** DO NOT EDIT
|
||||
** See Copyright Notice in lua.h
|
||||
@ -60,6 +60,7 @@ const char *const luaP_opnames[] = {
|
||||
((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \
|
||||
((sa)<<OpModesetA) | ((k)<<OpModeK) | (x)<<OpModeNoTrace | (m))
|
||||
|
||||
|
||||
const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||
/* T n B C sA K mode opcode */
|
||||
opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */
|
||||
@ -94,7 +95,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */
|
||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */
|
||||
,opmode(0,1,0,0, 0,0,iAsBc) /* OP_FORLOOP */
|
||||
,opmode(0,1,0,0, 0,0,iAsBc) /* OP_TFORLOOP */
|
||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_TFORLOOP */
|
||||
,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_CLOSE */
|
||||
|
10
lopcodes.h
10
lopcodes.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.h,v 1.85 2002/01/09 22:02:47 roberto Exp $
|
||||
** $Id: lopcodes.h,v 1.89 2002/02/14 21:43:01 roberto Exp roberto $
|
||||
** Opcodes for Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -166,11 +166,13 @@ OP_TESTGE,/* A C if not (R(A) >= R/K(C)) then pc++ */
|
||||
OP_TESTT,/* A B if (R(B)) then R(A) := R(B) else pc++ */
|
||||
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_FORLOOP,/* A sBc */
|
||||
OP_TFORLOOP,/* A sBc */
|
||||
OP_FORLOOP,/* A sBc R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBc */
|
||||
|
||||
OP_TFORLOOP,/* A C R(A+1), ... ,R(A+C) := R(A)();
|
||||
if R(A+1) ~= nil then pc++ */
|
||||
|
||||
OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */
|
||||
OP_SETLISTO,/* A Bc */
|
||||
|
84
lparser.c
84
lparser.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
|
||||
** $Id: lparser.c,v 1.167 2002/02/14 21:46:58 roberto Exp $
|
||||
** Lua Parser
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -247,12 +247,12 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
|
||||
}
|
||||
|
||||
|
||||
static void code_params (LexState *ls, int nparams, short dots) {
|
||||
static void code_params (LexState *ls, int nparams, int dots) {
|
||||
FuncState *fs = ls->fs;
|
||||
adjustlocalvars(ls, nparams);
|
||||
luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters");
|
||||
fs->f->numparams = cast(short, fs->nactloc); /* `self' could be there already */
|
||||
fs->f->is_vararg = dots;
|
||||
fs->f->numparams = cast(lu_byte, fs->nactloc);
|
||||
fs->f->is_vararg = cast(lu_byte, dots);
|
||||
if (dots) {
|
||||
new_localvarstr(ls, "arg", 0);
|
||||
adjustlocalvars(ls, 1);
|
||||
@ -271,7 +271,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) {
|
||||
|
||||
static void leavebreak (FuncState *fs, Breaklabel *bl) {
|
||||
fs->bl = bl->previous;
|
||||
luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs));
|
||||
luaK_patchtohere(fs, bl->breaklist);
|
||||
lua_assert(bl->nactloc == fs->nactloc);
|
||||
}
|
||||
|
||||
@ -471,8 +471,11 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
|
||||
FuncState *fs = ls->fs;
|
||||
int reg = ls->fs->freereg;
|
||||
expdesc key, val;
|
||||
if (ls->t.token == TK_NAME)
|
||||
if (ls->t.token == TK_NAME) {
|
||||
luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor");
|
||||
cc->nh++;
|
||||
checkname(ls, &key);
|
||||
}
|
||||
else /* ls->t.token == '[' */
|
||||
luaY_index(ls, &key);
|
||||
check(ls, '=');
|
||||
@ -481,8 +484,6 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
|
||||
luaK_exp2anyreg(fs, &val);
|
||||
luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key));
|
||||
fs->freereg = reg; /* free registers */
|
||||
luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor");
|
||||
cc->nh++;
|
||||
}
|
||||
|
||||
|
||||
@ -893,7 +894,7 @@ static void whilestat (LexState *ls, int line) {
|
||||
check(ls, TK_DO);
|
||||
block(ls);
|
||||
luaK_patchlist(fs, luaK_jump(fs), while_init);
|
||||
luaK_patchlist(fs, v.f, luaK_getlabel(fs));
|
||||
luaK_patchtohere(fs, v.f);
|
||||
check_match(ls, TK_END, TK_WHILE, line);
|
||||
leavebreak(fs, &bl);
|
||||
}
|
||||
@ -922,24 +923,11 @@ static void exp1 (LexState *ls) {
|
||||
}
|
||||
|
||||
|
||||
static void forbody (LexState *ls, OpCode loopfor) {
|
||||
/* forbody -> DO block END */
|
||||
FuncState *fs = ls->fs;
|
||||
int basereg = fs->freereg - 3;
|
||||
int prep = luaK_jump(fs);
|
||||
int blockinit = luaK_getlabel(fs);
|
||||
check(ls, TK_DO);
|
||||
adjustlocalvars(ls, 3); /* scope for control variables */
|
||||
block(ls);
|
||||
luaK_patchlist(fs, prep, luaK_getlabel(fs));
|
||||
luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit);
|
||||
removelocalvars(ls, 3, 1);
|
||||
}
|
||||
|
||||
|
||||
static void fornum (LexState *ls, TString *varname) {
|
||||
/* fornum -> NAME = exp1,exp1[,exp1] forbody */
|
||||
/* fornum -> NAME = exp1,exp1[,exp1] DO body */
|
||||
FuncState *fs = ls->fs;
|
||||
int prep;
|
||||
int base = fs->freereg;
|
||||
new_localvar(ls, varname, 0);
|
||||
new_localvarstr(ls, "(limit)", 1);
|
||||
new_localvarstr(ls, "(step)", 2);
|
||||
@ -954,26 +942,42 @@ static void fornum (LexState *ls, TString *varname) {
|
||||
luaK_reserveregs(fs, 1);
|
||||
}
|
||||
luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
|
||||
forbody(ls, OP_FORLOOP);
|
||||
luaK_jump(fs);
|
||||
prep = luaK_getlabel(fs);
|
||||
check(ls, TK_DO);
|
||||
adjustlocalvars(ls, 3); /* scope for control variables */
|
||||
block(ls);
|
||||
luaK_patchtohere(fs, prep-1);
|
||||
luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep);
|
||||
removelocalvars(ls, 3, 1);
|
||||
}
|
||||
|
||||
|
||||
static void forlist (LexState *ls, TString *indexname) {
|
||||
/* forlist -> NAME,NAME IN exp1 forbody */
|
||||
/* forlist -> NAME {,NAME} IN exp1 DO body */
|
||||
FuncState *fs = ls->fs;
|
||||
int nvars = 0;
|
||||
int prep;
|
||||
int base = fs->freereg;
|
||||
new_localvarstr(ls, "(table)", 0);
|
||||
new_localvar(ls, indexname, 1);
|
||||
if (optional(ls, ',')) {
|
||||
new_localvar(ls, str_checkname(ls), 2);
|
||||
next(ls); /* skip var name */
|
||||
new_localvar(ls, indexname, ++nvars);
|
||||
while (optional(ls, ',')) {
|
||||
new_localvar(ls, str_checkname(ls), ++nvars);
|
||||
next(ls);
|
||||
}
|
||||
else
|
||||
new_localvarstr(ls, "(val)", 2);
|
||||
check(ls, TK_IN);
|
||||
exp1(ls); /* table */
|
||||
luaK_reserveregs(fs, 2); /* registers for index and val */
|
||||
luaK_codeABC(fs, OP_LOADNIL, fs->freereg - 2, fs->freereg - 1, 0);
|
||||
forbody(ls, OP_TFORLOOP);
|
||||
luaK_checkstack(fs, 2); /* at least two slots, to traverse tables */
|
||||
luaK_reserveregs(fs, nvars); /* registers for vars */
|
||||
luaK_codeABC(fs, OP_LOADNIL, base+1, base+nvars, 0);
|
||||
adjustlocalvars(ls, nvars+1); /* scope for control variables */
|
||||
luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
|
||||
prep = luaK_jump(fs);
|
||||
check(ls, TK_DO);
|
||||
block(ls);
|
||||
luaK_patchlist(fs, luaK_jump(fs), prep-1);
|
||||
luaK_patchtohere(fs, prep);
|
||||
removelocalvars(ls, nvars+1, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -1013,18 +1017,18 @@ static void ifstat (LexState *ls, int line) {
|
||||
test_then_block(ls, &v); /* IF cond THEN block */
|
||||
while (ls->t.token == TK_ELSEIF) {
|
||||
luaK_concat(fs, &escapelist, luaK_jump(fs));
|
||||
luaK_patchlist(fs, v.f, luaK_getlabel(fs));
|
||||
luaK_patchtohere(fs, v.f);
|
||||
test_then_block(ls, &v); /* ELSEIF cond THEN block */
|
||||
}
|
||||
if (ls->t.token == TK_ELSE) {
|
||||
luaK_concat(fs, &escapelist, luaK_jump(fs));
|
||||
luaK_patchlist(fs, v.f, luaK_getlabel(fs));
|
||||
luaK_patchtohere(fs, v.f);
|
||||
next(ls); /* skip ELSE */
|
||||
block(ls); /* `else' part */
|
||||
}
|
||||
else
|
||||
luaK_concat(fs, &escapelist, v.f);
|
||||
luaK_patchlist(fs, escapelist, luaK_getlabel(fs));
|
||||
luaK_patchtohere(fs, escapelist);
|
||||
check_match(ls, TK_END, TK_IF, line);
|
||||
}
|
||||
|
||||
@ -1182,7 +1186,7 @@ static int statement (LexState *ls) {
|
||||
static void parlist (LexState *ls) {
|
||||
/* parlist -> [ param { `,' param } ] */
|
||||
int nparams = 0;
|
||||
short dots = 0;
|
||||
int dots = 0;
|
||||
if (ls->t.token != ')') { /* is `parlist' not empty? */
|
||||
do {
|
||||
switch (ls->t.token) {
|
||||
|
15
lvm.c
15
lvm.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.c,v 1.217 2002/03/04 15:40:04 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 1.218 2002/03/04 21:33:09 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -560,24 +560,21 @@ StkId luaV_execute (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
case OP_TFORLOOP: {
|
||||
int j = GETARG_sBc(i);
|
||||
int loop = 0;
|
||||
pc += j; /* jump back before tests (for error messages) */
|
||||
if (ttype(ra) == LUA_TTABLE) {
|
||||
Table *t = hvalue(ra);
|
||||
loop = luaH_next(L, t, ra+1);
|
||||
if (luaH_next(L, t, ra+1))
|
||||
pc++; /* skip jump (keep looping) */
|
||||
}
|
||||
else if (ttype(ra) == LUA_TFUNCTION) {
|
||||
setobj(ra+1, ra);
|
||||
L->top = ra+2; /* no arguments */
|
||||
luaD_call(L, ra+1, 2);
|
||||
luaD_call(L, ra+1, GETARG_C(i));
|
||||
L->top = L->ci->top;
|
||||
loop = (ttype(ra+1) != LUA_TNIL);
|
||||
if (ttype(ra+1) != LUA_TNIL)
|
||||
pc++; /* skip jump (keep looping) */
|
||||
}
|
||||
else
|
||||
luaD_error(L, "`for' generator must be a table or function");
|
||||
if (!loop)
|
||||
pc -= j; /* undo jump */
|
||||
break;
|
||||
}
|
||||
case OP_SETLIST:
|
||||
|
Loading…
Reference in New Issue
Block a user