aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-09 16:47:44 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-09 16:47:44 -0300
commit7b65328c8e89ecc999e47d00288bfa4cf6692cdc (patch)
tree4bff202763e7389ca40a44003703376d32eeaf78
parentd2e05589d738c3a1b563879435d5cc0830719fd1 (diff)
downloadlua-7b65328c8e89ecc999e47d00288bfa4cf6692cdc.tar.gz
lua-7b65328c8e89ecc999e47d00288bfa4cf6692cdc.tar.bz2
lua-7b65328c8e89ecc999e47d00288bfa4cf6692cdc.zip
new semantics for `generic for' (with state)
-rw-r--r--ldebug.c5
-rw-r--r--lopcodes.c4
-rw-r--r--lopcodes.h7
-rw-r--r--lparser.c24
-rw-r--r--lvm.c26
5 files changed, 35 insertions, 31 deletions
diff --git a/ldebug.c b/ldebug.c
index e69afafd..eb282db7 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 1.105 2002/03/25 17:47:14 roberto Exp roberto $ 2** $Id: ldebug.c,v 1.106 2002/04/04 17:21:31 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -347,8 +347,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
347 break; 347 break;
348 } 348 }
349 case OP_TFORLOOP: { 349 case OP_TFORLOOP: {
350 checkreg(pt, a+c); 350 checkreg(pt, a+2+c);
351 checkreg(pt, a+2); /* at least 2 for table generators */
352 check(pc+2 < pt->sizecode); /* check skip */ 351 check(pc+2 < pt->sizecode); /* check skip */
353 break; 352 break;
354 } 353 }
diff --git a/lopcodes.c b/lopcodes.c
index c156f533..bbe66717 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.c,v 1.13 2002/03/21 20:32:22 roberto Exp roberto $ 2** $Id: lopcodes.c,v 1.14 2002/03/25 17:47:14 roberto Exp roberto $
3** extracted automatically from lopcodes.h by mkprint.lua 3** extracted automatically from lopcodes.h by mkprint.lua
4** DO NOT EDIT 4** DO NOT EDIT
5** See Copyright Notice in lua.h 5** See Copyright Notice in lua.h
@@ -49,6 +49,7 @@ const char *const luaP_opnames[] = {
49 "RETURN", 49 "RETURN",
50 "FORLOOP", 50 "FORLOOP",
51 "TFORLOOP", 51 "TFORLOOP",
52 "OP_TFORPREP",
52 "SETLIST", 53 "SETLIST",
53 "SETLISTO", 54 "SETLISTO",
54 "CLOSE", 55 "CLOSE",
@@ -98,6 +99,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
98 ,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */ 99 ,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */
99 ,opmode(0,0,0,0, 0,0,iAsBc) /* OP_FORLOOP */ 100 ,opmode(0,0,0,0, 0,0,iAsBc) /* OP_FORLOOP */
100 ,opmode(0,0,0,0, 0,0,iABC) /* OP_TFORLOOP */ 101 ,opmode(0,0,0,0, 0,0,iABC) /* OP_TFORLOOP */
102 ,opmode(0,0,0,0, 0,0,iABC) /* OP_TFORPREP */
101 ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */ 103 ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */
102 ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */ 104 ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */
103 ,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */ 105 ,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */
diff --git a/lopcodes.h b/lopcodes.h
index 566fc84f..15e1f09d 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.h,v 1.92 2002/03/21 20:32:22 roberto Exp roberto $ 2** $Id: lopcodes.h,v 1.93 2002/03/25 17:47:14 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -173,8 +173,9 @@ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see (3)) */
173 173
174OP_FORLOOP,/* A sBc R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBc */ 174OP_FORLOOP,/* A sBc R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBc */
175 175
176OP_TFORLOOP,/* A C R(A+1), ... ,R(A+C) := R(A)(); 176OP_TFORLOOP,/* A C R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
177 if R(A+1) ~= nil then pc++ */ 177 if R(A+2) ~= nil then pc++ */
178OP_TFORPREP,/* A if type(R(A)) == table then R(A+1):=R(A), R(A):=next */
178 179
179OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ 180OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */
180OP_SETLISTO,/* A Bc */ 181OP_SETLISTO,/* A Bc */
diff --git a/lparser.c b/lparser.c
index 6b0234f5..9e723f0d 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 1.173 2002/03/25 17:47:14 roberto Exp roberto $ 2** $Id: lparser.c,v 1.174 2002/04/02 20:34:15 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -331,6 +331,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) {
331 bl->upval = 0; 331 bl->upval = 0;
332 bl->previous = fs->bl; 332 bl->previous = fs->bl;
333 fs->bl = bl; 333 fs->bl = bl;
334 lua_assert(fs->freereg == fs->nactloc);
334} 335}
335 336
336 337
@@ -1028,24 +1029,25 @@ static void fornum (LexState *ls, TString *varname, int line) {
1028 1029
1029 1030
1030static void forlist (LexState *ls, TString *indexname) { 1031static void forlist (LexState *ls, TString *indexname) {
1031 /* forlist -> NAME {,NAME} IN exp1 DO body */ 1032 /* forlist -> NAME {,NAME} IN explist1 DO body */
1032 FuncState *fs = ls->fs; 1033 FuncState *fs = ls->fs;
1034 expdesc e;
1033 int nvars = 0; 1035 int nvars = 0;
1034 int prep; 1036 int prep;
1035 int base = fs->freereg; 1037 int base = fs->freereg;
1036 new_localvarstr(ls, "(for generator)", 0); 1038 new_localvarstr(ls, "(for generator)", nvars++);
1037 new_localvar(ls, indexname, ++nvars); 1039 new_localvarstr(ls, "(for state)", nvars++);
1040 new_localvar(ls, indexname, nvars++);
1038 while (optional(ls, ',')) { 1041 while (optional(ls, ',')) {
1039 new_localvar(ls, str_checkname(ls), ++nvars); 1042 new_localvar(ls, str_checkname(ls), nvars++);
1040 next(ls); 1043 next(ls);
1041 } 1044 }
1042 check(ls, TK_IN); 1045 check(ls, TK_IN);
1043 exp1(ls); /* table */ 1046 adjust_assign(ls, 3, explist1(ls, &e), &e);
1044 luaK_checkstack(fs, 2); /* at least two slots, to traverse tables */ 1047 luaK_reserveregs(fs, nvars - 3); /* registers for other variables */
1045 luaK_reserveregs(fs, nvars); /* registers for vars */ 1048 luaK_codeABC(fs, OP_TFORPREP, base, 0, 0);
1046 luaK_codeABC(fs, OP_LOADNIL, base+1, base+nvars, 0); 1049 luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
1047 adjustlocalvars(ls, nvars+1); /* scope for control variables */ 1050 adjustlocalvars(ls, nvars); /* scope for all variables */
1048 luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
1049 prep = luaK_jump(fs); 1051 prep = luaK_jump(fs);
1050 check(ls, TK_DO); 1052 check(ls, TK_DO);
1051 block(ls); 1053 block(ls);
diff --git a/lvm.c b/lvm.c
index 7f358cca..bb1b9852 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.222 2002/03/22 16:54:31 roberto Exp roberto $ 2** $Id: lvm.c,v 1.223 2002/03/25 17:47:14 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -549,21 +549,21 @@ StkId luaV_execute (lua_State *L) {
549 break; 549 break;
550 } 550 }
551 case OP_TFORLOOP: { 551 case OP_TFORLOOP: {
552 setobj(ra+4, ra+2);
553 setobj(ra+3, ra+1);
554 setobj(ra+2, ra);
555 L->top = ra+5;
556 luaD_call(L, ra+2, GETARG_C(i) + 1);
557 L->top = L->ci->top;
558 if (ttype(ra+2) != LUA_TNIL) pc++; /* skip jump (keep looping) */
559 break;
560 }
561 case OP_TFORPREP: {
552 if (ttype(ra) == LUA_TTABLE) { 562 if (ttype(ra) == LUA_TTABLE) {
553 Table *t = hvalue(ra);
554 if (luaH_next(L, t, ra+1))
555 pc++; /* skip jump (keep looping) */
556 }
557 else if (ttype(ra) == LUA_TFUNCTION) {
558 setobj(ra+1, ra); 563 setobj(ra+1, ra);
559 L->top = ra+2; /* no arguments */ 564 setsvalue(ra, luaS_new(L, "next"));
560 luaD_call(L, ra+1, GETARG_C(i)); 565 luaV_gettable(L, gt(L), ra, ra);
561 L->top = L->ci->top;
562 if (ttype(ra+1) != LUA_TNIL)
563 pc++; /* skip jump (keep looping) */
564 } 566 }
565 else
566 luaD_error(L, "`for' generator must be a table or function");
567 break; 567 break;
568 } 568 }
569 case OP_SETLIST: 569 case OP_SETLIST: