2
0
Эх сурвалжийг харах

new implementation for global variable values (separated from strings)

Roberto Ierusalimschy 26 жил өмнө
parent
commit
cde179b369
12 өөрчлөгдсөн 166 нэмэгдсэн , 145 устгасан
  1. 28 39
      lapi.c
  2. 2 4
      lapi.h
  3. 35 26
      lbuiltin.c
  4. 2 3
      ldo.c
  5. 18 15
      lgc.c
  6. 16 11
      lobject.h
  7. 10 1
      lparser.c
  8. 2 2
      lstate.h
  9. 37 29
      lstring.c
  10. 3 2
      lstring.h
  11. 10 10
      lvm.c
  12. 3 3
      lvm.h

+ 28 - 39
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.53 1999/10/11 16:13:11 roberto Exp roberto $
+** $Id: lapi.c,v 1.54 1999/10/14 19:13:31 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -60,18 +60,6 @@ static const TObject *luaA_protovalue (const TObject *o) {
 }
 
 
-void luaA_packresults (void) {
-  luaV_pack(L->Cstack.lua2C, L->Cstack.num, L->stack.top);
-  incr_top;
-}
-
-
-int luaA_passresults (void) {
-  L->Cstack.base = L->Cstack.lua2C;  /* position of first result */
-  return L->Cstack.num;
-}
-
-
 static void checkCparams (int nParams) {
   if (L->stack.top-L->stack.stack < L->Cstack.base+nParams)
     lua_error("API error - wrong number of arguments in C2lua stack");
@@ -191,28 +179,28 @@ lua_Object lua_createtable (void) {
 
 lua_Object lua_getglobal (const char *name) {
   luaD_checkstack(2);  /* may need that to call T.M. */
-  luaV_getglobal(luaS_new(name));
+  luaV_getglobal(luaS_assertglobalbyname(name));
   return luaA_putObjectOnTop();
 }
 
 
 lua_Object lua_rawgetglobal (const char *name) {
-  TaggedString *ts = luaS_new(name);
-  return put_luaObject(&ts->u.s.globalval);
+  GlobalVar *gv = luaS_assertglobalbyname(name);
+  return put_luaObject(&gv->value);
 }
 
 
 void lua_setglobal (const char *name) {
   checkCparams(1);
   luaD_checkstack(2);  /* may need that to call T.M. */
-  luaV_setglobal(luaS_new(name));
+  luaV_setglobal(luaS_assertglobalbyname(name));
 }
 
 
 void lua_rawsetglobal (const char *name) {
-  TaggedString *ts = luaS_new(name);
+  GlobalVar *gv = luaS_assertglobalbyname(name);
   checkCparams(1);
-  luaS_rawsetglobal(ts, --L->stack.top);
+  gv->value = *(--L->stack.top);
 }
 
 
@@ -274,7 +262,7 @@ long lua_strlen (lua_Object object) {
 void *lua_getuserdata (lua_Object object) {
   if (object == LUA_NOOBJECT || ttype(Address(object)) != LUA_T_USERDATA)
     return NULL;
-  else return tsvalue(Address(object))->u.d.v;
+  else return tsvalue(Address(object))->u.d.value;
 }
 
 lua_CFunction lua_getcfunction (lua_Object object) {
@@ -388,31 +376,32 @@ void lua_settag (int tag) {
 }
 
 
-TaggedString *luaA_nextvar (TaggedString *g) {
-  if (g == NULL)
-    g = L->rootglobal;  /* first variable */
+GlobalVar *luaA_nextvar (TaggedString *ts) {
+  GlobalVar *gv;
+  if (ts == NULL)
+    gv = L->rootglobal;  /* first variable */
   else {
     /* check whether name is in global var list */
-    luaL_arg_check(g != g->nextglobal, 1, "variable name expected");
-    g = g->nextglobal;  /* get next */
+    luaL_arg_check(ts->u.s.gv, 1, "variable name expected");
+    gv = ts->u.s.gv->next;  /* get next */
   }
-  while (g && g->u.s.globalval.ttype == LUA_T_NIL)  /* skip globals with nil */
-    g = g->nextglobal;
-  if (g) {
-    ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = g;
+  while (gv && gv->value.ttype == LUA_T_NIL)  /* skip globals with nil */
+    gv = gv->next;
+  if (gv) {
+    ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = gv->name;
     incr_top;
-    luaA_pushobject(&g->u.s.globalval);
+    luaA_pushobject(&gv->value);
   }
-  return g;
+  return gv;
 }
 
 
 const char *lua_nextvar (const char *varname) {
-  TaggedString *g = (varname == NULL) ? NULL : luaS_new(varname);
-  g = luaA_nextvar(g);
-  if (g) {
+  TaggedString *ts = (varname == NULL) ? NULL : luaS_new(varname);
+  GlobalVar *gv = luaA_nextvar(ts);
+  if (gv) {
     top2LC(2);
-    return g->str;
+    return gv->name->str;
   }
   else {
     top2LC(0);
@@ -577,11 +566,11 @@ static int checkfunc (TObject *o) {
 
 const char *lua_getobjname (lua_Object o, const char **name) {
   /* try to find a name for given function */
-  TaggedString *g;
+  GlobalVar *g;
   set_normalized(L->stack.top, Address(o)); /* to be accessed by "checkfunc" */
-  for (g=L->rootglobal; g; g=g->nextglobal) {
-    if (checkfunc(&g->u.s.globalval)) {
-      *name = g->str;
+  for (g=L->rootglobal; g; g=g->next) {
+    if (checkfunc(&g->value)) {
+      *name = g->name->str;
       return "global";
     }
   }

+ 2 - 4
lapi.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.h,v 1.6 1999/09/20 14:57:29 roberto Exp roberto $
+** $Id: lapi.h,v 1.7 1999/09/21 16:10:13 roberto Exp roberto $
 ** Auxiliary functions from Lua API
 ** See Copyright Notice in lua.h
 */
@@ -14,9 +14,7 @@
 
 TObject *luaA_Address (lua_Object o);
 void luaA_pushobject (const TObject *o);
-void luaA_packresults (void);
-int luaA_passresults (void);
-TaggedString *luaA_nextvar (TaggedString *g);
+GlobalVar *luaA_nextvar (TaggedString *g);
 int luaA_next (const Hash *t, int i);
 lua_Object luaA_putObjectOnTop (void);
 

+ 35 - 26
lbuiltin.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbuiltin.c,v 1.68 1999/10/19 13:33:22 roberto Exp roberto $
+** $Id: lbuiltin.c,v 1.69 1999/10/26 10:53:40 roberto Exp roberto $
 ** Built-in functions
 ** See Copyright Notice in lua.h
 */
@@ -35,10 +35,9 @@
 
 
 static void pushtagstring (TaggedString *s) {
-  TObject o;
-  o.ttype = LUA_T_STRING;
-  o.value.ts = s;
-  luaA_pushobject(&o);
+  ttype(L->stack.top) = LUA_T_STRING;
+  tsvalue(L->stack.top) = s;
+  incr_top;
 }
 
 
@@ -107,7 +106,7 @@ static void error_message (void) {
 
 
 /*
-** If your system does not support "stdout", just remove this function.
+** If your system does not support "stdout", you can just remove this function.
 ** If you need, you can define your own "print" function, following this
 ** model but changing "fputs" to put the strings at a proper place
 ** (a console window or a log file, for instance).
@@ -264,22 +263,29 @@ static void luaB_type (void) {
 ** =======================================================
 */
 
+
+static void passresults (void) {
+  L->Cstack.base = L->Cstack.lua2C;  /* position of first result */
+  if (L->Cstack.num == 0)
+    lua_pushuserdata(NULL);  /* at least one result to signal no errors */
+}
+
 static void luaB_dostring (void) {
   long l;
   const char *s = luaL_check_lstr(1, &l);
   if (*s == ID_CHUNK)
     lua_error("`dostring' cannot run pre-compiled code");
   if (lua_dobuffer(s, l, luaL_opt_string(2, s)) == 0)
-    if (luaA_passresults() == 0)
-      lua_pushuserdata(NULL);  /* at least one result to signal no errors */
+    passresults();
+  /* else return no value */
 }
 
 
 static void luaB_dofile (void) {
   const char *fname = luaL_opt_string(1, NULL);
   if (lua_dofile(fname) == 0)
-    if (luaA_passresults() == 0)
-      lua_pushuserdata(NULL);  /* at least one result to signal no errors */
+    passresults();
+  /* else return no value */
 }
 
 
@@ -312,10 +318,12 @@ static void luaB_call (void) {
       lua_error(NULL);
   }
   else {  /* no errors */
-    if (strchr(options, 'p'))
-      luaA_packresults();
+    if (strchr(options, 'p')) {  /* pack results? */
+      luaV_pack(L->Cstack.lua2C, L->Cstack.num, L->stack.top);
+      incr_top;
+    }
     else
-      luaA_passresults();
+      L->Cstack.base = L->Cstack.lua2C;  /* position of first result */
   }
 }
 
@@ -373,7 +381,7 @@ static void luaB_tostring (void) {
       sprintf(buff, "function: %p", (void *)o->value.f);
       break;
     case LUA_T_USERDATA:
-      sprintf(buff, "userdata: %p", o->value.ts->u.d.v);
+      sprintf(buff, "userdata: %p", o->value.ts->u.d.value);
       break;
     case LUA_T_NIL:
       lua_pushstring("nil");
@@ -449,23 +457,23 @@ static void luaB_foreach (void) {
 
 
 static void luaB_foreachvar (void) {
-  TaggedString *s;
+  GlobalVar *gv;
   TObject f;  /* see comment in 'foreachi' */
   f = *luaA_Address(luaL_functionarg(1));
   luaD_checkstack(4);  /* for extra var name, f, var name, and globalval */
-  for (s = L->rootglobal; s; s = s->nextglobal) {
-    if (s->u.s.globalval.ttype != LUA_T_NIL) {
-      pushtagstring(s);  /* keep (extra) s on stack to avoid GC */
+  for (gv = L->rootglobal; gv; gv = gv->next) {
+    if (gv->value.ttype != LUA_T_NIL) {
+      pushtagstring(gv->name);  /* keep (extra) name on stack to avoid GC */
       *(L->stack.top++) = f;
-      pushtagstring(s);
-      *(L->stack.top++) = s->u.s.globalval;
+      pushtagstring(gv->name);
+      *(L->stack.top++) = gv->value;
       luaD_calln(2, 1);
       if (ttype(L->stack.top-1) != LUA_T_NIL) {
         L->stack.top--;
-        *(L->stack.top-1) = *L->stack.top;  /* remove extra `s' */
+        *(L->stack.top-1) = *L->stack.top;  /* remove extra name */
         return;
       }
-      L->stack.top-=2;  /* remove result and extra `s' */
+      L->stack.top-=2;  /* remove result and extra name */
     }
   }
 }
@@ -507,7 +515,8 @@ static void luaB_tremove (void) {
 }
 
 
-/* {
+/*
+** {======================================================
 ** Quicksort
 */
 
@@ -593,11 +602,10 @@ static void luaB_sort (void) {
   lua_pushobject(t);
 }
 
-/* }}===================================================== */
+/* }====================================================== */
 
 
-/*
-** ====================================================== */
+/* }====================================================== */
 
 
 
@@ -605,6 +613,7 @@ static void luaB_sort (void) {
 /*
 ** {======================================================
 ** some DEBUG functions
+** (for internal debugging of the Lua implementation)
 ** =======================================================
 */
 

+ 2 - 3
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.49 1999/10/14 17:53:35 roberto Exp roberto $
+** $Id: ldo.c,v 1.50 1999/10/14 19:46:57 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -219,7 +219,7 @@ void luaD_calln (int nArgs, int nResults) {
 
 
 static void message (const char *s) {
-  const TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval);
+  const TObject *em = &(luaS_assertglobalbyname("_ERRORMESSAGE")->value);
   if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO ||
       ttype(em) == LUA_T_CLOSURE) {
     *L->stack.top = *em;
@@ -237,7 +237,6 @@ void lua_error (const char *s) {
   if (L->errorJmp)
     longjmp(L->errorJmp->b, 1);
   else {
-    LUA_INTERNALERROR("exit!!");
     message("exit(1). Unable to recover.\n");
     exit(1);
   }

+ 18 - 15
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.28 1999/10/11 16:13:11 roberto Exp roberto $
+** $Id: lgc.c,v 1.29 1999/10/14 19:13:31 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -62,13 +62,13 @@ static void hashmark (Hash *h) {
 }
 
 
-static void globalmark (void) {
-  TaggedString *g;
-  for (g=L->rootglobal; g; g=g->nextglobal) {
-    LUA_ASSERT(g->constindex >= 0, "userdata in global list");
-    if (g->u.s.globalval.ttype != LUA_T_NIL) {
-      markobject(&g->u.s.globalval);
-      strmark(g);  /* cannot collect non nil global variables */
+static void travglobal (void) {
+  GlobalVar *gv;
+  for (gv=L->rootglobal; gv; gv=gv->next) {
+    LUA_ASSERT(gv->name->u.s.gv == gv, "inconsistent global name");
+    if (gv->value.ttype != LUA_T_NIL) {
+      strmark(gv->name);  /* cannot collect non nil global variables */
+      markobject(&gv->value);
     }
   }
 }
@@ -157,12 +157,16 @@ static void collecttable (void) {
 }
 
 
+/*
+** 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 (int limit) {
-  TaggedString **p = &L->rootglobal;
-  TaggedString *next;
+  GlobalVar **p = &L->rootglobal;
+  GlobalVar *next;
   while ((next = *p) != NULL) {
-    if (next->marked >= limit) p = &next->nextglobal;
-    else *p = next->nextglobal;
+    if (next->name->marked >= limit) p = &next->next;
+    else *p = next->next;
   }
 }
 
@@ -226,7 +230,7 @@ static void tableTM (void) {
 
 static void markall (void) {
   travstack(); /* mark stack objects */
-  globalmark();  /* mark global variable values and names */
+  travglobal();  /* mark global variable values and names */
   travlock(); /* mark locked objects */
   luaT_travtagmethods(markobject);  /* mark tag methods */
 }
@@ -239,8 +243,6 @@ void luaC_collect (int all) {
   collectstring(all?MAX_INT:1);
   collectproto();
   collectclosure();
-  if (!all)
-    luaD_gcIM(&luaO_nilobject);  /* GC tag method for nil (signal end of GC) */
 }
 
 
@@ -249,6 +251,7 @@ long lua_collectgarbage (long limit) {
   markall();
   luaR_invalidaterefs();
   luaC_collect(0);
+  luaD_gcIM(&luaO_nilobject);  /* GC tag method for nil (signal end of GC) */
   recovered = recovered - L->nblocks;
   L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit;
   return recovered;

+ 16 - 11
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.33 1999/10/14 19:13:31 roberto Exp roberto $
+** $Id: lobject.h,v 1.34 1999/10/19 13:33:22 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -87,25 +87,30 @@ typedef struct TObject {
 
 
 
+typedef struct GlobalVar {
+  TObject value;
+  struct GlobalVar *next;
+  struct TaggedString *name;
+} GlobalVar;
+
+
 /*
 ** String headers for string table
 */
-
 typedef struct TaggedString {
-  struct TaggedString *nexthash;  /* chain hash table */
-  struct TaggedString *nextglobal;  /* chain global variables */
-  unsigned long hash;
-  int constindex;  /* hint to reuse constants (= -1 if this is a userdata) */
   union {
-    struct {
-      TObject globalval;
-      long len;  /* if this is a string, here is its length */
+    struct {  /* for strings */
+      GlobalVar *gv;  /* eventual global value with this name */
+      long len;
     } s;
-    struct {
+    struct {  /* for userdata */
       int tag;
-      void *v;  /* if this is a userdata, here is its value */
+      void *value;
     } d;
   } u;
+  struct TaggedString *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];   /* \0 byte already reserved */
 } TaggedString;

+ 10 - 1
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.40 1999/09/02 13:13:22 roberto Exp roberto $
+** $Id: lparser.c,v 1.41 1999/09/20 14:15:18 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -232,6 +232,13 @@ static void code_constant (LexState *ls, int c) {
 }
 
 
+static void assertglobal (LexState *ls, int index) {
+  TObject *o = &ls->fs->f->consts[index];
+  LUA_ASSERT(ttype(o) == LUA_T_STRING, "global name is not a string");
+  luaS_assertglobal(tsvalue(o));
+}
+
+
 static int next_constant (FuncState *fs) {
   TProtoFunc *f = fs->f;
   luaM_growvector(f->consts, f->nconsts, 1, TObject, constantEM, MAX_ARG);
@@ -478,6 +485,7 @@ static void lua_pushvar (LexState *ls, vardesc *var) {
       break;
     case VGLOBAL:
       code_oparg(ls, GETGLOBAL, var->info, 1);
+      assertglobal(ls, var->info);  /* make sure that there is a global */
       break;
     case VDOT:
       code_oparg(ls, GETDOTTED, var->info, 0);
@@ -501,6 +509,7 @@ static void storevar (LexState *ls, const vardesc *var) {
       break;
     case VGLOBAL:
       code_oparg(ls, SETGLOBAL, var->info, -1);
+      assertglobal(ls, var->info);  /* make sure that there is a global */
       break;
     case VINDEXED:
       code_opcode(ls, SETTABLEPOP, -3);

+ 2 - 2
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.19 1999/05/11 20:08:20 roberto Exp roberto $
+** $Id: lstate.h,v 1.20 1999/10/04 17:51:04 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -76,7 +76,7 @@ struct lua_State {
   TProtoFunc *rootproto;  /* list of all prototypes */
   Closure *rootcl;  /* list of all closures */
   Hash *roottable;  /* list of all tables */
-  TaggedString *rootglobal;  /* list of strings with global values */
+  GlobalVar *rootglobal;  /* list of global variables */
   stringtable *string_root;  /* array of hash tables for strings and udata */
   struct IM *IMtable;  /* table for tag methods */
   int last_tag;  /* last used tag in IMtable */

+ 37 - 29
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.24 1999/10/14 19:13:31 roberto Exp roberto $
+** $Id: lstring.c,v 1.25 1999/10/19 13:33:22 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -87,7 +87,6 @@ static TaggedString *newone (long l, unsigned long h) {
                                        sizeof(TaggedString)+l*sizeof(char));
   ts->marked = 0;
   ts->nexthash = NULL;
-  ts->nextglobal = ts;  /* signal it is not in global list */
   ts->hash = h;
   return ts;
 }
@@ -97,7 +96,7 @@ static TaggedString *newone_s (const char *str, long l, unsigned long h) {
   TaggedString *ts = newone(l, h);
   memcpy(ts->str, str, l);
   ts->str[l] = 0;  /* ending 0 */
-  ts->u.s.globalval.ttype = LUA_T_NIL;  /* initialize global value */
+  ts->u.s.gv = NULL;  /* no global value */
   ts->u.s.len = l;
   ts->constindex = 0;
   L->nblocks += gcsizestring(l);
@@ -107,7 +106,7 @@ static TaggedString *newone_s (const char *str, long l, unsigned long h) {
 
 static TaggedString *newone_u (void *buff, int tag, unsigned long h) {
   TaggedString *ts = newone(0, h);
-  ts->u.d.v = buff;
+  ts->u.d.value = buff;
   ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
   ts->constindex = -1;  /* tag -> this is a userdata */
   L->nblocks++;
@@ -131,13 +130,15 @@ static void newentry (stringtable *tb, TaggedString *ts, int h) {
 }
 
 
-static TaggedString *insert_s (const char *str, long l,
-                               stringtable *tb, unsigned long h) {
+TaggedString *luaS_newlstr (const char *str, long l) {
+  unsigned long h = hash_s(str, l);
+  stringtable *tb = &L->string_root[h%NUM_HASHSTR];
   int h1 = h%tb->size;
   TaggedString *ts;
-  for (ts = tb->hash[h1]; ts; ts = ts->nexthash)
+  for (ts = tb->hash[h1]; ts; ts = ts->nexthash) {
     if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0))
       return ts;
+  }
   /* not found */
   ts = newone_s(str, l, h);  /* create new entry */
   newentry(tb, ts, h1);  /* insert it on table */
@@ -145,30 +146,22 @@ static TaggedString *insert_s (const char *str, long l,
 }
 
 
-static TaggedString *insert_u (void *buff, int tag, stringtable *tb) {
-  unsigned long h = (IntPoint)buff;
+TaggedString *luaS_createudata (void *udata, int tag) {
+  unsigned long h = (IntPoint)udata;
+  stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR];
   int h1 = h%tb->size;
   TaggedString *ts;
-  for (ts = tb->hash[h1]; ts; ts = ts->nexthash)
-    if ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v)
+  for (ts = tb->hash[h1]; ts; ts = ts->nexthash) {
+    if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG))
       return ts;
+  }
   /* not found */
-  ts = newone_u(buff, tag, h);
+  ts = newone_u(udata, tag, h);
   newentry(tb, ts, h1);
   return ts;
 }
 
 
-TaggedString *luaS_createudata (void *udata, int tag) {
-  int t = ((IntPoint)udata%NUM_HASHUDATA)+NUM_HASHSTR;
-  return insert_u(udata, tag, &L->string_root[t]);
-}
-
-TaggedString *luaS_newlstr (const char *str, long l) {
-  unsigned long h = hash_s(str, l);
-  return insert_s(str, l, &L->string_root[h%NUM_HASHSTR], h);
-}
-
 TaggedString *luaS_new (const char *str) {
   return luaS_newlstr(str, strlen(str));
 }
@@ -181,23 +174,38 @@ TaggedString *luaS_newfixedstring (const char *str) {
 
 
 void luaS_free (TaggedString *t) {
-  L->nblocks -= (t->constindex == -1) ? 1 : gcsizestring(t->u.s.len);
+  if (t->constindex == -1)  /* is userdata? */
+    L->nblocks--;
+  else {  /* is string */
+    L->nblocks -= gcsizestring(t->u.s.len);
+    luaM_free(t->u.s.gv);
+  }
   luaM_free(t);
 }
 
 
-void luaS_rawsetglobal (TaggedString *ts, const TObject *newval) {
-  ts->u.s.globalval = *newval;
-  if (ts->nextglobal == ts) {  /* is not in list? */
-    ts->nextglobal = L->rootglobal;
-    L->rootglobal = ts;
+GlobalVar *luaS_assertglobal (TaggedString *ts) {
+  GlobalVar *gv = ts->u.s.gv;
+  if (!gv) {  /* no global value yet? */
+    gv = luaM_new(GlobalVar);
+    gv->value.ttype = LUA_T_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 (const char *name) {
+  return luaS_assertglobal(luaS_new(name));
 }
 
 
 int luaS_globaldefined (const char *name) {
   TaggedString *ts = luaS_new(name);
-  return ts->u.s.globalval.ttype != LUA_T_NIL;
+  return ts->u.s.gv && ts->u.s.gv->value.ttype != LUA_T_NIL;
 }
 
 

+ 3 - 2
lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.10 1999/10/11 16:13:11 roberto Exp roberto $
+** $Id: lstring.h,v 1.11 1999/10/14 19:13:31 roberto Exp roberto $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -33,7 +33,8 @@ void luaS_free (TaggedString *ts);
 TaggedString *luaS_newlstr (const char *str, long l);
 TaggedString *luaS_new (const char *str);
 TaggedString *luaS_newfixedstring (const char *str);
-void luaS_rawsetglobal (TaggedString *ts, const TObject *newval);
+GlobalVar *luaS_assertglobal (TaggedString *ts);
+GlobalVar *luaS_assertglobalbyname (const char *name);
 int luaS_globaldefined (const char *name);
 
 

+ 10 - 10
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.63 1999/10/14 19:13:31 roberto Exp roberto $
+** $Id: lvm.c,v 1.64 1999/10/14 19:46:57 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -167,9 +167,9 @@ void luaV_rawsettable (const TObject *t) {
 }
 
 
-void luaV_getglobal (TaggedString *ts) {
+void luaV_getglobal (GlobalVar *gv) {
   /* WARNING: caller must assure stack space */
-  const TObject *value = &ts->u.s.globalval;
+  const TObject *value = &gv->value;
   switch (ttype(value)) {
     /* only userdata, tables and nil can have getglobal tag methods */
     case LUA_T_USERDATA: case LUA_T_ARRAY: case LUA_T_NIL: {
@@ -177,7 +177,7 @@ void luaV_getglobal (TaggedString *ts) {
       if (ttype(im) != LUA_T_NIL) {  /* is there a tag method? */
         struct Stack *S = &L->stack;
         ttype(S->top) = LUA_T_STRING;
-        tsvalue(S->top) = ts;
+        tsvalue(S->top) = gv->name;  /* global name */
         S->top++;
         *S->top++ = *value;
         luaD_callTM(im, 2, 1);
@@ -190,18 +190,18 @@ void luaV_getglobal (TaggedString *ts) {
 }
 
 
-void luaV_setglobal (TaggedString *ts) {
-  const TObject *oldvalue = &ts->u.s.globalval;
+void luaV_setglobal (GlobalVar *gv) {
+  const TObject *oldvalue = &gv->value;
   const TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
   if (ttype(im) == LUA_T_NIL)  /* is there a tag method? */
-    luaS_rawsetglobal(ts, --L->stack.top);
+    gv->value = *(--L->stack.top);
   else {
     /* WARNING: caller must assure stack space */
     struct Stack *S = &L->stack;
     TObject newvalue;
     newvalue = *(S->top-1);
     ttype(S->top-1) = LUA_T_STRING;
-    tsvalue(S->top-1) = ts;
+    tsvalue(S->top-1) = gv->name;
     *S->top++ = *oldvalue;
     *S->top++ = newvalue;
     luaD_callTM(im, 3, 0);
@@ -370,7 +370,7 @@ StkId luaV_execute (const Closure *cl, const TProtoFunc *tf, StkId base) {
 
       case GETGLOBALW: aux += highbyte(*pc++);
       case GETGLOBAL:  aux += *pc++;
-        luaV_getglobal(tsvalue(&consts[aux]));
+        luaV_getglobal(tsvalue(&consts[aux])->u.s.gv);
         break;
 
       case GETTABLE:
@@ -407,7 +407,7 @@ StkId luaV_execute (const Closure *cl, const TProtoFunc *tf, StkId base) {
 
       case SETGLOBALW: aux += highbyte(*pc++);
       case SETGLOBAL:  aux += *pc++;
-        luaV_setglobal(tsvalue(&consts[aux]));
+        luaV_setglobal(tsvalue(&consts[aux])->u.s.gv);
         break;
 
       case SETTABLEPOP:

+ 3 - 3
lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 1.9 1999/08/16 20:52:00 roberto Exp roberto $
+** $Id: lvm.h,v 1.10 1999/10/14 19:46:57 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -24,8 +24,8 @@ void luaV_setn (Hash *t, int val);
 void luaV_gettable (void);
 void luaV_settable (const TObject *t);
 void luaV_rawsettable (const TObject *t);
-void luaV_getglobal (TaggedString *ts);
-void luaV_setglobal (TaggedString *ts);
+void luaV_getglobal (GlobalVar *gv);
+void luaV_setglobal (GlobalVar *gv);
 StkId luaV_execute (const Closure *cl, const TProtoFunc *tf, StkId base);
 void luaV_closure (int nelems);
 void luaV_comparison (lua_Type ttype_less, lua_Type ttype_equal,