lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Thu, 25 Feb 2010 01:38:47 +0200, Roberto Ierusalimschy <roberto@inf.puc-rio.br> wrote:

2) Any global name <var> (that is, a variable name without a visible
declaration) is changed to _ENV.<var>. This change is syntactic, meaning
that _ENV refers to whatever _ENV is visible at that point in the
code. (Because of rule 1, however, _ENV will never be a global name.)

Really glad to see this change is coming.
It's much easier to reason about code when the whole concept of globals and environments
is gone from the internals.
Being able to use value of arbitrary type for environment is very helpful, too.

(So, the
only "environments" left are for userdata, which probably should
get a more proper name.)

I'd like to ask if you could consider making it possible to have 0..MAXSOMETHING
Lua values associated with userdata (specified at the creation time),
insetad of the fixed 1.
It wouldn't complicate core much, but could really help in the cases where one
has to associate more than one value with userdata.

Something like the following (I post the patch because it's easier than explaining
the idea in english :)

Index: lua/src/liolib.c
===================================================================
--- lua/src/liolib.c	(revision 22898)
+++ lua/src/liolib.c	(working copy)
@@ -110,7 +110,7 @@
 ** file is not left opened.
 */
 static FILE **newfile (lua_State *L) {
-  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
+  FILE **pf = (FILE **)lua_newudata(L, sizeof(FILE *), 1);
   *pf = NULL;  /* file handle is currently `closed' */
   luaL_getmetatable(L, LUA_FILEHANDLE);
   lua_setmetatable(L, -2);
Index: lua/src/lgc.c
===================================================================
--- lua/src/lgc.c	(revision 22898)
+++ lua/src/lgc.c	(working copy)
@@ -169,9 +169,10 @@
     }
     case LUA_TUSERDATA: {
       Table *mt = gco2u(o)->metatable;
+      int i = gco2u(o)->nvalues;
       gray2black(o);  /* udata are never gray */
       markobject(g, mt);
-      markobject(g, gco2u(o)->env);
+      while (i--) markvalue(g, udxval(gco2u(o), i+1));
       return;
     }
     case LUA_TUPVAL: {
@@ -518,7 +519,7 @@
     case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
     case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
     case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
-    case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
+ case LUA_TUSERDATA: luaM_freemem(L, udxval(gco2u(o), gco2u(o)->nvalues), sizeudata(gco2u(o))); break;
     case LUA_TSTRING: {
       G(L)->strt.nuse--;
       luaM_freemem(L, o, sizestring(gco2ts(o)));
Index: lua/src/lstring.c
===================================================================
--- lua/src/lstring.c	(revision 22898)
+++ lua/src/lstring.c	(working copy)
@@ -94,14 +94,16 @@
 }


-Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
+Udata *luaS_newudata (lua_State *L, size_t s, int nvals) {
   Udata *u;
-  if (s > MAX_SIZET - sizeof(Udata))
+  if (s > MAX_SIZET - sizeof(Udata) - sizeof(TValue) * nvals)
     luaM_toobig(L);
-  u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u;
+  u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(TValue) * nvals
+	  + sizeof(Udata) + s, NULL, sizeof(TValue) * nvals)->u;
   u->uv.len = s;
   u->uv.metatable = NULL;
-  u->uv.env = e;
+  u->uv.nvalues = nvals;
+  while (nvals--) setnilvalue(udxval(u, nvals+1));
   return u;
 }

Index: lua/src/lapi.c
===================================================================
--- lua/src/lapi.c	(revision 23039)
+++ lua/src/lapi.c	(working copy)
@@ -649,7 +649,8 @@
       sethvalue(L, L->top, clvalue(o)->c.env);
       break;
     case LUA_TUSERDATA:
-      sethvalue(L, L->top, uvalue(o)->env);
+      if (uvalue(o)->nvalues)
+	setobj2s(L, L->top, udxval(uvalue(o), 1));
       break;
     default:
       setnilvalue(L->top);
@@ -768,7 +769,8 @@
       clvalue(o)->c.env = hvalue(L->top - 1);
       break;
     case LUA_TUSERDATA:
-      uvalue(o)->env = hvalue(L->top - 1);
+      if (uvalue(o)->nvalues)
+	sethvalue(L, udxval(uvalue(o), 1), hvalue(L->top - 1));
       break;
     default:
       res = 0;
@@ -1058,11 +1060,11 @@
 }


-LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
+LUA_API void *lua_newudata (lua_State *L, size_t size, int nups) {
   Udata *u;
   lua_lock(L);
   luaC_checkGC(L);
-  u = luaS_newudata(L, size, getcurrenv(L));
+  u = luaS_newudata(L, size, nups);
   setuvalue(L, L->top, u);
   api_incr_top(L);
   lua_unlock(L);
@@ -1074,7 +1076,13 @@

 static const char *aux_upvalue (StkId fi, int n, TValue **val) {
   Closure *f;
-  if (!ttisfunction(fi)) return NULL;
+  if (!ttisfunction(fi)) {
+      if (ttisuserdata(fi) && n <= uvalue(fi)->nvalues) {
+	*val = udxval(uvalue(fi), n);
+	return "";
+      }
+      return NULL;
+  }
   f = clvalue(fi);
   if (f->c.isC) {
     if (!(1 <= n && n <= f->c.nupvalues)) return NULL;
Index: lua/src/lua.h
===================================================================
--- lua/src/lua.h	(revision 23039)
+++ lua/src/lua.h	(working copy)
@@ -222,7 +222,8 @@
 LUA_API void  (lua_rawget) (lua_State *L, int idx);
 LUA_API void  (lua_rawgeti) (lua_State *L, int idx, int n);
 LUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);
-LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
+LUA_API void *(lua_newudata) (lua_State *L, size_t sz, int nups);
+#define lua_newuserdata(L, size) lua_newudata(L, size, 0)
 LUA_API int   (lua_getmetatable) (lua_State *L, int objindex);
 LUA_API void  (lua_getfenv) (lua_State *L, int idx);

Index: lua/src/lobject.h
===================================================================
--- lua/src/lobject.h	(revision 22898)
+++ lua/src/lobject.h	(working copy)
@@ -222,14 +222,14 @@
   L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
   struct {
     CommonHeader;
+    lu_byte nvalues;
     struct Table *metatable;
-    struct Table *env;
     size_t len;
   } uv;
 } Udata;

+#define udxval(u, i)	(cast(TValue *, u)-(i))

-
 /*
 ** Upvalues from a function prototype
 */
Index: lua/src/lstring.h
===================================================================
--- lua/src/lstring.h	(revision 22898)
+++ lua/src/lstring.h	(working copy)
@@ -15,7 +15,7 @@

 #define sizestring(s)	(sizeof(union TString)+((s)->len+1)*sizeof(char))

-#define sizeudata(u)	(sizeof(union Udata)+(u)->len)
+#define sizeudata(u) (sizeof(TValue)*(u)->nvalues+sizeof(union Udata)+(u)->len)

 #define luaS_new(L, s)	(luaS_newlstr(L, s, strlen(s)))
 #define luaS_newliteral(L, s)	(luaS_newlstr(L, "" s, \
@@ -24,7 +24,7 @@
 #define luaS_fix(s)	l_setbit((s)->tsv.marked, FIXEDBIT)

 LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
-LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nups);
 LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);