Skip to content
Snippets Groups Projects
Commit 69e02409 authored by Roberto Ierusalimschy's avatar Roberto Ierusalimschy Committed by James R.
Browse files

tables and strings respect __len metamethod

parent e94bccc5
No related branches found
No related tags found
No related merge requests found
...@@ -31,9 +31,9 @@ void luaT_init (lua_State *L) { ...@@ -31,9 +31,9 @@ void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */ static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex", "__index", "__newindex",
"__usedindex", "__usedindex",
"__gc", "__mode", "__eq", "__gc", "__mode", "__len", "__eq",
"__add", "__sub", "__mul", "__div", "__mod", "__add", "__sub", "__mul", "__div", "__mod",
"__pow", "__unm", "__len", "__lt", "__le", "__pow", "__unm", "__lt", "__le",
"__concat", "__call" "__concat", "__call"
,"__strhook" ,"__strhook"
,"__and", "__or", "__xor", "__shl", "__shr", "__not" ,"__and", "__or", "__xor", "__shl", "__shr", "__not"
......
...@@ -21,6 +21,7 @@ typedef enum { ...@@ -21,6 +21,7 @@ typedef enum {
TM_USEDINDEX, TM_USEDINDEX,
TM_GC, TM_GC,
TM_MODE, TM_MODE,
TM_LEN,
TM_EQ, /* last tag method with `fast' access */ TM_EQ, /* last tag method with `fast' access */
TM_ADD, TM_ADD,
TM_SUB, TM_SUB,
...@@ -29,7 +30,6 @@ typedef enum { ...@@ -29,7 +30,6 @@ typedef enum {
TM_MOD, TM_MOD,
TM_POW, TM_POW,
TM_UNM, TM_UNM,
TM_LEN,
TM_LT, TM_LT,
TM_LE, TM_LE,
TM_CONCAT, TM_CONCAT,
......
...@@ -311,6 +311,33 @@ void luaV_concat (lua_State *L, int total, int last) { ...@@ -311,6 +311,33 @@ void luaV_concat (lua_State *L, int total, int last) {
} }
static void objlen (lua_State *L, StkId ra, TValue *rb) {
const TValue *tm;
switch (ttype(rb)) {
case LUA_TTABLE: {
Table *h = hvalue(rb);
tm = fasttm(L, h->metatable, TM_LEN);
if (tm) break; /* metamethod? break switch to call it */
setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */
return;
}
case LUA_TSTRING: {
tm = fasttm(L, G(L)->mt[LUA_TSTRING], TM_LEN);
if (tm) break; /* metamethod? break switch to call it */
setnvalue(ra, cast_num(tsvalue(rb)->len));
return;
}
default: { /* try metamethod */
tm = luaT_gettmbyobj(L, rb, TM_LEN);
if (ttisnil(tm)) /* no metamethod? */
luaG_typeerror(L, rb, "get length of");
break;
}
}
callTMres(L, ra, tm, rb, luaO_nilobject);
}
static void Arith (lua_State *L, StkId ra, TValue *rb, static void Arith (lua_State *L, StkId ra, TValue *rb,
TValue *rc, TMS op) { TValue *rc, TMS op) {
TValue tempb, tempc; TValue tempb, tempc;
...@@ -568,23 +595,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { ...@@ -568,23 +595,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
continue; continue;
} }
case OP_LEN: { case OP_LEN: {
TValue *rb = RB(i); Protect(objlen(L, ra, RB(i)));
switch (ttype(rb)) {
case LUA_TTABLE: {
setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
break;
}
case LUA_TSTRING: {
setnvalue(ra, cast_num(tsvalue(rb)->len));
break;
}
default: { /* try metamethod */
Protect(
if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
luaG_typeerror(L, rb, "get length of");
)
}
}
continue; continue;
} }
case OP_CONCAT: { case OP_CONCAT: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment