diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-06-02 16:31:40 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-06-02 16:31:40 -0300 |
| commit | 3b44821334a1aa387c13eaf3cd23a2344091cbc7 (patch) | |
| tree | 7070ed226b6db26ae82f99d94138465a95b0d7fc /lapi.c | |
| parent | 0214dab989396de05567f293e6aa909ee2ffbac1 (diff) | |
| download | lua-3b44821334a1aa387c13eaf3cd23a2344091cbc7.tar.gz lua-3b44821334a1aa387c13eaf3cd23a2344091cbc7.tar.bz2 lua-3b44821334a1aa387c13eaf3cd23a2344091cbc7.zip | |
stricter control (using tag variants) over closure kinds (Lua x C)
Diffstat (limited to '')
| -rw-r--r-- | lapi.c | 117 |
1 files changed, 61 insertions, 56 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.146 2011/05/31 18:24:36 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.147 2011/05/31 18:27:56 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -59,9 +59,9 @@ static TValue *index2addr (lua_State *L, int idx) { | |||
| 59 | if (ttislcf(ci->func)) /* light C function? */ | 59 | if (ttislcf(ci->func)) /* light C function? */ |
| 60 | return cast(TValue *, luaO_nilobject); /* it has no upvalues */ | 60 | return cast(TValue *, luaO_nilobject); /* it has no upvalues */ |
| 61 | else { | 61 | else { |
| 62 | Closure *func = clvalue(ci->func); | 62 | CClosure *func = clCvalue(ci->func); |
| 63 | return (idx <= func->c.nupvalues) | 63 | return (idx <= func->nupvalues) |
| 64 | ? &func->c.upvalue[idx-1] | 64 | ? &func->upvalue[idx-1] |
| 65 | : cast(TValue *, luaO_nilobject); | 65 | : cast(TValue *, luaO_nilobject); |
| 66 | } | 66 | } |
| 67 | } | 67 | } |
| @@ -195,10 +195,8 @@ static void moveto (lua_State *L, TValue *fr, int idx) { | |||
| 195 | TValue *to = index2addr(L, idx); | 195 | TValue *to = index2addr(L, idx); |
| 196 | api_checkvalidindex(L, to); | 196 | api_checkvalidindex(L, to); |
| 197 | setobj(L, to, fr); | 197 | setobj(L, to, fr); |
| 198 | if (idx < LUA_REGISTRYINDEX) { /* function upvalue? */ | 198 | if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ |
| 199 | lua_assert(ttisclosure(L->ci->func)); | 199 | luaC_barrier(L, clCvalue(L->ci->func), fr); |
| 200 | luaC_barrier(L, clvalue(L->ci->func), fr); | ||
| 201 | } | ||
| 202 | /* LUA_REGISTRYINDEX does not need gc barrier | 200 | /* LUA_REGISTRYINDEX does not need gc barrier |
| 203 | (collector revisits it before finishing collection) */ | 201 | (collector revisits it before finishing collection) */ |
| 204 | } | 202 | } |
| @@ -251,7 +249,7 @@ LUA_API const char *lua_typename (lua_State *L, int t) { | |||
| 251 | 249 | ||
| 252 | LUA_API int lua_iscfunction (lua_State *L, int idx) { | 250 | LUA_API int lua_iscfunction (lua_State *L, int idx) { |
| 253 | StkId o = index2addr(L, idx); | 251 | StkId o = index2addr(L, idx); |
| 254 | return (ttislcf(o) || (ttisclosure(o) && clvalue(o)->c.isC)); | 252 | return (ttislcf(o) || (ttisCclosure(o))); |
| 255 | } | 253 | } |
| 256 | 254 | ||
| 257 | 255 | ||
| @@ -398,7 +396,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | |||
| 398 | 396 | ||
| 399 | LUA_API size_t lua_rawlen (lua_State *L, int idx) { | 397 | LUA_API size_t lua_rawlen (lua_State *L, int idx) { |
| 400 | StkId o = index2addr(L, idx); | 398 | StkId o = index2addr(L, idx); |
| 401 | switch (ttype(o)) { | 399 | switch (ttypenv(o)) { |
| 402 | case LUA_TSTRING: return tsvalue(o)->len; | 400 | case LUA_TSTRING: return tsvalue(o)->len; |
| 403 | case LUA_TUSERDATA: return uvalue(o)->len; | 401 | case LUA_TUSERDATA: return uvalue(o)->len; |
| 404 | case LUA_TTABLE: return luaH_getn(hvalue(o)); | 402 | case LUA_TTABLE: return luaH_getn(hvalue(o)); |
| @@ -410,15 +408,15 @@ LUA_API size_t lua_rawlen (lua_State *L, int idx) { | |||
| 410 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { | 408 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { |
| 411 | StkId o = index2addr(L, idx); | 409 | StkId o = index2addr(L, idx); |
| 412 | if (ttislcf(o)) return fvalue(o); | 410 | if (ttislcf(o)) return fvalue(o); |
| 413 | else if (ttisclosure(o) && clvalue(o)->c.isC) | 411 | else if (ttisCclosure(o)) |
| 414 | return clvalue(o)->c.f; | 412 | return clCvalue(o)->f; |
| 415 | else return NULL; /* not a C function */ | 413 | else return NULL; /* not a C function */ |
| 416 | } | 414 | } |
| 417 | 415 | ||
| 418 | 416 | ||
| 419 | LUA_API void *lua_touserdata (lua_State *L, int idx) { | 417 | LUA_API void *lua_touserdata (lua_State *L, int idx) { |
| 420 | StkId o = index2addr(L, idx); | 418 | StkId o = index2addr(L, idx); |
| 421 | switch (ttype(o)) { | 419 | switch (ttypenv(o)) { |
| 422 | case LUA_TUSERDATA: return (rawuvalue(o) + 1); | 420 | case LUA_TUSERDATA: return (rawuvalue(o) + 1); |
| 423 | case LUA_TLIGHTUSERDATA: return pvalue(o); | 421 | case LUA_TLIGHTUSERDATA: return pvalue(o); |
| 424 | default: return NULL; | 422 | default: return NULL; |
| @@ -436,7 +434,8 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { | |||
| 436 | StkId o = index2addr(L, idx); | 434 | StkId o = index2addr(L, idx); |
| 437 | switch (ttype(o)) { | 435 | switch (ttype(o)) { |
| 438 | case LUA_TTABLE: return hvalue(o); | 436 | case LUA_TTABLE: return hvalue(o); |
| 439 | case LUA_TFUNCTION: return clvalue(o); | 437 | case LUA_TLCL: return clLvalue(o); |
| 438 | case LUA_TCCL: return clCvalue(o); | ||
| 440 | case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); | 439 | case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); |
| 441 | case LUA_TTHREAD: return thvalue(o); | 440 | case LUA_TTHREAD: return thvalue(o); |
| 442 | case LUA_TUSERDATA: | 441 | case LUA_TUSERDATA: |
| @@ -556,7 +555,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |||
| 556 | L->top -= n; | 555 | L->top -= n; |
| 557 | while (n--) | 556 | while (n--) |
| 558 | setobj2n(L, &cl->c.upvalue[n], L->top + n); | 557 | setobj2n(L, &cl->c.upvalue[n], L->top + n); |
| 559 | setclvalue(L, L->top, cl); | 558 | setclCvalue(L, L->top, cl); |
| 560 | } | 559 | } |
| 561 | api_incr_top(L); | 560 | api_incr_top(L); |
| 562 | lua_unlock(L); | 561 | lua_unlock(L); |
| @@ -656,7 +655,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
| 656 | int res; | 655 | int res; |
| 657 | lua_lock(L); | 656 | lua_lock(L); |
| 658 | obj = index2addr(L, objindex); | 657 | obj = index2addr(L, objindex); |
| 659 | switch (ttype(obj)) { | 658 | switch (ttypenv(obj)) { |
| 660 | case LUA_TTABLE: | 659 | case LUA_TTABLE: |
| 661 | mt = hvalue(obj)->metatable; | 660 | mt = hvalue(obj)->metatable; |
| 662 | break; | 661 | break; |
| @@ -763,7 +762,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
| 763 | api_check(L, ttistable(L->top - 1), "table expected"); | 762 | api_check(L, ttistable(L->top - 1), "table expected"); |
| 764 | mt = hvalue(L->top - 1); | 763 | mt = hvalue(L->top - 1); |
| 765 | } | 764 | } |
| 766 | switch (ttype(obj)) { | 765 | switch (ttypenv(obj)) { |
| 767 | case LUA_TTABLE: { | 766 | case LUA_TTABLE: { |
| 768 | hvalue(obj)->metatable = mt; | 767 | hvalue(obj)->metatable = mt; |
| 769 | if (mt) | 768 | if (mt) |
| @@ -921,15 +920,14 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, | |||
| 921 | luaZ_init(L, &z, reader, data); | 920 | luaZ_init(L, &z, reader, data); |
| 922 | status = luaD_protectedparser(L, &z, chunkname); | 921 | status = luaD_protectedparser(L, &z, chunkname); |
| 923 | if (status == LUA_OK) { /* no errors? */ | 922 | if (status == LUA_OK) { /* no errors? */ |
| 924 | Closure *f = clvalue(L->top - 1); /* get newly created function */ | 923 | LClosure *f = clLvalue(L->top - 1); /* get newly created function */ |
| 925 | lua_assert(!f->c.isC); | 924 | if (f->nupvalues == 1) { /* does it have one upvalue? */ |
| 926 | if (f->l.nupvalues == 1) { /* does it have one upvalue? */ | ||
| 927 | /* get global table from registry */ | 925 | /* get global table from registry */ |
| 928 | Table *reg = hvalue(&G(L)->l_registry); | 926 | Table *reg = hvalue(&G(L)->l_registry); |
| 929 | const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); | 927 | const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); |
| 930 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ | 928 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ |
| 931 | setobj(L, f->l.upvals[0]->v, gt); | 929 | setobj(L, f->upvals[0]->v, gt); |
| 932 | luaC_barrier(L, f->l.upvals[0], gt); | 930 | luaC_barrier(L, f->upvals[0], gt); |
| 933 | } | 931 | } |
| 934 | } | 932 | } |
| 935 | lua_unlock(L); | 933 | lua_unlock(L); |
| @@ -1131,25 +1129,27 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
| 1131 | 1129 | ||
| 1132 | static const char *aux_upvalue (StkId fi, int n, TValue **val, | 1130 | static const char *aux_upvalue (StkId fi, int n, TValue **val, |
| 1133 | GCObject **owner) { | 1131 | GCObject **owner) { |
| 1134 | Closure *f; | 1132 | switch (ttype(fi)) { |
| 1135 | if (!ttisclosure(fi)) return NULL; | 1133 | case LUA_TCCL: { /* C closure */ |
| 1136 | f = clvalue(fi); | 1134 | CClosure *f = clCvalue(fi); |
| 1137 | if (f->c.isC) { | 1135 | if (!(1 <= n && n <= f->nupvalues)) return NULL; |
| 1138 | if (!(1 <= n && n <= f->c.nupvalues)) return NULL; | 1136 | *val = &f->upvalue[n-1]; |
| 1139 | *val = &f->c.upvalue[n-1]; | 1137 | if (owner) *owner = obj2gco(f); |
| 1140 | if (owner) *owner = obj2gco(f); | 1138 | return ""; |
| 1141 | return ""; | 1139 | } |
| 1142 | } | 1140 | case LUA_TLCL: { /* Lua closure */ |
| 1143 | else { | 1141 | LClosure *f = clLvalue(fi); |
| 1144 | const char *name; | 1142 | const char *name; |
| 1145 | Proto *p = f->l.p; | 1143 | Proto *p = f->p; |
| 1146 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; | 1144 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; |
| 1147 | *val = f->l.upvals[n-1]->v; | 1145 | *val = f->upvals[n-1]->v; |
| 1148 | if (owner) *owner = obj2gco(f->l.upvals[n - 1]); | 1146 | if (owner) *owner = obj2gco(f->upvals[n - 1]); |
| 1149 | name = getstr(p->upvalues[n-1].name); | 1147 | name = getstr(p->upvalues[n-1].name); |
| 1150 | if (name == NULL) /* no debug information? */ | 1148 | if (name == NULL) /* no debug information? */ |
| 1151 | name = ""; | 1149 | name = ""; |
| 1152 | return name; | 1150 | return name; |
| 1151 | } | ||
| 1152 | default: return NULL; /* not a closure */ | ||
| 1153 | } | 1153 | } |
| 1154 | } | 1154 | } |
| 1155 | 1155 | ||
| @@ -1187,34 +1187,39 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | |||
| 1187 | } | 1187 | } |
| 1188 | 1188 | ||
| 1189 | 1189 | ||
| 1190 | static UpVal **getupvalref (lua_State *L, int fidx, int n, Closure **pf) { | 1190 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { |
| 1191 | Closure *f; | 1191 | LClosure *f; |
| 1192 | StkId fi = index2addr(L, fidx); | 1192 | StkId fi = index2addr(L, fidx); |
| 1193 | api_check(L, ttisclosure(fi), "Lua function expected"); | 1193 | api_check(L, ttisLclosure(fi), "Lua function expected"); |
| 1194 | f = clvalue(fi); | 1194 | f = clLvalue(fi); |
| 1195 | api_check(L, !f->c.isC, "Lua function expected"); | 1195 | api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); |
| 1196 | api_check(L, (1 <= n && n <= f->l.p->sizeupvalues), "invalid upvalue index"); | ||
| 1197 | if (pf) *pf = f; | 1196 | if (pf) *pf = f; |
| 1198 | return &f->l.upvals[n - 1]; /* get its upvalue pointer */ | 1197 | return &f->upvals[n - 1]; /* get its upvalue pointer */ |
| 1199 | } | 1198 | } |
| 1200 | 1199 | ||
| 1201 | 1200 | ||
| 1202 | LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { | 1201 | LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { |
| 1203 | Closure *f; | ||
| 1204 | StkId fi = index2addr(L, fidx); | 1202 | StkId fi = index2addr(L, fidx); |
| 1205 | api_check(L, ttisclosure(fi), "function expected"); | 1203 | switch (ttype(fi)) { |
| 1206 | f = clvalue(fi); | 1204 | case LUA_TLCL: { /* lua closure */ |
| 1207 | if (f->c.isC) { | 1205 | return *getupvalref(L, fidx, n, NULL); |
| 1208 | api_check(L, 1 <= n && n <= f->c.nupvalues, "invalid upvalue index"); | 1206 | } |
| 1209 | return &f->c.upvalue[n - 1]; | 1207 | case LUA_TCCL: { /* C closure */ |
| 1208 | CClosure *f = clCvalue(fi); | ||
| 1209 | api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); | ||
| 1210 | return &f->upvalue[n - 1]; | ||
| 1211 | } | ||
| 1212 | default: { | ||
| 1213 | api_check(L, 0, "closure expected"); | ||
| 1214 | return NULL; | ||
| 1215 | } | ||
| 1210 | } | 1216 | } |
| 1211 | else return *getupvalref(L, fidx, n, NULL); | ||
| 1212 | } | 1217 | } |
| 1213 | 1218 | ||
| 1214 | 1219 | ||
| 1215 | LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | 1220 | LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, |
| 1216 | int fidx2, int n2) { | 1221 | int fidx2, int n2) { |
| 1217 | Closure *f1; | 1222 | LClosure *f1; |
| 1218 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | 1223 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
| 1219 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | 1224 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
| 1220 | *up1 = *up2; | 1225 | *up1 = *up2; |
