ltm.c revision 1.11
1/*	$NetBSD: ltm.c,v 1.11 2023/06/08 21:12:08 nikita Exp $	*/
2
3/*
4** Id: ltm.c
5** Tag methods
6** See Copyright Notice in lua.h
7*/
8
9#define ltm_c
10#define LUA_CORE
11
12#include "lprefix.h"
13
14
15#ifndef _KERNEL
16#include <string.h>
17#endif /* _KERNEL */
18
19#include "lua.h"
20
21#include "ldebug.h"
22#include "ldo.h"
23#include "lgc.h"
24#include "lobject.h"
25#include "lstate.h"
26#include "lstring.h"
27#include "ltable.h"
28#include "ltm.h"
29#include "lvm.h"
30
31
32static const char udatatypename[] = "userdata";
33
34LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = {
35  "no value",
36  "nil", "boolean", udatatypename, "number",
37  "string", "table", "function", udatatypename, "thread",
38  "upvalue", "proto" /* these last cases are used for tests only */
39};
40
41
42void luaT_init (lua_State *L) {
43  static const char *const luaT_eventname[] = {  /* ORDER TM */
44    "__index", "__newindex",
45    "__gc", "__mode", "__len", "__eq",
46#ifndef _KERNEL
47    "__add", "__sub", "__mul", "__mod", "__pow",
48    "__div", "__idiv",
49#else /* _KERNEL */
50    "__add", "__sub", "__mul", "__mod",
51    "__idiv",
52#endif /* _KERNEL */
53    "__band", "__bor", "__bxor", "__shl", "__shr",
54    "__unm", "__bnot", "__lt", "__le",
55    "__concat", "__call", "__close"
56  };
57  int i;
58  for (i=0; i<TM_N; i++) {
59    G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
60    luaC_fix(L, obj2gco(G(L)->tmname[i]));  /* never collect these names */
61  }
62}
63
64
65/*
66** function to be used with macro "fasttm": optimized for absence of
67** tag methods
68*/
69const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
70  const TValue *tm = luaH_getshortstr(events, ename);
71  lua_assert(event <= TM_EQ);
72  if (notm(tm)) {  /* no tag method? */
73    events->flags |= cast_byte(1u<<event);  /* cache this fact */
74    return NULL;
75  }
76  else return tm;
77}
78
79
80const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
81  Table *mt;
82  switch (ttype(o)) {
83    case LUA_TTABLE:
84      mt = hvalue(o)->metatable;
85      break;
86    case LUA_TUSERDATA:
87      mt = uvalue(o)->metatable;
88      break;
89    default:
90      mt = G(L)->mt[ttype(o)];
91  }
92  return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue);
93}
94
95
96/*
97** Return the name of the type of an object. For tables and userdata
98** with metatable, use their '__name' metafield, if present.
99*/
100const char *luaT_objtypename (lua_State *L, const TValue *o) {
101  Table *mt;
102  if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
103      (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
104    const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
105    if (ttisstring(name))  /* is '__name' a string? */
106      return getstr(tsvalue(name));  /* use it as type name */
107  }
108  return ttypename(ttype(o));  /* else use standard type name */
109}
110
111
112void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
113                  const TValue *p2, const TValue *p3) {
114  StkId func = L->top.p;
115  setobj2s(L, func, f);  /* push function (assume EXTRA_STACK) */
116  setobj2s(L, func + 1, p1);  /* 1st argument */
117  setobj2s(L, func + 2, p2);  /* 2nd argument */
118  setobj2s(L, func + 3, p3);  /* 3rd argument */
119  L->top.p = func + 4;
120  /* metamethod may yield only when called from Lua code */
121  if (isLuacode(L->ci))
122    luaD_call(L, func, 0);
123  else
124    luaD_callnoyield(L, func, 0);
125}
126
127
128void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
129                     const TValue *p2, StkId res) {
130  ptrdiff_t result = savestack(L, res);
131  StkId func = L->top.p;
132  setobj2s(L, func, f);  /* push function (assume EXTRA_STACK) */
133  setobj2s(L, func + 1, p1);  /* 1st argument */
134  setobj2s(L, func + 2, p2);  /* 2nd argument */
135  L->top.p += 3;
136  /* metamethod may yield only when called from Lua code */
137  if (isLuacode(L->ci))
138    luaD_call(L, func, 1);
139  else
140    luaD_callnoyield(L, func, 1);
141  res = restorestack(L, result);
142  setobjs2s(L, res, --L->top.p);  /* move result to its place */
143}
144
145
146static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
147                      StkId res, TMS event) {
148  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
149  if (notm(tm))
150    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
151  if (notm(tm)) return 0;
152  luaT_callTMres(L, tm, p1, p2, res);
153  return 1;
154}
155
156
157void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
158                    StkId res, TMS event) {
159  if (l_unlikely(!callbinTM(L, p1, p2, res, event))) {
160    switch (event) {
161      case TM_BAND: case TM_BOR: case TM_BXOR:
162      case TM_SHL: case TM_SHR: case TM_BNOT: {
163        if (ttisnumber(p1) && ttisnumber(p2))
164          luaG_tointerror(L, p1, p2);
165        else
166          luaG_opinterror(L, p1, p2, "perform bitwise operation on");
167      }
168      /* calls never return, but to avoid warnings: *//* FALLTHROUGH */
169      default:
170        luaG_opinterror(L, p1, p2, "perform arithmetic on");
171    }
172  }
173}
174
175
176void luaT_tryconcatTM (lua_State *L) {
177  StkId top = L->top.p;
178  if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2,
179                               TM_CONCAT)))
180    luaG_concaterror(L, s2v(top - 2), s2v(top - 1));
181}
182
183
184void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2,
185                                       int flip, StkId res, TMS event) {
186  if (flip)
187    luaT_trybinTM(L, p2, p1, res, event);
188  else
189    luaT_trybinTM(L, p1, p2, res, event);
190}
191
192
193void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
194                                   int flip, StkId res, TMS event) {
195  TValue aux;
196  setivalue(&aux, i2);
197  luaT_trybinassocTM(L, p1, &aux, flip, res, event);
198}
199
200
201/*
202** Calls an order tag method.
203** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old
204** behavior: if there is no '__le', try '__lt', based on l <= r iff
205** !(r < l) (assuming a total order). If the metamethod yields during
206** this substitution, the continuation has to know about it (to negate
207** the result of r<l); bit CIST_LEQ in the call status keeps that
208** information.
209*/
210int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
211                      TMS event) {
212  if (callbinTM(L, p1, p2, L->top.p, event))  /* try original event */
213    return !l_isfalse(s2v(L->top.p));
214#if defined(LUA_COMPAT_LT_LE)
215  else if (event == TM_LE) {
216      /* try '!(p2 < p1)' for '(p1 <= p2)' */
217      L->ci->callstatus |= CIST_LEQ;  /* mark it is doing 'lt' for 'le' */
218      if (callbinTM(L, p2, p1, L->top.p, TM_LT)) {
219        L->ci->callstatus ^= CIST_LEQ;  /* clear mark */
220        return l_isfalse(s2v(L->top.p));
221      }
222      /* else error will remove this 'ci'; no need to clear mark */
223  }
224#endif
225  luaG_ordererror(L, p1, p2);  /* no metamethod found */
226  return 0;  /* to avoid warnings */
227}
228
229
230int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
231                       int flip, int isfloat, TMS event) {
232  TValue aux; const TValue *p2;
233#ifndef _KERNEL
234  if (isfloat) {
235    setfltvalue(&aux, cast_num(v2));
236  }
237  else
238#endif /* _KERNEL */
239    setivalue(&aux, v2);
240  if (flip) {  /* arguments were exchanged? */
241    p2 = p1; p1 = &aux;  /* correct them */
242  }
243  else
244    p2 = &aux;
245  return luaT_callorderTM(L, p1, p2, event);
246}
247
248
249void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci,
250                         const Proto *p) {
251  int i;
252  int actual = cast_int(L->top.p - ci->func.p) - 1;  /* number of arguments */
253  int nextra = actual - nfixparams;  /* number of extra arguments */
254  ci->u.l.nextraargs = nextra;
255  luaD_checkstack(L, p->maxstacksize + 1);
256  /* copy function to the top of the stack */
257  setobjs2s(L, L->top.p++, ci->func.p);
258  /* move fixed parameters to the top of the stack */
259  for (i = 1; i <= nfixparams; i++) {
260    setobjs2s(L, L->top.p++, ci->func.p + i);
261    setnilvalue(s2v(ci->func.p + i));  /* erase original parameter (for GC) */
262  }
263  ci->func.p += actual + 1;
264  ci->top.p += actual + 1;
265  lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p);
266}
267
268
269void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
270  int i;
271  int nextra = ci->u.l.nextraargs;
272  if (wanted < 0) {
273    wanted = nextra;  /* get all extra arguments available */
274    checkstackGCp(L, nextra, where);  /* ensure stack space */
275    L->top.p = where + nextra;  /* next instruction will need top */
276  }
277  for (i = 0; i < wanted && i < nextra; i++)
278    setobjs2s(L, where + i, ci->func.p - nextra + i);
279  for (; i < wanted; i++)   /* complete required results with nil */
280    setnilvalue(s2v(where + i));
281}
282
283