18e3e3a7aSWarner Losh /* 20495ed39SKyle Evans ** $Id: ltm.c $ 38e3e3a7aSWarner Losh ** Tag methods 48e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 58e3e3a7aSWarner Losh */ 68e3e3a7aSWarner Losh 78e3e3a7aSWarner Losh #define ltm_c 88e3e3a7aSWarner Losh #define LUA_CORE 98e3e3a7aSWarner Losh 108e3e3a7aSWarner Losh #include "lprefix.h" 118e3e3a7aSWarner Losh 128e3e3a7aSWarner Losh 138e3e3a7aSWarner Losh #include <string.h> 148e3e3a7aSWarner Losh 158e3e3a7aSWarner Losh #include "lua.h" 168e3e3a7aSWarner Losh 178e3e3a7aSWarner Losh #include "ldebug.h" 188e3e3a7aSWarner Losh #include "ldo.h" 190495ed39SKyle Evans #include "lgc.h" 208e3e3a7aSWarner Losh #include "lobject.h" 218e3e3a7aSWarner Losh #include "lstate.h" 228e3e3a7aSWarner Losh #include "lstring.h" 238e3e3a7aSWarner Losh #include "ltable.h" 248e3e3a7aSWarner Losh #include "ltm.h" 258e3e3a7aSWarner Losh #include "lvm.h" 268e3e3a7aSWarner Losh 278e3e3a7aSWarner Losh 288e3e3a7aSWarner Losh static const char udatatypename[] = "userdata"; 298e3e3a7aSWarner Losh 300495ed39SKyle Evans LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = { 318e3e3a7aSWarner Losh "no value", 328e3e3a7aSWarner Losh "nil", "boolean", udatatypename, "number", 338e3e3a7aSWarner Losh "string", "table", "function", udatatypename, "thread", 340495ed39SKyle Evans "upvalue", "proto" /* these last cases are used for tests only */ 358e3e3a7aSWarner Losh }; 368e3e3a7aSWarner Losh 378e3e3a7aSWarner Losh 388e3e3a7aSWarner Losh void luaT_init (lua_State *L) { 398e3e3a7aSWarner Losh static const char *const luaT_eventname[] = { /* ORDER TM */ 408e3e3a7aSWarner Losh "__index", "__newindex", 418e3e3a7aSWarner Losh "__gc", "__mode", "__len", "__eq", 428e3e3a7aSWarner Losh "__add", "__sub", "__mul", "__mod", "__pow", 438e3e3a7aSWarner Losh "__div", "__idiv", 448e3e3a7aSWarner Losh "__band", "__bor", "__bxor", "__shl", "__shr", 458e3e3a7aSWarner Losh "__unm", "__bnot", "__lt", "__le", 460495ed39SKyle Evans "__concat", "__call", "__close" 478e3e3a7aSWarner Losh }; 488e3e3a7aSWarner Losh int i; 498e3e3a7aSWarner Losh for (i=0; i<TM_N; i++) { 508e3e3a7aSWarner Losh G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]); 518e3e3a7aSWarner Losh luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ 528e3e3a7aSWarner Losh } 538e3e3a7aSWarner Losh } 548e3e3a7aSWarner Losh 558e3e3a7aSWarner Losh 568e3e3a7aSWarner Losh /* 578e3e3a7aSWarner Losh ** function to be used with macro "fasttm": optimized for absence of 588e3e3a7aSWarner Losh ** tag methods 598e3e3a7aSWarner Losh */ 608e3e3a7aSWarner Losh const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { 618e3e3a7aSWarner Losh const TValue *tm = luaH_getshortstr(events, ename); 628e3e3a7aSWarner Losh lua_assert(event <= TM_EQ); 630495ed39SKyle Evans if (notm(tm)) { /* no tag method? */ 648e3e3a7aSWarner Losh events->flags |= cast_byte(1u<<event); /* cache this fact */ 658e3e3a7aSWarner Losh return NULL; 668e3e3a7aSWarner Losh } 678e3e3a7aSWarner Losh else return tm; 688e3e3a7aSWarner Losh } 698e3e3a7aSWarner Losh 708e3e3a7aSWarner Losh 718e3e3a7aSWarner Losh const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { 728e3e3a7aSWarner Losh Table *mt; 730495ed39SKyle Evans switch (ttype(o)) { 748e3e3a7aSWarner Losh case LUA_TTABLE: 758e3e3a7aSWarner Losh mt = hvalue(o)->metatable; 768e3e3a7aSWarner Losh break; 778e3e3a7aSWarner Losh case LUA_TUSERDATA: 788e3e3a7aSWarner Losh mt = uvalue(o)->metatable; 798e3e3a7aSWarner Losh break; 808e3e3a7aSWarner Losh default: 810495ed39SKyle Evans mt = G(L)->mt[ttype(o)]; 828e3e3a7aSWarner Losh } 830495ed39SKyle Evans return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue); 848e3e3a7aSWarner Losh } 858e3e3a7aSWarner Losh 868e3e3a7aSWarner Losh 878e3e3a7aSWarner Losh /* 888e3e3a7aSWarner Losh ** Return the name of the type of an object. For tables and userdata 898e3e3a7aSWarner Losh ** with metatable, use their '__name' metafield, if present. 908e3e3a7aSWarner Losh */ 918e3e3a7aSWarner Losh const char *luaT_objtypename (lua_State *L, const TValue *o) { 928e3e3a7aSWarner Losh Table *mt; 938e3e3a7aSWarner Losh if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || 948e3e3a7aSWarner Losh (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { 958e3e3a7aSWarner Losh const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); 968e3e3a7aSWarner Losh if (ttisstring(name)) /* is '__name' a string? */ 978e3e3a7aSWarner Losh return getstr(tsvalue(name)); /* use it as type name */ 988e3e3a7aSWarner Losh } 990495ed39SKyle Evans return ttypename(ttype(o)); /* else use standard type name */ 1008e3e3a7aSWarner Losh } 1018e3e3a7aSWarner Losh 1028e3e3a7aSWarner Losh 1038e3e3a7aSWarner Losh void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 1040495ed39SKyle Evans const TValue *p2, const TValue *p3) { 1050495ed39SKyle Evans StkId func = L->top; 1060495ed39SKyle Evans setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 1070495ed39SKyle Evans setobj2s(L, func + 1, p1); /* 1st argument */ 1080495ed39SKyle Evans setobj2s(L, func + 2, p2); /* 2nd argument */ 1090495ed39SKyle Evans setobj2s(L, func + 3, p3); /* 3rd argument */ 1100495ed39SKyle Evans L->top = func + 4; 1110495ed39SKyle Evans /* metamethod may yield only when called from Lua code */ 1120495ed39SKyle Evans if (isLuacode(L->ci)) 1130495ed39SKyle Evans luaD_call(L, func, 0); 1140495ed39SKyle Evans else 1150495ed39SKyle Evans luaD_callnoyield(L, func, 0); 1160495ed39SKyle Evans } 1170495ed39SKyle Evans 1180495ed39SKyle Evans 1190495ed39SKyle Evans void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, 1200495ed39SKyle Evans const TValue *p2, StkId res) { 1210495ed39SKyle Evans ptrdiff_t result = savestack(L, res); 1228e3e3a7aSWarner Losh StkId func = L->top; 1238e3e3a7aSWarner Losh setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 1248e3e3a7aSWarner Losh setobj2s(L, func + 1, p1); /* 1st argument */ 1258e3e3a7aSWarner Losh setobj2s(L, func + 2, p2); /* 2nd argument */ 1268e3e3a7aSWarner Losh L->top += 3; 1278e3e3a7aSWarner Losh /* metamethod may yield only when called from Lua code */ 1280495ed39SKyle Evans if (isLuacode(L->ci)) 1290495ed39SKyle Evans luaD_call(L, func, 1); 1308e3e3a7aSWarner Losh else 1310495ed39SKyle Evans luaD_callnoyield(L, func, 1); 1320495ed39SKyle Evans res = restorestack(L, result); 1330495ed39SKyle Evans setobjs2s(L, res, --L->top); /* move result to its place */ 1348e3e3a7aSWarner Losh } 1358e3e3a7aSWarner Losh 1368e3e3a7aSWarner Losh 1370495ed39SKyle Evans static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, 1388e3e3a7aSWarner Losh StkId res, TMS event) { 1398e3e3a7aSWarner Losh const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 1400495ed39SKyle Evans if (notm(tm)) 1418e3e3a7aSWarner Losh tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 1420495ed39SKyle Evans if (notm(tm)) return 0; 1430495ed39SKyle Evans luaT_callTMres(L, tm, p1, p2, res); 1448e3e3a7aSWarner Losh return 1; 1458e3e3a7aSWarner Losh } 1468e3e3a7aSWarner Losh 1478e3e3a7aSWarner Losh 1488e3e3a7aSWarner Losh void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 1498e3e3a7aSWarner Losh StkId res, TMS event) { 150*8c784bb8SWarner Losh if (l_unlikely(!callbinTM(L, p1, p2, res, event))) { 1518e3e3a7aSWarner Losh switch (event) { 1528e3e3a7aSWarner Losh case TM_BAND: case TM_BOR: case TM_BXOR: 1538e3e3a7aSWarner Losh case TM_SHL: case TM_SHR: case TM_BNOT: { 1540495ed39SKyle Evans if (ttisnumber(p1) && ttisnumber(p2)) 1558e3e3a7aSWarner Losh luaG_tointerror(L, p1, p2); 1568e3e3a7aSWarner Losh else 1578e3e3a7aSWarner Losh luaG_opinterror(L, p1, p2, "perform bitwise operation on"); 1588e3e3a7aSWarner Losh } 1598e3e3a7aSWarner Losh /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ 1608e3e3a7aSWarner Losh default: 1618e3e3a7aSWarner Losh luaG_opinterror(L, p1, p2, "perform arithmetic on"); 1628e3e3a7aSWarner Losh } 1638e3e3a7aSWarner Losh } 1648e3e3a7aSWarner Losh } 1658e3e3a7aSWarner Losh 1668e3e3a7aSWarner Losh 1670495ed39SKyle Evans void luaT_tryconcatTM (lua_State *L) { 1680495ed39SKyle Evans StkId top = L->top; 169*8c784bb8SWarner Losh if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, 170*8c784bb8SWarner Losh TM_CONCAT))) 1710495ed39SKyle Evans luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); 1720495ed39SKyle Evans } 1730495ed39SKyle Evans 1740495ed39SKyle Evans 1750495ed39SKyle Evans void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, 1760495ed39SKyle Evans int flip, StkId res, TMS event) { 1770495ed39SKyle Evans if (flip) 1780495ed39SKyle Evans luaT_trybinTM(L, p2, p1, res, event); 1790495ed39SKyle Evans else 1800495ed39SKyle Evans luaT_trybinTM(L, p1, p2, res, event); 1810495ed39SKyle Evans } 1820495ed39SKyle Evans 1830495ed39SKyle Evans 1840495ed39SKyle Evans void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, 1850495ed39SKyle Evans int flip, StkId res, TMS event) { 1860495ed39SKyle Evans TValue aux; 1870495ed39SKyle Evans setivalue(&aux, i2); 1880495ed39SKyle Evans luaT_trybinassocTM(L, p1, &aux, flip, res, event); 1890495ed39SKyle Evans } 1900495ed39SKyle Evans 1910495ed39SKyle Evans 1920495ed39SKyle Evans /* 1930495ed39SKyle Evans ** Calls an order tag method. 1940495ed39SKyle Evans ** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old 1950495ed39SKyle Evans ** behavior: if there is no '__le', try '__lt', based on l <= r iff 1960495ed39SKyle Evans ** !(r < l) (assuming a total order). If the metamethod yields during 1970495ed39SKyle Evans ** this substitution, the continuation has to know about it (to negate 1980495ed39SKyle Evans ** the result of r<l); bit CIST_LEQ in the call status keeps that 1990495ed39SKyle Evans ** information. 2000495ed39SKyle Evans */ 2018e3e3a7aSWarner Losh int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, 2028e3e3a7aSWarner Losh TMS event) { 2030495ed39SKyle Evans if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ 2040495ed39SKyle Evans return !l_isfalse(s2v(L->top)); 2050495ed39SKyle Evans #if defined(LUA_COMPAT_LT_LE) 2060495ed39SKyle Evans else if (event == TM_LE) { 2070495ed39SKyle Evans /* try '!(p2 < p1)' for '(p1 <= p2)' */ 2080495ed39SKyle Evans L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ 2090495ed39SKyle Evans if (callbinTM(L, p2, p1, L->top, TM_LT)) { 2100495ed39SKyle Evans L->ci->callstatus ^= CIST_LEQ; /* clear mark */ 2110495ed39SKyle Evans return l_isfalse(s2v(L->top)); 2120495ed39SKyle Evans } 2130495ed39SKyle Evans /* else error will remove this 'ci'; no need to clear mark */ 2140495ed39SKyle Evans } 2150495ed39SKyle Evans #endif 2160495ed39SKyle Evans luaG_ordererror(L, p1, p2); /* no metamethod found */ 2170495ed39SKyle Evans return 0; /* to avoid warnings */ 2180495ed39SKyle Evans } 2190495ed39SKyle Evans 2200495ed39SKyle Evans 2210495ed39SKyle Evans int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, 2220495ed39SKyle Evans int flip, int isfloat, TMS event) { 2230495ed39SKyle Evans TValue aux; const TValue *p2; 2240495ed39SKyle Evans if (isfloat) { 2250495ed39SKyle Evans setfltvalue(&aux, cast_num(v2)); 2260495ed39SKyle Evans } 2278e3e3a7aSWarner Losh else 2280495ed39SKyle Evans setivalue(&aux, v2); 2290495ed39SKyle Evans if (flip) { /* arguments were exchanged? */ 2300495ed39SKyle Evans p2 = p1; p1 = &aux; /* correct them */ 2310495ed39SKyle Evans } 2320495ed39SKyle Evans else 2330495ed39SKyle Evans p2 = &aux; 2340495ed39SKyle Evans return luaT_callorderTM(L, p1, p2, event); 2350495ed39SKyle Evans } 2360495ed39SKyle Evans 2370495ed39SKyle Evans 2380495ed39SKyle Evans void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, 2390495ed39SKyle Evans const Proto *p) { 2400495ed39SKyle Evans int i; 2410495ed39SKyle Evans int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ 2420495ed39SKyle Evans int nextra = actual - nfixparams; /* number of extra arguments */ 2430495ed39SKyle Evans ci->u.l.nextraargs = nextra; 2440495ed39SKyle Evans luaD_checkstack(L, p->maxstacksize + 1); 2450495ed39SKyle Evans /* copy function to the top of the stack */ 2460495ed39SKyle Evans setobjs2s(L, L->top++, ci->func); 2470495ed39SKyle Evans /* move fixed parameters to the top of the stack */ 2480495ed39SKyle Evans for (i = 1; i <= nfixparams; i++) { 2490495ed39SKyle Evans setobjs2s(L, L->top++, ci->func + i); 2500495ed39SKyle Evans setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */ 2510495ed39SKyle Evans } 2520495ed39SKyle Evans ci->func += actual + 1; 2530495ed39SKyle Evans ci->top += actual + 1; 2540495ed39SKyle Evans lua_assert(L->top <= ci->top && ci->top <= L->stack_last); 2550495ed39SKyle Evans } 2560495ed39SKyle Evans 2570495ed39SKyle Evans 2580495ed39SKyle Evans void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { 2590495ed39SKyle Evans int i; 2600495ed39SKyle Evans int nextra = ci->u.l.nextraargs; 2610495ed39SKyle Evans if (wanted < 0) { 2620495ed39SKyle Evans wanted = nextra; /* get all extra arguments available */ 2630495ed39SKyle Evans checkstackGCp(L, nextra, where); /* ensure stack space */ 2640495ed39SKyle Evans L->top = where + nextra; /* next instruction will need top */ 2650495ed39SKyle Evans } 2660495ed39SKyle Evans for (i = 0; i < wanted && i < nextra; i++) 2670495ed39SKyle Evans setobjs2s(L, where + i, ci->func - nextra + i); 2680495ed39SKyle Evans for (; i < wanted; i++) /* complete required results with nil */ 2690495ed39SKyle Evans setnilvalue(s2v(where + i)); 2708e3e3a7aSWarner Losh } 2718e3e3a7aSWarner Losh 272