From 9ffba7a3dbdfa68595cd8cec26bd99689ce5fd08 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 7 Nov 1994 13:20:56 -0200 Subject: first implementation of 'fallbacks' --- opcode.c | 317 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 202 insertions(+), 115 deletions(-) diff --git a/opcode.c b/opcode.c index 298b172f..1c79e535 100644 --- a/opcode.c +++ b/opcode.c @@ -3,7 +3,7 @@ ** TecCGraf - PUC-Rio */ -char *rcs_opcode="$Id: opcode.c,v 3.1 1994/11/02 20:30:53 roberto Exp roberto $"; +char *rcs_opcode="$Id: opcode.c,v 3.2 1994/11/04 10:47:49 roberto Exp roberto $"; #include #include @@ -19,6 +19,7 @@ char *rcs_opcode="$Id: opcode.c,v 3.1 1994/11/02 20:30:53 roberto Exp roberto $" #include "inout.h" #include "table.h" #include "lua.h" +#include "fallback.h" #define tonumber(o) ((tag(o) != LUA_T_NUMBER) && (lua_tonumber(o) != 0)) #define tostring(o) ((tag(o) != LUA_T_STRING) && (lua_tostring(o) != 0)) @@ -26,9 +27,9 @@ char *rcs_opcode="$Id: opcode.c,v 3.1 1994/11/02 20:30:53 roberto Exp roberto $" #define STACK_BUFFER (STACKGAP+128) -static Long maxstack; -static Object *stack=NULL; -static Object *top; +static Long maxstack = 0L; +static Object *stack = NULL; +static Object *top = NULL; static int CBase = 0; /* when Lua calls C or C calls Lua, points to the */ @@ -40,11 +41,69 @@ static jmp_buf *errorJmp = NULL; /* current error recover point */ static int lua_execute (Byte *pc, int base); +static void do_call (Object *func, int base, int nResults, int whereRes); +/* +** Fallbacks +*/ + +static struct FB { + char *kind; + Object function; +} fallBacks[] = { +#define FB_ERROR 0 +{"error", {LUA_T_CFUNCTION, luaI_errorFB}}, +#define FB_INDEX 1 +{"index", {LUA_T_CFUNCTION, luaI_indexFB}}, +#define FB_GETTABLE 2 +{"gettable", {LUA_T_CFUNCTION, luaI_gettableFB}}, +#define FB_ARITH 3 +{"arith", {LUA_T_CFUNCTION, luaI_arithFB}}, +#define FB_ORDER 4 +{"order", {LUA_T_CFUNCTION, luaI_orderFB}}, +#define FB_CONCAT 5 +{"concat", {LUA_T_CFUNCTION, luaI_concatFB}}, +#define FB_UNMINUS 6 +{"unminus", {LUA_T_CFUNCTION, luaI_arithFB}}, +#define FB_SETTABLE 7 +{"settable", {LUA_T_CFUNCTION, luaI_gettableFB}} +}; + +#define N_FB (sizeof(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_iscfunction(func))) + { + lua_pushnil(); + return; + } + for (i=0; i maxstack) { - int t = top-stack; + int t; + if (stack == NULL) + lua_initstack(); + t = top-stack; maxstack *= 2; stack = (Object *)realloc(stack, maxstack*sizeof(Object)); if (stack == NULL) @@ -101,11 +161,22 @@ static void lua_checkstack (Word n) */ static char *lua_strconc (char *l, char *r) { - static char buffer[1024]; + static char *buffer = NULL; + static int buffer_size = 0; int n = strlen(l)+strlen(r)+1; - if (n > 1024) - lua_error ("string too large"); - return strcat(strcpy(buffer,l),r); + if (n > buffer_size) + { + buffer_size = n; + if (buffer != NULL) + free(buffer); + buffer = (char *)malloc(buffer_size); + if (buffer == NULL) + { + buffer_size = 0; + lua_error("concat - not enough memory"); + } + } + return strcat(strcpy(buffer,l),r); } @@ -138,11 +209,11 @@ static int lua_tostring (Object *obj) { static char s[256]; if (tag(obj) != LUA_T_NUMBER) - lua_reportbug ("unexpected type at conversion to string"); + return 1; if ((int) nvalue(obj) == nvalue(obj)) - sprintf (s, "%d", (int) nvalue(obj)); + sprintf (s, "%d", (int) nvalue(obj)); else - sprintf (s, "%g", nvalue(obj)); + sprintf (s, "%g", nvalue(obj)); svalue(obj) = lua_createstring(s); if (svalue(obj) == NULL) return 1; @@ -217,32 +288,35 @@ static void do_call (Object *func, int base, int nResults, int whereRes) */ static void pushsubscript (void) { - Object *h; if (tag(top-2) != LUA_T_ARRAY) - lua_reportbug ("indexed expression not a table"); - h = lua_hashget (avalue(top-2), top-1); - --top; - *(top-1) = *h; + do_call(&fallBacks[FB_GETTABLE].function, (top-stack)-2, 1, (top-stack)-2); + else + { + Object *h = lua_hashget(avalue(top-2), top-1); + if (h == NULL) + do_call(&fallBacks[FB_INDEX].function, (top-stack)-2, 1, (top-stack)-2); + else + { + --top; + *(top-1) = *h; + } + } } /* ** Function to store indexed based on values at the top */ -int lua_storesubscript (void) +static void storesubscript (void) { if (tag(top-3) != LUA_T_ARRAY) - { - lua_reportbug ("indexed expression not a table"); - return 1; - } + do_call(&fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); + else { Object *h = lua_hashdefine (avalue(top-3), top-2); - if (h == NULL) return 1; *h = *(top-1); + top -= 3; } - top -= 3; - return 0; } @@ -273,10 +347,12 @@ static int do_protectedrun (Object *function, int nResults) { if (function == NULL) { + tag(&f) = LUA_T_FUNCTION; + bvalue(&f) = lua_parse(); function = &f; - tag(function) = LUA_T_FUNCTION; - bvalue(function) = lua_parse(); } + else + tag(&f) = LUA_T_NIL; do_call(function, CBase, nResults, CBase); CnResults = (top-stack) - CBase; /* number of results */ CBase += CnResults; /* incorporate results on the stack */ @@ -288,6 +364,8 @@ static int do_protectedrun (Object *function, int nResults) top = stack+CBase; status = 1; } + if (tag(&f) == LUA_T_FUNCTION) + free(bvalue(&f)); errorJmp = oldErr; return status; } @@ -401,16 +479,6 @@ void *lua_getuserdata (Object *object) else return (uvalue(object)); } -/* -** Given an object handle, return its table. On error, return NULL. -*/ -void *lua_gettable (Object *object) -{ - if (object == NULL) return NULL; - if (tag(object) != LUA_T_ARRAY) return NULL; - else return (avalue(object)); -} - /* ** Get a global object. Return the object handle or NULL on error. */ @@ -472,16 +540,6 @@ int lua_pushuserdata (void *u) return 0; } -/* -** Push an object (tag=userdata) to stack. Return 0 on success or 1 on error. -*/ -int lua_pushtable (void *t) -{ - lua_checkstack(top-stack+1); - tag(top) = LUA_T_ARRAY; avalue(top++) = t; - return 0; -} - /* ** Push an object to stack. */ @@ -557,6 +615,35 @@ int lua_type (lua_Object o) } +static void call_arith (char *op) +{ + lua_pushstring(op); + do_call(&fallBacks[FB_ARITH].function, (top-stack)-3, 1, (top-stack)-3); +} + +static void comparison (lua_Type tag_less, lua_Type tag_equal, + lua_Type tag_great, char *op) +{ + Object *l = top-2; + Object *r = top-1; + int result; + if (tag(l) == LUA_T_NUMBER && tag(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); + do_call(&fallBacks[FB_ORDER].function, (top-stack)-3, 1, (top-stack)-3); + return; + } + else + result = strcmp(svalue(l), svalue(r)); + top--; + nvalue(top-1) = 1; + tag(top-1) = (result < 0) ? tag_less : (result == 0) ? tag_equal : tag_great; +} + + + /* ** Execute the given opcode, until a RET. Parameters are between ** [stack+base,top). Returns n such that the the results are between @@ -656,23 +743,26 @@ static int lua_execute (Byte *pc, int base) break; case STOREINDEXED0: - { - int s = lua_storesubscript(); - if (s == 1) return 1; - } - break; + storesubscript(); + break; case STOREINDEXED: { int n = *pc++; if (tag(top-3-n) != LUA_T_ARRAY) - lua_reportbug ("indexed expression not a table"); + { + *(top+1) = *(top-1); + *(top) = *(top-2-n); + *(top-1) = *(top-3-n); + top += 2; + do_call(&fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); + } + else { Object *h = lua_hashdefine (avalue(top-3-n), top-2-n); - if (h == NULL) return 1; *h = *(top-1); + top--; } - top--; } break; @@ -766,48 +856,33 @@ static int lua_execute (Byte *pc, int base) } break; - case LTOP: - { - Object *l = top-2; - Object *r = top-1; - --top; - if (tag(l) == LUA_T_NUMBER && tag(r) == LUA_T_NUMBER) - tag(top-1) = (nvalue(l) < nvalue(r)) ? LUA_T_NUMBER : LUA_T_NIL; - else - { - if (tostring(l) || tostring(r)) - return 1; - tag(top-1) = (strcmp (svalue(l), svalue(r)) < 0) ? LUA_T_NUMBER : LUA_T_NIL; - } - nvalue(top-1) = 1; - } - break; + case LTOP: + comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, "<"); + break; case LEOP: - { - Object *l = top-2; - Object *r = top-1; - --top; - if (tag(l) == LUA_T_NUMBER && tag(r) == LUA_T_NUMBER) - tag(top-1) = (nvalue(l) <= nvalue(r)) ? LUA_T_NUMBER : LUA_T_NIL; - else - { - if (tostring(l) || tostring(r)) - return 1; - tag(top-1) = (strcmp (svalue(l), svalue(r)) <= 0) ? LUA_T_NUMBER : LUA_T_NIL; - } - nvalue(top-1) = 1; - } - break; + comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, "<="); + break; + + case GTOP: + comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, ">"); + break; + + case GEOP: + comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, ">="); + break; case ADDOP: { Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) += nvalue(r); - --top; + call_arith("+"); + else + { + nvalue(l) += nvalue(r); + --top; + } } break; @@ -816,9 +891,12 @@ static int lua_execute (Byte *pc, int base) Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) -= nvalue(r); - --top; + call_arith("-"); + else + { + nvalue(l) -= nvalue(r); + --top; + } } break; @@ -827,9 +905,12 @@ static int lua_execute (Byte *pc, int base) Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) *= nvalue(r); - --top; + call_arith("*"); + else + { + nvalue(l) *= nvalue(r); + --top; + } } break; @@ -838,9 +919,12 @@ static int lua_execute (Byte *pc, int base) Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) /= nvalue(r); - --top; + call_arith("/"); + else + { + nvalue(l) /= nvalue(r); + --top; + } } break; @@ -849,9 +933,12 @@ static int lua_execute (Byte *pc, int base) Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) = pow(nvalue(l), nvalue(r)); - --top; + call_arith("^"); + else + { + nvalue(l) = pow(nvalue(l), nvalue(r)); + --top; + } } break; @@ -860,22 +947,24 @@ static int lua_execute (Byte *pc, int base) Object *l = top-2; Object *r = top-1; if (tostring(r) || tostring(l)) - return 1; - svalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); - if (svalue(l) == NULL) - return 1; - --top; + do_call(&fallBacks[FB_CONCAT].function, (top-stack)-2, 1, (top-stack)-2); + else + { + svalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); + --top; + } } break; case MINUSOP: if (tonumber(top-1)) - return 1; - nvalue(top-1) = - nvalue(top-1); + do_call(&fallBacks[FB_UNMINUS].function, (top-stack)-1, 1, (top-stack)-1); + else + nvalue(top-1) = - nvalue(top-1); break; case NOTOP: - tag(top-1) = tag(top-1) == LUA_T_NIL ? LUA_T_NUMBER : LUA_T_NIL; + tag(top-1) = (tag(top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL; break; case ONTJMP: @@ -952,8 +1041,7 @@ static int lua_execute (Byte *pc, int base) CodeWord func; get_code(file,pc); get_word(func,pc); - if (lua_pushfunction ((char *)file.b, func.w)) - return 1; + lua_pushfunction ((char *)file.b, func.w); } break; @@ -971,7 +1059,6 @@ static int lua_execute (Byte *pc, int base) default: lua_error ("internal error - opcode doesn't match"); - return 1; } } } -- cgit v1.2.3-55-g6feb