Ejemplo n.º 1
0
/*
** Call a function (C or Lua). The parameters must be on the stack,
** between [stack+base,top). The function to be called is at stack+base-1.
** When returns, the results are on the stack, between [stack+base-1,top).
** The number of results is nResults, unless nResults=MULT_RET.
*/
static void do_call (StkId base, int nResults)
{
  StkId firstResult;
  TObject *func = stack+base-1;
  int i;
  if (ttype(func) == LUA_T_CFUNCTION) {
    ttype(func) = LUA_T_CMARK;
    firstResult = callC(fvalue(func), base);
  }
  else if (ttype(func) == LUA_T_FUNCTION) {
    ttype(func) = LUA_T_MARK;
    firstResult = lua_execute(func->value.tf->code, base);
  }
  else { /* func is not a function */
    /* Check the tag method for invalid functions */
    TObject *im = luaI_getimbyObj(func, IM_FUNCTION);
    if (ttype(im) == LUA_T_NIL)
      lua_error("call expression not a function");
    open_stack((top-stack)-(base-1));
    stack[base-1] = *im;
    do_call(base, nResults);
    return;
  }
  /* adjust the number of results */
  if (nResults != MULT_RET)
    adjust_top(firstResult+nResults);
  /* move results to base-1 (to erase parameters and function) */
  base--;
  nResults = top - (stack+firstResult);  /* actual number of results */
  for (i=0; i<nResults; i++)
    *(stack+base+i) = *(stack+firstResult+i);
  top -= firstResult-base;
}
Ejemplo n.º 2
0
Archivo: opcode.c Proyecto: cskau/VM
/*
** Call a function (C or Lua). The parameters must be on the stack,
** between [stack+base,top). The function to be called is at stack+base-1.
** When returns, the results are on the stack, between [stack+base-1,top).
** The number of results is nResults, unless nResults=MULT_RET.
*/
static void do_call (StkId base, int nResults)
{
  StkId firstResult;
  Object *func = stack+base-1;
  int i;
  if (tag(func) == LUA_T_CFUNCTION)
  {
    tag(func) = LUA_T_CMARK;
    firstResult = callC(fvalue(func), base);
  }
  else if (tag(func) == LUA_T_FUNCTION)
  {
    tag(func) = LUA_T_MARK;
    firstResult = lua_execute(func->value.tf->code, base);
  }
  else
  { /* func is not a function */
    /* Call the fallback for invalid functions */
    open_stack((top-stack)-(base-1));
    stack[base-1] = luaI_fallBacks[FB_FUNCTION].function;
    do_call(base, nResults);
    return;
  }
  /* adjust the number of results */
  if (nResults != MULT_RET && top - (stack+firstResult) != nResults)
    adjust_top(firstResult+nResults);
  /* move results to base-1 (to erase parameters and function) */
  base--;
  nResults = top - (stack+firstResult);  /* actual number of results */
  for (i=0; i<nResults; i++)
    *(stack+base+i) = *(stack+firstResult+i);
  top -= firstResult-base;
}
Ejemplo n.º 3
0
static StkId callCclosure (struct Closure *cl, lua_CFunction f, StkId base) {
  TObject *pbase;
  int nup = cl->nelems;  /* number of upvalues */
  luaD_checkstack(nup);
  pbase = L->stack.stack+base;  /* care: previous call may change this */
  /* open space for upvalues as extra arguments */
  luaO_memup(pbase+nup, pbase, (L->stack.top-pbase)*sizeof(TObject));
  /* copy upvalues into stack */
  memcpy(pbase, cl->consts+1, nup*sizeof(TObject));
  L->stack.top += nup;
  return callC(f, base);
}
Ejemplo n.º 4
0
/*
** Call a function (C or Lua). The parameters must be on the stack,
** between [top-nArgs,top). The function to be called is right below the
** arguments.
** When returns, the results are on the stack, between [top-nArgs-1,top).
** The number of results is nResults, unless nResults=MULT_RET.
*/
void luaD_calln (int nArgs, int nResults) {
  struct Stack *S = &L->stack;  /* to optimize */
  StkId base = (S->top-S->stack)-nArgs;
  TObject *func = S->stack+base-1;
  StkId firstResult;
  int i;
  switch (ttype(func)) {
    case LUA_T_CPROTO:
      ttype(func) = LUA_T_CMARK;
      firstResult = callC(fvalue(func), base);
      break;
    case LUA_T_PROTO:
      ttype(func) = LUA_T_PMARK;
      firstResult = luaV_execute(NULL, tfvalue(func), base);
      break;
    case LUA_T_CLOSURE: {
      Closure *c = clvalue(func);
      TObject *proto = &(c->consts[0]);
      ttype(func) = LUA_T_CLMARK;
      firstResult = (ttype(proto) == LUA_T_CPROTO) ?
                       callCclosure(c, fvalue(proto), base) :
                       luaV_execute(c, tfvalue(proto), base);
      break;
    }
    default: { /* func is not a function */
      /* Check the tag method for invalid functions */
      TObject *im = luaT_getimbyObj(func, IM_FUNCTION);
      if (ttype(im) == LUA_T_NIL)
        lua_error("call expression not a function");
      luaD_callTM(im, (S->top-S->stack)-(base-1), nResults);
      return;
    }
  }
  /* adjust the number of results */
  if (nResults == MULT_RET)
    nResults = (S->top-S->stack)-firstResult;
  else
    luaD_adjusttop(firstResult+nResults);
  /* move results to base-1 (to erase parameters and function) */
  base--;
  for (i=0; i<nResults; i++)
    *(S->stack+base+i) = *(S->stack+firstResult+i);
  S->top -= firstResult-base;
}
Ejemplo n.º 5
0
int32 luaD_call(StkId base, int32 nResults) {
	lua_Task *tmpTask = lua_state->task;
	if (!lua_state->task || lua_state->state_counter2) {
		lua_Task *t = luaM_new(lua_Task);
		lua_taskinit(t, lua_state->task, base, nResults);
		lua_state->task = t;
	} else {
		tmpTask = lua_state->some_task;
	}

	while (1) {
		lua_CFunction function = NULL;
		StkId firstResult = 0;
		TObject *funcObj = lua_state->stack.stack + base - 1;
		if (ttype(funcObj) == LUA_T_CLOSURE) {
			Closure *c = clvalue(funcObj);
			TObject *proto = &(c->consts[0]);
			ttype(funcObj) = LUA_T_CLMARK;
			if (ttype(proto) == LUA_T_CPROTO) {
				function = fvalue(funcObj);
				firstResult = callCclosure(c, fvalue(proto), base);
			} else {
				lua_taskresume(lua_state->task, c, tfvalue(proto), base);
				firstResult = luaV_execute(lua_state->task);
			}
		} else if (ttype(funcObj) == LUA_T_PMARK) {
			if (!lua_state->task->some_flag) {
				TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
				if (ttype(im) == LUA_T_NIL)
					lua_error("call expression not a function");
				luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
				continue;
			}
			firstResult = luaV_execute(lua_state->task);
		} else if (ttype(funcObj) == LUA_T_CMARK) {
			if (!lua_state->task->some_flag) {
				TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
				if (ttype(im) == LUA_T_NIL)
					lua_error("call expression not a function");
				luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
				continue;
			}
		} else if (ttype(funcObj) == LUA_T_CLMARK) {
			Closure *c = clvalue(funcObj);
			TObject *proto = &(c->consts[0]);
			if (!lua_state->task->some_flag) {
				TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
				if (ttype(im) == LUA_T_NIL)
					lua_error("call expression not a function");
				luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
				continue;
			}
			if (ttype(proto) != LUA_T_CPROTO)
				firstResult = luaV_execute(lua_state->task);
		} else if (ttype(funcObj) == LUA_T_PROTO) {
			ttype(funcObj) = LUA_T_PMARK;
			lua_taskresume(lua_state->task, NULL, tfvalue(funcObj), base);
			firstResult = luaV_execute(lua_state->task);
		} else if (ttype(funcObj) == LUA_T_CPROTO) {
			ttype(funcObj) = LUA_T_CMARK;
			function = fvalue(funcObj);
			firstResult = callC(fvalue(funcObj), base);
		} else {
			TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
			if (ttype(im) == LUA_T_NIL) {
				// NOTE: Originally this throwed the lua_error. Anyway it is commented here because
				// when in year 4 bi.exit() calls bi.book.act:free(). But bi.book.act is nil,
				// hence it enters this branch and the error blocks the game.
				// Now we try instead to survive and go on with the function.
				lua_Task *t = lua_state->task;
				lua_state->task = t->next;
				lua_state->some_task = tmpTask;
				luaM_free(t);

				warning("Lua: call expression not a function");
				return 1;
// 				lua_error("call expression not a function");
			}
			luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
			continue;
		}

		if (firstResult <= 0) {
			nResults = lua_state->task->aux;
			base = -firstResult;
			lua_Task *t = luaM_new(lua_Task);
			lua_taskinit(t, lua_state->task, base, nResults);
			lua_state->task = t;
		} else {
			nResults = lua_state->task->some_results;
			base = lua_state->task->some_base;
			if (nResults != 255)
				luaD_adjusttop(firstResult + nResults);
			base--;
			nResults = lua_state->stack.top - (lua_state->stack.stack + firstResult);
			for (int32 i = 0; i < nResults; i++)
				*(lua_state->stack.stack + base + i) = *(lua_state->stack.stack + firstResult + i);
			lua_state->stack.top -= firstResult - base;

			lua_Task *tmp = lua_state->task;
			lua_state->task = lua_state->task->next;
			luaM_free(tmp);
			if (lua_state->task) {
				nResults = lua_state->task->some_results;
				base = lua_state->task->some_base;
			}

			if (function == break_here) {
				if (!lua_state->state_counter1)  {
					lua_state->some_task = tmpTask;
					return 1;
				}
			}
		}

		if (lua_state->task == tmpTask)
			break;
	}

	return 0;
}