예제 #1
0
파일: lparser.c 프로젝트: xiaofeng/Arcemu
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 adjust_assign(LexState *ls, int nvars, int nexps, expdesc *e)
{
    FuncState *fs   = ls->fs;
    int       extra = nvars - nexps;

    if (hasmultret(e->k))
    {
        extra++; /* includes call itself */
        if (extra < 0)
            extra = 0;

        luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
        if (extra > 1)
            luaK_reserveregs(fs, extra - 1);
    }
    else
    {
        if (e->k != VVOID)
            luaK_exp2nextreg(fs, e);             /* close last expression */

        if (extra > 0)
        {
            int reg = fs->freereg;
            luaK_reserveregs(fs, extra);
            luaK_nil(fs, reg, extra);
        }
    }
}
예제 #3
0
파일: lparser.c 프로젝트: Ape/DCPUToolchain
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 */
}
예제 #4
0
파일: lparser.c 프로젝트: xiaofeng/Arcemu
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);
  }
}
예제 #5
0
Statement *TypeCompiler::visit(ReturnStatement *statement)
{
    FuncState *fs = cs->fs;

    int first, nret; /* registers with returned values */

    if (!statement->result)
    {
        first = nret = 0; /* return no values */
    }
    else
    {
        ExpDesc e;
        nret = expList(&e, statement->result);

        if (hasmultret(e.k))
        {
            BC::setMultRet(fs, &e);

            // LOOM: No tail calls as they screw up profiling/debugging

            /*
             * 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 = BC::expToAnyReg(fs, &e);
            }
            else
            {
                BC::expToNextReg(fs, &e); /* values must go to the `stack' */
                first = fs->nactvar;      /* return all `active' values */
                lua_assert(nret == fs->freereg - first);
            }
        }
    }

    BC::ret(fs, first, nret);

    return statement;
}
예제 #6
0
void TypeCompiler::generateCall(ExpDesc *call, utArray<Expression *> *arguments,
                                MethodBase *methodBase)
{
    FuncState *fs = cs->fs;

    int line = lineNumber;

    ParameterInfo *vararg = NULL;

    if (methodBase)
    {
        vararg = methodBase->getVarArgParameter();
    }

    BC::expToNextReg(fs, call);

    ExpDesc args;
    args.k = VVOID;

    int nparams = 0;

    if ((arguments && arguments->size()) || vararg)
    {
        nparams = expList(&args, arguments, methodBase);
        BC::setMultRet(fs, &args);
    }

    lua_assert(call->k == VNONRELOC);
    int base = call->u.s.info; /* base register for call */

    if (hasmultret(args.k))
    {
        nparams = LUA_MULTRET; /* open call */
    }
    else
    {
        if (args.k != VVOID)
        {
            BC::expToNextReg(fs, &args); /* close last argument */
        }
        nparams = fs->freereg - (base + 1);
    }

    BC::initExpDesc(call, VCALL,
                    BC::codeABC(fs, OP_CALL, base, nparams + 1, 2));

    BC::fixLine(fs, line);

    fs->freereg = base + 1;
}
예제 #7
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);
}
예제 #8
0
파일: lparser.cpp 프로젝트: swizl/lua
/*static*/ void LexState::adjust_assign (/*LexState *ls,*/ int nvars, int nexps, expdesc *e) {
	//FuncState *fs = fs;
	int extra = nvars - nexps;
	if (hasmultret(e->k)) {
		extra++;  /* includes call itself */
		if (extra < 0) extra = 0;
		fs->luaK_setreturns(e, extra);  /* last exp. provides the difference */
		if (extra > 1) fs->luaK_reserveregs(extra-1);
	}
	else {
		if (e->k != VVOID) fs->luaK_exp2nextreg(e);  /* close last expression */
		if (extra > 0) {
			int reg = fs->free_reg;
			fs->luaK_reserveregs(extra);
			fs->luaK_nil(reg, extra);
		}
	}
}
예제 #9
0
Statement *TypeCompiler::visit(ForInStatement *statement)
{
    FuncState *fs   = cs->fs;
    int       nvars = 0;
    int       line;

    char forIteratorName[256];

    // save off the previous iterator
    const char *prevForInIteratorName = currentForInIteratorName;

    // initially null, unless we need to use it due to
    // iterating with a variable external to block
    currentForInIteratorName = NULL;
    forIteratorName[0]       = 0;

    const char *vname = NULL;

    ExpDesc v;
    ExpDesc fv;

    if (statement->variable->astType == AST_VARDECL)
    {
        VariableDeclaration *vd = (VariableDeclaration *)statement->variable;
        vname = vd->identifier->string.c_str();
    }
    else if (statement->variable->astType == AST_IDENTIFIER)
    {
        vname = ((Identifier *)statement->variable)->string.c_str();

        // a little sanity
        lmAssert(strlen(vname) < 240, "For..In variable name > 240 characters");

        // we are using an external variable as the iterator for the loop
        // this means that we'll have to do a quick store to it when exiting the
        // loop (also via break)
        sprintf(forIteratorName, "__ls_%s", vname);
        currentForInIteratorName = forIteratorName;

        BC::newLocalVar(cs, forIteratorName, 0);
        BC::reserveRegs(fs, 1);
        BC::adjustLocalVars(cs, 1);
    }
    else
    {
        lmAssert(0, "Unknown variable statement in for..in initializer");
    }

    BlockCnt forbl;
    enterBlock(fs, &forbl, 1); /* scope for loop and control variables */

    int base = fs->freereg;

    /* create control variables */
    BC::newLocalVar(cs, "(for generator)", nvars++);
    BC::newLocalVar(cs, "(for state)", nvars++);
    BC::newLocalVar(cs, "(for control)", nvars++);

    //TODO: It would be nice to have a way to iterate pairs
    if (statement->foreach)
    {
        BC::newLocalVar(cs, "__ls_key", nvars++);
    }

    /* create declared variables */
    BC::newLocalVar(cs, vname, nvars++);

    line = lineNumber;

    bool isVector = false;

    if (statement->expression->type->getFullName() == "system.Vector")
    {
        isVector = true;
    }

    ExpDesc pairs;

    if (isVector)
    {
        BC::singleVar(cs, &pairs, "__lua_ipairs");
    }
    else
    {
        BC::singleVar(cs, &pairs, "__lua_pairs");
    }

    BC::expToNextReg(fs, &pairs);

    ExpDesc arg;

    int cbase = pairs.u.s.info; /* base register for call */

    statement->expression->visitExpression(this);
    arg = statement->expression->e;
    ExpDesc right;

    if (isVector)
    {
        // we pass the instance itself
    }
    else
    {
        BC::initExpDesc(&right, VKNUM, 0);
        right.u.nval = LSINDEXDICTPAIRS;

        BC::expToNextReg(fs, &arg);
        BC::expToNextReg(fs, &right);
        BC::expToVal(fs, &right);
        BC::indexed(fs, &arg, &right);
    }

    BC::setMultRet(fs, &arg);

    int nparams = 0;

    if (hasmultret(arg.k))
    {
        nparams = LUA_MULTRET; /* open call */
    }
    else
    {
        if (arg.k != VVOID)
        {
            BC::expToNextReg(fs, &arg); /* close last argument */
        }
        nparams = fs->freereg - (cbase + 1);
    }

    BC::initExpDesc(&pairs, VCALL,
                    BC::codeABC(fs, OP_CALL, cbase, nparams + 1,
                                2 /* returns 1 values */));

    fs->freereg = cbase + 1; /* call remove function and arguments and leaves*/

    BC::adjustAssign(cs, 3, 1, &pairs);

    BC::checkStack(fs, 3); /* extra space to call generator */

    /* forbody -> DO block */
    BlockCnt bl;

    int prep, endfor;

    BC::adjustLocalVars(cs, 3); /* control variables */
    prep = BC::jump(fs);
    enterBlock(fs, &bl, 0);     /* scope for declared variables */
    BC::adjustLocalVars(cs, nvars - 3);
    BC::reserveRegs(fs, nvars - 3);
    block(cs, statement->statement);

    if (forIteratorName[0])
    {
        // we need to store
        BC::singleVar(cs, &v, vname);
        BC::singleVar(cs, &fv, forIteratorName);
        BC::storeVar(fs, &fv, &v);
    }

    leaveBlock(fs); /* end of scope for declared variables */

    BC::patchToHere(fs, prep);
    BC::patchToHere(fs, forbl.continuelist); /* patch in continue list for for .. in/ for .. each */

    endfor = BC::codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);

    BC::fixLine(fs, line); /* pretend that `OP_FOR' starts the loop */

    BC::patchList(fs, BC::jump(fs), prep + 1);

    leaveBlock(fs);

    if (forIteratorName[0])
    {
        // we need to store to this block's var
        BC::singleVar(cs, &v, vname);
        BC::singleVar(cs, &fv, forIteratorName);
        BC::storeVar(fs, &v, &fv);
    }

    currentForInIteratorName = prevForInIteratorName;

    return statement;
}