lua/lvm.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: lvm.c,v 1.3 2004/03/23 05:09:14 jbj Exp $
00003 ** Lua virtual machine
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 
00008 #include <stdarg.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 
00012 /* needed only when `lua_number2str' uses `sprintf' */
00013 #include <stdio.h>
00014 
00015 #define lvm_c
00016 
00017 #include "lua.h"
00018 
00019 #include "ldebug.h"
00020 #include "ldo.h"
00021 #include "lfunc.h"
00022 #include "lgc.h"
00023 #include "lobject.h"
00024 #include "lopcodes.h"
00025 #include "lstate.h"
00026 #include "lstring.h"
00027 #include "ltable.h"
00028 #include "ltm.h"
00029 #include "lvm.h"
00030 
00031 
00032 
00033 /* function to convert a lua_Number to a string */
00034 #ifndef lua_number2str
00035 #define lua_number2str(s,n)     sprintf((s), LUA_NUMBER_FMT, (n))
00036 #endif
00037 
00038 
00039 /* limit for table tag-method chains (to avoid loops) */
00040 #define MAXTAGLOOP      100
00041 
00042 
00043 const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
00044   lua_Number num;
00045   if (ttisnumber(obj)) return obj;
00046   if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
00047     setnvalue(n, num);
00048     return n;
00049   }
00050   else
00051     return NULL;
00052 }
00053 
00054 
00055 int luaV_tostring (lua_State *L, StkId obj) {
00056   if (!ttisnumber(obj))
00057     return 0;
00058   else {
00059     char s[32];  /* 16 digits, sign, point and \0  (+ some extra...) */
00060     lua_number2str(s, nvalue(obj));
00061     setsvalue2s(obj, luaS_new(L, s));
00062     return 1;
00063   }
00064 }
00065 
00066 
00067 static void traceexec (lua_State *L)
00068         /*@modifies L @*/
00069 {
00070   lu_byte mask = L->hookmask;
00071   if (mask & LUA_MASKCOUNT) {  /* instruction-hook set? */
00072     if (L->hookcount == 0) {
00073       resethookcount(L);
00074       luaD_callhook(L, LUA_HOOKCOUNT, -1);
00075       return;
00076     }
00077   }
00078   if (mask & LUA_MASKLINE) {
00079     CallInfo *ci = L->ci;
00080     Proto *p = ci_func(ci)->l.p;
00081     int newline = getline(p, pcRel(*ci->u.l.pc, p));
00082     if (!L->hookinit) {
00083       luaG_inithooks(L);
00084       return;
00085     }
00086     lua_assert(ci->state & CI_HASFRAME);
00087     if (pcRel(*ci->u.l.pc, p) == 0)  /* tracing may be starting now? */
00088       ci->u.l.savedpc = *ci->u.l.pc;  /* initialize `savedpc' */
00089     /* calls linehook when enters a new line or jumps back (loop) */
00090     if (*ci->u.l.pc <= ci->u.l.savedpc ||
00091         newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
00092       luaD_callhook(L, LUA_HOOKLINE, newline);
00093       ci = L->ci;  /* previous call may reallocate `ci' */
00094     }
00095     ci->u.l.savedpc = *ci->u.l.pc;
00096   }
00097 }
00098 
00099 
00100 static void callTMres (lua_State *L, const TObject *f,
00101                        const TObject *p1, const TObject *p2)
00102         /*@modifies L @*/
00103 {
00104   setobj2s(L->top, f);  /* push function */
00105   setobj2s(L->top+1, p1);  /* 1st argument */
00106   setobj2s(L->top+2, p2);  /* 2nd argument */
00107   luaD_checkstack(L, 3);  /* cannot check before (could invalidate p1, p2) */
00108   L->top += 3;
00109   luaD_call(L, L->top - 3, 1);
00110   L->top--;  /* result will be in L->top */
00111 }
00112 
00113 
00114 
00115 static void callTM (lua_State *L, const TObject *f,
00116                     const TObject *p1, const TObject *p2, const TObject *p3)
00117         /*@modifies L @*/
00118 {
00119   setobj2s(L->top, f);  /* push function */
00120   setobj2s(L->top+1, p1);  /* 1st argument */
00121   setobj2s(L->top+2, p2);  /* 2nd argument */
00122   setobj2s(L->top+3, p3);  /* 3th argument */
00123   luaD_checkstack(L, 4);  /* cannot check before (could invalidate p1...p3) */
00124   L->top += 4;
00125   luaD_call(L, L->top - 4, 0);
00126 }
00127 
00128 
00129 /*@observer@*/
00130 static const TObject *luaV_index (lua_State *L, const TObject *t,
00131                                   TObject *key, int loop)
00132         /*@modifies L, t @*/
00133 {
00134   const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
00135   if (tm == NULL) return &luaO_nilobject;  /* no TM */
00136   if (ttisfunction(tm)) {
00137     callTMres(L, tm, t, key);
00138     return L->top;
00139   }
00140   else return luaV_gettable(L, tm, key, loop);
00141 }
00142 
00143 /*@observer@*/
00144 static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
00145                                        TObject *key, int loop)
00146         /*@modifies L @*/
00147 {
00148   const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);
00149   if (ttisnil(tm))
00150     luaG_typeerror(L, t, "index");
00151   if (ttisfunction(tm)) {
00152     callTMres(L, tm, t, key);
00153     return L->top;
00154   }
00155 /*@-modobserver@*/
00156   else return luaV_gettable(L, tm, key, loop);
00157 /*@=modobserver@*/
00158 }
00159 
00160 
00161 /*
00162 ** Function to index a table.
00163 ** Receives the table at `t' and the key at `key'.
00164 ** leaves the result at `res'.
00165 */
00166 const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
00167                               int loop) {
00168   if (loop > MAXTAGLOOP)
00169     luaG_runerror(L, "loop in gettable");
00170   if (ttistable(t)) {  /* `t' is a table? */
00171     Table *h = hvalue(t);
00172     const TObject *v = luaH_get(h, key);  /* do a primitive get */
00173     if (!ttisnil(v)) return v;
00174     else return luaV_index(L, t, key, loop+1);
00175   }
00176   else return luaV_getnotable(L, t, key, loop+1);
00177 }
00178 
00179 
00180 /*
00181 ** Receives table at `t', key at `key' and value at `val'.
00182 */
00183 void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
00184   const TObject *tm;
00185   int loop = 0;
00186   do {
00187     if (ttistable(t)) {  /* `t' is a table? */
00188       Table *h = hvalue(t);
00189       TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
00190       if (!ttisnil(oldval) ||  /* result is no nil? */
00191           (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
00192         setobj2t(oldval, val);  /* write barrier */
00193         return;
00194       }
00195       /* else will try the tag method */
00196     }
00197     else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
00198       luaG_typeerror(L, t, "index");
00199     if (ttisfunction(tm)) {
00200       callTM(L, tm, t, key, val);
00201       return;
00202     }
00203     t = tm;  /* else repeat with `tm' */ 
00204   } while (++loop <= MAXTAGLOOP);
00205   luaG_runerror(L, "loop in settable");
00206 }
00207 
00208 
00209 static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
00210                        StkId res, TMS event)
00211         /*@modifies L @*/
00212 {
00213   ptrdiff_t result = savestack(L, res);
00214   const TObject *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
00215   if (ttisnil(tm))
00216     tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
00217   if (!ttisfunction(tm)) return 0;
00218   callTMres(L, tm, p1, p2);
00219   res = restorestack(L, result);  /* previous call may change stack */
00220   setobjs2s(res, L->top);
00221   return 1;
00222 }
00223 
00224 
00225 /*@null@*/
00226 static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
00227                                   TMS event)
00228         /*@modifies mt1, mt2 @*/
00229 {
00230   const TObject *tm1 = fasttm(L, mt1, event);
00231   const TObject *tm2;
00232   if (tm1 == NULL) return NULL;  /* no metamethod */
00233   if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */
00234   tm2 = fasttm(L, mt2, event);
00235   if (tm2 == NULL) return NULL;  /* no metamethod */
00236   if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */
00237     return tm1;
00238   return NULL;
00239 }
00240 
00241 
00242 static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2,
00243                          TMS event)
00244         /*@modifies L @*/
00245 {
00246   const TObject *tm1 = luaT_gettmbyobj(L, p1, event);
00247   const TObject *tm2;
00248   if (ttisnil(tm1)) return -1;  /* no metamethod? */
00249   tm2 = luaT_gettmbyobj(L, p2, event);
00250   if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */
00251     return -1;
00252   callTMres(L, tm1, p1, p2);
00253   return !l_isfalse(L->top);
00254 }
00255 
00256 
00257 static int luaV_strcmp (const TString *ls, const TString *rs)
00258         /*@*/
00259 {
00260   const char *l = getstr(ls);
00261   size_t ll = ls->tsv.len;
00262   const char *r = getstr(rs);
00263   size_t lr = rs->tsv.len;
00264   for (;;) {
00265     int temp = strcoll(l, r);
00266     if (temp != 0) return temp;
00267     else {  /* strings are equal up to a `\0' */
00268       size_t len = strlen(l);  /* index of first `\0' in both strings */
00269       if (len == lr)  /* r is finished? */
00270         return (len == ll) ? 0 : 1;
00271       else if (len == ll)  /* l is finished? */
00272         return -1;  /* l is smaller than r (because r is not finished) */
00273       /* both strings longer than `len'; go on comparing (after the `\0') */
00274       len++;
00275       l += len; ll -= len; r += len; lr -= len;
00276     }
00277   }
00278 }
00279 
00280 
00281 int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
00282   int res;
00283   if (ttype(l) != ttype(r))
00284     return luaG_ordererror(L, l, r);
00285   else if (ttisnumber(l))
00286     return nvalue(l) < nvalue(r);
00287   else if (ttisstring(l))
00288     return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
00289   else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
00290     return res;
00291   return luaG_ordererror(L, l, r);
00292 }
00293 
00294 
00295 static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r)
00296         /*@modifies L @*/
00297 {
00298   int res;
00299   if (ttype(l) != ttype(r))
00300     return luaG_ordererror(L, l, r);
00301   else if (ttisnumber(l))
00302     return nvalue(l) <= nvalue(r);
00303   else if (ttisstring(l))
00304     return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
00305   else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
00306     return res;
00307   else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */
00308     return !res;
00309   return luaG_ordererror(L, l, r);
00310 }
00311 
00312 
00313 int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
00314   const TObject *tm;
00315   lua_assert(ttype(t1) == ttype(t2));
00316   switch (ttype(t1)) {
00317     case LUA_TNIL: return 1;
00318     case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
00319     case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
00320     case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
00321     case LUA_TUSERDATA: {
00322       if (uvalue(t1) == uvalue(t2)) return 1;
00323       tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable,
00324                          TM_EQ);
00325       break;  /* will try TM */
00326     }
00327     case LUA_TTABLE: {
00328       if (hvalue(t1) == hvalue(t2)) return 1;
00329       tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
00330       break;  /* will try TM */
00331     }
00332     default: return gcvalue(t1) == gcvalue(t2);
00333   }
00334   if (tm == NULL) return 0;  /* no TM? */
00335   callTMres(L, tm, t1, t2);  /* call TM */
00336   return !l_isfalse(L->top);
00337 }
00338 
00339 
00340 void luaV_concat (lua_State *L, int total, int last) {
00341   do {
00342     StkId top = L->base + last + 1;
00343     int n = 2;  /* number of elements handled in this pass (at least 2) */
00344     if (!tostring(L, top-2) || !tostring(L, top-1)) {
00345       if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
00346         luaG_concaterror(L, top-2, top-1);
00347     } else if (tsvalue(top-1)->tsv.len > 0) {  /* if len=0, do nothing */
00348       /* at least two string values; get as many as possible */
00349       lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) +
00350                   cast(lu_mem, tsvalue(top-2)->tsv.len);
00351       char *buffer;
00352       int i;
00353       while (n < total && tostring(L, top-n-1)) {  /* collect total length */
00354         tl += tsvalue(top-n-1)->tsv.len;
00355         n++;
00356       }
00357       if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
00358       buffer = luaZ_openspace(L, &G(L)->buff, tl);
00359       tl = 0;
00360       for (i=n; i>0; i--) {  /* concat all strings */
00361         size_t l = tsvalue(top-i)->tsv.len;
00362         memcpy(buffer+tl, svalue(top-i), l);
00363         tl += l;
00364       }
00365       setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));
00366     }
00367     total -= n-1;  /* got `n' strings to create 1 new */
00368     last -= n-1;
00369   } while (total > 1);  /* repeat until only 1 result left */
00370 }
00371 
00372 
00373 static void Arith (lua_State *L, StkId ra,
00374                    const TObject *rb, const TObject *rc, TMS op)
00375         /*@modifies L, ra @*/
00376 {
00377   TObject tempb, tempc;
00378   const TObject *b, *c;
00379   if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
00380       (c = luaV_tonumber(rc, &tempc)) != NULL) {
00381     switch (op) {
00382       case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break;
00383       case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break;
00384       case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;
00385       case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;
00386       case TM_POW: {
00387         const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);
00388         ptrdiff_t res = savestack(L, ra);
00389         if (!ttisfunction(f))
00390           luaG_runerror(L, "`__pow' (`^' operator) is not a function");
00391         callTMres(L, f, b, c);
00392         ra = restorestack(L, res);  /* previous call may change stack */
00393         setobjs2s(ra, L->top);
00394         break;
00395       }
00396       default: lua_assert(0); break;
00397     }
00398   }
00399   else if (!call_binTM(L, rb, rc, ra, op))
00400     luaG_aritherror(L, rb, rc);
00401 }
00402 
00403 
00404 
00405 /*
00406 ** some macros for common tasks in `luaV_execute'
00407 */
00408 
00409 #define runtime_check(L, c)     { if (!(c)) return 0; }
00410 
00411 #define RA(i)   (base+GETARG_A(i))
00412 /* to be used after possible stack reallocation */
00413 #define XRA(i)  (L->base+GETARG_A(i))
00414 #define RB(i)   (base+GETARG_B(i))
00415 #define RKB(i)  ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)
00416 #define RC(i)   (base+GETARG_C(i))
00417 #define RKC(i)  ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)
00418 #define KBx(i)  (k+GETARG_Bx(i))
00419 
00420 
00421 #define dojump(pc, i)   ((pc) += (i))
00422 
00423 
00424 StkId luaV_execute (lua_State *L) {
00425   LClosure *cl;
00426   TObject *k;
00427   const Instruction *pc;
00428  callentry:  /* entry point when calling new functions */
00429   if (L->hookmask & LUA_MASKCALL) {
00430     L->ci->u.l.pc = &pc;
00431     luaD_callhook(L, LUA_HOOKCALL, -1);
00432   }
00433  retentry:  /* entry point when returning to old functions */
00434   L->ci->u.l.pc = &pc;
00435   lua_assert(L->ci->state == CI_SAVEDPC ||
00436              L->ci->state == (CI_SAVEDPC | CI_CALLING));
00437   L->ci->state = CI_HASFRAME;  /* activate frame */
00438   pc = L->ci->u.l.savedpc;
00439   cl = &clvalue(L->base - 1)->l;
00440   k = cl->p->k;
00441   /* main loop of interpreter */
00442   for (;;) {
00443     const Instruction i = *pc++;
00444     StkId base, ra;
00445     if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
00446         (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
00447       traceexec(L);
00448       if (L->ci->state & CI_YIELD) {  /* did hook yield? */
00449         L->ci->u.l.savedpc = pc - 1;
00450         L->ci->state = CI_YIELD | CI_SAVEDPC;
00451         return NULL;
00452       }
00453     }
00454     /* warning!! several calls may realloc the stack and invalidate `ra' */
00455     base = L->base;
00456     ra = RA(i);
00457     lua_assert(L->ci->state & CI_HASFRAME);
00458     lua_assert(base == L->ci->base);
00459     lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
00460     lua_assert(L->top == L->ci->top ||
00461          GET_OPCODE(i) == OP_CALL ||   GET_OPCODE(i) == OP_TAILCALL ||
00462          GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
00463     switch (GET_OPCODE(i)) {
00464       case OP_MOVE: {
00465         setobjs2s(ra, RB(i));
00466         break;
00467       }
00468       case OP_LOADK: {
00469         setobj2s(ra, KBx(i));
00470         break;
00471       }
00472       case OP_LOADBOOL: {
00473         setbvalue(ra, GETARG_B(i));
00474         if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
00475         break;
00476       }
00477       case OP_LOADNIL: {
00478         TObject *rb = RB(i);
00479         do {
00480           setnilvalue(rb--);
00481         } while (rb >= ra);
00482         break;
00483       }
00484       case OP_GETUPVAL: {
00485         int b = GETARG_B(i);
00486         setobj2s(ra, cl->upvals[b]->v);
00487         break;
00488       }
00489       case OP_GETGLOBAL: {
00490         TObject *rb = KBx(i);
00491         const TObject *v;
00492         lua_assert(ttisstring(rb) && ttistable(&cl->g));
00493         v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
00494         if (!ttisnil(v)) { setobj2s(ra, v); }
00495         else
00496           setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0));
00497         break;
00498       }
00499       case OP_GETTABLE: {
00500         StkId rb = RB(i);
00501         TObject *rc = RKC(i);
00502         if (ttistable(rb)) {
00503           const TObject *v = luaH_get(hvalue(rb), rc);
00504           if (!ttisnil(v)) { setobj2s(ra, v); }
00505           else
00506             setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
00507         }
00508         else
00509           setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
00510         break;
00511       }
00512       case OP_SETGLOBAL: {
00513         lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
00514         luaV_settable(L, &cl->g, KBx(i), ra);
00515         break;
00516       }
00517       case OP_SETUPVAL: {
00518         int b = GETARG_B(i);
00519         setobj(cl->upvals[b]->v, ra);  /* write barrier */
00520         break;
00521       }
00522       case OP_SETTABLE: {
00523         luaV_settable(L, ra, RKB(i), RKC(i));
00524         break;
00525       }
00526       case OP_NEWTABLE: {
00527         int b = GETARG_B(i);
00528         b = fb2int(b);
00529         sethvalue(ra, luaH_new(L, b, GETARG_C(i)));
00530         luaC_checkGC(L);
00531         break;
00532       }
00533       case OP_SELF: {
00534         StkId rb = RB(i);
00535         TObject *rc = RKC(i);
00536         runtime_check(L, ttisstring(rc));
00537         setobjs2s(ra+1, rb);
00538         if (ttistable(rb)) {
00539           const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
00540           if (!ttisnil(v)) { setobj2s(ra, v); }
00541           else
00542             setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
00543         }
00544         else
00545           setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
00546         break;
00547       }
00548       case OP_ADD: {
00549         TObject *rb = RKB(i);
00550         TObject *rc = RKC(i);
00551         if (ttisnumber(rb) && ttisnumber(rc)) {
00552           setnvalue(ra, nvalue(rb) + nvalue(rc));
00553         }
00554         else
00555           Arith(L, ra, rb, rc, TM_ADD);
00556         break;
00557       }
00558       case OP_SUB: {
00559         TObject *rb = RKB(i);
00560         TObject *rc = RKC(i);
00561         if (ttisnumber(rb) && ttisnumber(rc)) {
00562           setnvalue(ra, nvalue(rb) - nvalue(rc));
00563         }
00564         else
00565           Arith(L, ra, rb, rc, TM_SUB);
00566         break;
00567       }
00568       case OP_MUL: {
00569         TObject *rb = RKB(i);
00570         TObject *rc = RKC(i);
00571         if (ttisnumber(rb) && ttisnumber(rc)) {
00572           setnvalue(ra, nvalue(rb) * nvalue(rc));
00573         }
00574         else
00575           Arith(L, ra, rb, rc, TM_MUL);
00576         break;
00577       }
00578       case OP_DIV: {
00579         TObject *rb = RKB(i);
00580         TObject *rc = RKC(i);
00581         if (ttisnumber(rb) && ttisnumber(rc)) {
00582           setnvalue(ra, nvalue(rb) / nvalue(rc));
00583         }
00584         else
00585           Arith(L, ra, rb, rc, TM_DIV);
00586         break;
00587       }
00588       case OP_POW: {
00589         Arith(L, ra, RKB(i), RKC(i), TM_POW);
00590         break;
00591       }
00592       case OP_UNM: {
00593         const TObject *rb = RB(i);
00594         TObject temp;
00595         if (tonumber(rb, &temp)) {
00596           setnvalue(ra, -nvalue(rb));
00597         }
00598         else {
00599           setnilvalue(&temp);
00600           if (!call_binTM(L, RB(i), &temp, ra, TM_UNM))
00601             luaG_aritherror(L, RB(i), &temp);
00602         }
00603         break;
00604       }
00605       case OP_NOT: {
00606         int res = l_isfalse(RB(i));  /* next assignment may change this value */
00607         setbvalue(ra, res);
00608         break;
00609       }
00610       case OP_CONCAT: {
00611         int b = GETARG_B(i);
00612         int c = GETARG_C(i);
00613         luaV_concat(L, c-b+1, c);  /* may change `base' (and `ra') */
00614         base = L->base;
00615         setobjs2s(RA(i), base+b);
00616         luaC_checkGC(L);
00617         break;
00618       }
00619       case OP_JMP: {
00620         dojump(pc, GETARG_sBx(i));
00621         break;
00622       }
00623       case OP_EQ: {
00624         if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
00625         else dojump(pc, GETARG_sBx(*pc) + 1);
00626         break;
00627       }
00628       case OP_LT: {
00629         if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
00630         else dojump(pc, GETARG_sBx(*pc) + 1);
00631         break;
00632       }
00633       case OP_LE: {
00634         if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
00635         else dojump(pc, GETARG_sBx(*pc) + 1);
00636         break;
00637       }
00638       case OP_TEST: {
00639         TObject *rb = RB(i);
00640         if (l_isfalse(rb) == GETARG_C(i)) pc++;
00641         else {
00642           setobjs2s(ra, rb);
00643           dojump(pc, GETARG_sBx(*pc) + 1);
00644         }
00645         break;
00646       }
00647       case OP_CALL:
00648       case OP_TAILCALL: {
00649         StkId firstResult;
00650         int b = GETARG_B(i);
00651         int nresults;
00652         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
00653         nresults = GETARG_C(i) - 1;
00654         firstResult = luaD_precall(L, ra);
00655         if (firstResult) {
00656           if (firstResult > L->top) {  /* yield? */
00657             lua_assert(L->ci->state == (CI_C | CI_YIELD));
00658             (L->ci - 1)->u.l.savedpc = pc;
00659             (L->ci - 1)->state = CI_SAVEDPC;
00660             return NULL;
00661           }
00662           /* it was a C function (`precall' called it); adjust results */
00663           luaD_poscall(L, nresults, firstResult);
00664           if (nresults >= 0) L->top = L->ci->top;
00665         }
00666         else {  /* it is a Lua function */
00667           if (GET_OPCODE(i) == OP_CALL) {  /* regular call? */
00668             (L->ci-1)->u.l.savedpc = pc;  /* save `pc' to return later */
00669             (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING);
00670           }
00671           else {  /* tail call: put new frame in place of previous one */
00672             int aux;
00673             base = (L->ci - 1)->base;  /* `luaD_precall' may change the stack */
00674             ra = RA(i);
00675             if (L->openupval) luaF_close(L, base);
00676             for (aux = 0; ra+aux < L->top; aux++)  /* move frame down */
00677               setobjs2s(base+aux-1, ra+aux);
00678             (L->ci - 1)->top = L->top = base+aux;  /* correct top */
00679             lua_assert(L->ci->state & CI_SAVEDPC);
00680             (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
00681             (L->ci - 1)->u.l.tailcalls++;  /* one more call lost */
00682             (L->ci - 1)->state = CI_SAVEDPC;
00683             L->ci--;  /* remove new frame */
00684             L->base = L->ci->base;
00685           }
00686           goto callentry;
00687         }
00688         break;
00689       }
00690       case OP_RETURN: {
00691         CallInfo *ci = L->ci - 1;  /* previous function frame */
00692         int b = GETARG_B(i);
00693         if (b != 0) L->top = ra+b-1;
00694         lua_assert(L->ci->state & CI_HASFRAME);
00695         if (L->openupval) luaF_close(L, base);
00696         L->ci->state = CI_SAVEDPC;  /* deactivate current function */
00697         L->ci->u.l.savedpc = pc;
00698         /* previous function was running `here'? */
00699         if (!(ci->state & CI_CALLING)) {
00700           lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
00701           return ra;  /* no: return */
00702         }
00703         else {  /* yes: continue its execution */
00704           int nresults;
00705           lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC));
00706           lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
00707           nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
00708           luaD_poscall(L, nresults, ra);
00709           if (nresults >= 0) L->top = L->ci->top;
00710           goto retentry;
00711         }
00712       }
00713       case OP_FORLOOP: {
00714         lua_Number step, idx, limit;
00715         const TObject *plimit = ra+1;
00716         const TObject *pstep = ra+2;
00717         if (!ttisnumber(ra))
00718           luaG_runerror(L, "`for' initial value must be a number");
00719         if (!tonumber(plimit, ra+1))
00720           luaG_runerror(L, "`for' limit must be a number");
00721 /*@-modobserver@*/
00722         if (!tonumber(pstep, ra+2))
00723           luaG_runerror(L, "`for' step must be a number");
00724 /*@=modobserver@*/
00725         step = nvalue(pstep);
00726         idx = nvalue(ra) + step;  /* increment index */
00727         limit = nvalue(plimit);
00728         if (step > 0 ? idx <= limit : idx >= limit) {
00729           dojump(pc, GETARG_sBx(i));  /* jump back */
00730           chgnvalue(ra, idx);  /* update index */
00731         }
00732         break;
00733       }
00734       case OP_TFORLOOP: {
00735         int nvar = GETARG_C(i) + 1;
00736         StkId cb = ra + nvar + 2;  /* call base */
00737         setobjs2s(cb, ra);
00738         setobjs2s(cb+1, ra+1);
00739         setobjs2s(cb+2, ra+2);
00740         L->top = cb+3;  /* func. + 2 args (state and index) */
00741         luaD_call(L, cb, nvar);
00742         L->top = L->ci->top;
00743         ra = XRA(i) + 2;  /* final position of first result */
00744         cb = ra + nvar;
00745         do {  /* move results to proper positions */
00746           nvar--;
00747           setobjs2s(ra+nvar, cb+nvar);
00748         } while (nvar > 0);
00749         if (ttisnil(ra))  /* break loop? */
00750           pc++;  /* skip jump (break loop) */
00751         else
00752           dojump(pc, GETARG_sBx(*pc) + 1);  /* jump back */
00753         break;
00754       }
00755       case OP_TFORPREP: {  /* for compatibility only */
00756         if (ttistable(ra)) {
00757           setobjs2s(ra+1, ra);
00758           setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
00759         }
00760         dojump(pc, GETARG_sBx(i));
00761         break;
00762       }
00763       case OP_SETLIST:
00764       case OP_SETLISTO: {
00765         int bc;
00766         int n;
00767         Table *h;
00768         runtime_check(L, ttistable(ra));
00769         h = hvalue(ra);
00770         bc = GETARG_Bx(i);
00771         if (GET_OPCODE(i) == OP_SETLIST)
00772           n = (bc&(LFIELDS_PER_FLUSH-1)) + 1;
00773         else {
00774           n = L->top - ra - 1;
00775           L->top = L->ci->top;
00776         }
00777         bc &= ~(LFIELDS_PER_FLUSH-1);  /* bc = bc - bc%FPF */
00778         for (; n > 0; n--)
00779           setobj2t(luaH_setnum(L, h, bc+n), ra+n);  /* write barrier */
00780         break;
00781       }
00782       case OP_CLOSE: {
00783         luaF_close(L, ra);
00784         break;
00785       }
00786       case OP_CLOSURE: {
00787         Proto *p;
00788         Closure *ncl;
00789         int nup, j;
00790         p = cl->p->p[GETARG_Bx(i)];
00791         nup = p->nups;
00792         ncl = luaF_newLclosure(L, nup, &cl->g);
00793         ncl->l.p = p;
00794         for (j=0; j<nup; j++, pc++) {
00795           if (GET_OPCODE(*pc) == OP_GETUPVAL)
00796             ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
00797           else {
00798             lua_assert(GET_OPCODE(*pc) == OP_MOVE);
00799             ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
00800           }
00801         }
00802         setclvalue(ra, ncl);
00803         luaC_checkGC(L);
00804         break;
00805       }
00806     }
00807   }
00808 }
00809 
00810 

Generated on Fri Oct 12 08:44:54 2007 for rpm by  doxygen 1.5.2