Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ceguilua/src/lua-5.0.3/lua/lvm.c @ 1803

Last change on this file since 1803 was 1803, checked in by rgrieder, 16 years ago

added files for lua 5.1.3, lua 5.0.3, CEGUILua-0.6.1 and CEGUILua-0.5.0b

  • Property svn:eol-style set to native
File size: 23.7 KB
Line 
1/*
2** $Id: lvm.c,v 1.284c 2003/04/03 13:35:34 roberto Exp $
3** Lua virtual machine
4** See Copyright Notice in lua.h
5*/
6
7
8#include <stdarg.h>
9#include <stdlib.h>
10#include <string.h>
11
12/* needed only when `lua_number2str' uses `sprintf' */
13#include <stdio.h>
14
15#define lvm_c
16
17#include "lua.h"
18
19#include "ldebug.h"
20#include "ldo.h"
21#include "lfunc.h"
22#include "lgc.h"
23#include "lobject.h"
24#include "lopcodes.h"
25#include "lstate.h"
26#include "lstring.h"
27#include "ltable.h"
28#include "ltm.h"
29#include "lvm.h"
30
31
32
33/* function to convert a lua_Number to a string */
34#ifndef lua_number2str
35#define lua_number2str(s,n)     sprintf((s), LUA_NUMBER_FMT, (n))
36#endif
37
38
39/* limit for table tag-method chains (to avoid loops) */
40#define MAXTAGLOOP      100
41
42
43const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
44  lua_Number num;
45  if (ttisnumber(obj)) return obj;
46  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
47    setnvalue(n, num);
48    return n;
49  }
50  else
51    return NULL;
52}
53
54
55int luaV_tostring (lua_State *L, StkId obj) {
56  if (!ttisnumber(obj))
57    return 0;
58  else {
59    char s[32];  /* 16 digits, sign, point and \0  (+ some extra...) */
60    lua_number2str(s, nvalue(obj));
61    setsvalue2s(obj, luaS_new(L, s));
62    return 1;
63  }
64}
65
66
67static void traceexec (lua_State *L) {
68  lu_byte mask = L->hookmask;
69  if (mask & LUA_MASKCOUNT) {  /* instruction-hook set? */
70    if (L->hookcount == 0) {
71      resethookcount(L);
72      luaD_callhook(L, LUA_HOOKCOUNT, -1);
73      return;
74    }
75  }
76  if (mask & LUA_MASKLINE) {
77    CallInfo *ci = L->ci;
78    Proto *p = ci_func(ci)->l.p;
79    int newline = getline(p, pcRel(*ci->u.l.pc, p));
80    if (!L->hookinit) {
81      luaG_inithooks(L);
82      return;
83    }
84    lua_assert(ci->state & CI_HASFRAME);
85    if (pcRel(*ci->u.l.pc, p) == 0)  /* tracing may be starting now? */
86      ci->u.l.savedpc = *ci->u.l.pc;  /* initialize `savedpc' */
87    /* calls linehook when enters a new line or jumps back (loop) */
88    if (*ci->u.l.pc <= ci->u.l.savedpc ||
89        newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
90      luaD_callhook(L, LUA_HOOKLINE, newline);
91      ci = L->ci;  /* previous call may reallocate `ci' */
92    }
93    ci->u.l.savedpc = *ci->u.l.pc;
94  }
95}
96
97
98static void callTMres (lua_State *L, const TObject *f,
99                       const TObject *p1, const TObject *p2) {
100  setobj2s(L->top, f);  /* push function */
101  setobj2s(L->top+1, p1);  /* 1st argument */
102  setobj2s(L->top+2, p2);  /* 2nd argument */
103  luaD_checkstack(L, 3);  /* cannot check before (could invalidate p1, p2) */
104  L->top += 3;
105  luaD_call(L, L->top - 3, 1);
106  L->top--;  /* result will be in L->top */
107}
108
109
110
111static void callTM (lua_State *L, const TObject *f,
112                    const TObject *p1, const TObject *p2, const TObject *p3) {
113  setobj2s(L->top, f);  /* push function */
114  setobj2s(L->top+1, p1);  /* 1st argument */
115  setobj2s(L->top+2, p2);  /* 2nd argument */
116  setobj2s(L->top+3, p3);  /* 3th argument */
117  luaD_checkstack(L, 4);  /* cannot check before (could invalidate p1...p3) */
118  L->top += 4;
119  luaD_call(L, L->top - 4, 0);
120}
121
122
123static const TObject *luaV_index (lua_State *L, const TObject *t,
124                                  TObject *key, int loop) {
125  const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
126  if (tm == NULL) return &luaO_nilobject;  /* no TM */
127  if (ttisfunction(tm)) {
128    callTMres(L, tm, t, key);
129    return L->top;
130  }
131  else return luaV_gettable(L, tm, key, loop);
132}
133
134static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
135                                       TObject *key, int loop) {
136  const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);
137  if (ttisnil(tm))
138    luaG_typeerror(L, t, "index");
139  if (ttisfunction(tm)) {
140    callTMres(L, tm, t, key);
141    return L->top;
142  }
143  else return luaV_gettable(L, tm, key, loop);
144}
145
146
147/*
148** Function to index a table.
149** Receives the table at `t' and the key at `key'.
150** leaves the result at `res'.
151*/
152const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
153                              int loop) {
154  if (loop > MAXTAGLOOP)
155    luaG_runerror(L, "loop in gettable");
156  if (ttistable(t)) {  /* `t' is a table? */
157    Table *h = hvalue(t);
158    const TObject *v = luaH_get(h, key);  /* do a primitive get */
159    if (!ttisnil(v)) return v;
160    else return luaV_index(L, t, key, loop+1);
161  }
162  else return luaV_getnotable(L, t, key, loop+1);
163}
164
165
166/*
167** Receives table at `t', key at `key' and value at `val'.
168*/
169void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
170  const TObject *tm;
171  int loop = 0;
172  do {
173    if (ttistable(t)) {  /* `t' is a table? */
174      Table *h = hvalue(t);
175      TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
176      if (!ttisnil(oldval) ||  /* result is no nil? */
177          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
178        setobj2t(oldval, val);  /* write barrier */
179        return;
180      }
181      /* else will try the tag method */
182    }
183    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
184      luaG_typeerror(L, t, "index");
185    if (ttisfunction(tm)) {
186      callTM(L, tm, t, key, val);
187      return;
188    }
189    t = tm;  /* else repeat with `tm' */ 
190  } while (++loop <= MAXTAGLOOP);
191  luaG_runerror(L, "loop in settable");
192}
193
194
195static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
196                       StkId res, TMS event) {
197  ptrdiff_t result = savestack(L, res);
198  const TObject *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
199  if (ttisnil(tm))
200    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
201  if (!ttisfunction(tm)) return 0;
202  callTMres(L, tm, p1, p2);
203  res = restorestack(L, result);  /* previous call may change stack */
204  setobjs2s(res, L->top);
205  return 1;
206}
207
208
209static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
210                                  TMS event) {
211  const TObject *tm1 = fasttm(L, mt1, event);
212  const TObject *tm2;
213  if (tm1 == NULL) return NULL;  /* no metamethod */
214  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */
215  tm2 = fasttm(L, mt2, event);
216  if (tm2 == NULL) return NULL;  /* no metamethod */
217  if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */
218    return tm1;
219  return NULL;
220}
221
222
223static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2,
224                         TMS event) {
225  const TObject *tm1 = luaT_gettmbyobj(L, p1, event);
226  const TObject *tm2;
227  if (ttisnil(tm1)) return -1;  /* no metamethod? */
228  tm2 = luaT_gettmbyobj(L, p2, event);
229  if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */
230    return -1;
231  callTMres(L, tm1, p1, p2);
232  return !l_isfalse(L->top);
233}
234
235
236static int luaV_strcmp (const TString *ls, const TString *rs) {
237  const char *l = getstr(ls);
238  size_t ll = ls->tsv.len;
239  const char *r = getstr(rs);
240  size_t lr = rs->tsv.len;
241  for (;;) {
242    int temp = strcoll(l, r);
243    if (temp != 0) return temp;
244    else {  /* strings are equal up to a `\0' */
245      size_t len = strlen(l);  /* index of first `\0' in both strings */
246      if (len == lr)  /* r is finished? */
247        return (len == ll) ? 0 : 1;
248      else if (len == ll)  /* l is finished? */
249        return -1;  /* l is smaller than r (because r is not finished) */
250      /* both strings longer than `len'; go on comparing (after the `\0') */
251      len++;
252      l += len; ll -= len; r += len; lr -= len;
253    }
254  }
255}
256
257
258int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
259  int res;
260  if (ttype(l) != ttype(r))
261    return luaG_ordererror(L, l, r);
262  else if (ttisnumber(l))
263    return nvalue(l) < nvalue(r);
264  else if (ttisstring(l))
265    return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
266  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
267    return res;
268  return luaG_ordererror(L, l, r);
269}
270
271
272static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
273  int res;
274  if (ttype(l) != ttype(r))
275    return luaG_ordererror(L, l, r);
276  else if (ttisnumber(l))
277    return nvalue(l) <= nvalue(r);
278  else if (ttisstring(l))
279    return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
280  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
281    return res;
282  else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */
283    return !res;
284  return luaG_ordererror(L, l, r);
285}
286
287
288int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
289  const TObject *tm;
290  lua_assert(ttype(t1) == ttype(t2));
291  switch (ttype(t1)) {
292    case LUA_TNIL: return 1;
293    case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
294    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
295    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
296    case LUA_TUSERDATA: {
297      if (uvalue(t1) == uvalue(t2)) return 1;
298      tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable,
299                         TM_EQ);
300      break;  /* will try TM */
301    }
302    case LUA_TTABLE: {
303      if (hvalue(t1) == hvalue(t2)) return 1;
304      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
305      break;  /* will try TM */
306    }
307    default: return gcvalue(t1) == gcvalue(t2);
308  }
309  if (tm == NULL) return 0;  /* no TM? */
310  callTMres(L, tm, t1, t2);  /* call TM */
311  return !l_isfalse(L->top);
312}
313
314
315void luaV_concat (lua_State *L, int total, int last) {
316  do {
317    StkId top = L->base + last + 1;
318    int n = 2;  /* number of elements handled in this pass (at least 2) */
319    if (!tostring(L, top-2) || !tostring(L, top-1)) {
320      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
321        luaG_concaterror(L, top-2, top-1);
322    } else if (tsvalue(top-1)->tsv.len > 0) {  /* if len=0, do nothing */
323      /* at least two string values; get as many as possible */
324      size_t tl = tsvalue(top-1)->tsv.len;
325      char *buffer;
326      int i;
327      /* collect total length */
328      for (n = 1; n < total && tostring(L, top-n-1); n++) {
329        size_t l = tsvalue(top-n-1)->tsv.len;
330        if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
331        tl += l;
332      }
333      buffer = luaZ_openspace(L, &G(L)->buff, tl);
334      tl = 0;
335      for (i=n; i>0; i--) {  /* concat all strings */
336        size_t l = tsvalue(top-i)->tsv.len;
337        memcpy(buffer+tl, svalue(top-i), l);
338        tl += l;
339      }
340      setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));
341    }
342    total -= n-1;  /* got `n' strings to create 1 new */
343    last -= n-1;
344  } while (total > 1);  /* repeat until only 1 result left */
345}
346
347
348static void Arith (lua_State *L, StkId ra,
349                   const TObject *rb, const TObject *rc, TMS op) {
350  TObject tempb, tempc;
351  const TObject *b, *c;
352  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
353      (c = luaV_tonumber(rc, &tempc)) != NULL) {
354    switch (op) {
355      case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break;
356      case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break;
357      case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;
358      case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;
359      case TM_POW: {
360        const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);
361        ptrdiff_t res = savestack(L, ra);
362        if (!ttisfunction(f))
363          luaG_runerror(L, "`__pow' (`^' operator) is not a function");
364        callTMres(L, f, b, c);
365        ra = restorestack(L, res);  /* previous call may change stack */
366        setobjs2s(ra, L->top);
367        break;
368      }
369      default: lua_assert(0); break;
370    }
371  }
372  else if (!call_binTM(L, rb, rc, ra, op))
373    luaG_aritherror(L, rb, rc);
374}
375
376
377
378/*
379** some macros for common tasks in `luaV_execute'
380*/
381
382#define runtime_check(L, c)     { if (!(c)) return 0; }
383
384#define RA(i)   (base+GETARG_A(i))
385/* to be used after possible stack reallocation */
386#define XRA(i)  (L->base+GETARG_A(i))
387#define RB(i)   (base+GETARG_B(i))
388#define RKB(i)  ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)
389#define RC(i)   (base+GETARG_C(i))
390#define RKC(i)  ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)
391#define KBx(i)  (k+GETARG_Bx(i))
392
393
394#define dojump(pc, i)   ((pc) += (i))
395
396
397StkId luaV_execute (lua_State *L) {
398  LClosure *cl;
399  TObject *k;
400  const Instruction *pc;
401 callentry:  /* entry point when calling new functions */
402  if (L->hookmask & LUA_MASKCALL) {
403    L->ci->u.l.pc = &pc;
404    luaD_callhook(L, LUA_HOOKCALL, -1);
405  }
406 retentry:  /* entry point when returning to old functions */
407  L->ci->u.l.pc = &pc;
408  lua_assert(L->ci->state == CI_SAVEDPC ||
409             L->ci->state == (CI_SAVEDPC | CI_CALLING));
410  L->ci->state = CI_HASFRAME;  /* activate frame */
411  pc = L->ci->u.l.savedpc;
412  cl = &clvalue(L->base - 1)->l;
413  k = cl->p->k;
414  /* main loop of interpreter */
415  for (;;) {
416    const Instruction i = *pc++;
417    StkId base, ra;
418    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
419        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
420      traceexec(L);
421      if (L->ci->state & CI_YIELD) {  /* did hook yield? */
422        L->ci->u.l.savedpc = pc - 1;
423        L->ci->state = CI_YIELD | CI_SAVEDPC;
424        return NULL;
425      }
426    }
427    /* warning!! several calls may realloc the stack and invalidate `ra' */
428    base = L->base;
429    ra = RA(i);
430    lua_assert(L->ci->state & CI_HASFRAME);
431    lua_assert(base == L->ci->base);
432    lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
433    lua_assert(L->top == L->ci->top ||
434         GET_OPCODE(i) == OP_CALL ||   GET_OPCODE(i) == OP_TAILCALL ||
435         GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
436    switch (GET_OPCODE(i)) {
437      case OP_MOVE: {
438        setobjs2s(ra, RB(i));
439        break;
440      }
441      case OP_LOADK: {
442        setobj2s(ra, KBx(i));
443        break;
444      }
445      case OP_LOADBOOL: {
446        setbvalue(ra, GETARG_B(i));
447        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
448        break;
449      }
450      case OP_LOADNIL: {
451        TObject *rb = RB(i);
452        do {
453          setnilvalue(rb--);
454        } while (rb >= ra);
455        break;
456      }
457      case OP_GETUPVAL: {
458        int b = GETARG_B(i);
459        setobj2s(ra, cl->upvals[b]->v);
460        break;
461      }
462      case OP_GETGLOBAL: {
463        TObject *rb = KBx(i);
464        const TObject *v;
465        lua_assert(ttisstring(rb) && ttistable(&cl->g));
466        v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
467        if (!ttisnil(v)) { setobj2s(ra, v); }
468        else
469          setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0));
470        break;
471      }
472      case OP_GETTABLE: {
473        StkId rb = RB(i);
474        TObject *rc = RKC(i);
475        if (ttistable(rb)) {
476          const TObject *v = luaH_get(hvalue(rb), rc);
477          if (!ttisnil(v)) { setobj2s(ra, v); }
478          else
479            setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
480        }
481        else
482          setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
483        break;
484      }
485      case OP_SETGLOBAL: {
486        lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
487        luaV_settable(L, &cl->g, KBx(i), ra);
488        break;
489      }
490      case OP_SETUPVAL: {
491        int b = GETARG_B(i);
492        setobj(cl->upvals[b]->v, ra);  /* write barrier */
493        break;
494      }
495      case OP_SETTABLE: {
496        luaV_settable(L, ra, RKB(i), RKC(i));
497        break;
498      }
499      case OP_NEWTABLE: {
500        int b = GETARG_B(i);
501        b = fb2int(b);
502        sethvalue(ra, luaH_new(L, b, GETARG_C(i)));
503        luaC_checkGC(L);
504        break;
505      }
506      case OP_SELF: {
507        StkId rb = RB(i);
508        TObject *rc = RKC(i);
509        runtime_check(L, ttisstring(rc));
510        setobjs2s(ra+1, rb);
511        if (ttistable(rb)) {
512          const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
513          if (!ttisnil(v)) { setobj2s(ra, v); }
514          else
515            setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
516        }
517        else
518          setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
519        break;
520      }
521      case OP_ADD: {
522        TObject *rb = RKB(i);
523        TObject *rc = RKC(i);
524        if (ttisnumber(rb) && ttisnumber(rc)) {
525          setnvalue(ra, nvalue(rb) + nvalue(rc));
526        }
527        else
528          Arith(L, ra, rb, rc, TM_ADD);
529        break;
530      }
531      case OP_SUB: {
532        TObject *rb = RKB(i);
533        TObject *rc = RKC(i);
534        if (ttisnumber(rb) && ttisnumber(rc)) {
535          setnvalue(ra, nvalue(rb) - nvalue(rc));
536        }
537        else
538          Arith(L, ra, rb, rc, TM_SUB);
539        break;
540      }
541      case OP_MUL: {
542        TObject *rb = RKB(i);
543        TObject *rc = RKC(i);
544        if (ttisnumber(rb) && ttisnumber(rc)) {
545          setnvalue(ra, nvalue(rb) * nvalue(rc));
546        }
547        else
548          Arith(L, ra, rb, rc, TM_MUL);
549        break;
550      }
551      case OP_DIV: {
552        TObject *rb = RKB(i);
553        TObject *rc = RKC(i);
554        if (ttisnumber(rb) && ttisnumber(rc)) {
555          setnvalue(ra, nvalue(rb) / nvalue(rc));
556        }
557        else
558          Arith(L, ra, rb, rc, TM_DIV);
559        break;
560      }
561      case OP_POW: {
562        Arith(L, ra, RKB(i), RKC(i), TM_POW);
563        break;
564      }
565      case OP_UNM: {
566        const TObject *rb = RB(i);
567        TObject temp;
568        if (tonumber(rb, &temp)) {
569          setnvalue(ra, -nvalue(rb));
570        }
571        else {
572          setnilvalue(&temp);
573          if (!call_binTM(L, RB(i), &temp, ra, TM_UNM))
574            luaG_aritherror(L, RB(i), &temp);
575        }
576        break;
577      }
578      case OP_NOT: {
579        int res = l_isfalse(RB(i));  /* next assignment may change this value */
580        setbvalue(ra, res);
581        break;
582      }
583      case OP_CONCAT: {
584        int b = GETARG_B(i);
585        int c = GETARG_C(i);
586        luaV_concat(L, c-b+1, c);  /* may change `base' (and `ra') */
587        base = L->base;
588        setobjs2s(RA(i), base+b);
589        luaC_checkGC(L);
590        break;
591      }
592      case OP_JMP: {
593        dojump(pc, GETARG_sBx(i));
594        break;
595      }
596      case OP_EQ: {
597        if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
598        else dojump(pc, GETARG_sBx(*pc) + 1);
599        break;
600      }
601      case OP_LT: {
602        if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
603        else dojump(pc, GETARG_sBx(*pc) + 1);
604        break;
605      }
606      case OP_LE: {
607        if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
608        else dojump(pc, GETARG_sBx(*pc) + 1);
609        break;
610      }
611      case OP_TEST: {
612        TObject *rb = RB(i);
613        if (l_isfalse(rb) == GETARG_C(i)) pc++;
614        else {
615          setobjs2s(ra, rb);
616          dojump(pc, GETARG_sBx(*pc) + 1);
617        }
618        break;
619      }
620      case OP_CALL:
621      case OP_TAILCALL: {
622        StkId firstResult;
623        int b = GETARG_B(i);
624        int nresults;
625        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
626        nresults = GETARG_C(i) - 1;
627        firstResult = luaD_precall(L, ra);
628        if (firstResult) {
629          if (firstResult > L->top) {  /* yield? */
630            lua_assert(L->ci->state == (CI_C | CI_YIELD));
631            (L->ci - 1)->u.l.savedpc = pc;
632            (L->ci - 1)->state = CI_SAVEDPC;
633            return NULL;
634          }
635          /* it was a C function (`precall' called it); adjust results */
636          luaD_poscall(L, nresults, firstResult);
637          if (nresults >= 0) L->top = L->ci->top;
638        }
639        else {  /* it is a Lua function */
640          if (GET_OPCODE(i) == OP_CALL) {  /* regular call? */
641            (L->ci-1)->u.l.savedpc = pc;  /* save `pc' to return later */
642            (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING);
643          }
644          else {  /* tail call: put new frame in place of previous one */
645            int aux;
646            base = (L->ci - 1)->base;  /* `luaD_precall' may change the stack */
647            ra = RA(i);
648            if (L->openupval) luaF_close(L, base);
649            for (aux = 0; ra+aux < L->top; aux++)  /* move frame down */
650              setobjs2s(base+aux-1, ra+aux);
651            (L->ci - 1)->top = L->top = base+aux;  /* correct top */
652            lua_assert(L->ci->state & CI_SAVEDPC);
653            (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
654            (L->ci - 1)->u.l.tailcalls++;  /* one more call lost */
655            (L->ci - 1)->state = CI_SAVEDPC;
656            L->ci--;  /* remove new frame */
657            L->base = L->ci->base;
658          }
659          goto callentry;
660        }
661        break;
662      }
663      case OP_RETURN: {
664        CallInfo *ci = L->ci - 1;  /* previous function frame */
665        int b = GETARG_B(i);
666        if (b != 0) L->top = ra+b-1;
667        lua_assert(L->ci->state & CI_HASFRAME);
668        if (L->openupval) luaF_close(L, base);
669        L->ci->state = CI_SAVEDPC;  /* deactivate current function */
670        L->ci->u.l.savedpc = pc;
671        /* previous function was running `here'? */
672        if (!(ci->state & CI_CALLING)) {
673          lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
674          return ra;  /* no: return */
675        }
676        else {  /* yes: continue its execution */
677          int nresults;
678          lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC));
679          lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
680          nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
681          luaD_poscall(L, nresults, ra);
682          if (nresults >= 0) L->top = L->ci->top;
683          goto retentry;
684        }
685      }
686      case OP_FORLOOP: {
687        lua_Number step, idx, limit;
688        const TObject *plimit = ra+1;
689        const TObject *pstep = ra+2;
690        if (!ttisnumber(ra))
691          luaG_runerror(L, "`for' initial value must be a number");
692        if (!tonumber(plimit, ra+1))
693          luaG_runerror(L, "`for' limit must be a number");
694        if (!tonumber(pstep, ra+2))
695          luaG_runerror(L, "`for' step must be a number");
696        step = nvalue(pstep);
697        idx = nvalue(ra) + step;  /* increment index */
698        limit = nvalue(plimit);
699        if (step > 0 ? idx <= limit : idx >= limit) {
700          dojump(pc, GETARG_sBx(i));  /* jump back */
701          chgnvalue(ra, idx);  /* update index */
702        }
703        break;
704      }
705      case OP_TFORLOOP: {
706        int nvar = GETARG_C(i) + 1;
707        StkId cb = ra + nvar + 2;  /* call base */
708        setobjs2s(cb, ra);
709        setobjs2s(cb+1, ra+1);
710        setobjs2s(cb+2, ra+2);
711        L->top = cb+3;  /* func. + 2 args (state and index) */
712        luaD_call(L, cb, nvar);
713        L->top = L->ci->top;
714        ra = XRA(i) + 2;  /* final position of first result */
715        cb = ra + nvar;
716        do {  /* move results to proper positions */
717          nvar--;
718          setobjs2s(ra+nvar, cb+nvar);
719        } while (nvar > 0);
720        if (ttisnil(ra))  /* break loop? */
721          pc++;  /* skip jump (break loop) */
722        else
723          dojump(pc, GETARG_sBx(*pc) + 1);  /* jump back */
724        break;
725      }
726      case OP_TFORPREP: {  /* for compatibility only */
727        if (ttistable(ra)) {
728          setobjs2s(ra+1, ra);
729          setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
730        }
731        dojump(pc, GETARG_sBx(i));
732        break;
733      }
734      case OP_SETLIST:
735      case OP_SETLISTO: {
736        int bc;
737        int n;
738        Table *h;
739        runtime_check(L, ttistable(ra));
740        h = hvalue(ra);
741        bc = GETARG_Bx(i);
742        if (GET_OPCODE(i) == OP_SETLIST)
743          n = (bc&(LFIELDS_PER_FLUSH-1)) + 1;
744        else {
745          n = L->top - ra - 1;
746          L->top = L->ci->top;
747        }
748        bc &= ~(LFIELDS_PER_FLUSH-1);  /* bc = bc - bc%FPF */
749        for (; n > 0; n--)
750          setobj2t(luaH_setnum(L, h, bc+n), ra+n);  /* write barrier */
751        break;
752      }
753      case OP_CLOSE: {
754        luaF_close(L, ra);
755        break;
756      }
757      case OP_CLOSURE: {
758        Proto *p;
759        Closure *ncl;
760        int nup, j;
761        p = cl->p->p[GETARG_Bx(i)];
762        nup = p->nups;
763        ncl = luaF_newLclosure(L, nup, &cl->g);
764        ncl->l.p = p;
765        for (j=0; j<nup; j++, pc++) {
766          if (GET_OPCODE(*pc) == OP_GETUPVAL)
767            ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
768          else {
769            lua_assert(GET_OPCODE(*pc) == OP_MOVE);
770            ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
771          }
772        }
773        setclvalue(ra, ncl);
774        luaC_checkGC(L);
775        break;
776      }
777    }
778  }
779}
780
781
Note: See TracBrowser for help on using the repository browser.