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); |