Procházet zdrojové kódy

global variables are stored in a Lua table

Roberto Ierusalimschy před 25 roky
rodič
revize
11a7022067
21 změnil soubory, kde provedl 180 přidání a 274 odebrání
  1. 33 45
      lapi.c
  2. 1 2
      lapi.h
  3. 43 59
      lbuiltin.c
  4. 2 5
      lbuiltin.h
  5. 1 9
      lcode.c
  6. 6 5
      ldebug.c
  7. 3 2
      ldo.c
  8. 2 29
      lgc.c
  9. 9 2
      llex.c
  10. 2 10
      lobject.h
  11. 3 3
      lstate.c
  12. 3 3
      lstate.h
  13. 17 48
      lstring.c
  14. 2 5
      lstring.h
  15. 15 7
      ltable.c
  16. 4 2
      ltable.h
  17. 2 5
      ltests.c
  18. 8 5
      lua.h
  19. 2 3
      lundump.c
  20. 19 21
      lvm.c
  21. 3 4
      lvm.h

+ 33 - 45
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.77 2000/03/29 20:19:20 roberto Exp roberto $
+** $Id: lapi.c,v 1.78 2000/04/17 19:23:12 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -65,6 +65,20 @@ lua_Object lua_pop (lua_State *L) {
 }
 
 
+void lua_pushglobaltable (lua_State *L) {
+  avalue(L->top) = L->gt;
+  ttype(L->top) = TAG_TABLE;
+  incr_top;
+}
+
+
+void lua_setglobaltable (lua_State *L, lua_Object newtable) {
+  if (lua_type(L, newtable)[0] != 't')  /* type == "table"? */
+    lua_error(L, "Lua API error - invalid value for global table");
+  L->gt = avalue(newtable);
+}
+
+
 /*
 ** Get a parameter, returning the object handle or LUA_NOOBJECT on error.
 ** `number' must be 1 to get the first parameter.
@@ -131,7 +145,10 @@ void lua_settable (lua_State *L) {
 
 void lua_rawsettable (lua_State *L) {
   luaA_checkCargs(L, 3);
-  luaV_rawsettable(L, L->top-3);
+  if (ttype(L->top-3) != TAG_TABLE)
+    lua_error(L, "indexed expression not a table");
+  luaH_set(L, avalue(L->top-3), L->top-2, L->top-1);
+  L->top -= 3;
 }
 
 
@@ -145,27 +162,32 @@ lua_Object lua_createtable (lua_State *L) {
 
 
 lua_Object lua_getglobal (lua_State *L, const char *name) {
-  luaV_getglobal(L, luaS_assertglobalbyname(L, name), L->top++);
+  luaV_getglobal(L, luaS_new(L, name), L->top++);
   return luaA_putObjectOnTop(L);
 }
 
 
-lua_Object lua_rawgetglobal (lua_State *L, const char *name) {
-  GlobalVar *gv = luaS_assertglobalbyname(L, name);
-  return luaA_putluaObject(L, &gv->value);
+void lua_setglobal (lua_State *L, const char *name) {
+  luaA_checkCargs(L, 1);
+  luaV_setglobal(L, luaS_new(L, name), L->top--);
 }
 
 
-void lua_setglobal (lua_State *L, const char *name) {
-  luaA_checkCargs(L, 1);
-  luaV_setglobal(L, luaS_assertglobalbyname(L, name), L->top--);
+/* deprecated */
+lua_Object lua_rawgetglobal (lua_State *L, const char *name) {
+  lua_pushglobaltable(L);
+  lua_pushstring(L, name);
+  return lua_rawgettable(L);
 }
 
 
+/* deprecated */
 void lua_rawsetglobal (lua_State *L, const char *name) {
-  GlobalVar *gv = luaS_assertglobalbyname(L, name);
+  TObject key;
   luaA_checkCargs(L, 1);
-  gv->value = *(--L->top);
+  ttype(&key) = TAG_STRING;
+  tsvalue(&key) = luaS_new(L, name);
+  luaH_set(L, L->gt, &key, --L->top);
 }
 
 
@@ -334,40 +356,6 @@ void lua_settag (lua_State *L, int tag) {
 }
 
 
-GlobalVar *luaA_nextvar (lua_State *L, TString *ts) {
-  GlobalVar *gv;
-  if (ts == NULL)
-    gv = L->rootglobal;  /* first variable */
-  else {
-    /* check whether name is in global var list */
-    luaL_arg_check(L, ts->u.s.gv, 1, "variable name expected");
-    gv = ts->u.s.gv->next;  /* get next */
-  }
-  while (gv && gv->value.ttype == TAG_NIL)  /* skip globals with nil */
-    gv = gv->next;
-  if (gv) {
-    ttype(L->top) = TAG_STRING; tsvalue(L->top) = gv->name;
-    incr_top;
-    luaA_pushobject(L, &gv->value);
-  }
-  return gv;
-}
-
-
-const char *lua_nextvar (lua_State *L, const char *varname) {
-  TString *ts = (varname == NULL) ? NULL : luaS_new(L, varname);
-  GlobalVar *gv = luaA_nextvar(L, ts);
-  if (gv) {
-    top2LC(L, 2);
-    return gv->name->str;
-  }
-  else {
-    top2LC(L, 0);
-    return NULL;
-  }
-}
-
-
 int luaA_next (lua_State *L, const Hash *t, int i) {
   int tsize = t->size;
   for (; i<tsize; i++) {

+ 1 - 2
lapi.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.h,v 1.15 2000/03/10 18:37:44 roberto Exp roberto $
+** $Id: lapi.h,v 1.16 2000/03/29 20:19:20 roberto Exp roberto $
 ** Auxiliary functions from Lua API
 ** See Copyright Notice in lua.h
 */
@@ -13,7 +13,6 @@
 
 void luaA_checkCargs (lua_State *L, int nargs);
 void luaA_pushobject (lua_State *L, const TObject *o);
-GlobalVar *luaA_nextvar (lua_State *L, TString *g);
 int luaA_next (lua_State *L, const Hash *t, int i);
 lua_Object luaA_putluaObject (lua_State *L, const TObject *o);
 lua_Object luaA_putObjectOnTop (lua_State *L);

+ 43 - 59
lbuiltin.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbuiltin.c,v 1.106 2000/04/17 19:23:12 roberto Exp roberto $
+** $Id: lbuiltin.c,v 1.107 2000/04/25 16:55:09 roberto Exp roberto $
 ** Built-in functions
 ** See Copyright Notice in lua.h
 */
@@ -52,13 +52,6 @@ void luaB_opentests (lua_State *L);
 */
 
 
-static void pushtagstring (lua_State *L, TString *s) {
-  ttype(L->top) = TAG_STRING;
-  tsvalue(L->top) = s;
-  incr_top;
-}
-
-
 static Number getsize (const Hash *h) {
   Number max = 0;
   int i = h->size;
@@ -191,21 +184,10 @@ void luaB_setglobal (lua_State *L) {
   lua_setglobal(L, name);
 }
 
-void luaB_rawsetglobal (lua_State *L) {
-  const char *name = luaL_check_string(L, 1);
-  lua_Object value = luaL_nonnullarg(L, 2);
-  lua_pushobject(L, value);
-  lua_rawsetglobal(L, name);
-}
-
 void luaB_getglobal (lua_State *L) {
   lua_pushobject(L, lua_getglobal(L, luaL_check_string(L, 1)));
 }
 
-void luaB_rawgetglobal (lua_State *L) {
-  lua_pushobject(L, lua_rawgetglobal(L, luaL_check_string(L, 1)));
-}
-
 void luaB_tag (lua_State *L) {
   lua_pushnumber(L, lua_tag(L, luaL_nonnullarg(L, 1)));
 }
@@ -226,6 +208,12 @@ void luaB_copytagmethods (lua_State *L) {
                                           luaL_check_int(L, 2)));
 }
 
+void luaB_globals (lua_State *L) {
+  lua_pushglobaltable(L);
+  if (lua_getparam(L, 1) != LUA_NOOBJECT)
+    lua_setglobaltable(L, luaL_tablearg(L, 1));
+}
+
 void luaB_rawgettable (lua_State *L) {
   lua_pushobject(L, luaL_nonnullarg(L, 1));
   lua_pushobject(L, luaL_nonnullarg(L, 2));
@@ -346,20 +334,6 @@ void luaB_call (lua_State *L) {
 }
 
 
-void luaB_nextvar (lua_State *L) {
-  lua_Object o = lua_getparam(L, 1);
-  TString *name;
-  if (o == LUA_NOOBJECT || ttype(o) == TAG_NIL)
-    name = NULL;
-  else {
-    luaL_arg_check(L, ttype(o) == TAG_STRING, 1, "variable name expected");
-    name = tsvalue(o);
-  }
-  if (!luaA_nextvar(L, name))
-    lua_pushnil(L);
-}
-
-
 void luaB_next (lua_State *L) {
   const Hash *a = gettable(L, 1);
   lua_Object k = lua_getparam(L, 2);
@@ -463,28 +437,6 @@ void luaB_foreach (lua_State *L) {
 }
 
 
-void luaB_foreachvar (lua_State *L) {
-  lua_Object f = luaL_functionarg(L, 1);
-  GlobalVar *gv;
-  luaD_checkstack(L, 4);  /* for extra var name, f, var name, and globalval */
-  for (gv = L->rootglobal; gv; gv = gv->next) {
-    if (gv->value.ttype != TAG_NIL) {
-      pushtagstring(L, gv->name);  /* keep (extra) name on stack to avoid GC */
-      *(L->top++) = *f;
-      pushtagstring(L, gv->name);
-      *(L->top++) = gv->value;
-      luaD_call(L, L->top-3, 1);
-      if (ttype(L->top-1) != TAG_NIL) {
-        *(L->top-2) = *(L->top-1);  /* remove extra name */
-        L->top--;
-        return;
-      }
-      L->top-=2;  /* remove result and extra name */
-    }
-  }
-}
-
-
 void luaB_getn (lua_State *L) {
   lua_pushnumber(L, getnarg(L, gettable(L, 1)));
 }
@@ -610,6 +562,39 @@ void luaB_sort (lua_State *L) {
 /* }====================================================== */
 
 
+/*
+** {======================================================
+** Deprecated functions to manipulate global environment:
+** all of them can be simulated through table operations
+** over the global table.
+** =======================================================
+*/
+
+#define num_deprecated	4
+
+static const struct luaL_reg deprecated_global_funcs[num_deprecated] = {
+  {"foreachvar", luaB_foreach},
+  {"nextvar", luaB_next},
+  {"rawgetglobal", luaB_rawgettable},
+  {"rawsetglobal", luaB_rawsettable}
+};
+
+
+
+static void deprecated_funcs (lua_State *L) {
+  TObject gt;
+  int i;
+  ttype(&gt) = TAG_TABLE;
+  avalue(&gt) = L->gt;
+  for (i=0; i<num_deprecated; i++) {
+    lua_pushobject(L, &gt);
+    lua_pushcclosure(L, deprecated_global_funcs[i].func, 1);
+    lua_setglobal(L, deprecated_global_funcs[i].name);
+  }
+}
+
+/* }====================================================== */
+
 static const struct luaL_reg builtin_funcs[] = {
   {"_ALERT", luaB__ALERT},
   {"_ERRORMESSAGE", luaB__ERRORMESSAGE},
@@ -621,13 +606,11 @@ static const struct luaL_reg builtin_funcs[] = {
   {"error", luaB_error},
   {"getglobal", luaB_getglobal},
   {"gettagmethod", luaB_gettagmethod},
+  {"globals", luaB_globals},
   {"newtag", luaB_newtag},
   {"next", luaB_next},
-  {"nextvar", luaB_nextvar},
   {"print", luaB_print},
-  {"rawgetglobal", luaB_rawgetglobal},
   {"rawgettable", luaB_rawgettable},
-  {"rawsetglobal", luaB_rawsetglobal},
   {"rawsettable", luaB_rawsettable},
   {"setglobal", luaB_setglobal},
   {"settag", luaB_settag},
@@ -640,7 +623,6 @@ static const struct luaL_reg builtin_funcs[] = {
   {"assert", luaB_assert},
   {"foreach", luaB_foreach},
   {"foreachi", luaB_foreachi},
-  {"foreachvar", luaB_foreachvar},
   {"getn", luaB_getn},
   {"sort", luaB_sort},
   {"tinsert", luaB_tinsert},
@@ -648,6 +630,7 @@ static const struct luaL_reg builtin_funcs[] = {
 };
 
 
+
 void luaB_predefine (lua_State *L) {
   /* pre-register mem error messages, to avoid loop when error arises */
   luaS_newfixed(L, tableEM);
@@ -658,5 +641,6 @@ void luaB_predefine (lua_State *L) {
 #endif
   lua_pushstring(L, LUA_VERSION);
   lua_setglobal(L, "_VERSION");
+  deprecated_funcs(L);
 }
 

+ 2 - 5
lbuiltin.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lbuiltin.h,v 1.6 2000/03/03 14:58:26 roberto Exp roberto $
+** $Id: lbuiltin.h,v 1.7 2000/04/17 19:23:12 roberto Exp roberto $
 ** Built-in functions
 ** See Copyright Notice in lua.h
 */
@@ -20,17 +20,14 @@ void luaB_dostring (lua_State *L);
 void luaB_error (lua_State *L);
 void luaB_foreach (lua_State *L);
 void luaB_foreachi (lua_State *L);
-void luaB_foreachvar (lua_State *L);
 void luaB_getglobal (lua_State *L);
 void luaB_getn (lua_State *L);
 void luaB_gettagmethod (lua_State *L);
+void luaB_globals (lua_State *L);
 void luaB_newtag (lua_State *L);
 void luaB_next (lua_State *L);
-void luaB_nextvar (lua_State *L);
 void luaB_print (lua_State *L);
-void luaB_rawgetglobal (lua_State *L);
 void luaB_rawgettable (lua_State *L);
-void luaB_rawsetglobal (lua_State *L);
 void luaB_rawsettable (lua_State *L);
 void luaB_setglobal (lua_State *L);
 void luaB_settag (lua_State *L);

+ 1 - 9
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.27 2000/04/17 14:05:34 roberto Exp roberto $
+** $Id: lcode.c,v 1.28 2000/04/19 13:41:37 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -16,7 +16,6 @@
 #include "lobject.h"
 #include "lopcodes.h"
 #include "lparser.h"
-#include "lstring.h"
 
 
 void luaK_error (LexState *ls, const char *msg) {
@@ -148,11 +147,6 @@ void luaK_setcallreturns (FuncState *fs, int nresults) {
 }
 
 
-static void assertglobal (FuncState *fs, int index) {
-  luaS_assertglobal(fs->L, fs->f->kstr[index]);
-}
-
-
 static int discharge (FuncState *fs, expdesc *var) {
   switch (var->k) {
     case VLOCAL:
@@ -160,7 +154,6 @@ static int discharge (FuncState *fs, expdesc *var) {
       break;
     case VGLOBAL:
       luaK_code1(fs, OP_GETGLOBAL, var->u.index);
-      assertglobal(fs, var->u.index);  /* make sure that there is a global */
       break;
     case VINDEXED:
       luaK_code0(fs, OP_GETTABLE);
@@ -190,7 +183,6 @@ void luaK_storevar (LexState *ls, const expdesc *var) {
       break;
     case VGLOBAL:
       luaK_code1(fs, OP_SETGLOBAL, var->u.index);
-      assertglobal(fs, var->u.index);  /* make sure that there is a global */
       break;
     case VINDEXED:  /* table is at top-3; pop 3 elements after operation */
       luaK_code2(fs, OP_SETTABLE, 3, 3);

+ 6 - 5
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 1.15 2000/03/30 17:19:48 roberto Exp roberto $
+** $Id: ldebug.c,v 1.16 2000/03/30 20:55:50 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -159,12 +159,13 @@ static int checkfunc (lua_State *L, TObject *o) {
 
 
 static void lua_getobjname (lua_State *L, StkId f, lua_Debug *ar) {
-  GlobalVar *g;
+  Hash *g = L->gt;
+  int i;
   /* try to find a name for given function */
   setnormalized(L->top, f); /* to be used by `checkfunc' */
-  for (g=L->rootglobal; g; g=g->next) {
-    if (checkfunc(L, &g->value)) {
-      ar->name = g->name->str;
+  for (i=0; i<=g->size; i++) {
+    if (checkfunc(L, val(node(g,i))) && ttype(key(node(g,i))) == TAG_STRING) {
+      ar->name = tsvalue(key(node(g,i)))->str;
       ar->namewhat = "global";
       return;
     }

+ 3 - 2
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.72 2000/03/30 20:55:50 roberto Exp roberto $
+** $Id: ldo.c,v 1.73 2000/04/14 18:12:35 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -21,6 +21,7 @@
 #include "lparser.h"
 #include "lstate.h"
 #include "lstring.h"
+#include "ltable.h"
 #include "ltm.h"
 #include "lua.h"
 #include "luadebug.h"
@@ -222,7 +223,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
 
 
 static void message (lua_State *L, const char *s) {
-  const TObject *em = &(luaS_assertglobalbyname(L, "_ERRORMESSAGE")->value);
+  const TObject *em = luaH_getglobal(L, "_ERRORMESSAGE");
   if (*luaO_typename(em) == 'f') {
     *L->top = *em;
     incr_top;

+ 2 - 29
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.46 2000/03/30 20:55:50 roberto Exp roberto $
+** $Id: lgc.c,v 1.47 2000/04/14 18:12:35 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -77,18 +77,6 @@ static void hashmark (lua_State *L, Hash *h) {
 }
 
 
-static void travglobal (lua_State *L) {
-  GlobalVar *gv;
-  for (gv=L->rootglobal; gv; gv=gv->next) {
-    LUA_ASSERT(L, gv->name->u.s.gv == gv, "inconsistent global name");
-    if (gv->value.ttype != TAG_NIL) {
-      strmark(L, gv->name);  /* cannot collect non nil global variables */
-      markobject(L, &gv->value);
-    }
-  }
-}
-
-
 static void travstack (lua_State *L) {
   int i;
   for (i = (L->top-1)-L->stack; i>=0; i--)
@@ -173,20 +161,6 @@ static void collecttable (lua_State *L) {
 }
 
 
-/*
-** remove from the global list globals whose names will be collected
-** (the global itself is freed when its name is freed)
-*/
-static void clear_global_list (lua_State *L, int limit) {
-  GlobalVar **p = &L->rootglobal;
-  GlobalVar *next;
-  while ((next = *p) != NULL) {
-    if (next->name->marked >= limit) p = &next->next;
-    else *p = next->next;
-  }
-}
-
-
 /*
 ** collect all elements with `marked' < `limit'.
 ** with limit=1, that means all unmarked elements;
@@ -196,7 +170,6 @@ static void collectstring (lua_State *L, int limit) {
   TObject o;  /* to call userdata `gc' tag method */
   int i;
   ttype(&o) = TAG_USERDATA;
-  clear_global_list(L, limit);
   for (i=0; i<NUM_HASHS; i++) {  /* for each hash table */
     stringtable *tb = &L->string_root[i];
     int j;
@@ -228,7 +201,7 @@ static void collectstring (lua_State *L, int limit) {
 
 static void markall (lua_State *L) {
   travstack(L); /* mark stack objects */
-  travglobal(L);  /* mark global variable values and names */
+  hashmark(L, L->gt);  /* mark global variable values and names */
   travlock(L); /* mark locked objects */
   luaT_travtagmethods(L, markobject);  /* mark tag methods */
 }

+ 9 - 2
llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 1.56 2000/04/07 13:11:49 roberto Exp roberto $
+** $Id: llex.c,v 1.57 2000/04/12 18:57:19 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -18,6 +18,7 @@
 #include "lparser.h"
 #include "lstate.h"
 #include "lstring.h"
+#include "ltable.h"
 #include "luadebug.h"
 #include "lzio.h"
 
@@ -121,12 +122,18 @@ static void skipspace (LexState *LS) {
 }
 
 
+static int globaldefined (lua_State *L, const char *name) {
+  const TObject *value = luaH_getglobal(L, name);
+  return ttype(value) != TAG_NIL;
+}
+
+
 static int checkcond (lua_State *L, LexState *LS, const char *buff) {
   static const char *const opts[] = {"nil", "1", NULL};
   int i = luaL_findstring(buff, opts);
   if (i >= 0) return i;
   else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
-    return luaS_globaldefined(L, buff);
+    return globaldefined(L, buff);
   else {
     luaX_syntaxerror(LS, "invalid $if condition", buff);
     return 0;  /* to avoid warnings */

+ 2 - 10
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.60 2000/04/10 19:20:24 roberto Exp roberto $
+** $Id: lobject.h,v 1.61 2000/04/25 16:55:09 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -85,20 +85,13 @@ typedef struct TObject {
 } TObject;
 
 
-typedef struct GlobalVar {
-  TObject value;
-  struct GlobalVar *next;
-  struct TString *name;
-} GlobalVar;
-
-
 /*
 ** String headers for string table
 */
 typedef struct TString {
   union {
     struct {  /* for strings */
-      GlobalVar *gv;  /* eventual global value with this name */
+      unsigned long hash;
       long len;
     } s;
     struct {  /* for userdata */
@@ -107,7 +100,6 @@ typedef struct TString {
     } d;
   } u;
   struct TString *nexthash;  /* chain for hash table */
-  unsigned long hash;
   int constindex;  /* hint to reuse constants (= -1 if this is a userdata) */
   unsigned char marked;
   char str[1];   /* variable length string!! must be the last field! */

+ 3 - 3
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.24 2000/01/13 16:30:47 roberto Exp roberto $
+** $Id: lstate.c,v 1.25 2000/03/31 16:28:45 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -18,6 +18,7 @@
 #include "lref.h"
 #include "lstate.h"
 #include "lstring.h"
+#include "ltable.h"
 #include "ltm.h"
 
 
@@ -35,7 +36,6 @@ static lua_State *newstate_aux (int stacksize, int put_builtin) {
   L->numCblocks = 0;
   L->rootproto = NULL;
   L->rootcl = NULL;
-  L->rootglobal = NULL;
   L->roottable = NULL;
   L->IMtable = NULL;
   L->refArray = NULL;
@@ -47,6 +47,7 @@ static lua_State *newstate_aux (int stacksize, int put_builtin) {
   L->callhook = NULL;
   L->linehook = NULL;
   L->allowhooks = 1;
+  L->gt = luaH_new(L, 10);
   luaD_init(L, stacksize);
   luaS_init(L);
   luaX_init(L);
@@ -87,7 +88,6 @@ void lua_close (lua_State *L) {
   luaC_collect(L, 1);  /* collect all elements */
   LUA_ASSERT(L, L->rootproto == NULL, "list should be empty");
   LUA_ASSERT(L, L->rootcl == NULL, "list should be empty");
-  LUA_ASSERT(L, L->rootglobal == NULL, "list should be empty");
   LUA_ASSERT(L, L->roottable == NULL, "list should be empty");
   luaS_freeall(L);
   luaM_free(L, L->stack);

+ 3 - 3
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.30 2000/03/10 18:37:44 roberto Exp roberto $
+** $Id: lstate.h,v 1.31 2000/03/30 17:19:48 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -42,7 +42,7 @@ struct C_Lua_Stack {
 
 typedef struct stringtable {
   int size;
-  int nuse;  /* number of elements (including EMPTYs) */
+  int nuse;  /* number of elements */
   TString **hash;
 } stringtable;
 
@@ -66,8 +66,8 @@ struct lua_State {
   Proto *rootproto;  /* list of all prototypes */
   Closure *rootcl;  /* list of all closures */
   Hash *roottable;  /* list of all tables */
-  GlobalVar *rootglobal;  /* list of global variables */
   stringtable *string_root;  /* array of hash tables for strings and udata */
+  Hash *gt;  /* table for globals */
   struct IM *IMtable;  /* table for tag methods */
   int last_tag;  /* last used tag in IMtable */
   struct Ref *refArray;  /* locked objects */

+ 17 - 48
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.33 2000/03/10 14:38:10 roberto Exp roberto $
+** $Id: lstring.c,v 1.34 2000/03/10 18:37:44 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -62,11 +62,13 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
     TString *p = tb->hash[i];
     while (p) {  /* for each node in the list */
       TString *next = p->nexthash;  /* save next */
-      int h = p->hash&(newsize-1);  /* new position */
-      LUA_ASSERT(L, p->hash%newsize == (p->hash&(newsize-1)),
+      unsigned long h = (p->constindex == -1) ? IntPoint(p->u.d.value) :
+                                                p->u.s.hash;
+      int h1 = h&(newsize-1);  /* new position */
+      LUA_ASSERT(L, h%newsize == (h&(newsize-1)),
                     "a&(x-1) == a%x, for x power of 2");
-      p->nexthash = newhash[h];  /* chain it in new position */
-      newhash[h] = p;
+      p->nexthash = newhash[h1];  /* chain it in new position */
+      newhash[h1] = p;
       p = next;
     }
   }
@@ -76,32 +78,29 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
 }
 
 
-static TString *newone (lua_State *L, long l, unsigned long h) {
-  TString *ts = (TString *)luaM_malloc(L, 
-                                       sizeof(TString)+l*sizeof(char));
+static TString *newone (lua_State *L, long l) {
+  TString *ts = (TString *)luaM_malloc(L, sizeof(TString)+l*sizeof(char));
   ts->marked = 0;
   ts->nexthash = NULL;
-  ts->hash = h;
   return ts;
 }
 
 
 static TString *newone_s (lua_State *L, const char *str,
                                long l, unsigned long h) {
-  TString *ts = newone(L, l, h);
+  TString *ts = newone(L, l);
   memcpy(ts->str, str, l);
   ts->str[l] = 0;  /* ending 0 */
-  ts->u.s.gv = NULL;  /* no global value */
   ts->u.s.len = l;
+  ts->u.s.hash = h;
   ts->constindex = 0;
   L->nblocks += gcsizestring(L, l);
   return ts;
 }
 
 
-static TString *newone_u (lua_State *L, void *buff,
-                               int tag, unsigned long h) {
-  TString *ts = newone(L, 0, h);
+static TString *newone_u (lua_State *L, void *buff, int tag) {
+  TString *ts = newone(L, 0);
   ts->u.d.value = buff;
   ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
   ts->constindex = -1;  /* tag -> this is a userdata */
@@ -141,7 +140,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, long l) {
 ** so two '&' operations would be highly correlated
 */
 TString *luaS_createudata (lua_State *L, void *udata, int tag) {
-  unsigned long h = IntPoint(L, udata);
+  unsigned long h = IntPoint(udata);
   stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR];
   int h1 = h&(tb->size-1);
   TString *ts;
@@ -150,7 +149,7 @@ TString *luaS_createudata (lua_State *L, void *udata, int tag) {
       return ts;
   }
   /* not found */
-  ts = newone_u(L, udata, tag, h);
+  ts = newone_u(L, udata, tag);
   newentry(L, tb, ts, h1);
   return ts;
 }
@@ -168,38 +167,8 @@ TString *luaS_newfixed (lua_State *L, const char *str) {
 
 
 void luaS_free (lua_State *L, TString *t) {
-  if (t->constindex == -1)  /* is userdata? */
-    L->nblocks -= gcsizeudata;
-  else {  /* is string */
-    L->nblocks -= gcsizestring(L, t->u.s.len);
-    luaM_free(L, t->u.s.gv);
-  }
+  L->nblocks -= (t->constindex == -1) ? gcsizeudata :
+                                        gcsizestring(L, t->u.s.len);
   luaM_free(L, t);
 }
 
-
-GlobalVar *luaS_assertglobal (lua_State *L, TString *ts) {
-  GlobalVar *gv = ts->u.s.gv;
-  if (!gv) {  /* no global value yet? */
-    gv = luaM_new(L, GlobalVar);
-    gv->value.ttype = TAG_NIL;  /* initial value */
-    gv->name = ts;
-    gv->next = L->rootglobal;  /* chain in global list */
-    L->rootglobal = gv; 
-    ts->u.s.gv = gv;
-  }
-  return gv;
-}
-
-
-GlobalVar *luaS_assertglobalbyname (lua_State *L, const char *name) {
-  return luaS_assertglobal(L, luaS_new(L, name));
-}
-
-
-int luaS_globaldefined (lua_State *L, const char *name) {
-  TString *ts = luaS_new(L, name);
-  return ts->u.s.gv && ts->u.s.gv->value.ttype != TAG_NIL;
-}
-
-

+ 2 - 5
lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.17 2000/03/10 14:38:10 roberto Exp roberto $
+** $Id: lstring.h,v 1.18 2000/03/10 18:37:44 roberto Exp roberto $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -18,7 +18,7 @@
 
 
 /*
-** any taggedstring with mark>=FIXMARK is never collected.
+** any TString with mark>=FIXMARK is never collected.
 ** Marks>=RESERVEDMARK are used to identify reserved words.
 */
 #define FIXMARK		2
@@ -33,9 +33,6 @@ void luaS_free (lua_State *L, TString *ts);
 TString *luaS_newlstr (lua_State *L, const char *str, long l);
 TString *luaS_new (lua_State *L, const char *str);
 TString *luaS_newfixed (lua_State *L, const char *str);
-GlobalVar *luaS_assertglobal (lua_State *L, TString *ts);
-GlobalVar *luaS_assertglobalbyname (lua_State *L, const char *name);
-int luaS_globaldefined (lua_State *L, const char *name);
 
 
 #endif

+ 15 - 7
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.39 2000/03/31 16:28:45 roberto Exp roberto $
+** $Id: ltable.c,v 1.40 2000/04/25 16:55:09 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -24,6 +24,7 @@
 #include "lmem.h"
 #include "lobject.h"
 #include "lstate.h"
+#include "lstring.h"
 #include "ltable.h"
 #include "lua.h"
 
@@ -46,14 +47,17 @@ Node *luaH_mainposition (const Hash *t, const TObject *key) {
     case TAG_NUMBER:
       h = (unsigned long)(long)nvalue(key);
       break;
-    case TAG_STRING: case TAG_USERDATA:
-      h = tsvalue(key)->hash;
+    case TAG_STRING:
+      h = tsvalue(key)->u.s.hash;
+      break;
+    case TAG_USERDATA:
+      h = IntPoint(tsvalue(key));
       break;
     case TAG_TABLE:
-      h = IntPoint(L, avalue(key));
+      h = IntPoint(avalue(key));
       break;
     case TAG_LCLOSURE:  case TAG_CCLOSURE:
-      h = IntPoint(L, clvalue(key));
+      h = IntPoint(clvalue(key));
       break;
     default:
       return NULL;  /* invalid key */
@@ -91,8 +95,8 @@ const TObject *luaH_getnum (const Hash *t, Number key) {
 
 
 /* specialized version for strings */
-static const TObject *luaH_getstr (const Hash *t, TString *key) {
-  Node *n = &t->node[key->hash&(t->size-1)];
+const TObject *luaH_getstr (const Hash *t, TString *key) {
+  Node *n = &t->node[key->u.s.hash&(t->size-1)];
   do {
     if (ttype(&n->key) == TAG_STRING && tsvalue(&n->key) == key)
       return &n->val;
@@ -248,3 +252,7 @@ void luaH_setint (lua_State *L, Hash *t, int key, const TObject *val) {
   luaH_set(L, t, &index, val);
 }
 
+
+const TObject *luaH_getglobal (lua_State *L, const char *name) {
+  return luaH_getstr(L->gt, luaS_new(L, name));
+}

+ 4 - 2
ltable.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 1.18 1999/12/07 12:05:34 roberto Exp roberto $
+** $Id: ltable.h,v 1.19 2000/04/25 16:55:09 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -19,11 +19,13 @@
 Hash *luaH_new (lua_State *L, int nhash);
 void luaH_free (lua_State *L, Hash *t);
 const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key);
+const TObject *luaH_getnum (const Hash *t, Number key);
+const TObject *luaH_getstr (const Hash *t, TString *key);
 void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val);
 int luaH_pos (lua_State *L, const Hash *t, const TObject *r);
 void luaH_setint (lua_State *L, Hash *t, int key, const TObject *val);
-const TObject *luaH_getnum (const Hash *t, Number key);
 unsigned long luaH_hash (lua_State *L, const TObject *key);
+const TObject *luaH_getglobal (lua_State *L, const char *name);
 
 /* exported only for debugging */
 Node *luaH_mainposition (const Hash *t, const TObject *key);

+ 2 - 5
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.15 2000/04/13 16:51:01 roberto Exp roberto $
+** $Id: ltests.c,v 1.16 2000/04/14 17:46:15 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -167,7 +167,7 @@ static void hash_query (lua_State *L) {
   lua_Object o = luaL_nonnullarg(L, 1);
   if (lua_getparam(L, 2) == LUA_NOOBJECT) {
     luaL_arg_check(L, ttype(o) == TAG_STRING, 1, "string expected");
-    lua_pushnumber(L, tsvalue(o)->hash);
+    lua_pushnumber(L, tsvalue(o)->u.s.hash);
   }
   else {
     const Hash *t = avalue(luaL_tablearg(L, 2));
@@ -334,9 +334,6 @@ static void testC (lua_State *L) {
     else if EQ("type") {
       lua_pushstring(L, lua_type(L, reg[getreg(L, &pc)]));
     }
-    else if EQ("nextvar") {
-      lua_pushstring(L, lua_nextvar(L, lua_getstring(L, reg[getreg(L, &pc)])));
-    }
     else if EQ("next") {
       int n = getreg(L, &pc);
       n = lua_next(L, reg[n], (int)lua_getnumber(L, reg[getreg(L, &pc)]));

+ 8 - 5
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.47 2000/04/14 17:48:20 roberto Exp roberto $
+** $Id: lua.h,v 1.48 2000/04/17 19:23:12 roberto Exp roberto $
 ** Lua - An Extensible Extension Language
 ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
 ** e-mail: [email protected]
@@ -54,6 +54,9 @@ int            lua_callfunction (lua_State *L, lua_Object f);
 void	       lua_beginblock (lua_State *L);
 void	       lua_endblock (lua_State *L);
 
+void           lua_pushglobaltable (lua_State *L);
+void           lua_setglobaltable (lua_State *L, lua_Object newtable);
+
 lua_Object     lua_lua2C (lua_State *L, int number);
 #define	       lua_getparam		lua_lua2C
 #define	       lua_getresult		lua_lua2C
@@ -88,8 +91,8 @@ void           lua_pushobject (lua_State *L, lua_Object obj);
 lua_Object     lua_pop (lua_State *L);
 
 lua_Object     lua_getglobal (lua_State *L, const char *name);
-lua_Object     lua_rawgetglobal (lua_State *L, const char *name);
 void           lua_setglobal (lua_State *L, const char *name); /* In: value */
+lua_Object     lua_rawgetglobal (lua_State *L, const char *name);
 void           lua_rawsetglobal (lua_State *L, const char *name);/* In: value */
 
 void           lua_settable (lua_State *L); /* In: table, index, value */
@@ -99,7 +102,6 @@ lua_Object     lua_rawgettable (lua_State *L); /* In: table, index */
 
 int            lua_tag (lua_State *L, lua_Object obj);
 
-const char    *lua_nextvar (lua_State *L, const char *varname); /* Out: value */
 int            lua_next (lua_State *L, lua_Object o, int i);
 						/* Out: ref, value */ 
 
@@ -167,6 +169,8 @@ extern lua_State *lua_state;
 #define lua_callfunction(f)	(lua_callfunction)(lua_state, f)
 #define lua_beginblock()	(lua_beginblock)(lua_state)
 #define lua_endblock()		(lua_endblock)(lua_state)
+#define lua_pushglobaltable()	(lua_pushglobaltable)(lua_state)
+#define lua_setglobaltable(t)	(lua_setglobaltable)(lua_state, t)
 #define lua_lua2C(number)	(lua_lua2C)(lua_state, number)
 #define lua_type(obj)		(lua_type)(lua_state, obj)
 #define lua_isnil(obj)		(lua_isnil)(lua_state, obj)
@@ -190,15 +194,14 @@ extern lua_State *lua_state;
 #define lua_pushobject(obj)	(lua_pushobject)(lua_state, obj)
 #define lua_pop()		(lua_pop)(lua_state)
 #define lua_getglobal(name)	(lua_getglobal)(lua_state, name)
-#define lua_rawgetglobal(name)	(lua_rawgetglobal)(lua_state, name)
 #define lua_setglobal(name)	(lua_setglobal)(lua_state, name)
+#define lua_rawgetglobal(name)	(lua_rawgetglobal)(lua_state, name)
 #define lua_rawsetglobal(name)	(lua_rawsetglobal)(lua_state, name)
 #define lua_settable()		(lua_settable)(lua_state)
 #define lua_rawsettable()	(lua_rawsettable)(lua_state)
 #define lua_gettable()		(lua_gettable)(lua_state)
 #define lua_rawgettable()	(lua_rawgettable)(lua_state)
 #define lua_tag(obj)		(lua_tag)(lua_state, obj)
-#define lua_nextvar(varname)	(lua_nextvar)(lua_state, varname)
 #define lua_next(o,i)		(lua_next)(lua_state, o,i)
 #define lua_ref(lock)		(lua_ref)(lua_state, lock)
 #define lua_getref(ref)		(lua_getref)(lua_state, ref)

+ 2 - 3
lundump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 1.28 2000/04/24 19:32:58 lhf Exp $
+** $Id: lundump.c,v 1.20 2000/04/25 16:44:31 roberto Exp roberto $
 ** load bytecodes from files
 ** See Copyright Notice in lua.h
 */
@@ -155,8 +155,7 @@ static void LoadConstants (lua_State* L, Proto* tf, ZIO* Z, int native)
   for (i=0; i<n; i++)
   {
    TString* s=LoadString(L,Z);
-   int isglobal=LoadByte(L,Z);
-   if (isglobal) luaS_assertglobal(L,s);
+   LoadByte(L,Z);
    tf->kstr[i]=s;
   }
  }

+ 19 - 21
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.103 2000/04/14 17:45:25 roberto Exp roberto $
+** $Id: lvm.c,v 1.104 2000/04/19 13:36:25 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -164,18 +164,8 @@ void luaV_settable (lua_State *L, StkId t, StkId top) {
 }
 
 
-void luaV_rawsettable (lua_State *L, StkId t) {
-  if (ttype(t) != TAG_TABLE)
-    lua_error(L, "indexed expression not a table");
-  else {
-    luaH_set(L, avalue(t), t+1, L->top-1);
-    L->top -= 3;
-  }
-}
-
-
-void luaV_getglobal (lua_State *L, GlobalVar *gv, StkId top) {
-  const TObject *value = &gv->value;
+void luaV_getglobal (lua_State *L, TString *s, StkId top) {
+  const TObject *value = luaH_getstr(L->gt, s);
   TObject *im = luaT_getimbyObj(L, value, IM_GETGLOBAL);
   if (ttype(im) == TAG_NIL)  /* is there a tag method? */
     *top = *value;  /* default behavior */
@@ -183,7 +173,7 @@ void luaV_getglobal (lua_State *L, GlobalVar *gv, StkId top) {
     luaD_checkstack(L, 3);
     *top = *im;
     ttype(top+1) = TAG_STRING;
-    tsvalue(top+1) = gv->name;  /* global name */
+    tsvalue(top+1) = s;  /* global name */
     *(top+2) = *value;
     L->top = top+3;
     luaD_call(L, top, 1);
@@ -191,17 +181,25 @@ void luaV_getglobal (lua_State *L, GlobalVar *gv, StkId top) {
 }
 
 
-void luaV_setglobal (lua_State *L, GlobalVar *gv, StkId top) {
-  const TObject *oldvalue = &gv->value;
+void luaV_setglobal (lua_State *L, TString *s, StkId top) {
+  const TObject *oldvalue = luaH_getstr(L->gt, s);
   const TObject *im = luaT_getimbyObj(L, oldvalue, IM_SETGLOBAL);
-  if (ttype(im) == TAG_NIL)  /* is there a tag method? */
-    gv->value = *(top-1);
+  if (ttype(im) == TAG_NIL) {  /* is there a tag method? */
+    if (oldvalue != &luaO_nilobject)
+      *oldvalue = *(top-1);
+    else {
+      TObject key;
+      ttype(&key) = TAG_STRING;
+      tsvalue(&key) = s;
+      luaH_set(L, L->gt, &key, top-1);
+    }
+  }
   else {
     luaD_checkstack(L, 3);
     *(top+2) = *(top-1);  /* new value */
     *(top+1) = *oldvalue;
     ttype(top) = TAG_STRING;
-    tsvalue(top) = gv->name;
+    tsvalue(top) = s;
     *(top-1) = *im;
     L->top = top+3;
     luaD_call(L, top-1, 0);
@@ -415,7 +413,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         break;
 
       case OP_GETGLOBAL:
-        luaV_getglobal(L, kstr[GETARG_U(i)]->u.s.gv, top);
+        luaV_getglobal(L, kstr[GETARG_U(i)], top);
         top++;
         break;
 
@@ -460,7 +458,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         break;
 
       case OP_SETGLOBAL:
-        luaV_setglobal(L, kstr[GETARG_U(i)]->u.s.gv, top);
+        luaV_setglobal(L, kstr[GETARG_U(i)], top);
         top--;
         break;
 

+ 3 - 4
lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 1.20 2000/03/29 20:19:20 roberto Exp roberto $
+** $Id: lvm.h,v 1.21 2000/04/19 13:36:25 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -23,9 +23,8 @@ int luaV_tostring (lua_State *L, TObject *obj);
 void luaV_setn (lua_State *L, Hash *t, int val);
 void luaV_gettable (lua_State *L, StkId top);
 void luaV_settable (lua_State *L, StkId t, StkId top);
-void luaV_rawsettable (lua_State *L, StkId t);
-void luaV_getglobal (lua_State *L, GlobalVar *gv, StkId top);
-void luaV_setglobal (lua_State *L, GlobalVar *gv, StkId top);
+void luaV_getglobal (lua_State *L, TString *s, StkId top);
+void luaV_setglobal (lua_State *L, TString *s, StkId top);
 StkId luaV_execute (lua_State *L, const Closure *cl, StkId base);
 void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems);
 void luaV_Lclosure (lua_State *L, Proto *l, int nelems);