** Finish the table access 'val = t[key]'. ** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to ** t[k] entry (which must be nil). */
| 158 | ** t[k] entry (which must be nil). |
| 159 | */ |
| 160 | void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, |
| 161 | const TValue *slot) { |
| 162 | int loop; /* counter to avoid infinite loops */ |
| 163 | const TValue *tm; /* metamethod */ |
| 164 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 165 | if (slot == NULL) { /* 't' is not a table? */ |
| 166 | lua_assert(!ttistable(t)); |
| 167 | tm = luaT_gettmbyobj(L, t, TM_INDEX); |
| 168 | if (ttisnil(tm)) |
| 169 | luaG_typeerror(L, t, "index"); /* no metamethod */ |
| 170 | /* else will try the metamethod */ |
| 171 | } |
| 172 | else { /* 't' is a table */ |
| 173 | lua_assert(ttisnil(slot)); |
| 174 | tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ |
| 175 | if (tm == NULL) { /* no metamethod? */ |
| 176 | setnilvalue(val); /* result is nil */ |
| 177 | return; |
| 178 | } |
| 179 | /* else will try the metamethod */ |
| 180 | } |
| 181 | if (ttisfunction(tm)) { /* is metamethod a function? */ |
| 182 | luaT_callTM(L, tm, t, key, val, 1); /* call it */ |
| 183 | return; |
| 184 | } |
| 185 | t = tm; /* else try to access 'tm[key]' */ |
| 186 | if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ |
| 187 | setobj2s(L, val, slot); /* done */ |
| 188 | return; |
| 189 | } |
| 190 | /* else repeat (tail call 'luaV_finishget') */ |
| 191 | } |
| 192 | luaG_runerror(L, "'__index' chain too long; possible loop"); |
| 193 | } |
| 194 | |
| 195 | |
| 196 | /* |
no test coverage detected