From 11a70220670f25a9929439f0b27331f09f05235c Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 8 May 2000 16:32:53 -0300 Subject: [PATCH] global variables are stored in a Lua table --- lapi.c | 80 ++++++++++++++++++----------------------- lapi.h | 3 +- lbuiltin.c | 102 ++++++++++++++++++++++------------------------------- lbuiltin.h | 7 ++-- lcode.c | 10 +----- ldebug.c | 11 +++--- ldo.c | 5 +-- lgc.c | 31 ++-------------- llex.c | 11 ++++-- lobject.h | 12 ++----- lstate.c | 6 ++-- lstate.h | 6 ++-- lstring.c | 65 +++++++++------------------------- lstring.h | 7 ++-- ltable.c | 22 ++++++++---- ltable.h | 6 ++-- ltests.c | 7 ++-- lua.h | 13 ++++--- lundump.c | 5 ++- lvm.c | 40 ++++++++++----------- lvm.h | 7 ++-- 21 files changed, 181 insertions(+), 275 deletions(-) diff --git a/lapi.c b/lapi.c index 6685abdc..60a9b45c 100644 --- a/lapi.c +++ b/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_assertglobalbyname(L, name), L->top--); + luaV_setglobal(L, luaS_new(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 (; itop) = 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(>) = TAG_TABLE; + avalue(>) = L->gt; + for (i=0; iL, 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); diff --git a/ldebug.c b/ldebug.c index ef934d86..3a381455 100644 --- a/ldebug.c +++ b/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; } diff --git a/ldo.c b/ldo.c index 9791c7f5..edbaab85 100644 --- a/ldo.c +++ b/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; diff --git a/lgc.c b/lgc.c index ac213df2..32dd6471 100644 --- a/lgc.c +++ b/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; istring_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 */ } diff --git a/llex.c b/llex.c index 4efcb873..ae498715 100644 --- a/llex.c +++ b/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 */ diff --git a/lobject.h b/lobject.h index 921a7a05..c4e605c6 100644 --- a/lobject.h +++ b/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! */ diff --git a/lstate.c b/lstate.c index f1949df0..7ba9bcff 100644 --- a/lstate.c +++ b/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); diff --git a/lstate.h b/lstate.h index d099e6aa..6e943b30 100644 --- a/lstate.h +++ b/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 */ diff --git a/lstring.c b/lstring.c index 1dd4c9b9..3c9d0d8f 100644 --- a/lstring.c +++ b/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; -} - - diff --git a/lstring.h b/lstring.h index 80aa0b8f..8e307292 100644 --- a/lstring.h +++ b/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 diff --git a/ltable.c b/ltable.c index cc3a64f1..fb8b3dfe 100644 --- a/ltable.c +++ b/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)); +} diff --git a/ltable.h b/ltable.h index 9a5fe9a5..3d1f674a 100644 --- a/ltable.h +++ b/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); diff --git a/ltests.c b/ltests.c index 5ce089b9..03baa6e6 100644 --- a/ltests.c +++ b/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)])); diff --git a/lua.h b/lua.h index 23f5e472..58d5b27d 100644 --- a/lua.h +++ b/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: lua@tecgraf.puc-rio.br @@ -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) diff --git a/lundump.c b/lundump.c index f9d90168..11ada16d 100644 --- a/lundump.c +++ b/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; ikstr[i]=s; } } diff --git a/lvm.c b/lvm.c index 23f59032..9b0ea0c8 100644 --- a/lvm.c +++ b/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; diff --git a/lvm.h b/lvm.h index c3b2b6cc..ae57346b 100644 --- a/lvm.h +++ b/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);