** Main function for table assignment (invoking metamethods if needed). ** Compute 't[key] = val' */
| 192 | ** Compute 't[key] = val' |
| 193 | */ |
| 194 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { |
| 195 | int loop; /* counter to avoid infinite loops */ |
| 196 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 197 | const TValue *tm; |
| 198 | if (ttistable(t)) { /* 't' is a table? */ |
| 199 | Table *h = hvalue(t); |
| 200 | TValue *oldval = cast(TValue *, luaH_get(h, key)); |
| 201 | /* if previous value is not nil, there must be a previous entry |
| 202 | in the table; a metamethod has no relevance */ |
| 203 | if (!ttisnil(oldval) || |
| 204 | /* previous value is nil; must check the metamethod */ |
| 205 | ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && |
| 206 | /* no metamethod; is there a previous entry in the table? */ |
| 207 | (oldval != luaO_nilobject || |
| 208 | /* no previous entry; must create one. (The next test is |
| 209 | always true; we only need the assignment.) */ |
| 210 | (oldval = luaH_newkey(L, h, key), 1)))) { |
| 211 | /* no metamethod and (now) there is an entry with given key */ |
| 212 | setobj2t(L, oldval, val); /* assign new value to that entry */ |
| 213 | invalidateTMcache(h); |
| 214 | luaC_barrierback(L, h, val); |
| 215 | return; |
| 216 | } |
| 217 | /* else will try the metamethod */ |
| 218 | } |
| 219 | else /* not a table; check metamethod */ |
| 220 | if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) |
| 221 | luaG_typeerror(L, t, "index"); |
| 222 | /* try the metamethod */ |
| 223 | if (ttisfunction(tm)) { |
| 224 | luaT_callTM(L, tm, t, key, val, 0); |
| 225 | return; |
| 226 | } |
| 227 | t = tm; /* else repeat assignment over 'tm' */ |
| 228 | } |
| 229 | luaG_runerror(L, "settable chain too long; possible loop"); |
| 230 | } |
| 231 | |
| 232 | |
| 233 | /* |
no test coverage detected