Imported from ../lua-3.1.tar.gz.
[lua.git] / src / lvm.c
blob72c26c1caaa331044436832620c6c17730840a91
1 /*
2 ** $Id: lvm.c,v 1.30 1998/06/11 18:21:37 roberto Exp $
3 ** Lua virtual machine
4 ** See Copyright Notice in lua.h
5 */
8 #include <stdio.h>
9 #include <string.h>
11 #include "lauxlib.h"
12 #include "ldo.h"
13 #include "lfunc.h"
14 #include "lgc.h"
15 #include "lmem.h"
16 #include "lopcodes.h"
17 #include "lstate.h"
18 #include "lstring.h"
19 #include "ltable.h"
20 #include "ltm.h"
21 #include "luadebug.h"
22 #include "lvm.h"
25 #ifdef OLD_ANSI
26 #define strcoll(a,b) strcmp(a,b)
27 #endif
30 #define skip_word(pc) (pc+=2)
31 #define get_word(pc) ((*(pc)<<8)+(*((pc)+1)))
32 #define next_word(pc) (pc+=2, get_word(pc-2))
35 /* Extra stack size to run a function: LUA_T_LINE(1), TM calls(2), ... */
36 #define EXTRA_STACK 5
40 static TaggedString *strconc (TaggedString *l, TaggedString *r)
42 size_t nl = l->u.s.len;
43 size_t nr = r->u.s.len;
44 char *buffer = luaL_openspace(nl+nr+1);
45 memcpy(buffer, l->str, nl);
46 memcpy(buffer+nl, r->str, nr);
47 return luaS_newlstr(buffer, nl+nr);
51 int luaV_tonumber (TObject *obj)
52 { /* LUA_NUMBER */
53 double t;
54 char c;
55 if (ttype(obj) != LUA_T_STRING)
56 return 1;
57 else if (sscanf(svalue(obj), "%lf %c",&t, &c) == 1) {
58 nvalue(obj) = (real)t;
59 ttype(obj) = LUA_T_NUMBER;
60 return 0;
62 else
63 return 2;
67 int luaV_tostring (TObject *obj)
68 { /* LUA_NUMBER */
69 if (ttype(obj) != LUA_T_NUMBER)
70 return 1;
71 else {
72 char s[60];
73 real f = nvalue(obj);
74 int i;
75 if ((real)(-MAX_INT) <= f && f <= (real)MAX_INT && (real)(i=(int)f) == f)
76 sprintf (s, "%d", i);
77 else
78 sprintf (s, NUMBER_FMT, nvalue(obj));
79 tsvalue(obj) = luaS_new(s);
80 ttype(obj) = LUA_T_STRING;
81 return 0;
86 void luaV_closure (int nelems)
88 if (nelems > 0) {
89 struct Stack *S = &L->stack;
90 Closure *c = luaF_newclosure(nelems);
91 c->consts[0] = *(S->top-1);
92 memcpy(&c->consts[1], S->top-(nelems+1), nelems*sizeof(TObject));
93 S->top -= nelems;
94 ttype(S->top-1) = LUA_T_CLOSURE;
95 (S->top-1)->value.cl = c;
101 ** Function to index a table.
102 ** Receives the table at top-2 and the index at top-1.
104 void luaV_gettable (void)
106 struct Stack *S = &L->stack;
107 TObject *im;
108 if (ttype(S->top-2) != LUA_T_ARRAY) /* not a table, get "gettable" method */
109 im = luaT_getimbyObj(S->top-2, IM_GETTABLE);
110 else { /* object is a table... */
111 int tg = (S->top-2)->value.a->htag;
112 im = luaT_getim(tg, IM_GETTABLE);
113 if (ttype(im) == LUA_T_NIL) { /* and does not have a "gettable" method */
114 TObject *h = luaH_get(avalue(S->top-2), S->top-1);
115 if (h != NULL && ttype(h) != LUA_T_NIL) {
116 --S->top;
117 *(S->top-1) = *h;
119 else if (ttype(im=luaT_getim(tg, IM_INDEX)) != LUA_T_NIL)
120 luaD_callTM(im, 2, 1);
121 else {
122 --S->top;
123 ttype(S->top-1) = LUA_T_NIL;
125 return;
127 /* else it has a "gettable" method, go through to next command */
129 /* object is not a table, or it has a "gettable" method */
130 if (ttype(im) != LUA_T_NIL)
131 luaD_callTM(im, 2, 1);
132 else
133 lua_error("indexed expression not a table");
138 ** Function to store indexed based on values at the stack.top
139 ** mode = 0: raw store (without tag methods)
140 ** mode = 1: normal store (with tag methods)
141 ** mode = 2: "deep L->stack.stack" store (with tag methods)
143 void luaV_settable (TObject *t, int mode)
145 struct Stack *S = &L->stack;
146 TObject *im = (mode == 0) ? NULL : luaT_getimbyObj(t, IM_SETTABLE);
147 if (ttype(t) == LUA_T_ARRAY && (im == NULL || ttype(im) == LUA_T_NIL)) {
148 TObject *h = luaH_set(avalue(t), t+1);
149 *h = *(S->top-1);
150 S->top -= (mode == 2) ? 1 : 3;
152 else { /* object is not a table, and/or has a specific "settable" method */
153 if (im && ttype(im) != LUA_T_NIL) {
154 if (mode == 2) {
155 *(S->top+1) = *(L->stack.top-1);
156 *(S->top) = *(t+1);
157 *(S->top-1) = *t;
158 S->top += 2; /* WARNING: caller must assure stack space */
160 luaD_callTM(im, 3, 0);
162 else
163 lua_error("indexed expression not a table");
168 void luaV_getglobal (TaggedString *ts)
170 /* WARNING: caller must assure stack space */
171 TObject *value = &ts->u.s.globalval;
172 TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL);
173 if (ttype(im) == LUA_T_NIL) { /* default behavior */
174 *L->stack.top++ = *value;
176 else {
177 struct Stack *S = &L->stack;
178 ttype(S->top) = LUA_T_STRING;
179 tsvalue(S->top) = ts;
180 S->top++;
181 *S->top++ = *value;
182 luaD_callTM(im, 2, 1);
187 void luaV_setglobal (TaggedString *ts)
189 TObject *oldvalue = &ts->u.s.globalval;
190 TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
191 if (ttype(im) == LUA_T_NIL) /* default behavior */
192 luaS_rawsetglobal(ts, --L->stack.top);
193 else {
194 /* WARNING: caller must assure stack space */
195 struct Stack *S = &L->stack;
196 TObject newvalue = *(S->top-1);
197 ttype(S->top-1) = LUA_T_STRING;
198 tsvalue(S->top-1) = ts;
199 *S->top++ = *oldvalue;
200 *S->top++ = newvalue;
201 luaD_callTM(im, 3, 0);
206 static void call_binTM (IMS event, char *msg)
208 TObject *im = luaT_getimbyObj(L->stack.top-2, event);/* try first operand */
209 if (ttype(im) == LUA_T_NIL) {
210 im = luaT_getimbyObj(L->stack.top-1, event); /* try second operand */
211 if (ttype(im) == LUA_T_NIL) {
212 im = luaT_getim(0, event); /* try a 'global' i.m. */
213 if (ttype(im) == LUA_T_NIL)
214 lua_error(msg);
217 lua_pushstring(luaT_eventname[event]);
218 luaD_callTM(im, 3, 1);
222 static void call_arith (IMS event)
224 call_binTM(event, "unexpected type in arithmetic operation");
228 static int strcomp (char *l, long ll, char *r, long lr)
230 for (;;) {
231 long temp = strcoll(l, r);
232 if (temp != 0) return temp;
233 /* strings are equal up to a '\0' */
234 temp = strlen(l); /* index of first '\0' in both strings */
235 if (temp == ll) /* l is finished? */
236 return (temp == lr) ? 0 : -1; /* l is equal or smaller than r */
237 else if (temp == lr) /* r is finished? */
238 return 1; /* l is greater than r (because l is not finished) */
239 /* both strings longer than temp; go on comparing (after the '\0') */
240 temp++;
241 l += temp; ll -= temp; r += temp; lr -= temp;
245 static void comparison (lua_Type ttype_less, lua_Type ttype_equal,
246 lua_Type ttype_great, IMS op)
248 struct Stack *S = &L->stack;
249 TObject *l = S->top-2;
250 TObject *r = S->top-1;
251 int result;
252 if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER)
253 result = (nvalue(l) < nvalue(r)) ? -1 : (nvalue(l) == nvalue(r)) ? 0 : 1;
254 else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING)
255 result = strcomp(svalue(l), tsvalue(l)->u.s.len,
256 svalue(r), tsvalue(r)->u.s.len);
257 else {
258 call_binTM(op, "unexpected type in comparison");
259 return;
261 S->top--;
262 nvalue(S->top-1) = 1;
263 ttype(S->top-1) = (result < 0) ? ttype_less :
264 (result == 0) ? ttype_equal : ttype_great;
268 void luaV_pack (StkId firstel, int nvararg, TObject *tab)
270 TObject *firstelem = L->stack.stack+firstel;
271 int i;
272 if (nvararg < 0) nvararg = 0;
273 avalue(tab) = luaH_new(nvararg+1); /* +1 for field 'n' */
274 ttype(tab) = LUA_T_ARRAY;
275 for (i=0; i<nvararg; i++) {
276 TObject index;
277 ttype(&index) = LUA_T_NUMBER;
278 nvalue(&index) = i+1;
279 *(luaH_set(avalue(tab), &index)) = *(firstelem+i);
281 /* store counter in field "n" */ {
282 TObject index, extra;
283 ttype(&index) = LUA_T_STRING;
284 tsvalue(&index) = luaS_new("n");
285 ttype(&extra) = LUA_T_NUMBER;
286 nvalue(&extra) = nvararg;
287 *(luaH_set(avalue(tab), &index)) = extra;
292 static void adjust_varargs (StkId first_extra_arg)
294 TObject arg;
295 luaV_pack(first_extra_arg,
296 (L->stack.top-L->stack.stack)-first_extra_arg, &arg);
297 luaD_adjusttop(first_extra_arg);
298 *L->stack.top++ = arg;
304 ** Execute the given opcode, until a RET. Parameters are between
305 ** [stack+base,top). Returns n such that the the results are between
306 ** [stack+n,top).
308 StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base)
310 struct Stack *S = &L->stack; /* to optimize */
311 Byte *pc = tf->code;
312 TObject *consts = tf->consts;
313 if (lua_callhook)
314 luaD_callHook(base, tf, 0);
315 luaD_checkstack((*pc++)+EXTRA_STACK);
316 if (*pc < ZEROVARARG)
317 luaD_adjusttop(base+*(pc++));
318 else { /* varargs */
319 luaC_checkGC();
320 adjust_varargs(base+(*pc++)-ZEROVARARG);
322 while (1) {
323 int aux;
324 switch ((OpCode)(aux = *pc++)) {
326 case PUSHNIL0:
327 ttype(S->top++) = LUA_T_NIL;
328 break;
330 case PUSHNIL:
331 aux = *pc++;
332 do {
333 ttype(S->top++) = LUA_T_NIL;
334 } while (aux--);
335 break;
337 case PUSHNUMBER:
338 aux = *pc++; goto pushnumber;
340 case PUSHNUMBERW:
341 aux = next_word(pc); goto pushnumber;
343 case PUSHNUMBER0: case PUSHNUMBER1: case PUSHNUMBER2:
344 aux -= PUSHNUMBER0;
345 pushnumber:
346 ttype(S->top) = LUA_T_NUMBER;
347 nvalue(S->top) = aux;
348 S->top++;
349 break;
351 case PUSHLOCAL:
352 aux = *pc++; goto pushlocal;
354 case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3:
355 case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7:
356 aux -= PUSHLOCAL0;
357 pushlocal:
358 *S->top++ = *((S->stack+base) + aux);
359 break;
361 case GETGLOBALW:
362 aux = next_word(pc); goto getglobal;
364 case GETGLOBAL:
365 aux = *pc++; goto getglobal;
367 case GETGLOBAL0: case GETGLOBAL1: case GETGLOBAL2: case GETGLOBAL3:
368 case GETGLOBAL4: case GETGLOBAL5: case GETGLOBAL6: case GETGLOBAL7:
369 aux -= GETGLOBAL0;
370 getglobal:
371 luaV_getglobal(tsvalue(&consts[aux]));
372 break;
374 case GETTABLE:
375 luaV_gettable();
376 break;
378 case GETDOTTEDW:
379 aux = next_word(pc); goto getdotted;
381 case GETDOTTED:
382 aux = *pc++; goto getdotted;
384 case GETDOTTED0: case GETDOTTED1: case GETDOTTED2: case GETDOTTED3:
385 case GETDOTTED4: case GETDOTTED5: case GETDOTTED6: case GETDOTTED7:
386 aux -= GETDOTTED0;
387 getdotted:
388 *S->top++ = consts[aux];
389 luaV_gettable();
390 break;
392 case PUSHSELFW:
393 aux = next_word(pc); goto pushself;
395 case PUSHSELF:
396 aux = *pc++; goto pushself;
398 case PUSHSELF0: case PUSHSELF1: case PUSHSELF2: case PUSHSELF3:
399 case PUSHSELF4: case PUSHSELF5: case PUSHSELF6: case PUSHSELF7:
400 aux -= PUSHSELF0;
401 pushself: {
402 TObject receiver = *(S->top-1);
403 *S->top++ = consts[aux];
404 luaV_gettable();
405 *S->top++ = receiver;
406 break;
409 case PUSHCONSTANTW:
410 aux = next_word(pc); goto pushconstant;
412 case PUSHCONSTANT:
413 aux = *pc++; goto pushconstant;
415 case PUSHCONSTANT0: case PUSHCONSTANT1: case PUSHCONSTANT2:
416 case PUSHCONSTANT3: case PUSHCONSTANT4: case PUSHCONSTANT5:
417 case PUSHCONSTANT6: case PUSHCONSTANT7:
418 aux -= PUSHCONSTANT0;
419 pushconstant:
420 *S->top++ = consts[aux];
421 break;
423 case PUSHUPVALUE:
424 aux = *pc++; goto pushupvalue;
426 case PUSHUPVALUE0: case PUSHUPVALUE1:
427 aux -= PUSHUPVALUE0;
428 pushupvalue:
429 *S->top++ = cl->consts[aux+1];
430 break;
432 case SETLOCAL:
433 aux = *pc++; goto setlocal;
435 case SETLOCAL0: case SETLOCAL1: case SETLOCAL2: case SETLOCAL3:
436 case SETLOCAL4: case SETLOCAL5: case SETLOCAL6: case SETLOCAL7:
437 aux -= SETLOCAL0;
438 setlocal:
439 *((S->stack+base) + aux) = *(--S->top);
440 break;
442 case SETGLOBALW:
443 aux = next_word(pc); goto setglobal;
445 case SETGLOBAL:
446 aux = *pc++; goto setglobal;
448 case SETGLOBAL0: case SETGLOBAL1: case SETGLOBAL2: case SETGLOBAL3:
449 case SETGLOBAL4: case SETGLOBAL5: case SETGLOBAL6: case SETGLOBAL7:
450 aux -= SETGLOBAL0;
451 setglobal:
452 luaV_setglobal(tsvalue(&consts[aux]));
453 break;
455 case SETTABLE0:
456 luaV_settable(S->top-3, 1);
457 break;
459 case SETTABLE:
460 luaV_settable(S->top-3-(*pc++), 2);
461 break;
463 case SETLISTW:
464 aux = next_word(pc); aux *= LFIELDS_PER_FLUSH; goto setlist;
466 case SETLIST:
467 aux = *(pc++) * LFIELDS_PER_FLUSH; goto setlist;
469 case SETLIST0:
470 aux = 0;
471 setlist: {
472 int n = *(pc++);
473 TObject *arr = S->top-n-1;
474 for (; n; n--) {
475 ttype(S->top) = LUA_T_NUMBER;
476 nvalue(S->top) = n+aux;
477 *(luaH_set(avalue(arr), S->top)) = *(S->top-1);
478 S->top--;
480 break;
483 case SETMAP0:
484 aux = 0; goto setmap;
486 case SETMAP:
487 aux = *pc++;
488 setmap: {
489 TObject *arr = S->top-(2*aux)-3;
490 do {
491 *(luaH_set(avalue(arr), S->top-2)) = *(S->top-1);
492 S->top-=2;
493 } while (aux--);
494 break;
497 case POP:
498 aux = *pc++; goto pop;
500 case POP0: case POP1:
501 aux -= POP0;
502 pop:
503 S->top -= (aux+1);
504 break;
506 case CREATEARRAYW:
507 aux = next_word(pc); goto createarray;
509 case CREATEARRAY0: case CREATEARRAY1:
510 aux -= CREATEARRAY0; goto createarray;
512 case CREATEARRAY:
513 aux = *pc++;
514 createarray:
515 luaC_checkGC();
516 avalue(S->top) = luaH_new(aux);
517 ttype(S->top) = LUA_T_ARRAY;
518 S->top++;
519 break;
521 case EQOP: case NEQOP: {
522 int res = luaO_equalObj(S->top-2, S->top-1);
523 S->top--;
524 if (aux == NEQOP) res = !res;
525 ttype(S->top-1) = res ? LUA_T_NUMBER : LUA_T_NIL;
526 nvalue(S->top-1) = 1;
527 break;
530 case LTOP:
531 comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
532 break;
534 case LEOP:
535 comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE);
536 break;
538 case GTOP:
539 comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT);
540 break;
542 case GEOP:
543 comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE);
544 break;
546 case ADDOP: {
547 TObject *l = S->top-2;
548 TObject *r = S->top-1;
549 if (tonumber(r) || tonumber(l))
550 call_arith(IM_ADD);
551 else {
552 nvalue(l) += nvalue(r);
553 --S->top;
555 break;
558 case SUBOP: {
559 TObject *l = S->top-2;
560 TObject *r = S->top-1;
561 if (tonumber(r) || tonumber(l))
562 call_arith(IM_SUB);
563 else {
564 nvalue(l) -= nvalue(r);
565 --S->top;
567 break;
570 case MULTOP: {
571 TObject *l = S->top-2;
572 TObject *r = S->top-1;
573 if (tonumber(r) || tonumber(l))
574 call_arith(IM_MUL);
575 else {
576 nvalue(l) *= nvalue(r);
577 --S->top;
579 break;
582 case DIVOP: {
583 TObject *l = S->top-2;
584 TObject *r = S->top-1;
585 if (tonumber(r) || tonumber(l))
586 call_arith(IM_DIV);
587 else {
588 nvalue(l) /= nvalue(r);
589 --S->top;
591 break;
594 case POWOP:
595 call_binTM(IM_POW, "undefined operation");
596 break;
598 case CONCOP: {
599 TObject *l = S->top-2;
600 TObject *r = S->top-1;
601 if (tostring(l) || tostring(r))
602 call_binTM(IM_CONCAT, "unexpected type for concatenation");
603 else {
604 tsvalue(l) = strconc(tsvalue(l), tsvalue(r));
605 --S->top;
607 luaC_checkGC();
608 break;
611 case MINUSOP:
612 if (tonumber(S->top-1)) {
613 ttype(S->top) = LUA_T_NIL;
614 S->top++;
615 call_arith(IM_UNM);
617 else
618 nvalue(S->top-1) = - nvalue(S->top-1);
619 break;
621 case NOTOP:
622 ttype(S->top-1) =
623 (ttype(S->top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL;
624 nvalue(S->top-1) = 1;
625 break;
627 case ONTJMPW:
628 aux = next_word(pc); goto ontjmp;
630 case ONTJMP:
631 aux = *pc++;
632 ontjmp:
633 if (ttype(S->top-1) != LUA_T_NIL) pc += aux;
634 else S->top--;
635 break;
637 case ONFJMPW:
638 aux = next_word(pc); goto onfjmp;
640 case ONFJMP:
641 aux = *pc++;
642 onfjmp:
643 if (ttype(S->top-1) == LUA_T_NIL) pc += aux;
644 else S->top--;
645 break;
647 case JMPW:
648 aux = next_word(pc); goto jmp;
650 case JMP:
651 aux = *pc++;
652 jmp:
653 pc += aux;
654 break;
656 case IFFJMPW:
657 aux = next_word(pc); goto iffjmp;
659 case IFFJMP:
660 aux = *pc++;
661 iffjmp:
662 if (ttype(--S->top) == LUA_T_NIL) pc += aux;
663 break;
665 case IFTUPJMPW:
666 aux = next_word(pc); goto iftupjmp;
668 case IFTUPJMP:
669 aux = *pc++;
670 iftupjmp:
671 if (ttype(--S->top) != LUA_T_NIL) pc -= aux;
672 break;
674 case IFFUPJMPW:
675 aux = next_word(pc); goto iffupjmp;
677 case IFFUPJMP:
678 aux = *pc++;
679 iffupjmp:
680 if (ttype(--S->top) == LUA_T_NIL) pc -= aux;
681 break;
683 case CLOSUREW:
684 aux = next_word(pc); goto closure;
686 case CLOSURE:
687 aux = *pc++;
688 closure:
689 *S->top++ = consts[aux];
690 luaV_closure(*pc++);
691 luaC_checkGC();
692 break;
694 case CALLFUNC:
695 aux = *pc++; goto callfunc;
697 case CALLFUNC0: case CALLFUNC1:
698 aux -= CALLFUNC0;
699 callfunc: {
700 StkId newBase = (S->top-S->stack)-(*pc++);
701 luaD_call(newBase, aux);
702 break;
705 case ENDCODE:
706 S->top = S->stack + base;
707 /* goes through */
708 case RETCODE:
709 if (lua_callhook)
710 luaD_callHook(base, NULL, 1);
711 return (base + ((aux==RETCODE) ? *pc : 0));
713 case SETLINEW:
714 aux = next_word(pc); goto setline;
716 case SETLINE:
717 aux = *pc++;
718 setline:
719 if ((S->stack+base-1)->ttype != LUA_T_LINE) {
720 /* open space for LINE value */
721 luaD_openstack((S->top-S->stack)-base);
722 base++;
723 (S->stack+base-1)->ttype = LUA_T_LINE;
725 (S->stack+base-1)->value.i = aux;
726 if (lua_linehook)
727 luaD_lineHook(aux);
728 break;
730 #ifdef DEBUG
731 default:
732 LUA_INTERNALERROR("opcode doesn't match");
733 #endif