Пример #1
0
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);
}
Пример #2
0
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 */
}
Пример #3
0
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);
  }
}
Пример #4
0
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);
}