Mercurial > vba-clojure
diff src/lua/lvm.c @ 11:27763b933818
raise lua sources up one level
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:07:39 -0600 |
parents | src/lua/src/lvm.c@f9f4f1b99eed |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/lua/lvm.c Sat Mar 03 11:07:39 2012 -0600 1.3 @@ -0,0 +1,763 @@ 1.4 +/* 1.5 +** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ 1.6 +** Lua virtual machine 1.7 +** See Copyright Notice in lua.h 1.8 +*/ 1.9 + 1.10 + 1.11 +#include <stdio.h> 1.12 +#include <stdlib.h> 1.13 +#include <string.h> 1.14 + 1.15 +#define lvm_c 1.16 +#define LUA_CORE 1.17 + 1.18 +#include "lua.h" 1.19 + 1.20 +#include "ldebug.h" 1.21 +#include "ldo.h" 1.22 +#include "lfunc.h" 1.23 +#include "lgc.h" 1.24 +#include "lobject.h" 1.25 +#include "lopcodes.h" 1.26 +#include "lstate.h" 1.27 +#include "lstring.h" 1.28 +#include "ltable.h" 1.29 +#include "ltm.h" 1.30 +#include "lvm.h" 1.31 + 1.32 + 1.33 + 1.34 +/* limit for table tag-method chains (to avoid loops) */ 1.35 +#define MAXTAGLOOP 100 1.36 + 1.37 + 1.38 +const TValue *luaV_tonumber (const TValue *obj, TValue *n) { 1.39 + lua_Number num; 1.40 + if (ttisnumber(obj)) return obj; 1.41 + if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { 1.42 + setnvalue(n, num); 1.43 + return n; 1.44 + } 1.45 + else 1.46 + return NULL; 1.47 +} 1.48 + 1.49 + 1.50 +int luaV_tostring (lua_State *L, StkId obj) { 1.51 + if (!ttisnumber(obj)) 1.52 + return 0; 1.53 + else { 1.54 + char s[LUAI_MAXNUMBER2STR]; 1.55 + lua_Number n = nvalue(obj); 1.56 + lua_number2str(s, n); 1.57 + setsvalue2s(L, obj, luaS_new(L, s)); 1.58 + return 1; 1.59 + } 1.60 +} 1.61 + 1.62 + 1.63 +static void traceexec (lua_State *L, const Instruction *pc) { 1.64 + lu_byte mask = L->hookmask; 1.65 + const Instruction *oldpc = L->savedpc; 1.66 + L->savedpc = pc; 1.67 + if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { 1.68 + resethookcount(L); 1.69 + luaD_callhook(L, LUA_HOOKCOUNT, -1); 1.70 + } 1.71 + if (mask & LUA_MASKLINE) { 1.72 + Proto *p = ci_func(L->ci)->l.p; 1.73 + int npc = pcRel(pc, p); 1.74 + int newline = getline(p, npc); 1.75 + /* call linehook when enter a new function, when jump back (loop), 1.76 + or when enter a new line */ 1.77 + if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) 1.78 + luaD_callhook(L, LUA_HOOKLINE, newline); 1.79 + } 1.80 +} 1.81 + 1.82 + 1.83 +static void callTMres (lua_State *L, StkId res, const TValue *f, 1.84 + const TValue *p1, const TValue *p2) { 1.85 + ptrdiff_t result = savestack(L, res); 1.86 + setobj2s(L, L->top, f); /* push function */ 1.87 + setobj2s(L, L->top+1, p1); /* 1st argument */ 1.88 + setobj2s(L, L->top+2, p2); /* 2nd argument */ 1.89 + luaD_checkstack(L, 3); 1.90 + L->top += 3; 1.91 + luaD_call(L, L->top - 3, 1); 1.92 + res = restorestack(L, result); 1.93 + L->top--; 1.94 + setobjs2s(L, res, L->top); 1.95 +} 1.96 + 1.97 + 1.98 + 1.99 +static void callTM (lua_State *L, const TValue *f, const TValue *p1, 1.100 + const TValue *p2, const TValue *p3) { 1.101 + setobj2s(L, L->top, f); /* push function */ 1.102 + setobj2s(L, L->top+1, p1); /* 1st argument */ 1.103 + setobj2s(L, L->top+2, p2); /* 2nd argument */ 1.104 + setobj2s(L, L->top+3, p3); /* 3th argument */ 1.105 + luaD_checkstack(L, 4); 1.106 + L->top += 4; 1.107 + luaD_call(L, L->top - 4, 0); 1.108 +} 1.109 + 1.110 + 1.111 +void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { 1.112 + int loop; 1.113 + for (loop = 0; loop < MAXTAGLOOP; loop++) { 1.114 + const TValue *tm; 1.115 + if (ttistable(t)) { /* `t' is a table? */ 1.116 + Table *h = hvalue(t); 1.117 + const TValue *res = luaH_get(h, key); /* do a primitive get */ 1.118 + if (!ttisnil(res) || /* result is no nil? */ 1.119 + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ 1.120 + setobj2s(L, val, res); 1.121 + return; 1.122 + } 1.123 + /* else will try the tag method */ 1.124 + } 1.125 + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) 1.126 + luaG_typeerror(L, t, "index"); 1.127 + if (ttisfunction(tm)) { 1.128 + callTMres(L, val, tm, t, key); 1.129 + return; 1.130 + } 1.131 + t = tm; /* else repeat with `tm' */ 1.132 + } 1.133 + luaG_runerror(L, "loop in gettable"); 1.134 +} 1.135 + 1.136 + 1.137 +void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { 1.138 + int loop; 1.139 + for (loop = 0; loop < MAXTAGLOOP; loop++) { 1.140 + const TValue *tm; 1.141 + if (ttistable(t)) { /* `t' is a table? */ 1.142 + Table *h = hvalue(t); 1.143 + TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ 1.144 + if (!ttisnil(oldval) || /* result is no nil? */ 1.145 + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ 1.146 + setobj2t(L, oldval, val); 1.147 + luaC_barriert(L, h, val); 1.148 + return; 1.149 + } 1.150 + /* else will try the tag method */ 1.151 + } 1.152 + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) 1.153 + luaG_typeerror(L, t, "index"); 1.154 + if (ttisfunction(tm)) { 1.155 + callTM(L, tm, t, key, val); 1.156 + return; 1.157 + } 1.158 + t = tm; /* else repeat with `tm' */ 1.159 + } 1.160 + luaG_runerror(L, "loop in settable"); 1.161 +} 1.162 + 1.163 + 1.164 +static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, 1.165 + StkId res, TMS event) { 1.166 + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 1.167 + if (ttisnil(tm)) 1.168 + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 1.169 + if (ttisnil(tm)) return 0; 1.170 + callTMres(L, res, tm, p1, p2); 1.171 + return 1; 1.172 +} 1.173 + 1.174 + 1.175 +static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, 1.176 + TMS event) { 1.177 + const TValue *tm1 = fasttm(L, mt1, event); 1.178 + const TValue *tm2; 1.179 + if (tm1 == NULL) return NULL; /* no metamethod */ 1.180 + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ 1.181 + tm2 = fasttm(L, mt2, event); 1.182 + if (tm2 == NULL) return NULL; /* no metamethod */ 1.183 + if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ 1.184 + return tm1; 1.185 + return NULL; 1.186 +} 1.187 + 1.188 + 1.189 +static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, 1.190 + TMS event) { 1.191 + const TValue *tm1 = luaT_gettmbyobj(L, p1, event); 1.192 + const TValue *tm2; 1.193 + if (ttisnil(tm1)) return -1; /* no metamethod? */ 1.194 + tm2 = luaT_gettmbyobj(L, p2, event); 1.195 + if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ 1.196 + return -1; 1.197 + callTMres(L, L->top, tm1, p1, p2); 1.198 + return !l_isfalse(L->top); 1.199 +} 1.200 + 1.201 + 1.202 +static int l_strcmp (const TString *ls, const TString *rs) { 1.203 + const char *l = getstr(ls); 1.204 + size_t ll = ls->tsv.len; 1.205 + const char *r = getstr(rs); 1.206 + size_t lr = rs->tsv.len; 1.207 + for (;;) { 1.208 + int temp = strcoll(l, r); 1.209 + if (temp != 0) return temp; 1.210 + else { /* strings are equal up to a `\0' */ 1.211 + size_t len = strlen(l); /* index of first `\0' in both strings */ 1.212 + if (len == lr) /* r is finished? */ 1.213 + return (len == ll) ? 0 : 1; 1.214 + else if (len == ll) /* l is finished? */ 1.215 + return -1; /* l is smaller than r (because r is not finished) */ 1.216 + /* both strings longer than `len'; go on comparing (after the `\0') */ 1.217 + len++; 1.218 + l += len; ll -= len; r += len; lr -= len; 1.219 + } 1.220 + } 1.221 +} 1.222 + 1.223 + 1.224 +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { 1.225 + int res; 1.226 + if (ttype(l) != ttype(r)) 1.227 + return luaG_ordererror(L, l, r); 1.228 + else if (ttisnumber(l)) 1.229 + return luai_numlt(nvalue(l), nvalue(r)); 1.230 + else if (ttisstring(l)) 1.231 + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; 1.232 + else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) 1.233 + return res; 1.234 + return luaG_ordererror(L, l, r); 1.235 +} 1.236 + 1.237 + 1.238 +static int lessequal (lua_State *L, const TValue *l, const TValue *r) { 1.239 + int res; 1.240 + if (ttype(l) != ttype(r)) 1.241 + return luaG_ordererror(L, l, r); 1.242 + else if (ttisnumber(l)) 1.243 + return luai_numle(nvalue(l), nvalue(r)); 1.244 + else if (ttisstring(l)) 1.245 + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; 1.246 + else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ 1.247 + return res; 1.248 + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ 1.249 + return !res; 1.250 + return luaG_ordererror(L, l, r); 1.251 +} 1.252 + 1.253 + 1.254 +int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { 1.255 + const TValue *tm; 1.256 + lua_assert(ttype(t1) == ttype(t2)); 1.257 + switch (ttype(t1)) { 1.258 + case LUA_TNIL: return 1; 1.259 + case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); 1.260 + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ 1.261 + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); 1.262 + case LUA_TUSERDATA: { 1.263 + if (uvalue(t1) == uvalue(t2)) return 1; 1.264 + tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, 1.265 + TM_EQ); 1.266 + break; /* will try TM */ 1.267 + } 1.268 + case LUA_TTABLE: { 1.269 + if (hvalue(t1) == hvalue(t2)) return 1; 1.270 + tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); 1.271 + break; /* will try TM */ 1.272 + } 1.273 + default: return gcvalue(t1) == gcvalue(t2); 1.274 + } 1.275 + if (tm == NULL) return 0; /* no TM? */ 1.276 + callTMres(L, L->top, tm, t1, t2); /* call TM */ 1.277 + return !l_isfalse(L->top); 1.278 +} 1.279 + 1.280 + 1.281 +void luaV_concat (lua_State *L, int total, int last) { 1.282 + do { 1.283 + StkId top = L->base + last + 1; 1.284 + int n = 2; /* number of elements handled in this pass (at least 2) */ 1.285 + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { 1.286 + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) 1.287 + luaG_concaterror(L, top-2, top-1); 1.288 + } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ 1.289 + (void)tostring(L, top - 2); /* result is first op (as string) */ 1.290 + else { 1.291 + /* at least two string values; get as many as possible */ 1.292 + size_t tl = tsvalue(top-1)->len; 1.293 + char *buffer; 1.294 + int i; 1.295 + /* collect total length */ 1.296 + for (n = 1; n < total && tostring(L, top-n-1); n++) { 1.297 + size_t l = tsvalue(top-n-1)->len; 1.298 + if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); 1.299 + tl += l; 1.300 + } 1.301 + buffer = luaZ_openspace(L, &G(L)->buff, tl); 1.302 + tl = 0; 1.303 + for (i=n; i>0; i--) { /* concat all strings */ 1.304 + size_t l = tsvalue(top-i)->len; 1.305 + memcpy(buffer+tl, svalue(top-i), l); 1.306 + tl += l; 1.307 + } 1.308 + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); 1.309 + } 1.310 + total -= n-1; /* got `n' strings to create 1 new */ 1.311 + last -= n-1; 1.312 + } while (total > 1); /* repeat until only 1 result left */ 1.313 +} 1.314 + 1.315 + 1.316 +static void Arith (lua_State *L, StkId ra, const TValue *rb, 1.317 + const TValue *rc, TMS op) { 1.318 + TValue tempb, tempc; 1.319 + const TValue *b, *c; 1.320 + if ((b = luaV_tonumber(rb, &tempb)) != NULL && 1.321 + (c = luaV_tonumber(rc, &tempc)) != NULL) { 1.322 + lua_Number nb = nvalue(b), nc = nvalue(c); 1.323 + switch (op) { 1.324 + case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; 1.325 + case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; 1.326 + case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; 1.327 + case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; 1.328 + case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; 1.329 + case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; 1.330 + case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; 1.331 + default: lua_assert(0); break; 1.332 + } 1.333 + } 1.334 + else if (!call_binTM(L, rb, rc, ra, op)) 1.335 + luaG_aritherror(L, rb, rc); 1.336 +} 1.337 + 1.338 + 1.339 + 1.340 +/* 1.341 +** some macros for common tasks in `luaV_execute' 1.342 +*/ 1.343 + 1.344 +#define runtime_check(L, c) { if (!(c)) break; } 1.345 + 1.346 +#define RA(i) (base+GETARG_A(i)) 1.347 +/* to be used after possible stack reallocation */ 1.348 +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) 1.349 +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) 1.350 +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ 1.351 + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) 1.352 +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ 1.353 + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) 1.354 +#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) 1.355 + 1.356 + 1.357 +#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} 1.358 + 1.359 + 1.360 +#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } 1.361 + 1.362 + 1.363 +#define arith_op(op,tm) { \ 1.364 + TValue *rb = RKB(i); \ 1.365 + TValue *rc = RKC(i); \ 1.366 + if (ttisnumber(rb) && ttisnumber(rc)) { \ 1.367 + lua_Number nb = nvalue(rb), nc = nvalue(rc); \ 1.368 + setnvalue(ra, op(nb, nc)); \ 1.369 + } \ 1.370 + else \ 1.371 + Protect(Arith(L, ra, rb, rc, tm)); \ 1.372 + } 1.373 + 1.374 + 1.375 + 1.376 +void luaV_execute (lua_State *L, int nexeccalls) { 1.377 + LClosure *cl; 1.378 + StkId base; 1.379 + TValue *k; 1.380 + const Instruction *pc; 1.381 + reentry: /* entry point */ 1.382 + lua_assert(isLua(L->ci)); 1.383 + pc = L->savedpc; 1.384 + cl = &clvalue(L->ci->func)->l; 1.385 + base = L->base; 1.386 + k = cl->p->k; 1.387 + /* main loop of interpreter */ 1.388 + for (;;) { 1.389 + const Instruction i = *pc++; 1.390 + StkId ra; 1.391 + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && 1.392 + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { 1.393 + traceexec(L, pc); 1.394 + if (L->status == LUA_YIELD) { /* did hook yield? */ 1.395 + L->savedpc = pc - 1; 1.396 + return; 1.397 + } 1.398 + base = L->base; 1.399 + } 1.400 + /* warning!! several calls may realloc the stack and invalidate `ra' */ 1.401 + ra = RA(i); 1.402 + lua_assert(base == L->base && L->base == L->ci->base); 1.403 + lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); 1.404 + lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); 1.405 + switch (GET_OPCODE(i)) { 1.406 + case OP_MOVE: { 1.407 + setobjs2s(L, ra, RB(i)); 1.408 + continue; 1.409 + } 1.410 + case OP_LOADK: { 1.411 + setobj2s(L, ra, KBx(i)); 1.412 + continue; 1.413 + } 1.414 + case OP_LOADBOOL: { 1.415 + setbvalue(ra, GETARG_B(i)); 1.416 + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ 1.417 + continue; 1.418 + } 1.419 + case OP_LOADNIL: { 1.420 + TValue *rb = RB(i); 1.421 + do { 1.422 + setnilvalue(rb--); 1.423 + } while (rb >= ra); 1.424 + continue; 1.425 + } 1.426 + case OP_GETUPVAL: { 1.427 + int b = GETARG_B(i); 1.428 + setobj2s(L, ra, cl->upvals[b]->v); 1.429 + continue; 1.430 + } 1.431 + case OP_GETGLOBAL: { 1.432 + TValue g; 1.433 + TValue *rb = KBx(i); 1.434 + sethvalue(L, &g, cl->env); 1.435 + lua_assert(ttisstring(rb)); 1.436 + Protect(luaV_gettable(L, &g, rb, ra)); 1.437 + continue; 1.438 + } 1.439 + case OP_GETTABLE: { 1.440 + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); 1.441 + continue; 1.442 + } 1.443 + case OP_SETGLOBAL: { 1.444 + TValue g; 1.445 + sethvalue(L, &g, cl->env); 1.446 + lua_assert(ttisstring(KBx(i))); 1.447 + Protect(luaV_settable(L, &g, KBx(i), ra)); 1.448 + continue; 1.449 + } 1.450 + case OP_SETUPVAL: { 1.451 + UpVal *uv = cl->upvals[GETARG_B(i)]; 1.452 + setobj(L, uv->v, ra); 1.453 + luaC_barrier(L, uv, ra); 1.454 + continue; 1.455 + } 1.456 + case OP_SETTABLE: { 1.457 + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); 1.458 + continue; 1.459 + } 1.460 + case OP_NEWTABLE: { 1.461 + int b = GETARG_B(i); 1.462 + int c = GETARG_C(i); 1.463 + sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); 1.464 + Protect(luaC_checkGC(L)); 1.465 + continue; 1.466 + } 1.467 + case OP_SELF: { 1.468 + StkId rb = RB(i); 1.469 + setobjs2s(L, ra+1, rb); 1.470 + Protect(luaV_gettable(L, rb, RKC(i), ra)); 1.471 + continue; 1.472 + } 1.473 + case OP_ADD: { 1.474 + arith_op(luai_numadd, TM_ADD); 1.475 + continue; 1.476 + } 1.477 + case OP_SUB: { 1.478 + arith_op(luai_numsub, TM_SUB); 1.479 + continue; 1.480 + } 1.481 + case OP_MUL: { 1.482 + arith_op(luai_nummul, TM_MUL); 1.483 + continue; 1.484 + } 1.485 + case OP_DIV: { 1.486 + arith_op(luai_numdiv, TM_DIV); 1.487 + continue; 1.488 + } 1.489 + case OP_MOD: { 1.490 + arith_op(luai_nummod, TM_MOD); 1.491 + continue; 1.492 + } 1.493 + case OP_POW: { 1.494 + arith_op(luai_numpow, TM_POW); 1.495 + continue; 1.496 + } 1.497 + case OP_UNM: { 1.498 + TValue *rb = RB(i); 1.499 + if (ttisnumber(rb)) { 1.500 + lua_Number nb = nvalue(rb); 1.501 + setnvalue(ra, luai_numunm(nb)); 1.502 + } 1.503 + else { 1.504 + Protect(Arith(L, ra, rb, rb, TM_UNM)); 1.505 + } 1.506 + continue; 1.507 + } 1.508 + case OP_NOT: { 1.509 + int res = l_isfalse(RB(i)); /* next assignment may change this value */ 1.510 + setbvalue(ra, res); 1.511 + continue; 1.512 + } 1.513 + case OP_LEN: { 1.514 + const TValue *rb = RB(i); 1.515 + switch (ttype(rb)) { 1.516 + case LUA_TTABLE: { 1.517 + setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); 1.518 + break; 1.519 + } 1.520 + case LUA_TSTRING: { 1.521 + setnvalue(ra, cast_num(tsvalue(rb)->len)); 1.522 + break; 1.523 + } 1.524 + default: { /* try metamethod */ 1.525 + Protect( 1.526 + if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) 1.527 + luaG_typeerror(L, rb, "get length of"); 1.528 + ) 1.529 + } 1.530 + } 1.531 + continue; 1.532 + } 1.533 + case OP_CONCAT: { 1.534 + int b = GETARG_B(i); 1.535 + int c = GETARG_C(i); 1.536 + Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); 1.537 + setobjs2s(L, RA(i), base+b); 1.538 + continue; 1.539 + } 1.540 + case OP_JMP: { 1.541 + dojump(L, pc, GETARG_sBx(i)); 1.542 + continue; 1.543 + } 1.544 + case OP_EQ: { 1.545 + TValue *rb = RKB(i); 1.546 + TValue *rc = RKC(i); 1.547 + Protect( 1.548 + if (equalobj(L, rb, rc) == GETARG_A(i)) 1.549 + dojump(L, pc, GETARG_sBx(*pc)); 1.550 + ) 1.551 + pc++; 1.552 + continue; 1.553 + } 1.554 + case OP_LT: { 1.555 + Protect( 1.556 + if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) 1.557 + dojump(L, pc, GETARG_sBx(*pc)); 1.558 + ) 1.559 + pc++; 1.560 + continue; 1.561 + } 1.562 + case OP_LE: { 1.563 + Protect( 1.564 + if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) 1.565 + dojump(L, pc, GETARG_sBx(*pc)); 1.566 + ) 1.567 + pc++; 1.568 + continue; 1.569 + } 1.570 + case OP_TEST: { 1.571 + if (l_isfalse(ra) != GETARG_C(i)) 1.572 + dojump(L, pc, GETARG_sBx(*pc)); 1.573 + pc++; 1.574 + continue; 1.575 + } 1.576 + case OP_TESTSET: { 1.577 + TValue *rb = RB(i); 1.578 + if (l_isfalse(rb) != GETARG_C(i)) { 1.579 + setobjs2s(L, ra, rb); 1.580 + dojump(L, pc, GETARG_sBx(*pc)); 1.581 + } 1.582 + pc++; 1.583 + continue; 1.584 + } 1.585 + case OP_CALL: { 1.586 + int b = GETARG_B(i); 1.587 + int nresults = GETARG_C(i) - 1; 1.588 + if (b != 0) L->top = ra+b; /* else previous instruction set top */ 1.589 + L->savedpc = pc; 1.590 + switch (luaD_precall(L, ra, nresults)) { 1.591 + case PCRLUA: { 1.592 + nexeccalls++; 1.593 + goto reentry; /* restart luaV_execute over new Lua function */ 1.594 + } 1.595 + case PCRC: { 1.596 + /* it was a C function (`precall' called it); adjust results */ 1.597 + if (nresults >= 0) L->top = L->ci->top; 1.598 + base = L->base; 1.599 + continue; 1.600 + } 1.601 + default: { 1.602 + return; /* yield */ 1.603 + } 1.604 + } 1.605 + } 1.606 + case OP_TAILCALL: { 1.607 + int b = GETARG_B(i); 1.608 + if (b != 0) L->top = ra+b; /* else previous instruction set top */ 1.609 + L->savedpc = pc; 1.610 + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); 1.611 + switch (luaD_precall(L, ra, LUA_MULTRET)) { 1.612 + case PCRLUA: { 1.613 + /* tail call: put new frame in place of previous one */ 1.614 + CallInfo *ci = L->ci - 1; /* previous frame */ 1.615 + int aux; 1.616 + StkId func = ci->func; 1.617 + StkId pfunc = (ci+1)->func; /* previous function index */ 1.618 + if (L->openupval) luaF_close(L, ci->base); 1.619 + L->base = ci->base = ci->func + ((ci+1)->base - pfunc); 1.620 + for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ 1.621 + setobjs2s(L, func+aux, pfunc+aux); 1.622 + ci->top = L->top = func+aux; /* correct top */ 1.623 + lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); 1.624 + ci->savedpc = L->savedpc; 1.625 + ci->tailcalls++; /* one more call lost */ 1.626 + L->ci--; /* remove new frame */ 1.627 + goto reentry; 1.628 + } 1.629 + case PCRC: { /* it was a C function (`precall' called it) */ 1.630 + base = L->base; 1.631 + continue; 1.632 + } 1.633 + default: { 1.634 + return; /* yield */ 1.635 + } 1.636 + } 1.637 + } 1.638 + case OP_RETURN: { 1.639 + int b = GETARG_B(i); 1.640 + if (b != 0) L->top = ra+b-1; 1.641 + if (L->openupval) luaF_close(L, base); 1.642 + L->savedpc = pc; 1.643 + b = luaD_poscall(L, ra); 1.644 + if (--nexeccalls == 0) /* was previous function running `here'? */ 1.645 + return; /* no: return */ 1.646 + else { /* yes: continue its execution */ 1.647 + if (b) L->top = L->ci->top; 1.648 + lua_assert(isLua(L->ci)); 1.649 + lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); 1.650 + goto reentry; 1.651 + } 1.652 + } 1.653 + case OP_FORLOOP: { 1.654 + lua_Number step = nvalue(ra+2); 1.655 + lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ 1.656 + lua_Number limit = nvalue(ra+1); 1.657 + if (luai_numlt(0, step) ? luai_numle(idx, limit) 1.658 + : luai_numle(limit, idx)) { 1.659 + dojump(L, pc, GETARG_sBx(i)); /* jump back */ 1.660 + setnvalue(ra, idx); /* update internal index... */ 1.661 + setnvalue(ra+3, idx); /* ...and external index */ 1.662 + } 1.663 + continue; 1.664 + } 1.665 + case OP_FORPREP: { 1.666 + const TValue *init = ra; 1.667 + const TValue *plimit = ra+1; 1.668 + const TValue *pstep = ra+2; 1.669 + L->savedpc = pc; /* next steps may throw errors */ 1.670 + if (!tonumber(init, ra)) 1.671 + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); 1.672 + else if (!tonumber(plimit, ra+1)) 1.673 + luaG_runerror(L, LUA_QL("for") " limit must be a number"); 1.674 + else if (!tonumber(pstep, ra+2)) 1.675 + luaG_runerror(L, LUA_QL("for") " step must be a number"); 1.676 + setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); 1.677 + dojump(L, pc, GETARG_sBx(i)); 1.678 + continue; 1.679 + } 1.680 + case OP_TFORLOOP: { 1.681 + StkId cb = ra + 3; /* call base */ 1.682 + setobjs2s(L, cb+2, ra+2); 1.683 + setobjs2s(L, cb+1, ra+1); 1.684 + setobjs2s(L, cb, ra); 1.685 + L->top = cb+3; /* func. + 2 args (state and index) */ 1.686 + Protect(luaD_call(L, cb, GETARG_C(i))); 1.687 + L->top = L->ci->top; 1.688 + cb = RA(i) + 3; /* previous call may change the stack */ 1.689 + if (!ttisnil(cb)) { /* continue loop? */ 1.690 + setobjs2s(L, cb-1, cb); /* save control variable */ 1.691 + dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ 1.692 + } 1.693 + pc++; 1.694 + continue; 1.695 + } 1.696 + case OP_SETLIST: { 1.697 + int n = GETARG_B(i); 1.698 + int c = GETARG_C(i); 1.699 + int last; 1.700 + Table *h; 1.701 + if (n == 0) { 1.702 + n = cast_int(L->top - ra) - 1; 1.703 + L->top = L->ci->top; 1.704 + } 1.705 + if (c == 0) c = cast_int(*pc++); 1.706 + runtime_check(L, ttistable(ra)); 1.707 + h = hvalue(ra); 1.708 + last = ((c-1)*LFIELDS_PER_FLUSH) + n; 1.709 + if (last > h->sizearray) /* needs more space? */ 1.710 + luaH_resizearray(L, h, last); /* pre-alloc it at once */ 1.711 + for (; n > 0; n--) { 1.712 + TValue *val = ra+n; 1.713 + setobj2t(L, luaH_setnum(L, h, last--), val); 1.714 + luaC_barriert(L, h, val); 1.715 + } 1.716 + continue; 1.717 + } 1.718 + case OP_CLOSE: { 1.719 + luaF_close(L, ra); 1.720 + continue; 1.721 + } 1.722 + case OP_CLOSURE: { 1.723 + Proto *p; 1.724 + Closure *ncl; 1.725 + int nup, j; 1.726 + p = cl->p->p[GETARG_Bx(i)]; 1.727 + nup = p->nups; 1.728 + ncl = luaF_newLclosure(L, nup, cl->env); 1.729 + ncl->l.p = p; 1.730 + for (j=0; j<nup; j++, pc++) { 1.731 + if (GET_OPCODE(*pc) == OP_GETUPVAL) 1.732 + ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; 1.733 + else { 1.734 + lua_assert(GET_OPCODE(*pc) == OP_MOVE); 1.735 + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); 1.736 + } 1.737 + } 1.738 + setclvalue(L, ra, ncl); 1.739 + Protect(luaC_checkGC(L)); 1.740 + continue; 1.741 + } 1.742 + case OP_VARARG: { 1.743 + int b = GETARG_B(i) - 1; 1.744 + int j; 1.745 + CallInfo *ci = L->ci; 1.746 + int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; 1.747 + if (b == LUA_MULTRET) { 1.748 + Protect(luaD_checkstack(L, n)); 1.749 + ra = RA(i); /* previous call may change the stack */ 1.750 + b = n; 1.751 + L->top = ra + n; 1.752 + } 1.753 + for (j = 0; j < b; j++) { 1.754 + if (j < n) { 1.755 + setobjs2s(L, ra + j, ci->base - n + j); 1.756 + } 1.757 + else { 1.758 + setnilvalue(ra + j); 1.759 + } 1.760 + } 1.761 + continue; 1.762 + } 1.763 + } 1.764 + } 1.765 +} 1.766 +