lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 1444d28476af70bc51c4fdba71deb669f41c77a3
parent 2de803c250de373186afbbea0a5978f54c52850c
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Wed, 19 Mar 1997 16:40:50 -0300

first full implementation of internal methods

Diffstat:
Mfallback.c | 369++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mfallback.h | 37+++++++++++++++++++------------------
Mhash.c | 9++++-----
Mhash.h | 3++-
Minout.c | 4+++-
Mlua.h | 20+++++++-------------
Mopcode.c | 161+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mopcode.h | 22++++++++++++----------
Mtable.c | 4+++-
Mtree.c | 23++++++++++++++++++++++-
Mtree.h | 3++-
11 files changed, 404 insertions(+), 251 deletions(-)

diff --git a/fallback.c b/fallback.c @@ -3,11 +3,12 @@ ** TecCGraf - PUC-Rio */ -char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable roberto $"; +char *rcs_fallback="$Id: fallback.c,v 1.27 1997/03/11 18:44:28 roberto Exp roberto $"; #include <stdio.h> #include <string.h> +#include "auxlib.h" #include "mem.h" #include "fallback.h" #include "opcode.h" @@ -17,105 +18,6 @@ char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable #include "hash.h" -static void errorFB (void); -static void indexFB (void); -static void gettableFB (void); -static void arithFB (void); -static void concatFB (void); -static void orderFB (void); -static void GDFB (void); -static void funcFB (void); - - -/* -** Warning: This list must be in the same order as the #define's -*/ -struct FB luaI_fallBacks[] = { -{"gettable", {LUA_T_CFUNCTION, {gettableFB}}, 2, 1}, -{"arith", {LUA_T_CFUNCTION, {arithFB}}, 3, 1}, -{"order", {LUA_T_CFUNCTION, {orderFB}}, 3, 1}, -{"concat", {LUA_T_CFUNCTION, {concatFB}}, 2, 1}, -{"settable", {LUA_T_CFUNCTION, {gettableFB}}, 3, 0}, -{"gc", {LUA_T_CFUNCTION, {GDFB}}, 1, 0}, -{"function", {LUA_T_CFUNCTION, {funcFB}}, -1, -1}, - /* no fixed number of params or results */ -{"getglobal", {LUA_T_CFUNCTION, {indexFB}}, 1, 1}, - /* same default behavior of index FB */ -{"index", {LUA_T_CFUNCTION, {indexFB}}, 2, 1}, -{"error", {LUA_T_CFUNCTION, {errorFB}}, 1, 0} -}; - -#define N_FB (sizeof(luaI_fallBacks)/sizeof(struct FB)) - -static int luaI_findevent (char *name) -{ - int i; - for (i=0; i<N_FB; i++) - if (strcmp(luaI_fallBacks[i].kind, name) == 0) - return i; - /* name not found */ - lua_error("invalid event name"); - return 0; /* to avoid warnings */ -} - - -void luaI_setfallback (void) -{ - int i; - char *name = lua_getstring(lua_getparam(1)); - lua_Object func = lua_getparam(2); - if (name == NULL || !lua_isfunction(func)) - lua_error("incorrect argument to function `setfallback'"); - i = luaI_findevent(name); - luaI_pushobject(&luaI_fallBacks[i].function); - luaI_fallBacks[i].function = *luaI_Address(func); -} - - -static void errorFB (void) -{ - lua_Object o = lua_getparam(1); - if (lua_isstring(o)) - fprintf (stderr, "lua: %s\n", lua_getstring(o)); - else - fprintf(stderr, "lua: unknown error\n"); -} - - -static void indexFB (void) -{ - lua_pushnil(); -} - - -static void gettableFB (void) -{ - lua_error("indexed expression not a table"); -} - - -static void arithFB (void) -{ - lua_error("unexpected type at conversion to number"); -} - -static void concatFB (void) -{ - lua_error("unexpected type at conversion to string"); -} - - -static void orderFB (void) -{ - lua_error("unexpected type at comparison"); -} - -static void GDFB (void) { } - -static void funcFB (void) -{ - lua_error("call expression not a function"); -} /* ------------------------------------------- @@ -187,50 +89,127 @@ void luaI_invalidaterefs (void) refArray[i].status = COLLECTED; } -char *luaI_travfallbacks (int (*fn)(Object *)) + +/* ------------------------------------------- +* Internal Methods +*/ + +char *eventname[] = { + "gettable", /* IM_GETTABLE */ + "arith", /* IM_ARITH */ + "order", /* IM_ORDER */ + "concat", /* IM_CONCAT */ + "settable", /* IM_SETTABLE */ + "gc", /* IM_GC */ + "function", /* IM_FUNCTION */ + "index", /* IM_INDEX */ + NULL +}; + + +char *geventname[] = { + "error", /* GIM_ERROR */ + "getglobal", /* GIM_GETGLOBAL */ + "setglobal", /* GIM_SETGLOBAL */ + NULL +}; + +static int luaI_findevent (char *name, char *list[]) { int i; - for (i=0; i<N_FB; i++) - if (fn(&luaI_fallBacks[i].function)) - return luaI_fallBacks[i].kind; - return NULL; + for (i=0; list[i]; i++) + if (strcmp(list[i], name) == 0) + return i; + /* name not found */ + return -1; } +static int luaI_checkevent (char *name, char *list[]) +{ + int e = luaI_findevent(name, list); + if (e < 0) + lua_error("invalid event name"); + return e; +} -/* ------------------------------------------- -* Internal Methods -*/ -#define BASE_TAG 1000 static struct IM { lua_Type tp; - Object int_method[FB_N]; - } *luaI_IMtable = NULL; + Object int_method[IM_N]; +} *luaI_IMtable = NULL; + static int IMtable_size = 0; -static int last_tag = BASE_TAG-1; +static int last_tag = LUA_T_NIL; + +static struct { + lua_Type t; + int event; +} exceptions[] = { /* list of events that cannot be modified */ + {LUA_T_NUMBER, IM_ARITH}, + {LUA_T_NUMBER, IM_ORDER}, + {LUA_T_NUMBER, IM_GC}, + {LUA_T_STRING, IM_ARITH}, + {LUA_T_STRING, IM_ORDER}, + {LUA_T_STRING, IM_CONCAT}, + {LUA_T_STRING, IM_GC}, + {LUA_T_ARRAY, IM_GETTABLE}, + {LUA_T_ARRAY, IM_SETTABLE}, + {LUA_T_FUNCTION, IM_FUNCTION}, + {LUA_T_FUNCTION, IM_GC}, + {LUA_T_CFUNCTION, IM_FUNCTION}, + {LUA_T_CFUNCTION, IM_GC}, + {LUA_T_NIL, 0} /* flag end of list */ +}; -int lua_newtag (char *t) + +static int validevent (int t, int event) +{ + int i; + if (t == LUA_T_NIL) /* cannot modify any event for nil */ + return 0; + for (i=0; exceptions[i].t != LUA_T_NIL; i++) + if (exceptions[i].t == t && exceptions[i].event == event) + return 0; + return 1; +} + +static void init_entry (int tag) { int i; - ++last_tag; - if ((last_tag-BASE_TAG) >= IMtable_size) + for (i=0; i<IM_N; i++) + luaI_IMtable[-tag].int_method[i].ttype = LUA_T_NIL; +} + +void luaI_initfallbacks (void) +{ + int i; + IMtable_size = NUM_TYPES+10; + luaI_IMtable = newvector(IMtable_size, struct IM); + for (i=LUA_T_NIL; i<=LUA_T_USERDATA; i++) { + luaI_IMtable[-i].tp = (lua_Type)i; + init_entry(i); + } +} + +int lua_newtag (char *t) +{ + --last_tag; + if ((-last_tag) >= IMtable_size) IMtable_size = growvector(&luaI_IMtable, IMtable_size, struct IM, memEM, MAX_INT); if (strcmp(t, "table") == 0) - luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_ARRAY; + luaI_IMtable[-last_tag].tp = LUA_T_ARRAY; else if (strcmp(t, "userdata") == 0) - luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_USERDATA; + luaI_IMtable[-last_tag].tp = LUA_T_USERDATA; else lua_error("invalid type for new tag"); - for (i=0; i<FB_N; i++) - luaI_IMtable[last_tag-BASE_TAG].int_method[i].ttype = LUA_T_NIL; + init_entry(last_tag); return last_tag; } -static int validtag (int tag) -{ - return (BASE_TAG <= tag && tag <= last_tag); -} + +#define validtag(tag) (last_tag <= (tag) && (tag) <= 0) + static void checktag (int tag) { @@ -238,10 +217,18 @@ static void checktag (int tag) lua_error("invalid tag"); } +lua_Type luaI_typetag (int tag) +{ + if (tag >= 0) return LUA_T_USERDATA; + else { + checktag(tag); + return luaI_IMtable[-tag].tp; + } +} + void luaI_settag (int tag, Object *o) { - checktag(tag); - if (ttype(o) != luaI_IMtable[tag-BASE_TAG].tp) + if (ttype(o) != luaI_typetag(tag)) lua_error("Tag is not compatible with this type"); if (o->ttype == LUA_T_ARRAY) o->value.a->htag = tag; @@ -261,29 +248,123 @@ int luaI_tag (Object *o) Object *luaI_getim (int tag, int event) { - if (tag == 0) - return &luaI_fallBacks[event].function; - else if (validtag(tag)) { - Object *func = &luaI_IMtable[tag-BASE_TAG].int_method[event]; - if (func->ttype == LUA_T_NIL) - return NULL; - else - return func; - } - else return NULL; + if (tag > LUA_T_USERDATA) + tag = LUA_T_USERDATA; /* default for non-registered tags */ + return &luaI_IMtable[-tag].int_method[event]; +} + +Object *luaI_getimbyObj (Object *o, int event) +{ + return luaI_getim(luaI_tag(o), event); } void luaI_setintmethod (void) { - lua_Object tag = lua_getparam(1); - lua_Object event = lua_getparam(2); + int t = (int)luaL_check_number(1, "setintmethod"); + int e = luaI_checkevent(luaL_check_string(2, "setintmethod"), eventname); lua_Object func = lua_getparam(3); - if (!(lua_isnumber(tag) && lua_isstring(event) && lua_isfunction(func))) - lua_error("incorrect arguments to function `setintmethod'"); - else { - int i = luaI_findevent(lua_getstring(event)); - int t = lua_getnumber(tag); - checktag(t); - luaI_IMtable[t-BASE_TAG].int_method[i] = *luaI_Address(func); + if (!validevent(t, e)) + lua_error("cannot change this internal method"); + luaL_arg_check(lua_isnil(func) || lua_isfunction(func), "setintmethod", + 3, "function expected"); + checktag(t); + luaI_IMtable[-t].int_method[e] = *luaI_Address(func); +} + +static Object gmethod[GIM_N] = { + {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}} +}; + +Object *luaI_getgim (int event) +{ + return &gmethod[event]; +} + +void luaI_setglobalmethod (void) +{ + int e = luaI_checkevent(luaL_check_string(1, "setintmethod"), geventname); + lua_Object func = lua_getparam(2); + luaL_arg_check(lua_isnil(func) || lua_isfunction(func), "setintmethod", + 2, "function expected"); + gmethod[e] = *luaI_Address(func); +} + +char *luaI_travfallbacks (int (*fn)(Object *)) +{ /* ?????????? + int i; + for (i=0; i<N_FB; i++) + if (fn(&luaI_fallBacks[i].function)) + return luaI_fallBacks[i].kind; */ + return NULL; +} + + +/* +* =================================================================== +* compatibility with old fallback system +*/ + + +static void errorFB (void) +{ + lua_Object o = lua_getparam(1); + if (lua_isstring(o)) + fprintf (stderr, "lua: %s\n", lua_getstring(o)); + else + fprintf(stderr, "lua: unknown error\n"); +} + + +static void nilFB (void) { } + + +static void typeFB (void) +{ + lua_error("unexpected type"); +} + + +void luaI_setfallback (void) +{ + int e; + char *name = luaL_check_string(1, "setfallback"); + lua_Object func = lua_getparam(2); + luaL_arg_check(lua_isfunction(func), "setfallback", 2, "function expected"); + e = luaI_findevent(name, geventname); + if (e >= 0) { /* global event */ + switch (e) { + case GIM_ERROR: + gmethod[e] = *luaI_Address(func); + lua_pushcfunction(errorFB); + break; + case GIM_GETGLOBAL: /* goes through */ + case GIM_SETGLOBAL: + gmethod[e] = *luaI_Address(func); + lua_pushcfunction(nilFB); + break; + default: lua_error("internal error"); + } + } + else { /* tagged name? */ + int t; + Object oldfunc; + e = luaI_checkevent(name, eventname); + oldfunc = luaI_IMtable[LUA_T_USERDATA].int_method[e]; + for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++) + if (validevent(t, e)) + luaI_IMtable[-t].int_method[e] = *luaI_Address(func); + if (oldfunc.ttype != LUA_T_NIL) + luaI_pushobject(&oldfunc); + else { + switch (e) { + case IM_GC: case IM_INDEX: + lua_pushcfunction(nilFB); + break; + default: + lua_pushcfunction(typeFB); + break; + } + } } } + diff --git a/fallback.h b/fallback.h @@ -1,5 +1,5 @@ /* -** $Id: fallback.h,v 1.13 1996/04/25 14:10:00 roberto Exp roberto $ +** $Id: fallback.h,v 1.14 1997/02/26 17:38:41 roberto Unstable roberto $ */ #ifndef fallback_h @@ -8,24 +8,20 @@ #include "lua.h" #include "opcode.h" -extern struct FB { - char *kind; - Object function; - int nParams; - int nResults; -} luaI_fallBacks[]; +#define IM_GETTABLE 0 +#define IM_ARITH 1 +#define IM_ORDER 2 +#define IM_CONCAT 3 +#define IM_SETTABLE 4 +#define IM_GC 5 +#define IM_FUNCTION 6 +#define IM_INDEX 7 +#define IM_N 8 -#define FB_GETTABLE 0 -#define FB_ARITH 1 -#define FB_ORDER 2 -#define FB_CONCAT 3 -#define FB_SETTABLE 4 -#define FB_GC 5 -#define FB_FUNCTION 6 -#define FB_GETGLOBAL 7 -#define FB_INDEX 8 -#define FB_ERROR 9 -#define FB_N 10 +#define GIM_ERROR 0 +#define GIM_GETGLOBAL 1 +#define GIM_SETGLOBAL 2 +#define GIM_N 3 void luaI_setfallback (void); int luaI_ref (Object *object, int lock); @@ -35,9 +31,14 @@ void luaI_invalidaterefs (void); char *luaI_travfallbacks (int (*fn)(Object *)); void luaI_settag (int tag, Object *o); +lua_Type luaI_typetag (int tag); Object *luaI_getim (int tag, int event); +Object *luaI_getgim (int event); +Object *luaI_getimbyObj (Object *o, int event); int luaI_tag (Object *o); void luaI_setintmethod (void); +void luaI_setglobalmethod (void); +void luaI_initfallbacks (void); #endif diff --git a/hash.c b/hash.c @@ -3,7 +3,7 @@ ** hash manager for lua */ -char *rcs_hash="$Id: hash.c,v 2.34 1997/02/26 17:38:41 roberto Unstable roberto $"; +char *rcs_hash="$Id: hash.c,v 2.35 1997/03/11 18:44:28 roberto Exp roberto $"; #include "mem.h" @@ -159,7 +159,7 @@ void lua_hashmark (Hash *h) } -static void call_fallbacks (void) +void luaI_hashcallIM (void) { Hash *curr_array; Object t; @@ -168,10 +168,10 @@ static void call_fallbacks (void) if (markarray(curr_array) != 1) { avalue(&t) = curr_array; - luaI_gcFB(&t); + luaI_gcIM(&t); } ttype(&t) = LUA_T_NIL; - luaI_gcFB(&t); /* end of list */ + luaI_gcIM(&t); /* end of list */ } @@ -183,7 +183,6 @@ Long lua_hashcollector (void) { Hash *curr_array = listhead, *prev = NULL; Long counter = 0; - call_fallbacks(); while (curr_array != NULL) { Hash *next = curr_array->next; diff --git a/hash.h b/hash.h @@ -1,7 +1,7 @@ /* ** hash.h ** hash manager for lua -** $Id: hash.h,v 2.12 1996/05/06 14:30:27 roberto Exp roberto $ +** $Id: hash.h,v 2.13 1997/02/26 17:38:41 roberto Unstable roberto $ */ #ifndef hash_h @@ -30,6 +30,7 @@ int luaI_redimension (int nhash); Hash *lua_createarray (int nhash); void lua_hashmark (Hash *h); Long lua_hashcollector (void); +void luaI_hashcallIM (void); Object *lua_hashget (Hash *t, Object *ref); Object *lua_hashdefine (Hash *t, Object *ref); void lua_next (void); diff --git a/inout.c b/inout.c @@ -5,11 +5,12 @@ ** Also provides some predefined lua functions. */ -char *rcs_inout="$Id: inout.c,v 2.45 1997/03/11 18:44:28 roberto Exp roberto $"; +char *rcs_inout="$Id: inout.c,v 2.46 1997/03/17 17:01:10 roberto Exp roberto $"; #include <stdio.h> #include <string.h> +#include "auxlib.h" #include "lex.h" #include "opcode.h" #include "inout.h" @@ -322,6 +323,7 @@ static struct { {"print", luaI_print}, {"setfallback", luaI_setfallback}, {"setintmethod", luaI_setintmethod}, + {"setglobalmethod", luaI_setglobalmethod}, {"setglobal", luaI_setglobal}, {"tonumber", lua_obj2number}, {"tostring", luaI_tostring}, diff --git a/lua.h b/lua.h @@ -2,7 +2,7 @@ ** LUA - Linguagem para Usuarios de Aplicacao ** Grupo de Tecnologia em Computacao Grafica ** TeCGraf - PUC-Rio -** $Id: lua.h,v 3.35 1997/02/26 17:38:41 roberto Unstable roberto $ +** $Id: lua.h,v 3.36 1997/03/17 17:01:10 roberto Exp roberto $ */ @@ -21,6 +21,7 @@ typedef unsigned int lua_Object; lua_Object lua_setfallback (char *event, lua_CFunction fallback); void lua_setintmethod (int tag, char *event, lua_CFunction method); +void lua_setglobalmethod (char *event, lua_CFunction method); int lua_newtag (char *t); void lua_settag (int tag); /* In: object */ @@ -36,8 +37,9 @@ int lua_call (char *funcname); void lua_beginblock (void); void lua_endblock (void); -lua_Object lua_getparam (int number); -#define lua_getresult(_) lua_getparam(_) +lua_Object lua_lua2C (int number); +#define lua_getparam(_) lua_lua2C(_) +#define lua_getresult(_) lua_lua2C(_) int lua_isnil (lua_Object object); int lua_istable (lua_Object object); @@ -62,7 +64,9 @@ void lua_pushusertag (void *u, int tag); void lua_pushobject (lua_Object object); lua_Object lua_getglobal (char *name); +lua_Object lua_basicgetglobal (char *name); void lua_storeglobal (char *name); /* In: value */ +void lua_basicstoreglobal (char *name); /* In: value */ void lua_storesubscript (void); /* In: table, index, value */ void lua_basicstoreindex (void); /* In: table, index, value */ @@ -91,16 +95,6 @@ lua_Object lua_createtable (void); /* =============================================================== */ -/* Auxiliar functions for libraries */ - -void luaL_arg_check(int cond, char *funcname, int numarg, char *extramsg); -char *luaL_check_string (int numArg, char *funcname); -char *luaL_opt_string (int numArg, char *def, char *funcname); -double luaL_check_number (int numArg, char *funcname); -double luaL_opt_number (int numArg, double def, char *funcname); - - -/* =============================================================== */ /* for compatibility with old versions. Avoid using these macros */ #define lua_type(o) (lua_tag(o)) diff --git a/opcode.c b/opcode.c @@ -3,7 +3,7 @@ ** TecCGraf - PUC-Rio */ -char *rcs_opcode="$Id: opcode.c,v 3.83 1997/03/06 17:30:55 roberto Exp roberto $"; +char *rcs_opcode="$Id: opcode.c,v 3.84 1997/03/11 18:44:28 roberto Exp roberto $"; #include <setjmp.h> #include <stdio.h> @@ -268,15 +268,6 @@ static void callIM (Object *f, int nParams, int nResults) do_call((top-stack)-nParams, nResults); } -/* -** Call the specified fallback, putting it on the stack below its arguments -*/ -static void callFB (int fb) -{ - callIM(&luaI_fallBacks[fb].function, luaI_fallBacks[fb].nParams, - luaI_fallBacks[fb].nResults); -} - /* ** Call a function (C or Lua). The parameters must be on the stack, @@ -289,21 +280,21 @@ static void do_call (StkId base, int nResults) StkId firstResult; Object *func = stack+base-1; int i; - if (ttype(func) == LUA_T_CFUNCTION) - { + if (ttype(func) == LUA_T_CFUNCTION) { ttype(func) = LUA_T_CMARK; firstResult = callC(fvalue(func), base); } - else if (ttype(func) == LUA_T_FUNCTION) - { + else if (ttype(func) == LUA_T_FUNCTION) { ttype(func) = LUA_T_MARK; firstResult = lua_execute(func->value.tf->code, base); } - else - { /* func is not a function */ - /* Call the fallback for invalid functions */ + else { /* func is not a function */ + /* Check the fallback for invalid functions */ + Object *im = luaI_getimbyObj(func, IM_FUNCTION); + if (ttype(im) == LUA_T_NIL) + lua_error("call expression not a function"); open_stack((top-stack)-(base-1)); - stack[base-1] = luaI_fallBacks[FB_FUNCTION].function; + stack[base-1] = *im; do_call(base, nResults); return; } @@ -326,15 +317,14 @@ static void do_call (StkId base, int nResults) static void pushsubscript (void) { int tg = luaI_tag(top-2); - Object *im = luaI_getim(tg, FB_GETTABLE); - if (ttype(top-2) == LUA_T_ARRAY && im == NULL) { + Object *im = luaI_getim(tg, IM_GETTABLE); + if (ttype(top-2) == LUA_T_ARRAY && ttype(im) == LUA_T_NIL) { Object *h = lua_hashget(avalue(top-2), top-1); if (h != NULL && ttype(h) != LUA_T_NIL) { --top; *(top-1) = *h; } - else if (tg == LUA_T_ARRAY && - (im=luaI_getim(0, FB_INDEX)) != NULL) + else if (ttype(im=luaI_getim(tg, IM_INDEX)) != LUA_T_NIL) callIM(im, 2, 1); else { --top; @@ -376,14 +366,14 @@ lua_Object lua_basicindex (void) */ static void storesubscript (Object *t, int mode) { - Object *im = (mode == 0) ? NULL : luaI_getim(luaI_tag(t), FB_SETTABLE); - if (ttype(t) == LUA_T_ARRAY && im == NULL) { + Object *im = (mode == 0) ? NULL : luaI_getimbyObj(t, IM_SETTABLE); + if (ttype(t) == LUA_T_ARRAY && (im == NULL || ttype(im) == LUA_T_NIL)) { Object *h = lua_hashdefine(avalue(t), t+1); *h = *(top-1); top -= (mode == 2) ? 1 : 3; } else { /* object is not a table, and/or has a specific "settable" method */ - if (im) { + if (im && ttype(im) != LUA_T_NIL) { if (mode == 2) { lua_checkstack(top+2); *(top+1) = *(top-1); @@ -403,11 +393,13 @@ static void getglobal (Word n) { *top = lua_table[n].object; incr_top; - if (ttype(top-1) == LUA_T_NIL) - { /* must call getglobal fallback */ - ttype(top-1) = LUA_T_STRING; - tsvalue(top-1) = lua_table[n].varname; - callFB(FB_GETGLOBAL); + if (ttype(top-1) == LUA_T_NIL) { /* check i.m. */ + Object *im = luaI_getgim(GIM_GETGLOBAL); + if (ttype(im) != LUA_T_NIL) { + ttype(top-1) = LUA_T_STRING; + tsvalue(top-1) = lua_table[n].varname; + callIM(im, 1, 1); + } } } @@ -428,8 +420,13 @@ void lua_travstack (int (*fn)(Object *)) static void lua_message (char *s) { - lua_pushstring(s); - callFB(FB_ERROR); + Object *im = luaI_getgim(GIM_ERROR); + if (ttype(im) == LUA_T_NIL) + fprintf(stderr, "lua: %s\n", s); + else { + lua_pushstring(s); + callIM(im, 1, 0); + } } /* @@ -659,10 +656,20 @@ void lua_setintmethod (int tag, char *event, lua_CFunction method) { lua_pushnumber(tag); lua_pushstring(event); - lua_pushcfunction (method); + if (method) + lua_pushcfunction (method); + else + lua_pushnil(); do_unprotectedrun(luaI_setintmethod, 3, 0); } +void lua_setglobalmethod (char *event, lua_CFunction method) +{ + lua_pushstring(event); + lua_pushcfunction (method); + do_unprotectedrun(luaI_setglobalmethod, 3, 0); +} + /* ** API: receives on the stack the table and the index. @@ -741,7 +748,7 @@ lua_Object lua_createtable (void) ** Get a parameter, returning the object handle or LUA_NOOBJECT on error. ** 'number' must be 1 to get the first parameter. */ -lua_Object lua_getparam (int number) +lua_Object lua_lua2C (int number) { if (number <= 0 || number > CLS_current.num) return LUA_NOOBJECT; /* Ref(stack+(CLS_current.base-CLS_current.num+number-1)) == @@ -874,6 +881,17 @@ lua_Object lua_getglobal (char *name) return Ref(top-1); } + +lua_Object lua_basicgetglobal (char *name) +{ + adjustC(0); + *top = lua_table[luaI_findsymbolbyname(name)].object; + incr_top; + CLS_current.base++; /* incorporate object in the stack */ + return Ref(top-1); +} + + /* ** Store top of the stack at a global variable array field. */ @@ -944,7 +962,7 @@ void lua_pushbinarydata (void *buff, int size, int tag) */ void lua_pushusertag (void *u, int tag) { - if (tag < LUA_T_USERDATA) + if (luaI_typetag(tag) != LUA_T_USERDATA) lua_error("invalid tag in `lua_pushusertag'"); lua_pushbinarydata(&u, sizeof(void *), tag); } @@ -977,18 +995,47 @@ int lua_tag (lua_Object o) } -void luaI_gcFB (Object *o) +void luaI_gcIM (Object *o) { - *top = *o; - incr_top; - callFB(FB_GC); + Object *im = luaI_getimbyObj(o, IM_GC); + if (ttype(im) != LUA_T_NIL) { + *top = *o; + incr_top; + callIM(im, 1, 0); + } } static void call_arith (char *op) { + Object *im = luaI_getimbyObj(top-2, IM_ARITH); /* try first operand */ + if (ttype(im) == LUA_T_NIL) { + im = luaI_getimbyObj(top-1, IM_ARITH); /* try second operand */ + if (ttype(im) == LUA_T_NIL) { + im = luaI_getim(0, IM_ARITH); /* try a 'global' i.m. */ + if (ttype(im) == LUA_T_NIL) + lua_error("unexpected type at conversion to number"); + } + } lua_pushstring(op); - callFB(FB_ARITH); + callIM(im, 3, 1); +} + +static void concim (Object *o) +{ + Object *im = luaI_getimbyObj(o, IM_CONCAT); + if (ttype(im) == LUA_T_NIL) + lua_error("unexpected type at conversion to string"); + callIM(im, 2, 1); +} + +static void ordim (Object *o, char *op) +{ + Object *im = luaI_getimbyObj(o, IM_ORDER); + if (ttype(im) == LUA_T_NIL) + lua_error("unexpected type at comparison"); + lua_pushstring(op); + callIM(im, 3, 1); } static void comparison (lua_Type ttype_less, lua_Type ttype_equal, @@ -999,10 +1046,12 @@ static void comparison (lua_Type ttype_less, lua_Type ttype_equal, int result; if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER) result = (nvalue(l) < nvalue(r)) ? -1 : (nvalue(l) == nvalue(r)) ? 0 : 1; - else if (tostring(l) || tostring(r)) - { - lua_pushstring(op); - callFB(FB_ORDER); + else if (tostring(l)) { + ordim(l, op); + return; + } + else if (tostring(r)) { + ordim(r, op); return; } else @@ -1318,17 +1367,17 @@ static StkId lua_execute (Byte *pc, StkId base) call_arith("pow"); break; - case CONCOP: - { - Object *l = top-2; - Object *r = top-1; - if (tostring(r) || tostring(l)) - callFB(FB_CONCAT); - else - { - tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); - --top; - } + case CONCOP: { + Object *l = top-2; + Object *r = top-1; + if (tostring(l)) /* first argument is not a string */ + concim(l); + else if (tostring(r)) /* second argument is not a string */ + concim(r); + else { + tsvalue(l) = lua_createstring(lua_strconc(svalue(l),svalue(r))); + --top; + } } break; @@ -1356,7 +1405,7 @@ static StkId lua_execute (Byte *pc, StkId base) } break; - case ONFJMP: + case ONFJMP: { Word w; get_word(w,pc); diff --git a/opcode.h b/opcode.h @@ -1,6 +1,6 @@ /* ** TeCGraf - PUC-Rio -** $Id: opcode.h,v 3.27 1997/03/06 17:30:55 roberto Exp roberto $ +** $Id: opcode.h,v 3.28 1997/03/11 18:44:28 roberto Exp roberto $ */ #ifndef opcode_h @@ -16,18 +16,20 @@ typedef enum { - LUA_T_NIL = -1, - LUA_T_NUMBER = -2, - LUA_T_STRING = -3, - LUA_T_ARRAY = -4, /* array==table */ + LUA_T_NIL = -9, + LUA_T_NUMBER = -8, + LUA_T_STRING = -7, + LUA_T_ARRAY = -6, /* array==table */ LUA_T_FUNCTION = -5, - LUA_T_CFUNCTION= -6, - LUA_T_MARK = -7, - LUA_T_CMARK = -8, - LUA_T_LINE = -9, + LUA_T_CFUNCTION= -4, + LUA_T_MARK = -3, + LUA_T_CMARK = -2, + LUA_T_LINE = -1, LUA_T_USERDATA = 0 } lua_Type; +#define NUM_TYPES 10 + typedef enum { /* name parm before after side effect @@ -156,7 +158,7 @@ void luaI_codedebugline (int line); /* from "lua.stx" module */ void lua_travstack (int (*fn)(Object *)); Object *luaI_Address (lua_Object o); void luaI_pushobject (Object *o); -void luaI_gcFB (Object *o); +void luaI_gcIM (Object *o); int luaI_dorun (TFunc *tf); #endif diff --git a/table.c b/table.c @@ -3,7 +3,7 @@ ** Module to control static tables */ -char *rcs_table="$Id: table.c,v 2.59 1997/02/26 17:38:41 roberto Unstable roberto $"; +char *rcs_table="$Id: table.c,v 2.60 1997/03/11 18:44:28 roberto Exp roberto $"; #include "mem.h" #include "opcode.h" @@ -168,6 +168,8 @@ Long luaI_collectgarbage (void) lua_travsymbol(lua_markobject); /* mark symbol table objects */ luaI_travlock(lua_markobject); /* mark locked objects */ luaI_travfallbacks(lua_markobject); /* mark fallbacks */ + luaI_hashcallIM(); + luaI_strcallIM(); luaI_invalidaterefs(); recovered += lua_strcollector(); recovered += lua_hashcollector(); diff --git a/tree.c b/tree.c @@ -3,7 +3,7 @@ ** TecCGraf - PUC-Rio */ -char *rcs_tree="$Id: tree.c,v 1.20 1996/03/14 15:56:26 roberto Exp roberto $"; +char *rcs_tree="$Id: tree.c,v 1.21 1997/02/11 11:35:05 roberto Exp roberto $"; #include <string.h> @@ -14,6 +14,7 @@ char *rcs_tree="$Id: tree.c,v 1.20 1996/03/14 15:56:26 roberto Exp roberto $"; #include "lex.h" #include "hash.h" #include "table.h" +#include "fallback.h" #define NUM_HASHS 64 @@ -45,6 +46,7 @@ static void initialize (void) luaI_addReserved(); luaI_initsymbol(); luaI_initconstant(); + luaI_initfallbacks(); } @@ -120,6 +122,25 @@ TaggedString *lua_createstring (char *str) } +void luaI_strcallIM (void) +{ + int i; + Object o; + ttype(&o) = LUA_T_USERDATA; + for (i=0; i<NUM_HASHS; i++) { + stringtable *tb = &string_root[i]; + int j; + for (j=0; j<tb->size; j++) { + TaggedString *t = tb->hash[j]; + if (t != NULL && t->tag != LUA_T_STRING && t->marked == 0) { + tsvalue(&o) = t; + luaI_gcIM(&o); + } + } + } +} + + /* ** Garbage collection function. ** This function traverse the string list freeing unindexed strings diff --git a/tree.h b/tree.h @@ -1,7 +1,7 @@ /* ** tree.h ** TecCGraf - PUC-Rio -** $Id: tree.h,v 1.14 1996/02/26 17:07:49 roberto Exp roberto $ +** $Id: tree.h,v 1.15 1997/02/11 11:35:05 roberto Exp roberto $ */ #ifndef tree_h @@ -27,5 +27,6 @@ typedef struct TaggedString TaggedString *lua_createstring (char *str); TaggedString *luaI_createuserdata (char *buff, long size, int tag); Long lua_strcollector (void); +void luaI_strcallIM (void); #endif