Kaynağa Gözat

new function "lua_next" (+ new implementation for "next")

Roberto Ierusalimschy 26 yıl önce
ebeveyn
işleme
f04c83e075
6 değiştirilmiş dosya ile 143 ekleme ve 132 silme
  1. 48 16
      lapi.c
  2. 2 1
      lapi.h
  3. 83 89
      lbuiltin.c
  4. 5 23
      ltable.c
  5. 2 2
      ltable.h
  6. 3 1
      lua.h

+ 48 - 16
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;
 }
 
 

+ 2 - 1
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

+ 83 - 89
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;

+ 5 - 23
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);
 }
 
 

+ 2 - 2
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);
 

+ 3 - 1
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: [email protected]
@@ -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);