summaryrefslogtreecommitdiff
path: root/lapi.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-02-18 10:40:02 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-02-18 10:40:02 -0200
commit7d45a5f48ff32a4e09a1734de23823943d6a6b28 (patch)
treede7bef1faf37d9b639928e5269e89d7112b5b6fa /lapi.c
parent73d764024451c24bc43b8e5102fe90974a86b7f4 (diff)
downloadlua-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.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/lapi.c b/lapi.c
index f82b00dc..b08fa6ad 100644
--- a/lapi.c
+++ b/lapi.c
@@ -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
78static 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
73void luaA_pushobject (lua_State *L, const TValue *o) { 88void 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
683LUA_API int lua_setfenv (lua_State *L, int idx) { 716LUA_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' */
776static void f_Ccall (lua_State *L, void *ud) { 816static 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);