xref: /freebsd-src/contrib/lua/src/ltm.c (revision 8e3e3a7ae841ccf6f6ac30a2eeab85df5d7f04bc)
1*8e3e3a7aSWarner Losh /*
2*8e3e3a7aSWarner Losh ** $Id: ltm.c,v 2.38 2016/12/22 13:08:50 roberto Exp $
3*8e3e3a7aSWarner Losh ** Tag methods
4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h
5*8e3e3a7aSWarner Losh */
6*8e3e3a7aSWarner Losh 
7*8e3e3a7aSWarner Losh #define ltm_c
8*8e3e3a7aSWarner Losh #define LUA_CORE
9*8e3e3a7aSWarner Losh 
10*8e3e3a7aSWarner Losh #include "lprefix.h"
11*8e3e3a7aSWarner Losh 
12*8e3e3a7aSWarner Losh 
13*8e3e3a7aSWarner Losh #include <string.h>
14*8e3e3a7aSWarner Losh 
15*8e3e3a7aSWarner Losh #include "lua.h"
16*8e3e3a7aSWarner Losh 
17*8e3e3a7aSWarner Losh #include "ldebug.h"
18*8e3e3a7aSWarner Losh #include "ldo.h"
19*8e3e3a7aSWarner Losh #include "lobject.h"
20*8e3e3a7aSWarner Losh #include "lstate.h"
21*8e3e3a7aSWarner Losh #include "lstring.h"
22*8e3e3a7aSWarner Losh #include "ltable.h"
23*8e3e3a7aSWarner Losh #include "ltm.h"
24*8e3e3a7aSWarner Losh #include "lvm.h"
25*8e3e3a7aSWarner Losh 
26*8e3e3a7aSWarner Losh 
27*8e3e3a7aSWarner Losh static const char udatatypename[] = "userdata";
28*8e3e3a7aSWarner Losh 
29*8e3e3a7aSWarner Losh LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
30*8e3e3a7aSWarner Losh   "no value",
31*8e3e3a7aSWarner Losh   "nil", "boolean", udatatypename, "number",
32*8e3e3a7aSWarner Losh   "string", "table", "function", udatatypename, "thread",
33*8e3e3a7aSWarner Losh   "proto" /* this last case is used for tests only */
34*8e3e3a7aSWarner Losh };
35*8e3e3a7aSWarner Losh 
36*8e3e3a7aSWarner Losh 
37*8e3e3a7aSWarner Losh void luaT_init (lua_State *L) {
38*8e3e3a7aSWarner Losh   static const char *const luaT_eventname[] = {  /* ORDER TM */
39*8e3e3a7aSWarner Losh     "__index", "__newindex",
40*8e3e3a7aSWarner Losh     "__gc", "__mode", "__len", "__eq",
41*8e3e3a7aSWarner Losh     "__add", "__sub", "__mul", "__mod", "__pow",
42*8e3e3a7aSWarner Losh     "__div", "__idiv",
43*8e3e3a7aSWarner Losh     "__band", "__bor", "__bxor", "__shl", "__shr",
44*8e3e3a7aSWarner Losh     "__unm", "__bnot", "__lt", "__le",
45*8e3e3a7aSWarner Losh     "__concat", "__call"
46*8e3e3a7aSWarner Losh   };
47*8e3e3a7aSWarner Losh   int i;
48*8e3e3a7aSWarner Losh   for (i=0; i<TM_N; i++) {
49*8e3e3a7aSWarner Losh     G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
50*8e3e3a7aSWarner Losh     luaC_fix(L, obj2gco(G(L)->tmname[i]));  /* never collect these names */
51*8e3e3a7aSWarner Losh   }
52*8e3e3a7aSWarner Losh }
53*8e3e3a7aSWarner Losh 
54*8e3e3a7aSWarner Losh 
55*8e3e3a7aSWarner Losh /*
56*8e3e3a7aSWarner Losh ** function to be used with macro "fasttm": optimized for absence of
57*8e3e3a7aSWarner Losh ** tag methods
58*8e3e3a7aSWarner Losh */
59*8e3e3a7aSWarner Losh const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
60*8e3e3a7aSWarner Losh   const TValue *tm = luaH_getshortstr(events, ename);
61*8e3e3a7aSWarner Losh   lua_assert(event <= TM_EQ);
62*8e3e3a7aSWarner Losh   if (ttisnil(tm)) {  /* no tag method? */
63*8e3e3a7aSWarner Losh     events->flags |= cast_byte(1u<<event);  /* cache this fact */
64*8e3e3a7aSWarner Losh     return NULL;
65*8e3e3a7aSWarner Losh   }
66*8e3e3a7aSWarner Losh   else return tm;
67*8e3e3a7aSWarner Losh }
68*8e3e3a7aSWarner Losh 
69*8e3e3a7aSWarner Losh 
70*8e3e3a7aSWarner Losh const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
71*8e3e3a7aSWarner Losh   Table *mt;
72*8e3e3a7aSWarner Losh   switch (ttnov(o)) {
73*8e3e3a7aSWarner Losh     case LUA_TTABLE:
74*8e3e3a7aSWarner Losh       mt = hvalue(o)->metatable;
75*8e3e3a7aSWarner Losh       break;
76*8e3e3a7aSWarner Losh     case LUA_TUSERDATA:
77*8e3e3a7aSWarner Losh       mt = uvalue(o)->metatable;
78*8e3e3a7aSWarner Losh       break;
79*8e3e3a7aSWarner Losh     default:
80*8e3e3a7aSWarner Losh       mt = G(L)->mt[ttnov(o)];
81*8e3e3a7aSWarner Losh   }
82*8e3e3a7aSWarner Losh   return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);
83*8e3e3a7aSWarner Losh }
84*8e3e3a7aSWarner Losh 
85*8e3e3a7aSWarner Losh 
86*8e3e3a7aSWarner Losh /*
87*8e3e3a7aSWarner Losh ** Return the name of the type of an object. For tables and userdata
88*8e3e3a7aSWarner Losh ** with metatable, use their '__name' metafield, if present.
89*8e3e3a7aSWarner Losh */
90*8e3e3a7aSWarner Losh const char *luaT_objtypename (lua_State *L, const TValue *o) {
91*8e3e3a7aSWarner Losh   Table *mt;
92*8e3e3a7aSWarner Losh   if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
93*8e3e3a7aSWarner Losh       (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
94*8e3e3a7aSWarner Losh     const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
95*8e3e3a7aSWarner Losh     if (ttisstring(name))  /* is '__name' a string? */
96*8e3e3a7aSWarner Losh       return getstr(tsvalue(name));  /* use it as type name */
97*8e3e3a7aSWarner Losh   }
98*8e3e3a7aSWarner Losh   return ttypename(ttnov(o));  /* else use standard type name */
99*8e3e3a7aSWarner Losh }
100*8e3e3a7aSWarner Losh 
101*8e3e3a7aSWarner Losh 
102*8e3e3a7aSWarner Losh void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
103*8e3e3a7aSWarner Losh                   const TValue *p2, TValue *p3, int hasres) {
104*8e3e3a7aSWarner Losh   ptrdiff_t result = savestack(L, p3);
105*8e3e3a7aSWarner Losh   StkId func = L->top;
106*8e3e3a7aSWarner Losh   setobj2s(L, func, f);  /* push function (assume EXTRA_STACK) */
107*8e3e3a7aSWarner Losh   setobj2s(L, func + 1, p1);  /* 1st argument */
108*8e3e3a7aSWarner Losh   setobj2s(L, func + 2, p2);  /* 2nd argument */
109*8e3e3a7aSWarner Losh   L->top += 3;
110*8e3e3a7aSWarner Losh   if (!hasres)  /* no result? 'p3' is third argument */
111*8e3e3a7aSWarner Losh     setobj2s(L, L->top++, p3);  /* 3rd argument */
112*8e3e3a7aSWarner Losh   /* metamethod may yield only when called from Lua code */
113*8e3e3a7aSWarner Losh   if (isLua(L->ci))
114*8e3e3a7aSWarner Losh     luaD_call(L, func, hasres);
115*8e3e3a7aSWarner Losh   else
116*8e3e3a7aSWarner Losh     luaD_callnoyield(L, func, hasres);
117*8e3e3a7aSWarner Losh   if (hasres) {  /* if has result, move it to its place */
118*8e3e3a7aSWarner Losh     p3 = restorestack(L, result);
119*8e3e3a7aSWarner Losh     setobjs2s(L, p3, --L->top);
120*8e3e3a7aSWarner Losh   }
121*8e3e3a7aSWarner Losh }
122*8e3e3a7aSWarner Losh 
123*8e3e3a7aSWarner Losh 
124*8e3e3a7aSWarner Losh int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
125*8e3e3a7aSWarner Losh                     StkId res, TMS event) {
126*8e3e3a7aSWarner Losh   const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
127*8e3e3a7aSWarner Losh   if (ttisnil(tm))
128*8e3e3a7aSWarner Losh     tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
129*8e3e3a7aSWarner Losh   if (ttisnil(tm)) return 0;
130*8e3e3a7aSWarner Losh   luaT_callTM(L, tm, p1, p2, res, 1);
131*8e3e3a7aSWarner Losh   return 1;
132*8e3e3a7aSWarner Losh }
133*8e3e3a7aSWarner Losh 
134*8e3e3a7aSWarner Losh 
135*8e3e3a7aSWarner Losh void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
136*8e3e3a7aSWarner Losh                     StkId res, TMS event) {
137*8e3e3a7aSWarner Losh   if (!luaT_callbinTM(L, p1, p2, res, event)) {
138*8e3e3a7aSWarner Losh     switch (event) {
139*8e3e3a7aSWarner Losh       case TM_CONCAT:
140*8e3e3a7aSWarner Losh         luaG_concaterror(L, p1, p2);
141*8e3e3a7aSWarner Losh       /* call never returns, but to avoid warnings: *//* FALLTHROUGH */
142*8e3e3a7aSWarner Losh       case TM_BAND: case TM_BOR: case TM_BXOR:
143*8e3e3a7aSWarner Losh       case TM_SHL: case TM_SHR: case TM_BNOT: {
144*8e3e3a7aSWarner Losh         lua_Number dummy;
145*8e3e3a7aSWarner Losh         if (tonumber(p1, &dummy) && tonumber(p2, &dummy))
146*8e3e3a7aSWarner Losh           luaG_tointerror(L, p1, p2);
147*8e3e3a7aSWarner Losh         else
148*8e3e3a7aSWarner Losh           luaG_opinterror(L, p1, p2, "perform bitwise operation on");
149*8e3e3a7aSWarner Losh       }
150*8e3e3a7aSWarner Losh       /* calls never return, but to avoid warnings: *//* FALLTHROUGH */
151*8e3e3a7aSWarner Losh       default:
152*8e3e3a7aSWarner Losh         luaG_opinterror(L, p1, p2, "perform arithmetic on");
153*8e3e3a7aSWarner Losh     }
154*8e3e3a7aSWarner Losh   }
155*8e3e3a7aSWarner Losh }
156*8e3e3a7aSWarner Losh 
157*8e3e3a7aSWarner Losh 
158*8e3e3a7aSWarner Losh int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
159*8e3e3a7aSWarner Losh                       TMS event) {
160*8e3e3a7aSWarner Losh   if (!luaT_callbinTM(L, p1, p2, L->top, event))
161*8e3e3a7aSWarner Losh     return -1;  /* no metamethod */
162*8e3e3a7aSWarner Losh   else
163*8e3e3a7aSWarner Losh     return !l_isfalse(L->top);
164*8e3e3a7aSWarner Losh }
165*8e3e3a7aSWarner Losh 
166