123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- ** $Id: ltm.c,v 2.38 2016/12/22 13:08:50 roberto Exp $
- ** 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",
- "proto" /* this last case is 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, TValue *p3, int hasres) {
- ptrdiff_t result = savestack(L, 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 */
- L->top += 3;
- if (!hasres) /* no result? 'p3' is third argument */
- setobj2s(L, L->top++, p3); /* 3rd argument */
- /* metamethod may yield only when called from Lua code */
- if (isLua(L->ci))
- luaD_call(L, func, hasres);
- else
- luaD_callnoyield(L, func, hasres);
- if (hasres) { /* if has result, move it to its place */
- p3 = restorestack(L, result);
- setobjs2s(L, p3, --L->top);
- }
- }
- int luaT_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_callTM(L, tm, p1, p2, res, 1);
- return 1;
- }
- void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event) {
- if (!luaT_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 (!luaT_callbinTM(L, p1, p2, L->top, event))
- return -1; /* no metamethod */
- else
- return !l_isfalse(L->top);
- }
|