aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c48
-rw-r--r--ldblib.c28
-rw-r--r--lfunc.c4
-rw-r--r--lgc.c8
-rw-r--r--lobject.h5
-rw-r--r--lparser.c28
-rw-r--r--lparser.h3
-rw-r--r--ltests.c21
-rw-r--r--lua.h4
9 files changed, 128 insertions, 21 deletions
diff --git a/lapi.c b/lapi.c
index 0dd005c0..998bac0a 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 1.225 2002/12/04 17:28:27 roberto Exp roberto $ 2** $Id: lapi.c,v 1.226 2002/12/04 17:38:31 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*/
@@ -866,3 +866,49 @@ LUA_API int lua_pushupvalues (lua_State *L) {
866} 866}
867 867
868 868
869static const char *aux_upvalue (lua_State *L, int funcindex, int n,
870 TObject **val) {
871 Closure *f;
872 StkId fi = luaA_index(L, funcindex);
873 if (!ttisfunction(fi)) return NULL;
874 f = clvalue(fi);
875 if (n > f->l.nupvalues) return NULL;
876 if (f->c.isC) {
877 *val = &f->c.upvalue[n-1];
878 return "";
879 }
880 else {
881 *val = f->l.upvals[n-1]->v;
882 return getstr(f->l.p->upvalues[n-1]);
883 }
884}
885
886
887LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
888 const char *name;
889 TObject *val;
890 lua_lock(L);
891 name = aux_upvalue(L, funcindex, n, &val);
892 if (name) {
893 setobj2s(L->top, val);
894 api_incr_top(L);
895 }
896 lua_unlock(L);
897 return name;
898}
899
900
901LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
902 const char *name;
903 TObject *val;
904 lua_lock(L);
905 api_checknelems(L, 1);
906 name = aux_upvalue(L, funcindex, n, &val);
907 if (name) {
908 L->top--;
909 setobj(val, L->top); /* write barrier */
910 }
911 lua_unlock(L);
912 return name;
913}
914
diff --git a/ldblib.c b/ldblib.c
index 94087679..98b3106b 100644
--- a/ldblib.c
+++ b/ldblib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldblib.c,v 1.74 2002/12/04 17:38:31 roberto Exp roberto $ 2** $Id: ldblib.c,v 1.75 2002/12/05 17:50:10 roberto Exp roberto $
3** Interface from Lua to its debug API 3** Interface from Lua to its debug API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -108,6 +108,30 @@ static int setlocal (lua_State *L) {
108} 108}
109 109
110 110
111static int auxupvalue (lua_State *L, int get) {
112 const char *name;
113 int n = luaL_checkint(L, 2);
114 luaL_checktype(L, 1, LUA_TFUNCTION);
115 if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */
116 name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
117 if (name == NULL) return 0;
118 lua_pushstring(L, name);
119 lua_insert(L, -(get+1));
120 return get + 1;
121}
122
123
124static int getupvalue (lua_State *L) {
125 return auxupvalue(L, 1);
126}
127
128
129static int setupvalue (lua_State *L) {
130 luaL_checkany(L, 3);
131 return auxupvalue(L, 0);
132}
133
134
111 135
112static const char KEY_HOOK = 'h'; 136static const char KEY_HOOK = 'h';
113 137
@@ -253,8 +277,10 @@ static const luaL_reg dblib[] = {
253 {"getlocal", getlocal}, 277 {"getlocal", getlocal},
254 {"getinfo", getinfo}, 278 {"getinfo", getinfo},
255 {"gethook", gethook}, 279 {"gethook", gethook},
280 {"getupvalue", getupvalue},
256 {"sethook", sethook}, 281 {"sethook", sethook},
257 {"setlocal", setlocal}, 282 {"setlocal", setlocal},
283 {"setupvalue", setupvalue},
258 {"debug", debug}, 284 {"debug", debug},
259 {"traceback", errorfb}, 285 {"traceback", errorfb},
260 {NULL, NULL} 286 {NULL, NULL}
diff --git a/lfunc.c b/lfunc.c
index bb8a48c2..e55b59d9 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 1.63 2002/11/14 16:15:53 roberto Exp roberto $ 2** $Id: lfunc.c,v 1.64 2002/12/04 17:38:31 roberto Exp roberto $
3** Auxiliary functions to manipulate prototypes and closures 3** Auxiliary functions to manipulate prototypes and closures
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -85,6 +85,7 @@ Proto *luaF_newproto (lua_State *L) {
85 f->sizecode = 0; 85 f->sizecode = 0;
86 f->sizelineinfo = 0; 86 f->sizelineinfo = 0;
87 f->nupvalues = 0; 87 f->nupvalues = 0;
88 f->upvalues = NULL;
88 f->numparams = 0; 89 f->numparams = 0;
89 f->is_vararg = 0; 90 f->is_vararg = 0;
90 f->maxstacksize = 0; 91 f->maxstacksize = 0;
@@ -103,6 +104,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
103 luaM_freearray(L, f->k, f->sizek, TObject); 104 luaM_freearray(L, f->k, f->sizek, TObject);
104 luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); 105 luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
105 luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); 106 luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
107 luaM_freearray(L, f->upvalues, f->nupvalues, TString *);
106 luaM_freelem(L, f); 108 luaM_freelem(L, f);
107} 109}
108 110
diff --git a/lgc.c b/lgc.c
index d20b33c1..fb3dfd09 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.165 2002/12/02 12:06:10 roberto Exp roberto $ 2** $Id: lgc.c,v 1.166 2002/12/04 17:38:31 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -186,11 +186,13 @@ static void traversetable (GCState *st, Table *h) {
186static void traverseproto (GCState *st, Proto *f) { 186static void traverseproto (GCState *st, Proto *f) {
187 int i; 187 int i;
188 stringmark(f->source); 188 stringmark(f->source);
189 for (i=0; i<f->sizek; i++) { 189 for (i=0; i<f->sizek; i++) { /* mark literal strings */
190 if (ttisstring(f->k+i)) 190 if (ttisstring(f->k+i))
191 stringmark(tsvalue(f->k+i)); 191 stringmark(tsvalue(f->k+i));
192 } 192 }
193 for (i=0; i<f->sizep; i++) 193 for (i=0; i<f->nupvalues; i++) /* mark upvalue names */
194 stringmark(f->upvalues[i]);
195 for (i=0; i<f->sizep; i++) /* mark nested protos */
194 markvalue(st, f->p[i]); 196 markvalue(st, f->p[i]);
195 for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ 197 for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
196 stringmark(f->locvars[i].varname); 198 stringmark(f->locvars[i].varname);
diff --git a/lobject.h b/lobject.h
index 4fb42461..6b00b4b6 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 1.154 2002/11/14 11:51:50 roberto Exp roberto $ 2** $Id: lobject.h,v 1.155 2002/11/14 16:16:21 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -214,7 +214,9 @@ typedef struct Proto {
214 struct Proto **p; /* functions defined inside the function */ 214 struct Proto **p; /* functions defined inside the function */
215 int *lineinfo; /* map from opcodes to source lines */ 215 int *lineinfo; /* map from opcodes to source lines */
216 struct LocVar *locvars; /* information about local variables */ 216 struct LocVar *locvars; /* information about local variables */
217 TString **upvalues; /* upvalue names */
217 TString *source; 218 TString *source;
219 int nupvalues; /* (also size of `upvals') */
218 int sizek; /* size of `k' */ 220 int sizek; /* size of `k' */
219 int sizecode; 221 int sizecode;
220 int sizelineinfo; 222 int sizelineinfo;
@@ -222,7 +224,6 @@ typedef struct Proto {
222 int sizelocvars; 224 int sizelocvars;
223 int lineDefined; 225 int lineDefined;
224 GCObject *gclist; 226 GCObject *gclist;
225 lu_byte nupvalues;
226 lu_byte numparams; 227 lu_byte numparams;
227 lu_byte is_vararg; 228 lu_byte is_vararg;
228 lu_byte maxstacksize; 229 lu_byte maxstacksize;
diff --git a/lparser.c b/lparser.c
index e016b835..d804e430 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 1.201 2002/12/06 17:09:00 roberto Exp roberto $ 2** $Id: lparser.c,v 1.202 2002/12/11 12:34:22 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -179,16 +179,21 @@ static void create_local (LexState *ls, const char *name) {
179} 179}
180 180
181 181
182static int indexupvalue (FuncState *fs, expdesc *v) { 182static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
183 int i; 183 int i;
184 for (i=0; i<fs->f->nupvalues; i++) { 184 for (i=0; i<fs->nu; i++) {
185 if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) 185 if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) {
186 lua_assert(fs->f->upvalues[i] == name);
186 return i; 187 return i;
188 }
187 } 189 }
188 /* new one */ 190 /* new one */
189 luaX_checklimit(fs->ls, fs->f->nupvalues+1, MAXUPVALUES, "upvalues"); 191 luaX_checklimit(fs->ls, fs->nu + 1, MAXUPVALUES, "upvalues");
190 fs->upvalues[fs->f->nupvalues] = *v; 192 luaM_growvector(fs->L, fs->f->upvalues, fs->nu, fs->f->nupvalues,
191 return fs->f->nupvalues++; 193 TString *, MAX_INT, "");
194 fs->f->upvalues[fs->nu] = name;
195 fs->upvalues[fs->nu] = *v;
196 return fs->nu++;
192} 197}
193 198
194 199
@@ -226,7 +231,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
226 var->info = luaK_stringK(fs, n); /* info points to global name */ 231 var->info = luaK_stringK(fs, n); /* info points to global name */
227 } 232 }
228 else { /* LOCAL or UPVAL */ 233 else { /* LOCAL or UPVAL */
229 var->info = indexupvalue(fs, var); 234 var->info = indexupvalue(fs, n, var);
230 var->k = VUPVAL; /* upvalue in this level */ 235 var->k = VUPVAL; /* upvalue in this level */
231 } 236 }
232 } 237 }
@@ -302,7 +307,7 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
302 MAXARG_Bx, "constant table overflow"); 307 MAXARG_Bx, "constant table overflow");
303 f->p[fs->np++] = func->f; 308 f->p[fs->np++] = func->f;
304 init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); 309 init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
305 for (i=0; i<func->f->nupvalues; i++) { 310 for (i=0; i<func->nu; i++) {
306 OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; 311 OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
307 luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); 312 luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
308 } 313 }
@@ -321,6 +326,7 @@ static void open_func (LexState *ls, FuncState *fs) {
321 fs->jpc = NO_JUMP; 326 fs->jpc = NO_JUMP;
322 fs->freereg = 0; 327 fs->freereg = 0;
323 fs->nk = 0; 328 fs->nk = 0;
329 fs->nu = 0;
324 fs->h = luaH_new(ls->L, 0, 0); 330 fs->h = luaH_new(ls->L, 0, 0);
325 fs->np = 0; 331 fs->np = 0;
326 fs->nlocvars = 0; 332 fs->nlocvars = 0;
@@ -350,6 +356,8 @@ static void close_func (LexState *ls) {
350 f->sizep = fs->np; 356 f->sizep = fs->np;
351 luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); 357 luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
352 f->sizelocvars = fs->nlocvars; 358 f->sizelocvars = fs->nlocvars;
359 luaM_reallocvector(L, f->upvalues, f->nupvalues, fs->nu, TString *);
360 f->nupvalues = fs->nu;
353 lua_assert(luaG_checkcode(f)); 361 lua_assert(luaG_checkcode(f));
354 lua_assert(fs->bl == NULL); 362 lua_assert(fs->bl == NULL);
355 ls->fs = fs->prev; 363 ls->fs = fs->prev;
@@ -368,7 +376,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
368 check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); 376 check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
369 close_func(&lexstate); 377 close_func(&lexstate);
370 lua_assert(funcstate.prev == NULL); 378 lua_assert(funcstate.prev == NULL);
371 lua_assert(funcstate.f->nupvalues == 0); 379 lua_assert(funcstate.nu == 0);
372 lua_assert(lexstate.nestlevel == 0); 380 lua_assert(lexstate.nestlevel == 0);
373 return funcstate.f; 381 return funcstate.f;
374} 382}
diff --git a/lparser.h b/lparser.h
index 011c59fe..b426c800 100644
--- a/lparser.h
+++ b/lparser.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.h,v 1.44 2002/05/14 17:52:22 roberto Exp roberto $ 2** $Id: lparser.h,v 1.45 2002/10/08 18:46:08 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -58,6 +58,7 @@ typedef struct FuncState {
58 int freereg; /* first free register */ 58 int freereg; /* first free register */
59 int nk; /* number of elements in `k' */ 59 int nk; /* number of elements in `k' */
60 int np; /* number of elements in `p' */ 60 int np; /* number of elements in `p' */
61 int nu; /* number of elements in `upvalues' */
61 int nlocvars; /* number of elements in `locvars' */ 62 int nlocvars; /* number of elements in `locvars' */
62 int nactvar; /* number of active local variables */ 63 int nactvar; /* number of active local variables */
63 expdesc upvalues[MAXUPVALUES]; /* upvalues */ 64 expdesc upvalues[MAXUPVALUES]; /* upvalues */
diff --git a/ltests.c b/ltests.c
index adc1d260..a326c2de 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.147 2002/12/04 17:29:05 roberto Exp roberto $ 2** $Id: ltests.c,v 1.148 2002/12/04 17:38:31 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -384,6 +384,24 @@ static int metatable (lua_State *L) {
384 return 1; 384 return 1;
385} 385}
386 386
387
388static int upvalue (lua_State *L) {
389 int n = luaL_checkint(L, 2);
390 luaL_checktype(L, 1, LUA_TFUNCTION);
391 if (lua_isnone(L, 3)) {
392 const char *name = lua_getupvalue(L, 1, n);
393 if (name == NULL) return 0;
394 lua_pushstring(L, name);
395 return 2;
396 }
397 else {
398 const char *name = lua_setupvalue(L, 1, n);
399 lua_pushstring(L, name);
400 return 1;
401 }
402}
403
404
387static int newuserdata (lua_State *L) { 405static int newuserdata (lua_State *L) {
388 size_t size = luaL_checkint(L, 1); 406 size_t size = luaL_checkint(L, 1);
389 char *p = cast(char *, lua_newuserdata(L, size)); 407 char *p = cast(char *, lua_newuserdata(L, size));
@@ -754,6 +772,7 @@ static const struct luaL_reg tests_funcs[] = {
754 {"d2s", d2s}, 772 {"d2s", d2s},
755 {"s2d", s2d}, 773 {"s2d", s2d},
756 {"metatable", metatable}, 774 {"metatable", metatable},
775 {"upvalue", upvalue},
757 {"newuserdata", newuserdata}, 776 {"newuserdata", newuserdata},
758 {"pushuserdata", pushuserdata}, 777 {"pushuserdata", pushuserdata},
759 {"udataval", udataval}, 778 {"udataval", udataval},
diff --git a/lua.h b/lua.h
index d8fb9047..3f5d447f 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.168 2002/11/26 12:53:29 roberto Exp roberto $ 2** $Id: lua.h,v 1.169 2002/12/04 17:28:27 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil 4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
5** http://www.lua.org mailto:info@lua.org 5** http://www.lua.org mailto:info@lua.org
@@ -336,6 +336,8 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
336LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); 336LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
337LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); 337LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
338LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); 338LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
339LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
340LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
339 341
340LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); 342LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
341LUA_API lua_Hook lua_gethook (lua_State *L); 343LUA_API lua_Hook lua_gethook (lua_State *L);