From caf01b5bfa33617b7bb2c40292f74599f6030eba Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 29 Jan 2001 11:14:49 -0200 Subject: better implementation for list "for" --- lcode.c | 6 +++--- lparser.c | 9 +++++---- ltable.c | 11 ++++++++++- ltable.h | 5 +++-- lvm.c | 28 ++++++++++++++++++---------- 5 files changed, 39 insertions(+), 20 deletions(-) diff --git a/lcode.c b/lcode.c index 61b1f2ce..30a25a65 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.56 2001/01/15 16:13:24 roberto Exp roberto $ +** $Id: lcode.c,v 1.57 2001/01/19 13:20:30 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -698,8 +698,8 @@ const OpProperties luaK_opproperties[NUM_OPCODES] = { {iO, 0, 0}, /* OP_PUSHNILJMP */ {iS, 0, 0}, /* OP_FORPREP */ {iS, 0, 3}, /* OP_FORLOOP */ - {iS, 2, 0}, /* OP_LFORPREP */ - {iS, 0, 3}, /* OP_LFORLOOP */ + {iS, 3, 0}, /* OP_LFORPREP */ + {iS, 0, 4}, /* OP_LFORLOOP */ {iAB, VD, 0} /* OP_CLOSURE */ }; diff --git a/lparser.c b/lparser.c index d796fabd..83496128 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.124 2001/01/15 16:13:24 roberto Exp roberto $ +** $Id: lparser.c,v 1.125 2001/01/19 13:20:30 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -890,9 +890,10 @@ static void forlist (LexState *ls, TString *indexname) { next(ls); /* skip `in' */ exp1(ls); /* table */ new_localvarstr(ls, "(table)", 0); - new_localvar(ls, indexname, 1); - new_localvar(ls, valname, 2); - forbody(ls, 3, OP_LFORPREP, OP_LFORLOOP); + new_localvarstr(ls, "(index)", 1); + new_localvar(ls, indexname, 2); + new_localvar(ls, valname, 3); + forbody(ls, 4, OP_LFORPREP, OP_LFORLOOP); } diff --git a/ltable.c b/ltable.c index 5893f629..f8352fe5 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 1.69 2001/01/26 14:16:35 roberto Exp roberto $ +** $Id: ltable.c,v 1.70 2001/01/26 15:58:50 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -72,6 +72,15 @@ Node *luaH_next (lua_State *L, Hash *t, const TObject *key) { } +int luaH_nexti (Hash *t, int i) { + for (i++; isize; i++) { + if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */ + return i; + } + return -1; /* no more elements */ +} + + static void setnodevector (lua_State *L, Hash *t, luint32 size) { int i; if (size > MAX_INT) diff --git a/ltable.h b/ltable.h index 482f0ee6..cbdcf743 100644 --- a/ltable.h +++ b/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 1.28 2001/01/26 13:18:00 roberto Exp roberto $ +** $Id: ltable.h,v 1.29 2001/01/26 14:16:35 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -21,7 +21,8 @@ Hash *luaH_new (lua_State *L, int nhash); void luaH_free (lua_State *L, Hash *t); TObject *luaH_set (lua_State *L, Hash *t, const TObject *key); -Node * luaH_next (lua_State *L, Hash *t, const TObject *r); +Node *luaH_next (lua_State *L, Hash *t, const TObject *r); +int luaH_nexti (Hash *t, int i); TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key); TObject *luaH_setstr (lua_State *L, Hash *t, TString *key); diff --git a/lvm.c b/lvm.c index 9a2c75f4..1da0ce20 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.157 2001/01/24 16:20:54 roberto Exp roberto $ +** $Id: lvm.c,v 1.158 2001/01/26 18:43:22 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -644,28 +644,36 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { break; } case OP_LFORPREP: { - Node *node; + int n; + Hash *t; if (ttype(top-1) != LUA_TTABLE) luaD_error(L, "`for' table must be a table"); - node = luaH_next(L, hvalue(top-1), &luaO_nilobject); - if (node == NULL) { /* `empty' loop? */ + t = hvalue(top-1); + n = luaH_nexti(t, -1); + if (n == -1) { /* `empty' loop? */ top--; /* remove table */ dojump(pc, i); /* jump to loop end */ } else { - top += 2; /* index,value */ + Node *node = node(t, n); + top += 3; /* index,key,value */ + setnvalue(top-3, n); /* index */ setobj(top-2, key(node)); setobj(top-1, val(node)); } break; } case OP_LFORLOOP: { - Node *node; - lua_assert(ttype(top-3) == LUA_TTABLE); - node = luaH_next(L, hvalue(top-3), top-2); - if (node == NULL) /* end loop? */ - top -= 3; /* remove table, key, and value */ + Hash *t = hvalue(top-4); + int n = (int)nvalue(top-3); + lua_assert(ttype(top-3) == LUA_TNUMBER); + lua_assert(ttype(top-4) == LUA_TTABLE); + n = luaH_nexti(t, n); + if (n == -1) /* end loop? */ + top -= 4; /* remove table, index, key, and value */ else { + Node *node = node(t, n); + setnvalue(top-3, n); /* index */ setobj(top-2, key(node)); setobj(top-1, val(node)); dojump(pc, i); /* repeat loop */ -- cgit v1.2.3-55-g6feb