diff options
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 78 |
1 files changed, 41 insertions, 37 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.165 2013/04/26 16:06:53 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.166 2013/04/26 19:51:17 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -56,6 +56,28 @@ int luaV_tostring (lua_State *L, StkId obj) { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
59 | int luaV_numtointeger (lua_Number n, lua_Integer *p) { | ||
60 | lua_Integer k; | ||
61 | lua_number2integer(k, n); | ||
62 | if (luai_numeq(cast_num(k), n)) { /* 'k' is int? */ | ||
63 | *p = k; | ||
64 | return 1; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | |||
70 | int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { | ||
71 | lua_Number n; | ||
72 | lua_assert(!ttisinteger(obj)); | ||
73 | if (tonumber(obj, &n)) { | ||
74 | n = l_mathop(floor)(n); | ||
75 | return luaV_numtointeger(n, p); | ||
76 | } | ||
77 | else return 0; | ||
78 | } | ||
79 | |||
80 | |||
59 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 81 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { |
60 | int loop; | 82 | int loop; |
61 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 83 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
@@ -225,10 +247,8 @@ void luaV_concat (lua_State *L, int total) { | |||
225 | do { | 247 | do { |
226 | StkId top = L->top; | 248 | StkId top = L->top; |
227 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 249 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
228 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { | 250 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) |
229 | if (!luaT_callbinTM(L, top-2, top-1, top-2, TM_CONCAT)) | 251 | luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); |
230 | luaG_concaterror(L, top-2, top-1); | ||
231 | } | ||
232 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ | 252 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ |
233 | (void)tostring(L, top - 2); /* result is first operand */ | 253 | (void)tostring(L, top - 2); /* result is first operand */ |
234 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { | 254 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { |
@@ -335,18 +355,6 @@ lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { | |||
335 | } | 355 | } |
336 | 356 | ||
337 | 357 | ||
338 | void luaV_arith (lua_State *L, StkId ra, const TValue *rb, | ||
339 | const TValue *rc, TMS op) { | ||
340 | lua_Number b, c; | ||
341 | if (tonumber(rb, &b) && tonumber(rc, &c)) { | ||
342 | lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, b, c); | ||
343 | setnvalue(ra, res); | ||
344 | } | ||
345 | else if (!luaT_callbinTM(L, rb, rc, ra, op)) | ||
346 | luaG_aritherror(L, rb, rc); | ||
347 | } | ||
348 | |||
349 | |||
350 | /* | 358 | /* |
351 | ** check whether cached closure in prototype 'p' may be reused, that is, | 359 | ** check whether cached closure in prototype 'p' may be reused, that is, |
352 | ** whether there is a cached closure with the same upvalues needed by | 360 | ** whether there is a cached closure with the same upvalues needed by |
@@ -422,7 +430,7 @@ void luaV_finishOp (lua_State *L) { | |||
422 | break; | 430 | break; |
423 | } | 431 | } |
424 | case OP_CONCAT: { | 432 | case OP_CONCAT: { |
425 | StkId top = L->top - 1; /* top when 'luaT_callbinTM' was called */ | 433 | StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ |
426 | int b = GETARG_B(inst); /* first element to concatenate */ | 434 | int b = GETARG_B(inst); /* first element to concatenate */ |
427 | int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ | 435 | int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ |
428 | setobj2s(L, top - 2, top); /* put TM result in proper position */ | 436 | setobj2s(L, top - 2, top); /* put TM result in proper position */ |
@@ -586,12 +594,12 @@ void luaV_execute (lua_State *L) { | |||
586 | lua_Number nb; lua_Number nc; | 594 | lua_Number nb; lua_Number nc; |
587 | if (ttisinteger(rb) && ttisinteger(rc)) { | 595 | if (ttisinteger(rb) && ttisinteger(rc)) { |
588 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); | 596 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); |
589 | setivalue(ra, ib + ic); | 597 | setivalue(ra, cast_integer(cast_unsigned(ib) + cast_unsigned(ic))); |
590 | } | 598 | } |
591 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 599 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
592 | setnvalue(ra, luai_numadd(L, nb, nc)); | 600 | setnvalue(ra, luai_numadd(L, nb, nc)); |
593 | } | 601 | } |
594 | else { Protect(luaV_arith(L, ra, rb, rc, TM_ADD)); } | 602 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } |
595 | ) | 603 | ) |
596 | vmcase(OP_SUB, | 604 | vmcase(OP_SUB, |
597 | TValue *rb = RKB(i); | 605 | TValue *rb = RKB(i); |
@@ -599,12 +607,12 @@ void luaV_execute (lua_State *L) { | |||
599 | lua_Number nb; lua_Number nc; | 607 | lua_Number nb; lua_Number nc; |
600 | if (ttisinteger(rb) && ttisinteger(rc)) { | 608 | if (ttisinteger(rb) && ttisinteger(rc)) { |
601 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); | 609 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); |
602 | setivalue(ra, ib - ic); | 610 | setivalue(ra, cast_integer(cast_unsigned(ib) - cast_unsigned(ic))); |
603 | } | 611 | } |
604 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 612 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
605 | setnvalue(ra, luai_numsub(L, nb, nc)); | 613 | setnvalue(ra, luai_numsub(L, nb, nc)); |
606 | } | 614 | } |
607 | else { Protect(luaV_arith(L, ra, rb, rc, TM_SUB)); } | 615 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } |
608 | ) | 616 | ) |
609 | vmcase(OP_MUL, | 617 | vmcase(OP_MUL, |
610 | TValue *rb = RKB(i); | 618 | TValue *rb = RKB(i); |
@@ -612,12 +620,12 @@ void luaV_execute (lua_State *L) { | |||
612 | lua_Number nb; lua_Number nc; | 620 | lua_Number nb; lua_Number nc; |
613 | if (ttisinteger(rb) && ttisinteger(rc)) { | 621 | if (ttisinteger(rb) && ttisinteger(rc)) { |
614 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); | 622 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); |
615 | setivalue(ra, ib * ic); | 623 | setivalue(ra, cast_integer(cast_unsigned(ib) * cast_unsigned(ic))); |
616 | } | 624 | } |
617 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 625 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
618 | setnvalue(ra, luai_nummul(L, nb, nc)); | 626 | setnvalue(ra, luai_nummul(L, nb, nc)); |
619 | } | 627 | } |
620 | else { Protect(luaV_arith(L, ra, rb, rc, TM_MUL)); } | 628 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } |
621 | ) | 629 | ) |
622 | vmcase(OP_DIV, /* float division (always with floats) */ | 630 | vmcase(OP_DIV, /* float division (always with floats) */ |
623 | TValue *rb = RKB(i); | 631 | TValue *rb = RKB(i); |
@@ -626,20 +634,16 @@ void luaV_execute (lua_State *L) { | |||
626 | if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 634 | if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
627 | setnvalue(ra, luai_numdiv(L, nb, nc)); | 635 | setnvalue(ra, luai_numdiv(L, nb, nc)); |
628 | } | 636 | } |
629 | else { Protect(luaV_arith(L, ra, rb, rc, TM_DIV)); } | 637 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } |
630 | ) | 638 | ) |
631 | vmcase(OP_IDIV, /* integer division */ | 639 | vmcase(OP_IDIV, /* integer division */ |
632 | TValue *rb = RKB(i); | 640 | TValue *rb = RKB(i); |
633 | TValue *rc = RKC(i); | 641 | TValue *rc = RKC(i); |
634 | lua_Number nb; lua_Number nc; | 642 | lua_Integer ib; lua_Integer ic; |
635 | if (ttisinteger(rb) && ttisinteger(rc)) { | 643 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { |
636 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); | ||
637 | setivalue(ra, luaV_div(L, ib, ic)); | 644 | setivalue(ra, luaV_div(L, ib, ic)); |
638 | } | 645 | } |
639 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 646 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } |
640 | setnvalue(ra, luai_numidiv(L, nb, nc)); | ||
641 | } | ||
642 | else { Protect(luaV_arith(L, ra, rb, rc, TM_IDIV)); } | ||
643 | ) | 647 | ) |
644 | vmcase(OP_MOD, | 648 | vmcase(OP_MOD, |
645 | TValue *rb = RKB(i); | 649 | TValue *rb = RKB(i); |
@@ -652,7 +656,7 @@ void luaV_execute (lua_State *L) { | |||
652 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 656 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
653 | setnvalue(ra, luai_nummod(L, nb, nc)); | 657 | setnvalue(ra, luai_nummod(L, nb, nc)); |
654 | } | 658 | } |
655 | else { Protect(luaV_arith(L, ra, rb, rc, TM_MOD)); } | 659 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } |
656 | ) | 660 | ) |
657 | vmcase(OP_POW, | 661 | vmcase(OP_POW, |
658 | TValue *rb = RKB(i); | 662 | TValue *rb = RKB(i); |
@@ -667,20 +671,20 @@ void luaV_execute (lua_State *L) { | |||
667 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 671 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
668 | setnvalue(ra, luai_numpow(L, nb, nc)); | 672 | setnvalue(ra, luai_numpow(L, nb, nc)); |
669 | } | 673 | } |
670 | else { Protect(luaV_arith(L, ra, rb, rc, TM_POW)); } | 674 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } |
671 | ) | 675 | ) |
672 | vmcase(OP_UNM, | 676 | vmcase(OP_UNM, |
673 | TValue *rb = RB(i); | 677 | TValue *rb = RB(i); |
678 | lua_Number nb; | ||
674 | if (ttisinteger(rb)) { | 679 | if (ttisinteger(rb)) { |
675 | lua_Integer ib = ivalue(rb); | 680 | lua_Integer ib = ivalue(rb); |
676 | setivalue(ra, -ib); | 681 | setivalue(ra, -ib); |
677 | } | 682 | } |
678 | else if (ttisfloat(rb)) { | 683 | else if (tonumber(rb, &nb)) { |
679 | lua_Number nb = fltvalue(rb); | ||
680 | setnvalue(ra, luai_numunm(L, nb)); | 684 | setnvalue(ra, luai_numunm(L, nb)); |
681 | } | 685 | } |
682 | else { | 686 | else { |
683 | Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); | 687 | Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); |
684 | } | 688 | } |
685 | ) | 689 | ) |
686 | vmcase(OP_NOT, | 690 | vmcase(OP_NOT, |