diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-24 11:11:14 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-24 11:11:14 -0300 |
| commit | ad41fc11eb2be960ee700c913c7a5c341d541af5 (patch) | |
| tree | 1007dbff70a1fc91443d4c15540bee4a0767ed83 | |
| parent | e182cf452fca5e00c6bd6a63642ce3ef8d7f7a53 (diff) | |
| download | lua-ad41fc11eb2be960ee700c913c7a5c341d541af5.tar.gz lua-ad41fc11eb2be960ee700c913c7a5c341d541af5.tar.bz2 lua-ad41fc11eb2be960ee700c913c7a5c341d541af5.zip | |
details in arithmetic implementation
| -rw-r--r-- | lvm.c | 98 |
1 files changed, 58 insertions, 40 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.240 2002/06/20 20:41:46 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.241 2002/06/24 13:08:45 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 | */ |
| @@ -182,13 +182,6 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | |||
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | 184 | ||
| 185 | static void call_arith (lua_State *L, StkId p1, const TObject *p2, | ||
| 186 | StkId res, TMS event) { | ||
| 187 | if (!call_binTM(L, p1, p2, res, event)) | ||
| 188 | luaG_aritherror(L, p1, p2); | ||
| 189 | } | ||
| 190 | |||
| 191 | |||
| 192 | static int luaV_strcmp (const TString *ls, const TString *rs) { | 185 | static int luaV_strcmp (const TString *ls, const TString *rs) { |
| 193 | const char *l = getstr(ls); | 186 | const char *l = getstr(ls); |
| 194 | size_t ll = ls->tsv.len; | 187 | size_t ll = ls->tsv.len; |
| @@ -300,23 +293,32 @@ void luaV_concat (lua_State *L, int total, int last) { | |||
| 300 | } | 293 | } |
| 301 | 294 | ||
| 302 | 295 | ||
| 303 | static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) { | 296 | static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) { |
| 304 | const TObject *b = rb; | ||
| 305 | const TObject *c = rc; | ||
| 306 | ptrdiff_t res = savestack(L, ra); | ||
| 307 | TObject tempb, tempc; | 297 | TObject tempb, tempc; |
| 308 | if (tonumber(b, &tempb) && tonumber(c, &tempc)) { | 298 | const TObject *b, *c; |
| 309 | TObject f, o; | 299 | if ((b = luaV_tonumber(rb, &tempb)) != NULL && |
| 310 | setsvalue(&o, luaS_newliteral(L, "pow")); | 300 | (c = luaV_tonumber(rc, &tempc)) != NULL) { |
| 311 | f = *luaV_gettable(L, gt(L), &o); | 301 | switch (op) { |
| 312 | if (ttype(&f) != LUA_TFUNCTION) | 302 | case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break; |
| 313 | luaG_runerror(L, "`pow' (for `^' operator) is not a function"); | 303 | case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break; |
| 314 | callTMres(L, &f, b, c); | 304 | case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break; |
| 315 | ra = restorestack(L, res); /* previous call may change stack */ | 305 | case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break; |
| 316 | setobj(ra, L->top); | 306 | case TM_POW: { |
| 307 | const TObject *f = luaH_getstr(hvalue(registry(L)), | ||
| 308 | G(L)->tmname[TM_POW]); | ||
| 309 | ptrdiff_t res = savestack(L, ra); | ||
| 310 | if (ttype(f) != LUA_TFUNCTION) | ||
| 311 | luaG_runerror(L, "`pow' (for `^' operator) is not a function"); | ||
| 312 | callTMres(L, f, b, c); | ||
| 313 | ra = restorestack(L, res); /* previous call may change stack */ | ||
| 314 | setobj(ra, L->top); | ||
| 315 | break; | ||
| 316 | } | ||
| 317 | default: lua_assert(0); break; | ||
| 318 | } | ||
| 317 | } | 319 | } |
| 318 | else | 320 | else if (!call_binTM(L, rb, rc, ra, op)) |
| 319 | call_arith(L, rb, rc, ra, TM_POW); | 321 | luaG_aritherror(L, rb, rc); |
| 320 | } | 322 | } |
| 321 | 323 | ||
| 322 | 324 | ||
| @@ -335,15 +337,6 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) { | |||
| 335 | k+GETARG_C(i)-MAXSTACK) | 337 | k+GETARG_C(i)-MAXSTACK) |
| 336 | #define KBx(i) (k+GETARG_Bx(i)) | 338 | #define KBx(i) (k+GETARG_Bx(i)) |
| 337 | 339 | ||
| 338 | #define Arith(op, optm) { \ | ||
| 339 | const TObject *b = RB(i); const TObject *c = RKC(i); \ | ||
| 340 | TObject tempb, tempc; \ | ||
| 341 | if (tonumber(b, &tempb) && tonumber(c, &tempc)) { \ | ||
| 342 | setnvalue(ra, nvalue(b) op nvalue(c)); \ | ||
| 343 | } else \ | ||
| 344 | call_arith(L, RB(i), RKC(i), ra, optm); \ | ||
| 345 | } | ||
| 346 | |||
| 347 | 340 | ||
| 348 | #define dojump(pc, i) ((pc) += (i)) | 341 | #define dojump(pc, i) ((pc) += (i)) |
| 349 | 342 | ||
| @@ -435,34 +428,59 @@ StkId luaV_execute (lua_State *L) { | |||
| 435 | break; | 428 | break; |
| 436 | } | 429 | } |
| 437 | case OP_ADD: { | 430 | case OP_ADD: { |
| 438 | Arith( + , TM_ADD); | 431 | StkId rb = RB(i); |
| 432 | StkId rc = RKC(i); | ||
| 433 | if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { | ||
| 434 | setnvalue(ra, nvalue(rb) + nvalue(rc)); | ||
| 435 | } | ||
| 436 | else | ||
| 437 | Arith(L, ra, rb, rc, TM_ADD); | ||
| 439 | break; | 438 | break; |
| 440 | } | 439 | } |
| 441 | case OP_SUB: { | 440 | case OP_SUB: { |
| 442 | Arith( - , TM_SUB); | 441 | StkId rb = RB(i); |
| 442 | StkId rc = RKC(i); | ||
| 443 | if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { | ||
| 444 | setnvalue(ra, nvalue(rb) - nvalue(rc)); | ||
| 445 | } | ||
| 446 | else | ||
| 447 | Arith(L, ra, rb, rc, TM_SUB); | ||
| 443 | break; | 448 | break; |
| 444 | } | 449 | } |
| 445 | case OP_MUL: { | 450 | case OP_MUL: { |
| 446 | Arith( * , TM_MUL); | 451 | StkId rb = RB(i); |
| 452 | StkId rc = RKC(i); | ||
| 453 | if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { | ||
| 454 | setnvalue(ra, nvalue(rb) * nvalue(rc)); | ||
| 455 | } | ||
| 456 | else | ||
| 457 | Arith(L, ra, rb, rc, TM_MUL); | ||
| 447 | break; | 458 | break; |
| 448 | } | 459 | } |
| 449 | case OP_DIV: { | 460 | case OP_DIV: { |
| 450 | Arith( / , TM_DIV); | 461 | StkId rb = RB(i); |
| 462 | StkId rc = RKC(i); | ||
| 463 | if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { | ||
| 464 | setnvalue(ra, nvalue(rb) / nvalue(rc)); | ||
| 465 | } | ||
| 466 | else | ||
| 467 | Arith(L, ra, rb, rc, TM_DIV); | ||
| 451 | break; | 468 | break; |
| 452 | } | 469 | } |
| 453 | case OP_POW: { | 470 | case OP_POW: { |
| 454 | powOp(L, ra, RB(i), RKC(i)); | 471 | Arith(L, ra, RB(i), RKC(i), TM_POW); |
| 455 | break; | 472 | break; |
| 456 | } | 473 | } |
| 457 | case OP_UNM: { | 474 | case OP_UNM: { |
| 458 | const TObject *rb = RB(i); | 475 | const TObject *rb = RB(i); |
| 459 | if (tonumber(rb, ra)) { | 476 | TObject temp; |
| 477 | if (tonumber(rb, &temp)) { | ||
| 460 | setnvalue(ra, -nvalue(rb)); | 478 | setnvalue(ra, -nvalue(rb)); |
| 461 | } | 479 | } |
| 462 | else { | 480 | else { |
| 463 | TObject temp; | ||
| 464 | setnilvalue(&temp); | 481 | setnilvalue(&temp); |
| 465 | call_arith(L, RB(i), &temp, ra, TM_UNM); | 482 | if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) |
| 483 | luaG_aritherror(L, RB(i), &temp); | ||
| 466 | } | 484 | } |
| 467 | break; | 485 | break; |
| 468 | } | 486 | } |
