/* ** 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"); }
static void message(const char *s) { TObject im = errorim; if (ttype(&im) != LUA_T_NIL) { lua_pushstring(s); luaD_callTM(&im, 1, 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); } }
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); }
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); } }
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; }
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); } }
/* ** 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; }
/* ** 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"); } }
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; }