2
0
Эх сурвалжийг харах

new functions to manipulate upvales (get/setupvalue)

Roberto Ierusalimschy 22 жил өмнө
parent
commit
dd8edecae1
9 өөрчлөгдсөн 128 нэмэгдсэн , 21 устгасан
  1. 47 1
      lapi.c
  2. 27 1
      ldblib.c
  3. 3 1
      lfunc.c
  4. 5 3
      lgc.c
  5. 3 2
      lobject.h
  6. 18 10
      lparser.c
  7. 2 1
      lparser.h
  8. 20 1
      ltests.c
  9. 3 1
      lua.h

+ 47 - 1
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;
+}
+

+ 27 - 1
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}

+ 3 - 1
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);
 }
 

+ 5 - 3
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; i<f->sizek; i++) {
+  for (i=0; i<f->sizek; i++) {  /* mark literal strings */
     if (ttisstring(f->k+i))
       stringmark(tsvalue(f->k+i));
   }
-  for (i=0; i<f->sizep; i++)
+  for (i=0; i<f->nupvalues; i++)  /* mark upvalue names */
+    stringmark(f->upvalues[i]);
+  for (i=0; i<f->sizep; i++)  /* mark nested protos */
     markvalue(st, f->p[i]);
   for (i=0; i<f->sizelocvars; i++)  /* mark local-variable names */
     stringmark(f->locvars[i].varname);

+ 3 - 2
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;

+ 18 - 10
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; i<fs->f->nupvalues; i++) {
-    if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info)
+  for (i=0; i<fs->nu; 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; i<func->f->nupvalues; i++) {
+  for (i=0; i<func->nu; 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), "<eof> 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;
 }

+ 2 - 1
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 */

+ 20 - 1
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},

+ 3 - 1
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:[email protected]
@@ -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);