diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-05-31 15:51:50 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-05-31 15:51:50 -0300 |
commit | 616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59 (patch) | |
tree | 78322d820e3af1ca6645ed08eaa65a8f0aa04fec /lparser.c | |
parent | 47eda6ebd83785908ac26f8dd06dff36a7d42664 (diff) | |
download | lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.tar.gz lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.tar.bz2 lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.zip |
new way to use `vararg' parameters (with `...')
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 60 |
1 files changed, 31 insertions, 29 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.3 2004/03/26 14:02:41 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | 28 | ||
29 | 29 | ||
30 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) | ||
31 | |||
30 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) | 32 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) |
31 | 33 | ||
32 | #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m) | 34 | #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m) |
@@ -272,11 +274,11 @@ static TString *singlevar (LexState *ls, expdesc *var, int base) { | |||
272 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | 274 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
273 | FuncState *fs = ls->fs; | 275 | FuncState *fs = ls->fs; |
274 | int extra = nvars - nexps; | 276 | int extra = nvars - nexps; |
275 | if (e->k == VCALL) { | 277 | if (hasmultret(e->k)) { |
276 | extra++; /* includes call itself */ | 278 | extra++; /* includes call itself */ |
277 | if (extra <= 0) extra = 0; | 279 | if (extra < 0) extra = 0; |
278 | else luaK_reserveregs(fs, extra-1); | 280 | luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ |
279 | luaK_setcallreturns(fs, e, extra); /* call provides the difference */ | 281 | if (extra > 1) luaK_reserveregs(fs, extra-1); |
280 | } | 282 | } |
281 | else { | 283 | else { |
282 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ | 284 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ |
@@ -392,6 +394,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { | |||
392 | lexstate.nestlevel = 0; | 394 | lexstate.nestlevel = 0; |
393 | luaX_setinput(L, &lexstate, z, luaS_new(L, name)); | 395 | luaX_setinput(L, &lexstate, z, luaS_new(L, name)); |
394 | open_func(&lexstate, &funcstate); | 396 | open_func(&lexstate, &funcstate); |
397 | funcstate.f->is_vararg = NEWSTYLEVARARG; | ||
395 | next(&lexstate); /* read first token */ | 398 | next(&lexstate); /* read first token */ |
396 | chunk(&lexstate); | 399 | chunk(&lexstate); |
397 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); | 400 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); |
@@ -481,8 +484,8 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) { | |||
481 | 484 | ||
482 | static void lastlistfield (FuncState *fs, struct ConsControl *cc) { | 485 | static void lastlistfield (FuncState *fs, struct ConsControl *cc) { |
483 | if (cc->tostore == 0) return; | 486 | if (cc->tostore == 0) return; |
484 | if (cc->v.k == VCALL) { | 487 | if (hasmultret(cc->v.k)) { |
485 | luaK_setcallreturns(fs, &cc->v, LUA_MULTRET); | 488 | luaK_setmultret(fs, &cc->v); |
486 | luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1); | 489 | luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1); |
487 | cc->na--; /* do not count last expression (unknown number of elements) */ | 490 | cc->na--; /* do not count last expression (unknown number of elements) */ |
488 | } | 491 | } |
@@ -558,12 +561,8 @@ static void parlist (LexState *ls) { | |||
558 | if (ls->t.token != ')') { /* is `parlist' not empty? */ | 561 | if (ls->t.token != ')') { /* is `parlist' not empty? */ |
559 | do { | 562 | do { |
560 | switch (ls->t.token) { | 563 | switch (ls->t.token) { |
561 | case TK_NAME: { /* param -> NAME [ `=' `...' ] */ | 564 | case TK_NAME: { /* param -> NAME */ |
562 | new_localvar(ls, str_checkname(ls), nparams++); | 565 | new_localvar(ls, str_checkname(ls), nparams++); |
563 | if (testnext(ls, '=')) { | ||
564 | check(ls, TK_DOTS); | ||
565 | f->is_vararg = 1; | ||
566 | } | ||
567 | break; | 566 | break; |
568 | } | 567 | } |
569 | case TK_DOTS: { /* param -> `...' */ | 568 | case TK_DOTS: { /* param -> `...' */ |
@@ -629,7 +628,7 @@ static void funcargs (LexState *ls, expdesc *f) { | |||
629 | args.k = VVOID; | 628 | args.k = VVOID; |
630 | else { | 629 | else { |
631 | explist1(ls, &args); | 630 | explist1(ls, &args); |
632 | luaK_setcallreturns(fs, &args, LUA_MULTRET); | 631 | luaK_setmultret(fs, &args); |
633 | } | 632 | } |
634 | check_match(ls, ')', '(', line); | 633 | check_match(ls, ')', '(', line); |
635 | break; | 634 | break; |
@@ -650,7 +649,7 @@ static void funcargs (LexState *ls, expdesc *f) { | |||
650 | } | 649 | } |
651 | lua_assert(f->k == VNONRELOC); | 650 | lua_assert(f->k == VNONRELOC); |
652 | base = f->info; /* base register for call */ | 651 | base = f->info; /* base register for call */ |
653 | if (args.k == VCALL) | 652 | if (hasmultret(args.k)) |
654 | nparams = LUA_MULTRET; /* open call */ | 653 | nparams = LUA_MULTRET; /* open call */ |
655 | else { | 654 | else { |
656 | if (args.k != VVOID) | 655 | if (args.k != VVOID) |
@@ -739,43 +738,47 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
739 | switch (ls->t.token) { | 738 | switch (ls->t.token) { |
740 | case TK_NUMBER: { | 739 | case TK_NUMBER: { |
741 | init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r)); | 740 | init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r)); |
742 | next(ls); /* must use `seminfo' before `next' */ | ||
743 | break; | 741 | break; |
744 | } | 742 | } |
745 | case TK_STRING: { | 743 | case TK_STRING: { |
746 | codestring(ls, v, ls->t.seminfo.ts); | 744 | codestring(ls, v, ls->t.seminfo.ts); |
747 | next(ls); /* must use `seminfo' before `next' */ | ||
748 | break; | 745 | break; |
749 | } | 746 | } |
750 | case TK_NIL: { | 747 | case TK_NIL: { |
751 | init_exp(v, VNIL, 0); | 748 | init_exp(v, VNIL, 0); |
752 | next(ls); | ||
753 | break; | 749 | break; |
754 | } | 750 | } |
755 | case TK_TRUE: { | 751 | case TK_TRUE: { |
756 | init_exp(v, VTRUE, 0); | 752 | init_exp(v, VTRUE, 0); |
757 | next(ls); | ||
758 | break; | 753 | break; |
759 | } | 754 | } |
760 | case TK_FALSE: { | 755 | case TK_FALSE: { |
761 | init_exp(v, VFALSE, 0); | 756 | init_exp(v, VFALSE, 0); |
762 | next(ls); | 757 | break; |
758 | } | ||
759 | case TK_DOTS: { /* vararg */ | ||
760 | FuncState *fs = ls->fs; | ||
761 | check_condition(ls, fs->f->is_vararg, | ||
762 | "cannot use `...' outside a vararg function"); | ||
763 | fs->f->is_vararg = NEWSTYLEVARARG; | ||
764 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); | ||
763 | break; | 765 | break; |
764 | } | 766 | } |
765 | case '{': { /* constructor */ | 767 | case '{': { /* constructor */ |
766 | constructor(ls, v); | 768 | constructor(ls, v); |
767 | break; | 769 | return; |
768 | } | 770 | } |
769 | case TK_FUNCTION: { | 771 | case TK_FUNCTION: { |
770 | next(ls); | 772 | next(ls); |
771 | body(ls, v, 0, ls->linenumber); | 773 | body(ls, v, 0, ls->linenumber); |
772 | break; | 774 | return; |
773 | } | 775 | } |
774 | default: { | 776 | default: { |
775 | primaryexp(ls, v); | 777 | primaryexp(ls, v); |
776 | break; | 778 | return; |
777 | } | 779 | } |
778 | } | 780 | } |
781 | next(ls); | ||
779 | } | 782 | } |
780 | 783 | ||
781 | 784 | ||
@@ -952,7 +955,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | |||
952 | ls->fs->freereg -= nexps - nvars; /* remove extra values */ | 955 | ls->fs->freereg -= nexps - nvars; /* remove extra values */ |
953 | } | 956 | } |
954 | else { | 957 | else { |
955 | luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */ | 958 | luaK_setoneret(ls->fs, &e); /* close last expression */ |
956 | luaK_storevar(ls->fs, &lh->v, &e); | 959 | luaK_storevar(ls->fs, &lh->v, &e); |
957 | return; /* avoid default */ | 960 | return; /* avoid default */ |
958 | } | 961 | } |
@@ -1236,9 +1239,8 @@ static void exprstat (LexState *ls) { | |||
1236 | FuncState *fs = ls->fs; | 1239 | FuncState *fs = ls->fs; |
1237 | struct LHS_assign v; | 1240 | struct LHS_assign v; |
1238 | primaryexp(ls, &v.v); | 1241 | primaryexp(ls, &v.v); |
1239 | if (v.v.k == VCALL) { /* stat -> func */ | 1242 | if (v.v.k == VCALL) /* stat -> func */ |
1240 | luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */ | 1243 | SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ |
1241 | } | ||
1242 | else { /* stat -> assignment */ | 1244 | else { /* stat -> assignment */ |
1243 | v.prev = NULL; | 1245 | v.prev = NULL; |
1244 | assignment(ls, &v, 1); | 1246 | assignment(ls, &v, 1); |
@@ -1256,9 +1258,9 @@ static void retstat (LexState *ls) { | |||
1256 | first = nret = 0; /* return no values */ | 1258 | first = nret = 0; /* return no values */ |
1257 | else { | 1259 | else { |
1258 | nret = explist1(ls, &e); /* optional return values */ | 1260 | nret = explist1(ls, &e); /* optional return values */ |
1259 | if (e.k == VCALL) { | 1261 | if (hasmultret(e.k)) { |
1260 | luaK_setcallreturns(fs, &e, LUA_MULTRET); | 1262 | luaK_setmultret(fs, &e); |
1261 | if (nret == 1) { /* tail call? */ | 1263 | if (e.k == VCALL && nret == 1) { /* tail call? */ |
1262 | SET_OPCODE(getcode(fs,&e), OP_TAILCALL); | 1264 | SET_OPCODE(getcode(fs,&e), OP_TAILCALL); |
1263 | lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); | 1265 | lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); |
1264 | } | 1266 | } |