diff --git a/lapi.c b/lapi.c index 91cea50c..6e941752 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.160 2001/11/16 16:29:51 roberto Exp $ +** $Id: lapi.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua API ** See Copyright Notice in lua.h */ @@ -45,8 +45,8 @@ static TObject *negindex (lua_State *L, int index) { return L->top+index; } else switch (index) { /* pseudo-indices */ - case LUA_REGISTRYINDEX: return &G(L)->registry; - case LUA_GLOBALSINDEX: return &L->gt; + case LUA_REGISTRYINDEX: return registry(L); + case LUA_GLOBALSINDEX: return gt(L); default: { TObject *func = (L->ci->base - 1); index = LUA_GLOBALSINDEX - index; @@ -149,20 +149,15 @@ LUA_API void lua_pushvalue (lua_State *L, int index) { */ -LUA_API int lua_rawtag (lua_State *L, int index) { +LUA_API int lua_type (lua_State *L, int index) { StkId o = luaA_indexAcceptable(L, index); return (o == NULL) ? LUA_TNONE : ttype(o); } -LUA_API const char *lua_type (lua_State *L, int index) { - StkId o; - const char *type; - lua_lock(L); - o = luaA_indexAcceptable(L, index); - type = (o == NULL) ? "no value" : luaT_typename(G(L), o); - lua_unlock(L); - return type; +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; } @@ -180,22 +175,11 @@ LUA_API int lua_isnumber (lua_State *L, int index) { LUA_API int lua_isstring (lua_State *L, int index) { - int t = lua_rawtag(L, index); + int t = lua_type(L, index); return (t == LUA_TSTRING || t == LUA_TNUMBER); } -LUA_API int lua_tag (lua_State *L, int index) { - StkId o; - int i; - lua_lock(L); /* other thread could be changing the tag */ - o = luaA_indexAcceptable(L, index); - i = (o == NULL) ? LUA_NOTAG : luaT_tag(o); - lua_unlock(L); - return i; -} - - LUA_API int lua_equal (lua_State *L, int index1, int index2) { StkId o1 = luaA_indexAcceptable(L, index1); StkId o2 = luaA_indexAcceptable(L, index2); @@ -346,8 +330,10 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { LUA_API void lua_getglobal (lua_State *L, const char *name) { + TObject o; lua_lock(L); - luaV_getglobal(L, luaS_new(L, name), L->top); + setsvalue(&o, luaS_new(L, name)); + luaV_gettable(L, gt(L), &o, L->top); api_incr_top(L); lua_unlock(L); } @@ -391,6 +377,29 @@ LUA_API void lua_newtable (lua_State *L) { } +LUA_API void lua_geteventtable (lua_State *L, int objindex) { + StkId obj; + Table *et; + lua_lock(L); + obj = luaA_indexAcceptable(L, objindex); + switch (ttype(obj)) { + case LUA_TTABLE: + et = hvalue(obj)->eventtable; + break; + case LUA_TUSERDATA: + et = uvalue(obj)->uv.eventtable; + break; + default: + et = hvalue(defaultet(L)); + } + if (et == hvalue(defaultet(L))) + setnilvalue(L->top); + else + sethvalue(L->top, et); + api_incr_top(L); + lua_unlock(L); +} + /* ** set functions (stack -> Lua) @@ -398,9 +407,11 @@ LUA_API void lua_newtable (lua_State *L) { LUA_API void lua_setglobal (lua_State *L, const char *name) { + TObject o; lua_lock(L); api_checknelems(L, 1); - luaV_setglobal(L, luaS_new(L, name), L->top - 1); + setsvalue(&o, luaS_new(L, name)); + luaV_settable(L, gt(L), &o, L->top - 1); L->top--; /* remove element from the top */ lua_unlock(L); } @@ -447,11 +458,32 @@ LUA_API void lua_setglobals (lua_State *L) { api_checknelems(L, 1); newtable = --L->top; api_check(L, ttype(newtable) == LUA_TTABLE); - setobj(&L->gt, newtable); + setobj(gt(L), newtable); lua_unlock(L); } +LUA_API void lua_seteventtable (lua_State *L, int objindex) { + StkId obj, et; + lua_lock(L); + api_checknelems(L, 1); + obj = luaA_indexAcceptable(L, objindex); + et = --L->top; + api_check(L, ttype(et) == LUA_TTABLE); + switch (ttype(obj)) { + case LUA_TTABLE: + hvalue(obj)->eventtable = hvalue(et); + break; + case LUA_TUSERDATA: + uvalue(obj)->uv.eventtable = hvalue(et); + break; + default: + luaO_verror(L, "cannot change the event table of a %.20s", + luaT_typenames[ttype(obj)]); + } + lua_unlock(L); +} + /* ** `do' functions (run Lua code) @@ -533,70 +565,6 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { ** miscellaneous functions */ -LUA_API int lua_newtype (lua_State *L, const char *name, int basictype) { - int tag; - lua_lock(L); - if (basictype != LUA_TNONE && - basictype != LUA_TTABLE && - basictype != LUA_TUSERDATA) - luaO_verror(L, "invalid basic type (%d) for new type", basictype); - tag = luaT_newtag(L, name, basictype); - if (tag == LUA_TNONE) - luaO_verror(L, "type name '%.30s' already exists", name); - lua_unlock(L); - return tag; -} - - -LUA_API int lua_name2tag (lua_State *L, const char *name) { - int tag; - const TObject *v; - lua_lock(L); - v = luaH_getstr(G(L)->type2tag, luaS_new(L, name)); - if (ttype(v) == LUA_TNIL) - tag = LUA_TNONE; - else { - lua_assert(ttype(v) == LUA_TNUMBER); - tag = cast(int, nvalue(v)); - } - lua_unlock(L); - return tag; -} - - -LUA_API const char *lua_tag2name (lua_State *L, int tag) { - const char *s; - lua_lock(L); - s = (tag == LUA_TNONE) ? "no value" : typenamebytag(G(L), tag); - lua_unlock(L); - return s; -} - - -LUA_API void lua_settag (lua_State *L, int tag) { - int basictype; - lua_lock(L); - api_checknelems(L, 1); - if (tag < 0 || tag >= G(L)->ntag) - luaO_verror(L, "%d is not a valid tag", tag); - basictype = G(L)->TMtable[tag].basictype; - if (basictype != LUA_TNONE && basictype != ttype(L->top-1)) - luaO_verror(L, "tag %d can only be used for type '%.20s'", tag, - typenamebytag(G(L), basictype)); - switch (ttype(L->top-1)) { - case LUA_TTABLE: - hvalue(L->top-1)->htag = tag; - break; - case LUA_TUSERDATA: - uvalue(L->top-1)->uv.tag = tag; - break; - default: - luaO_verror(L, "cannot change the tag of a %.20s", - luaT_typename(G(L), L->top-1)); - } - lua_unlock(L); -} - LUA_API void lua_error (lua_State *L, const char *s) { lua_lock(L); diff --git a/lauxlib.c b/lauxlib.c index 1189af50..849daa33 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.53 2001/10/31 19:40:14 roberto Exp $ +** $Id: lauxlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -43,7 +43,8 @@ LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) { LUALIB_API void luaL_typerror (lua_State *L, int narg, const char *tname) { char buff[80]; - sprintf(buff, "%.25s expected, got %.25s", tname, lua_type(L,narg)); + sprintf(buff, "%.25s expected, got %.25s", tname, + lua_typename(L, lua_type(L,narg))); luaL_argerror(L, narg, buff); } @@ -59,26 +60,18 @@ LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) { } -LUALIB_API void luaL_check_rawtype(lua_State *L, int narg, int t) { - if (lua_rawtag(L, narg) != t) +LUALIB_API void luaL_check_type(lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) tag_error(L, narg, t); } LUALIB_API void luaL_check_any (lua_State *L, int narg) { - if (lua_rawtag(L, narg) == LUA_TNONE) + if (lua_type(L, narg) == LUA_TNONE) luaL_argerror(L, narg, "value expected"); } -LUALIB_API void *luaL_check_userdata (lua_State *L, int narg, - const char *name) { - if (strcmp(lua_type(L, narg), name) != 0) - luaL_typerror(L, narg, name); - return lua_touserdata(L, narg); -} - - LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) { const char *s = lua_tostring(L, narg); if (!s) tag_error(L, narg, LUA_TSTRING); diff --git a/lauxlib.h b/lauxlib.h index 43405bf2..fd9d1f53 100644 --- a/lauxlib.h +++ b/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.38 2001/10/31 19:40:14 roberto Exp $ +** $Id: lauxlib.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -38,10 +38,8 @@ LUALIB_API lua_Number luaL_check_number (lua_State *L, int numArg); LUALIB_API lua_Number luaL_opt_number (lua_State *L, int nArg, lua_Number def); LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg); -LUALIB_API void luaL_check_rawtype (lua_State *L, int narg, int t); +LUALIB_API void luaL_check_type (lua_State *L, int narg, int t); LUALIB_API void luaL_check_any (lua_State *L, int narg); -LUALIB_API void *luaL_check_userdata (lua_State *L, int narg, - const char *name); LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...); LUALIB_API int luaL_findstring (const char *name, diff --git a/lbaselib.c b/lbaselib.c index 52343fe5..adb9af0c 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.45 2001/10/26 17:33:30 roberto Exp $ +** $Id: lbaselib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Basic library ** See Copyright Notice in lua.h */ @@ -41,7 +41,7 @@ static int luaB__ALERT (lua_State *L) { ** The library `liolib' redefines _ERRORMESSAGE for better error information. */ static int luaB__ERRORMESSAGE (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TSTRING); + luaL_check_type(L, 1, LUA_TSTRING); lua_getglobal(L, LUA_ALERT); if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */ lua_Debug ar; @@ -136,41 +136,22 @@ static int luaB_getglobal (lua_State *L) { } -/* auxiliary function to get `tags' */ -static int gettag (lua_State *L, int narg) { - switch (lua_rawtag(L, narg)) { - case LUA_TNUMBER: - return (int)(lua_tonumber(L, narg)); - case LUA_TSTRING: { - const char *name = lua_tostring(L, narg); - int tag = lua_name2tag(L, name); - if (tag == LUA_TNONE) - luaL_verror(L, "'%.30s' is not a valid type name", name); - return tag; - } - default: - luaL_argerror(L, narg, "tag or type name expected"); - return 0; /* to avoid warnings */ +static int luaB_eventtable (lua_State *L) { + luaL_check_type(L, 1, LUA_TTABLE); + if (lua_isnull(L, 2)) + lua_geteventtable(L, 1); + else { + lua_settop(L, 2); + luaL_check_type(L, 2, LUA_TTABLE); + lua_seteventtable(L, 1); } -} - - -static int luaB_tag (lua_State *L) { - luaL_check_any(L, 1); - lua_pushnumber(L, lua_tag(L, 1)); return 1; } -static int luaB_settype (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TTABLE); - lua_pushvalue(L, 1); /* push table */ - lua_settag(L, gettag(L, 2)); - return 1; /* return table */ -} static int luaB_weakmode (lua_State *L) { const char *mode = luaL_check_string(L, 2); - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); if (*mode == '?') { char buff[3]; char *s = buff; @@ -191,17 +172,11 @@ static int luaB_weakmode (lua_State *L) { } } -static int luaB_newtype (lua_State *L) { - const char *name = luaL_opt_string(L, 1, NULL); - lua_pushnumber(L, lua_newtype(L, name, LUA_TTABLE)); - return 1; -} - static int luaB_globals (lua_State *L) { lua_getglobals(L); /* value to be returned */ if (!lua_isnull(L, 1)) { - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); lua_pushvalue(L, 1); /* new table of globals */ lua_setglobals(L); } @@ -209,43 +184,20 @@ static int luaB_globals (lua_State *L) { } static int luaB_rawget (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); luaL_check_any(L, 2); lua_rawget(L, -2); return 1; } static int luaB_rawset (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); luaL_check_any(L, 2); luaL_check_any(L, 3); lua_rawset(L, -3); return 1; } -static int luaB_settagmethod (lua_State *L) { - int tag = gettag(L, 1); - const char *event = luaL_check_string(L, 2); - luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3, - "function or nil expected"); - if (strcmp(event, "gc") == 0) - lua_error(L, "cannot set `gc' tag method from Lua"); - lua_gettagmethod(L, tag, event); - lua_pushvalue(L, 3); - lua_settagmethod(L, tag, event); - return 1; -} - - -static int luaB_gettagmethod (lua_State *L) { - int tag = gettag(L, 1); - const char *event = luaL_check_string(L, 2); - if (strcmp(event, "gc") == 0) - lua_error(L, "cannot get `gc' tag method from Lua"); - lua_gettagmethod(L, tag, event); - return 1; -} - static int luaB_gcinfo (lua_State *L) { lua_pushnumber(L, lua_getgccount(L)); @@ -262,20 +214,20 @@ static int luaB_collectgarbage (lua_State *L) { static int luaB_type (lua_State *L) { luaL_check_any(L, 1); - lua_pushstring(L, lua_type(L, 1)); - return 1; -} - - -static int luaB_rawtype (lua_State *L) { - luaL_check_any(L, 1); - lua_pushstring(L, lua_tag2name(L, lua_rawtag(L, 1))); + if (lua_isnull(L, 2)) + lua_pushstring(L, lua_typename(L, lua_type(L, 1))); + else { + if (strcmp(lua_typename(L, lua_type(L, 1)), luaL_check_string(L, 2)) == 0) + lua_pushnumber(L, 1); + else + lua_pushnil(L); + } return 1; } static int luaB_next (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); lua_settop(L, 2); /* create a 2nd argument if there isn't one */ if (lua_next(L, 1)) return 2; @@ -393,7 +345,7 @@ static int luaB_require (lua_State *L) { static int aux_unpack (lua_State *L, int arg) { int n, i; - luaL_check_rawtype(L, arg, LUA_TTABLE); + luaL_check_type(L, arg, LUA_TTABLE); n = lua_getn(L, arg); luaL_check_stack(L, n, "table too big to unpack"); for (i=1; i<=n; i++) /* push arg[1...n] */ @@ -443,7 +395,7 @@ static int luaB_call (lua_State *L) { static int luaB_tostring (lua_State *L) { char buff[64]; - switch (lua_rawtag(L, 1)) { + switch (lua_type(L, 1)) { case LUA_TNUMBER: lua_pushstring(L, lua_tostring(L, 1)); return 1; @@ -451,16 +403,15 @@ static int luaB_tostring (lua_State *L) { lua_pushvalue(L, 1); return 1; case LUA_TTABLE: - sprintf(buff, "%.40s: %p", lua_type(L, 1), lua_topointer(L, 1)); + sprintf(buff, "%.40s: %p", lua_typename(L, lua_type(L, 1)), lua_topointer(L, 1)); break; case LUA_TFUNCTION: sprintf(buff, "function: %p", lua_topointer(L, 1)); break; case LUA_TUSERDATA: { - const char *t = lua_type(L, 1); + const char *t = lua_typename(L, lua_type(L, 1)); if (strcmp(t, "userdata") == 0) - sprintf(buff, "userdata(%d): %p", lua_tag(L, 1), - lua_touserdata(L, 1)); + sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); else sprintf(buff, "%.40s: %p", t, lua_touserdata(L, 1)); break; @@ -478,8 +429,8 @@ static int luaB_tostring (lua_State *L) { static int luaB_foreachi (lua_State *L) { int n, i; - luaL_check_rawtype(L, 1, LUA_TTABLE); - luaL_check_rawtype(L, 2, LUA_TFUNCTION); + luaL_check_type(L, 1, LUA_TTABLE); + luaL_check_type(L, 2, LUA_TFUNCTION); n = lua_getn(L, 1); for (i=1; i<=n; i++) { lua_pushvalue(L, 2); /* function */ @@ -495,8 +446,8 @@ static int luaB_foreachi (lua_State *L) { static int luaB_foreach (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TTABLE); - luaL_check_rawtype(L, 2, LUA_TFUNCTION); + luaL_check_type(L, 1, LUA_TTABLE); + luaL_check_type(L, 2, LUA_TFUNCTION); lua_pushnil(L); /* first index */ for (;;) { if (lua_next(L, 1) == 0) @@ -523,7 +474,7 @@ static int luaB_assert (lua_State *L) { static int luaB_getn (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); lua_pushnumber(L, lua_getn(L, 1)); return 1; } @@ -532,7 +483,7 @@ static int luaB_getn (lua_State *L) { static int luaB_tinsert (lua_State *L) { int v = lua_gettop(L); /* number of arguments */ int n, pos; - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); n = lua_getn(L, 1); if (v == 2) /* called with only 2 arguments */ pos = n+1; @@ -553,7 +504,7 @@ static int luaB_tinsert (lua_State *L) { static int luaB_tremove (lua_State *L) { int pos, n; - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); n = lua_getn(L, 1); pos = luaL_opt_int(L, 2, n); if (n <= 0) return 0; /* table is `empty' */ @@ -665,10 +616,10 @@ static void auxsort (lua_State *L, int l, int u) { static int luaB_sort (lua_State *L) { int n; - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); n = lua_getn(L, 1); if (!lua_isnull(L, 2)) /* is there a 2nd argument? */ - luaL_check_rawtype(L, 2, LUA_TFUNCTION); + luaL_check_type(L, 2, LUA_TFUNCTION); lua_settop(L, 2); /* make sure there is two arguments */ auxsort(L, 1, n); return 0; @@ -686,28 +637,19 @@ static const luaL_reg base_funcs[] = { {"dofile", luaB_dofile}, {"dostring", luaB_dostring}, {"error", luaB_error}, + {"eventtable", luaB_eventtable}, {"foreach", luaB_foreach}, {"foreachi", luaB_foreachi}, {"gcinfo", luaB_gcinfo}, - {"getglobal", luaB_getglobal}, - {"gettagmethod", luaB_gettagmethod}, + {"getglobal", luaB_getglobal}, /* compatibility with 4.0 */ {"globals", luaB_globals}, {"loadfile", luaB_loadfile}, {"loadstring", luaB_loadstring}, - {"newtype", luaB_newtype}, - {"newtag", luaB_newtype}, /* for compatibility 4.0 */ {"next", luaB_next}, {"print", luaB_print}, {"rawget", luaB_rawget}, {"rawset", luaB_rawset}, - {"rawgettable", luaB_rawget}, /* for compatibility 3.2 */ - {"rawsettable", luaB_rawset}, /* for compatibility 3.2 */ - {"rawtype", luaB_rawtype}, - {"setglobal", luaB_setglobal}, - {"settag", luaB_settype}, /* for compatibility 4.0 */ - {"settype", luaB_settype}, - {"settagmethod", luaB_settagmethod}, - {"tag", luaB_tag}, + {"setglobal", luaB_setglobal}, /* compatibility with 4.0 */ {"tonumber", luaB_tonumber}, {"tostring", luaB_tostring}, {"type", luaB_type}, diff --git a/ldebug.c b/ldebug.c index 5537fcd3..954c68c0 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.92 2001/10/31 19:58:11 roberto Exp $ +** $Id: ldebug.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -205,22 +205,8 @@ static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { } -static const char *travtagmethods (global_State *G, const TObject *o) { - if (ttype(o) == LUA_TFUNCTION) { - int e; - for (e=0; entag; t++) - if (clvalue(o) == luaT_gettm(G, t, e)) - return luaT_eventname[e]; - } - } - return NULL; -} - - static const char *travglobals (lua_State *L, const TObject *o) { - Table *g = hvalue(&L->gt); + Table *g = hvalue(gt(L)); int i = sizenode(g); while (i--) { Node *n = node(g, i); @@ -235,10 +221,7 @@ static void getname (lua_State *L, const TObject *f, lua_Debug *ar) { /* try to find a name for given function */ if ((ar->name = travglobals(L, f)) != NULL) ar->namewhat = "global"; - /* not found: try tag methods */ - else if ((ar->name = travtagmethods(G(L), f)) != NULL) - ar->namewhat = "tag-method"; - else ar->namewhat = ""; /* not found at all */ + else ar->namewhat = ""; /* not found */ } @@ -531,7 +514,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, void luaG_typeerror (lua_State *L, StkId o, const char *op) { const char *name; const char *kind = getobjname(L, o, &name); - const char *t = luaT_typename(G(L), o); + const char *t = luaT_typenames[ttype(o)]; if (kind) luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)", op, kind, name, t); @@ -556,8 +539,8 @@ void luaG_aritherror (lua_State *L, StkId p1, TObject *p2) { void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { - const char *t1 = luaT_typename(G(L), p1); - const char *t2 = luaT_typename(G(L), p2); + const char *t1 = luaT_typenames[ttype(p1)]; + const char *t2 = luaT_typenames[ttype(p2)]; if (t1[2] == t2[2]) luaO_verror(L, "attempt to compare two %.10s values", t1); else diff --git a/ldo.c b/ldo.c index 4e7722e3..aaf4de55 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.144 2001/11/27 20:56:47 roberto Exp $ +** $Id: ldo.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -43,8 +43,7 @@ void luaD_init (lua_State *L, int stacksize) { stacksize += EXTRA_STACK; L->stack = luaM_newvector(L, stacksize, TObject); L->stacksize = stacksize; - setnilvalue(L->stack); /* the `initial' function */ - L->top = L->basefunc.base = L->stack + 1; + L->top = L->basefunc.base = L->stack + RESERVED_STACK_PREFIX; restore_stack_limit(L); } @@ -143,12 +142,13 @@ void luaD_call (lua_State *L, StkId func) { CallInfo ci; if (ttype(func) != LUA_TFUNCTION) { /* `func' is not a function; check the `function' tag method */ - Closure *tm = luaT_gettmbyObj(G(L), func, TM_FUNCTION); - if (tm == NULL) + const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); + if (tm == NULL || ttype(tm) != LUA_TFUNCTION) luaG_typeerror(L, func, "call"); luaD_openstack(L, func); - setclvalue(func, tm); /* tag method is the new function to be called */ + setobj(func, tm); /* tag method is the new function to be called */ } + lua_assert(ttype(func) == LUA_TFUNCTION); ci.prev = L->ci; /* chain new callinfo */ L->ci = &ci; ci.base = func+1; @@ -300,9 +300,12 @@ struct lua_longjmp { static void message (lua_State *L, const char *s) { - StkId top = L->top; - luaV_getglobal(L, luaS_newliteral(L, LUA_ERRORMESSAGE), top); - if (ttype(top) == LUA_TFUNCTION) { + TObject o, m; + setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE)); + luaV_gettable(L, gt(L), &o, &m); + if (ttype(&m) == LUA_TFUNCTION) { + StkId top = L->top; + setobj(top, &m); incr_top; setsvalue(top+1, luaS_new(L, s)); incr_top; diff --git a/lfunc.c b/lfunc.c index 25a8bb07..d1eaa2f9 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 1.49 2001/11/06 21:41:53 roberto Exp $ +** $Id: lfunc.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -54,7 +54,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { } p = luaM_new(L, UpVal); /* not found: create a new one */ p->v = level; /* current value lives in the stack */ - p->mark = 1; /* won't participate in GC while open */ p->next = *pp; /* chain it in the proper position */ *pp = p; return p; @@ -68,7 +67,6 @@ void luaF_close (lua_State *L, StkId level) { p->v = &p->value; /* now current value lives here */ L->openupval = p->next; /* remove from `open' list */ p->next = G(L)->rootupval; /* chain in `closed' list */ - p->mark = 0; /* now it can be collected */ G(L)->rootupval = p; } } diff --git a/lgc.c b/lgc.c index 5ea01c77..3aa9f98d 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.116 2001/11/06 21:41:53 roberto Exp $ +** $Id: lgc.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -30,6 +30,15 @@ typedef struct GCState { #define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;} +/* mark tricks for userdata */ +#define isudmarked(u) (u->uv.len & 1) +#define markud(u) (u->uv.len |= 1) +#define unmarkud(u) (u->uv.len--) + + +/* mark tricks for upvalues (assume that open upvalues are always marked) */ +#define isupvalmarked(uv) ((uv)->v != &(uv)->value) + static void markobject (GCState *st, TObject *o); @@ -66,9 +75,9 @@ static void markclosure (GCState *st, Closure *cl) { protomark(cl->l.p); for (i=0; il.nupvalues; i++) { /* mark its upvalues */ UpVal *u = cl->l.upvals[i]; - if (!u->mark) { - u->mark = 1; - markobject(st, u->v); + if (!isupvalmarked(u)) { + markobject(st, &u->value); + u->v = NULL; /* mark it! */ } } } @@ -90,8 +99,8 @@ static void markobject (GCState *st, TObject *o) { strmark(tsvalue(o)); break; case LUA_TUSERDATA: - if (!ismarkedudata(uvalue(o))) - switchudatamark(uvalue(o)); + if (!isudmarked(uvalue(o))) + markud(uvalue(o)); break; case LUA_TFUNCTION: markclosure(st, clvalue(o)); @@ -112,7 +121,6 @@ static void markstacks (lua_State *L, GCState *st) { lua_State *L1 = L; do { /* for each thread */ StkId o, lim; - markobject(st, &L1->gt); /* mark table of globals */ for (o=L1->stack; otop; o++) markobject(st, o); lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK @@ -124,17 +132,10 @@ static void markstacks (lua_State *L, GCState *st) { } -static void marktagmethods (global_State *G, GCState *st) { - int t; - for (t=0; tntag; t++) { - struct TM *tm = &G->TMtable[t]; - int e; - if (tm->name) strmark(tm->name); - for (e=0; emethod[e]; - if (cl) markclosure(st, cl); - } - } +static void markudet (lua_State *L, GCState *st) { + Udata *u; + for (u = G(L)->rootudata; u; u = u->uv.next) + marktable(st, u->uv.eventtable); } @@ -152,6 +153,7 @@ static void traversetable (GCState *st, Table *h) { h->mark = st->toclear; /* put in the appropriate list */ st->toclear = h; } + marktable(st, h->eventtable); if (!(mode & LUA_WEAK_VALUE)) { i = sizearray(h); while (i--) @@ -172,11 +174,9 @@ static void traversetable (GCState *st, Table *h) { static void markall (lua_State *L, GCState *st) { - marktagmethods(G(L), st); /* mark tag methods */ markstacks(L, st); /* mark all stacks */ - marktable(st, G(L)->type2tag); - markobject(st, &G(L)->registry); - while (st->tmark) { /* mark tables */ + markudet(L, st); /* mark userdata's event tables */ + while (st->tmark) { /* traverse marked tables */ Table *h = st->tmark; /* get first table from list */ st->tmark = h->mark; /* remove it from list */ traversetable(st, h); @@ -189,7 +189,7 @@ static int hasmark (const TObject *o) { case LUA_TSTRING: return tsvalue(o)->tsv.marked; case LUA_TUSERDATA: - return ismarkedudata(uvalue(o)); + return isudmarked(uvalue(o)); case LUA_TTABLE: return ismarked(hvalue(o)); case LUA_TFUNCTION: @@ -261,8 +261,9 @@ static void collectupval (lua_State *L) { UpVal **v = &G(L)->rootupval; UpVal *curr; while ((curr = *v) != NULL) { - if (curr->mark) { - curr->mark = 0; + if (isupvalmarked(curr)) { + lua_assert(curr->v == NULL); + curr->v = &curr->value; /* unmark */ v = &curr->next; /* next */ } else { @@ -289,26 +290,27 @@ static void collecttable (lua_State *L) { } -static void collectudata (lua_State *L, int keep) { +static Udata *collectudata (lua_State *L, int keep) { Udata **p = &G(L)->rootudata; Udata *curr; + Udata *collected = NULL; while ((curr = *p) != NULL) { - if (ismarkedudata(curr)) { - switchudatamark(curr); /* unmark */ + if (isudmarked(curr)) { + unmarkud(curr); p = &curr->uv.next; } else { /* collect */ - int tag = curr->uv.tag; + const TObject *tm = fasttm(L, curr->uv.eventtable, TM_GC); *p = curr->uv.next; - if (keep || /* must keep all of them (to close state)? */ - luaT_gettm(G(L), tag, TM_GC)) { /* or is there a GC tag method? */ - curr->uv.next = G(L)->TMtable[tag].collected; /* chain udata ... */ - G(L)->TMtable[tag].collected = curr; /* ... to call its TM later */ + if (keep || tm != NULL) { + curr->uv.next = collected; + collected = curr; } - else /* no tag method; delete udata */ + else /* no gc action; delete udata */ luaM_free(L, curr, sizeudata(curr->uv.len)); } } + return collected; } @@ -347,14 +349,14 @@ static void checkMbuffer (lua_State *L) { } -static void callgcTM (lua_State *L, const TObject *obj) { - Closure *tm = luaT_gettmbyObj(G(L), obj, TM_GC); - if (tm != NULL) { +static void callgcTM (lua_State *L, Udata *udata) { + const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC); + if (tm != NULL && ttype(tm) == LUA_TFUNCTION) { int oldah = L->allowhooks; StkId top = L->top; L->allowhooks = 0; /* stop debug hooks during GC tag methods */ - setclvalue(top, tm); - setobj(top+1, obj); + setobj(top, tm); + setuvalue(top+1, udata); L->top += 2; luaD_call(L, top); L->top = top; /* restore top */ @@ -363,53 +365,52 @@ static void callgcTM (lua_State *L, const TObject *obj) { } -static void callgcTMudata (lua_State *L) { - int tag; +static void callgcTMudata (lua_State *L, Udata *c) { luaD_checkstack(L, 3); - for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */ - Udata *udata; - while ((udata = G(L)->TMtable[tag].collected) != NULL) { - G(L)->TMtable[tag].collected = udata->uv.next; /* remove it from list */ - udata->uv.next = G(L)->rootudata; /* resurect it */ - G(L)->rootudata = udata; - setuvalue(L->top, udata); - L->top++; /* keep it in stack to avoid being (recursively) collected */ - callgcTM(L, L->top-1); - uvalue(L->top-1)->uv.tag = 0; /* default tag (udata is `finalized') */ - L->top--; - } + L->top++; /* reserve space to keep udata while runs its gc method */ + while (c != NULL) { + Udata *udata = c; + c = udata->uv.next; /* remove udata from list */ + udata->uv.next = G(L)->rootudata; /* resurect it */ + G(L)->rootudata = udata; + setuvalue(L->top - 1, udata); + callgcTM(L, udata); + /* mark udata as finalized (default event table) */ + uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L)); } + L->top--; } void luaC_callallgcTM (lua_State *L) { if (G(L)->rootudata) { /* avoid problems with incomplete states */ - collectudata(L, 1); /* collect all udata into tag lists */ - callgcTMudata(L); /* call their GC tag methods */ + Udata *c = collectudata(L, 1); /* collect all udata */ + callgcTMudata(L, c); /* call their GC tag methods */ } } -void luaC_collect (lua_State *L, int all) { - collectudata(L, 0); +Udata *luaC_collect (lua_State *L, int all) { + Udata *c = collectudata(L, 0); collectstrings(L, all); collecttable(L); collectproto(L); collectupval(L); collectclosures(L); + return c; } void luaC_collectgarbage (lua_State *L) { + Udata *c; GCState st; st.tmark = NULL; st.toclear = NULL; markall(L, &st); cleartables(st.toclear); - luaC_collect(L, 0); + c = luaC_collect(L, 0); checkMbuffer(L); G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ - callgcTMudata(L); - callgcTM(L, &luaO_nilobject); + callgcTMudata(L, c); } diff --git a/lgc.h b/lgc.h index 7e1e5478..a5baebcb 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 1.11 2001/06/12 18:43:13 roberto Exp roberto $ +** $Id: lgc.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -16,7 +16,7 @@ void luaC_callallgcTM (lua_State *L); -void luaC_collect (lua_State *L, int all); +Udata *luaC_collect (lua_State *L, int all); void luaC_collectgarbage (lua_State *L); diff --git a/liolib.c b/liolib.c index 16adf983..a4f6eed5 100644 --- a/liolib.c +++ b/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 1.124 2001/10/26 17:33:30 roberto Exp $ +** $Id: liolib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -61,6 +61,7 @@ static int pushresult (lua_State *L, int i) { } + /* ** {====================================================== ** FILE Operations @@ -68,14 +69,30 @@ static int pushresult (lua_State *L, int i) { */ -#define checkfile(L,f) (strcmp(lua_type(L,(f)), FILEHANDLE) == 0) + +static int checkfile (lua_State *L, int findex, const char *tname) { + int res; + lua_geteventtable(L, findex); + lua_pushstring(L, tname); + lua_gettable(L, LUA_REGISTRYINDEX); + res = lua_equal(L, -1, -2); + lua_pop(L, 2); + return res; +} + + +/* temporary?? should be in auxlib... */ +static void *luaL_check_userdata (lua_State *L, int findex, const char *tn) { + luaL_arg_check(L, checkfile(L, findex, tn), findex, "bad file"); + return lua_touserdata(L, findex); +} static FILE *getopthandle (lua_State *L, int inout) { FILE *p = (FILE *)(lua_touserdata(L, 1)); if (p != NULL) { /* is it a userdata ? */ - if (!checkfile(L, 1)) { /* not a valid file handle? */ - if (strcmp(lua_type(L, 1), CLOSEDFILEHANDLE) == 0) + if (!checkfile(L, 1, FILEHANDLE)) { /* not a valid file handle? */ + if (checkfile(L, 1, CLOSEDFILEHANDLE)) luaL_argerror(L, 1, "file is closed"); else luaL_argerror(L, 1, "(invalid value)"); @@ -84,7 +101,7 @@ static FILE *getopthandle (lua_State *L, int inout) { } else { /* try global value */ lua_getglobal(L, filenames[inout]); - if (!checkfile(L,-1)) + if (!checkfile(L, -1, FILEHANDLE)) luaL_verror(L, "global variable `%.10s' is not a valid file handle", filenames[inout]); p = (FILE *)(lua_touserdata(L, -1)); @@ -95,7 +112,9 @@ static FILE *getopthandle (lua_State *L, int inout) { static void newfile (lua_State *L, FILE *f) { lua_newuserdatabox(L, f); - lua_settag(L, lua_name2tag(L, FILEHANDLE)); + lua_pushliteral(L, FILEHANDLE); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_seteventtable(L, -2); } @@ -130,7 +149,9 @@ static int io_close (lua_State *L) { int status = 1; if (f != stdin && f != stdout && f != stderr) { lua_settop(L, 1); /* make sure file is on top */ - lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE)); + lua_pushliteral(L, CLOSEDFILEHANDLE); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_seteventtable(L, 1); status = (CLOSEFILE(L, f) == 0); } return pushresult(L, status); @@ -301,7 +322,7 @@ static int io_read (lua_State *L) { luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments"); success = 1; for (n = 1; n<=nargs && success; n++) { - if (lua_rawtag(L, n) == LUA_TNUMBER) { + if (lua_type(L, n) == LUA_TNUMBER) { size_t l = (size_t)lua_tonumber(L, n); success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); } @@ -353,7 +374,7 @@ static int io_write (lua_State *L) { int arg; int status = 1; for (arg=1; arg<=nargs; arg++) { - if (lua_rawtag(L, arg) == LUA_TNUMBER) { + if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; @@ -514,7 +535,7 @@ static int io_time (lua_State *L) { else { time_t t; struct tm ts; - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); lua_settop(L, 1); /* make sure table is at the top */ ts.tm_sec = getfield(L, "sec", 0); ts.tm_min = getfield(L, "min", 0); @@ -677,8 +698,18 @@ static const luaL_reg iolib[] = { LUALIB_API int lua_iolibopen (lua_State *L) { - int iotag = lua_newtype(L, FILEHANDLE, LUA_TUSERDATA); - lua_newtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA); + lua_pushliteral(L, FILEHANDLE); + lua_newtable(L); /* event table for FILEHANDLE */ + /* close files when collected */ + lua_pushliteral(L, "gc"); + lua_pushcfunction(L, file_collect); + lua_settable(L, -3); + /* put new eventtable into registry */ + lua_settable(L, LUA_REGISTRYINDEX); /* registry.FILEHANDLE = eventtable */ + lua_pushliteral(L, CLOSEDFILEHANDLE); + /* event table for CLOSEDFILEHANDLE */ + lua_newtable(L); + lua_settable(L, LUA_REGISTRYINDEX); luaL_openl(L, iolib); /* predefined file handles */ newfilewithname(L, stdin, basicfiles[INFILE]); @@ -686,9 +717,6 @@ LUALIB_API int lua_iolibopen (lua_State *L) { newfilewithname(L, stderr, "_STDERR"); resetfile(L, INFILE); resetfile(L, OUTFILE); - /* close files when collected */ - lua_pushcfunction(L, file_collect); - lua_settagmethod(L, iotag, "gc"); return 0; } diff --git a/lmathlib.c b/lmathlib.c index eb05fef2..e5be054a 100644 --- a/lmathlib.c +++ b/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.38 2001/03/26 14:31:49 roberto Exp $ +** $Id: lmathlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -220,6 +220,7 @@ static const luaL_reg mathlib[] = { {"log10", math_log10}, {"exp", math_exp}, {"deg", math_deg}, +{"pow", math_pow}, {"rad", math_rad}, {"random", math_random}, {"randomseed", math_randomseed} @@ -230,8 +231,6 @@ static const luaL_reg mathlib[] = { */ LUALIB_API int lua_mathlibopen (lua_State *L) { luaL_openl(L, mathlib); - lua_pushcfunction(L, math_pow); - lua_settagmethod(L, LUA_TNUMBER, "pow"); lua_pushnumber(L, PI); lua_setglobal(L, "PI"); return 0; diff --git a/lobject.h b/lobject.h index beb6574f..bf07e3db 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 1.116 2001/11/06 21:41:53 roberto Exp $ +** $Id: lobject.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -31,15 +31,6 @@ #define NUM_TAGS 6 -/* -** extra tags: -** first is used locally when moving an upvalue from the stack to the heap; -** second prefixes upvalues in the heap -*/ -#define LUA_TUPVAL 6 -#define LUA_HEAPUPVAL 7 - - typedef union { union TString *ts; union Udata *u; @@ -122,17 +113,14 @@ typedef union TString { typedef union Udata { union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ struct { - int tag; /* negative means `marked' (only during GC) */ + struct Table *eventtable; void *value; - size_t len; + size_t len; /* least bit reserved for gc mark */ union Udata *next; /* chain for list of all udata */ } uv; } Udata; -#define switchudatamark(u) ((u)->uv.tag = (-((u)->uv.tag+1))) -#define ismarkedudata(u) ((u)->uv.tag < 0) - /* @@ -175,7 +163,6 @@ typedef struct LocVar { typedef struct UpVal { TObject *v; /* points to stack or to its own value */ - int mark; struct UpVal *next; TObject value; /* the value (when closed) */ } UpVal; @@ -227,12 +214,13 @@ typedef struct Node { typedef struct Table { + struct Table *eventtable; TObject *array; /* array part */ Node *node; - int htag; int sizearray; /* size of `array' array */ lu_byte lsizenode; /* log2 of size of `node' array */ lu_byte weakmode; + unsigned short flags; /* 1<

stacksize += LUA_MINSTACK; if (so->L != NULL) { /* shared global state? */ L->_G = G(so->L); - L->gt = so->L->gt; /* share table of globals */ so->L->next->previous = L; /* insert L into linked list */ L->next = so->L->next; so->L->next = L; L->previous = so->L; luaD_init(L, so->stacksize); /* init stack */ + setobj(defaultet(L), defaultet(so->L)); /* share default event table */ + setobj(gt(L), gt(so->L)); /* share table of globals */ + setobj(registry(L), registry(so->L)); /* share registry */ } else { /* create a new global state */ L->_G = luaM_new(L, global_State); @@ -59,17 +61,17 @@ static void f_luaopen (lua_State *L, void *ud) { G(L)->roottable = NULL; G(L)->rootudata = NULL; G(L)->rootupval = NULL; - G(L)->TMtable = NULL; - G(L)->sizeTM = 0; - G(L)->ntag = 0; G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); luaD_init(L, so->stacksize); /* init stack */ - sethvalue(&L->gt, luaH_new(L, 0, 4)); /* table of globals */ - G(L)->type2tag = luaH_new(L, 0, 3); - sethvalue(&G(L)->registry, luaH_new(L, 0, 0)); + /* create default event table with a dummy table, and then close the loop */ + sethvalue(defaultet(L), NULL); + sethvalue(defaultet(L), luaH_new(L, 0, 4)); + hvalue(defaultet(L))->eventtable = hvalue(defaultet(L)); + sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ + sethvalue(registry(L), luaH_new(L, 0, 0)); /* registry */ luaS_resize(L, 4); /* initial size of string table */ - luaX_init(L); luaT_init(L); + luaX_init(L); G(L)->GCthreshold = 4*G(L)->nblocks; } } @@ -122,7 +124,6 @@ static void close_state (lua_State *L, lua_State *OL) { lua_assert(G(L)->rootupval == NULL); lua_assert(G(L)->roottable == NULL); luaS_freeall(L); - luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char); luaM_freelem(NULL, L->_G); } diff --git a/lstate.h b/lstate.h index 981e28fe..84d3358e 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.64 2001/11/06 21:40:51 roberto Exp $ +** $Id: lstate.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Global State ** See Copyright Notice in lua.h */ @@ -7,8 +7,10 @@ #ifndef lstate_h #define lstate_h -#include "lobject.h" #include "lua.h" + +#include "lobject.h" +#include "ltm.h" #include "luadebug.h" @@ -40,7 +42,24 @@ struct lua_longjmp; /* defined in ldo.c */ -struct TM; /* defined in ltm.h */ + + + +/* +** reserve init of stack to store some global values +*/ + +/* default event table (both for tables and udata) */ +#define defaultet(L) (L->stack) + +/* table of globals */ +#define gt(L) (L->stack + 1) + +/* registry */ +#define registry(L) (L->stack + 2) + +#define RESERVED_STACK_PREFIX 3 + typedef struct stringtable { @@ -57,11 +76,6 @@ typedef struct global_State { void *Mbuffer; /* global buffer */ size_t Mbuffsize; /* size of Mbuffer */ stringtable strt; /* hash table for strings */ - Table *type2tag; /* hash table from type names to tags */ - TObject registry; /* registry table */ - struct TM *TMtable; /* table for tag methods */ - int sizeTM; /* size of TMtable */ - int ntag; /* number of tags in TMtable */ lu_mem GCthreshold; lu_mem nblocks; /* number of `bytes' currently allocated */ Proto *rootproto; /* list of all prototypes */ @@ -69,6 +83,7 @@ typedef struct global_State { Table *roottable; /* list of all tables */ Udata *rootudata; /* list of all userdata */ UpVal *rootupval; /* list of closed up values */ + TString *tmname[TM_N]; /* array with tag-method names */ } global_State; @@ -80,10 +95,9 @@ struct lua_State { StkId top; /* first free slot in the stack */ CallInfo *ci; /* call info for current function */ StkId stack_last; /* last free slot in the stack */ - TObject gt; /* table for globals */ - global_State *_G; StkId stack; /* stack base */ int stacksize; + global_State *_G; lua_Hook callhook; lua_Hook linehook; int allowhooks; diff --git a/lstring.c b/lstring.c index 5f69aafc..d12b6f0f 100644 --- a/lstring.c +++ b/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 1.67 2001/08/31 19:46:07 roberto Exp $ +** $Id: lstring.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -84,9 +84,11 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { Udata *luaS_newudata (lua_State *L, size_t s) { - Udata *u = cast(Udata *, luaM_malloc(L, sizeudata(s))); + Udata *u; + if (s & 1) s++; /* make sure size is even */ + u = cast(Udata *, luaM_malloc(L, sizeudata(s))); u->uv.len = s; - u->uv.tag = 0; + u->uv.eventtable = hvalue(defaultet(L)); u->uv.value = u + 1; /* chain it on udata list */ u->uv.next = G(L)->rootudata; diff --git a/lstrlib.c b/lstrlib.c index 8ce5e9ba..2172a09c 100644 --- a/lstrlib.c +++ b/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.73 2001/10/26 17:33:30 roberto Exp $ +** $Id: lstrlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -97,7 +97,7 @@ static int str_concat (lua_State *L) { size_t lsep; const char *sep = luaL_opt_lstr(L, 2, "", &lsep); int n, i; - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); luaL_buffinit(L, &b); n = lua_getn(L, 1); for (i=1; i<=n; i++) { diff --git a/ltable.c b/ltable.c index 61a5866d..25d62e41 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 1.88 2001/11/16 16:29:51 roberto Exp $ +** $Id: ltable.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -258,11 +258,12 @@ static void rehash (lua_State *L, Table *t) { Table *luaH_new (lua_State *L, int narray, int lnhash) { Table *t = luaM_new(L, Table); - t->htag = TagDefault; + t->eventtable = hvalue(defaultet(L)); t->next = G(L)->roottable; G(L)->roottable = t; t->mark = t; t->weakmode = 0; + t->flags = ~0; /* temporary values (kept only if some malloc fails) */ t->array = NULL; t->sizearray = 0; @@ -419,19 +420,7 @@ void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val) { if (ttype(key) == LUA_TNIL) luaD_error(L, "table index is nil"); newkey(L, t, key, val); } -} - - -void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val) { - const TObject *p = luaH_getstr(t, key); - if (p != &luaO_nilobject) { - settableval(p, val); - } - else { - TObject k; - setsvalue(&k, key); - newkey(L, t, &k, val); - } + t->flags = 0; } diff --git a/ltable.h b/ltable.h index 4d0faf55..67199ad2 100644 --- a/ltable.h +++ b/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 1.37 2001/10/25 19:14:14 roberto Exp $ +** $Id: ltable.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -20,7 +20,6 @@ const TObject *luaH_getnum (Table *t, int key); void luaH_setnum (lua_State *L, Table *t, int key, const TObject *val); const TObject *luaH_getstr (Table *t, TString *key); -void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val); const TObject *luaH_get (Table *t, const TObject *key); void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val); Table *luaH_new (lua_State *L, int narray, int lnhash); diff --git a/ltests.c b/ltests.c index e51ff23f..282c58b6 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.96 2001/11/06 21:41:43 roberto Exp $ +** $Id: ltests.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -240,13 +240,13 @@ static int mem_query (lua_State *L) { static int hash_query (lua_State *L) { if (lua_isnull(L, 2)) { - luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, "string expected"); + luaL_arg_check(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash); } else { TObject *o = luaA_index(L, 1); Table *t; - luaL_check_rawtype(L, 2, LUA_TTABLE); + luaL_check_type(L, 2, LUA_TTABLE); t = hvalue(luaA_index(L, 2)); lua_pushnumber(L, luaH_mainposition(t, o) - t->node); } @@ -257,7 +257,7 @@ static int hash_query (lua_State *L) { static int table_query (lua_State *L) { const Table *t; int i = luaL_opt_int(L, 2, -1); - luaL_check_rawtype(L, 1, LUA_TTABLE); + luaL_check_type(L, 1, LUA_TTABLE); t = hvalue(luaA_index(L, 1)); if (i == -1) { lua_pushnumber(L, t->sizearray); @@ -333,6 +333,18 @@ static int unref (lua_State *L) { return 0; } +static int eventtable (lua_State *L) { + luaL_check_any(L, 1); + if (lua_isnull(L, 2)) + lua_geteventtable(L, 1); + else { + lua_settop(L, 2); + luaL_check_type(L, 2, LUA_TTABLE); + lua_seteventtable(L, 1); + } + return 1; +} + static int newuserdata (lua_State *L) { size_t size = luaL_check_int(L, 1); char *p = cast(char *, lua_newuserdata(L, size)); @@ -345,24 +357,13 @@ static int newuserdatabox (lua_State *L) { return 1; } -static int settag (lua_State *L) { - luaL_check_any(L, 1); - lua_pushvalue(L, 1); /* push value */ - lua_settag(L, luaL_check_int(L, 2)); - return 1; /* return value */ -} static int udataval (lua_State *L) { - luaL_check_rawtype(L, 1, LUA_TUSERDATA); + luaL_check_type(L, 1, LUA_TUSERDATA); lua_pushnumber(L, cast(int, lua_touserdata(L, 1))); return 1; } -static int newtag (lua_State *L) { - lua_pushnumber(L, lua_newtype(L, lua_tostring(L, 1), - cast(int, lua_tonumber(L, 2)))); - return 1; -} static int doonnewstack (lua_State *L) { lua_State *L1 = lua_newthread(L, luaL_check_int(L, 1)); @@ -435,16 +436,6 @@ static int doremote (lua_State *L) { } } -static int settagmethod (lua_State *L) { - int tag = luaL_check_int(L, 1); - const char *event = luaL_check_string(L, 2); - luaL_check_any(L, 3); - lua_gettagmethod(L, tag, event); - lua_pushvalue(L, 3); - lua_settagmethod(L, tag, event); - return 1; -} - static int log2_aux (lua_State *L) { lua_pushnumber(L, luaO_log2(luaL_check_int(L, 1))); @@ -614,18 +605,14 @@ static int testC (lua_State *L) { else if EQ("dostring") { lua_dostring(L, luaL_check_string(L, getnum)); } - else if EQ("settagmethod") { - int tag = getnum; - const char *event = getname; - lua_settagmethod(L, tag, event); + else if EQ("seteventtable") { + lua_seteventtable(L, getnum); } - else if EQ("gettagmethod") { - int tag = getnum; - const char *event = getname; - lua_gettagmethod(L, tag, event); + else if EQ("geteventtable") { + lua_geteventtable(L, getnum); } else if EQ("type") { - lua_pushstring(L, lua_type(L, getnum)); + lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); } else luaL_verror(L, "unknown instruction %.30s", buff); } @@ -651,16 +638,14 @@ static const struct luaL_reg tests_funcs[] = { {"unref", unref}, {"d2s", d2s}, {"s2d", s2d}, + {"eventtable", eventtable}, {"newuserdata", newuserdata}, {"newuserdatabox", newuserdatabox}, - {"settag", settag}, {"udataval", udataval}, - {"newtag", newtag}, {"doonnewstack", doonnewstack}, {"newstate", newstate}, {"closestate", closestate}, {"doremote", doremote}, - {"settagmethod", settagmethod}, {"log2", log2_aux}, {"totalmem", mem_query} }; diff --git a/ltm.c b/ltm.c index ef0f89e1..5d1c83d1 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 1.80 2001/10/11 21:41:21 roberto Exp $ +** $Id: ltm.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -10,8 +10,6 @@ #include "lua.h" -#include "ldo.h" -#include "lmem.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" @@ -19,161 +17,46 @@ #include "ltm.h" -const char *const luaT_eventname[] = { /* ORDER TM */ - "gettable", "settable", "index", "getglobal", - "setglobal", "add", "sub", "mul", "div", - "pow", "unm", "lt", "concat", "gc", - "function", - NULL + +const char *const luaT_typenames[] = { + "userdata", "nil", "number", "string", "table", "function" }; -static int findevent (const char *name) { - int i; - for (i=0; luaT_eventname[i]; i++) - if (strcmp(luaT_eventname[i], name) == 0) - return i; - return -1; /* name not found */ -} - - -static int luaI_checkevent (lua_State *L, const char *name) { - int e = findevent(name); - if (e < 0) - luaO_verror(L, "`%.50s' is not a valid event name", name); - return e; -} - - - -/* events in LUA_TNIL are all allowed, since this is used as a -* `placeholder' for default fallbacks -*/ -/* ORDER LUA_T, ORDER TM */ -static const lu_byte luaT_validevents[NUM_TAGS][TM_N] = { - {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */ - {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */ - {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_TSTRING */ - {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TTABLE */ - {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} /* LUA_TFUNCTION */ -}; - -static int luaT_validevent (int t, int e) { /* ORDER LUA_T */ - return (t >= NUM_TAGS) ? 1 : cast(int, luaT_validevents[t][e]); -} - - void luaT_init (lua_State *L) { - static const char *const typenames[NUM_TAGS] = { - "userdata", "nil", "number", "string", - "table", "function" + static const char *const luaT_eventname[] = { /* ORDER TM */ + "gettable", "settable", "index", + "gc", + "add", "sub", "mul", "div", + "pow", "unm", "lt", "concat", + "call" }; int i; - for (i=0; iTMtable, G(L)->ntag, G(L)->sizeTM, struct TM, - MAX_INT, "tag table overflow"); - tag = G(L)->ntag; - if (name) { - const TObject *v; - TObject otag; - ts = luaS_new(L, name); - v = luaH_getstr(G(L)->type2tag, ts); - if (ttype(v) == LUA_TNUMBER) return cast(int, nvalue(v)); - setnvalue(&otag, tag); - luaH_setstr(L, G(L)->type2tag, ts, &otag); - } - for (i=0; iTMtable[tag].collected = NULL; - G(L)->TMtable[tag].name = ts; - G(L)->TMtable[tag].basictype = basictype; - G(L)->ntag++; - return tag; -} - - -static void checktag (lua_State *L, int tag) { - if (!(0 <= tag && tag < G(L)->ntag)) - luaO_verror(L, "%d is not a valid tag", tag); -} - - -int luaT_tag (const TObject *o) { - int t = ttype(o); - switch (t) { - case LUA_TUSERDATA: return uvalue(o)->uv.tag; - case LUA_TTABLE: return hvalue(o)->htag; - default: return t; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + G(L)->tmname[i]->tsv.marked = FIXMARK; /* never collect these names */ } } -const char *luaT_typename (global_State *G, const TObject *o) { - int t = ttype(o); - int tag; - TString *ts; - switch (t) { - case LUA_TUSERDATA: - tag = uvalue(o)->uv.tag; - break; +const TObject *luaT_gettm (Table *events, TMS event, TString *ename) { + const TObject *tm = luaH_getstr(events, ename); + if (ttype(tm) == LUA_TNIL) { /* no tag method? */ + events->flags |= (1<htag; - break; + return fasttm(L, hvalue(o)->eventtable, event); + case LUA_TUSERDATA: + return fasttm(L, uvalue(o)->uv.eventtable, event); default: - tag = t; + return NULL; } - ts = G->TMtable[tag].name; - if (ts == NULL) - ts = G->TMtable[t].name; - return getstr(ts); -} - - -LUA_API void lua_gettagmethod (lua_State *L, int t, const char *event) { - int e; - lua_lock(L); - e = luaI_checkevent(L, event); - checktag(L, t); - if (luaT_validevent(t, e) && luaT_gettm(G(L), t, e)) { - setclvalue(L->top, luaT_gettm(G(L), t, e)); - } - else - setnilvalue(L->top); - incr_top; - lua_unlock(L); -} - - -LUA_API void lua_settagmethod (lua_State *L, int t, const char *event) { - int e; - lua_lock(L); - e = luaI_checkevent(L, event); - checktag(L, t); - if (!luaT_validevent(t, e)) - luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s", - luaT_eventname[e], typenamebytag(G(L), t), - (t == LUA_TTABLE || t == LUA_TUSERDATA) ? - " with default tag" : ""); - switch (ttype(L->top - 1)) { - case LUA_TNIL: - luaT_gettm(G(L), t, e) = NULL; - break; - case LUA_TFUNCTION: - luaT_gettm(G(L), t, e) = clvalue(L->top - 1); - break; - default: - luaD_error(L, "tag method must be a function (or nil)"); - } - L->top--; - lua_unlock(L); } diff --git a/ltm.h b/ltm.h index 797dd9a6..053b6f90 100644 --- a/ltm.h +++ b/ltm.h @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 1.28 2001/10/02 16:43:54 roberto Exp $ +** $Id: ltm.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -9,7 +9,6 @@ #include "lobject.h" -#include "lstate.h" /* * WARNING: if you change the order of this enumeration, @@ -19,8 +18,7 @@ typedef enum { TM_GETTABLE = 0, TM_SETTABLE, TM_INDEX, - TM_GETGLOBAL, - TM_SETGLOBAL, + TM_GC, TM_ADD, TM_SUB, TM_MUL, @@ -29,51 +27,20 @@ typedef enum { TM_UNM, TM_LT, TM_CONCAT, - TM_GC, - TM_FUNCTION, + TM_CALL, TM_N /* number of elements in the enum */ } TMS; -/* -** masks for allowable tag methods -** (see `luaT_validevents') -*/ -#define HAS_TM_GETGLOBAL(L,t) ((1<<(t)) & ((1<TMtable[tag].method[event]) -#define luaT_gettmbyObj(G,o,e) (luaT_gettm((G),luaT_tag(o),(e))) - -#define typenamebytag(G, t) getstr(G->TMtable[t].name) - - -#define validtag(G,t) (NUM_TAGS <= (t) && (t) < G->ntag) - -extern const char *const luaT_eventname[]; +#define fasttm(l,et,e) \ + (((et)->flags & (1<<(e))) ? NULL : luaT_gettm(et, e, G(l)->tmname[e])) +const TObject *luaT_gettm (Table *events, TMS event, TString *ename); +const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event); void luaT_init (lua_State *L); -int luaT_newtag (lua_State *L, const char *name, int basictype); -const char *luaT_typename (global_State *G, const TObject *o); -int luaT_tag (const TObject *o); +extern const char *const luaT_typenames[]; #endif diff --git a/lua.h b/lua.h index 52179b84..5c63a770 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.107 2001/10/31 19:58:11 roberto Exp $ +** $Id: lua.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua - An Extensible Extension Language ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil ** e-mail: info@lua.org @@ -55,15 +55,11 @@ typedef struct lua_State lua_State; typedef int (*lua_CFunction) (lua_State *L); -/* -** an invalid `tag' -*/ -#define LUA_NOTAG (-1) /* -** tags for basic types +** basic types */ -#define LUA_TNONE LUA_NOTAG +#define LUA_TNONE (-1) #define LUA_TUSERDATA 0 #define LUA_TNIL 1 @@ -120,12 +116,11 @@ LUA_API int lua_stackspace (lua_State *L); ** access functions (stack -> C) */ -LUA_API const char *lua_type (lua_State *L, int index); LUA_API int lua_isnumber (lua_State *L, int index); LUA_API int lua_isstring (lua_State *L, int index); LUA_API int lua_iscfunction (lua_State *L, int index); -LUA_API int lua_tag (lua_State *L, int index); -LUA_API int lua_rawtag (lua_State *L, int index); +LUA_API int lua_type (lua_State *L, int index); +LUA_API const char *lua_typename (lua_State *L, int type); LUA_API int lua_equal (lua_State *L, int index1, int index2); LUA_API int lua_lessthan (lua_State *L, int index1, int index2); @@ -155,9 +150,9 @@ LUA_API void lua_getglobal (lua_State *L, const char *name); LUA_API void lua_gettable (lua_State *L, int index); LUA_API void lua_rawget (lua_State *L, int index); LUA_API void lua_rawgeti (lua_State *L, int index, int n); -LUA_API void lua_gettagmethod (lua_State *L, int tag, const char *event); LUA_API void lua_newtable (lua_State *L); LUA_API void lua_getweakregistry (lua_State *L); +LUA_API void lua_geteventtable (lua_State *L, int objindex); /* @@ -168,7 +163,7 @@ LUA_API void lua_settable (lua_State *L, int index); LUA_API void lua_rawset (lua_State *L, int index); LUA_API void lua_rawseti (lua_State *L, int index, int n); LUA_API void lua_setglobals (lua_State *L); -LUA_API void lua_settagmethod (lua_State *L, int tag, const char *event); +LUA_API void lua_seteventtable (lua_State *L, int objindex); /* @@ -194,11 +189,6 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); /* ** miscellaneous functions */ -LUA_API int lua_newtype (lua_State *L, const char *name, int basictype); -LUA_API void lua_settag (lua_State *L, int tag); - -LUA_API int lua_name2tag (lua_State *L, const char *name); -LUA_API const char *lua_tag2name (lua_State *L, int tag); LUA_API void lua_error (lua_State *L, const char *s); @@ -228,11 +218,11 @@ LUA_API int lua_getweakmode (lua_State *L, int index); #define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) #define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) -#define lua_isfunction(L,n) (lua_rawtag(L,n) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_rawtag(L,n) == LUA_TTABLE) -#define lua_isuserdata(L,n) (lua_rawtag(L,n) == LUA_TUSERDATA) -#define lua_isnil(L,n) (lua_rawtag(L,n) == LUA_TNIL) -#define lua_isnull(L,n) (lua_rawtag(L,n) == LUA_TNONE) +#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) +#define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) +#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) +#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) #define lua_pushliteral(L, s) lua_pushlstring(L, "" s, \ (sizeof(s)/sizeof(char))-1) @@ -245,8 +235,6 @@ LUA_API int lua_getweakmode (lua_State *L, int index); /* ** compatibility macros and functions */ -#define lua_newtag(L) lua_newtype(L, NULL, LUA_TNONE) -#define lua_typename lua_tag2name LUA_API void lua_pushupvalues (lua_State *L); diff --git a/lvm.c b/lvm.c index c4281e44..ea1ba100 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.198 2001/11/06 21:41:53 roberto Exp $ +** $Id: lvm.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -85,69 +85,66 @@ static void traceexec (lua_State *L, lua_Hook linehook) { /* maximum stack used by a call to a tag method (func + args) */ #define MAXSTACK_TM 4 -static StkId callTM (lua_State *L, Closure *f, const char *fmt, ...) { - va_list argp; +static void callTM (lua_State *L, const TObject *f, + const TObject *p1, const TObject *p2, const TObject *p3, TObject *result ) { StkId base = L->top; - lua_assert(strlen(fmt)+1 <= MAXSTACK_TM); luaD_checkstack(L, MAXSTACK_TM); - va_start(argp, fmt); - setclvalue(L->top, f); /* push function */ - L->top++; - while (*fmt) { - if (*fmt++ == 'o') { - setobj(L->top, va_arg(argp, TObject *)); - } - else { - lua_assert(*(fmt-1) == 's'); - setsvalue(L->top, va_arg(argp, TString *)); - } + setobj(base, f); /* push function */ + setobj(base+1, p1); /* 1st argument */ + setobj(base+2, p2); /* 2nd argument */ + L->top += 3; + if (p3) { + setobj(base+3, p3); /* 3th argument */ L->top++; } luaD_call(L, base); - va_end(argp); - return base; -} - - -#define setTM(L, base) (L->top = (base)) - -static void setTMresult (lua_State *L, TObject *result, StkId base) { - if (L->top == base) { /* are there valid results? */ - setnilvalue(result); /* function had no results */ - } - else { - setobj(result, base); /* get first result */ + if (result) { /* need a result? */ + if (L->top == base) { /* are there valid results? */ + setnilvalue(result); /* function had no results */ + } + else { + setobj(result, base); /* get first result */ + } } L->top = base; /* restore top */ } + /* ** Function to index a table. ** Receives the table at `t' and the key at the `key'. ** leaves the result at `res'. */ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { - Closure *tm; + const TObject *tm; + init: if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ - int tg = hvalue(t)->htag; - if (tg == LUA_TTABLE || /* with default tag? */ - (tm = luaT_gettm(G(L), tg, TM_GETTABLE)) == NULL) { /* or no TM? */ + Table *et = hvalue(t)->eventtable; + if ((tm = fasttm(L, et, TM_GETTABLE)) == NULL) { /* no gettable TM? */ const TObject *h = luaH_get(hvalue(t), key); /* do a primitive get */ /* result is no nil or there is no `index' tag method? */ if (ttype(h) != LUA_TNIL || /* no nil? */ - ((tm=luaT_gettm(G(L), tg, TM_INDEX)) == NULL)) { /* or no index TM? */ + (tm = fasttm(L, et, TM_INDEX)) == NULL) { /* or no index TM? */ setobj(res, h); /* default get */ return; } } /* else will call the tag method */ } else { /* not a table; try a `gettable' tag method */ - tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); - if (tm == NULL) /* no tag method? */ + if (ttype(t) != LUA_TUSERDATA || + (tm = fasttm(L, uvalue(t)->uv.eventtable, TM_GETTABLE)) == NULL) { luaG_typeerror(L, t, "index"); + return; /* to avoid warnings */ + } + } + lua_assert(tm != NULL); + if (ttype(tm) == LUA_TFUNCTION) + callTM(L, tm, t, key, NULL, res); + else { + t = tm; + goto init; /* return luaV_gettable(L, tm, key, res); */ } - setTMresult(L, res, callTM(L, tm, "oo", t, key)); } @@ -156,63 +153,44 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { ** Receives table at `t', key at `key' and value at `val'. */ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { - Closure *tm; + const TObject *tm; + init: if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ - int tg = hvalue(t)->htag; - if (hvalue(t)->htag == LUA_TTABLE || /* with default tag? */ - (tm = luaT_gettm(G(L), tg, TM_SETTABLE)) == NULL) { /* or no TM? */ + Table *et = hvalue(t)->eventtable; + if ((tm = fasttm(L, et, TM_SETTABLE)) == NULL) { /* no TM? */ luaH_set(L, hvalue(t), key, val); /* do a primitive set */ return; } /* else will call the tag method */ } else { /* not a table; try a `settable' tag method */ - tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); - if (tm == NULL) /* no tag method? */ + if (ttype(t) != LUA_TUSERDATA || + (tm = fasttm(L, uvalue(t)->uv.eventtable, TM_SETTABLE)) == NULL) { luaG_typeerror(L, t, "index"); + return; /* to avoid warnings */ + } } - setTM(L, callTM(L, tm, "ooo", t, key, val)); -} - - -void luaV_getglobal (lua_State *L, TString *name, StkId res) { - const TObject *value = luaH_getstr(hvalue(&L->gt), name); - Closure *tm; - if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ - (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { - setobj(res, value); /* default behavior */ + lua_assert(tm != NULL); + if (ttype(tm) == LUA_TFUNCTION) + callTM(L, tm, t, key, val, NULL); + else { + t = tm; + goto init; /* luaV_settable(L, tm, key, val); */ } - else - setTMresult(L, res, callTM(L, tm, "so", name, value)); -} - - -void luaV_setglobal (lua_State *L, TString *name, StkId val) { - const TObject *oldvalue = luaH_getstr(hvalue(&L->gt), name); - Closure *tm; - if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ - (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { - if (oldvalue == &luaO_nilobject) - luaH_setstr(L, hvalue(&L->gt), name, val); /* raw set */ - else - settableval(oldvalue, val); /* warning: tricky optimization! */ - } - else - setTM(L, callTM(L, tm, "soo", name, oldvalue, val)); } static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, TObject *res, TMS event) { - Closure *tm = luaT_gettmbyObj(G(L), p1, event); /* try first operand */ + const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ if (tm == NULL) { - tm = luaT_gettmbyObj(G(L), p2, event); /* try second operand */ + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ if (tm == NULL) { - tm = luaT_gettm(G(L), 0, event); /* try a `global' method */ - if (tm == NULL) - return 0; /* no tag method */ + tm = fasttm(L, hvalue(gt(L)), event); + if (tm == NULL) return 0; /* no tag method */ } } - setTMresult(L, res, callTM(L, tm, "oo", p1, p2)); + if (ttype(tm) != LUA_TFUNCTION) return 0; + callTM(L, tm, p1, p2, NULL, res); return 1; } @@ -295,12 +273,13 @@ void luaV_strconc (lua_State *L, int total, StkId top) { static void luaV_pack (lua_State *L, StkId firstelem) { int i; Table *htab = luaH_new(L, 0, 0); - TObject n; + TObject n, nname; for (i=0; firstelem+itop; i++) luaH_setnum(L, htab, i+1, firstelem+i); /* store counter in field `n' */ setnvalue(&n, i); - luaH_setstr(L, htab, luaS_newliteral(L, "n"), &n); + setsvalue(&nname, luaS_newliteral(L, "n")); + luaH_set(L, htab, &nname, &n); L->top = firstelem; /* remove elements from the stack */ sethvalue(L->top, htab); incr_top; @@ -395,7 +374,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { } case OP_GETGLOBAL: { lua_assert(ttype(KBc(i)) == LUA_TSTRING); - luaV_getglobal(L, tsvalue(KBc(i)), ra); + luaV_gettable(L, gt(L), KBc(i), ra); break; } case OP_GETTABLE: { @@ -404,7 +383,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { } case OP_SETGLOBAL: { lua_assert(ttype(KBc(i)) == LUA_TSTRING); - luaV_setglobal(L, tsvalue(KBc(i)), ra); + luaV_settable(L, gt(L), KBc(i), ra); break; } case OP_SETUPVAL: { diff --git a/lvm.h b/lvm.h index a9378de1..1e0369fc 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 1.31 2001/09/07 17:39:10 roberto Exp $ +** $Id: lvm.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -20,8 +20,6 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n); int luaV_tostring (lua_State *L, TObject *obj); void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res); void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val); -void luaV_getglobal (lua_State *L, TString *s, StkId res); -void luaV_setglobal (lua_State *L, TString *s, StkId val); StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base); int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); void luaV_strconc (lua_State *L, int total, StkId top);