diff options
Diffstat (limited to 'lparser.c')
| -rw-r--r-- | lparser.c | 233 |
1 files changed, 100 insertions, 133 deletions
| @@ -22,18 +22,6 @@ | |||
| 22 | #include "lstring.h" | 22 | #include "lstring.h" |
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | /* | ||
| 26 | ** Constructors descriptor: | ||
| 27 | ** `n' indicates number of elements, and `k' signals whether | ||
| 28 | ** it is a list constructor (k = 0) or a record constructor (k = 1) | ||
| 29 | ** or empty (k = `;' or `}') | ||
| 30 | */ | ||
| 31 | typedef struct Constdesc { | ||
| 32 | int narray; | ||
| 33 | int nhash; | ||
| 34 | int k; | ||
| 35 | } Constdesc; | ||
| 36 | |||
| 37 | 25 | ||
| 38 | /* | 26 | /* |
| 39 | ** nodes for break list (list of active breakable loops) | 27 | ** nodes for break list (list of active breakable loops) |
| @@ -251,7 +239,7 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
| 251 | else { | 239 | else { |
| 252 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ | 240 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ |
| 253 | if (extra > 0) { | 241 | if (extra > 0) { |
| 254 | int reg = fs->freereg; | 242 | int reg = fs->freereg; |
| 255 | luaK_reserveregs(fs, extra); | 243 | luaK_reserveregs(fs, extra); |
| 256 | luaK_nil(fs, reg, extra); | 244 | luaK_nil(fs, reg, extra); |
| 257 | } | 245 | } |
| @@ -469,139 +457,118 @@ static void funcargs (LexState *ls, expdesc *f) { | |||
| 469 | */ | 457 | */ |
| 470 | 458 | ||
| 471 | 459 | ||
| 472 | static void recfield (LexState *ls, expdesc *t) { | 460 | struct ConsControl { |
| 461 | expdesc v; /* last list item read */ | ||
| 462 | expdesc *t; /* table descriptor */ | ||
| 463 | int nh; /* total number of `record' elements */ | ||
| 464 | int na; /* total number of array elements */ | ||
| 465 | int tostore; /* number of array elements pending to be stored */ | ||
| 466 | }; | ||
| 467 | |||
| 468 | |||
| 469 | static void recfield (LexState *ls, struct ConsControl *cc) { | ||
| 473 | /* recfield -> (NAME | `['exp1`]') = exp1 */ | 470 | /* recfield -> (NAME | `['exp1`]') = exp1 */ |
| 474 | FuncState *fs = ls->fs; | 471 | FuncState *fs = ls->fs; |
| 475 | int reg = ls->fs->freereg; | 472 | int reg = ls->fs->freereg; |
| 476 | expdesc key, val; | 473 | expdesc key, val; |
| 477 | switch (ls->t.token) { | 474 | if (ls->t.token == TK_NAME) |
| 478 | case TK_NAME: { | 475 | checkname(ls, &key); |
| 479 | checkname(ls, &key); | 476 | else /* ls->t.token == '[' */ |
| 480 | break; | 477 | luaY_index(ls, &key); |
| 481 | } | ||
| 482 | case '[': { | ||
| 483 | luaY_index(ls, &key); | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | default: luaK_error(ls, "<name> or `[' expected"); | ||
| 487 | } | ||
| 488 | check(ls, '='); | 478 | check(ls, '='); |
| 489 | luaK_exp2RK(fs, &key); | 479 | luaK_exp2RK(fs, &key); |
| 490 | expr(ls, &val); | 480 | expr(ls, &val); |
| 491 | luaK_exp2anyreg(fs, &val); | 481 | luaK_exp2anyreg(fs, &val); |
| 492 | luaK_codeABC(fs, OP_SETTABLE, val.info, t->info, | 482 | luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key)); |
| 493 | luaK_exp2RK(fs, &key)); | ||
| 494 | fs->freereg = reg; /* free registers */ | 483 | fs->freereg = reg; /* free registers */ |
| 484 | luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); | ||
| 485 | cc->nh++; | ||
| 495 | } | 486 | } |
| 496 | 487 | ||
| 497 | 488 | ||
| 498 | static int anotherfield (LexState *ls) { | 489 | static void closelistfield (FuncState *fs, struct ConsControl *cc) { |
| 499 | if (ls->t.token != ',') return 0; | 490 | if (cc->v.k == VVOID) return; /* there is no list item */ |
| 500 | next(ls); /* skip the comma */ | 491 | luaK_exp2nextreg(fs, &cc->v); |
| 501 | return (ls->t.token != ';' && ls->t.token != '}'); | 492 | cc->v.k = VVOID; |
| 502 | } | 493 | if (cc->tostore == LFIELDS_PER_FLUSH) { |
| 503 | 494 | luaK_codeABc(fs, OP_SETLIST, cc->t->info, cc->na-1); /* flush */ | |
| 504 | 495 | cc->tostore = 0; /* no more items pending */ | |
| 505 | static int recfields (LexState *ls, expdesc *t) { | 496 | fs->freereg = cc->t->info + 1; /* free registers */ |
| 506 | /* recfields -> recfield { `,' recfield } [`,'] */ | 497 | } |
| 507 | int n = 0; | ||
| 508 | do { /* at least one element */ | ||
| 509 | recfield(ls, t); | ||
| 510 | luaX_checklimit(ls, n, MAX_INT, "items in a constructor"); | ||
| 511 | n++; | ||
| 512 | } while (anotherfield(ls)); | ||
| 513 | return n; | ||
| 514 | } | 498 | } |
| 515 | 499 | ||
| 516 | 500 | ||
| 517 | static int listfields (LexState *ls, expdesc *t) { | 501 | static void lastlistfield (FuncState *fs, struct ConsControl *cc) { |
| 518 | /* listfields -> exp1 { `,' exp1 } [`,'] */ | 502 | if (cc->tostore == 0) return; |
| 519 | expdesc v; | 503 | if (cc->v.k == VCALL) { |
| 520 | FuncState *fs = ls->fs; | 504 | luaK_setcallreturns(fs, &cc->v, LUA_MULTRET); |
| 521 | int n = 1; /* at least one element */ | 505 | luaK_codeABc(fs, OP_SETLISTO, cc->t->info, cc->na-1); |
| 522 | int reg; | ||
| 523 | reg = fs->freereg; | ||
| 524 | expr(ls, &v); | ||
| 525 | while (anotherfield(ls)) { | ||
| 526 | luaK_exp2nextreg(fs, &v); | ||
| 527 | luaX_checklimit(ls, n, MAXARG_Bc, "items in a constructor"); | ||
| 528 | if (n%LFIELDS_PER_FLUSH == 0) { | ||
| 529 | luaK_codeABc(fs, OP_SETLIST, t->info, n-1); /* flush */ | ||
| 530 | fs->freereg = reg; /* free registers */ | ||
| 531 | } | ||
| 532 | expr(ls, &v); | ||
| 533 | n++; | ||
| 534 | } | ||
| 535 | if (v.k == VCALL) { | ||
| 536 | luaK_setcallreturns(fs, &v, LUA_MULTRET); | ||
| 537 | luaK_codeABc(fs, OP_SETLISTO, t->info, n-1); | ||
| 538 | } | 506 | } |
| 539 | else { | 507 | else { |
| 540 | luaK_exp2nextreg(fs, &v); | 508 | if (cc->v.k != VVOID) |
| 541 | luaK_codeABc(fs, OP_SETLIST, t->info, n-1); | 509 | luaK_exp2nextreg(fs, &cc->v); |
| 510 | luaK_codeABc(fs, OP_SETLIST, cc->t->info, cc->na-1); | ||
| 542 | } | 511 | } |
| 543 | fs->freereg = reg; /* free registers */ | 512 | fs->freereg = cc->t->info + 1; /* free registers */ |
| 544 | return n; | ||
| 545 | } | 513 | } |
| 546 | 514 | ||
| 547 | 515 | ||
| 548 | static void constructor_part (LexState *ls, expdesc *t, Constdesc *cd) { | 516 | static void listfield (LexState *ls, struct ConsControl *cc) { |
| 549 | switch (ls->t.token) { | 517 | expr(ls, &cc->v); |
| 550 | case ';': case '}': { /* constructor_part -> empty */ | 518 | luaX_checklimit(ls, cc->na, MAXARG_Bc, "items in a constructor"); |
| 551 | cd->narray = cd->nhash = 0; | 519 | cc->na++; |
| 552 | cd->k = ls->t.token; | 520 | cc->tostore++; |
| 553 | break; | ||
| 554 | } | ||
| 555 | case TK_NAME: { /* may be listfields or recfields */ | ||
| 556 | lookahead(ls); | ||
| 557 | if (ls->lookahead.token != '=') /* expression? */ | ||
| 558 | goto case_default; | ||
| 559 | /* else go through to recfields */ | ||
| 560 | } | ||
| 561 | case '[': { /* constructor_part -> recfields */ | ||
| 562 | cd->nhash = recfields(ls, t); | ||
| 563 | cd->narray = 0; | ||
| 564 | cd->k = 1; /* record */ | ||
| 565 | break; | ||
| 566 | } | ||
| 567 | default: { /* constructor_part -> listfields */ | ||
| 568 | case_default: | ||
| 569 | cd->narray = listfields(ls, t); | ||
| 570 | cd->nhash = 0; | ||
| 571 | cd->k = 0; /* list */ | ||
| 572 | break; | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } | 521 | } |
| 576 | 522 | ||
| 577 | 523 | ||
| 578 | static void constructor (LexState *ls, expdesc *t) { | 524 | static void constructor (LexState *ls, expdesc *t) { |
| 579 | /* constructor -> `{' constructor_part [`;' constructor_part] `}' */ | 525 | /* constructor -> ?? */ |
| 580 | FuncState *fs = ls->fs; | 526 | FuncState *fs = ls->fs; |
| 581 | int line = ls->linenumber; | 527 | int line = ls->linenumber; |
| 582 | int na, nh; | 528 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); |
| 583 | int pc; | 529 | struct ConsControl cc; |
| 584 | Constdesc cd; | 530 | cc.na = cc.nh = cc.tostore = 0; |
| 585 | pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); | 531 | cc.t = t; |
| 586 | init_exp(t, VRELOCABLE, pc); | 532 | init_exp(t, VRELOCABLE, pc); |
| 533 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ | ||
| 587 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ | 534 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ |
| 588 | check(ls, '{'); | 535 | check(ls, '{'); |
| 589 | constructor_part(ls, t, &cd); | 536 | for (;;) { |
| 590 | na = cd.narray; | 537 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); |
| 591 | nh = cd.nhash; | 538 | optional(ls, ';'); /* compatibility only */ |
| 592 | if (optional(ls, ';')) { | 539 | if (ls->t.token == '}') break; |
| 593 | Constdesc other_cd; | 540 | closelistfield(fs, &cc); |
| 594 | constructor_part(ls, t, &other_cd); | 541 | switch(ls->t.token) { |
| 595 | check_condition(ls,(cd.k != other_cd.k), "invalid constructor syntax"); | 542 | case TK_NAME: { /* may be listfields or recfields */ |
| 596 | na += other_cd.narray; | 543 | lookahead(ls); |
| 597 | nh += other_cd.nhash; | 544 | if (ls->lookahead.token != '=') /* expression? */ |
| 545 | listfield(ls, &cc); | ||
| 546 | else | ||
| 547 | recfield(ls, &cc); | ||
| 548 | break; | ||
| 549 | } | ||
| 550 | case '[': { /* constructor_item -> recfield */ | ||
| 551 | recfield(ls, &cc); | ||
| 552 | break; | ||
| 553 | } | ||
| 554 | default: { /* constructor_part -> listfield */ | ||
| 555 | listfield(ls, &cc); | ||
| 556 | break; | ||
| 557 | } | ||
| 558 | } | ||
| 559 | if (ls->t.token == ',' || ls->t.token == ';') | ||
| 560 | next(ls); | ||
| 561 | else | ||
| 562 | break; | ||
| 598 | } | 563 | } |
| 599 | check_match(ls, '}', '{', line); | 564 | check_match(ls, '}', '{', line); |
| 600 | if (na > 0) | 565 | lastlistfield(fs, &cc); |
| 601 | SETARG_B(fs->f->code[pc], luaO_log2(na-1)+2); /* set initial table size */ | 566 | if (cc.na > 0) |
| 602 | SETARG_C(fs->f->code[pc], luaO_log2(nh)+1); /* set initial table size */ | 567 | SETARG_B(fs->f->code[pc], luaO_log2(cc.na-1)+2); /* set initial table size */ |
| 568 | SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */ | ||
| 603 | } | 569 | } |
| 604 | 570 | ||
| 571 | |||
| 605 | /* }====================================================================== */ | 572 | /* }====================================================================== */ |
| 606 | 573 | ||
| 607 | 574 | ||
| @@ -955,24 +922,27 @@ static void exp1 (LexState *ls) { | |||
| 955 | } | 922 | } |
| 956 | 923 | ||
| 957 | 924 | ||
| 958 | static void forbody (LexState *ls, int nvar, OpCode loopfor) { | 925 | static void forbody (LexState *ls, OpCode loopfor) { |
| 959 | /* forbody -> DO block END */ | 926 | /* forbody -> DO block END */ |
| 960 | FuncState *fs = ls->fs; | 927 | FuncState *fs = ls->fs; |
| 961 | int basereg = fs->freereg - nvar; | 928 | int basereg = fs->freereg - 3; |
| 962 | int prep = luaK_jump(fs); | 929 | int prep = luaK_jump(fs); |
| 963 | int blockinit = luaK_getlabel(fs); | 930 | int blockinit = luaK_getlabel(fs); |
| 964 | check(ls, TK_DO); | 931 | check(ls, TK_DO); |
| 965 | adjustlocalvars(ls, nvar); /* scope for control variables */ | 932 | adjustlocalvars(ls, 3); /* scope for control variables */ |
| 966 | block(ls); | 933 | block(ls); |
| 967 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); | 934 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); |
| 968 | luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit); | 935 | luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit); |
| 969 | removelocalvars(ls, nvar, 1); | 936 | removelocalvars(ls, 3, 1); |
| 970 | } | 937 | } |
| 971 | 938 | ||
| 972 | 939 | ||
| 973 | static void fornum (LexState *ls, TString *varname) { | 940 | static void fornum (LexState *ls, TString *varname) { |
| 974 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ | 941 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ |
| 975 | FuncState *fs = ls->fs; | 942 | FuncState *fs = ls->fs; |
| 943 | new_localvar(ls, varname, 0); | ||
| 944 | new_localvarstr(ls, "(limit)", 1); | ||
| 945 | new_localvarstr(ls, "(step)", 2); | ||
| 976 | check(ls, '='); | 946 | check(ls, '='); |
| 977 | exp1(ls); /* initial value */ | 947 | exp1(ls); /* initial value */ |
| 978 | check(ls, ','); | 948 | check(ls, ','); |
| @@ -983,30 +953,27 @@ static void fornum (LexState *ls, TString *varname) { | |||
| 983 | luaK_codeABc(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); | 953 | luaK_codeABc(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); |
| 984 | luaK_reserveregs(fs, 1); | 954 | luaK_reserveregs(fs, 1); |
| 985 | } | 955 | } |
| 986 | new_localvar(ls, varname, 0); | ||
| 987 | new_localvarstr(ls, "(limit)", 1); | ||
| 988 | new_localvarstr(ls, "(step)", 2); | ||
| 989 | luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); | 956 | luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); |
| 990 | forbody(ls, 3, OP_FORLOOP); | 957 | forbody(ls, OP_FORLOOP); |
| 991 | } | 958 | } |
| 992 | 959 | ||
| 993 | 960 | ||
| 994 | static void forlist (LexState *ls, TString *indexname) { | 961 | static void forlist (LexState *ls, TString *indexname) { |
| 995 | /* forlist -> NAME,NAME IN exp1 forbody */ | 962 | /* forlist -> NAME,NAME IN exp1 forbody */ |
| 996 | TString *valname; | ||
| 997 | FuncState *fs = ls->fs; | 963 | FuncState *fs = ls->fs; |
| 998 | check(ls, ','); | 964 | new_localvarstr(ls, "(table)", 0); |
| 999 | valname = str_checkname(ls); | 965 | new_localvar(ls, indexname, 1); |
| 1000 | next(ls); /* skip var name */ | 966 | if (optional(ls, ',')) { |
| 967 | new_localvar(ls, str_checkname(ls), 2); | ||
| 968 | next(ls); /* skip var name */ | ||
| 969 | } | ||
| 970 | else | ||
| 971 | new_localvarstr(ls, "(val)", 2); | ||
| 1001 | check(ls, TK_IN); | 972 | check(ls, TK_IN); |
| 1002 | exp1(ls); /* table */ | 973 | exp1(ls); /* table */ |
| 1003 | new_localvarstr(ls, "(table)", 0); | 974 | luaK_reserveregs(fs, 2); /* registers for index and val */ |
| 1004 | new_localvarstr(ls, "(index)", 1); | 975 | luaK_codeABC(fs, OP_LOADNIL, fs->freereg - 2, fs->freereg - 1, 0); |
| 1005 | new_localvar(ls, indexname, 2); | 976 | forbody(ls, OP_TFORLOOP); |
| 1006 | new_localvar(ls, valname, 3); | ||
| 1007 | luaK_reserveregs(fs, 3); /* registers for control, index and val */ | ||
| 1008 | luaK_codeABc(fs, OP_LOADK, fs->freereg - 3, luaK_numberK(fs, -1)); | ||
| 1009 | forbody(ls, 4, OP_TFORLOOP); | ||
| 1010 | } | 977 | } |
| 1011 | 978 | ||
| 1012 | 979 | ||
| @@ -1021,8 +988,8 @@ static void forstat (LexState *ls, int line) { | |||
| 1021 | next(ls); /* skip var name */ | 988 | next(ls); /* skip var name */ |
| 1022 | switch (ls->t.token) { | 989 | switch (ls->t.token) { |
| 1023 | case '=': fornum(ls, varname); break; | 990 | case '=': fornum(ls, varname); break; |
| 1024 | case ',': forlist(ls, varname); break; | 991 | case ',': case TK_IN: forlist(ls, varname); break; |
| 1025 | default: luaK_error(ls, "`=' or `,' expected"); | 992 | default: luaK_error(ls, "`=' or `in' expected"); |
| 1026 | } | 993 | } |
| 1027 | check_match(ls, TK_END, TK_FOR, line); | 994 | check_match(ls, TK_END, TK_FOR, line); |
| 1028 | leavebreak(fs, &bl); | 995 | leavebreak(fs, &bl); |
