Exemple #1
0
/*
** Function to index a table.
** Receives the table at top-2 and the index at top-1.
*/
void luaV_gettable (void)
{
  struct Stack *S = &L->stack;
  TObject *im;
  if (ttype(S->top-2) != LUA_T_ARRAY)  /* not a table, get "gettable" method */
    im = luaT_getimbyObj(S->top-2, IM_GETTABLE);
  else {  /* object is a table... */
    int32 tg = (S->top-2)->value.a->htag;
    im = luaT_getim(tg, IM_GETTABLE);
    if (ttype(im) == LUA_T_NIL) {  /* and does not have a "gettable" method */
      TObject *h = luaH_get(avalue(S->top-2), S->top-1);
      if (h != NULL && ttype(h) != LUA_T_NIL) {
        --S->top;
        *(S->top-1) = *h;
      }
      else if (ttype(im=luaT_getim(tg, IM_INDEX)) != LUA_T_NIL)
        luaD_callTM(im, 2, 1);
      else {
        --S->top;
        ttype(S->top-1) = LUA_T_NIL;
      }
      return;
    }
    /* else it has a "gettable" method, go through to next command */
  }
  /* object is not a table, or it has a "gettable" method */
  if (ttype(im) != LUA_T_NIL)
    luaD_callTM(im, 2, 1);
  else
    lua_error("indexed expression not a table");
}
Exemple #2
0
static void message(const char *s) {
	TObject im = errorim;
	if (ttype(&im) != LUA_T_NIL) {
		lua_pushstring(s);
		luaD_callTM(&im, 1, 0);
	}
}
Exemple #3
0
void luaD_gcIM(TObject *o) {
	TObject *im = luaT_getimbyObj(o, IM_GC);
	if (ttype(im) != LUA_T_NIL) {
		*lua_state->stack.top = *o;
		incr_top;
		luaD_callTM(im, 1, 0);
	}
}
Exemple #4
0
static void call_binTM(IMS event, const char *msg) {
	TObject *im = luaT_getimbyObj(lua_state->stack.top - 2, event); // try first operand
	if (ttype(im) == LUA_T_NIL) {
		im = luaT_getimbyObj(lua_state->stack.top - 1, event);  // try second operand
		if (ttype(im) == LUA_T_NIL) {
			im = luaT_getim(0, event);  // try a 'global' i.m.
			if (ttype(im) == LUA_T_NIL)
				lua_error(msg);
		}
	}
	lua_pushstring(luaT_eventname[event]);
	luaD_callTM(im, 3, 1);
}
Exemple #5
0
void luaV_getglobal(TaggedString *ts) {
	// WARNING: caller must assure stack space
	TObject *value = &ts->globalval;
	TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL);
	if (ttype(im) == LUA_T_NIL) {  // default behavior
		*lua_state->stack.top++ = *value;
	} else {
		Stack *S = &lua_state->stack;
		ttype(S->top) = LUA_T_STRING;
		tsvalue(S->top) = ts;
		S->top++;
		*S->top++ = *value;
		luaD_callTM(im, 2, 1);
	}
}
Exemple #6
0
static int call_binTM (lua_State *L, StkId top, TMS event) {
  /* try first operand */
  Closure *tm = luaT_gettmbyObj(L, top-2, event);
  L->top = top;
  if (tm == NULL) {
    tm = luaT_gettmbyObj(L, top-1, event);  /* try second operand */
    if (tm == NULL) {
      tm = luaT_gettm(L, 0, event);  /* try a `global' method */
      if (tm == NULL)
        return 0;  /* error */
    }
  }
  lua_pushstring(L, luaT_eventname[event]);
  luaD_callTM(L, tm, 3, 1);
  return 1;
}
Exemple #7
0
void luaV_setglobal(TaggedString *ts) {
	TObject *oldvalue = &ts->globalval;
	TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
	if (ttype(im) == LUA_T_NIL)  // default behavior */
		luaS_rawsetglobal(ts, --lua_state->stack.top);
	else {
		// WARNING: caller must assure stack space
		Stack *S = &lua_state->stack;
		TObject newvalue = *(S->top - 1);
		ttype(S->top - 1) = LUA_T_STRING;
		tsvalue(S->top - 1) = ts;
		*S->top++ = *oldvalue;
		*S->top++ = newvalue;
		luaD_callTM(im, 3, 0);
	}
}
Exemple #8
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;
}
Exemple #9
0
/*
** Function to store indexed based on values at the stack.top
** mode = 0: raw store (without tag methods)
** mode = 1: normal store (with tag methods)
** mode = 2: "deep lua_state->stack.stack" store (with tag methods)
*/
void luaV_settable(TObject *t, int32 mode) {
	struct Stack *S = &lua_state->stack;
	TObject *im = (mode == 0) ? NULL : luaT_getimbyObj(t, IM_SETTABLE);
	if (ttype(t) == LUA_T_ARRAY && (!im || ttype(im) == LUA_T_NIL)) {
		TObject *h = luaH_set(avalue(t), t + 1);
		*h = *(S->top - 1);
		S->top -= (mode == 2) ? 1 : 3;
	} else {  // object is not a table, and/or has a specific "settable" method
		if (im && ttype(im) != LUA_T_NIL) {
			if (mode == 2) {
				*(S->top + 1) = *(lua_state->stack.top - 1);
				*(S->top) = *(t + 1);
				*(S->top - 1) = *t;
				S->top += 2;  // WARNING: caller must assure stack space
			}
			luaD_callTM(im, 3, 0);
		} else
			lua_error("indexed expression not a table");
	}
}
Exemple #10
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;
}