diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-02-18 10:40:02 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-02-18 10:40:02 -0200 |
| commit | 7d45a5f48ff32a4e09a1734de23823943d6a6b28 (patch) | |
| tree | de7bef1faf37d9b639928e5269e89d7112b5b6fa /lapi.c | |
| parent | 73d764024451c24bc43b8e5102fe90974a86b7f4 (diff) | |
| download | lua-7d45a5f48ff32a4e09a1734de23823943d6a6b28.tar.gz lua-7d45a5f48ff32a4e09a1734de23823943d6a6b28.tar.bz2 lua-7d45a5f48ff32a4e09a1734de23823943d6a6b28.zip | |
C functions and userdata also have environments
Diffstat (limited to 'lapi.c')
| -rw-r--r-- | lapi.c | 66 |
1 files changed, 53 insertions, 13 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.25 2005/01/07 19:53:32 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.26 2005/01/14 14:19:42 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 | */ |
| @@ -58,6 +58,11 @@ static TValue *index2adr (lua_State *L, int idx) { | |||
| 58 | } | 58 | } |
| 59 | else switch (idx) { /* pseudo-indices */ | 59 | else switch (idx) { /* pseudo-indices */ |
| 60 | case LUA_REGISTRYINDEX: return registry(L); | 60 | case LUA_REGISTRYINDEX: return registry(L); |
| 61 | case LUA_ENVIRONINDEX: { | ||
| 62 | Closure *func = curr_func(L); | ||
| 63 | sethvalue(L, &L->env, func->c.env); | ||
| 64 | return &L->env; | ||
| 65 | } | ||
| 61 | case LUA_GLOBALSINDEX: return gt(L); | 66 | case LUA_GLOBALSINDEX: return gt(L); |
| 62 | default: { | 67 | default: { |
| 63 | Closure *func = curr_func(L); | 68 | Closure *func = curr_func(L); |
| @@ -70,6 +75,16 @@ static TValue *index2adr (lua_State *L, int idx) { | |||
| 70 | } | 75 | } |
| 71 | 76 | ||
| 72 | 77 | ||
| 78 | static Table *getcurrenv (lua_State *L) { | ||
| 79 | if (L->ci == L->base_ci) /* no enclosing function? */ | ||
| 80 | return hvalue(gt(L)); /* use global table as environment */ | ||
| 81 | else { | ||
| 82 | Closure *func = curr_func(L); | ||
| 83 | return func->c.env; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 73 | void luaA_pushobject (lua_State *L, const TValue *o) { | 88 | void luaA_pushobject (lua_State *L, const TValue *o) { |
| 74 | setobj2s(L, L->top, o); | 89 | setobj2s(L, L->top, o); |
| 75 | incr_top(L); | 90 | incr_top(L); |
| @@ -186,9 +201,17 @@ LUA_API void lua_replace (lua_State *L, int idx) { | |||
| 186 | api_checknelems(L, 1); | 201 | api_checknelems(L, 1); |
| 187 | o = index2adr(L, idx); | 202 | o = index2adr(L, idx); |
| 188 | api_checkvalidindex(L, o); | 203 | api_checkvalidindex(L, o); |
| 189 | setobj(L, o, L->top - 1); | 204 | if (idx == LUA_ENVIRONINDEX) { |
| 190 | if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ | 205 | Closure *func = curr_func(L); |
| 191 | luaC_barrier(L, curr_func(L), L->top - 1); | 206 | api_check(L, ttistable(L->top - 1)); |
| 207 | func->c.env = hvalue(L->top - 1); | ||
| 208 | luaC_barrier(L, func, L->top - 1); | ||
| 209 | } | ||
| 210 | else { | ||
| 211 | setobj(L, o, L->top - 1); | ||
| 212 | if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ | ||
| 213 | luaC_barrier(L, curr_func(L), L->top - 1); | ||
| 214 | } | ||
| 192 | L->top--; | 215 | L->top--; |
| 193 | lua_unlock(L); | 216 | lua_unlock(L); |
| 194 | } | 217 | } |
| @@ -452,7 +475,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |||
| 452 | lua_lock(L); | 475 | lua_lock(L); |
| 453 | luaC_checkGC(L); | 476 | luaC_checkGC(L); |
| 454 | api_checknelems(L, n); | 477 | api_checknelems(L, n); |
| 455 | cl = luaF_newCclosure(L, n); | 478 | cl = luaF_newCclosure(L, n, getcurrenv(L)); |
| 456 | cl->c.f = fn; | 479 | cl->c.f = fn; |
| 457 | L->top -= n; | 480 | L->top -= n; |
| 458 | while (n--) | 481 | while (n--) |
| @@ -579,7 +602,17 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { | |||
| 579 | lua_lock(L); | 602 | lua_lock(L); |
| 580 | o = index2adr(L, idx); | 603 | o = index2adr(L, idx); |
| 581 | api_checkvalidindex(L, o); | 604 | api_checkvalidindex(L, o); |
| 582 | setobj2s(L, L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L)); | 605 | switch (ttype(o)) { |
| 606 | case LUA_TFUNCTION: | ||
| 607 | sethvalue(L, L->top, clvalue(o)->c.env); | ||
| 608 | break; | ||
| 609 | case LUA_TUSERDATA: | ||
| 610 | sethvalue(L, L->top, uvalue(o)->env); | ||
| 611 | break; | ||
| 612 | default: | ||
| 613 | setnilvalue(L->top); | ||
| 614 | break; | ||
| 615 | } | ||
| 583 | api_incr_top(L); | 616 | api_incr_top(L); |
| 584 | lua_unlock(L); | 617 | lua_unlock(L); |
| 585 | } | 618 | } |
| @@ -682,17 +715,24 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
| 682 | 715 | ||
| 683 | LUA_API int lua_setfenv (lua_State *L, int idx) { | 716 | LUA_API int lua_setfenv (lua_State *L, int idx) { |
| 684 | StkId o; | 717 | StkId o; |
| 685 | int res = 0; | 718 | int res = 1; |
| 686 | lua_lock(L); | 719 | lua_lock(L); |
| 687 | api_checknelems(L, 1); | 720 | api_checknelems(L, 1); |
| 688 | o = index2adr(L, idx); | 721 | o = index2adr(L, idx); |
| 689 | api_checkvalidindex(L, o); | 722 | api_checkvalidindex(L, o); |
| 690 | api_check(L, ttistable(L->top - 1)); | 723 | api_check(L, ttistable(L->top - 1)); |
| 691 | if (isLfunction(o)) { | 724 | switch (ttype(o)) { |
| 692 | res = 1; | 725 | case LUA_TFUNCTION: |
| 693 | clvalue(o)->l.g = *(L->top - 1); | 726 | clvalue(o)->c.env = hvalue(L->top - 1); |
| 694 | luaC_objbarrier(L, clvalue(o), hvalue(L->top - 1)); | 727 | break; |
| 728 | case LUA_TUSERDATA: | ||
| 729 | uvalue(o)->env = hvalue(L->top - 1); | ||
| 730 | break; | ||
| 731 | default: | ||
| 732 | res = 0; | ||
| 733 | break; | ||
| 695 | } | 734 | } |
| 735 | luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); | ||
| 696 | L->top--; | 736 | L->top--; |
| 697 | lua_unlock(L); | 737 | lua_unlock(L); |
| 698 | return res; | 738 | return res; |
| @@ -776,7 +816,7 @@ struct CCallS { /* data to `f_Ccall' */ | |||
| 776 | static void f_Ccall (lua_State *L, void *ud) { | 816 | static void f_Ccall (lua_State *L, void *ud) { |
| 777 | struct CCallS *c = cast(struct CCallS *, ud); | 817 | struct CCallS *c = cast(struct CCallS *, ud); |
| 778 | Closure *cl; | 818 | Closure *cl; |
| 779 | cl = luaF_newCclosure(L, 0); | 819 | cl = luaF_newCclosure(L, 0, getcurrenv(L)); |
| 780 | cl->c.f = c->func; | 820 | cl->c.f = c->func; |
| 781 | setclvalue(L, L->top, cl); /* push function */ | 821 | setclvalue(L, L->top, cl); /* push function */ |
| 782 | incr_top(L); | 822 | incr_top(L); |
| @@ -943,7 +983,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
| 943 | Udata *u; | 983 | Udata *u; |
| 944 | lua_lock(L); | 984 | lua_lock(L); |
| 945 | luaC_checkGC(L); | 985 | luaC_checkGC(L); |
| 946 | u = luaS_newudata(L, size); | 986 | u = luaS_newudata(L, size, getcurrenv(L)); |
| 947 | setuvalue(L, L->top, u); | 987 | setuvalue(L, L->top, u); |
| 948 | api_incr_top(L); | 988 | api_incr_top(L); |
| 949 | lua_unlock(L); | 989 | lua_unlock(L); |
