Bladeren bron

back to old-style vararg system (with vararg table collecting extra
arguments)

Roberto Ierusalimschy 8 jaren geleden
bovenliggende
commit
5c8770f896
7 gewijzigde bestanden met toevoegingen van 74 en 72 verwijderingen
  1. 3 18
      ldebug.c
  2. 6 35
      ldo.c
  3. 9 1
      ldo.h
  4. 10 1
      lparser.c
  5. 39 1
      ltm.c
  6. 4 1
      ltm.h
  7. 3 15
      lvm.c

+ 3 - 18
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.123 2017/04/28 20:57:45 roberto Exp roberto $
+** $Id: ldebug.c,v 2.124 2017/04/29 15:28:38 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -131,28 +131,13 @@ static const char *upvalname (Proto *p, int uv) {
 }
 
 
-static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
-  int nparams = clLvalue(ci->func)->p->numparams;
-  if (n >= cast_int(ci->u.l.base - ci->func) - nparams)
-    return NULL;  /* no such vararg */
-  else {
-    *pos = ci->func + nparams + n;
-    return "(*vararg)";  /* generic name for any vararg */
-  }
-}
-
-
 static const char *findlocal (lua_State *L, CallInfo *ci, int n,
                               StkId *pos) {
   const char *name = NULL;
   StkId base;
   if (isLua(ci)) {
-    if (n < 0)  /* access to vararg values? */
-      return findvararg(ci, -n, pos);
-    else {
-      base = ci->u.l.base;
-      name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
-    }
+    base = ci->u.l.base;
+    name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
   }
   else
     base = ci->func + 1;

+ 6 - 35
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.156 2016/09/20 16:37:45 roberto Exp roberto $
+** $Id: ldo.c,v 2.157 2016/12/13 15:52:21 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -290,23 +290,6 @@ static void callhook (lua_State *L, CallInfo *ci) {
 }
 
 
-static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
-  int i;
-  int nfixargs = p->numparams;
-  StkId base, fixed;
-  /* move fixed parameters to final position */
-  fixed = L->top - actual;  /* first fixed argument */
-  base = L->top;  /* final position of first argument */
-  for (i = 0; i < nfixargs && i < actual; i++) {
-    setobjs2s(L, L->top++, fixed + i);
-    setnilvalue(fixed + i);  /* erase original copy (for GC) */
-  }
-  for (; i < nfixargs; i++)
-    setnilvalue(L->top++);  /* complete missing arguments */
-  return base;
-}
-
-
 /*
 ** Check whether __call metafield of 'func' is a function. If so, put
 ** it in stack below original 'func' so that 'luaD_precall' can call
@@ -395,14 +378,6 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
 #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
 
 
-/* macro to check stack size, preserving 'p' */
-#define checkstackp(L,n,p)  \
-  luaD_checkstackaux(L, n, \
-    ptrdiff_t t__ = savestack(L, p);  /* save 'p' */ \
-    luaC_checkGC(L),  /* stack grow uses memory */ \
-    p = restorestack(L, t__))  /* 'pos' part: restore 'p' */
-
-
 /*
 ** Prepares a function call: checks the stack, creates a new CallInfo
 ** entry, fills in the relevant information, calls hook if needed.
@@ -438,23 +413,19 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
       return 1;
     }
     case LUA_TLCL: {  /* Lua function: prepare its call */
-      StkId base;
       Proto *p = clLvalue(func)->p;
       int n = cast_int(L->top - func) - 1;  /* number of real arguments */
       int fsize = p->maxstacksize;  /* frame size */
       checkstackp(L, fsize, func);
+      for (; n < p->numparams - p->is_vararg; n++)
+        setnilvalue(L->top++);  /* complete missing arguments */
       if (p->is_vararg)
-        base = adjust_varargs(L, p, n);
-      else {  /* non vararg function */
-        for (; n < p->numparams; n++)
-          setnilvalue(L->top++);  /* complete missing arguments */
-        base = func + 1;
-      }
+        luaT_adjustvarargs(L, p, n);
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
       ci->func = func;
-      ci->u.l.base = base;
-      L->top = ci->top = base + fsize;
+      ci->u.l.base = func + 1;
+      L->top = ci->top = func + 1 + fsize;
       lua_assert(ci->top <= L->stack_last);
       ci->u.l.savedpc = p->code;  /* starting point */
       ci->callstatus = CIST_LUA;

+ 9 - 1
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp roberto $
+** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -33,6 +33,14 @@
 #define restorestack(L,n)	((TValue *)((char *)L->stack + (n)))
 
 
+/* macro to check stack size, preserving 'p' */
+#define checkstackp(L,n,p)  \
+  luaD_checkstackaux(L, n, \
+    ptrdiff_t t__ = savestack(L, p);  /* save 'p' */ \
+    luaC_checkGC(L),  /* stack grow uses memory */ \
+    p = restorestack(L, t__))  /* 'pos' part: restore 'p' */
+
+
 /* type of protected functions, to be ran by 'runprotected' */
 typedef void (*Pfunc) (lua_State *L, void *ud);
 

+ 10 - 1
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.157 2017/04/28 20:57:45 roberto Exp roberto $
+** $Id: lparser.c,v 2.158 2017/04/29 18:09:17 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -766,7 +766,12 @@ static void parlist (LexState *ls) {
         }
         case TK_DOTS: {  /* param -> '...' */
           luaX_next(ls);
+          if (testnext(ls, '='))
+            new_localvar(ls, str_checkname(ls));
+          else
+            new_localvarliteral(ls, "_ARG");
           f->is_vararg = 1;  /* declared vararg */
+          nparams++;
           break;
         }
         default: luaX_syntaxerror(ls, "<name> or '...' expected");
@@ -1622,6 +1627,10 @@ static void mainfunc (LexState *ls, FuncState *fs) {
   expdesc v;
   open_func(ls, fs, &bl);
   fs->f->is_vararg = 1;  /* main function is always declared vararg */
+  fs->f->numparams = 1;
+  new_localvarliteral(ls, "_ARG");
+  adjustlocalvars(ls, 1);
+  luaK_reserveregs(fs, 1);  /* reserve register for vararg */
   init_exp(&v, VLOCAL, 0);  /* create and... */
   newupvalue(fs, ls->envn, &v);  /* ...set environment upvalue */
   luaX_next(ls);  /* read first token */

+ 39 - 1
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.39 2017/04/11 18:41:09 roberto Exp roberto $
+** $Id: ltm.c,v 2.40 2017/05/08 15:57:23 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -163,3 +163,41 @@ int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
     return !l_isfalse(L->top);
 }
 
+
+void luaT_adjustvarargs (lua_State *L, Proto *p, int actual) {
+  int i;
+  Table *vtab;
+  TValue nname;
+  int nfixparams = p->numparams - 1;  /* number of fixed parameters */
+  actual -= nfixparams;  /* number of extra arguments */
+  vtab = luaH_new(L);  /* create vararg table */
+  sethvalue(L, L->top, vtab);  /* anchor it for resizing */
+  L->top++;  /* space ensured by caller */
+  luaH_resize(L, vtab, actual, 1);
+  for (i = 0; i < actual; i++)  /* put extra arguments into vararg table */
+    setobj2n(L, &vtab->array[i], L->top - actual + i - 1);
+  setsvalue(L, &nname, luaS_newliteral(L, "n"));  /* get field 'n' */
+  setivalue(luaH_set(L, vtab, &nname), actual);  /* store counter there */
+  L->top -= actual;  /* remove extra elements from the stack */
+  sethvalue(L, L->top - 1, vtab);  /* move table to new top */
+}
+
+
+void luaT_getvarargs (lua_State *L, StkId t, StkId where, int wanted) {
+  if (!ttistable(t))
+    luaG_runerror(L, "'vararg' parameter is not a table");
+  else {
+    int i;
+    Table *h = hvalue(t);
+    if (wanted < 0) {  /* get all? */
+      const TValue *ns = luaH_getstr(h, luaS_newliteral(L, "n"));
+      int n = (ttisinteger(ns)) ? ivalue(ns) : 0;
+      wanted = n;
+      checkstackp(L, n, where);
+      L->top = where + n;
+    }
+    for (i = 0; i < wanted; i++)  /* get what is available */
+      setobj2s(L, where + i, luaH_getint(h, i + 1));
+    return;
+  }
+}

+ 4 - 1
ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp roberto $
+** $Id: ltm.h,v 2.23 2017/05/08 15:57:23 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -69,6 +69,9 @@ LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
 LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
                                 const TValue *p2, TMS event);
 
+LUAI_FUNC void luaT_adjustvarargs (lua_State *L, Proto *p, int actual);
+LUAI_FUNC void luaT_getvarargs (lua_State *L, StkId t, StkId where,
+                                int wanted);
 
 
 #endif

+ 3 - 15
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.279 2017/05/10 17:32:19 roberto Exp roberto $
+** $Id: lvm.c,v 2.280 2017/05/11 18:57:46 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -1433,20 +1433,8 @@ void luaV_execute (lua_State *L) {
       }
       vmcase(OP_VARARG) {
         int b = GETARG_B(i) - 1;  /* required results */
-        int j;
-        int n = cast_int(base - ci->func) - cl->p->numparams - 1;
-        if (n < 0)  /* less arguments than parameters? */
-          n = 0;  /* no vararg arguments */
-        if (b < 0) {  /* B == 0? */
-          b = n;  /* get all var. arguments */
-          Protect(luaD_checkstack(L, n));
-          ra = RA(i);  /* previous call may change the stack */
-          L->top = ra + n;
-        }
-        for (j = 0; j < b && j < n; j++)
-          setobjs2s(L, ra + j, base - n + j);
-        for (; j < b; j++)  /* complete required results with nil */
-          setnilvalue(ra + j);
+        StkId vtab = base + cl->p->numparams - 1;  /* vararg table */ 
+        Protect(luaT_getvarargs(L, vtab, ra, b));
         vmbreak;
       }
       vmcase(OP_EXTRAARG) {