| 135 | |
| 136 | |
| 137 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { |
| 138 | int loop; |
| 139 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 140 | const TValue *tm; |
| 141 | if (ttistable(t)) { /* `t' is a table? */ |
| 142 | Table *h = hvalue(t); |
| 143 | TValue *oldval = cast(TValue *, luaH_get(h, key)); |
| 144 | /* if previous value is not nil, there must be a previous entry |
| 145 | in the table; moreover, a metamethod has no relevance */ |
| 146 | if (!ttisnil(oldval) || |
| 147 | /* previous value is nil; must check the metamethod */ |
| 148 | ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && |
| 149 | /* no metamethod; is there a previous entry in the table? */ |
| 150 | (oldval != luaO_nilobject || |
| 151 | /* no previous entry; must create one. (The next test is |
| 152 | always true; we only need the assignment.) */ |
| 153 | (oldval = luaH_newkey(L, h, key), 1)))) { |
| 154 | /* no metamethod and (now) there is an entry with given key */ |
| 155 | setobj2t(L, oldval, val); /* assign new value to that entry */ |
| 156 | invalidateTMcache(h); |
| 157 | luaC_barrierback(L, obj2gco(h), val); |
| 158 | return; |
| 159 | } |
| 160 | /* else will try the metamethod */ |
| 161 | } |
| 162 | else /* not a table; check metamethod */ |
| 163 | if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) |
| 164 | luaG_typeerror(L, t, "index"); |
| 165 | /* there is a metamethod */ |
| 166 | if (ttisfunction(tm)) { |
| 167 | callTM(L, tm, t, key, val, 0); |
| 168 | return; |
| 169 | } |
| 170 | t = tm; /* else repeat with 'tm' */ |
| 171 | } |
| 172 | luaG_runerror(L, "loop in settable"); |
| 173 | } |
| 174 | |
| 175 | |
| 176 | static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, |
no test coverage detected