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 (lua_State *L, TString *s) { const TObject *oldvalue = luaH_getstr(L->gt, s); Closure *tm = luaT_gettmbyObj(L, oldvalue, TM_SETGLOBAL); if (tm == NULL) { /* is there a tag method? */ if (oldvalue != &luaO_nilobject) { /* cast to remove `const' is OK, because `oldvalue' != luaO_nilobject */ *(TObject *)oldvalue = *(L->top - 1); } else { TObject key; ttype(&key) = LUA_TSTRING; tsvalue(&key) = s; *luaH_set(L, L->gt, &key) = *(L->top - 1); } } else { luaD_checkstack(L, 3); *(L->top+2) = *(L->top-1); /* new value */ *(L->top+1) = *oldvalue; ttype(L->top) = LUA_TSTRING; tsvalue(L->top) = s; clvalue(L->top-1) = tm; ttype(L->top-1) = LUA_TFUNCTION; L->top += 3; luaD_call(L, L->top - 4, 0); } }
/* ** Function to index a table. ** Receives the table at `t' and the key at top. */ const TObject *luaV_gettable (lua_State *L, StkId t) { Closure *tm; int tg; if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ luaT_gettm(L, tg, TM_GETTABLE) == NULL)) { /* or no TM? */ /* do a primitive get */ const TObject *h = luaH_get(L, hvalue(t), L->top-1); /* result is no nil or there is no `index' tag method? */ if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(L, tg, TM_INDEX)) == NULL)) return h; /* return result */ /* else call `index' tag method */ } else { /* try a `gettable' tag method */ tm = luaT_gettmbyObj(L, t, TM_GETTABLE); } if (tm != NULL) { /* is there a tag method? */ luaD_checkstack(L, 2); *(L->top+1) = *(L->top-1); /* key */ *L->top = *t; /* table */ clvalue(L->top-1) = tm; /* tag method */ ttype(L->top-1) = LUA_TFUNCTION; L->top += 2; luaD_call(L, L->top - 3, 1); return L->top - 1; /* call result */ } else { /* no tag method */ luaG_typeerror(L, t, "index"); return NULL; /* to avoid warnings */ } }
const TObject *luaV_getglobal (lua_State *L, TString *s) { const TObject *value = luaH_getstr(L->gt, s); Closure *tm = luaT_gettmbyObj(L, value, TM_GETGLOBAL); if (tm == NULL) /* is there a tag method? */ return value; /* default behavior */ else { /* tag method */ luaD_checkstack(L, 3); clvalue(L->top) = tm; ttype(L->top) = LUA_TFUNCTION; tsvalue(L->top+1) = s; /* global name */ ttype(L->top+1) = LUA_TSTRING; *(L->top+2) = *value; L->top += 3; luaD_call(L, L->top - 3, 1); return L->top - 1; } }
/* ** Call a function (C or Lua). The function to be called is at *func. ** The arguments are on the stack, right after the function. ** When returns, the results are on the stack, starting at the original ** function position. ** The number of results is nResults, unless nResults=LUA_MULTRET. */ void luaD_call (lua_State *L, StkId func, int nResults) { lua_Hook callhook; StkId firstResult; CallInfo ci; Closure *cl; if (ttype(func) != LUA_TFUNCTION) { /* `func' is not a function; check the `function' tag method */ Closure *tm = luaT_gettmbyObj(L, func, TM_FUNCTION); if (tm == NULL) luaG_typeerror(L, func, "call"); luaD_openstack(L, func); clvalue(func) = tm; /* tag method is the new function to be called */ ttype(func) = LUA_TFUNCTION; } cl = clvalue(func); ci.func = cl; infovalue(func) = &ci; ttype(func) = LUA_TMARK; callhook = L->callhook; if (callhook) luaD_callHook(L, func, callhook, "call"); firstResult = (cl->isC ? callCclosure(L, cl, func+1) : luaV_execute(L, cl, func+1)); if (callhook) /* same hook that was active at entry */ luaD_callHook(L, func, callhook, "return"); LUA_ASSERT(ttype(func) == LUA_TMARK, "invalid tag"); /* move results to `func' (to erase parameters and function) */ if (nResults == LUA_MULTRET) { while (firstResult < L->top) /* copy all results */ *func++ = *firstResult++; L->top = func; } else { /* copy at most `nResults' */ for (; nResults > 0 && firstResult < L->top; nResults--) *func++ = *firstResult++; L->top = func; for (; nResults > 0; nResults--) { /* if there are not enough results */ ttype(L->top) = LUA_TNIL; /* adjust the stack */ incr_top; /* must check stack space */ } } luaC_checkGC(L); }
/* ** Receives table at `t', key at `key' and value at top. */ void luaV_settable (lua_State *L, StkId t, StkId key) { int tg; if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ luaT_gettm(L, tg, TM_SETTABLE) == NULL)) /* or no TM? */ *luaH_set(L, hvalue(t), key) = *(L->top-1); /* do a primitive set */ else { /* try a `settable' tag method */ Closure *tm = luaT_gettmbyObj(L, t, TM_SETTABLE); if (tm != NULL) { luaD_checkstack(L, 3); *(L->top+2) = *(L->top-1); *(L->top+1) = *key; *(L->top) = *t; clvalue(L->top-1) = tm; ttype(L->top-1) = LUA_TFUNCTION; L->top += 3; luaD_call(L, L->top - 4, 0); /* call `settable' tag method */ } else /* no tag method... */ luaG_typeerror(L, t, "index"); } }