lua-users home
lua-l archive

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


Now includes the inheritance of the scoped environment for created
closures. It doesn't survive bytecode save/load, but it should be
good enough for experimentation.

The following example works now:

  local env = { myprint = print }
  in env do
    function foo()
      myprint("hello")
    end
  end

  env.foo()

--Mike
--- lua-5.1.4/src/lparser.h	2007-12-27 14:02:25 +0100
+++ lua-5.1.4-in2/src/lparser.h	2010-01-08 19:07:19 +0100
@@ -70,6 +70,7 @@
   int np;  /* number of elements in `p' */
   short nlocvars;  /* number of elements in `locvars' */
   lu_byte nactvar;  /* number of active local variables */
+  lu_byte globalvar;  /* global scope variable or NO_REG */
   upvaldesc upvalues[LUAI_MAXUPVALUES];  /* upvalues */
   unsigned short actvar[LUAI_MAXVARS];  /* declared-variable stack */
 } FuncState;
--- lua-5.1.4/src/lobject.h	2008-08-06 15:29:48 +0200
+++ lua-5.1.4-in2/src/lobject.h	2010-01-08 19:07:19 +0100
@@ -230,6 +230,7 @@
 */
 typedef struct Proto {
   CommonHeader;
+  lu_byte envslot;
   TValue *k;  /* constants used by the function */
   Instruction *code;
   struct Proto **p;  /* functions defined inside the function */
--- lua-5.1.4/src/lparser.c	2007-12-28 16:32:23 +0100
+++ lua-5.1.4-in2/src/lparser.c	2010-01-08 19:07:19 +0100
@@ -248,8 +248,16 @@
 static void singlevar (LexState *ls, expdesc *var) {
   TString *varname = str_checkname(ls);
   FuncState *fs = ls->fs;
-  if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
-    var->u.s.info = luaK_stringK(fs, varname);  /* info points to global name */
+  if (singlevaraux(fs, varname, var, 1) == VGLOBAL) {
+    if (fs->globalvar == NO_REG)
+      var->u.s.info = luaK_stringK(fs, varname);  /* info has global name */
+    else {
+      expdesc key;
+      var->u.s.info = fs->globalvar;
+      codestring(ls, &key, varname);
+      luaK_indexed(fs, var, &key);
+    }
+  }
 }
 
 
@@ -329,6 +337,7 @@
   lua_State *L = ls->L;
   Proto *f = luaF_newproto(L);
   fs->f = f;
+  f->envslot = ls->fs ? ls->fs->globalvar : NO_REG;
   fs->prev = ls->fs;  /* linked list of funcstates */
   fs->ls = ls;
   fs->L = L;
@@ -342,6 +351,7 @@
   fs->nlocvars = 0;
   fs->nactvar = 0;
   fs->bl = NULL;
+  fs->globalvar = NO_REG;
   f->source = ls->source;
   f->maxstacksize = 2;  /* registers 0/1 are always valid */
   fs->h = luaH_new(L, 0, 0);
@@ -1268,6 +1278,24 @@
 }
 
 
+static void instat (LexState *ls, int line) {
+  /* stat -> IN exp1 DO block END */
+  FuncState *fs = ls->fs;
+  int oldglobal = fs->globalvar;
+  BlockCnt bl;
+  enterblock(fs, &bl, 0);
+  new_localvarliteral(ls, "(env)", 0);
+  exp1(ls);
+  fs->globalvar = fs->nactvar;
+  adjustlocalvars(ls, 1);
+  checknext(ls, TK_DO);
+  chunk(ls);
+  check_match(ls, TK_END, TK_DO, line);
+  leaveblock(fs);
+  fs->globalvar = oldglobal;
+}
+
+
 static int statement (LexState *ls) {
   int line = ls->linenumber;  /* may be needed for error messages */
   switch (ls->t.token) {
@@ -1314,6 +1342,11 @@
       breakstat(ls);
       return 1;  /* must be last statement */
     }
+    case TK_IN: {  /* stat -> instat */
+      luaX_next(ls);  /* skip IN */
+      instat(ls, line);
+      return 0;
+    }
     default: {
       exprstat(ls);
       return 0;  /* to avoid warnings */
--- lua-5.1.4/src/lvm.c	2007-12-28 16:32:23 +0100
+++ lua-5.1.4-in2/src/lvm.c	2010-01-08 19:07:19 +0100
@@ -720,9 +720,17 @@
         Proto *p;
         Closure *ncl;
         int nup, j;
+        Table *clenv;
         p = cl->p->p[GETARG_Bx(i)];
+        if (p->envslot == NO_REG)
+          clenv = cl->env;
+        else {
+          if (!ttistable(base+p->envslot))
+            luaG_runerror(L, "environment must be a table");
+          clenv = hvalue(base+p->envslot);
+        }
         nup = p->nups;
-        ncl = luaF_newLclosure(L, nup, cl->env);
+        ncl = luaF_newLclosure(L, nup, clenv);
         ncl->l.p = p;
         for (j=0; j<nup; j++, pc++) {
           if (GET_OPCODE(*pc) == OP_GETUPVAL)
--- lua-5.1.4/src/loadlib.c	2008-08-06 15:29:28 +0200
+++ lua-5.1.4-in2/src/loadlib.c	2010-01-08 19:07:19 +0100
@@ -565,7 +565,7 @@
   lua_pushvalue(L, -1);
   setfenv(L);
   dooptions(L, loaded - 1);
-  return 0;
+  return 1;
 }