diff options
author | Lua Team <team@lua.org> | 2013-07-06 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 2013-07-06 12:00:00 +0000 |
commit | 87cc247b6b22184fba47184c218a642ea7a49e96 (patch) | |
tree | 299ba8b72b95aa32336b5c810b7133f8efc4fb29 /src/ltm.c | |
parent | dc27609467d2699ac9252e89d632432ac5f798f2 (diff) | |
download | lua-github-5.3.0-work1.tar.gz |
Lua 5.3.0-work15.3.0-work1
Diffstat (limited to 'src/ltm.c')
-rw-r--r-- | src/ltm.c | 74 |
1 files changed, 70 insertions, 4 deletions
@@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.14 2011/06/02 19:31:40 roberto Exp $ +** $Id: ltm.c,v 2.20 2013/05/06 17:19:11 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -12,11 +12,14 @@ #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"; @@ -33,7 +36,7 @@ void luaT_init (lua_State *L) { static const char *const luaT_eventname[] = { /* ORDER TM */ "__index", "__newindex", "__gc", "__mode", "__len", "__eq", - "__add", "__sub", "__mul", "__div", "__mod", + "__add", "__sub", "__mul", "__div", "__idiv", "__mod", "__pow", "__unm", "__lt", "__le", "__concat", "__call" }; @@ -62,7 +65,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { Table *mt; - switch (ttypenv(o)) { + switch (ttnov(o)) { case LUA_TTABLE: mt = hvalue(o)->metatable; break; @@ -70,8 +73,71 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { mt = uvalue(o)->metatable; break; default: - mt = G(L)->mt[ttypenv(o)]; + mt = G(L)->mt[ttnov(o)]; } return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); } + +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); + setobj2s(L, L->top++, f); /* push function */ + setobj2s(L, L->top++, p1); /* 1st argument */ + setobj2s(L, L->top++, p2); /* 2nd argument */ + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + /* metamethod may yield only when called from Lua code */ + luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); + 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)) { + if (event == TM_CONCAT) + luaG_concaterror(L, p1, p2); + else if (event == TM_IDIV && ttisnumber(p1) && ttisnumber(p2)) + luaG_tointerror(L, p1, p2); + else + luaG_aritherror(L, p1, p2); + } +} + + +const TValue *luaT_getequalTM (lua_State *L, Table *mt1, Table *mt2) { + const TValue *tm1 = fasttm(L, mt1, TM_EQ); + const TValue *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, TM_EQ); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +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); +} + |