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 /lvm.c | |
parent | e182cf452fca5e00c6bd6a63642ce3ef8d7f7a53 (diff) | |
download | lua-ad41fc11eb2be960ee700c913c7a5c341d541af5.tar.gz lua-ad41fc11eb2be960ee700c913c7a5c341d541af5.tar.bz2 lua-ad41fc11eb2be960ee700c913c7a5c341d541af5.zip |
details in arithmetic implementation
Diffstat (limited to 'lvm.c')
-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 | } |