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: { |
