diff options
author | Lua Team <team@lua.org> | 1995-02-07 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 1995-02-07 12:00:00 +0000 |
commit | a8b6ba0954edb9e0e669e1f451b9a8f145ce5166 (patch) | |
tree | 35e9e9999968c4f13a25a5f647203456f044274a /src/opcode.c | |
parent | 944fc7d7d95575f2b8023c1f3d4ac19e1369fc76 (diff) | |
download | lua-github-2.1.tar.gz |
Lua 2.12.1
Diffstat (limited to 'src/opcode.c')
-rw-r--r-- | src/opcode.c | 1623 |
1 files changed, 859 insertions, 764 deletions
diff --git a/src/opcode.c b/src/opcode.c index 6006f7ac..7ce5b2a6 100644 --- a/src/opcode.c +++ b/src/opcode.c @@ -3,171 +3,763 @@ ** TecCGraf - PUC-Rio */ -char *rcs_opcode="$Id: opcode.c,v 2.1 1994/04/20 22:07:57 celes Exp $"; +char *rcs_opcode="$Id: opcode.c,v 3.34 1995/02/06 19:35:09 roberto Exp $"; -#include <stdio.h> +#include <setjmp.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> +#include <math.h> -/* stdlib.h does not have this in SunOS */ -extern double strtod(const char *, char **); - -#include "mm.h" - +#include "mem.h" #include "opcode.h" #include "hash.h" #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)) + + +#define STACK_BUFFER (STACKGAP+128) + +typedef int StkId; /* index to stack elements */ + +static Long maxstack = 0L; +static Object *stack = NULL; +static Object *top = NULL; + + +/* macros to convert from lua_Object to (Object *) and back */ + +#define Address(lo) ((lo)+stack-1) +#define Ref(st) ((st)-stack+1) + + +static StkId CBase = 0; /* when Lua calls C or C calls Lua, points to */ + /* the first slot after the last parameter. */ +static int CnResults = 0; /* when Lua calls C, has the number of parameters; */ + /* when C calls Lua, has the number of results. */ -#define tonumber(o) ((tag(o) != T_NUMBER) && (lua_tonumber(o) != 0)) -#define tostring(o) ((tag(o) != T_STRING) && (lua_tostring(o) != 0)) +static jmp_buf *errorJmp = NULL; /* current error recover point */ -#ifndef MAXSTACK -#define MAXSTACK 256 -#endif -static Object stack[MAXSTACK] = {{T_MARK, {NULL}}}; -static Object *top=stack+1, *base=stack+1; + +static StkId lua_execute (Byte *pc, StkId base); +static void do_call (Object *func, StkId base, int nResults, StkId whereRes); + + + +Object *luaI_Address (lua_Object o) +{ + return Address(o); +} /* -** Concatenate two given string, creating a mark space at the beginning. -** Return the new string pointer. +** Error messages */ -static char *lua_strconc (char *l, char *r) + +static void lua_message (char *s) { - char *s = calloc (strlen(l)+strlen(r)+2, sizeof(char)); - if (s == NULL) - { - lua_error ("not enough memory"); - return NULL; - } - *s++ = 0; /* create mark space */ - return strcat(strcpy(s,l),r); + lua_pushstring(s); + do_call(&luaI_fallBacks[FB_ERROR].function, (top-stack)-1, 0, (top-stack)-1); } /* -** Duplicate a string, creating a mark space at the beginning. -** Return the new string pointer. +** Reports an error, and jumps up to the available recover label */ -char *lua_strdup (char *l) +void lua_error (char *s) { - char *s = calloc (strlen(l)+2, sizeof(char)); - if (s == NULL) - { - lua_error ("not enough memory"); - return NULL; - } - *s++ = 0; /* create mark space */ - return strcpy(s,l); + if (s) lua_message(s); + if (errorJmp) + longjmp(*errorJmp, 1); + else + { + fprintf (stderr, "lua: exit(1). Unable to recover\n"); + exit(1); + } } + /* -** Convert, if possible, to a number tag. -** Return 0 in success or not 0 on error. -*/ -static int lua_tonumber (Object *obj) +** Init stack +*/ +static void lua_initstack (void) { - char *ptr; - if (tag(obj) != T_STRING) - { - lua_reportbug ("unexpected type at conversion to number"); - return 1; - } - nvalue(obj) = strtod(svalue(obj), &ptr); - if (*ptr) - { - lua_reportbug ("string to number convertion failed"); - return 2; - } - tag(obj) = T_NUMBER; - return 0; + maxstack = STACK_BUFFER; + stack = newvector(maxstack, Object); + top = stack; } + /* -** Test if is possible to convert an object to a number one. -** If possible, return the converted object, otherwise return nil object. -*/ -static Object *lua_convtonumber (Object *obj) +** Check stack overflow and, if necessary, realloc vector +*/ +#define lua_checkstack(n) if ((Long)(n) > maxstack) checkstack(n) + +static void checkstack (StkId n) { - static Object cvt; - - if (tag(obj) == T_NUMBER) - { - cvt = *obj; - return &cvt; - } - - tag(&cvt) = T_NIL; - if (tag(obj) == T_STRING) + StkId t; + if (stack == NULL) + lua_initstack(); + if (maxstack >= MAX_INT) + lua_error("stack size overflow"); + t = top-stack; + maxstack *= 2; + if (maxstack >= MAX_INT) + maxstack = MAX_INT; + stack = growvector(stack, maxstack, Object); + top = stack + t; +} + + +/* +** Concatenate two given strings. Return the new string pointer. +*/ +static char *lua_strconc (char *l, char *r) +{ + static char *buffer = NULL; + static int buffer_size = 0; + int nl = strlen(l); + int n = nl+strlen(r)+1; + if (n > buffer_size) + { + buffer_size = n; + if (buffer != NULL) + luaI_free(buffer); + buffer = newvector(buffer_size, char); + } + strcpy(buffer,l); + strcpy(buffer+nl, r); + return buffer; +} + + +/* +** Convert, if possible, to a number object. +** Return 0 if success, not 0 if error. +*/ +static int lua_tonumber (Object *obj) +{ + float t; + char c; + if (tag(obj) != LUA_T_STRING) + return 1; + else if (sscanf(svalue(obj), "%f %c",&t, &c) == 1) { - char *ptr; - nvalue(&cvt) = strtod(svalue(obj), &ptr); - if (*ptr == 0) - tag(&cvt) = T_NUMBER; + nvalue(obj) = t; + tag(obj) = LUA_T_NUMBER; + return 0; } - return &cvt; + else + return 2; } - /* ** Convert, if possible, to a string tag ** Return 0 in success or not 0 on error. -*/ +*/ static int lua_tostring (Object *obj) { static char s[256]; - if (tag(obj) != T_NUMBER) - { - lua_reportbug ("unexpected type at conversion to string"); - return 1; - } + if (tag(obj) != LUA_T_NUMBER) + 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)); - svalue(obj) = lua_createstring(lua_strdup(s)); - if (svalue(obj) == NULL) + sprintf (s, "%g", nvalue(obj)); + tsvalue(obj) = lua_createstring(s); + if (tsvalue(obj) == NULL) return 1; - tag(obj) = T_STRING; + tag(obj) = LUA_T_STRING; return 0; } /* -** Execute the given opcode. Return 0 in success or 1 on error. +** Adjust stack. Set top to the given value, pushing NILs if needed. +*/ +static void adjust_top (StkId newtop) +{ + Object *nt = stack+newtop; + while (top < nt) tag(top++) = LUA_T_NIL; + top = nt; /* top could be bigger than newtop */ +} + + +static void adjustC (int nParams) +{ + adjust_top(CBase+nParams); +} + + +/* +** Call a C function. CBase will point to the top of the stack, +** and CnResults is the number of parameters. Returns an index +** to the first result from C. +*/ +static StkId callC (lua_CFunction func, StkId base) +{ + StkId oldBase = CBase; + int oldCnResults = CnResults; + StkId firstResult; + CnResults = (top-stack) - base; + /* incorporate parameters on the stack */ + CBase = base+CnResults; + (*func)(); + firstResult = CBase; + CBase = oldBase; + CnResults = oldCnResults; + return firstResult; +} + +/* +** Call the fallback for invalid functions (see do_call) +*/ +static void call_funcFB (Object *func, StkId base, int nResults, StkId whereRes) +{ + StkId i; + /* open space for first parameter (func) */ + for (i=top-stack; i>base; i--) + stack[i] = stack[i-1]; + top++; + stack[base] = *func; + do_call(&luaI_fallBacks[FB_FUNCTION].function, base, nResults, whereRes); +} + + +/* +** Call a function (C or Lua). The parameters must be on the stack, +** between [stack+base,top). When returns, the results are on the stack, +** between [stack+whereRes,top). The number of results is nResults, unless +** nResults=MULT_RET. +*/ +static void do_call (Object *func, StkId base, int nResults, StkId whereRes) +{ + StkId firstResult; + if (tag(func) == LUA_T_CFUNCTION) + firstResult = callC(fvalue(func), base); + else if (tag(func) == LUA_T_FUNCTION) + firstResult = lua_execute(bvalue(func), base); + else + { /* func is not a function */ + call_funcFB(func, base, nResults, whereRes); + return; + } + /* adjust the number of results */ + if (nResults != MULT_RET && top - (stack+firstResult) != nResults) + adjust_top(firstResult+nResults); + /* move results to the given position */ + if (firstResult != whereRes) + { + int i; + nResults = top - (stack+firstResult); /* actual number of results */ + for (i=0; i<nResults; i++) + *(stack+whereRes+i) = *(stack+firstResult+i); + top -= firstResult-whereRes; + } +} + + +/* +** Function to index a table. Receives the table at top-2 and the index +** at top-1. +*/ +static void pushsubscript (void) +{ + if (tag(top-2) != LUA_T_ARRAY) + do_call(&luaI_fallBacks[FB_GETTABLE].function, (top-stack)-2, 1, (top-stack)-2); + else + { + Object *h = lua_hashget(avalue(top-2), top-1); + if (h == NULL || tag(h) == LUA_T_NIL) + do_call(&luaI_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 +*/ +static void storesubscript (void) +{ + if (tag(top-3) != LUA_T_ARRAY) + do_call(&luaI_fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); + else + { + Object *h = lua_hashdefine (avalue(top-3), top-2); + *h = *(top-1); + top -= 3; + } +} + + +/* +** Traverse all objects on stack +*/ +void lua_travstack (void (*fn)(Object *)) +{ + Object *o; + for (o = top-1; o >= stack; o--) + fn (o); +} + + +/* +** Execute a protected call. If function is null compiles the pre-set input. +** Leave nResults on the stack. +*/ +static int do_protectedrun (Object *function, int nResults) +{ + jmp_buf myErrorJmp; + int status; + StkId oldCBase = CBase; + jmp_buf *oldErr = errorJmp; + errorJmp = &myErrorJmp; + if (setjmp(myErrorJmp) == 0) + { + do_call(function, CBase, nResults, CBase); + CnResults = (top-stack) - CBase; /* number of results */ + CBase += CnResults; /* incorporate results on the stack */ + status = 0; + } + else + { + CBase = oldCBase; + top = stack+CBase; + status = 1; + } + errorJmp = oldErr; + return status; +} + + +static int do_protectedmain (void) +{ + Byte *code = NULL; + int status; + StkId oldCBase = CBase; + jmp_buf myErrorJmp; + jmp_buf *oldErr = errorJmp; + errorJmp = &myErrorJmp; + if (setjmp(myErrorJmp) == 0) + { + Object f; + lua_parse(&code); + tag(&f) = LUA_T_FUNCTION; bvalue(&f) = code; + do_call(&f, CBase, 0, CBase); + status = 0; + } + else + status = 1; + if (code) + luaI_free(code); + errorJmp = oldErr; + CBase = oldCBase; + top = stack+CBase; + return status; +} + + +/* +** Execute the given lua function. Return 0 on success or 1 on error. +*/ +int lua_callfunction (lua_Object function) +{ + if (function == LUA_NOOBJECT) + return 1; + else + return do_protectedrun (Address(function), MULT_RET); +} + + +int lua_call (char *funcname) +{ + Word n = luaI_findsymbolbyname(funcname); + return do_protectedrun(&s_object(n), MULT_RET); +} + + +/* +** Open file, generate opcode and execute global statement. Return 0 on +** success or 1 on error. +*/ +int lua_dofile (char *filename) +{ + int status; + char *message = lua_openfile (filename); + if (message) + { + lua_message(message); + return 1; + } + status = do_protectedmain(); + lua_closefile(); + return status; +} + +/* +** Generate opcode stored on string and execute global statement. Return 0 on +** success or 1 on error. +*/ +int lua_dostring (char *string) +{ + int status; + char *message = lua_openstring(string); + if (message) + { + lua_message(message); + return 1; + } + status = do_protectedmain(); + lua_closestring(); + return status; +} + + +/* +** API: set a function as a fallback +*/ +lua_Object lua_setfallback (char *name, lua_CFunction fallback) +{ + static Object func = {LUA_T_CFUNCTION, luaI_setfallback}; + adjustC(0); + lua_pushstring(name); + lua_pushcfunction(fallback); + do_protectedrun(&func, 1); + return (Ref(top-1)); +} + + +/* +** API: receives on the stack the table and the index. +** returns the value. +*/ +lua_Object lua_getsubscript (void) +{ + adjustC(2); + pushsubscript(); + CBase++; /* incorporate object in the stack */ + return (Ref(top-1)); +} + + +#define MAX_C_BLOCKS 10 + +static int numCblocks = 0; +static StkId Cblocks[MAX_C_BLOCKS]; + +/* +** API: starts a new block +*/ +void lua_beginblock (void) +{ + if (numCblocks < MAX_C_BLOCKS) + Cblocks[numCblocks] = CBase; + numCblocks++; +} + +/* +** API: ends a block +*/ +void lua_endblock (void) +{ + --numCblocks; + if (numCblocks < MAX_C_BLOCKS) + { + CBase = Cblocks[numCblocks]; + adjustC(0); + } +} + +/* +** API: receives on the stack the table, the index, and the new value. +*/ +void lua_storesubscript (void) +{ + adjustC(3); + storesubscript(); +} + +/* +** API: creates a new table +*/ +lua_Object lua_createtable (void) +{ + adjustC(0); + avalue(top) = lua_createarray(0); + tag(top) = LUA_T_ARRAY; + top++; + CBase++; /* incorporate object in the stack */ + return Ref(top-1); +} + +/* +** 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) +{ + if (number <= 0 || number > CnResults) return LUA_NOOBJECT; + /* Ref(stack+(CBase-CnResults+number-1)) == + stack+(CBase-CnResults+number-1)-stack+1 == */ + return CBase-CnResults+number; +} + +/* +** Given an object handle, return its number value. On error, return 0.0. +*/ +real lua_getnumber (lua_Object object) +{ + if (object == LUA_NOOBJECT || tag(Address(object)) == LUA_T_NIL) return 0.0; + if (tonumber (Address(object))) return 0.0; + else return (nvalue(Address(object))); +} + +/* +** Given an object handle, return its string pointer. On error, return NULL. +*/ +char *lua_getstring (lua_Object object) +{ + if (object == LUA_NOOBJECT || tag(Address(object)) == LUA_T_NIL) return NULL; + if (tostring (Address(object))) return NULL; + else return (svalue(Address(object))); +} + +/* +** Given an object handle, return its cfuntion pointer. On error, return NULL. +*/ +lua_CFunction lua_getcfunction (lua_Object object) +{ + if (object == LUA_NOOBJECT || tag(Address(object)) != LUA_T_CFUNCTION) + return NULL; + else return (fvalue(Address(object))); +} + +/* +** Given an object handle, return its user data. On error, return NULL. +*/ +void *lua_getuserdata (lua_Object object) +{ + if (object == LUA_NOOBJECT || tag(Address(object)) < LUA_T_USERDATA) + return NULL; + else return (uvalue(Address(object))); +} + + +lua_Object lua_getlocked (int ref) +{ + adjustC(0); + *top = *luaI_getlocked(ref); + top++; + CBase++; /* incorporate object in the stack */ + return Ref(top-1); +} + + +void lua_pushlocked (int ref) +{ + lua_checkstack(top-stack+1); + *top = *luaI_getlocked(ref); + top++; +} + + +int lua_lock (void) +{ + adjustC(1); + return luaI_lock(--top); +} + + +/* +** Get a global object. Return the object handle or NULL on error. +*/ +lua_Object lua_getglobal (char *name) +{ + Word n = luaI_findsymbolbyname(name); + adjustC(0); + *top = s_object(n); + top++; + CBase++; /* incorporate object in the stack */ + return Ref(top-1); +} + +/* +** Store top of the stack at a global variable array field. +*/ +void lua_storeglobal (char *name) +{ + Word n = luaI_findsymbolbyname(name); + adjustC(1); + s_object(n) = *(--top); +} + +/* +** Push a nil object +*/ +void lua_pushnil (void) +{ + lua_checkstack(top-stack+1); + tag(top++) = LUA_T_NIL; +} + +/* +** Push an object (tag=number) to stack. +*/ +void lua_pushnumber (real n) +{ + lua_checkstack(top-stack+1); + tag(top) = LUA_T_NUMBER; nvalue(top++) = n; +} + +/* +** Push an object (tag=string) to stack. +*/ +void lua_pushstring (char *s) +{ + lua_checkstack(top-stack+1); + tsvalue(top) = lua_createstring(s); + tag(top) = LUA_T_STRING; + top++; +} + +/* +** Push an object (tag=string) on stack and register it on the constant table. +*/ +void lua_pushliteral (char *s) +{ + lua_checkstack(top-stack+1); + tsvalue(top) = lua_constant[luaI_findconstant(lua_constcreate(s))]; + tag(top) = LUA_T_STRING; + top++; +} + +/* +** Push an object (tag=cfunction) to stack. +*/ +void lua_pushcfunction (lua_CFunction fn) +{ + lua_checkstack(top-stack+1); + tag(top) = LUA_T_CFUNCTION; fvalue(top++) = fn; +} + +/* +** Push an object (tag=userdata) to stack. +*/ +void lua_pushusertag (void *u, int tag) +{ + if (tag < LUA_T_USERDATA) return; + lua_checkstack(top-stack+1); + tag(top) = tag; uvalue(top++) = u; +} + +/* +** Push a lua_Object to stack. +*/ +void lua_pushobject (lua_Object o) +{ + lua_checkstack(top-stack+1); + *top++ = *Address(o); +} + +/* +** Push an object on the stack. +*/ +void luaI_pushobject (Object *o) +{ + lua_checkstack(top-stack+1); + *top++ = *o; +} + +int lua_type (lua_Object o) +{ + if (o == LUA_NOOBJECT) + return LUA_T_NIL; + else + return tag(Address(o)); +} + + +void luaI_gcFB (Object *o) +{ + *(top++) = *o; + do_call(&luaI_fallBacks[FB_GC].function, (top-stack)-1, 0, (top-stack)-1); +} + + +static void call_arith (char *op) +{ + lua_pushstring(op); + do_call(&luaI_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(&luaI_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 +** [stack+n,top). */ -int lua_execute (Byte *pc) +static StkId lua_execute (Byte *pc, StkId base) { - Object *oldbase = base; - base = top; + lua_checkstack(STACKGAP+MAX_TEMPS+base); while (1) { OpCode opcode; switch (opcode = (OpCode)*pc++) { - case PUSHNIL: tag(top++) = T_NIL; break; - - case PUSH0: tag(top) = T_NUMBER; nvalue(top++) = 0; break; - case PUSH1: tag(top) = T_NUMBER; nvalue(top++) = 1; break; - case PUSH2: tag(top) = T_NUMBER; nvalue(top++) = 2; break; - - case PUSHBYTE: tag(top) = T_NUMBER; nvalue(top++) = *pc++; break; - - case PUSHWORD: + case PUSHNIL: tag(top++) = LUA_T_NIL; break; + + case PUSH0: case PUSH1: case PUSH2: + tag(top) = LUA_T_NUMBER; + nvalue(top++) = opcode-PUSH0; + break; + + case PUSHBYTE: tag(top) = LUA_T_NUMBER; nvalue(top++) = *pc++; break; + + case PUSHWORD: { CodeWord code; get_word(code,pc); - tag(top) = T_NUMBER; nvalue(top++) = code.w; + tag(top) = LUA_T_NUMBER; nvalue(top++) = code.w; } break; - + case PUSHFLOAT: { CodeFloat code; get_float(code,pc); - tag(top) = T_NUMBER; nvalue(top++) = code.f; + tag(top) = LUA_T_NUMBER; nvalue(top++) = code.f; } break; @@ -175,50 +767,57 @@ int lua_execute (Byte *pc) { CodeWord code; get_word(code,pc); - tag(top) = T_STRING; svalue(top++) = lua_constant[code.w]; + tag(top) = LUA_T_STRING; tsvalue(top++) = lua_constant[code.w]; } break; - + + case PUSHFUNCTION: + { + CodeCode code; + get_code(code,pc); + tag(top) = LUA_T_FUNCTION; bvalue(top++) = code.b; + } + break; + case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8: - case PUSHLOCAL9: *top++ = *(base + (int)(opcode-PUSHLOCAL0)); break; - - case PUSHLOCAL: *top++ = *(base + (*pc++)); break; - - case PUSHGLOBAL: + case PUSHLOCAL9: *top++ = *((stack+base) + (int)(opcode-PUSHLOCAL0)); break; + + case PUSHLOCAL: *top++ = *((stack+base) + (*pc++)); break; + + case PUSHGLOBAL: { CodeWord code; get_word(code,pc); *top++ = s_object(code.w); } break; - + case PUSHINDEXED: - --top; - if (tag(top-1) != T_ARRAY) - { - lua_reportbug ("indexed expression not a table"); - return 1; - } - { - Object *h = lua_hashdefine (avalue(top-1), top); - if (h == NULL) return 1; - *(top-1) = *h; - } - break; - - case PUSHMARK: tag(top++) = T_MARK; break; - - case PUSHOBJECT: *top = *(top-3); top++; break; - + pushsubscript(); + break; + + case PUSHSELF: + { + Object receiver = *(top-1); + CodeWord code; + get_word(code,pc); + tag(top) = LUA_T_STRING; tsvalue(top++) = lua_constant[code.w]; + pushsubscript(); + *(top++) = receiver; + break; + } + case STORELOCAL0: case STORELOCAL1: case STORELOCAL2: case STORELOCAL3: case STORELOCAL4: case STORELOCAL5: case STORELOCAL6: case STORELOCAL7: case STORELOCAL8: - case STORELOCAL9: *(base + (int)(opcode-STORELOCAL0)) = *(--top); break; - - case STORELOCAL: *(base + (*pc++)) = *(--top); break; - + case STORELOCAL9: + *((stack+base) + (int)(opcode-STORELOCAL0)) = *(--top); + break; + + case STORELOCAL: *((stack+base) + (*pc++)) = *(--top); break; + case STOREGLOBAL: { CodeWord code; @@ -228,36 +827,29 @@ int lua_execute (Byte *pc) break; case STOREINDEXED0: - if (tag(top-3) != T_ARRAY) - { - lua_reportbug ("indexed expression not a table"); - return 1; - } - { - Object *h = lua_hashdefine (avalue(top-3), top-2); - if (h == NULL) return 1; - *h = *(top-1); - } - top -= 3; - break; - + storesubscript(); + break; + case STOREINDEXED: { int n = *pc++; - if (tag(top-3-n) != T_ARRAY) + if (tag(top-3-n) != LUA_T_ARRAY) { - lua_reportbug ("indexed expression not a table"); - return 1; + *(top+1) = *(top-1); + *(top) = *(top-2-n); + *(top-1) = *(top-3-n); + top += 2; + do_call(&luaI_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; - + case STORELIST0: case STORELIST: { @@ -267,206 +859,180 @@ int lua_execute (Byte *pc) else m = *(pc++) * FIELDS_PER_FLUSH; n = *(pc++); arr = top-n-1; - if (tag(arr) != T_ARRAY) - { - lua_reportbug ("internal error - table expected"); - return 1; - } while (n) { - tag(top) = T_NUMBER; nvalue(top) = n+m; + tag(top) = LUA_T_NUMBER; nvalue(top) = n+m; *(lua_hashdefine (avalue(arr), top)) = *(top-1); top--; n--; } } break; - + case STORERECORD: { int n = *(pc++); Object *arr = top-n-1; - if (tag(arr) != T_ARRAY) - { - lua_reportbug ("internal error - table expected"); - return 1; - } while (n) { CodeWord code; get_word(code,pc); - tag(top) = T_STRING; svalue(top) = lua_constant[code.w]; + tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; *(lua_hashdefine (avalue(arr), top)) = *(top-1); top--; n--; } } break; - + + case ADJUST0: + adjust_top(base); + break; + case ADJUST: + adjust_top(base + *(pc++)); + break; + + case CREATEARRAY: { - Object *newtop = base + *(pc++); - while (top < newtop) tag(top++) = T_NIL; - top = newtop; /* top could be bigger than newtop */ + CodeWord size; + get_word(size,pc); + avalue(top) = lua_createarray(size.w); + tag(top) = LUA_T_ARRAY; + top++; } break; - - case CREATEARRAY: - if (tag(top-1) == T_NIL) - nvalue(top-1) = 101; - else - { - if (tonumber(top-1)) return 1; - if (nvalue(top-1) <= 0) nvalue(top-1) = 101; - } - avalue(top-1) = lua_createarray(nvalue(top-1)); - if (avalue(top-1) == NULL) - return 1; - tag(top-1) = T_ARRAY; - break; - + case EQOP: { - Object *l = top-2; - Object *r = top-1; + int res = lua_equalObj(top-2, top-1); --top; - if (tag(l) != tag(r)) - tag(top-1) = T_NIL; - else - { - switch (tag(l)) - { - case T_NIL: tag(top-1) = T_NUMBER; break; - case T_NUMBER: tag(top-1) = (nvalue(l) == nvalue(r)) ? T_NUMBER : T_NIL; break; - case T_ARRAY: tag(top-1) = (avalue(l) == avalue(r)) ? T_NUMBER : T_NIL; break; - case T_FUNCTION: tag(top-1) = (bvalue(l) == bvalue(r)) ? T_NUMBER : T_NIL; break; - case T_CFUNCTION: tag(top-1) = (fvalue(l) == fvalue(r)) ? T_NUMBER : T_NIL; break; - case T_USERDATA: tag(top-1) = (uvalue(l) == uvalue(r)) ? T_NUMBER : T_NIL; break; - case T_STRING: tag(top-1) = (strcmp (svalue(l), svalue(r)) == 0) ? T_NUMBER : T_NIL; break; - case T_MARK: return 1; - } - } + tag(top-1) = res ? LUA_T_NUMBER : LUA_T_NIL; nvalue(top-1) = 1; } break; - - case LTOP: + + case LTOP: + comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, "lt"); + break; + + case LEOP: + comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, "le"); + break; + + case GTOP: + comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, "gt"); + break; + + case GEOP: + comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, "ge"); + break; + + case ADDOP: { Object *l = top-2; Object *r = top-1; - --top; - if (tag(l) == T_NUMBER && tag(r) == T_NUMBER) - tag(top-1) = (nvalue(l) < nvalue(r)) ? T_NUMBER : T_NIL; + if (tonumber(r) || tonumber(l)) + call_arith("add"); else { - if (tostring(l) || tostring(r)) - return 1; - tag(top-1) = (strcmp (svalue(l), svalue(r)) < 0) ? T_NUMBER : T_NIL; + nvalue(l) += nvalue(r); + --top; } - nvalue(top-1) = 1; } break; - - case LEOP: + + case SUBOP: { Object *l = top-2; Object *r = top-1; - --top; - if (tag(l) == T_NUMBER && tag(r) == T_NUMBER) - tag(top-1) = (nvalue(l) <= nvalue(r)) ? T_NUMBER : T_NIL; + if (tonumber(r) || tonumber(l)) + call_arith("sub"); else { - if (tostring(l) || tostring(r)) - return 1; - tag(top-1) = (strcmp (svalue(l), svalue(r)) <= 0) ? T_NUMBER : T_NIL; + nvalue(l) -= nvalue(r); + --top; } - nvalue(top-1) = 1; } break; - - case ADDOP: - { - Object *l = top-2; - Object *r = top-1; - if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) += nvalue(r); - --top; - } - break; - - case SUBOP: - { - Object *l = top-2; - Object *r = top-1; - if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) -= nvalue(r); - --top; - } - break; - + case MULTOP: { Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) *= nvalue(r); - --top; + call_arith("mul"); + else + { + nvalue(l) *= nvalue(r); + --top; + } } - break; - + break; + case DIVOP: { Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) - return 1; - nvalue(l) /= nvalue(r); - --top; + call_arith("div"); + else + { + nvalue(l) /= nvalue(r); + --top; + } } - break; - + break; + + case POWOP: + call_arith("pow"); + break; + case CONCOP: { 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(&luaI_fallBacks[FB_CONCAT].function, (top-stack)-2, 1, (top-stack)-2); + else + { + tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); + --top; + } } - break; - + break; + case MINUSOP: if (tonumber(top-1)) - return 1; - nvalue(top-1) = - nvalue(top-1); - break; - + { + tag(top++) = LUA_T_NIL; + call_arith("unm"); + } + else + nvalue(top-1) = - nvalue(top-1); + break; + case NOTOP: - tag(top-1) = tag(top-1) == T_NIL ? T_NUMBER : T_NIL; - break; - + tag(top-1) = (tag(top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL; + nvalue(top-1) = 1; + break; + case ONTJMP: { CodeWord code; get_word(code,pc); - if (tag(top-1) != T_NIL) pc += code.w; + if (tag(top-1) != LUA_T_NIL) pc += code.w; } break; - - case ONFJMP: + + case ONFJMP: { CodeWord code; get_word(code,pc); - if (tag(top-1) == T_NIL) pc += code.w; + if (tag(top-1) == LUA_T_NIL) pc += code.w; } break; - + case JMP: { CodeWord code; @@ -474,7 +1040,7 @@ int lua_execute (Byte *pc) pc += code.w; } break; - + case UPJMP: { CodeWord code; @@ -482,13 +1048,13 @@ int lua_execute (Byte *pc) pc -= code.w; } break; - + case IFFJMP: { CodeWord code; get_word(code,pc); top--; - if (tag(top) == T_NIL) pc += code.w; + if (tag(top) == LUA_T_NIL) pc += code.w; } break; @@ -497,91 +1063,38 @@ int lua_execute (Byte *pc) CodeWord code; get_word(code,pc); top--; - if (tag(top) == T_NIL) pc -= code.w; + if (tag(top) == LUA_T_NIL) pc -= code.w; } break; case POP: --top; break; - + case CALLFUNC: { - Byte *newpc; - Object *b = top-1; - while (tag(b) != T_MARK) b--; - if (tag(b-1) == T_FUNCTION) - { - lua_debugline = 0; /* always reset debug flag */ - newpc = bvalue(b-1); - bvalue(b-1) = pc; /* store return code */ - nvalue(b) = (base-stack); /* store base value */ - base = b+1; - pc = newpc; - if (MAXSTACK-(base-stack) < STACKGAP) - { - lua_error ("stack overflow"); - return 1; - } - } - else if (tag(b-1) == T_CFUNCTION) - { - int nparam; - lua_debugline = 0; /* always reset debug flag */ - nvalue(b) = (base-stack); /* store base value */ - base = b+1; - nparam = top-base; /* number of parameters */ - (fvalue(b-1))(); /* call C function */ - - /* shift returned values */ - { - int i; - int nretval = top - base - nparam; - top = base - 2; - base = stack + (int) nvalue(base-1); - for (i=0; i<nretval; i++) - { - *top = *(top+nparam+2); - ++top; - } - } - } - else - { - lua_reportbug ("call expression not a function"); - return 1; - } + int nParams = *(pc++); + int nResults = *(pc++); + Object *func = top-1-nParams; /* function is below parameters */ + StkId newBase = (top-stack)-nParams; + do_call(func, newBase, nResults, newBase-1); } break; - + + case RETCODE0: + return base; + case RETCODE: - { - int i; - int shift = *pc++; - int nretval = top - base - shift; - top = base - 2; - pc = bvalue(base-2); - base = stack + (int) nvalue(base-1); - for (i=0; i<nretval; i++) - { - *top = *(top+shift+2); - ++top; - } - } - break; - - case HALT: - base = oldbase; - return 0; /* success */ - + return base+*pc; + case SETFUNCTION: { - CodeWord file, func; - get_word(file,pc); + CodeCode file; + CodeWord func; + get_code(file,pc); get_word(func,pc); - if (lua_pushfunction (file.w, func.w)) - return 1; + lua_pushfunction ((char *)file.b, func.w); } break; - + case SETLINE: { CodeWord code; @@ -589,433 +1102,15 @@ int lua_execute (Byte *pc) lua_debugline = code.w; } break; - + case RESET: lua_popfunction (); break; - + default: - lua_error ("internal error - opcode didn't match"); - return 1; + lua_error ("internal error - opcode doesn't match"); } } } -/* -** Traverse all objects on stack -*/ -void lua_travstack (void (*fn)(Object *)) -{ - Object *o; - for (o = top-1; o >= stack; o--) - fn (o); -} - -/* -** Open file, generate opcode and execute global statement. Return 0 on -** success or 1 on error. -*/ -int lua_dofile (char *filename) -{ - if (lua_openfile (filename)) return 1; - if (lua_parse ()) { lua_closefile (); return 1; } - lua_closefile (); - return 0; -} - -/* -** Generate opcode stored on string and execute global statement. Return 0 on -** success or 1 on error. -*/ -int lua_dostring (char *string) -{ - if (lua_openstring (string)) return 1; - if (lua_parse ()) return 1; - lua_closestring(); - return 0; -} - -/* -** Execute the given function. Return 0 on success or 1 on error. -*/ -int lua_call (char *functionname, int nparam) -{ - static Byte startcode[] = {CALLFUNC, HALT}; - int i; - Object func = s_object(lua_findsymbol(functionname)); - if (tag(&func) != T_FUNCTION) return 1; - for (i=1; i<=nparam; i++) - *(top-i+2) = *(top-i); - top += 2; - tag(top-nparam-1) = T_MARK; - *(top-nparam-2) = func; - return (lua_execute (startcode)); -} - -/* -** Get a parameter, returning the object handle or NULL on error. -** 'number' must be 1 to get the first parameter. -*/ -Object *lua_getparam (int number) -{ - if (number <= 0 || number > top-base) return NULL; - return (base+number-1); -} - -/* -** Given an object handle, return its number value. On error, return 0.0. -*/ -real lua_getnumber (Object *object) -{ - if (object == NULL || tag(object) == T_NIL) return 0.0; - if (tonumber (object)) return 0.0; - else return (nvalue(object)); -} - -/* -** Given an object handle, return its string pointer. On error, return NULL. -*/ -char *lua_getstring (Object *object) -{ - if (object == NULL || tag(object) == T_NIL) return NULL; - if (tostring (object)) return NULL; - else return (svalue(object)); -} - -/* -** Given an object handle, return a copy of its string. On error, return NULL. -*/ -char *lua_copystring (Object *object) -{ - if (object == NULL || tag(object) == T_NIL) return NULL; - if (tostring (object)) return NULL; - else return (strdup(svalue(object))); -} - -/* -** Given an object handle, return its cfuntion pointer. On error, return NULL. -*/ -lua_CFunction lua_getcfunction (Object *object) -{ - if (object == NULL) return NULL; - if (tag(object) != T_CFUNCTION) return NULL; - else return (fvalue(object)); -} - -/* -** Given an object handle, return its user data. On error, return NULL. -*/ -void *lua_getuserdata (Object *object) -{ - if (object == NULL) return NULL; - if (tag(object) != T_USERDATA) return NULL; - else return (uvalue(object)); -} - -/* -** Given an object handle and a field name, return its field object. -** On error, return NULL. -*/ -Object *lua_getfield (Object *object, char *field) -{ - if (object == NULL) return NULL; - if (tag(object) != T_ARRAY) - return NULL; - else - { - Object ref; - tag(&ref) = T_STRING; - svalue(&ref) = lua_createstring(lua_strdup(field)); - return (lua_hashdefine(avalue(object), &ref)); - } -} - -/* -** Given an object handle and an index, return its indexed object. -** On error, return NULL. -*/ -Object *lua_getindexed (Object *object, float index) -{ - if (object == NULL) return NULL; - if (tag(object) != T_ARRAY) - return NULL; - else - { - Object ref; - tag(&ref) = T_NUMBER; - nvalue(&ref) = index; - return (lua_hashdefine(avalue(object), &ref)); - } -} - -/* -** Get a global object. Return the object handle or NULL on error. -*/ -Object *lua_getglobal (char *name) -{ - int n = lua_findsymbol(name); - if (n < 0) return NULL; - return &s_object(n); -} - -/* -** Pop and return an object -*/ -Object *lua_pop (void) -{ - if (top <= base) return NULL; - top--; - return top; -} - -/* -** Push a nil object -*/ -int lua_pushnil (void) -{ - if ((top-stack) >= MAXSTACK-1) - { - lua_error ("stack overflow"); - return 1; - } - tag(top) = T_NIL; - return 0; -} - -/* -** Push an object (tag=number) to stack. Return 0 on success or 1 on error. -*/ -int lua_pushnumber (real n) -{ - if ((top-stack) >= MAXSTACK-1) - { - lua_error ("stack overflow"); - return 1; - } - tag(top) = T_NUMBER; nvalue(top++) = n; - return 0; -} - -/* -** Push an object (tag=string) to stack. Return 0 on success or 1 on error. -*/ -int lua_pushstring (char *s) -{ - if ((top-stack) >= MAXSTACK-1) - { - lua_error ("stack overflow"); - return 1; - } - tag(top) = T_STRING; - svalue(top++) = lua_createstring(lua_strdup(s)); - return 0; -} - -/* -** Push an object (tag=cfunction) to stack. Return 0 on success or 1 on error. -*/ -int lua_pushcfunction (lua_CFunction fn) -{ - if ((top-stack) >= MAXSTACK-1) - { - lua_error ("stack overflow"); - return 1; - } - tag(top) = T_CFUNCTION; fvalue(top++) = fn; - return 0; -} - -/* -** Push an object (tag=userdata) to stack. Return 0 on success or 1 on error. -*/ -int lua_pushuserdata (void *u) -{ - if ((top-stack) >= MAXSTACK-1) - { - lua_error ("stack overflow"); - return 1; - } - tag(top) = T_USERDATA; uvalue(top++) = u; - return 0; -} - -/* -** Push an object to stack. -*/ -int lua_pushobject (Object *o) -{ - if ((top-stack) >= MAXSTACK-1) - { - lua_error ("stack overflow"); - return 1; - } - *top++ = *o; - return 0; -} - -/* -** Store top of the stack at a global variable array field. -** Return 1 on error, 0 on success. -*/ -int lua_storeglobal (char *name) -{ - int n = lua_findsymbol (name); - if (n < 0) return 1; - if (tag(top-1) == T_MARK) return 1; - s_object(n) = *(--top); - return 0; -} - -/* -** Store top of the stack at an array field. Return 1 on error, 0 on success. -*/ -int lua_storefield (lua_Object object, char *field) -{ - if (tag(object) != T_ARRAY) - return 1; - else - { - Object ref, *h; - tag(&ref) = T_STRING; - svalue(&ref) = lua_createstring(lua_strdup(field)); - h = lua_hashdefine(avalue(object), &ref); - if (h == NULL) return 1; - if (tag(top-1) == T_MARK) return 1; - *h = *(--top); - } - return 0; -} - - -/* -** Store top of the stack at an array index. Return 1 on error, 0 on success. -*/ -int lua_storeindexed (lua_Object object, float index) -{ - if (tag(object) != T_ARRAY) - return 1; - else - { - Object ref, *h; - tag(&ref) = T_NUMBER; - nvalue(&ref) = index; - h = lua_hashdefine(avalue(object), &ref); - if (h == NULL) return 1; - if (tag(top-1) == T_MARK) return 1; - *h = *(--top); - } - return 0; -} - - -/* -** Given an object handle, return if it is nil. -*/ -int lua_isnil (Object *object) -{ - return (object != NULL && tag(object) == T_NIL); -} - -/* -** Given an object handle, return if it is a number one. -*/ -int lua_isnumber (Object *object) -{ - return (object != NULL && tag(object) == T_NUMBER); -} - -/* -** Given an object handle, return if it is a string one. -*/ -int lua_isstring (Object *object) -{ - return (object != NULL && tag(object) == T_STRING); -} - -/* -** Given an object handle, return if it is an array one. -*/ -int lua_istable (Object *object) -{ - return (object != NULL && tag(object) == T_ARRAY); -} - -/* -** Given an object handle, return if it is a cfunction one. -*/ -int lua_iscfunction (Object *object) -{ - return (object != NULL && tag(object) == T_CFUNCTION); -} - -/* -** Given an object handle, return if it is an user data one. -*/ -int lua_isuserdata (Object *object) -{ - return (object != NULL && tag(object) == T_USERDATA); -} - -/* -** Internal function: return an object type. -*/ -void lua_type (void) -{ - Object *o = lua_getparam(1); - lua_pushstring (lua_constant[tag(o)]); -} - -/* -** Internal function: convert an object to a number -*/ -void lua_obj2number (void) -{ - Object *o = lua_getparam(1); - lua_pushobject (lua_convtonumber(o)); -} - -/* -** Internal function: print object values -*/ -void lua_print (void) -{ - int i=1; - void *obj; - while ((obj=lua_getparam (i++)) != NULL) - { - if (lua_isnumber(obj)) printf("%g\n",lua_getnumber (obj)); - else if (lua_isstring(obj)) printf("%s\n",lua_getstring (obj)); - else if (lua_iscfunction(obj)) printf("cfunction: %p\n",lua_getcfunction (obj)); - else if (lua_isuserdata(obj)) printf("userdata: %p\n",lua_getuserdata (obj)); - else if (lua_istable(obj)) printf("table: %p\n",obj); - else if (lua_isnil(obj)) printf("nil\n"); - else printf("invalid value to print\n"); - } -} - -/* -** Internal function: do a file -*/ -void lua_internaldofile (void) -{ - lua_Object obj = lua_getparam (1); - if (lua_isstring(obj) && !lua_dofile(lua_getstring(obj))) - lua_pushnumber(1); - else - lua_pushnil(); -} - -/* -** Internal function: do a string -*/ -void lua_internaldostring (void) -{ - lua_Object obj = lua_getparam (1); - if (lua_isstring(obj) && !lua_dostring(lua_getstring(obj))) - lua_pushnumber(1); - else - lua_pushnil(); -} - - |