diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-11 20:48:44 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-11 20:48:44 -0200 |
| commit | 9aff171f3bf0125314a29a5ca952470b2d83708e (patch) | |
| tree | 8d1b400e0108198bde554a31731c655113bc4086 /lcode.c | |
| parent | ed9be5e1f0d4b68aa848f85744ad959d7a57c9f4 (diff) | |
| download | lua-9aff171f3bf0125314a29a5ca952470b2d83708e.tar.gz lua-9aff171f3bf0125314a29a5ca952470b2d83708e.tar.bz2 lua-9aff171f3bf0125314a29a5ca952470b2d83708e.zip | |
new type `boolean'
Diffstat (limited to 'lcode.c')
| -rw-r--r-- | lcode.c | 123 |
1 files changed, 61 insertions, 62 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.82 2001/09/07 17:39:10 roberto Exp $ | 2 | ** $Id: lcode.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
| 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 | */ |
| @@ -221,10 +221,10 @@ static void freeexp (FuncState *fs, expdesc *e) { | |||
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | 223 | ||
| 224 | static int addk (FuncState *fs, TObject *k) { | 224 | static int addk (FuncState *fs, TObject *k, TObject *v) { |
| 225 | const TObject *index = luaH_get(fs->h, k); | 225 | const TObject *index = luaH_get(fs->h, k); |
| 226 | if (ttype(index) == LUA_TNUMBER) { | 226 | if (ttype(index) == LUA_TNUMBER) { |
| 227 | lua_assert(luaO_equalObj(&fs->f->k[cast(int, nvalue(index))], k)); | 227 | lua_assert(luaO_equalObj(&fs->f->k[cast(int, nvalue(index))], v)); |
| 228 | return cast(int, nvalue(index)); | 228 | return cast(int, nvalue(index)); |
| 229 | } | 229 | } |
| 230 | else { /* constant not found; create a new entry */ | 230 | else { /* constant not found; create a new entry */ |
| @@ -232,7 +232,7 @@ static int addk (FuncState *fs, TObject *k) { | |||
| 232 | Proto *f = fs->f; | 232 | Proto *f = fs->f; |
| 233 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, | 233 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, |
| 234 | MAXARG_Bc, "constant table overflow"); | 234 | MAXARG_Bc, "constant table overflow"); |
| 235 | setobj(&f->k[fs->nk], k); | 235 | setobj(&f->k[fs->nk], v); |
| 236 | setnvalue(&o, fs->nk); | 236 | setnvalue(&o, fs->nk); |
| 237 | luaH_set(fs->L, fs->h, k, &o); | 237 | luaH_set(fs->L, fs->h, k, &o); |
| 238 | return fs->nk++; | 238 | return fs->nk++; |
| @@ -243,14 +243,22 @@ static int addk (FuncState *fs, TObject *k) { | |||
| 243 | int luaK_stringk (FuncState *fs, TString *s) { | 243 | int luaK_stringk (FuncState *fs, TString *s) { |
| 244 | TObject o; | 244 | TObject o; |
| 245 | setsvalue(&o, s); | 245 | setsvalue(&o, s); |
| 246 | return addk(fs, &o); | 246 | return addk(fs, &o, &o); |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | 249 | ||
| 250 | static int number_constant (FuncState *fs, lua_Number r) { | 250 | static int number_constant (FuncState *fs, lua_Number r) { |
| 251 | TObject o; | 251 | TObject o; |
| 252 | setnvalue(&o, r); | 252 | setnvalue(&o, r); |
| 253 | return addk(fs, &o); | 253 | return addk(fs, &o, &o); |
| 254 | } | ||
| 255 | |||
| 256 | |||
| 257 | static int nil_constant (FuncState *fs) { | ||
| 258 | TObject k, v; | ||
| 259 | setnilvalue(&v); | ||
| 260 | sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */ | ||
| 261 | return addk(fs, &k, &v); | ||
| 254 | } | 262 | } |
| 255 | 263 | ||
| 256 | 264 | ||
| @@ -298,27 +306,29 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 298 | } | 306 | } |
| 299 | 307 | ||
| 300 | 308 | ||
| 301 | static int code_label (FuncState *fs, OpCode op, int A, int sBc) { | 309 | static int code_label (FuncState *fs, int A, int b, int jump) { |
| 302 | luaK_getlabel(fs); /* those instructions may be jump targets */ | 310 | luaK_getlabel(fs); /* those instructions may be jump targets */ |
| 303 | return luaK_codeAsBc(fs, op, A, sBc); | 311 | return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); |
| 304 | } | 312 | } |
| 305 | 313 | ||
| 306 | 314 | ||
| 307 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { | 315 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { |
| 308 | if (hasjumps(e)) { | 316 | if (hasjumps(e)) { |
| 309 | int final; /* position after whole expression */ | 317 | int final; /* position after whole expression */ |
| 310 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ | 318 | int p_f = NO_JUMP; /* position of an eventual PUSH false */ |
| 311 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ | 319 | int p_t = NO_JUMP; /* position of an eventual PUSH true */ |
| 312 | if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { | 320 | if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { |
| 313 | /* expression needs values */ | 321 | /* expression needs values */ |
| 314 | if (e->k != VJMP) | 322 | if (e->k != VJMP) { |
| 315 | code_label(fs, OP_JMP, 0, 2); /* to jump over both pushes */ | 323 | luaK_getlabel(fs); /* these instruction may be jump target */ |
| 316 | p_nil = code_label(fs, OP_NILJMP, reg, 0); | 324 | luaK_codeAsBc(fs, OP_JMP, 0, 2); /* to jump over both pushes */ |
| 317 | p_1 = code_label(fs, OP_LOADINT, reg, 1); | 325 | } |
| 326 | p_f = code_label(fs, reg, 0, 1); | ||
| 327 | p_t = code_label(fs, reg, 1, 0); | ||
| 318 | } | 328 | } |
| 319 | final = luaK_getlabel(fs); | 329 | final = luaK_getlabel(fs); |
| 320 | luaK_patchlistaux(fs, e->f, p_nil, NO_REG, final, reg, p_nil); | 330 | luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); |
| 321 | luaK_patchlistaux(fs, e->t, final, reg, p_1, NO_REG, p_1); | 331 | luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); |
| 322 | } | 332 | } |
| 323 | e->f = e->t = NO_JUMP; | 333 | e->f = e->t = NO_JUMP; |
| 324 | } | 334 | } |
| @@ -331,6 +341,10 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 331 | luaK_nil(fs, reg, 1); | 341 | luaK_nil(fs, reg, 1); |
| 332 | break; | 342 | break; |
| 333 | } | 343 | } |
| 344 | case VFALSE: case VTRUE: { | ||
| 345 | luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); | ||
| 346 | break; | ||
| 347 | } | ||
| 334 | case VNUMBER: { | 348 | case VNUMBER: { |
| 335 | lua_Number f = e->u.n; | 349 | lua_Number f = e->u.n; |
| 336 | int i = cast(int, f); | 350 | int i = cast(int, f); |
| @@ -424,13 +438,25 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { | |||
| 424 | 438 | ||
| 425 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 439 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 426 | luaK_exp2val(fs, e); | 440 | luaK_exp2val(fs, e); |
| 427 | if (e->k == VNUMBER && fs->nk + MAXSTACK <= MAXARG_C) { | 441 | switch (e->k) { |
| 428 | e->u.i.info = number_constant(fs, e->u.n); | 442 | case VNUMBER: case VNIL: { |
| 429 | e->k = VK; | 443 | if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */ |
| 444 | e->u.i.info = (e->k == VNIL) ? nil_constant(fs) : | ||
| 445 | number_constant(fs, e->u.n); | ||
| 446 | e->k = VK; | ||
| 447 | return e->u.i.info + MAXSTACK; | ||
| 448 | } | ||
| 449 | else break; | ||
| 450 | } | ||
| 451 | case VK: { | ||
| 452 | if (e->u.i.info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */ | ||
| 453 | return e->u.i.info + MAXSTACK; | ||
| 454 | else break; | ||
| 455 | } | ||
| 456 | default: break; | ||
| 430 | } | 457 | } |
| 431 | else if (!(e->k == VK && e->u.i.info + MAXSTACK <= MAXARG_C)) | 458 | /* not a constant in the right range: put in a register */ |
| 432 | luaK_exp2anyreg(fs, e); /* not a constant in the right range */ | 459 | return luaK_exp2anyreg(fs, e); |
| 433 | return (e->k == VK) ? e->u.i.info+MAXSTACK : e->u.i.info; | ||
| 434 | } | 460 | } |
| 435 | 461 | ||
| 436 | 462 | ||
| @@ -521,11 +547,11 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
| 521 | int pc; /* pc of last jump */ | 547 | int pc; /* pc of last jump */ |
| 522 | luaK_dischargevars(fs, e); | 548 | luaK_dischargevars(fs, e); |
| 523 | switch (e->k) { | 549 | switch (e->k) { |
| 524 | case VK: case VNUMBER: { | 550 | case VK: case VNUMBER: case VTRUE: { |
| 525 | pc = NO_JUMP; /* always true; do nothing */ | 551 | pc = NO_JUMP; /* always true; do nothing */ |
| 526 | break; | 552 | break; |
| 527 | } | 553 | } |
| 528 | case VNIL: { | 554 | case VFALSE: { |
| 529 | pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ | 555 | pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ |
| 530 | break; | 556 | break; |
| 531 | } | 557 | } |
| @@ -534,14 +560,8 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
| 534 | pc = e->u.i.info; | 560 | pc = e->u.i.info; |
| 535 | break; | 561 | break; |
| 536 | } | 562 | } |
| 537 | case VRELOCABLE: | ||
| 538 | case VNONRELOC: { | ||
| 539 | pc = jumponcond(fs, e, OP_TESTF); | ||
| 540 | break; | ||
| 541 | } | ||
| 542 | default: { | 563 | default: { |
| 543 | pc = 0; /* to avoid warnings */ | 564 | pc = jumponcond(fs, e, OP_TESTF); |
| 544 | lua_assert(0); /* cannot happen */ | ||
| 545 | break; | 565 | break; |
| 546 | } | 566 | } |
| 547 | } | 567 | } |
| @@ -555,23 +575,20 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) { | |||
| 555 | int pc; /* pc of last jump */ | 575 | int pc; /* pc of last jump */ |
| 556 | luaK_dischargevars(fs, e); | 576 | luaK_dischargevars(fs, e); |
| 557 | switch (e->k) { | 577 | switch (e->k) { |
| 558 | case VNIL: { | 578 | case VNIL: case VFALSE: { |
| 559 | pc = NO_JUMP; /* always false; do nothing */ | 579 | pc = NO_JUMP; /* always false; do nothing */ |
| 560 | break; | 580 | break; |
| 561 | } | 581 | } |
| 562 | case VJMP: { | 582 | case VTRUE: { |
| 563 | pc = e->u.i.info; | 583 | pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ |
| 564 | break; | 584 | break; |
| 565 | } | 585 | } |
| 566 | case VK: case VNUMBER: /* cannot optimize it (`or' must keep value) */ | 586 | case VJMP: { |
| 567 | case VRELOCABLE: | 587 | pc = e->u.i.info; |
| 568 | case VNONRELOC: { | ||
| 569 | pc = jumponcond(fs, e, OP_TESTT); | ||
| 570 | break; | 588 | break; |
| 571 | } | 589 | } |
| 572 | default: { | 590 | default: { |
| 573 | pc = 0; /* to avoid warnings */ | 591 | pc = jumponcond(fs, e, OP_TESTT); |
| 574 | lua_assert(0); /* cannot happen */ | ||
| 575 | break; | 592 | break; |
| 576 | } | 593 | } |
| 577 | } | 594 | } |
| @@ -584,13 +601,12 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) { | |||
| 584 | static void codenot (FuncState *fs, expdesc *e) { | 601 | static void codenot (FuncState *fs, expdesc *e) { |
| 585 | luaK_dischargevars(fs, e); | 602 | luaK_dischargevars(fs, e); |
| 586 | switch (e->k) { | 603 | switch (e->k) { |
| 587 | case VNIL: { | 604 | case VNIL: case VFALSE: { |
| 588 | e->u.n = 1; | 605 | e->k = VTRUE; |
| 589 | e->k = VNUMBER; | ||
| 590 | break; | 606 | break; |
| 591 | } | 607 | } |
| 592 | case VK: case VNUMBER: { | 608 | case VK: case VNUMBER: case VTRUE: { |
| 593 | e->k = VNIL; | 609 | e->k = VFALSE; |
| 594 | break; | 610 | break; |
| 595 | } | 611 | } |
| 596 | case VJMP: { | 612 | case VJMP: { |
| @@ -719,23 +735,6 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | |||
| 719 | } | 735 | } |
| 720 | break; | 736 | break; |
| 721 | } | 737 | } |
| 722 | case OPR_EQ: case OPR_NE: { | ||
| 723 | luaK_exp2val(fs, e2); | ||
| 724 | if (e2->k == VNIL) { /* exp x= nil ? */ | ||
| 725 | if (e1->k == VK) { /* constant x= nil ? */ | ||
| 726 | if (op == OPR_EQ) /* constant == nil ? */ | ||
| 727 | e1->k = VNIL; /* always false */ | ||
| 728 | /* else always true (leave the constant itself) */ | ||
| 729 | } | ||
| 730 | else { | ||
| 731 | OpCode opc = (op == OPR_EQ) ? OP_TESTF : OP_TESTT; | ||
| 732 | e1->u.i.info = jumponcond(fs, e1, opc); | ||
| 733 | e1->k = VJMP; | ||
| 734 | } | ||
| 735 | break; | ||
| 736 | } | ||
| 737 | /* else go through */ | ||
| 738 | } | ||
| 739 | default: { | 738 | default: { |
| 740 | int o1, o2; | 739 | int o1, o2; |
| 741 | OpCode opc; | 740 | OpCode opc; |
