From 69e0240978fe86d032167711a9b6c7058db0c897 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 10 Sep 2007 14:59:32 -0300 Subject: [PATCH] tables and strings respect __len metamethod --- src/blua/ltm.c | 4 ++-- src/blua/ltm.h | 2 +- src/blua/lvm.c | 45 ++++++++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/blua/ltm.c b/src/blua/ltm.c index 031a2811e..570bded69 100644 --- a/src/blua/ltm.c +++ b/src/blua/ltm.c @@ -31,9 +31,9 @@ void luaT_init (lua_State *L) { static const char *const luaT_eventname[] = { /* ORDER TM */ "__index", "__newindex", "__usedindex", - "__gc", "__mode", "__eq", + "__gc", "__mode", "__len", "__eq", "__add", "__sub", "__mul", "__div", "__mod", - "__pow", "__unm", "__len", "__lt", "__le", + "__pow", "__unm", "__lt", "__le", "__concat", "__call" ,"__strhook" ,"__and", "__or", "__xor", "__shl", "__shr", "__not" diff --git a/src/blua/ltm.h b/src/blua/ltm.h index 3d4ac8c0e..3f2aa4a45 100644 --- a/src/blua/ltm.h +++ b/src/blua/ltm.h @@ -21,6 +21,7 @@ typedef enum { TM_USEDINDEX, TM_GC, TM_MODE, + TM_LEN, TM_EQ, /* last tag method with `fast' access */ TM_ADD, TM_SUB, @@ -29,7 +30,6 @@ typedef enum { TM_MOD, TM_POW, TM_UNM, - TM_LEN, TM_LT, TM_LE, TM_CONCAT, diff --git a/src/blua/lvm.c b/src/blua/lvm.c index 46a015c1e..b74fef4ee 100644 --- a/src/blua/lvm.c +++ b/src/blua/lvm.c @@ -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, TValue *rc, TMS op) { TValue tempb, tempc; @@ -568,23 +595,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { continue; } case OP_LEN: { - TValue *rb = 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"); - ) - } - } + Protect(objlen(L, ra, RB(i))); continue; } case OP_CONCAT: {