summaryrefslogtreecommitdiff
path: root/src/ltm.c
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2013-07-06 12:00:00 +0000
committerrepogen <>2013-07-06 12:00:00 +0000
commit87cc247b6b22184fba47184c218a642ea7a49e96 (patch)
tree299ba8b72b95aa32336b5c810b7133f8efc4fb29 /src/ltm.c
parentdc27609467d2699ac9252e89d632432ac5f798f2 (diff)
downloadlua-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.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/src/ltm.c b/src/ltm.c
index e70006dd..3d1126a1 100644
--- a/src/ltm.c
+++ b/src/ltm.c
@@ -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);
+}
+