From a68635a919c5541b6acf5c2e8da5f81c67b65a7a Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 6 Apr 2001 15:25:00 -0300
Subject: [PATCH] list constructors do not adjust last expression

---
 lbaselib.c | 26 +++++++-------------------
 lcode.c    |  8 +++-----
 ldebug.c   | 10 +++++-----
 lopcodes.h |  6 +++---
 lparser.c  | 35 ++++++++++++++++++-----------------
 lvm.c      | 19 ++++++++++---------
 6 files changed, 46 insertions(+), 58 deletions(-)

diff --git a/lbaselib.c b/lbaselib.c
index d26bc7b0..d0dd1e9f 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.30 2001/03/07 12:43:52 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.31 2001/03/26 14:31:49 roberto Exp roberto $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -366,30 +366,19 @@ static int luaB_require (lua_State *L) {
 }
 
 
-static int luaB_pack (lua_State *L) {
-  int n = lua_gettop(L);
-  lua_newtable(L);
-  aux_setn(L, -3, n);
-  lua_insert(L, 1);
-  while (n)
-    lua_rawseti(L, 1, n--);
-  return 1;
-}
-
-
-static int aux_unpack (lua_State *L, int arg) {
+static int aux_unwrap (lua_State *L, int arg) {
   int n, i;
   luaL_checktype(L, arg, LUA_TTABLE);
   n = lua_getn(L, arg);
-  luaL_checkstack(L, n, l_s("too many arguments"));
+  luaL_checkstack(L, n, l_s("table too big to unwrap"));
   for (i=1; i<=n; i++)  /* push arg[1...n] */
     lua_rawgeti(L, arg, i);
   return n;
 }
 
 
-static int luaB_unpack (lua_State *L) {
-  return aux_unpack(L, 1);
+static int luaB_unwrap (lua_State *L) {
+  return aux_unwrap(L, 1);
 }
 
 
@@ -408,7 +397,7 @@ static int luaB_call (lua_State *L) {
   oldtop = lua_gettop(L);  /* top before function-call preparation */
   /* push function */
   lua_pushvalue(L, 1);
-  n = aux_unpack(L, 2);  /* push arg[1...n] */
+  n = aux_unwrap(L, 2);  /* push arg[1...n] */
   status = lua_call(L, n, LUA_MULTRET);
   if (err != 0) {  /* restore old error method */
     lua_pushvalue(L, err);
@@ -762,8 +751,7 @@ static const luaL_reg base_funcs[] = {
   {l_s("sort"), luaB_sort},
   {l_s("tinsert"), luaB_tinsert},
   {l_s("tremove"), luaB_tremove},
-  {l_s("pack"), luaB_pack},
-  {l_s("unpack"), luaB_unpack},
+  {l_s("unwrap"), luaB_unwrap},
   {l_s("xtype"), luaB_xtype},
 };
 
diff --git a/lcode.c b/lcode.c
index 72a1b71e..1b745d64 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.65 2001/03/07 13:22:55 roberto Exp roberto $
+** $Id: lcode.c,v 1.66 2001/03/26 14:31:49 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -474,13 +474,11 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
       break;
     }
     case OP_SETLIST: {
-      if (arg2 == 0) return NO_JUMP;  /* nothing to do */
-      pop = arg2;
+      pop = fs->stacklevel - 1 - arg2;
       break;
     }
     case OP_SETMAP: {
-      if (arg1 == 0) return NO_JUMP;  /* nothing to do */
-      pop = 2*arg1;
+      pop = fs->stacklevel - 1 - arg1;
       break;
     }
     case OP_PUSHNIL: {
diff --git a/ldebug.c b/ldebug.c
index 5f114f88..f8369d2d 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 1.74 2001/03/07 18:09:25 roberto Exp roberto $
+** $Id: ldebug.c,v 1.75 2001/03/26 14:31:49 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -419,13 +419,13 @@ static Instruction luaG_symbexec (lua_State *L, const Proto *pt,
         break;
       }
       case OP_SETLIST: {
-        pop = arg2;
-        check(top-pop >= 1);  /* there must be a table below the list */
+        check(arg2 >= 0);
+        pop = top-arg2-1;
         break;
       }
       case OP_SETMAP: {
-        pop = 2*arg1;
-        check(top-pop >= 1);
+        check(arg1 >= 0);
+        pop = top-arg1-1;
         break;
       }
       case OP_CONCAT: {
diff --git a/lopcodes.h b/lopcodes.h
index 207627a5..3b743880 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.70 2001/01/15 16:13:24 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.71 2001/03/07 13:22:55 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -110,8 +110,8 @@ OP_SETLOCAL,/*	L	x		-		LOC[l]=x	*/
 OP_SETGLOBAL,/*	K	x		-		VAR[KSTR[k]]=x	*/
 OP_SETTABLE,/*	A B	v a_a-a_1 i t	(pops b values)	t[i]=v		*/
 
-OP_SETLIST,/*	A B	v_b-v_1 t	t		t[i+a*FPF]=v_i	*/
-OP_SETMAP,/*	U	v_u k_u - v_1 k_1 t	t	t[k_i]=v_i	*/
+OP_SETLIST,/*	A B	v_n-v_1 v_b	v_b		v_b[i+a*FPF]=v_i */
+OP_SETMAP,/*	U	v_n k_n - v_1 k_1 v_u	v_u	v_u[k_i]=v_i	*/
 
 OP_ADD,/*	-	y x		x+y				*/
 OP_ADDI,/*	S	x		x+s				*/
diff --git a/lparser.c b/lparser.c
index f01440ac..a5a56829 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.140 2001/03/26 14:31:49 roberto Exp roberto $
+** $Id: lparser.c,v 1.141 2001/04/05 16:49:14 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -465,39 +465,40 @@ static void recfield (LexState *ls) {
 static int recfields (LexState *ls) {
   /* recfields -> recfield { `,' recfield } [`,'] */
   FuncState *fs = ls->fs;
+  int t = fs->stacklevel-1;  /* level of table on the stack */
   int n = 1;  /* at least one element */
   recfield(ls);
-  while (ls->t.token == l_c(',')) {
-    next(ls);
-    if (ls->t.token == l_c(';') || ls->t.token == l_c('}'))
-      break;
+  while (ls->t.token == l_c(',') &&
+         (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) {
+    if (n%RFIELDS_PER_FLUSH == 0)
+      luaK_code1(fs, OP_SETMAP, t);
     recfield(ls);
     n++;
-    if (n%RFIELDS_PER_FLUSH == 0)
-      luaK_code1(fs, OP_SETMAP, RFIELDS_PER_FLUSH);
   }
-  luaK_code1(fs, OP_SETMAP, n%RFIELDS_PER_FLUSH);
+  luaK_code1(fs, OP_SETMAP, t);
   return n;
 }
 
 
 static int listfields (LexState *ls) {
   /* listfields -> exp1 { `,' exp1 } [`,'] */
+  expdesc v;
   FuncState *fs = ls->fs;
+  int t = fs->stacklevel-1;  /* level of table on the stack */
   int n = 1;  /* at least one element */
-  exp1(ls);
-  while (ls->t.token == l_c(',')) {
-    next(ls);
-    if (ls->t.token == l_c(';') || ls->t.token == l_c('}'))
-      break;
-    exp1(ls);
-    n++;
+  expr(ls, &v);
+  while (ls->t.token == l_c(',') &&
+         (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) {
+    luaK_tostack(ls, &v, 1);  /* only one value from intermediate expressions */
     luaX_checklimit(ls, n/LFIELDS_PER_FLUSH, MAXARG_A,
                l_s("`item groups' in a list initializer"));
     if (n%LFIELDS_PER_FLUSH == 0)
-      luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH);
+      luaK_code2(fs, OP_SETLIST, (n-1)/LFIELDS_PER_FLUSH, t);
+    expr(ls, &v);
+    n++;
   }
-  luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH);
+  luaK_tostack(ls, &v, 0);  /* allow multiple values for last expression */
+  luaK_code2(fs, OP_SETLIST, (n-1)/LFIELDS_PER_FLUSH, t);
   return n;
 }
 
diff --git a/lvm.c b/lvm.c
index 14f6feb3..9c1b13d0 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.176 2001/03/07 18:16:22 roberto Exp roberto $
+** $Id: lvm.c,v 1.177 2001/03/26 14:31:49 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -446,18 +446,19 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
       }
       case OP_SETLIST: {
         int aux = GETARG_A(i) * LFIELDS_PER_FLUSH;
-        int n = GETARG_B(i);
-        Hash *arr = hvalue(top-n-1);
-        for (; n; n--)
-          setobj(luaH_setnum(L, arr, n+aux), --top);
+        TObject *t = base+GETARG_B(i);
+        Hash *h = hvalue(t);
+        int n;
+        for (n = top-t-1; n; n--)
+          setobj(luaH_setnum(L, h, n+aux), --top);
         break;
       }
       case OP_SETMAP: {
-        int n = GETARG_U(i);
-        Hash *arr = hvalue((top-2*n)-1);
-        for (; n; n--) {
+        TObject *t = base+GETARG_U(i);
+        Hash *h = hvalue(t);
+        while (top-1 > t) {
           top-=2;
-          setobj(luaH_set(L, arr, top), top+1);
+          setobj(luaH_set(L, h, top), top+1);
         }
         break;
       }