diff options
| -rw-r--r-- | lcode.c | 227 |
1 files changed, 134 insertions, 93 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.16 2005/08/29 20:49:21 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.17 2005/09/30 14:23:33 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -27,6 +27,11 @@ | |||
| 27 | #define hasjumps(e) ((e)->t != (e)->f) | 27 | #define hasjumps(e) ((e)->t != (e)->f) |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | static int isnumeral(FuncState *fs, expdesc *e) { | ||
| 31 | return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); | ||
| 32 | } | ||
| 33 | |||
| 34 | |||
| 30 | void luaK_nil (FuncState *fs, int from, int n) { | 35 | void luaK_nil (FuncState *fs, int from, int n) { |
| 31 | Instruction *previous; | 36 | Instruction *previous; |
| 32 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ | 37 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ |
| @@ -213,7 +218,7 @@ static void freereg (FuncState *fs, int reg) { | |||
| 213 | 218 | ||
| 214 | static void freeexp (FuncState *fs, expdesc *e) { | 219 | static void freeexp (FuncState *fs, expdesc *e) { |
| 215 | if (e->k == VNONRELOC) | 220 | if (e->k == VNONRELOC) |
| 216 | freereg(fs, e->info); | 221 | freereg(fs, e->u.s.info); |
| 217 | } | 222 | } |
| 218 | 223 | ||
| 219 | 224 | ||
| @@ -283,7 +288,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { | |||
| 283 | void luaK_setoneret (FuncState *fs, expdesc *e) { | 288 | void luaK_setoneret (FuncState *fs, expdesc *e) { |
| 284 | if (e->k == VCALL) { /* expression is an open function call? */ | 289 | if (e->k == VCALL) { /* expression is an open function call? */ |
| 285 | e->k = VNONRELOC; | 290 | e->k = VNONRELOC; |
| 286 | e->info = GETARG_A(getcode(fs, e)); | 291 | e->u.s.info = GETARG_A(getcode(fs, e)); |
| 287 | } | 292 | } |
| 288 | else if (e->k == VVARARG) { | 293 | else if (e->k == VVARARG) { |
| 289 | SETARG_B(getcode(fs, e), 2); | 294 | SETARG_B(getcode(fs, e), 2); |
| @@ -299,19 +304,19 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 299 | break; | 304 | break; |
| 300 | } | 305 | } |
| 301 | case VUPVAL: { | 306 | case VUPVAL: { |
| 302 | e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0); | 307 | e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); |
| 303 | e->k = VRELOCABLE; | 308 | e->k = VRELOCABLE; |
| 304 | break; | 309 | break; |
| 305 | } | 310 | } |
| 306 | case VGLOBAL: { | 311 | case VGLOBAL: { |
| 307 | e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info); | 312 | e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); |
| 308 | e->k = VRELOCABLE; | 313 | e->k = VRELOCABLE; |
| 309 | break; | 314 | break; |
| 310 | } | 315 | } |
| 311 | case VINDEXED: { | 316 | case VINDEXED: { |
| 312 | freereg(fs, e->aux); | 317 | freereg(fs, e->u.s.aux); |
| 313 | freereg(fs, e->info); | 318 | freereg(fs, e->u.s.info); |
| 314 | e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); | 319 | e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); |
| 315 | e->k = VRELOCABLE; | 320 | e->k = VRELOCABLE; |
| 316 | break; | 321 | break; |
| 317 | } | 322 | } |
| @@ -343,7 +348,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 343 | break; | 348 | break; |
| 344 | } | 349 | } |
| 345 | case VK: { | 350 | case VK: { |
| 346 | luaK_codeABx(fs, OP_LOADK, reg, e->info); | 351 | luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); |
| 352 | break; | ||
| 353 | } | ||
| 354 | case VKNUM: { | ||
| 355 | luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); | ||
| 347 | break; | 356 | break; |
| 348 | } | 357 | } |
| 349 | case VRELOCABLE: { | 358 | case VRELOCABLE: { |
| @@ -352,8 +361,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 352 | break; | 361 | break; |
| 353 | } | 362 | } |
| 354 | case VNONRELOC: { | 363 | case VNONRELOC: { |
| 355 | if (reg != e->info) | 364 | if (reg != e->u.s.info) |
| 356 | luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); | 365 | luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); |
| 357 | break; | 366 | break; |
| 358 | } | 367 | } |
| 359 | default: { | 368 | default: { |
| @@ -361,7 +370,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 361 | return; /* nothing to do... */ | 370 | return; /* nothing to do... */ |
| 362 | } | 371 | } |
| 363 | } | 372 | } |
| 364 | e->info = reg; | 373 | e->u.s.info = reg; |
| 365 | e->k = VNONRELOC; | 374 | e->k = VNONRELOC; |
| 366 | } | 375 | } |
| 367 | 376 | ||
| @@ -377,7 +386,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { | |||
| 377 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { | 386 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
| 378 | discharge2reg(fs, e, reg); | 387 | discharge2reg(fs, e, reg); |
| 379 | if (e->k == VJMP) | 388 | if (e->k == VJMP) |
| 380 | luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */ | 389 | luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ |
| 381 | if (hasjumps(e)) { | 390 | if (hasjumps(e)) { |
| 382 | int final; /* position after whole expression */ | 391 | int final; /* position after whole expression */ |
| 383 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | 392 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
| @@ -395,7 +404,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 395 | patchlistaux(fs, e->t, final, reg, p_t); | 404 | patchlistaux(fs, e->t, final, reg, p_t); |
| 396 | } | 405 | } |
| 397 | e->f = e->t = NO_JUMP; | 406 | e->f = e->t = NO_JUMP; |
| 398 | e->info = reg; | 407 | e->u.s.info = reg; |
| 399 | e->k = VNONRELOC; | 408 | e->k = VNONRELOC; |
| 400 | } | 409 | } |
| 401 | 410 | ||
| @@ -411,14 +420,14 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { | |||
| 411 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | 420 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
| 412 | luaK_dischargevars(fs, e); | 421 | luaK_dischargevars(fs, e); |
| 413 | if (e->k == VNONRELOC) { | 422 | if (e->k == VNONRELOC) { |
| 414 | if (!hasjumps(e)) return e->info; /* exp is already in a register */ | 423 | if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ |
| 415 | if (e->info >= fs->nactvar) { /* reg. is not a local? */ | 424 | if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ |
| 416 | exp2reg(fs, e, e->info); /* put value on it */ | 425 | exp2reg(fs, e, e->u.s.info); /* put value on it */ |
| 417 | return e->info; | 426 | return e->u.s.info; |
| 418 | } | 427 | } |
| 419 | } | 428 | } |
| 420 | luaK_exp2nextreg(fs, e); /* default */ | 429 | luaK_exp2nextreg(fs, e); /* default */ |
| 421 | return e->info; | 430 | return e->u.s.info; |
| 422 | } | 431 | } |
| 423 | 432 | ||
| 424 | 433 | ||
| @@ -433,19 +442,22 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { | |||
| 433 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 442 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 434 | luaK_exp2val(fs, e); | 443 | luaK_exp2val(fs, e); |
| 435 | switch (e->k) { | 444 | switch (e->k) { |
| 445 | case VKNUM: | ||
| 436 | case VTRUE: | 446 | case VTRUE: |
| 437 | case VFALSE: | 447 | case VFALSE: |
| 438 | case VNIL: { | 448 | case VNIL: { |
| 439 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ | 449 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ |
| 440 | e->info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); | 450 | e->u.s.info = (e->k == VNIL) ? nilK(fs) : |
| 451 | (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : | ||
| 452 | boolK(fs, (e->k == VTRUE)); | ||
| 441 | e->k = VK; | 453 | e->k = VK; |
| 442 | return RKASK(e->info); | 454 | return RKASK(e->u.s.info); |
| 443 | } | 455 | } |
| 444 | else break; | 456 | else break; |
| 445 | } | 457 | } |
| 446 | case VK: { | 458 | case VK: { |
| 447 | if (e->info <= MAXINDEXRK) /* constant fit in argC? */ | 459 | if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ |
| 448 | return RKASK(e->info); | 460 | return RKASK(e->u.s.info); |
| 449 | else break; | 461 | else break; |
| 450 | } | 462 | } |
| 451 | default: break; | 463 | default: break; |
| @@ -459,22 +471,22 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
| 459 | switch (var->k) { | 471 | switch (var->k) { |
| 460 | case VLOCAL: { | 472 | case VLOCAL: { |
| 461 | freeexp(fs, ex); | 473 | freeexp(fs, ex); |
| 462 | exp2reg(fs, ex, var->info); | 474 | exp2reg(fs, ex, var->u.s.info); |
| 463 | return; | 475 | return; |
| 464 | } | 476 | } |
| 465 | case VUPVAL: { | 477 | case VUPVAL: { |
| 466 | int e = luaK_exp2anyreg(fs, ex); | 478 | int e = luaK_exp2anyreg(fs, ex); |
| 467 | luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); | 479 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); |
| 468 | break; | 480 | break; |
| 469 | } | 481 | } |
| 470 | case VGLOBAL: { | 482 | case VGLOBAL: { |
| 471 | int e = luaK_exp2anyreg(fs, ex); | 483 | int e = luaK_exp2anyreg(fs, ex); |
| 472 | luaK_codeABx(fs, OP_SETGLOBAL, e, var->info); | 484 | luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); |
| 473 | break; | 485 | break; |
| 474 | } | 486 | } |
| 475 | case VINDEXED: { | 487 | case VINDEXED: { |
| 476 | int e = luaK_exp2RK(fs, ex); | 488 | int e = luaK_exp2RK(fs, ex); |
| 477 | luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); | 489 | luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); |
| 478 | break; | 490 | break; |
| 479 | } | 491 | } |
| 480 | default: { | 492 | default: { |
| @@ -492,15 +504,15 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |||
| 492 | freeexp(fs, e); | 504 | freeexp(fs, e); |
| 493 | func = fs->freereg; | 505 | func = fs->freereg; |
| 494 | luaK_reserveregs(fs, 2); | 506 | luaK_reserveregs(fs, 2); |
| 495 | luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key)); | 507 | luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); |
| 496 | freeexp(fs, key); | 508 | freeexp(fs, key); |
| 497 | e->info = func; | 509 | e->u.s.info = func; |
| 498 | e->k = VNONRELOC; | 510 | e->k = VNONRELOC; |
| 499 | } | 511 | } |
| 500 | 512 | ||
| 501 | 513 | ||
| 502 | static void invertjump (FuncState *fs, expdesc *e) { | 514 | static void invertjump (FuncState *fs, expdesc *e) { |
| 503 | Instruction *pc = getjumpcontrol(fs, e->info); | 515 | Instruction *pc = getjumpcontrol(fs, e->u.s.info); |
| 504 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && | 516 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
| 505 | GET_OPCODE(*pc) != OP_TEST); | 517 | GET_OPCODE(*pc) != OP_TEST); |
| 506 | SETARG_A(*pc, !(GETARG_A(*pc))); | 518 | SETARG_A(*pc, !(GETARG_A(*pc))); |
| @@ -518,7 +530,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
| 518 | } | 530 | } |
| 519 | discharge2anyreg(fs, e); | 531 | discharge2anyreg(fs, e); |
| 520 | freeexp(fs, e); | 532 | freeexp(fs, e); |
| 521 | return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); | 533 | return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); |
| 522 | } | 534 | } |
| 523 | 535 | ||
| 524 | 536 | ||
| @@ -526,7 +538,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
| 526 | int pc; /* pc of last jump */ | 538 | int pc; /* pc of last jump */ |
| 527 | luaK_dischargevars(fs, e); | 539 | luaK_dischargevars(fs, e); |
| 528 | switch (e->k) { | 540 | switch (e->k) { |
| 529 | case VK: case VTRUE: { | 541 | case VK: case VKNUM: case VTRUE: { |
| 530 | pc = NO_JUMP; /* always true; do nothing */ | 542 | pc = NO_JUMP; /* always true; do nothing */ |
| 531 | break; | 543 | break; |
| 532 | } | 544 | } |
| @@ -536,7 +548,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
| 536 | } | 548 | } |
| 537 | case VJMP: { | 549 | case VJMP: { |
| 538 | invertjump(fs, e); | 550 | invertjump(fs, e); |
| 539 | pc = e->info; | 551 | pc = e->u.s.info; |
| 540 | break; | 552 | break; |
| 541 | } | 553 | } |
| 542 | default: { | 554 | default: { |
| @@ -563,7 +575,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { | |||
| 563 | break; | 575 | break; |
| 564 | } | 576 | } |
| 565 | case VJMP: { | 577 | case VJMP: { |
| 566 | pc = e->info; | 578 | pc = e->u.s.info; |
| 567 | break; | 579 | break; |
| 568 | } | 580 | } |
| 569 | default: { | 581 | default: { |
| @@ -584,7 +596,7 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
| 584 | e->k = VTRUE; | 596 | e->k = VTRUE; |
| 585 | break; | 597 | break; |
| 586 | } | 598 | } |
| 587 | case VK: case VTRUE: { | 599 | case VK: case VKNUM: case VTRUE: { |
| 588 | e->k = VFALSE; | 600 | e->k = VFALSE; |
| 589 | break; | 601 | break; |
| 590 | } | 602 | } |
| @@ -596,7 +608,7 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
| 596 | case VNONRELOC: { | 608 | case VNONRELOC: { |
| 597 | discharge2anyreg(fs, e); | 609 | discharge2anyreg(fs, e); |
| 598 | freeexp(fs, e); | 610 | freeexp(fs, e); |
| 599 | e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0); | 611 | e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); |
| 600 | e->k = VRELOCABLE; | 612 | e->k = VRELOCABLE; |
| 601 | break; | 613 | break; |
| 602 | } | 614 | } |
| @@ -613,34 +625,79 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
| 613 | 625 | ||
| 614 | 626 | ||
| 615 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 627 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
| 616 | t->aux = luaK_exp2RK(fs, k); | 628 | t->u.s.aux = luaK_exp2RK(fs, k); |
| 617 | t->k = VINDEXED; | 629 | t->k = VINDEXED; |
| 618 | } | 630 | } |
| 619 | 631 | ||
| 620 | 632 | ||
| 633 | static int constfolding (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | ||
| 634 | lua_Number v1, v2, r; | ||
| 635 | if (!isnumeral(fs, e1) || !isnumeral(fs, e2)) return 0; | ||
| 636 | v1 = e1->u.nval; | ||
| 637 | v2 = e2->u.nval; | ||
| 638 | switch (op) { | ||
| 639 | case OP_ADD: r = luai_numadd(fs->L, v1, v2); break; | ||
| 640 | case OP_SUB: r = luai_numsub(fs->L, v1, v2); break; | ||
| 641 | case OP_MUL: r = luai_nummul(fs->L, v1, v2); break; | ||
| 642 | case OP_DIV: | ||
| 643 | if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | ||
| 644 | r = luai_numdiv(fs->L, v1, v2); break; | ||
| 645 | case OP_MOD: r = luai_nummod(fs->L, v1, v2); break; | ||
| 646 | case OP_POW: r = luai_numpow(fs->L, v1, v2); break; | ||
| 647 | case OP_UNM: r = luai_numunm(fs->L, v1); break; | ||
| 648 | case OP_LEN: return 0; /* no constant folding for 'len' */ | ||
| 649 | default: lua_assert(0); r = 0; break; | ||
| 650 | } | ||
| 651 | if (r != r) return 0; /* do not attempt to produce NaN */ | ||
| 652 | e1->u.nval = r; | ||
| 653 | return 1; | ||
| 654 | } | ||
| 655 | |||
| 656 | |||
| 657 | static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | ||
| 658 | if (constfolding(fs, op, e1, e2)) | ||
| 659 | return; | ||
| 660 | else { | ||
| 661 | int o1 = luaK_exp2RK(fs, e1); | ||
| 662 | int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; | ||
| 663 | freeexp(fs, e2); | ||
| 664 | freeexp(fs, e1); | ||
| 665 | e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); | ||
| 666 | e1->k = VRELOCABLE; | ||
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | |||
| 671 | static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, | ||
| 672 | expdesc *e2) { | ||
| 673 | int o1 = luaK_exp2RK(fs, e1); | ||
| 674 | int o2 = luaK_exp2RK(fs, e2); | ||
| 675 | freeexp(fs, e2); | ||
| 676 | freeexp(fs, e1); | ||
| 677 | if (cond == 0 && op != OP_EQ) { | ||
| 678 | int temp; /* exchange args to replace by `<' or `<=' */ | ||
| 679 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | ||
| 680 | cond = 1; | ||
| 681 | } | ||
| 682 | e1->u.s.info = condjump(fs, op, cond, o1, o2); | ||
| 683 | e1->k = VJMP; | ||
| 684 | } | ||
| 685 | |||
| 686 | |||
| 621 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { | 687 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
| 688 | expdesc e2; | ||
| 689 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; | ||
| 622 | switch (op) { | 690 | switch (op) { |
| 623 | case OPR_MINUS: { | 691 | case OPR_MINUS: { |
| 624 | luaK_exp2val(fs, e); | 692 | if (e->k == VK) |
| 625 | if (e->k == VK && ttisnumber(&fs->f->k[e->info])) | 693 | luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ |
| 626 | e->info = luaK_numberK(fs, luai_numunm(L, nvalue(&fs->f->k[e->info]))); | 694 | codearith(fs, OP_UNM, e, &e2); |
| 627 | else { | ||
| 628 | luaK_exp2anyreg(fs, e); | ||
| 629 | freeexp(fs, e); | ||
| 630 | e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0); | ||
| 631 | e->k = VRELOCABLE; | ||
| 632 | } | ||
| 633 | break; | ||
| 634 | } | ||
| 635 | case OPR_NOT: { | ||
| 636 | codenot(fs, e); | ||
| 637 | break; | 695 | break; |
| 638 | } | 696 | } |
| 697 | case OPR_NOT: codenot(fs, e); break; | ||
| 639 | case OPR_LEN: { | 698 | case OPR_LEN: { |
| 640 | luaK_exp2anyreg(fs, e); | 699 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ |
| 641 | freeexp(fs, e); | 700 | codearith(fs, OP_LEN, e, &e2); |
| 642 | e->info = luaK_codeABC(fs, OP_LEN, 0, e->info, 0); | ||
| 643 | e->k = VRELOCABLE; | ||
| 644 | break; | 701 | break; |
| 645 | } | 702 | } |
| 646 | default: lua_assert(0); | 703 | default: lua_assert(0); |
| @@ -663,74 +720,58 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
| 663 | break; | 720 | break; |
| 664 | } | 721 | } |
| 665 | default: { | 722 | default: { |
| 666 | luaK_exp2RK(fs, v); | 723 | if (!isnumeral(fs, v)) luaK_exp2RK(fs, v); |
| 667 | break; | 724 | break; |
| 668 | } | 725 | } |
| 669 | } | 726 | } |
| 670 | } | 727 | } |
| 671 | 728 | ||
| 672 | 729 | ||
| 673 | static void codebinop (FuncState *fs, expdesc *res, BinOpr op, | ||
| 674 | int o1, int o2) { | ||
| 675 | if (op <= OPR_POW) { /* arithmetic operator? */ | ||
| 676 | OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */ | ||
| 677 | res->info = luaK_codeABC(fs, opc, 0, o1, o2); | ||
| 678 | res->k = VRELOCABLE; | ||
| 679 | } | ||
| 680 | else { /* test operator */ | ||
| 681 | static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE}; | ||
| 682 | int cond = 1; | ||
| 683 | if (op >= OPR_GT) { /* `>' or `>='? */ | ||
| 684 | int temp; /* exchange args and replace by `<' or `<=' */ | ||
| 685 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | ||
| 686 | } | ||
| 687 | else if (op == OPR_NE) cond = 0; | ||
| 688 | res->info = condjump(fs, ops[op - OPR_NE], cond, o1, o2); | ||
| 689 | res->k = VJMP; | ||
| 690 | } | ||
| 691 | } | ||
| 692 | |||
| 693 | |||
| 694 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | 730 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { |
| 695 | switch (op) { | 731 | switch (op) { |
| 696 | case OPR_AND: { | 732 | case OPR_AND: { |
| 697 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | 733 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ |
| 698 | luaK_dischargevars(fs, e2); | 734 | luaK_dischargevars(fs, e2); |
| 699 | luaK_concat(fs, &e1->f, e2->f); | 735 | luaK_concat(fs, &e1->f, e2->f); |
| 700 | e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t; | 736 | e1->k = e2->k; e1->u.s.info = e2->u.s.info; |
| 737 | e1->u.s.aux = e2->u.s.aux; e1->t = e2->t; | ||
| 701 | break; | 738 | break; |
| 702 | } | 739 | } |
| 703 | case OPR_OR: { | 740 | case OPR_OR: { |
| 704 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ | 741 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ |
| 705 | luaK_dischargevars(fs, e2); | 742 | luaK_dischargevars(fs, e2); |
| 706 | luaK_concat(fs, &e1->t, e2->t); | 743 | luaK_concat(fs, &e1->t, e2->t); |
| 707 | e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f; | 744 | e1->k = e2->k; e1->u.s.info = e2->u.s.info; |
| 745 | e1->u.s.aux = e2->u.s.aux; e1->f = e2->f; | ||
| 708 | break; | 746 | break; |
| 709 | } | 747 | } |
| 710 | case OPR_CONCAT: { | 748 | case OPR_CONCAT: { |
| 711 | luaK_exp2val(fs, e2); | 749 | luaK_exp2val(fs, e2); |
| 712 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | 750 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { |
| 713 | lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1); | 751 | lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); |
| 714 | freeexp(fs, e1); | 752 | freeexp(fs, e1); |
| 715 | SETARG_B(getcode(fs, e2), e1->info); | 753 | SETARG_B(getcode(fs, e2), e1->u.s.info); |
| 716 | e1->k = e2->k; e1->info = e2->info; | 754 | e1->k = e2->k; e1->u.s.info = e2->u.s.info; |
| 717 | } | 755 | } |
| 718 | else { | 756 | else { |
| 719 | luaK_exp2nextreg(fs, e2); | 757 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ |
| 720 | freeexp(fs, e2); | 758 | codearith(fs, OP_CONCAT, e1, e2); |
| 721 | freeexp(fs, e1); | ||
| 722 | e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info); | ||
| 723 | e1->k = VRELOCABLE; | ||
| 724 | } | 759 | } |
| 725 | break; | 760 | break; |
| 726 | } | 761 | } |
| 727 | default: { | 762 | case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; |
| 728 | int o1 = luaK_exp2RK(fs, e1); | 763 | case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; |
| 729 | int o2 = luaK_exp2RK(fs, e2); | 764 | case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; |
| 730 | freeexp(fs, e2); | 765 | case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; |
| 731 | freeexp(fs, e1); | 766 | case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; |
| 732 | codebinop(fs, e1, op, o1, o2); | 767 | case OPR_POW: codearith(fs, OP_POW, e1, e2); break; |
| 733 | } | 768 | case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; |
| 769 | case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; | ||
| 770 | case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; | ||
| 771 | case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; | ||
| 772 | case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; | ||
| 773 | case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; | ||
| 774 | default: lua_assert(0); | ||
| 734 | } | 775 | } |
| 735 | } | 776 | } |
| 736 | 777 | ||
