tag system replaced by event tables

This commit is contained in:
Roberto Ierusalimschy 2001-12-05 18:15:18 -02:00
parent 413fc7334b
commit 592a309177
24 changed files with 417 additions and 711 deletions

150
lapi.c
View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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},

View File

@ -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; e<TM_N; e++) {
int t;
for (t=0; t<G->ntag; 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

21
ldo.c
View File

@ -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;

View File

@ -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;
}
}

121
lgc.c
View File

@ -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; i<cl->l.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; o<L1->top; 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; t<G->ntag; t++) {
struct TM *tm = &G->TMtable[t];
int e;
if (tm->name) strmark(tm->name);
for (e=0; e<TM_N; e++) {
Closure *cl = tm->method[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);
}

4
lgc.h
View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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<<p means tagmethod(p) is not present */
Node *firstfree; /* this position is free; all positions after it are full */
struct Table *next;
struct Table *mark; /* marked tables (point to itself when not marked) */

View File

@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 1.72 2001/11/06 21:40:51 roberto Exp $
** $Id: lstate.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
** Global State
** See Copyright Notice in lua.h
*/
@ -40,12 +40,14 @@ static void f_luaopen (lua_State *L, void *ud) {
so->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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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++) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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}
};

175
ltm.c
View File

@ -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; i<NUM_TAGS; i++)
luaT_newtag(L, typenames[i], i);
}
int luaT_newtag (lua_State *L, const char *name, int basictype) {
int tag;
int i;
TString *ts = NULL;
luaM_growvector(L, G(L)->TMtable, 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; i<TM_N; i++)
luaT_gettm(G(L), tag, i) = NULL;
G(L)->TMtable[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; i<TM_N; i++) {
G(L)->tmname[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<<event); /* cache this fact */
return NULL;
}
else return tm;
}
const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event) {
switch (ttype(o)) {
case LUA_TTABLE:
tag = hvalue(o)->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);
}

49
ltm.h
View File

@ -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<<LUA_TUSERDATA) | \
(1<<LUA_TTABLE) | \
(1<<LUA_TNIL)))
#define HAS_TM_SETGLOBAL(L,t) ((1<<(t)) & ((1<<LUA_TUSERDATA) | \
(1<<LUA_TTABLE) | \
(1<<LUA_TNIL) | \
(1<<LUA_TFUNCTION)))
struct TM {
Closure *method[TM_N];
Udata *collected; /* list of garbage-collected udata with this tag */
TString *name; /* type name */
int basictype;
};
#define luaT_gettm(G,tag,event) (G->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

36
lua.h
View File

@ -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);

137
lvm.c
View File

@ -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+i<L->top; 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: {

4
lvm.h
View File

@ -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);