diff options
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | lapi.c | 19 | ||||
| -rw-r--r-- | ldblib.c | 24 | ||||
| -rw-r--r-- | testes/closure.lua | 2 |
4 files changed, 33 insertions, 15 deletions
| @@ -10,3 +10,6 @@ testes/time.txt | |||
| 10 | testes/time-debug.txt | 10 | testes/time-debug.txt |
| 11 | 11 | ||
| 12 | testes/libs/all | 12 | testes/libs/all |
| 13 | |||
| 14 | temp | ||
| 15 | lua | ||
| @@ -1383,13 +1383,16 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | |||
| 1383 | 1383 | ||
| 1384 | 1384 | ||
| 1385 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { | 1385 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { |
| 1386 | static const UpVal *const nullup = NULL; | ||
| 1386 | LClosure *f; | 1387 | LClosure *f; |
| 1387 | TValue *fi = index2value(L, fidx); | 1388 | TValue *fi = index2value(L, fidx); |
| 1388 | api_check(L, ttisLclosure(fi), "Lua function expected"); | 1389 | api_check(L, ttisLclosure(fi), "Lua function expected"); |
| 1389 | f = clLvalue(fi); | 1390 | f = clLvalue(fi); |
| 1390 | api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); | ||
| 1391 | if (pf) *pf = f; | 1391 | if (pf) *pf = f; |
| 1392 | return &f->upvals[n - 1]; /* get its upvalue pointer */ | 1392 | if (1 <= n && n <= f->p->sizeupvalues) |
| 1393 | return &f->upvals[n - 1]; /* get its upvalue pointer */ | ||
| 1394 | else | ||
| 1395 | return (UpVal**)&nullup; | ||
| 1393 | } | 1396 | } |
| 1394 | 1397 | ||
| 1395 | 1398 | ||
| @@ -1401,11 +1404,14 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { | |||
| 1401 | } | 1404 | } |
| 1402 | case LUA_VCCL: { /* C closure */ | 1405 | case LUA_VCCL: { /* C closure */ |
| 1403 | CClosure *f = clCvalue(fi); | 1406 | CClosure *f = clCvalue(fi); |
| 1404 | api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); | 1407 | if (1 <= n && n <= f->nupvalues) |
| 1405 | return &f->upvalue[n - 1]; | 1408 | return &f->upvalue[n - 1]; |
| 1406 | } | 1409 | /* else */ |
| 1410 | } /* FALLTHROUGH */ | ||
| 1411 | case LUA_VLCF: | ||
| 1412 | return NULL; /* light C functions have no upvalues */ | ||
| 1407 | default: { | 1413 | default: { |
| 1408 | api_check(L, 0, "closure expected"); | 1414 | api_check(L, 0, "function expected"); |
| 1409 | return NULL; | 1415 | return NULL; |
| 1410 | } | 1416 | } |
| 1411 | } | 1417 | } |
| @@ -1417,6 +1423,7 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | |||
| 1417 | LClosure *f1; | 1423 | LClosure *f1; |
| 1418 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | 1424 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
| 1419 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | 1425 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
| 1426 | api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index"); | ||
| 1420 | *up1 = *up2; | 1427 | *up1 = *up2; |
| 1421 | luaC_objbarrier(L, f1, *up1); | 1428 | luaC_objbarrier(L, f1, *up1); |
| 1422 | } | 1429 | } |
| @@ -281,25 +281,33 @@ static int db_setupvalue (lua_State *L) { | |||
| 281 | ** Check whether a given upvalue from a given closure exists and | 281 | ** Check whether a given upvalue from a given closure exists and |
| 282 | ** returns its index | 282 | ** returns its index |
| 283 | */ | 283 | */ |
| 284 | static int checkupval (lua_State *L, int argf, int argnup) { | 284 | static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) { |
| 285 | void *id; | ||
| 285 | int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ | 286 | int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ |
| 286 | luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ | 287 | luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ |
| 287 | luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, | 288 | id = lua_upvalueid(L, argf, nup); |
| 288 | "invalid upvalue index"); | 289 | if (pnup) { |
| 289 | return nup; | 290 | luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index"); |
| 291 | *pnup = nup; | ||
| 292 | } | ||
| 293 | return id; | ||
| 290 | } | 294 | } |
| 291 | 295 | ||
| 292 | 296 | ||
| 293 | static int db_upvalueid (lua_State *L) { | 297 | static int db_upvalueid (lua_State *L) { |
| 294 | int n = checkupval(L, 1, 2); | 298 | void *id = checkupval(L, 1, 2, NULL); |
| 295 | lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); | 299 | if (id != NULL) |
| 300 | lua_pushlightuserdata(L, id); | ||
| 301 | else | ||
| 302 | luaL_pushfail(L); | ||
| 296 | return 1; | 303 | return 1; |
| 297 | } | 304 | } |
| 298 | 305 | ||
| 299 | 306 | ||
| 300 | static int db_upvaluejoin (lua_State *L) { | 307 | static int db_upvaluejoin (lua_State *L) { |
| 301 | int n1 = checkupval(L, 1, 2); | 308 | int n1, n2; |
| 302 | int n2 = checkupval(L, 3, 4); | 309 | checkupval(L, 1, 2, &n1); |
| 310 | checkupval(L, 3, 4, &n2); | ||
| 303 | luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); | 311 | luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); |
| 304 | luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); | 312 | luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); |
| 305 | lua_upvaluejoin(L, 1, n1, 3, n2); | 313 | lua_upvaluejoin(L, 1, n1, 3, n2); |
diff --git a/testes/closure.lua b/testes/closure.lua index cdeaebaa..c2453677 100644 --- a/testes/closure.lua +++ b/testes/closure.lua | |||
| @@ -242,7 +242,7 @@ end | |||
| 242 | 242 | ||
| 243 | assert(debug.upvalueid(foo1, 1)) | 243 | assert(debug.upvalueid(foo1, 1)) |
| 244 | assert(debug.upvalueid(foo1, 2)) | 244 | assert(debug.upvalueid(foo1, 2)) |
| 245 | assert(not pcall(debug.upvalueid, foo1, 3)) | 245 | assert(not debug.upvalueid(foo1, 3)) |
| 246 | assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) | 246 | assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) |
| 247 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) | 247 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) |
| 248 | assert(debug.upvalueid(foo3, 1)) | 248 | assert(debug.upvalueid(foo3, 1)) |
