From 100bfec39a3de3029a97e645e7fe33877d7bbc2f Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 31 Aug 2000 11:08:27 -0300 Subject: new implementation for `next' --- lapi.c | 35 ++++++++++++++++------------------- lapi.h | 3 +-- lbuiltin.c | 31 +++++++++++++------------------ lcode.c | 6 +++--- lparser.c | 9 ++++----- ltable.c | 24 +++++++++++++++++++----- ltable.h | 4 ++-- lua.h | 7 ++++--- lvm.c | 32 ++++++++++++++------------------ 9 files changed, 76 insertions(+), 75 deletions(-) diff --git a/lapi.c b/lapi.c index e3d4a906..75159082 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.89 2000/08/29 14:52:27 roberto Exp roberto $ +** $Id: lapi.c,v 1.90 2000/08/29 20:43:28 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -327,7 +327,7 @@ int lua_ref (lua_State *L, int lock) { /* -** miscelaneous functions +** miscellaneous functions */ @@ -359,24 +359,21 @@ void lua_unref (lua_State *L, int ref) { } -int luaA_next (lua_State *L, const Hash *t, int i) { - int tsize = t->size; - for (; itop-1) = *key(n); + *L->top = *val(n); + api_incr_top(L); + return 1; + } + else { /* no more elements */ + L->top -= 2; /* remove key and table */ + return 0; + } } diff --git a/lapi.h b/lapi.h index e8c66393..7a475ac9 100644 --- a/lapi.h +++ b/lapi.h @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 1.18 2000/05/08 20:49:05 roberto Exp roberto $ +** $Id: lapi.h,v 1.19 2000/08/28 17:57:04 roberto Exp roberto $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -13,6 +13,5 @@ TObject *luaA_index (lua_State *L, int index); void luaA_pushobject (lua_State *L, const TObject *o); -int luaA_next (lua_State *L, const Hash *t, int i); #endif diff --git a/lbuiltin.c b/lbuiltin.c index b0399941..10dd13af 100644 --- a/lbuiltin.c +++ b/lbuiltin.c @@ -1,5 +1,5 @@ /* -** $Id: lbuiltin.c,v 1.123 2000/08/29 14:33:31 roberto Exp roberto $ +** $Id: lbuiltin.c,v 1.124 2000/08/29 14:41:56 roberto Exp roberto $ ** Built-in functions ** See Copyright Notice in lua.h */ @@ -267,6 +267,18 @@ int luaB_type (lua_State *L) { return 1; } + +int luaB_next (lua_State *L) { + luaL_checktype(L, 1, "table"); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + /* }====================================================== */ @@ -355,23 +367,6 @@ int luaB_call (lua_State *L) { } -int luaB_next (lua_State *L) { - const Hash *a = gettable(L, 1); - int i; /* `luaA_next' gets first element after `i' */ - if (lua_isnull(L, 2) || lua_isnil(L, 2)) /* no index or nil index? */ - i = 0; /* get first */ - else { - i = luaH_pos(L, a, luaA_index(L, 2))+1; - luaL_arg_check(L, i != 0, 2, "key not found"); - } - if (luaA_next(L, a, i) != 0) - return 2; /* `luaA_next' left them on the stack */ - else { - lua_pushnil(L); - return 1; - } -} - int luaB_tostring (lua_State *L) { char buff[64]; diff --git a/lcode.c b/lcode.c index adaff37a..047fb74a 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.48 2000/08/14 17:46:27 roberto Exp roberto $ +** $Id: lcode.c,v 1.49 2000/08/15 13:18:28 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -693,8 +693,8 @@ const struct OpProperties luaK_opproperties[NUM_OPCODES] = { {iO, 0, 0}, /* OP_PUSHNILJMP */ {iS, 0, 0}, /* OP_FORPREP */ {iS, 0, 3}, /* OP_FORLOOP */ - {iS, 3, 0}, /* OP_LFORPREP */ - {iS, 0, 4}, /* OP_LFORLOOP */ + {iS, 2, 0}, /* OP_LFORPREP */ + {iS, 0, 3}, /* OP_LFORLOOP */ {iAB, VD, 0} /* OP_CLOSURE */ }; diff --git a/lparser.c b/lparser.c index 673302df..5c8efeaa 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.109 2000/08/15 13:18:28 roberto Exp roberto $ +** $Id: lparser.c,v 1.110 2000/08/22 17:44:17 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -877,10 +877,9 @@ static void forlist (LexState *ls, TString *indexname) { next(ls); /* skip `in' */ exp1(ls); /* table */ new_localvarstr(ls, "*table*", 0); - new_localvarstr(ls, "*counter*", 1); - new_localvar(ls, indexname, 2); - new_localvar(ls, valname, 3); - forbody(ls, 4, OP_LFORPREP, OP_LFORLOOP); + new_localvar(ls, indexname, 1); + new_localvar(ls, valname, 2); + forbody(ls, 3, OP_LFORPREP, OP_LFORLOOP); } diff --git a/ltable.c b/ltable.c index 604129c5..3d2c4765 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 1.52 2000/08/07 20:21:34 roberto Exp roberto $ +** $Id: ltable.c,v 1.53 2000/08/09 19:16:57 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -114,12 +114,26 @@ const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) { } -int luaH_pos (lua_State *L, const Hash *t, const TObject *key) { - const TObject *v = luaH_get(L, t, key); - return (v == &luaO_nilobject) ? -1 : /* key not found */ - (int)(((const char *)v - (const char *)(&t->node[0].val))/sizeof(Node)); +Node *luaH_next (lua_State *L, const Hash *t, const TObject *key) { + int i; + if (ttype(key) == TAG_NIL) + i = 0; /* first iteration */ + else { + const TObject *v = luaH_get(L, t, key); + if (v == &luaO_nilobject) + lua_error(L, "invalid key for `next'"); + i = (int)(((const char *)v - + (const char *)(&t->node[0].val)) / sizeof(Node)) + 1; + } + for (; isize; i++) { + Node *n = node(t, i); + if (ttype(val(n)) != TAG_NIL) + return n; + } + return NULL; /* no more elements */ } + /* ** try to remove a key without value from a table. To avoid problems with ** hash, change `key' for a number with the same hash. diff --git a/ltable.h b/ltable.h index 458075b6..00dfd1c0 100644 --- a/ltable.h +++ b/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 1.22 2000/06/05 20:15:33 roberto Exp roberto $ +** $Id: ltable.h,v 1.23 2000/06/06 16:31:41 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -21,7 +21,7 @@ const TObject *luaH_getnum (const Hash *t, Number key); const TObject *luaH_getstr (const Hash *t, TString *key); void luaH_remove (Hash *t, TObject *key); TObject *luaH_set (lua_State *L, Hash *t, const TObject *key); -int luaH_pos (lua_State *L, const Hash *t, const TObject *r); +Node * luaH_next (lua_State *L, const Hash *t, const TObject *r); TObject *luaH_setint (lua_State *L, Hash *t, int key); void luaH_setstrnum (lua_State *L, Hash *t, TString *key, Number val); unsigned long luaH_hash (lua_State *L, const TObject *key); diff --git a/lua.h b/lua.h index 567f4e1a..0ad37ad6 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.61 2000/08/29 14:33:31 roberto Exp roberto $ +** $Id: lua.h,v 1.62 2000/08/29 20:43:28 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil ** e-mail: lua@tecgraf.puc-rio.br @@ -29,6 +29,7 @@ #define LUA_REFNIL (-1) #define LUA_ANYTAG (-1) +#define LUA_NOTAG (-2) #define LUA_MULTRET (-1) @@ -129,7 +130,7 @@ int lua_dobuffer (lua_State *L, const char *buff, size_t size, /* -** miscelaneous functions +** miscellaneous functions */ int lua_newtag (lua_State *L); int lua_copytagmethods (lua_State *L, int tagto, int tagfrom); @@ -141,7 +142,7 @@ void lua_unref (lua_State *L, int ref); long lua_collectgarbage (lua_State *L, long limit); -int lua_next (lua_State *L, int index, int i); +int lua_next (lua_State *L); diff --git a/lvm.c b/lvm.c index b9f5f74e..fb7998f4 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.130 2000/08/29 14:41:56 roberto Exp roberto $ +** $Id: lvm.c,v 1.131 2000/08/29 14:48:16 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -656,34 +656,30 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { break; } case OP_LFORPREP: { + Node *node; if (ttype(top-1) != TAG_TABLE) lua_error(L, "`for' table must be a table"); - top++; /* counter */ - L->top = top; - ttype(top-1) = TAG_NUMBER; - nvalue(top-1) = (Number)luaA_next(L, hvalue(top-2), 0); /* counter */ - if (nvalue(top-1) == 0) { /* `empty' loop? */ - top -= 2; /* remove table and counter */ + node = luaH_next(L, hvalue(top-1), &luaO_nilobject); + if (node == NULL) { /* `empty' loop? */ + top--; /* remove table */ pc += GETARG_S(i)+1; /* jump to loop end */ } else { top += 2; /* index,value */ - LUA_ASSERT(top==L->top, "bad top"); + *(top-2) = *key(node); + *(top-1) = *val(node); } break; } case OP_LFORLOOP: { - int n; - top -= 2; /* remove old index,value */ - LUA_ASSERT(ttype(top-2) == TAG_TABLE, "invalid table"); - LUA_ASSERT(ttype(top-1) == TAG_NUMBER, "invalid counter"); - L->top = top; - n = luaA_next(L, hvalue(top-2), (int)nvalue(top-1)); - if (n == 0) /* end loop? */ - top -= 2; /* remove table and counter */ + Node *node; + LUA_ASSERT(ttype(top-3) == TAG_TABLE, "invalid table"); + node = luaH_next(L, hvalue(top-3), top-2); + if (node == NULL) /* end loop? */ + top -= 3; /* remove table, key, and value */ else { - nvalue(top-1) = (Number)n; - top += 2; /* new index,value */ + *(top-2) = *key(node); + *(top-1) = *val(node); pc += GETARG_S(i); /* repeat loop */ } break; -- cgit v1.2.3-55-g6feb