summaryrefslogtreecommitdiff
path: root/src/fallback.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fallback.c')
-rw-r--r--src/fallback.c395
1 files changed, 286 insertions, 109 deletions
diff --git a/src/fallback.c b/src/fallback.c
index 5718f5c1..5a0b5a5b 100644
--- a/src/fallback.c
+++ b/src/fallback.c
@@ -3,130 +3,37 @@
** TecCGraf - PUC-Rio
*/
-char *rcs_fallback="$Id: fallback.c,v 1.25 1996/04/25 14:10:00 roberto Exp $";
+char *rcs_fallback="$Id: fallback.c,v 2.9 1997/06/23 18:27:53 roberto Exp $";
#include <stdio.h>
#include <string.h>
-#include "mem.h"
+#include "auxlib.h"
+#include "luamem.h"
#include "fallback.h"
#include "opcode.h"
#include "lua.h"
#include "table.h"
+#include "tree.h"
+#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[] = {
-{"error", {LUA_T_CFUNCTION, {errorFB}}, 1, 0},
-{"index", {LUA_T_CFUNCTION, {indexFB}}, 2, 1},
-{"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 */
-};
-
-#define N_FB (sizeof(luaI_fallBacks)/sizeof(struct FB))
-
-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'");
- for (i=0; i<N_FB; i++)
- {
- if (strcmp(luaI_fallBacks[i].kind, name) == 0)
- {
- luaI_pushobject(&luaI_fallBacks[i].function);
- luaI_fallBacks[i].function = *luaI_Address(func);
- return;
- }
- }
- /* name not found */
- lua_error("incorrect argument to function `setfallback'");
-}
-
-
-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");
-}
-
-
-/*
+/* -------------------------------------------
** Reference routines
*/
static struct ref {
- Object o;
+ TObject o;
enum {LOCK, HOLD, FREE, COLLECTED} status;
} *refArray = NULL;
static int refSize = 0;
-int luaI_ref (Object *object, int lock)
+int luaI_ref (TObject *object, int lock)
{
int i;
int oldSize;
- if (tag(object) == LUA_T_NIL)
+ if (ttype(object) == LUA_T_NIL)
return -1; /* special ref for nil */
for (i=0; i<refSize; i++)
if (refArray[i].status == FREE)
@@ -151,9 +58,9 @@ void lua_unref (int ref)
}
-Object *luaI_getref (int ref)
+TObject *luaI_getref (int ref)
{
- static Object nul = {LUA_T_NIL, {0}};
+ static TObject nul = {LUA_T_NIL, {0}};
if (ref == -1)
return &nul;
if (ref >= 0 && ref < refSize &&
@@ -164,7 +71,7 @@ Object *luaI_getref (int ref)
}
-void luaI_travlock (int (*fn)(Object *))
+void luaI_travlock (int (*fn)(TObject *))
{
int i;
for (i=0; i<refSize; i++)
@@ -181,11 +88,281 @@ void luaI_invalidaterefs (void)
refArray[i].status = COLLECTED;
}
-char *luaI_travfallbacks (int (*fn)(Object *))
+
+/* -------------------------------------------
+* Internal Methods
+*/
+
+char *luaI_eventname[] = { /* ORDER IM */
+ "gettable", "settable", "index", "getglobal", "setglobal", "add",
+ "sub", "mul", "div", "pow", "unm", "lt", "le", "gt", "ge",
+ "concat", "gc", "function",
+ NULL
+};
+
+
+
+static int luaI_checkevent (char *name, char *list[])
+{
+ int e = luaI_findstring(name, list);
+ if (e < 0)
+ luaL_verror("`%s' is not a valid event name", name);
+ return e;
+}
+
+
+struct IM *luaI_IMtable = NULL;
+
+static int IMtable_size = 0;
+static int last_tag = LUA_T_NIL; /* ORDER LUA_T */
+
+
+/* events in LUA_T_LINE are all allowed, since this is used as a
+* 'placeholder' for "default" fallbacks
+*/
+static char validevents[NUM_TYPES][IM_N] = { /* ORDER LUA_T, ORDER IM */
+{1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_USERDATA */
+{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_LINE */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_CMARK */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_MARK */
+{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CFUNCTION */
+{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_FUNCTION */
+{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_ARRAY */
+{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */
+{1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_NUMBER */
+{1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} /* LUA_T_NIL */
+};
+
+static int validevent (lua_Type t, int e)
+{ /* ORDER LUA_T */
+ return (t < LUA_T_NIL) ? 1 : validevents[-t][e];
+}
+
+
+static void init_entry (int tag)
{
int i;
- for (i=0; i<N_FB; i++)
- if (fn(&luaI_fallBacks[i].function))
- return luaI_fallBacks[i].kind;
+ for (i=0; i<IM_N; i++)
+ ttype(luaI_getim(tag, i)) = LUA_T_NIL;
+}
+
+void luaI_initfallbacks (void)
+{
+ if (luaI_IMtable == NULL) {
+ int i;
+ IMtable_size = NUM_TYPES+10;
+ luaI_IMtable = newvector(IMtable_size, struct IM);
+ for (i=LUA_T_NIL; i<=LUA_T_USERDATA; i++)
+ init_entry(i);
+ }
+}
+
+int lua_newtag (void)
+{
+ --last_tag;
+ if ((-last_tag) >= IMtable_size) {
+ luaI_initfallbacks();
+ IMtable_size = growvector(&luaI_IMtable, IMtable_size,
+ struct IM, memEM, MAX_INT);
+ }
+ init_entry(last_tag);
+ return last_tag;
+}
+
+
+static void checktag (int tag)
+{
+ if (!(last_tag <= tag && tag <= 0))
+ luaL_verror("%d is not a valid tag", tag);
+}
+
+void luaI_realtag (int tag)
+{
+ if (!(last_tag <= tag && tag < LUA_T_NIL))
+ luaL_verror("tag %d is not result of `newtag'", tag);
+}
+
+
+void luaI_settag (int tag, TObject *o)
+{
+ luaI_realtag(tag);
+ switch (ttype(o)) {
+ case LUA_T_ARRAY:
+ o->value.a->htag = tag;
+ break;
+ case LUA_T_USERDATA:
+ o->value.ts->tag = tag;
+ break;
+ default:
+ luaL_verror("cannot change the tag of a %s", luaI_typenames[-ttype(o)]);
+ }
+}
+
+
+int luaI_efectivetag (TObject *o)
+{
+ lua_Type t = ttype(o);
+ if (t == LUA_T_USERDATA) {
+ int tag = o->value.ts->tag;
+ return (tag >= 0) ? LUA_T_USERDATA : tag;
+ }
+ else if (t == LUA_T_ARRAY)
+ return o->value.a->htag;
+ else return t;
+}
+
+
+void luaI_gettagmethod (void)
+{
+ int t = (int)luaL_check_number(1);
+ int e = luaI_checkevent(luaL_check_string(2), luaI_eventname);
+ checktag(t);
+ if (validevent(t, e))
+ luaI_pushobject(luaI_getim(t,e));
+}
+
+
+void luaI_settagmethod (void)
+{
+ int t = (int)luaL_check_number(1);
+ int e = luaI_checkevent(luaL_check_string(2), luaI_eventname);
+ lua_Object func = lua_getparam(3);
+ checktag(t);
+ if (!validevent(t, e))
+ luaL_verror("cannot change internal method `%s' for tag %d",
+ luaI_eventname[e], t);
+ luaL_arg_check(lua_isnil(func) || lua_isfunction(func),
+ 3, "function expected");
+ luaI_pushobject(luaI_getim(t,e));
+ *luaI_getim(t, e) = *luaI_Address(func);
+}
+
+
+static void stderrorim (void)
+{
+ lua_Object s = lua_getparam(1);
+ if (lua_isstring(s))
+ fprintf(stderr, "lua: %s\n", lua_getstring(s));
+}
+
+static TObject errorim = {LUA_T_CFUNCTION, {stderrorim}};
+
+
+TObject *luaI_geterrorim (void)
+{
+ return &errorim;
+}
+
+void luaI_seterrormethod (void)
+{
+ lua_Object func = lua_getparam(1);
+ luaL_arg_check(lua_isnil(func) || lua_isfunction(func),
+ 1, "function expected");
+ luaI_pushobject(&errorim);
+ errorim = *luaI_Address(func);
+}
+
+char *luaI_travfallbacks (int (*fn)(TObject *))
+{
+ int e;
+ if (fn(&errorim))
+ return "error";
+ for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { /* ORDER IM */
+ int t;
+ for (t=0; t>=last_tag; t--)
+ if (fn(luaI_getim(t,e)))
+ return luaI_eventname[e];
+ }
return NULL;
}
+
+
+/*
+* ===================================================================
+* compatibility with old fallback system
+*/
+#if LUA_COMPAT2_5
+
+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");
+}
+
+
+static void fillvalids (IMS e, TObject *func)
+{
+ int t;
+ for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++)
+ if (validevent(t, e))
+ *luaI_getim(t, e) = *func;
+}
+
+
+void luaI_setfallback (void)
+{
+ static char *oldnames [] = {"error", "getglobal", "arith", "order", NULL};
+ TObject oldfunc;
+ lua_CFunction replace;
+ char *name = luaL_check_string(1);
+ lua_Object func = lua_getparam(2);
+ luaI_initfallbacks();
+ luaL_arg_check(lua_isfunction(func), 2, "function expected");
+ switch (luaI_findstring(name, oldnames)) {
+ case 0: /* old error fallback */
+ oldfunc = errorim;
+ errorim = *luaI_Address(func);
+ replace = errorFB;
+ break;
+ case 1: /* old getglobal fallback */
+ oldfunc = *luaI_getim(LUA_T_NIL, IM_GETGLOBAL);
+ *luaI_getim(LUA_T_NIL, IM_GETGLOBAL) = *luaI_Address(func);
+ replace = nilFB;
+ break;
+ case 2: { /* old arith fallback */
+ int i;
+ oldfunc = *luaI_getim(LUA_T_NUMBER, IM_POW);
+ for (i=IM_ADD; i<=IM_UNM; i++) /* ORDER IM */
+ fillvalids(i, luaI_Address(func));
+ replace = typeFB;
+ break;
+ }
+ case 3: { /* old order fallback */
+ int i;
+ oldfunc = *luaI_getim(LUA_T_LINE, IM_LT);
+ for (i=IM_LT; i<=IM_GE; i++) /* ORDER IM */
+ fillvalids(i, luaI_Address(func));
+ replace = typeFB;
+ break;
+ }
+ default: {
+ int e;
+ if ((e = luaI_findstring(name, luaI_eventname)) >= 0) {
+ oldfunc = *luaI_getim(LUA_T_LINE, e);
+ fillvalids(e, luaI_Address(func));
+ replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB;
+ }
+ else {
+ luaL_verror("`%s' is not a valid fallback name", name);
+ replace = NULL; /* to avoid warnings */
+ }
+ }
+ }
+ if (oldfunc.ttype != LUA_T_NIL)
+ luaI_pushobject(&oldfunc);
+ else
+ lua_pushcfunction(replace);
+}
+#endif