aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-05-31 15:51:50 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-05-31 15:51:50 -0300
commit616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59 (patch)
tree78322d820e3af1ca6645ed08eaa65a8f0aa04fec /lparser.c
parent47eda6ebd83785908ac26f8dd06dff36a7d42664 (diff)
downloadlua-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.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/lparser.c b/lparser.c
index d9f6cbd4..06fd8951 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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) {
272static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { 274static 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
482static void lastlistfield (FuncState *fs, struct ConsControl *cc) { 485static 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 }