diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-02-14 19:46:58 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-02-14 19:46:58 -0200 |
commit | ac178ee4788c13761ec0850b31ff17673a33f227 (patch) | |
tree | 6df840528827d07988481e561c4015a0842eaeb8 /lparser.c | |
parent | 1e602a61b331a46e3690cc43a6c41074c1de7eab (diff) | |
download | lua-ac178ee4788c13761ec0850b31ff17673a33f227.tar.gz lua-ac178ee4788c13761ec0850b31ff17673a33f227.tar.bz2 lua-ac178ee4788c13761ec0850b31ff17673a33f227.zip |
new constructor syntax + new generic `for'
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); |