static void retstat (LexState *ls) { /* stat -> RETURN explist */ FuncState *fs = ls->fs; expdesc e; int first, nret; /* registers with returned values */ luaX_next(ls); /* skip RETURN */ if (block_follow(ls->t.token) || ls->t.token == ';') first = nret = 0; /* return no values */ else { nret = explist1(ls, &e); /* optional return values */ if (hasmultret(e.k)) { luaK_setmultret(fs, &e); if (e.k == VCALL && nret == 1) { /* tail call? */ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); } first = fs->nactvar; nret = LUA_MULTRET; /* return all values */ } else { if (nret == 1) /* only one single value? */ first = luaK_exp2anyreg(fs, &e); else { luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ first = fs->nactvar; /* return all `active' values */ lua_assert(nret == fs->freereg - first); } } } luaK_ret(fs, first, nret); }
static void funcargs(LexState* ls, expdesc* f) { FuncState* fs = ls->fs; expdesc args; int base, nparams; int line = ls->linenumber; switch (ls->t.token) { case '(': /* funcargs -> `(' [ explist1 ] `)' */ { if (line != ls->lastline) luaX_syntaxerror(ls, "ambiguous syntax (function call x new statement)"); luaX_next(ls); if (ls->t.token == ')') /* arg list is empty? */ args.k = VVOID; else { explist1(ls, &args); luaK_setmultret(fs, &args); } check_match(ls, ')', '(', line); break; } case '{': /* funcargs -> constructor */ { constructor(ls, &args); break; } case TK_STRING: /* funcargs -> STRING */ { codestring(ls, &args, ls->t.seminfo.ts); luaX_next(ls); /* must use `seminfo' before `next' */ break; } default: { luaX_syntaxerror(ls, "function arguments expected"); return; } } lua_assert(f->k == VNONRELOC); base = f->u.s.info; /* base register for call */ if (hasmultret(args.k)) nparams = LUA_MULTRET; /* open call */ else { if (args.k != VVOID) luaK_exp2nextreg(fs, &args); /* close last argument */ nparams = fs->freereg - (base + 1); } init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams + 1, 2)); luaK_fixline(fs, line); fs->freereg = base + 1; /* call remove function and arguments and leaves (unless changed) one result */ }
static void lastlistfield (FuncState *fs, struct ConsControl *cc) { if (cc->tostore == 0) return; if (hasmultret(cc->v.k)) { luaK_setmultret(fs, &cc->v); luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); cc->na--; /* do not count last expression (unknown number of elements) */ } else { if (cc->v.k != VVOID) luaK_exp2nextreg(fs, &cc->v); luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); } }
static void retstat (LexState *ls) { /* stat -> RETURN explist */ FuncState *fs = ls->fs; BlockCnt *bl = fs->bl; expdesc e; int first, nret; /* registers with returned values */ int ret_in_try = 0; luaX_next(ls); /* skip RETURN */ if (block_follow(ls->t.token) || ls->t.token == ';') first = nret = 0; /* return no values */ else { nret = explist1(ls, &e); /* optional return values */ if (hasmultret(e.k)) { luaK_setmultret(fs, &e); if (e.k == VCALL && nret == 1) { /* tail call? */ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); } first = fs->nactvar; nret = LUA_MULTRET; /* return all values */ } else { if (nret == 1) /* only one single value? */ first = luaK_exp2anyreg(fs, &e); else { luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ first = fs->nactvar; /* return all `active' values */ lua_assert(nret == fs->freereg - first); } } } /* before return, we should exit all try-catch blocks */ while (bl) { if (bl->isbreakable == 2) { if (ret_in_try) luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0); else { ret_in_try = 1; luaK_codeABC(fs, OP_EXITTRY, first, nret+1, 1); /* here we will save all return values */ } } else if (bl->isbreakable == 3) luaX_syntaxerror(ls, "can't return in _finally_ clause"); bl = bl->previous; } luaK_codeABC(fs, OP_RETURN, first, nret+1, ret_in_try); }