From f04c83e0759b1059545ea0526c5999c35cb1793f Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 23 Feb 1999 11:57:28 -0300 Subject: [PATCH] new function "lua_next" (+ new implementation for "next") --- lapi.c | 64 +++++++++++++++----- lapi.h | 3 +- lbuiltin.c | 172 ++++++++++++++++++++++++++--------------------------- ltable.c | 28 ++------- ltable.h | 4 +- lua.h | 4 +- 6 files changed, 143 insertions(+), 132 deletions(-) diff --git a/lapi.c b/lapi.c index 65654138..86acf301 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.36 1999/02/12 19:23:02 roberto Exp roberto $ +** $Id: lapi.c,v 1.37 1999/02/22 19:13:12 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -25,7 +25,7 @@ char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" - "$Autores: " LUA_AUTHORS " $"; + "$Authors: " LUA_AUTHORS " $"; @@ -70,12 +70,8 @@ void luaA_packresults (void) } -int luaA_passresults (void) -{ - luaD_checkstack(L->Cstack.num); - memcpy(L->stack.top, L->Cstack.lua2C+L->stack.stack, - L->Cstack.num*sizeof(TObject)); - L->stack.top += L->Cstack.num; +int luaA_passresults (void) { + L->Cstack.base = L->Cstack.lua2C; /* position of first result */ return L->Cstack.num; } @@ -87,24 +83,29 @@ static void checkCparams (int nParams) } -static lua_Object put_luaObject (TObject *o) -{ +static lua_Object put_luaObject (TObject *o) { luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base); L->stack.stack[L->Cstack.base++] = *o; return L->Cstack.base; /* this is +1 real position (see Ref) */ } -static lua_Object put_luaObjectonTop (void) -{ +static lua_Object put_luaObjectonTop (void) { luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base); L->stack.stack[L->Cstack.base++] = *(--L->stack.top); return L->Cstack.base; /* this is +1 real position (see Ref) */ } -lua_Object lua_pop (void) -{ +static void top2LC (int n) { + /* Put the 'n' elements on the top as the Lua2C contents */ + L->Cstack.base = (L->stack.top-L->stack.stack); /* new base */ + L->Cstack.lua2C = L->Cstack.base-n; /* position of the new results */ + L->Cstack.num = n; /* number of results */ +} + + +lua_Object lua_pop (void) { checkCparams(1); return put_luaObjectonTop(); } @@ -436,6 +437,11 @@ TaggedString *luaA_nextvar (TaggedString *g) { } while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */ g = (TaggedString *)g->head.next; + if (g) { + ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = g; + incr_top; + luaA_pushobject(&g->u.s.globalval); + } return g; } @@ -444,11 +450,37 @@ char *lua_nextvar (char *varname) { TaggedString *g = (varname == NULL) ? NULL : luaS_new(varname); g = luaA_nextvar(g); if (g) { - luaA_pushobject(&g->u.s.globalval); + top2LC(2); return g->str; } - else + else { + top2LC(0); return NULL; + } +} + + +int luaA_next (Hash *t, int i) { + Node *n; + int tsize = nhash(t); + while (i < tsize && ttype(val(n=node(t, i))) == LUA_T_NIL) i++; + if (i >= tsize) + return 0; + else { + luaA_pushobject(ref(n)); + luaA_pushobject(val(n)); + return i+1; + } +} + + +int lua_next (lua_Object o, int i) { + TObject *t = Address(o); + if (ttype(t) != LUA_T_ARRAY) + lua_error("API error: object is not a table in `lua_next'"); + i = luaA_next(avalue(t), i); + top2LC((i==0) ? 0 : 2); + return i; } diff --git a/lapi.h b/lapi.h index cf4ebff4..c3d6fc8d 100644 --- a/lapi.h +++ b/lapi.h @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 1.2 1998/06/19 16:14:09 roberto Exp roberto $ +** $Id: lapi.h,v 1.3 1999/02/22 19:13:12 roberto Exp roberto $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -17,5 +17,6 @@ void luaA_pushobject (TObject *o); void luaA_packresults (void); int luaA_passresults (void); TaggedString *luaA_nextvar (TaggedString *g); +int luaA_next (Hash *t, int i); #endif diff --git a/lbuiltin.c b/lbuiltin.c index 1143dae7..9971f5a1 100644 --- a/lbuiltin.c +++ b/lbuiltin.c @@ -1,5 +1,5 @@ /* -** $Id: lbuiltin.c,v 1.52 1999/02/22 14:17:24 roberto Exp roberto $ +** $Id: lbuiltin.c,v 1.53 1999/02/22 19:13:12 roberto Exp roberto $ ** Built-in functions ** See Copyright Notice in lua.h */ @@ -300,9 +300,76 @@ static void luaB_call (void) { } } + +static void luaB_nextvar (void) { + TObject *o = luaA_Address(luaL_nonnullarg(1)); + TaggedString *g; + if (ttype(o) == LUA_T_NIL) + g = NULL; + else { + luaL_arg_check(ttype(o) == LUA_T_STRING, 1, "variable name expected"); + g = tsvalue(o); + } + if (!luaA_nextvar(g)) + lua_pushnil(); +} + + +static void luaB_next (void) { + Hash *a = gethash(1); + TObject *k = luaA_Address(luaL_nonnullarg(2)); + int i = (ttype(k) == LUA_T_NIL) ? 0 : luaH_pos(a, k)+1; + if (luaA_next(a, i) == 0) + lua_pushnil(); +} + + +static void luaB_tostring (void) { + lua_Object obj = lua_getparam(1); + TObject *o = luaA_Address(obj); + char buff[64]; + switch (ttype(o)) { + case LUA_T_NUMBER: + lua_pushstring(lua_getstring(obj)); + return; + case LUA_T_STRING: + lua_pushobject(obj); + return; + case LUA_T_ARRAY: + sprintf(buff, "table: %p", (void *)o->value.a); + break; + case LUA_T_CLOSURE: + sprintf(buff, "function: %p", (void *)o->value.cl); + break; + case LUA_T_PROTO: + sprintf(buff, "function: %p", (void *)o->value.tf); + break; + case LUA_T_CPROTO: + sprintf(buff, "function: %p", (void *)o->value.f); + break; + case LUA_T_USERDATA: + sprintf(buff, "userdata: %p", o->value.ts->u.d.v); + break; + case LUA_T_NIL: + lua_pushstring("nil"); + return; + default: + LUA_INTERNALERROR("invalid type"); + } + lua_pushstring(buff); +} + + +static void luaB_type (void) { + lua_Object o = luaL_nonnullarg(1); + lua_pushstring(luaO_typename(luaA_Address(o))); + lua_pushnumber(lua_tag(o)); +} + /* }====================================================== */ + /* ** {====================================================== ** "Extra" functions @@ -352,7 +419,7 @@ static void luaB_foreach (void) { luaD_calln(2, 1); if (ttype(L->stack.top-1) != LUA_T_NIL) return; - L->stack.top--; + L->stack.top--; /* remove result */ } } } @@ -361,22 +428,21 @@ static void luaB_foreach (void) { static void luaB_foreachvar (void) { TObject *f = luaA_Address(luaL_functionarg(1)); GCnode *g; - StkId name = L->Cstack.base++; /* place to keep var name (to avoid GC) */ - luaD_checkstack(4); /* for var name, f, s, and globalvar */ - ttype(L->stack.stack+name) = LUA_T_NIL; - L->stack.top++; /* top == base */ + luaD_checkstack(4); /* for extra var name, f, var name, and globalval */ for (g = L->rootglobal.next; g; g = g->next) { TaggedString *s = (TaggedString *)g; if (s->u.s.globalval.ttype != LUA_T_NIL) { - ttype(L->stack.stack+name) = LUA_T_STRING; - tsvalue(L->stack.stack+name) = s; /* keep s on stack to avoid GC */ + pushtagstring(s); /* keep (extra) s on stack to avoid GC */ *(L->stack.top++) = *f; pushtagstring(s); *(L->stack.top++) = s->u.s.globalval; luaD_calln(2, 1); - if (ttype(L->stack.top-1) != LUA_T_NIL) + if (ttype(L->stack.top-1) != LUA_T_NIL) { + L->stack.top--; + *(L->stack.top-1) = *L->stack.top; /* remove extra s */ return; - L->stack.top--; + } + L->stack.top-=2; /* remove result and extra s */ } } } @@ -505,85 +571,7 @@ static void luaB_sort (void) { /* -** {====================================================== -** Internal Functions. -** These functions need access to internal structures -** to be implemented. -** ======================================================= -*/ - - -static void luaB_nextvar (void) { - TObject *o = luaA_Address(luaL_nonnullarg(1)); - TaggedString *g; - if (ttype(o) == LUA_T_NIL) - g = NULL; - else { - luaL_arg_check(ttype(o) == LUA_T_STRING, 1, "variable name expected"); - g = tsvalue(o); - } - g = luaA_nextvar(g); - if (g) { - pushtagstring(g); - luaA_pushobject(&g->u.s.globalval); - } - else lua_pushnil(); /* no more globals */ -} - - -static void luaB_next (void) { - Node *n = luaH_next(gethash(1), luaA_Address(luaL_nonnullarg(2))); - if (n) { - luaA_pushobject(&n->ref); - luaA_pushobject(&n->val); - } - else lua_pushnil(); -} - - -static void luaB_tostring (void) { - lua_Object obj = lua_getparam(1); - TObject *o = luaA_Address(obj); - char buff[64]; - switch (ttype(o)) { - case LUA_T_NUMBER: - lua_pushstring(lua_getstring(obj)); - return; - case LUA_T_STRING: - lua_pushobject(obj); - return; - case LUA_T_ARRAY: - sprintf(buff, "table: %p", (void *)o->value.a); - break; - case LUA_T_CLOSURE: - sprintf(buff, "function: %p", (void *)o->value.cl); - break; - case LUA_T_PROTO: - sprintf(buff, "function: %p", (void *)o->value.tf); - break; - case LUA_T_CPROTO: - sprintf(buff, "function: %p", (void *)o->value.f); - break; - case LUA_T_USERDATA: - sprintf(buff, "userdata: %p", o->value.ts->u.d.v); - break; - case LUA_T_NIL: - lua_pushstring("nil"); - return; - default: - LUA_INTERNALERROR("invalid type"); - } - lua_pushstring(buff); -} - - -static void luaB_type (void) { - lua_Object o = luaL_nonnullarg(1); - lua_pushstring(luaO_typename(luaA_Address(o))); - lua_pushnumber(lua_tag(o)); -} - -/* }====================================================== */ +** ====================================================== */ @@ -658,6 +646,12 @@ static void testC (void) { case 'I': reg[getnum(s)] = lua_rawgettable(); break; case 't': lua_settable(); break; case 'T': lua_rawsettable(); break; + case 'N' : lua_pushstring(lua_nextvar(lua_getstring(reg[getnum(s)]))); + break; + case 'n' : { int n=getnum(s); + n=lua_next(reg[n], lua_getnumber(reg[getnum(s)])); + lua_pushnumber(n); break; + } default: luaL_verror("unknown command in `testC': %c", *(s-1)); } if (*s == 0) return; diff --git a/ltable.c b/ltable.c index 7b355519..85cc6218 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 1.19 1999/01/25 12:30:11 roberto Exp roberto $ +** $Id: ltable.c,v 1.20 1999/01/25 17:41:19 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -152,28 +152,10 @@ void luaH_set (Hash *t, TObject *ref, TObject *val) { } -static Node *hashnext (Hash *t, int i) { - Node *n; - int tsize = nhash(t); - if (i >= tsize) - return NULL; - n = node(t, i); - while (ttype(val(n)) == LUA_T_NIL) { - if (++i >= tsize) - return NULL; - n = node(t, i); - } - return n; -} - -Node *luaH_next (Hash *t, TObject *r) { - if (ttype(r) == LUA_T_NIL) - return hashnext(t, 0); - else { - Node *n = luaH_present(t, r); - luaL_arg_check(ttype(val(n)) != LUA_T_NIL, 2, "key not found"); - return hashnext(t, (n-(t->node))+1); - } +int luaH_pos (Hash *t, TObject *r) { + Node *n = luaH_present(t, r); + luaL_arg_check(ttype(val(n)) != LUA_T_NIL, 2, "key not found"); + return n-(t->node); } diff --git a/ltable.h b/ltable.h index 766bda16..b6a46cd2 100644 --- a/ltable.h +++ b/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 1.9 1999/01/25 12:30:11 roberto Exp roberto $ +** $Id: ltable.h,v 1.10 1999/01/25 17:40:10 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -22,7 +22,7 @@ Hash *luaH_new (int nhash); void luaH_free (Hash *frees); Node *luaH_present (Hash *t, TObject *key); void luaH_set (Hash *t, TObject *ref, TObject *val); -Node *luaH_next (Hash *t, TObject *r); +int luaH_pos (Hash *t, TObject *r); void luaH_setint (Hash *t, int ref, TObject *val); TObject *luaH_getint (Hash *t, int ref); diff --git a/lua.h b/lua.h index 237c72eb..c6374a44 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.27 1999/02/09 15:59:22 roberto Exp roberto $ +** $Id: lua.h,v 1.28 1999/02/22 19:13:12 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 @@ -90,6 +90,8 @@ lua_Object lua_rawgettable (void); /* In: table, index */ int lua_tag (lua_Object object); char *lua_nextvar (char *varname); /* Out: value */ +int lua_next (lua_Object o, int i); + /* Out: ref, value */ int lua_ref (int lock); /* In: value */ lua_Object lua_getref (int ref);