new implementation for `next'

This commit is contained in:
Roberto Ierusalimschy 2000-08-31 11:08:27 -03:00
parent a290b84c67
commit 100bfec39a
9 changed files with 76 additions and 75 deletions

35
lapi.c
View File

@ -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 (; i<tsize; i++) {
Node *n = node(t, i);
if (ttype(val(n)) != TAG_NIL) {
luaA_pushobject(L, key(n));
luaA_pushobject(L, val(n));
return i+1; /* index to be used next time */
}
}
return 0; /* no more elements */
}
int lua_next (lua_State *L, int index, int i) {
const TObject *t = Index(L, index);
int lua_next (lua_State *L) {
const TObject *t = Index(L, -2);
Node *n;
if (ttype(t) != TAG_TABLE)
lua_error(L, "Lua API error - object is not a table in `lua_next'");
return luaA_next(L, hvalue(t), i);
n = luaH_next(L, hvalue(t), Index(L, -1));
if (n) {
*(L->top-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;
}
}

3
lapi.h
View File

@ -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

View File

@ -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];

View File

@ -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 */
};

View File

@ -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);
}

View File

@ -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 (; i<t->size; 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.

View File

@ -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);

7
lua.h
View File

@ -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);

32
lvm.c
View File

@ -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;