123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /*
- ** $Id: ltm.c,v 2.41 2017/05/13 12:57:20 roberto Exp roberto $
- ** Tag methods
- ** See Copyright Notice in lua.h
- */
- #define ltm_c
- #define LUA_CORE
- #include "lprefix.h"
- #include <string.h>
- #include "lua.h"
- #include "ldebug.h"
- #include "ldo.h"
- #include "lobject.h"
- #include "lstate.h"
- #include "lstring.h"
- #include "ltable.h"
- #include "ltm.h"
- #include "lvm.h"
- static const char udatatypename[] = "userdata";
- LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
- "no value",
- "nil", "boolean", udatatypename, "number",
- "string", "table", "function", udatatypename, "thread",
- "upvalue", "proto" /* these last cases are used for tests only */
- };
- void luaT_init (lua_State *L) {
- static const char *const luaT_eventname[] = { /* ORDER TM */
- "__index", "__newindex",
- "__gc", "__mode", "__len", "__eq",
- "__add", "__sub", "__mul", "__mod", "__pow",
- "__div", "__idiv",
- "__band", "__bor", "__bxor", "__shl", "__shr",
- "__unm", "__bnot", "__lt", "__le",
- "__concat", "__call"
- };
- int i;
- for (i=0; i<TM_N; i++) {
- G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
- luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */
- }
- }
- /*
- ** function to be used with macro "fasttm": optimized for absence of
- ** tag methods
- */
- const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
- const TValue *tm = luaH_getshortstr(events, ename);
- lua_assert(event <= TM_EQ);
- if (ttisnil(tm)) { /* no tag method? */
- events->flags |= cast_byte(1u<<event); /* cache this fact */
- return NULL;
- }
- else return tm;
- }
- const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
- Table *mt;
- switch (ttnov(o)) {
- case LUA_TTABLE:
- mt = hvalue(o)->metatable;
- break;
- case LUA_TUSERDATA:
- mt = uvalue(o)->metatable;
- break;
- default:
- mt = G(L)->mt[ttnov(o)];
- }
- return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);
- }
- /*
- ** Return the name of the type of an object. For tables and userdata
- ** with metatable, use their '__name' metafield, if present.
- */
- const char *luaT_objtypename (lua_State *L, const TValue *o) {
- Table *mt;
- if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
- (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
- const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
- if (ttisstring(name)) /* is '__name' a string? */
- return getstr(tsvalue(name)); /* use it as type name */
- }
- return ttypename(ttnov(o)); /* else use standard type name */
- }
- void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
- const TValue *p2, const TValue *p3) {
- StkId func = L->top;
- setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
- setobj2s(L, func + 1, p1); /* 1st argument */
- setobj2s(L, func + 2, p2); /* 2nd argument */
- setobj2s(L, func + 3, p3); /* 3rd argument */
- L->top += 4;
- /* metamethod may yield only when called from Lua code */
- if (isLua(L->ci))
- luaD_call(L, func, 0);
- else
- luaD_callnoyield(L, func, 0);
- }
- void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
- const TValue *p2, StkId res) {
- ptrdiff_t result = savestack(L, res);
- StkId func = L->top;
- setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
- setobj2s(L, func + 1, p1); /* 1st argument */
- setobj2s(L, func + 2, p2); /* 2nd argument */
- L->top += 3;
- /* metamethod may yield only when called from Lua code */
- if (isLua(L->ci))
- luaD_call(L, func, 1);
- else
- luaD_callnoyield(L, func, 1);
- res = restorestack(L, result);
- setobjs2s(L, res, --L->top); /* more result to its place */
- }
- static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event) {
- const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
- if (ttisnil(tm))
- tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
- if (ttisnil(tm)) return 0;
- luaT_callTMres(L, tm, p1, p2, res);
- return 1;
- }
- void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event) {
- if (!callbinTM(L, p1, p2, res, event)) {
- switch (event) {
- case TM_CONCAT:
- luaG_concaterror(L, p1, p2);
- /* call never returns, but to avoid warnings: *//* FALLTHROUGH */
- case TM_BAND: case TM_BOR: case TM_BXOR:
- case TM_SHL: case TM_SHR: case TM_BNOT: {
- lua_Number dummy;
- if (tonumber(p1, &dummy) && tonumber(p2, &dummy))
- luaG_tointerror(L, p1, p2);
- else
- luaG_opinterror(L, p1, p2, "perform bitwise operation on");
- }
- /* calls never return, but to avoid warnings: *//* FALLTHROUGH */
- default:
- luaG_opinterror(L, p1, p2, "perform arithmetic on");
- }
- }
- }
- int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
- TMS event) {
- if (!callbinTM(L, p1, p2, L->top, event))
- return -1; /* no metamethod */
- else
- return !l_isfalse(s2v(L->top));
- }
- void luaT_adjustvarargs (lua_State *L, Proto *p, int actual) {
- int i;
- Table *vtab;
- TValue nname;
- int nfixparams = p->numparams - 1; /* number of fixed parameters */
- actual -= nfixparams; /* number of extra arguments */
- vtab = luaH_new(L); /* create vararg table */
- sethvalue2s(L, L->top, vtab); /* anchor it for resizing */
- L->top++; /* space ensured by caller */
- luaH_resize(L, vtab, actual, 1);
- for (i = 0; i < actual; i++) /* put extra arguments into vararg table */
- setobj2n(L, &vtab->array[i], s2v(L->top - actual + i - 1));
- setsvalue(L, &nname, luaS_newliteral(L, "n")); /* get field 'n' */
- setivalue(luaH_set(L, vtab, &nname), actual); /* store counter there */
- L->top -= actual; /* remove extra elements from the stack */
- sethvalue2s(L, L->top - 1, vtab); /* move table to new top */
- }
- void luaT_getvarargs (lua_State *L, TValue *t, StkId where, int wanted) {
- if (!ttistable(t))
- luaG_runerror(L, "'vararg' parameter is not a table");
- else {
- int i;
- Table *h = hvalue(t);
- if (wanted < 0) { /* get all? */
- const TValue *ns = luaH_getstr(h, luaS_newliteral(L, "n"));
- int n = (ttisinteger(ns)) ? ivalue(ns) : 0;
- wanted = n;
- checkstackp(L, n, where);
- L->top = where + n;
- }
- for (i = 0; i < wanted; i++) /* get what is available */
- setobj2s(L, where + i, luaH_getint(h, i + 1));
- return;
- }
- }
|