diff --git a/lapi.c b/lapi.c index 0dd005c0..998bac0a 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.225 2002/12/04 17:28:27 roberto Exp roberto $ +** $Id: lapi.c,v 1.226 2002/12/04 17:38:31 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -866,3 +866,49 @@ LUA_API int lua_pushupvalues (lua_State *L) { } +static const char *aux_upvalue (lua_State *L, int funcindex, int n, + TObject **val) { + Closure *f; + StkId fi = luaA_index(L, funcindex); + if (!ttisfunction(fi)) return NULL; + f = clvalue(fi); + if (n > f->l.nupvalues) return NULL; + if (f->c.isC) { + *val = &f->c.upvalue[n-1]; + return ""; + } + else { + *val = f->l.upvals[n-1]->v; + return getstr(f->l.p->upvalues[n-1]); + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TObject *val; + lua_lock(L); + name = aux_upvalue(L, funcindex, n, &val); + if (name) { + setobj2s(L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TObject *val; + lua_lock(L); + api_checknelems(L, 1); + name = aux_upvalue(L, funcindex, n, &val); + if (name) { + L->top--; + setobj(val, L->top); /* write barrier */ + } + lua_unlock(L); + return name; +} + diff --git a/ldblib.c b/ldblib.c index 94087679..98b3106b 100644 --- a/ldblib.c +++ b/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.74 2002/12/04 17:38:31 roberto Exp roberto $ +** $Id: ldblib.c,v 1.75 2002/12/05 17:50:10 roberto Exp roberto $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -108,6 +108,30 @@ static int setlocal (lua_State *L) { } +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + static const char KEY_HOOK = 'h'; @@ -253,8 +277,10 @@ static const luaL_reg dblib[] = { {"getlocal", getlocal}, {"getinfo", getinfo}, {"gethook", gethook}, + {"getupvalue", getupvalue}, {"sethook", sethook}, {"setlocal", setlocal}, + {"setupvalue", setupvalue}, {"debug", debug}, {"traceback", errorfb}, {NULL, NULL} diff --git a/lfunc.c b/lfunc.c index bb8a48c2..e55b59d9 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 1.63 2002/11/14 16:15:53 roberto Exp roberto $ +** $Id: lfunc.c,v 1.64 2002/12/04 17:38:31 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -85,6 +85,7 @@ Proto *luaF_newproto (lua_State *L) { f->sizecode = 0; f->sizelineinfo = 0; f->nupvalues = 0; + f->upvalues = NULL; f->numparams = 0; f->is_vararg = 0; f->maxstacksize = 0; @@ -103,6 +104,7 @@ void luaF_freeproto (lua_State *L, Proto *f) { luaM_freearray(L, f->k, f->sizek, TObject); luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->nupvalues, TString *); luaM_freelem(L, f); } diff --git a/lgc.c b/lgc.c index d20b33c1..fb3dfd09 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.165 2002/12/02 12:06:10 roberto Exp roberto $ +** $Id: lgc.c,v 1.166 2002/12/04 17:38:31 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -186,11 +186,13 @@ static void traversetable (GCState *st, Table *h) { static void traverseproto (GCState *st, Proto *f) { int i; stringmark(f->source); - for (i=0; isizek; i++) { + for (i=0; isizek; i++) { /* mark literal strings */ if (ttisstring(f->k+i)) stringmark(tsvalue(f->k+i)); } - for (i=0; isizep; i++) + for (i=0; inupvalues; i++) /* mark upvalue names */ + stringmark(f->upvalues[i]); + for (i=0; isizep; i++) /* mark nested protos */ markvalue(st, f->p[i]); for (i=0; isizelocvars; i++) /* mark local-variable names */ 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 @@ /* -** $Id: lobject.h,v 1.154 2002/11/14 11:51:50 roberto Exp roberto $ +** $Id: lobject.h,v 1.155 2002/11/14 16:16:21 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -214,7 +214,9 @@ typedef struct Proto { struct Proto **p; /* functions defined inside the function */ int *lineinfo; /* map from opcodes to source lines */ struct LocVar *locvars; /* information about local variables */ + TString **upvalues; /* upvalue names */ TString *source; + int nupvalues; /* (also size of `upvals') */ int sizek; /* size of `k' */ int sizecode; int sizelineinfo; @@ -222,7 +224,6 @@ typedef struct Proto { int sizelocvars; int lineDefined; GCObject *gclist; - lu_byte nupvalues; lu_byte numparams; lu_byte is_vararg; 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 @@ /* -** $Id: lparser.c,v 1.201 2002/12/06 17:09:00 roberto Exp roberto $ +** $Id: lparser.c,v 1.202 2002/12/11 12:34:22 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -179,16 +179,21 @@ static void create_local (LexState *ls, const char *name) { } -static int indexupvalue (FuncState *fs, expdesc *v) { +static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { int i; - for (i=0; if->nupvalues; i++) { - if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) + for (i=0; inu; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { + lua_assert(fs->f->upvalues[i] == name); return i; + } } /* new one */ - luaX_checklimit(fs->ls, fs->f->nupvalues+1, MAXUPVALUES, "upvalues"); - fs->upvalues[fs->f->nupvalues] = *v; - return fs->f->nupvalues++; + luaX_checklimit(fs->ls, fs->nu + 1, MAXUPVALUES, "upvalues"); + luaM_growvector(fs->L, fs->f->upvalues, fs->nu, fs->f->nupvalues, + TString *, MAX_INT, ""); + fs->f->upvalues[fs->nu] = name; + fs->upvalues[fs->nu] = *v; + return fs->nu++; } @@ -226,7 +231,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { var->info = luaK_stringK(fs, n); /* info points to global name */ } else { /* LOCAL or UPVAL */ - var->info = indexupvalue(fs, var); + var->info = indexupvalue(fs, n, var); var->k = VUPVAL; /* upvalue in this level */ } } @@ -302,7 +307,7 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { MAXARG_Bx, "constant table overflow"); f->p[fs->np++] = func->f; init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); - for (i=0; if->nupvalues; i++) { + for (i=0; inu; i++) { OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); } @@ -321,6 +326,7 @@ static void open_func (LexState *ls, FuncState *fs) { fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; + fs->nu = 0; fs->h = luaH_new(ls->L, 0, 0); fs->np = 0; fs->nlocvars = 0; @@ -350,6 +356,8 @@ static void close_func (LexState *ls) { f->sizep = fs->np; luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->nupvalues, fs->nu, TString *); + f->nupvalues = fs->nu; lua_assert(luaG_checkcode(f)); lua_assert(fs->bl == NULL); ls->fs = fs->prev; @@ -368,7 +376,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { check_condition(&lexstate, (lexstate.t.token == TK_EOS), " expected"); close_func(&lexstate); lua_assert(funcstate.prev == NULL); - lua_assert(funcstate.f->nupvalues == 0); + lua_assert(funcstate.nu == 0); lua_assert(lexstate.nestlevel == 0); return funcstate.f; } diff --git a/lparser.h b/lparser.h index 011c59fe..b426c800 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.44 2002/05/14 17:52:22 roberto Exp roberto $ +** $Id: lparser.h,v 1.45 2002/10/08 18:46:08 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -58,6 +58,7 @@ typedef struct FuncState { int freereg; /* first free register */ int nk; /* number of elements in `k' */ int np; /* number of elements in `p' */ + int nu; /* number of elements in `upvalues' */ int nlocvars; /* number of elements in `locvars' */ int nactvar; /* number of active local variables */ 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 @@ /* -** $Id: ltests.c,v 1.147 2002/12/04 17:29:05 roberto Exp roberto $ +** $Id: ltests.c,v 1.148 2002/12/04 17:38:31 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -384,6 +384,24 @@ static int metatable (lua_State *L) { return 1; } + +static int upvalue (lua_State *L) { + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_isnone(L, 3)) { + const char *name = lua_getupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + return 2; + } + else { + const char *name = lua_setupvalue(L, 1, n); + lua_pushstring(L, name); + return 1; + } +} + + static int newuserdata (lua_State *L) { size_t size = luaL_checkint(L, 1); char *p = cast(char *, lua_newuserdata(L, size)); @@ -754,6 +772,7 @@ static const struct luaL_reg tests_funcs[] = { {"d2s", d2s}, {"s2d", s2d}, {"metatable", metatable}, + {"upvalue", upvalue}, {"newuserdata", newuserdata}, {"pushuserdata", pushuserdata}, {"udataval", udataval}, diff --git a/lua.h b/lua.h index d8fb9047..3f5d447f 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.168 2002/11/26 12:53:29 roberto Exp roberto $ +** $Id: lua.h,v 1.169 2002/12/04 17:28:27 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil ** 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); LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); LUA_API lua_Hook lua_gethook (lua_State *L);