diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-09-10 14:59:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-09-10 14:59:32 -0300 |
commit | fe0838cd1c75e309f9d136d69f9d77e997181d80 (patch) | |
tree | 88acac0e70fe74cb686d87ffb471e906c04b9cfd /lvm.c | |
parent | 8acaa2ce07ff19a99a8f6d97627df37fd15cc669 (diff) | |
download | lua-fe0838cd1c75e309f9d136d69f9d77e997181d80.tar.gz lua-fe0838cd1c75e309f9d136d69f9d77e997181d80.tar.bz2 lua-fe0838cd1c75e309f9d136d69f9d77e997181d80.zip |
tables and strings respect __len metamethod
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 47 |
1 files changed, 29 insertions, 18 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.71 2007/03/26 15:56:23 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.72 2007/06/19 19:48:15 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -310,6 +310,33 @@ void luaV_concat (lua_State *L, int total, int last) { | |||
310 | } | 310 | } |
311 | 311 | ||
312 | 312 | ||
313 | static void objlen (lua_State *L, StkId ra, const TValue *rb) { | ||
314 | const TValue *tm; | ||
315 | switch (ttype(rb)) { | ||
316 | case LUA_TTABLE: { | ||
317 | Table *h = hvalue(rb); | ||
318 | tm = fasttm(L, h->metatable, TM_LEN); | ||
319 | if (tm) break; /* metamethod? break switch to call it */ | ||
320 | setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ | ||
321 | return; | ||
322 | } | ||
323 | case LUA_TSTRING: { | ||
324 | tm = fasttm(L, G(L)->mt[LUA_TSTRING], TM_LEN); | ||
325 | if (tm) break; /* metamethod? break switch to call it */ | ||
326 | setnvalue(ra, cast_num(tsvalue(rb)->len)); | ||
327 | return; | ||
328 | } | ||
329 | default: { /* try metamethod */ | ||
330 | tm = luaT_gettmbyobj(L, rb, TM_LEN); | ||
331 | if (ttisnil(tm)) /* no metamethod? */ | ||
332 | luaG_typeerror(L, rb, "get length of"); | ||
333 | break; | ||
334 | } | ||
335 | } | ||
336 | callTMres(L, ra, tm, rb, luaO_nilobject); | ||
337 | } | ||
338 | |||
339 | |||
313 | static void Arith (lua_State *L, StkId ra, const TValue *rb, | 340 | static void Arith (lua_State *L, StkId ra, const TValue *rb, |
314 | const TValue *rc, TMS op) { | 341 | const TValue *rc, TMS op) { |
315 | TValue tempb, tempc; | 342 | TValue tempb, tempc; |
@@ -509,23 +536,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
509 | continue; | 536 | continue; |
510 | } | 537 | } |
511 | case OP_LEN: { | 538 | case OP_LEN: { |
512 | const TValue *rb = RB(i); | 539 | Protect(objlen(L, ra, RB(i))); |
513 | switch (ttype(rb)) { | ||
514 | case LUA_TTABLE: { | ||
515 | setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); | ||
516 | break; | ||
517 | } | ||
518 | case LUA_TSTRING: { | ||
519 | setnvalue(ra, cast_num(tsvalue(rb)->len)); | ||
520 | break; | ||
521 | } | ||
522 | default: { /* try metamethod */ | ||
523 | Protect( | ||
524 | if (!call_binTM(L, rb, rb, ra, TM_LEN)) | ||
525 | luaG_typeerror(L, rb, "get length of"); | ||
526 | ) | ||
527 | } | ||
528 | } | ||
529 | continue; | 540 | continue; |
530 | } | 541 | } |
531 | case OP_CONCAT: { | 542 | case OP_CONCAT: { |